1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 22919e95c2a59a087ba8297c2f551c3ebc3754c9ehenrika@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 116388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/channel.h" 126388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org 1364dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin#include <algorithm> 14f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi#include <utility> 1564dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin 16ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen#include "webrtc/base/checks.h" 174591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org#include "webrtc/base/format_macros.h" 18ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos#include "webrtc/base/logging.h" 19b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer#include "webrtc/base/thread_checker.h" 2094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org#include "webrtc/base/timeutils.h" 21e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org#include "webrtc/common.h" 2264dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin#include "webrtc/config.h" 236388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/audio_device/include/audio_device.h" 246388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h" 25ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/include/module_common_types.h" 26b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer#include "webrtc/modules/pacing/packet_router.h" 27ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" 28ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" 29ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" 30822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" 31ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/utility/include/audio_frame_operations.h" 32ff761fba8274d93bd73e76c8b8a1f2d0776dd840Henrik Kjellander#include "webrtc/modules/utility/include/process_thread.h" 3398f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 3498f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/trace.h" 356388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_base.h" 366388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_external_media.h" 376388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" 386388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/output_mixer.h" 396388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/statistics.h" 406388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h" 416388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/utility.h" 42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#if defined(_WIN32) 44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <Qos.h> 45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4750419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace webrtc { 4850419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace voe { 49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 50b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmerclass TransportFeedbackProxy : public TransportFeedbackObserver { 51b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer public: 52b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportFeedbackProxy() : feedback_observer_(nullptr) { 53b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer pacer_thread_.DetachFromThread(); 54b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer network_thread_.DetachFromThread(); 55b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 56b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 57b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void SetTransportFeedbackObserver( 58b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportFeedbackObserver* feedback_observer) { 59b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(thread_checker_.CalledOnValidThread()); 60b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 61b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer feedback_observer_ = feedback_observer; 62b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 63b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 64b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // Implements TransportFeedbackObserver. 65b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void AddPacket(uint16_t sequence_number, 66b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer size_t length, 67b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer bool was_paced) override { 68b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(pacer_thread_.CalledOnValidThread()); 69b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 70b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (feedback_observer_) 71b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer feedback_observer_->AddPacket(sequence_number, length, was_paced); 72b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 73b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override { 74b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(network_thread_.CalledOnValidThread()); 75b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 76b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (feedback_observer_) 77b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer feedback_observer_->OnTransportFeedback(feedback); 78b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 79b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 80b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer private: 81b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CriticalSection crit_; 82b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker thread_checker_; 83b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker pacer_thread_; 84b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker network_thread_; 85b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_); 86b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer}; 87b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 88b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmerclass TransportSequenceNumberProxy : public TransportSequenceNumberAllocator { 89b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer public: 90b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) { 91b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer pacer_thread_.DetachFromThread(); 92b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 93b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 94b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void SetSequenceNumberAllocator( 95b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportSequenceNumberAllocator* seq_num_allocator) { 96b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(thread_checker_.CalledOnValidThread()); 97b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 98b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer seq_num_allocator_ = seq_num_allocator; 99b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 100b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 101b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // Implements TransportSequenceNumberAllocator. 102b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer uint16_t AllocateSequenceNumber() override { 103b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(pacer_thread_.CalledOnValidThread()); 104b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 105b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (!seq_num_allocator_) 106b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer return 0; 107b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer return seq_num_allocator_->AllocateSequenceNumber(); 108b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 109b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 110b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer private: 111b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CriticalSection crit_; 112b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker thread_checker_; 113b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker pacer_thread_; 114b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_); 115b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer}; 116b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 117b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmerclass RtpPacketSenderProxy : public RtpPacketSender { 118b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer public: 119b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) { 120b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 121b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 122b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void SetPacketSender(RtpPacketSender* rtp_packet_sender) { 123b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(thread_checker_.CalledOnValidThread()); 124b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 125b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_packet_sender_ = rtp_packet_sender; 126b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 127b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 128b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // Implements RtpPacketSender. 129b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer void InsertPacket(Priority priority, 130b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer uint32_t ssrc, 131b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer uint16_t sequence_number, 132b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer int64_t capture_time_ms, 133b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer size_t bytes, 134b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer bool retransmission) override { 135b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CritScope lock(&crit_); 136b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (rtp_packet_sender_) { 137b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number, 138b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer capture_time_ms, bytes, retransmission); 139b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 140b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 141b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 142b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer private: 143b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::ThreadChecker thread_checker_; 144b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtc::CriticalSection crit_; 145b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_); 146b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer}; 147b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 14854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// Extend the default RTCP statistics struct with max_jitter, defined as the 14954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// maximum jitter value seen in an RTCP report block. 15054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgstruct ChannelStatistics : public RtcpStatistics { 15154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org ChannelStatistics() : rtcp(), max_jitter(0) {} 15254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 15354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org RtcpStatistics rtcp; 15454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org uint32_t max_jitter; 15554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org}; 15654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 15754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// Statistics callback, called at each generation of a new RTCP report block. 15854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgclass StatisticsProxy : public RtcpStatisticsCallback { 15954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org public: 16054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org StatisticsProxy(uint32_t ssrc) 16154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org : stats_lock_(CriticalSectionWrapper::CreateCriticalSection()), 16254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org ssrc_(ssrc) {} 16354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org virtual ~StatisticsProxy() {} 16454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 16514665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void StatisticsUpdated(const RtcpStatistics& statistics, 16614665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org uint32_t ssrc) override { 16754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org if (ssrc != ssrc_) 16854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org return; 16954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 17054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org CriticalSectionScoped cs(stats_lock_.get()); 17154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org stats_.rtcp = statistics; 17254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org if (statistics.jitter > stats_.max_jitter) { 17354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org stats_.max_jitter = statistics.jitter; 17454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org } 17554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org } 17654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 17714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void CNameChanged(const char* cname, uint32_t ssrc) override {} 178ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org 17954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org ChannelStatistics GetStats() { 18054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org CriticalSectionScoped cs(stats_lock_.get()); 18154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org return stats_; 18254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org } 18354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 18454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org private: 18554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // StatisticsUpdated calls are triggered from threads in the RTP module, 18654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // while GetStats calls can be triggered from the public voice engine API, 18754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // hence synchronization is needed. 18800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<CriticalSectionWrapper> stats_lock_; 18954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org const uint32_t ssrc_; 19054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org ChannelStatistics stats_; 19154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org}; 19254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 1930a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.orgclass VoERtcpObserver : public RtcpBandwidthObserver { 194c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org public: 1950a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org explicit VoERtcpObserver(Channel* owner) : owner_(owner) {} 1960a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org virtual ~VoERtcpObserver() {} 1970a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 1980a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org void OnReceivedEstimatedBitrate(uint32_t bitrate) override { 1990a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // Not used for Voice Engine. 2000a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org } 2010a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 20214665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks, 20314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org int64_t rtt, 20414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org int64_t now_ms) override { 2050a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // TODO(mflodman): Do we need to aggregate reports here or can we jut send 2060a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // what we get? I.e. do we ever get multiple reports bundled into one RTCP 2070a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // report for VoiceEngine? 2080a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org if (report_blocks.empty()) 2090a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org return; 2100a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 2110a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org int fraction_lost_aggregate = 0; 2120a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org int total_number_of_packets = 0; 2130a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 2140a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // If receiving multiple report blocks, calculate the weighted average based 2150a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // on the number of packets a report refers to. 2160a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org for (ReportBlockList::const_iterator block_it = report_blocks.begin(); 2170a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org block_it != report_blocks.end(); ++block_it) { 2180a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // Find the previous extended high sequence number for this remote SSRC, 2190a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // to calculate the number of RTP packets this report refers to. Ignore if 2200a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // we haven't seen this SSRC before. 2210a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org std::map<uint32_t, uint32_t>::iterator seq_num_it = 2220a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org extended_max_sequence_number_.find(block_it->sourceSSRC); 2230a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org int number_of_packets = 0; 2240a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org if (seq_num_it != extended_max_sequence_number_.end()) { 2250a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second; 2260a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org } 2270a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org fraction_lost_aggregate += number_of_packets * block_it->fractionLost; 2280a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org total_number_of_packets += number_of_packets; 2290a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 2300a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org extended_max_sequence_number_[block_it->sourceSSRC] = 2310a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org block_it->extendedHighSeqNum; 2320a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org } 2330a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org int weighted_fraction_lost = 0; 2340a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org if (total_number_of_packets > 0) { 2350a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org weighted_fraction_lost = (fraction_lost_aggregate + 2360a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org total_number_of_packets / 2) / total_number_of_packets; 2370a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org } 2380a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org owner_->OnIncomingFractionLoss(weighted_fraction_lost); 239c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org } 240c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 241c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org private: 242c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org Channel* owner_; 2430a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org // Maps remote side ssrc to extended highest sequence number received. 2440a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org std::map<uint32_t, uint32_t> extended_max_sequence_number_; 245c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}; 246c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 2476141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendData(FrameType frameType, 2496141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint8_t payloadType, 2506141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint32_t timeStamp, 2516141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint8_t* payloadData, 2524591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t payloadSize, 253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const RTPFragmentationHeader* fragmentation) 254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u," 2574591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org " payloadSize=%" PRIuS ", fragmentation=0x%x)", 2584591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org frameType, payloadType, timeStamp, 2594591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org payloadSize, fragmentation); 260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_includeAudioLevelIndication) 262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Store current audio level in the RTP/RTCP module. 264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The level will be used in combination with voice-activity state 265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // (frameType) to add an RTP header extension 266382c0c209d323c1e6972d988a7b26f08fc2e8a6bandrew@webrtc.org _rtpRtcpModule->SetAudioLevel(rms_level_.RMS()); 267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Push data from ACM to RTP/RTCP-module to deliver audio frame for 270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // packetization. 271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // This call will trigger Transport::SendPacket() from the RTP/RTCP module. 2722853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType, 273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com payloadType, 274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com timeStamp, 275ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org // Leaving the time when this frame was 276ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org // received from the capture device as 277ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org // undefined for voice for now. 278ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org -1, 279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com payloadData, 280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com payloadSize, 281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fragmentation) == -1) 282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendData() failed to send data to RTP/RTCP module"); 286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _lastLocalTimeStamp = timeStamp; 290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _lastPayloadType = payloadType; 291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2956141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 296e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.orgChannel::InFrameType(FrameType frame_type) 297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 299e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.org "Channel::InFrameType(frame_type=%d)", frame_type); 300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3019a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 302e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.org _sendFrameType = (frame_type == kAudioFrameSpeech); 303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3066141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 3079213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::OnRxVadDetected(int vadDecision) 308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3099a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_rxVadObserverPtr) 311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _rxVadObserverPtr->OnRxVad(_channelId, vadDecision); 313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3181d8a506405734d0cef9653704b036ca4f1388960stefanbool Channel::SendRtp(const uint8_t* data, 3191d8a506405734d0cef9653704b036ca4f1388960stefan size_t len, 3201d8a506405734d0cef9653704b036ca4f1388960stefan const PacketOptions& options) { 321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 322ac547a653862744d0aae560713f8418ad2852085Peter Boström "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len); 323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 324fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 325fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org 326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_transportPtr == NULL) 327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendPacket() failed to send RTP packet due to" 330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " invalid transport object"); 3312d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3346141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint8_t* bufferToSendPtr = (uint8_t*)data; 3354591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t bufferLength = len; 336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3371d8a506405734d0cef9653704b036ca4f1388960stefan if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) { 338fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org std::string transport_name = 339fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org _externalTransport ? "external transport" : "WebRtc sockets"; 340fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org WEBRTC_TRACE(kTraceError, kTraceVoice, 341fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org VoEId(_instanceId,_channelId), 342fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org "Channel::SendPacket() RTP transmission using %s failed", 343fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org transport_name.c_str()); 3442d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3462d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return true; 347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3492d566686a23fe93ada58f1c38a0d4b9a0d68556epbosbool 3502d566686a23fe93ada58f1c38a0d4b9a0d68556epbosChannel::SendRtcp(const uint8_t *data, size_t len) 351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3532d566686a23fe93ada58f1c38a0d4b9a0d68556epbos "Channel::SendRtcp(len=%" PRIuS ")", len); 354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 355fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 356fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org if (_transportPtr == NULL) 357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 358fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org WEBRTC_TRACE(kTraceError, kTraceVoice, 359fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org VoEId(_instanceId,_channelId), 3602d566686a23fe93ada58f1c38a0d4b9a0d68556epbos "Channel::SendRtcp() failed to send RTCP packet" 361fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org " due to invalid transport object"); 3622d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3656141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint8_t* bufferToSendPtr = (uint8_t*)data; 3664591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t bufferLength = len; 367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3682d566686a23fe93ada58f1c38a0d4b9a0d68556epbos int n = _transportPtr->SendRtcp(bufferToSendPtr, bufferLength); 369fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org if (n < 0) { 370fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org std::string transport_name = 371fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org _externalTransport ? "external transport" : "WebRtc sockets"; 372fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, 373fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org VoEId(_instanceId,_channelId), 3742d566686a23fe93ada58f1c38a0d4b9a0d68556epbos "Channel::SendRtcp() transmission using %s failed", 375fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org transport_name.c_str()); 3762d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return false; 377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3782d566686a23fe93ada58f1c38a0d4b9a0d68556epbos return true; 379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 381ac547a653862744d0aae560713f8418ad2852085Peter Boströmvoid Channel::OnPlayTelephoneEvent(uint8_t event, 382ac547a653862744d0aae560713f8418ad2852085Peter Boström uint16_t lengthMs, 383ac547a653862744d0aae560713f8418ad2852085Peter Boström uint8_t volume) { 384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 385ac547a653862744d0aae560713f8418ad2852085Peter Boström "Channel::OnPlayTelephoneEvent(event=%u, lengthMs=%u," 386ac547a653862744d0aae560713f8418ad2852085Peter Boström " volume=%u)", event, lengthMs, volume); 387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_playOutbandDtmfEvent || (event > 15)) 389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Ignore callback since feedback is disabled or event is not a 391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Dtmf tone event. 392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return; 393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com assert(_outputMixerPtr != NULL); 396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Start playing out the Dtmf tone (if playout is enabled). 398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Reduce length of tone with 80ms to the reduce risk of echo. 399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume); 400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 403ac547a653862744d0aae560713f8418ad2852085Peter BoströmChannel::OnIncomingSSRCChanged(uint32_t ssrc) 404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 406ac547a653862744d0aae560713f8418ad2852085Peter Boström "Channel::OnIncomingSSRCChanged(SSRC=%d)", ssrc); 407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 408b295a3f5920e2706d42c960c5180c7cc6e1f435edwkang@webrtc.org // Update ssrc so that NTP for AV sync can be updated. 409b295a3f5920e2706d42c960c5180c7cc6e1f435edwkang@webrtc.org _rtpRtcpModule->SetRemoteSSRC(ssrc); 410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 412ac547a653862744d0aae560713f8418ad2852085Peter Boströmvoid Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) { 413ac547a653862744d0aae560713f8418ad2852085Peter Boström WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 414ac547a653862744d0aae560713f8418ad2852085Peter Boström "Channel::OnIncomingCSRCChanged(CSRC=%d, added=%d)", CSRC, 415ac547a653862744d0aae560713f8418ad2852085Peter Boström added); 416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 418ac547a653862744d0aae560713f8418ad2852085Peter Boströmint32_t Channel::OnInitializeDecoder( 4199213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int8_t payloadType, 420813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org const char payloadName[RTP_PAYLOAD_NAME_SIZE], 4219213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int frequency, 4226955870806624479723addfae6dcf5d13968796cPeter Kasting size_t channels, 423ac547a653862744d0aae560713f8418ad2852085Peter Boström uint32_t rate) { 424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 425ac547a653862744d0aae560713f8418ad2852085Peter Boström "Channel::OnInitializeDecoder(payloadType=%d, " 4266955870806624479723addfae6dcf5d13968796cPeter Kasting "payloadName=%s, frequency=%u, channels=%" PRIuS ", rate=%u)", 427ac547a653862744d0aae560713f8418ad2852085Peter Boström payloadType, payloadName, frequency, channels, rate); 428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 429f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org CodecInst receiveCodec = {0}; 430f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org CodecInst dummyCodec = {0}; 431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com receiveCodec.pltype = payloadType; 433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com receiveCodec.plfreq = frequency; 434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com receiveCodec.channels = channels; 435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com receiveCodec.rate = rate; 436f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 437ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 438eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels); 439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com receiveCodec.pacsize = dummyCodec.pacsize; 440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Register the new codec to the ACM 442eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterReceiveCodec(receiveCodec) == -1) 443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 445ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org VoEId(_instanceId, _channelId), 446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::OnInitializeDecoder() invalid codec (" 447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "pt=%d, name=%s) received - 1", payloadType, payloadName); 448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR); 449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4556141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 4566141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::OnReceivedPayloadData(const uint8_t* payloadData, 4574591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t payloadSize, 458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const WebRtcRTPHeader* rtpHeader) 459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 4614591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS "," 4626955870806624479723addfae6dcf5d13968796cPeter Kasting " payloadType=%u, audioChannel=%" PRIuS ")", 463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com payloadSize, 464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com rtpHeader->header.payloadType, 465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com rtpHeader->type.Audio.channel); 466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 467944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().playing) 468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Avoid inserting into NetEQ when we are not playing. Count the 470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // packet as discarded. 471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, 472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "received packet is discarded since playing is not" 474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " activated"); 475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _numberOfDiscardedPackets++; 476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Push the incoming payload (parsed and ready for decoding) into the ACM 480eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->IncomingPacket(payloadData, 481eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org payloadSize, 482eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org *rtpHeader) != 0) 483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning, 486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::OnReceivedPayloadData() unable to push data to the ACM"); 487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 490d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org // Update the packet delay. 491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com UpdatePacketDelay(rtpHeader->header.timestamp, 492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com rtpHeader->header.sequenceNumber); 493d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org 49416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t round_trip_time = 0; 495822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, 496822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org NULL, NULL, NULL); 497822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 498eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org std::vector<uint16_t> nack_list = audio_coding_->GetNackList( 499822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org round_trip_time); 500822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (!nack_list.empty()) { 501822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Can't use nack_list.data() since it's not supported by all 502822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // compilers. 503822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size())); 504d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org } 505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5087bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::OnRecoveredPacket(const uint8_t* rtp_packet, 5094591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t rtp_packet_length) { 5107bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org RTPHeader header; 5117bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) { 5127bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId, 5137bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org "IncomingPacket invalid RTP header"); 5147bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 5157bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 5167bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org header.payload_type_frequency = 5177bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType); 5187bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (header.payload_type_frequency < 0) 5197bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 5207bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return ReceivePacket(rtp_packet, rtp_packet_length, header, false); 5217bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 5227bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 5230f4b3731c34e796da92572380855dbc7321c8cfeminyuelint32_t Channel::GetAudioFrame(int32_t id, AudioFrame* audioFrame) 524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 525ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen if (event_log_) { 526ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen unsigned int ssrc; 527ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen RTC_CHECK_EQ(GetLocalSSRC(ssrc), 0); 528ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen event_log_->LogAudioPlayout(ssrc); 529ae856f2c9fc358e5cd68d8a595136dcef017ed96Ivo Creusen } 530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Get 10ms raw PCM data from the ACM (mixer limits output frequency) 5310f4b3731c34e796da92572380855dbc7321c8cfeminyuel if (audio_coding_->PlayoutData10Ms(audioFrame->sample_rate_hz_, 5320f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame) == -1) 533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, 535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::GetAudioFrame() PlayoutData10Ms() failed!"); 5377859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org // In all likelihood, the audio in this frame is garbage. We return an 5387859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org // error so that the audio mixer module doesn't add it to the mix. As 5397859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org // a result, it won't be played out and the actions skipped here are 5407859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org // irrelevant. 5417859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org return -1; 542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_RxVadDetection) 545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 5460f4b3731c34e796da92572380855dbc7321c8cfeminyuel UpdateRxVadDetection(*audioFrame); 547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Convert module ID to internal VoE channel ID 5500f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame->id_ = VoEChannelId(audioFrame->id_); 551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Store speech type for dead-or-alive detection 5520f4b3731c34e796da92572380855dbc7321c8cfeminyuel _outputSpeechType = audioFrame->speech_type_; 553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 554944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org ChannelState::State state = channel_state_.Get(); 555944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org 556944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (state.rx_apm_is_enabled) { 5570f4b3731c34e796da92572380855dbc7321c8cfeminyuel int err = rx_audioproc_->ProcessStream(audioFrame); 55860730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org if (err) { 55960730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org LOG(LS_ERROR) << "ProcessStream() error: " << err; 56060730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org assert(false); 56160730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org } 562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 564f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi { 565f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi // Pass the audio buffers to an optional sink callback, before applying 566f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi // scaling/panning, as that applies to the mix operation. 567f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi // External recipients of the audio (e.g. via AudioTrack), will do their 568f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi // own mixing/dynamic processing. 569f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi CriticalSectionScoped cs(&_callbackCritSect); 570f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi if (audio_sink_) { 571f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi AudioSinkInterface::Data data( 572f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi &audioFrame->data_[0], 573f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi audioFrame->samples_per_channel_, audioFrame->sample_rate_hz_, 574f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi audioFrame->num_channels_, audioFrame->timestamp_); 575f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi audio_sink_->OnData(data); 576f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi } 577f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi } 578f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi 57963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org float output_gain = 1.0f; 58063420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org float left_pan = 1.0f; 58163420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org float right_pan = 1.0f; 58263420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org { 58363420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 58463420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org output_gain = _outputGain; 58563420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org left_pan = _panLeft; 58663420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org right_pan= _panRight; 58763420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org } 58863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org 589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Output volume scaling 59063420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org if (output_gain < 0.99f || output_gain > 1.01f) 591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 5920f4b3731c34e796da92572380855dbc7321c8cfeminyuel AudioFrameOperations::ScaleWithSat(output_gain, *audioFrame); 593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Scale left and/or right channel(s) if stereo and master balance is 596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // active 597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 59863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org if (left_pan != 1.0f || right_pan != 1.0f) 599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 6000f4b3731c34e796da92572380855dbc7321c8cfeminyuel if (audioFrame->num_channels_ == 1) 601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Emulate stereo mode since panning is active. 603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The mono signal is copied to both left and right channels here. 6040f4b3731c34e796da92572380855dbc7321c8cfeminyuel AudioFrameOperations::MonoToStereo(audioFrame); 605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // For true stereo mode (when we are receiving a stereo signal), no 607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // action is needed. 608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Do the panning operation (the audio frame contains stereo at this 610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // stage) 6110f4b3731c34e796da92572380855dbc7321c8cfeminyuel AudioFrameOperations::Scale(left_pan, right_pan, *audioFrame); 612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Mix decoded PCM output with file if file mixing is enabled 615944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (state.output_file_playing) 616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 6170f4b3731c34e796da92572380855dbc7321c8cfeminyuel MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_); 618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // External media 621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputExternalMedia) 622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 6239a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 6240f4b3731c34e796da92572380855dbc7321c8cfeminyuel const bool isStereo = (audioFrame->num_channels_ == 2); 625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputExternalMediaCallbackPtr) 626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 627f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi _outputExternalMediaCallbackPtr->Process( 628f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi _channelId, kPlaybackPerChannel, (int16_t*)audioFrame->data_, 629f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi audioFrame->samples_per_channel_, audioFrame->sample_rate_hz_, 630f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi isStereo); 631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Record playout if enabled 635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 6369a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecording && _outputFileRecorderPtr) 639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 6400f4b3731c34e796da92572380855dbc7321c8cfeminyuel _outputFileRecorderPtr->RecordAudioToFile(*audioFrame); 641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Measure audio level (0-9) 6450f4b3731c34e796da92572380855dbc7321c8cfeminyuel _outputAudioLevel.ComputeLevel(*audioFrame); 646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6470f4b3731c34e796da92572380855dbc7321c8cfeminyuel if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) { 64894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // The first frame with a valid rtp timestamp. 6490f4b3731c34e796da92572380855dbc7321c8cfeminyuel capture_start_rtp_time_stamp_ = audioFrame->timestamp_; 65094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org } 65194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org 65294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org if (capture_start_rtp_time_stamp_ >= 0) { 65394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // audioFrame.timestamp_ should be valid from now on. 65494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org 65594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // Compute elapsed time. 65694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org int64_t unwrap_timestamp = 6570f4b3731c34e796da92572380855dbc7321c8cfeminyuel rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_); 6580f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame->elapsed_time_ms_ = 65994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org (unwrap_timestamp - capture_start_rtp_time_stamp_) / 66094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org (GetPlayoutFrequency() / 1000); 66194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org 6628e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org { 663cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org CriticalSectionScoped lock(ts_stats_lock_.get()); 6648e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org // Compute ntp time. 6650f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame->ntp_time_ms_ = ntp_estimator_.Estimate( 6660f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame->timestamp_); 6678e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received. 6680f4b3731c34e796da92572380855dbc7321c8cfeminyuel if (audioFrame->ntp_time_ms_ > 0) { 6698e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org // Compute |capture_start_ntp_time_ms_| so that 6708e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_| 6718e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org capture_start_ntp_time_ms_ = 6720f4b3731c34e796da92572380855dbc7321c8cfeminyuel audioFrame->ntp_time_ms_ - audioFrame->elapsed_time_ms_; 6738e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org } 674cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org } 675cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org } 676cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org 677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 6810f4b3731c34e796da92572380855dbc7321c8cfeminyuelChannel::NeededFrequency(int32_t id) const 682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::NeededFrequency(id=%d)", id); 685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int highestNeeded = 0; 687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Determine highest needed receive frequency 689eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org int32_t receiveFrequency = audio_coding_->ReceiveFrequency(); 690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Return the bigger of playout and receive frequency in the ACM. 692eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->PlayoutFrequency() > receiveFrequency) 693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 694eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org highestNeeded = audio_coding_->PlayoutFrequency(); 695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com highestNeeded = receiveFrequency; 699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Special case, if we're playing a file on the playout side 702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // we take that frequency into consideration as well 703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // This is not needed on sending side, since the codec will 704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // limit the spectrum anyway. 705944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().output_file_playing) 706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 7079a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 708944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (_outputFilePlayerPtr) 709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(_outputFilePlayerPtr->Frequency()>highestNeeded) 711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com highestNeeded=_outputFilePlayerPtr->Frequency(); 713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(highestNeeded); 718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 720b04965ccf83c2bc6e2758abab9bea0c18551a54civocint32_t Channel::CreateChannel(Channel*& channel, 721b04965ccf83c2bc6e2758abab9bea0c18551a54civoc int32_t channelId, 722b04965ccf83c2bc6e2758abab9bea0c18551a54civoc uint32_t instanceId, 723b04965ccf83c2bc6e2758abab9bea0c18551a54civoc RtcEventLog* const event_log, 724b04965ccf83c2bc6e2758abab9bea0c18551a54civoc const Config& config) { 725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId), 726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::CreateChannel(channelId=%d, instanceId=%d)", 727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com channelId, instanceId); 728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 729b04965ccf83c2bc6e2758abab9bea0c18551a54civoc channel = new Channel(channelId, instanceId, event_log, config); 730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (channel == NULL) 731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, 733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(instanceId,channelId), 734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::CreateChannel() unable to allocate memory for" 735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " channel"); 736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 7429213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::PlayNotification(int32_t id, uint32_t durationMs) 743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PlayNotification(id=%d, durationMs=%d)", 746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com id, durationMs); 747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Not implement yet 749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 7529213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::RecordNotification(int32_t id, uint32_t durationMs) 753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RecordNotification(id=%d, durationMs=%d)", 756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com id, durationMs); 757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Not implement yet 759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 7629213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::PlayFileEnded(int32_t id) 763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PlayFileEnded(id=%d)", id); 766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (id == _inputFilePlayerId) 768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 769944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputFilePlaying(false); 770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PlayFileEnded() => input file player module is" 773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " shutdown"); 774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if (id == _outputFilePlayerId) 776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 777944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetOutputFilePlaying(false); 778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PlayFileEnded() => output file player module is" 781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " shutdown"); 782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 7869213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::RecordFileEnded(int32_t id) 787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RecordFileEnded(id=%d)", id); 790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com assert(id == _outputFileRecorderId); 792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 7939a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = false; 796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RecordFileEnded() => output file recorder module is" 799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " shutdown"); 800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 8029213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::Channel(int32_t channelId, 803e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org uint32_t instanceId, 804b04965ccf83c2bc6e2758abab9bea0c18551a54civoc RtcEventLog* const event_log, 805b04965ccf83c2bc6e2758abab9bea0c18551a54civoc const Config& config) 806b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer : _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 807b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 808b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer volume_settings_critsect_( 809b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer *CriticalSectionWrapper::CreateCriticalSection()), 810b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _instanceId(instanceId), 811b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _channelId(channelId), 812b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer event_log_(event_log), 813b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_header_parser_(RtpHeaderParser::Create()), 814b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_payload_registry_( 815b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))), 816b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_receive_statistics_( 817b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer ReceiveStatistics::Create(Clock::GetRealTimeClock())), 818b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_receiver_( 819b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(), 820b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer this, 821b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer this, 822b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer this, 823b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_payload_registry_.get())), 824b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()), 825b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputAudioLevel(), 826b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _externalTransport(false), 827b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _inputFilePlayerPtr(NULL), 828b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputFilePlayerPtr(NULL), 829b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputFileRecorderPtr(NULL), 830b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // Avoid conflict with other channels by adding 1024 - 1026, 831b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // won't use as much as 1024 channels. 832b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024), 833b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025), 834b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026), 835b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputFileRecording(false), 836b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _inbandDtmfQueue(VoEModuleId(instanceId, channelId)), 837b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)), 838b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputExternalMedia(false), 839b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _inputExternalMediaCallbackPtr(NULL), 840b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputExternalMediaCallbackPtr(NULL), 841b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _timeStamp(0), // This is just an offset, RTP module will add it's own 842b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // random offset 843b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _sendTelephoneEventPayloadType(106), 844b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer ntp_estimator_(Clock::GetRealTimeClock()), 845b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer jitter_buffer_playout_timestamp_(0), 846b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer playout_timestamp_rtp_(0), 847b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer playout_timestamp_rtcp_(0), 848b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer playout_delay_ms_(0), 849b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _numberOfDiscardedPackets(0), 850b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer send_sequence_number_(0), 851b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer ts_stats_lock_(CriticalSectionWrapper::CreateCriticalSection()), 852b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()), 853b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer capture_start_rtp_time_stamp_(-1), 854b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer capture_start_ntp_time_ms_(-1), 855b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _engineStatisticsPtr(NULL), 856b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputMixerPtr(NULL), 857b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _transmitMixerPtr(NULL), 858b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _moduleProcessThreadPtr(NULL), 859b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _audioDeviceModulePtr(NULL), 860b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _voiceEngineObserverPtr(NULL), 861b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _callbackCritSectPtr(NULL), 862b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _transportPtr(NULL), 863b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _rxVadObserverPtr(NULL), 864b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _oldVadDecision(-1), 865b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _sendFrameType(0), 866b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _externalMixing(false), 867b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _mixFileWithMicrophone(false), 868b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _mute(false), 869b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _panLeft(1.0f), 870b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _panRight(1.0f), 871b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputGain(1.0f), 872b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _playOutbandDtmfEvent(false), 873b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _playInbandDtmfEvent(false), 874b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _lastLocalTimeStamp(0), 875b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _lastPayloadType(0), 876b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _includeAudioLevelIndication(false), 877b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _outputSpeechType(AudioFrame::kNormalSpeech), 878b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer video_sync_lock_(CriticalSectionWrapper::CreateCriticalSection()), 879b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _average_jitter_buffer_delay_us(0), 880b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _previousTimestamp(0), 881b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _recPacketDelayMs(20), 882b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _RxVadDetection(false), 883b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _rxAgcIsEnabled(false), 884b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _rxNsIsEnabled(false), 885b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer restored_packet_in_use_(false), 886b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtcp_observer_(new VoERtcpObserver(this)), 887b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer network_predictor_(new NetworkPredictor(Clock::GetRealTimeClock())), 888b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer assoc_send_channel_lock_(CriticalSectionWrapper::CreateCriticalSection()), 889b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer associate_send_channel_(ChannelOwner(nullptr)), 890b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer pacing_enabled_(config.Get<VoicePacing>().enabled), 891b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer feedback_observer_proxy_(pacing_enabled_ ? new TransportFeedbackProxy() 892b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer : nullptr), 893b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer seq_num_allocator_proxy_( 894b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer pacing_enabled_ ? new TransportSequenceNumberProxy() : nullptr), 895b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer rtp_packet_sender_proxy_(pacing_enabled_ ? new RtpPacketSenderProxy() 896b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer : nullptr) { 897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), 898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Channel() - ctor"); 89964dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin AudioCodingModule::Config acm_config; 90064dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin acm_config.id = VoEModuleId(instanceId, channelId); 90164dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin if (config.Get<NetEqCapacityConfig>().enabled) { 90264dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin // Clamping the buffer capacity at 20 packets. While going lower will 90364dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin // probably work, it makes little sense. 90464dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin acm_config.neteq_config.max_packets_in_buffer = 90564dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin std::max(20, config.Get<NetEqCapacityConfig>().capacity); 90664dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin } 9075263b3c1ddb10ecca58d9f08364aad2d6ba1d95dHenrik Lundin acm_config.neteq_config.enable_fast_accelerate = 9085263b3c1ddb10ecca58d9f08364aad2d6ba1d95dHenrik Lundin config.Get<NetEqFastAccelerate>().enabled; 90964dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin audio_coding_.reset(AudioCodingModule::Create(acm_config)); 91064dad838e61e92e4a72437b153c5eba7a200fb4aHenrik Lundin 911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfQueue.ResetDtmf(); 912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.Init(); 913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputAudioLevel.Clear(); 914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 9152853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org RtpRtcp::Configuration configuration; 9162853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org configuration.audio = true; 9172853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org configuration.outgoing_transport = this; 9182853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org configuration.audio_messages = this; 919822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org configuration.receive_statistics = rtp_receive_statistics_.get(); 9200a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org configuration.bandwidth_callback = rtcp_observer_.get(); 921b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer configuration.paced_sender = rtp_packet_sender_proxy_.get(); 922b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer configuration.transport_sequence_number_allocator = 923b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer seq_num_allocator_proxy_.get(); 924b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer configuration.transport_feedback_callback = feedback_observer_proxy_.get(); 9252853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org 9262853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); 92754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 92854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC())); 92954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org rtp_receive_statistics_->RegisterRtcpStatisticsCallback( 93054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org statistics_proxy_.get()); 931f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org 932f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org Config audioproc_config; 933f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org audioproc_config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 934f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org rx_audioproc_.reset(AudioProcessing::Create(audioproc_config)); 935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::~Channel() 938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 93954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL); 940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), 941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::~Channel() - dtor"); 942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputExternalMedia) 944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com DeRegisterExternalMediaProcessing(kPlaybackPerChannel); 946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 947944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().input_external_media) 948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com DeRegisterExternalMediaProcessing(kRecordingPerChannel); 950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com StopSend(); 952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com StopPlayout(); 953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 9559a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr) 957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->StopPlayingFile(); 960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFilePlayerPtr) 964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFilePlayerPtr->StopPlayingFile(); 967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFilePlayerPtr = NULL; 969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The order to safely shutdown modules in a channel is: 980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // 1. De-register callbacks in modules 981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // 2. De-register modules in process thread 982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // 3. Destroy modules 983eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterTransportCallback(NULL) == -1) 984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "~Channel() failed to de-register transport callback" 988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " (Audio coding module)"); 989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 990eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterVADCallback(NULL) == -1) 991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "~Channel() failed to de-register VAD callback" 995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " (Audio coding module)"); 996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // De-register modules in process thread 9983985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()); 9993985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org 1000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // End of modules shutdown 1001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Delete other objects 1003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete &_callbackCritSect; 1004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com delete &_fileCritSect; 100563420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org delete &volume_settings_critsect_; 1006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10086141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Init() 1010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init()"); 1013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1014944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.Reset(); 1015944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org 1016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Initial sanity 1017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((_engineStatisticsPtr == NULL) || 1019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (_moduleProcessThreadPtr == NULL)) 1020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, 1022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 1023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() must call SetEngineInformation() first"); 1024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Add modules to process thread (for periodic schedulation) 1028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 10293985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()); 10303985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org 1031c450a1966965fbb3c16ec6d02c3d5cbec67df500pwestin@webrtc.org // --- ACM initialization 1032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1033061b79af6023b6caf9975be39fe53dd0ec3b7464henrik.lundin if (audio_coding_->InitializeReceiver() == -1) { 1034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() unable to initialize the ACM - 1"); 1037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- RTP/RTCP module initialization 1041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Ensure that RTCP is enabled by default for the created channel. 1043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Note that, the module will keep generating RTCP until it is explicitly 1044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // disabled by the user. 1045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // After StopListen (when no sockets exists), RTCP packets will no longer 1046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // be transmitted since the Transport object will then be invalid. 1047822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org telephone_event_handler_->SetTelephoneEventForwardToDecoder(true); 1048822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // RTCP is enabled by default. 1049da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound); 1050d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org // --- Register all permanent callbacks 1051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const bool fail = 1052eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org (audio_coding_->RegisterTransportCallback(this) == -1) || 1053eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org (audio_coding_->RegisterVADCallback(this) == -1); 1054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (fail) 1056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_CANNOT_INIT_CHANNEL, kTraceError, 1059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() callbacks not registered"); 1060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Register all supported codecs to the receiving side of the 1064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // RTP/RTCP module 1065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst codec; 10676141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs(); 1068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (int idx = 0; idx < nSupportedCodecs; idx++) 1070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Open up the RTP/RTCP receiver for all supported codecs 1072eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if ((audio_coding_->Codec(idx, &codec) == -1) || 1073822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (rtp_receiver_->RegisterReceivePayload( 1074822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plname, 1075822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.pltype, 1076822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plfreq, 1077822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.channels, 1078822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (codec.rate < 0) ? 0 : codec.rate) == -1)) 1079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 10826955870806624479723addfae6dcf5d13968796cPeter Kasting "Channel::Init() unable to register %s " 10836955870806624479723addfae6dcf5d13968796cPeter Kasting "(%d/%d/%" PRIuS "/%d) to RTP/RTCP receiver", 1084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.plname, codec.pltype, codec.plfreq, 1085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.channels, codec.rate); 1086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 1088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, 1090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 10916955870806624479723addfae6dcf5d13968796cPeter Kasting "Channel::Init() %s (%d/%d/%" PRIuS "/%d) has been " 10926955870806624479723addfae6dcf5d13968796cPeter Kasting "added to the RTP/RTCP receiver", 1093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.plname, codec.pltype, codec.plfreq, 1094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.channels, codec.rate); 1095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Ensure that PCMU is used as default codec on the sending side 10984517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) 1099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com SetSendCodec(codec); 1101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Register default PT for outband 'telephone-event' 1104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!STR_CASE_CMP(codec.plname, "telephone-event")) 1105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 11062853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) || 1107eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org (audio_coding_->RegisterReceiveCodec(codec) == -1)) 1108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 1111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() failed to register outband " 1112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "'telephone-event' (%d/%d) correctly", 1113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.pltype, codec.plfreq); 1114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!STR_CASE_CMP(codec.plname, "CN")) 1118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1119eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if ((audio_coding_->RegisterSendCodec(codec) == -1) || 1120eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org (audio_coding_->RegisterReceiveCodec(codec) == -1) || 11212853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org (_rtpRtcpModule->RegisterSendPayload(codec) == -1)) 1122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 1125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() failed to register CN (%d/%d) " 1126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "correctly - 1", 1127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.pltype, codec.plfreq); 1128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_CODEC_RED 1131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Register RED to the receiving side of the ACM. 1132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // We will not receive an OnInitializeDecoder() callback for RED. 1133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!STR_CASE_CMP(codec.plname, "RED")) 1134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1135eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterReceiveCodec(codec) == -1) 1136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId,_channelId), 1139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::Init() failed to register RED (%d/%d) " 1140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "correctly", 1141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.pltype, codec.plfreq); 1142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif 1145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1146684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 11476c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org if (rx_audioproc_->noise_suppression()->set_level(kDefaultNsMode) != 0) { 1148ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos LOG(LS_ERROR) << "noise_suppression()->set_level(kDefaultNsMode) failed."; 11496c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org return -1; 1150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 11516c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org if (rx_audioproc_->gain_control()->set_mode(kDefaultRxAgcMode) != 0) { 1152ad856229a796a8efa1126ef8aa8d238f2b0a2b21pbos LOG(LS_ERROR) << "gain_control()->set_mode(kDefaultRxAgcMode) failed."; 11536c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org return -1; 1154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11596141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetEngineInformation(Statistics& engineStatistics, 1161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com OutputMixer& outputMixer, 1162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com voe::TransmitMixer& transmitMixer, 1163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ProcessThread& moduleProcessThread, 1164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com AudioDeviceModule& audioDeviceModule, 1165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoiceEngineObserver* voiceEngineObserver, 1166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CriticalSectionWrapper* callbackCritSect) 1167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetEngineInformation()"); 1170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr = &engineStatistics; 1171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr = &outputMixer; 1172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transmitMixerPtr = &transmitMixer, 1173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _moduleProcessThreadPtr = &moduleProcessThread; 1174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _audioDeviceModulePtr = &audioDeviceModule; 1175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _voiceEngineObserverPtr = voiceEngineObserver; 1176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _callbackCritSectPtr = callbackCritSect; 1177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateLocalTimeStamp() 1182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1184b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_); 1185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11882d110be77f14cab0bb51efe8b61d9c7a967d04cbdeadbeefvoid Channel::SetSink(rtc::scoped_ptr<AudioSinkInterface> sink) { 1189f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi CriticalSectionScoped cs(&_callbackCritSect); 11902d110be77f14cab0bb51efe8b61d9c7a967d04cbdeadbeef audio_sink_ = std::move(sink); 1191f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi} 1192f888bb58da04c5095759b5ec7ce2e1fa2cd414fdTommi 11936141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartPlayout() 1195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartPlayout()"); 1198944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().playing) 1199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 12021b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 12031b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com if (!_externalMixing) { 12041b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com // Add participant as candidates for mixing. 12051b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) 12061b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com { 12071b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com _engineStatisticsPtr->SetLastError( 12081b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 12091b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com "StartPlayout() failed to add participant to mixer"); 12101b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com return -1; 12111b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com } 1212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1214944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetPlaying(true); 1215ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org if (RegisterFilePlayingToMixer() != 0) 1216ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org return -1; 1217ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 1218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 12216141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopPlayout() 1223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopPlayout()"); 1226944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().playing) 1227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 12301b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 12311b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com if (!_externalMixing) { 12321b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com // Remove participant as candidates for mixing 12331b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) 12341b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com { 12351b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com _engineStatisticsPtr->SetLastError( 12361b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 12371b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com "StopPlayout() failed to remove participant from mixer"); 12381b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com return -1; 12391b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com } 1240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1242944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetPlaying(false); 1243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputAudioLevel.Clear(); 1244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 12486141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartSend() 1250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartSend()"); 125309e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // Resume the previous sequence number which was reset by StopSend(). 1254944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org // This needs to be done before |sending| is set to true. 125509e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org if (send_sequence_number_) 125609e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org SetInitSequenceNumber(send_sequence_number_); 125709e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org 1258944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().sending) 1259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1260944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org return 0; 1261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1262944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetSending(true); 1263e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org 12642853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SetSendingStatus(true) != 0) 1265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartSend() RTP/RTCP failed to start sending"); 12699a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 1270944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetSending(false); 1271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1273e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org 1274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 12776141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopSend() 1279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopSend()"); 1282944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().sending) 1283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1284944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org return 0; 1285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1286944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetSending(false); 1287e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org 128809e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // Store the sequence number to be able to pick up the same sequence for 128909e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // the next StartSend(). This is needed for restarting device, otherwise 129009e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // it might cause libSRTP to complain about packets being replayed. 129109e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring 129209e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // CL is landed. See issue 129309e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org // https://code.google.com/p/webrtc/issues/detail?id=2111 . 129409e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org send_sequence_number_ = _rtpRtcpModule->SequenceNumber(); 129509e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org 1296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Reset sending SSRC and sequence number and triggers direct transmission 1297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // of RTCP BYE 1298d436298332c7a7ecb51241f3a66588539c2ece83pbos if (_rtpRtcpModule->SetSendingStatus(false) == -1) 1299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 1302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartSend() RTP/RTCP failed to stop sending"); 1303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13086141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartReceiving() 1310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartReceiving()"); 1313944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().receiving) 1314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1317944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetReceiving(true); 1318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _numberOfDiscardedPackets = 0; 1319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13226141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopReceiving() 1324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopReceiving()"); 1327944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().receiving) 1328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1331684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 1332944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetReceiving(false); 1333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13366141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) 1338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterVoiceEngineObserver()"); 13419a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 1342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_voiceEngineObserverPtr) 1344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceError, 1347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterVoiceEngineObserver() observer already enabled"); 1348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _voiceEngineObserverPtr = &observer; 1351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13546141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterVoiceEngineObserver() 1356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterVoiceEngineObserver()"); 13599a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 1360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_voiceEngineObserverPtr) 1362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceWarning, 1365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "DeRegisterVoiceEngineObserver() observer already disabled"); 1366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _voiceEngineObserverPtr = NULL; 1369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13726141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendCodec(CodecInst& codec) 1374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 13751fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg auto send_codec = audio_coding_->SendCodec(); 13761fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg if (send_codec) { 13771fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg codec = *send_codec; 13781fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg return 0; 13791fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg } 13801fd4a4ab35f1fcb08b551befca180de9a1f55dfckwiberg return -1; 1381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13836141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecCodec(CodecInst& codec) 1385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1386eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org return (audio_coding_->ReceiveCodec(&codec)); 1387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13896141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCodec(const CodecInst& codec) 1391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetSendCodec()"); 1394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1395eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterSendCodec(codec) != 0) 1396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCodec() failed to register codec to ACM"); 1399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14022853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 14042853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 14052853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE( 1408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCodec() failed to register codec to" 1410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " RTP/RTCP module"); 1411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14152853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0) 1416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCodec() failed to set audio packet size"); 1419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1425adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusenvoid Channel::SetBitRate(int bitrate_bps) { 1426adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 1427adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps); 1428adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen audio_coding_->SetBitRate(bitrate_bps); 1429adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen} 1430adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen 14310a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.orgvoid Channel::OnIncomingFractionLoss(int fraction_lost) { 143274aaf29a0ff1b211dbfdbb6309791111a7871779minyue@webrtc.org network_predictor_->UpdatePacketLossRate(fraction_lost); 14330a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org uint8_t average_fraction_loss = network_predictor_->GetLossRate(); 14340a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 1435c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org // Normalizes rate to 0 - 100. 14360a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org if (audio_coding_->SetPacketLossRate( 14370a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org 100 * average_fraction_loss / 255) != 0) { 1438c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org assert(false); // This should not happen. 1439c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org } 1440c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org} 1441c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 14426141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX) 1444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetVADStatus(mode=%d)", mode); 1447664ccb7d8da3adfffdb7c56f885b633224555e6ehenrik.lundin@webrtc.org assert(!(disableDTX && enableVAD)); // disableDTX mode is deprecated. 1448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // To disable VAD, DTX must be disabled too 1449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com disableDTX = ((enableVAD == false) ? true : disableDTX); 1450eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->SetVAD(!disableDTX, enableVAD, mode) != 0) 1451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetVADStatus() failed to set VAD"); 1455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14606141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX) 1462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1463eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->VAD(&disabledDTX, &enabledVAD, &mode) != 0) 1464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetVADStatus() failed to get VAD status"); 1468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com disabledDTX = !disabledDTX; 1471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14746141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRecPayloadType(const CodecInst& codec) 1476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetRecPayloadType()"); 1479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1480944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().playing) 1481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_PLAYING, kTraceError, 1484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() unable to set PT while playing"); 1485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1487944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().receiving) 1488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_LISTENING, kTraceError, 1491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() unable to set PT while listening"); 1492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (codec.pltype == -1) 1496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // De-register the selected codec (RTP/RTCP module and ACM) 1498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 14996141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int8_t pltype(-1); 1500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst rxCodec = codec; 1501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Get payload type for the given codec 1503822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_payload_registry_->ReceivePayloadType( 1504822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rxCodec.plname, 1505822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rxCodec.plfreq, 1506822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rxCodec.channels, 1507822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (rxCodec.rate < 0) ? 0 : rxCodec.rate, 1508822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org &pltype); 1509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com rxCodec.pltype = pltype; 1510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1511822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) 1512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, 1515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 1516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() RTP/RTCP-module deregistration " 1517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "failed"); 1518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1520eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) 1521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() ACM deregistration failed - 1"); 1525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1530822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (rtp_receiver_->RegisterReceivePayload( 1531822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plname, 1532822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.pltype, 1533822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plfreq, 1534822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.channels, 1535822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (codec.rate < 0) ? 0 : codec.rate) != 0) 1536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // First attempt to register failed => de-register and try again 1538822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_receiver_->DeRegisterReceivePayload(codec.pltype); 1539822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (rtp_receiver_->RegisterReceivePayload( 1540822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plname, 1541822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.pltype, 1542822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plfreq, 1543822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.channels, 1544822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (codec.rate < 0) ? 0 : codec.rate) != 0) 1545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() RTP/RTCP-module registration failed"); 1549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1552eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterReceiveCodec(codec) != 0) 1553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1554eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org audio_coding_->UnregisterReceiveCodec(codec.pltype); 1555eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterReceiveCodec(codec) != 0) 1556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRecPayloadType() ACM registration failed - 1"); 1560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 15666141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecPayloadType(CodecInst& codec) 1568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 15696141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int8_t payloadType(-1); 1570822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (rtp_payload_registry_->ReceivePayloadType( 1571822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plname, 1572822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plfreq, 1573822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.channels, 1574822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (codec.rate < 0) ? 0 : codec.rate, 1575822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org &payloadType) != 0) 1576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 157837198007eab6731fa0f77866155dd4f2b332a262henrika@webrtc.org VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 1579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetRecPayloadType() failed to retrieve RX payload type"); 1580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.pltype = payloadType; 1583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 15866141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) 1588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetSendCNPayloadType()"); 1591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst codec; 15936141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int32_t samplingFreqHz(-1); 15946955870806624479723addfae6dcf5d13968796cPeter Kasting const size_t kMono = 1; 1595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (frequency == kFreq32000Hz) 1596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com samplingFreqHz = 32000; 1597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if (frequency == kFreq16000Hz) 1598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com samplingFreqHz = 16000; 1599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1600eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) 1601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCNPayloadType() failed to retrieve default CN codec " 1605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "settings"); 1606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Modify the payload type (must be set to dynamic range) 1610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.pltype = type; 1611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1612eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterSendCodec(codec) != 0) 1613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCNPayloadType() failed to register CN to ACM"); 1617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 16202853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 16222853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 16232853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendCNPayloadType() failed to register CN to RTP/RTCP " 1628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "module"); 1629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1635adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.orgint Channel::SetOpusMaxPlaybackRate(int frequency_hz) { 16366aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 1637adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org "Channel::SetOpusMaxPlaybackRate()"); 16386aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org 1639adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) { 16406aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org _engineStatisticsPtr->SetLastError( 16416aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1642adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org "SetOpusMaxPlaybackRate() failed to set maximum playback rate"); 16436aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org return -1; 16446aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org } 16456aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org return 0; 16466aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org} 16476aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org 16489b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.orgint Channel::SetOpusDtx(bool enable_dtx) { 16499b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 16509b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org "Channel::SetOpusDtx(%d)", enable_dtx); 1651092041c1cdadeb82463ee79dfc291d60b41d35efMinyue Li int ret = enable_dtx ? audio_coding_->EnableOpusDtx() 16529b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org : audio_coding_->DisableOpusDtx(); 16539b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org if (ret != 0) { 16549b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org _engineStatisticsPtr->SetLastError( 16559b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org VE_AUDIO_CODING_MODULE_ERROR, kTraceError, "SetOpusDtx() failed"); 16569b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org return -1; 16579b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org } 16589b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org return 0; 16599b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org} 16609b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org 16616141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t Channel::RegisterExternalTransport(Transport& transport) 1662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 1664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterExternalTransport()"); 1665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 16669a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 1667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_externalTransport) 1669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, 1671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceError, 1672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterExternalTransport() external transport already enabled"); 1673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalTransport = true; 1676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transportPtr = &transport; 1677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 16806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 1681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterExternalTransport() 1682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterExternalTransport()"); 1685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 16869a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 168783661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org 1688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_transportPtr) 1689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceWarning, 1692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "DeRegisterExternalTransport() external transport already " 1693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "disabled"); 1694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _externalTransport = false; 1697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _transportPtr = NULL; 1698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "DeRegisterExternalTransport() all transport is disabled"); 1700684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org return 0; 1701684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org} 1702684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 17034591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t Channel::ReceivedRTPPacket(const int8_t* data, size_t length, 1704b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org const PacketTime& packet_time) { 17050c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 17060c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org "Channel::ReceivedRTPPacket()"); 1707684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 17080c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org // Store playout timestamp for the received RTP packet 17091de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org UpdatePlayoutTimestamp(false); 1710684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 17117bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org const uint8_t* received_packet = reinterpret_cast<const uint8_t*>(data); 1712a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org RTPHeader header; 17137bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!rtp_header_parser_->Parse(received_packet, length, &header)) { 17147bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 17157bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org "Incoming packet: invalid RTP header"); 1716a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org return -1; 1717a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org } 1718822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org header.payload_type_frequency = 1719822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType); 17207bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (header.payload_type_frequency < 0) 1721822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org return -1; 172248df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org bool in_order = IsPacketInOrder(header); 17237bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receive_statistics_->IncomingPacket(header, length, 172448df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org IsPacketRetransmitted(header, in_order)); 17257bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_payload_registry_->SetIncomingPayloadType(header); 1726b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org 172748df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1; 17287bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 17297bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 17307bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::ReceivePacket(const uint8_t* packet, 17314591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t packet_length, 17327bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org const RTPHeader& header, 17337bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org bool in_order) { 1734456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org if (rtp_payload_registry_->IsRtx(header)) { 1735456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org return HandleRtxPacket(packet, packet_length, header); 1736822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 17377bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org const uint8_t* payload = packet + header.headerLength; 17384591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org assert(packet_length >= header.headerLength); 17394591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t payload_length = packet_length - header.headerLength; 1740822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org PayloadUnion payload_specific; 1741822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, 17427bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org &payload_specific)) { 17437bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 1744822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 17457bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length, 17467bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org payload_specific, in_order); 17477bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 17487bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 1749456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.orgbool Channel::HandleRtxPacket(const uint8_t* packet, 1750456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org size_t packet_length, 1751456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org const RTPHeader& header) { 17527bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!rtp_payload_registry_->IsRtx(header)) 17537bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17547bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 17557bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Remove the RTX header and parse the original RTP header. 17567bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (packet_length < header.headerLength) 17577bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17587bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (packet_length > kVoiceEngineMaxIpPacketSizeBytes) 17597bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17607bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (restored_packet_in_use_) { 17617bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 17627bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org "Multiple RTX headers detected, dropping packet"); 17637bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17640c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org } 17657bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!rtp_payload_registry_->RestoreOriginalPacket( 176665220a70a38ffe252b587775c5e9104606ab7c2cnoahric restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(), 176765220a70a38ffe252b587775c5e9104606ab7c2cnoahric header)) { 17687bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 17697bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org "Incoming RTX packet: invalid RTP header"); 17707bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17717bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 17727bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org restored_packet_in_use_ = true; 177365220a70a38ffe252b587775c5e9104606ab7c2cnoahric bool ret = OnRecoveredPacket(restored_packet_, packet_length); 17747bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org restored_packet_in_use_ = false; 17757bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return ret; 17767bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 17777bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 17787bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::IsPacketInOrder(const RTPHeader& header) const { 17797bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org StreamStatistician* statistician = 17807bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receive_statistics_->GetStatistician(header.ssrc); 17817bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!statistician) 17827bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17837bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return statistician->IsPacketInOrder(header.sequenceNumber); 17840c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org} 17850c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org 178648df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.orgbool Channel::IsPacketRetransmitted(const RTPHeader& header, 178748df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org bool in_order) const { 17887bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Retransmissions are handled separately if RTX is enabled. 17897bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (rtp_payload_registry_->RtxEnabled()) 17907bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17917bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org StreamStatistician* statistician = 17927bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receive_statistics_->GetStatistician(header.ssrc); 17937bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (!statistician) 17947bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 17957bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Check if this is a retransmission. 179616825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t min_rtt = 0; 17977bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); 179848df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org return !in_order && 17997bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org statistician->IsRetransmitOfOldPacket(header, min_rtt); 1800822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} 1801822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 18024591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t Channel::ReceivedRTCPPacket(const int8_t* data, size_t length) { 18030c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 18040c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org "Channel::ReceivedRTCPPacket()"); 18050c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org // Store playout timestamp for the received RTCP packet 18061de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org UpdatePlayoutTimestamp(true); 18070c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org 18080c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org // Deliver RTCP packet to RTP/RTCP module for parsing 18094591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data, length) == -1) { 18100c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org _engineStatisticsPtr->SetLastError( 18110c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, 18120c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org "Channel::IncomingRTPPacket() RTCP packet is invalid"); 18130c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org } 181482c4b8531c2c4c2aaf82ff57ee1805037a43ed50wu@webrtc.org 18152013aeced2b7821a407f302802c4a16fd02728b1Minyue int64_t rtt = GetRTT(true); 18162013aeced2b7821a407f302802c4a16fd02728b1Minyue if (rtt == 0) { 18172013aeced2b7821a407f302802c4a16fd02728b1Minyue // Waiting for valid RTT. 18182013aeced2b7821a407f302802c4a16fd02728b1Minyue return 0; 18192013aeced2b7821a407f302802c4a16fd02728b1Minyue } 18202013aeced2b7821a407f302802c4a16fd02728b1Minyue uint32_t ntp_secs = 0; 18212013aeced2b7821a407f302802c4a16fd02728b1Minyue uint32_t ntp_frac = 0; 18222013aeced2b7821a407f302802c4a16fd02728b1Minyue uint32_t rtp_timestamp = 0; 18232013aeced2b7821a407f302802c4a16fd02728b1Minyue if (0 != _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL, 18242013aeced2b7821a407f302802c4a16fd02728b1Minyue &rtp_timestamp)) { 18252013aeced2b7821a407f302802c4a16fd02728b1Minyue // Waiting for RTCP. 18262013aeced2b7821a407f302802c4a16fd02728b1Minyue return 0; 18272013aeced2b7821a407f302802c4a16fd02728b1Minyue } 18282013aeced2b7821a407f302802c4a16fd02728b1Minyue 18298e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org { 18308e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org CriticalSectionScoped lock(ts_stats_lock_.get()); 18312c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp); 18328e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org } 18330c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org return 0; 1834684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org} 1835684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org 1836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(const char* fileName, 18379213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org bool loop, 18389213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org FileFormats format, 18399213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int startPosition, 18409213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org float volumeScaling, 18419213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int stopPosition, 1842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 1843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d," 1846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " format=%d, volumeScaling=%5.3f, startPosition=%d, " 1847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "stopPosition=%d)", fileName, loop, format, volumeScaling, 1848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com startPosition, stopPosition); 1849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1850944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().output_file_playing) 1851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_PLAYING, kTraceError, 1854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileLocally() is already playing"); 1855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 18599a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 1860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1861b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr) 1862b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1863b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 1864b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1865b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = NULL; 1866b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1868b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = FilePlayer::CreateFilePlayer( 1869b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerId, (const FileFormats)format); 1870b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1871b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr == NULL) 1872b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1873b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _engineStatisticsPtr->SetLastError( 1874b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org VE_INVALID_ARGUMENT, kTraceError, 187531d30700d638c4cfa47c26cac7cb00c7232874c9henrike@webrtc.org "StartPlayingFileLocally() filePlayer format is not correct"); 1876b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org return -1; 1877b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 18796141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 1880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1881b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr->StartPlayingFile( 1882b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org fileName, 1883b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org loop, 1884b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org startPosition, 1885b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org volumeScaling, 1886b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org notificationTime, 1887b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org stopPosition, 1888b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org (const CodecInst*)codecInst) != 0) 1889b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1890b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _engineStatisticsPtr->SetLastError( 1891b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org VE_BAD_FILE, kTraceError, 1892b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "StartPlayingFile() failed to start file playout"); 1893b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->StopPlayingFile(); 1894b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1895b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = NULL; 1896b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org return -1; 1897b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1898b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->RegisterModuleFileCallback(this); 1899944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetOutputFilePlaying(true); 1900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1901ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 1902ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org if (RegisterFilePlayingToMixer() != 0) 1903066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org return -1; 1904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(InStream* stream, 19099213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org FileFormats format, 19109213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int startPosition, 19119213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org float volumeScaling, 19129213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int stopPosition, 1913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 1914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartPlayingFileLocally(format=%d," 1917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)", 1918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format, volumeScaling, startPosition, stopPosition); 1919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(stream == NULL) 1921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_FILE, kTraceError, 1924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileLocally() NULL as input stream"); 1925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1929944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().output_file_playing) 1930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 1932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_PLAYING, kTraceError, 1933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileLocally() is already playing"); 1934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 1935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 19389a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 1939b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1940b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org // Destroy the old instance 1941b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr) 1942b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1943b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 1944b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1945b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = NULL; 1946b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1947b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1948b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org // Create the instance 1949b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = FilePlayer::CreateFilePlayer( 1950b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerId, 1951b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org (const FileFormats)format); 1952b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1953b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr == NULL) 1954b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1955b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _engineStatisticsPtr->SetLastError( 1956b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org VE_INVALID_ARGUMENT, kTraceError, 1957b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "StartPlayingFileLocally() filePlayer format isnot correct"); 1958b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org return -1; 1959b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1960b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 19616141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 1962b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1963b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition, 1964b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org volumeScaling, 1965b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org notificationTime, 1966b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org stopPosition, codecInst) != 0) 1967b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 1968b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 1969b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "StartPlayingFile() failed to " 1970b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "start file playout"); 1971b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->StopPlayingFile(); 1972b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1973b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = NULL; 1974b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org return -1; 1975b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1976b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->RegisterModuleFileCallback(this); 1977944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetOutputFilePlaying(true); 1978b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 1979ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 1980ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org if (RegisterFilePlayingToMixer() != 0) 1981066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org return -1; 1982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 1985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileLocally() 1987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 1988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopPlayingFileLocally()"); 1990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1991944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().output_file_playing) 1992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 1994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 1995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 19979a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 1998b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org 1999b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org if (_outputFilePlayerPtr->StopPlayingFile() != 0) 2000b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org { 2001b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _engineStatisticsPtr->SetLastError( 2002b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org VE_STOP_RECORDING_FAILED, kTraceError, 2003b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "StopPlayingFile() could not stop playing"); 2004b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org return -1; 2005b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org } 2006b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2007b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2008b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org _outputFilePlayerPtr = NULL; 2009944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetOutputFilePlaying(false); 2010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2011b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org // _fileCritSect cannot be taken while calling 2012b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org // SetAnonymousMixibilityStatus. Refer to comments in 2013b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org // StartPlayingFileLocally(const char* ...) for more details. 2014066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) 2015066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org { 2016066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org _engineStatisticsPtr->SetLastError( 2017066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 2018b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "StopPlayingFile() failed to stop participant from playing as" 2019b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org "file in the mixer"); 2020066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org return -1; 2021066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org } 2022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileLocally() const 2027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2028944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org return channel_state_.Get().output_file_playing; 2029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2031ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.orgint Channel::RegisterFilePlayingToMixer() 2032ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org{ 2033ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // Return success for not registering for file playing to mixer if: 2034ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // 1. playing file before playout is started on that channel. 2035ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // 2. starting playout without file playing on that channel. 2036944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().playing || 2037944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org !channel_state_.Get().output_file_playing) 2038ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org { 2039ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org return 0; 2040ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org } 2041ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 2042ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // |_fileCritSect| cannot be taken while calling 2043ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // SetAnonymousMixabilityStatus() since as soon as the participant is added 2044ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // frames can be pulled by the mixer. Since the frames are generated from 2045ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org // the file, _fileCritSect will be taken. This would result in a deadlock. 2046ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) 2047ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org { 2048944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetOutputFilePlaying(false); 2049ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2050ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org _engineStatisticsPtr->SetLastError( 2051ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 2052ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org "StartPlayingFile() failed to add participant as file to mixer"); 2053ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org _outputFilePlayerPtr->StopPlayingFile(); 2054ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2055ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org _outputFilePlayerPtr = NULL; 2056ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org return -1; 2057ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org } 2058ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 2059ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org return 0; 2060ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org} 2061ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org 2062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(const char* fileName, 20639213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org bool loop, 20649213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org FileFormats format, 20659213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int startPosition, 20669213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org float volumeScaling, 20679213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int stopPosition, 2068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 2069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, " 2072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, " 2073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "stopPosition=%d)", fileName, loop, format, volumeScaling, 2074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com startPosition, stopPosition); 2075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2076944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2077944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org 2078944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().input_file_playing) 2079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_PLAYING, kTraceWarning, 2082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileAsMicrophone() filePlayer is playing"); 2083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 2087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr) 2088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 2092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Create the instance 2095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = FilePlayer::CreateFilePlayer( 2096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerId, (const FileFormats)format); 2097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr == NULL) 2099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileAsMicrophone() filePlayer format isnot correct"); 2103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 21066141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 2107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr->StartPlayingFile( 2109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fileName, 2110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com loop, 2111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com startPosition, 2112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com volumeScaling, 2113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com notificationTime, 2114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stopPosition, 2115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const CodecInst*)codecInst) != 0) 2116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_FILE, kTraceError, 2119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFile() failed to start file playout"); 2120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->StopPlayingFile(); 2121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 2123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(this); 2126944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputFilePlaying(true); 2127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(InStream* stream, 21329213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org FileFormats format, 21339213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int startPosition, 21349213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org float volumeScaling, 21359213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int stopPosition, 2136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 2137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartPlayingFileAsMicrophone(format=%d, " 2140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)", 2141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format, volumeScaling, startPosition, stopPosition); 2142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(stream == NULL) 2144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_FILE, kTraceError, 2147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileAsMicrophone NULL as input stream"); 2148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2151944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2152944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org 2153944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().input_file_playing) 2154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_PLAYING, kTraceWarning, 2157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFileAsMicrophone() is playing"); 2158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 2162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr) 2163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 2167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Create the instance 2170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = FilePlayer::CreateFilePlayer( 2171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerId, (const FileFormats)format); 2172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr == NULL) 2174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingInputFile() filePlayer format isnot correct"); 2178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 21816141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); 2182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition, 2184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com volumeScaling, notificationTime, 2185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stopPosition, codecInst) != 0) 2186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 2188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartPlayingFile() failed to start " 2189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "file playout"); 2190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->StopPlayingFile(); 2191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 2193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2195ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 2196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(this); 2197944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputFilePlaying(true); 2198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileAsMicrophone() 2203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopPlayingFileAsMicrophone()"); 2206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2207944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2208944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org 2209944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().input_file_playing) 2210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr->StopPlayingFile() != 0) 2215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_STOP_RECORDING_FAILED, kTraceError, 2218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StopPlayingFile() could not stop playing"); 2219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputFilePlayerPtr = NULL; 2224944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputFilePlaying(false); 2225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileAsMicrophone() const 2230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2231944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org return channel_state_.Get().input_file_playing; 2232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2234813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.orgint Channel::StartRecordingPlayout(const char* fileName, 2235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 2236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartRecordingPlayout(fileName=%s)", fileName); 2239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecording) 2241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 2243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() is already recording"); 2244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileFormats format; 22486141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); // Not supported in VoE 2249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 2250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 225140197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org if ((codecInst != NULL) && 225240197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org ((codecInst->channels < 1) || (codecInst->channels > 2))) 2253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_ARGUMENT, kTraceError, 2256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() invalid compression"); 2257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-1); 2258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(codecInst == NULL) 2260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatPcm16kHzFile; 2262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codecInst=&dummyCodec; 2263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 2265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 2266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 2267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatWavFile; 2269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 2271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatCompressedFile; 2273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 22759a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 2278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 2279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 2283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 2286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderId, (const FileFormats)format); 2287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr == NULL) 2288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() fileRecorder format isnot correct"); 2292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StartRecordingAudioFile( 2296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fileName, (const CodecInst&)*codecInst, notificationTime) != 0) 2297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_FILE, kTraceError, 2300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingAudioFile() failed to start file recording"); 2301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 2302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 2304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(this); 2307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = true; 2308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartRecordingPlayout(OutStream* stream, 2313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const CodecInst* codecInst) 2314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StartRecordingPlayout()"); 2317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecording) 2319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 2321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() is already recording"); 2322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileFormats format; 23266141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint32_t notificationTime(0); // Not supported in VoE 2327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 2328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (codecInst != NULL && codecInst->channels != 1) 2330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_BAD_ARGUMENT, kTraceError, 2333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() invalid compression"); 2334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-1); 2335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(codecInst == NULL) 2337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatPcm16kHzFile; 2339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codecInst=&dummyCodec; 2340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 2342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 2343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 2344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatWavFile; 2346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 2348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com format = kFileFormatCompressedFile; 2350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 23529a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Destroy the old instance 2355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr) 2356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 2360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 2363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderId, (const FileFormats)format); 2364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr == NULL) 2365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() fileRecorder format isnot correct"); 2369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst, 2373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com notificationTime) != 0) 2374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 2376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StartRecordingPlayout() failed to " 2377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "start file recording"); 2378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->StopRecording(); 2379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 2381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2383ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 2384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(this); 2385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = true; 2386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopRecordingPlayout() 2391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 2393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::StopRecordingPlayout()"); 2394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_outputFileRecording) 2396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), 2398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StopRecordingPlayout() isnot recording"); 2399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 24039a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFileRecorderPtr->StopRecording() != 0) 2406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_STOP_RECORDING_FAILED, kTraceError, 2409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "StopRecording() could not stop recording"); 2410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-1); 2411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecorderPtr = NULL; 2415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputFileRecording = false; 2416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 2421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMixWithMicStatus(bool mix) 2422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2423944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 2424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _mixFileWithMicrophone=mix; 2425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 24286141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::GetSpeechOutputLevel(uint32_t& level) const 2429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 24306141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int8_t currentLevel = _outputAudioLevel.Level(); 24316141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org level = static_cast<int32_t> (currentLevel); 2432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 24366141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::GetSpeechOutputLevelFullRange(uint32_t& level) const 2437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 24386141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int16_t currentLevel = _outputAudioLevel.LevelFullRange(); 24396141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org level = static_cast<int32_t> (currentLevel); 2440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMute(bool enable) 2445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 244663420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetMute(enable=%d)", enable); 2449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _mute = enable; 2450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool 2454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Mute() const 2455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 245663420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return _mute; 2458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetOutputVolumePan(float left, float right) 2462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 246363420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetOutputVolumePan()"); 2466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panLeft = left; 2467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _panRight = right; 2468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetOutputVolumePan(float& left, float& right) const 2473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 247463420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com left = _panLeft; 2476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com right = _panRight; 2477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetChannelOutputVolumeScaling(float scaling) 2482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 248363420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetChannelOutputVolumeScaling()"); 2486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputGain = scaling; 2487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetChannelOutputVolumeScaling(float& scaling) const 2492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 249363420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org CriticalSectionScoped cs(&volume_settings_critsect_); 2494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com scaling = _outputGain; 2495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventOutband(unsigned char eventCode, 2499822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org int lengthMs, int attenuationDb, 2500822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org bool playDtmfEvent) 2501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)", 2504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com playDtmfEvent); 2505b572768efbc1e52b97a5ad98932c667956aba4b8Fredrik Solenberg if (!Sending()) { 2506b572768efbc1e52b97a5ad98932c667956aba4b8Fredrik Solenberg return -1; 2507b572768efbc1e52b97a5ad98932c667956aba4b8Fredrik Solenberg } 2508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _playOutbandDtmfEvent = playDtmfEvent; 2510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 25112853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs, 2512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com attenuationDb) != 0) 2513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_SEND_DTMF_FAILED, 2516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceWarning, 2517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendTelephoneEventOutband() failed to send event"); 2518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventInband(unsigned char eventCode, 2524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int lengthMs, 2525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int attenuationDb, 2526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com bool playDtmfEvent) 2527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)", 2530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com playDtmfEvent); 2531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _playInbandDtmfEvent = playDtmfEvent; 2533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb); 2534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendTelephoneEventPayloadType(unsigned char type) 2540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetSendTelephoneEventPayloadType()"); 2543f81f9f8c2a18fb20ee60406ece45ff3210367ff9andrew@webrtc.org if (type > 127) 2544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetSendTelephoneEventPayloadType() invalid type"); 2548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 25505b10d8fb184db0192091bf407c8166b5d03b932epbos@webrtc.org CodecInst codec = {}; 25511da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org codec.plfreq = 8000; 25521da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org codec.pltype = type; 25531da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org memcpy(codec.plname, "telephone-event", 16); 25542853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 2555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 25564392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 25574392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) { 25584392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org _engineStatisticsPtr->SetLastError( 25594392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org VE_RTP_RTCP_MODULE_ERROR, kTraceError, 25604392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org "SetSendTelephoneEventPayloadType() failed to register send" 25614392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org "payload type"); 25624392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org return -1; 25634392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org } 2564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _sendTelephoneEventPayloadType = type; 2566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendTelephoneEventPayloadType(unsigned char& type) 2571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com type = _sendTelephoneEventPayloadType; 2573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateRxVadDetection(AudioFrame& audioFrame) 2578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 2580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::UpdateRxVadDetection()"); 2581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int vadDecision = 1; 2583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 258463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0; 2585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr) 2587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com OnRxVadDetected(vadDecision); 2589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _oldVadDecision = vadDecision; 2590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 2593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::UpdateRxVadDetection() => vadDecision=%d", 2594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com vadDecision); 2595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterRxVadObserver(VoERxVadCallback &observer) 2600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterRxVadObserver()"); 26039a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 2604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_rxVadObserverPtr) 2606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceError, 2609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "RegisterRxVadObserver() observer already enabled"); 2610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _rxVadObserverPtr = &observer; 2613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _RxVadDetection = true; 2614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterRxVadObserver() 2619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterRxVadObserver()"); 26229a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 2623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_rxVadObserverPtr) 2625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceWarning, 2628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "DeRegisterRxVadObserver() observer already disabled"); 2629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _rxVadObserverPtr = NULL; 2632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _RxVadDetection = false; 2633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::VoiceActivityIndicator(int &activity) 2638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com activity = _sendFrameType; 2640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_AGC 2644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 26469213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxAgcStatus(bool enable, AgcModes mode) 2647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetRxAgcStatus(enable=%d, mode=%d)", 2650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (int)enable, (int)mode); 2651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 26526c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org GainControl::Mode agcMode = kDefaultRxAgcMode; 2653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (mode) 2654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kAgcDefault: 2656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kAgcUnchanged: 2658f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org agcMode = rx_audioproc_->gain_control()->mode(); 2659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kAgcFixedDigital: 2661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com agcMode = GainControl::kFixedDigital; 2662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kAgcAdaptiveDigital: 2664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com agcMode =GainControl::kAdaptiveDigital; 2665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com default: 2667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcStatus() invalid Agc mode"); 2670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2673f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->gain_control()->set_mode(agcMode) != 0) 2674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcStatus() failed to set Agc mode"); 2678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2680f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->gain_control()->Enable(enable) != 0) 2681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcStatus() failed to set Agc state"); 2685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _rxAgcIsEnabled = enable; 2689944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled); 2690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcStatus(bool& enabled, AgcModes& mode) 2696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2697f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org bool enable = rx_audioproc_->gain_control()->is_enabled(); 2698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com GainControl::Mode agcMode = 2699f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->gain_control()->mode(); 2700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com enabled = enable; 2702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (agcMode) 2704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case GainControl::kFixedDigital: 2706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kAgcFixedDigital; 2707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case GainControl::kAdaptiveDigital: 2709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kAgcAdaptiveDigital; 2710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com default: 2712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetRxAgcStatus() invalid Agc mode"); 2715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 27229213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxAgcConfig(AgcConfig config) 2723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetRxAgcConfig()"); 2726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2727f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->gain_control()->set_target_level_dbfs( 2728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.targetLeveldBOv) != 0) 2729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcConfig() failed to set target peak |level|" 2733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "(or envelope) of the Agc"); 2734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2736f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->gain_control()->set_compression_gain_db( 2737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.digitalCompressionGaindB) != 0) 2738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcConfig() failed to set the range in |gain| the" 2742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " digital compression stage may apply"); 2743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2745f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->gain_control()->enable_limiter( 2746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.limiterEnable) != 0) 2747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 2750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRxAgcConfig() failed to set hard limiter to the signal"); 2751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcConfig(AgcConfig& config) 2759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.targetLeveldBOv = 2761f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->gain_control()->target_level_dbfs(); 2762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.digitalCompressionGaindB = 2763f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->gain_control()->compression_gain_db(); 2764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com config.limiterEnable = 2765f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->gain_control()->is_limiter_enabled(); 2766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC 2771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_NR 2773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 27759213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxNsStatus(bool enable, NsModes mode) 2776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetRxNsStatus(enable=%d, mode=%d)", 2779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (int)enable, (int)mode); 2780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 27816c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org NoiseSuppression::Level nsLevel = kDefaultNsMode; 2782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (mode) 2783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsDefault: 2786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsUnchanged: 2788f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org nsLevel = rx_audioproc_->noise_suppression()->level(); 2789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsConference: 2791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nsLevel = NoiseSuppression::kHigh; 2792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsLowSuppression: 2794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nsLevel = NoiseSuppression::kLow; 2795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsModerateSuppression: 2797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nsLevel = NoiseSuppression::kModerate; 2798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsHighSuppression: 2800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nsLevel = NoiseSuppression::kHigh; 2801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case kNsVeryHighSuppression: 2803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nsLevel = NoiseSuppression::kVeryHigh; 2804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2807f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->noise_suppression()->set_level(nsLevel) 2808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com != 0) 2809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 28126c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org "SetRxNsStatus() failed to set NS level"); 2813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2815f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org if (rx_audioproc_->noise_suppression()->Enable(enable) != 0) 2816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_APM_ERROR, kTraceError, 28196c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org "SetRxNsStatus() failed to set NS state"); 2820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _rxNsIsEnabled = enable; 2824944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled); 2825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxNsStatus(bool& enabled, NsModes& mode) 2831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com bool enable = 2833f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->noise_suppression()->is_enabled(); 2834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com NoiseSuppression::Level ncLevel = 2835f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org rx_audioproc_->noise_suppression()->level(); 2836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com enabled = enable; 2838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com switch (ncLevel) 2840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case NoiseSuppression::kLow: 2842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kNsLowSuppression; 2843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case NoiseSuppression::kModerate: 2845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kNsModerateSuppression; 2846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case NoiseSuppression::kHigh: 2848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kNsHighSuppression; 2849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com case NoiseSuppression::kVeryHigh: 2851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mode = kNsVeryHighSuppression; 2852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com break; 2853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_NR 2859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetLocalSSRC(unsigned int ssrc) 2862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetLocalSSRC()"); 2865944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().sending) 2866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_ALREADY_SENDING, kTraceError, 2869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetLocalSSRC() already sending"); 2870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2872ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org _rtpRtcpModule->SetSSRC(ssrc); 2873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetLocalSSRC(unsigned int& ssrc) 2878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 28792853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org ssrc = _rtpRtcpModule->SSRC(); 2880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteSSRC(unsigned int& ssrc) 2885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2886822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org ssrc = rtp_receiver_->SSRC(); 2887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2890ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) { 2891f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org _includeAudioLevelIndication = enable; 2892ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id); 2893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2894f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org 289593fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.orgint Channel::SetReceiveAudioLevelIndicationStatus(bool enable, 289693fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org unsigned char id) { 289793fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org rtp_header_parser_->DeregisterRtpHeaderExtension( 289893fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org kRtpExtensionAudioLevel); 289993fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension( 290093fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org kRtpExtensionAudioLevel, id)) { 290193fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org return -1; 290293fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org } 290393fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org return 0; 290493fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org} 290593fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org 2906ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id) { 2907ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org return SetSendRtpHeaderExtension(enable, kRtpExtensionAbsoluteSendTime, id); 2908ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org} 2909ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org 2910ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) { 2911ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org rtp_header_parser_->DeregisterRtpHeaderExtension( 2912ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org kRtpExtensionAbsoluteSendTime); 2913b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension( 2914b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org kRtpExtensionAbsoluteSendTime, id)) { 2915b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org return -1; 2916ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org } 2917ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org return 0; 2918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2920b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmervoid Channel::EnableSendTransportSequenceNumber(int id) { 2921b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer int ret = 2922b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id); 2923b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK_EQ(0, ret); 2924b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer} 2925b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 2926b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmervoid Channel::SetCongestionControlObjects( 2927b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RtpPacketSender* rtp_packet_sender, 2928b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer TransportFeedbackObserver* transport_feedback_observer, 2929b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer PacketRouter* packet_router) { 2930b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer RTC_DCHECK(packet_router != nullptr || packet_router_ != nullptr); 29313842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer if (transport_feedback_observer) { 29323842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer RTC_DCHECK(feedback_observer_proxy_.get()); 29333842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer feedback_observer_proxy_->SetTransportFeedbackObserver( 29343842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer transport_feedback_observer); 29353842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer } 29363842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer if (rtp_packet_sender) { 29373842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer RTC_DCHECK(rtp_packet_sender_proxy_.get()); 29383842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender); 29393842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer } 29403842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer if (seq_num_allocator_proxy_.get()) { 29413842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router); 29423842c5c7f73639527e653f41c65334245d2317a1Stefan Holmer } 2943b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _rtpRtcpModule->SetStorePacketsStatus(rtp_packet_sender != nullptr, 600); 2944b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (packet_router != nullptr) { 2945b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer packet_router->AddRtpModule(_rtpRtcpModule.get()); 2946b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } else { 2947b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer packet_router_->RemoveRtpModule(_rtpRtcpModule.get()); 2948b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer } 2949b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer packet_router_ = packet_router; 2950b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer} 2951b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer 2952d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid Channel::SetRTCPStatus(bool enable) { 2953d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2954d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org "Channel::SetRTCPStatus()"); 2955da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff); 2956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTCPStatus(bool& enabled) 2960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2961da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos RtcpMode method = _rtpRtcpModule->RTCP(); 2962da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos enabled = (method != RtcpMode::kOff); 2963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRTCP_CNAME(const char cName[256]) 2968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetRTCP_CNAME()"); 29712853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SetCNAME(cName) != 0) 2972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 2975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetRTCP_CNAME() failed to set RTCP CNAME"); 2976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 2979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 2980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 2982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCP_CNAME(char cName[256]) 2983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 2984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (cName == NULL) 2985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 2988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetRemoteRTCP_CNAME() invalid CNAME input buffer"); 2989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 2991813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org char cname[RTCP_CNAME_SIZE]; 2992822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org const uint32_t remoteSSRC = rtp_receiver_->SSRC(); 29932853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) 2994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 2995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 2996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_CANNOT_RETRIEVE_CNAME, kTraceError, 2997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME"); 2998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 2999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com strcpy(cName, cname); 3001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCPData( 3006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& NTPHigh, 3007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& NTPLow, 3008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& timestamp, 3009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& playoutTimestamp, 3010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int* jitter, 3011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned short* fractionLost) 3012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Information from sender info in received Sender Reports 3014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com RTCPSenderInfo senderInfo; 30162853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0) 3017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3020fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org "GetRemoteRTCPData() failed to retrieve sender info for remote " 3021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "side"); 3022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // We only utilize 12 out of 20 bytes in the sender info (ignores packet 3026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // and octet count) 3027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com NTPHigh = senderInfo.NTPseconds; 3028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com NTPLow = senderInfo.NTPfraction; 3029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com timestamp = senderInfo.RTPtimeStamp; 3030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Locally derived information 3032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // This value is updated on each incoming RTCP packet (0 when no packet 3034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // has been received) 30351de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org playoutTimestamp = playout_timestamp_rtcp_; 3036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (NULL != jitter || NULL != fractionLost) 3038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3039ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // Get all RTCP receiver report blocks that have been received on this 3040ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // channel. If we receive RTP packets from a remote source we know the 3041ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // remote SSRC and use the report block from him. 3042ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // Otherwise use the first report block. 3043ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org std::vector<RTCPReportBlock> remote_stats; 30442853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 || 3045ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org remote_stats.empty()) { 3046ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3047ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org VoEId(_instanceId, _channelId), 3048ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org "GetRemoteRTCPData() failed to measure statistics due" 3049ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org " to lack of received RTP and/or RTCP packets"); 3050ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org return -1; 3051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3052ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org 3053822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org uint32_t remoteSSRC = rtp_receiver_->SSRC(); 3054ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin(); 3055ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org for (; it != remote_stats.end(); ++it) { 3056ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org if (it->remoteSSRC == remoteSSRC) 3057ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org break; 3058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3059ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org 3060ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org if (it == remote_stats.end()) { 3061ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // If we have not received any RTCP packets from this SSRC it probably 3062ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // means that we have not received any RTP packets. 3063ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org // Use the first received report block instead. 3064ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org it = remote_stats.begin(); 3065ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org remoteSSRC = it->remoteSSRC; 3066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3067ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org 306879af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org if (jitter) { 306979af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org *jitter = it->jitter; 307079af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org } 3071ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org 307279af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org if (fractionLost) { 307379af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org *fractionLost = it->fractionLost; 307479af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org } 3075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 30809213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SendApplicationDefinedRTCPPacket(unsigned char subType, 3081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int name, 3082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com const char* data, 3083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned short dataLengthInBytes) 3084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SendApplicationDefinedRTCPPacket()"); 3087944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (!channel_state_.Get().sending) 3088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_NOT_SENDING, kTraceError, 3091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendApplicationDefinedRTCPPacket() not sending"); 3092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (NULL == data) 3095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 3098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendApplicationDefinedRTCPPacket() invalid data value"); 3099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (dataLengthInBytes % 4 != 0) 3102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 3105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendApplicationDefinedRTCPPacket() invalid length value"); 3106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3108da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos RtcpMode status = _rtpRtcpModule->RTCP(); 3109da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos if (status == RtcpMode::kOff) { 3110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTCP_ERROR, kTraceError, 3112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendApplicationDefinedRTCPPacket() RTCP is disabled"); 3113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Create and schedule the RTCP APP packet for transmission 31172853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->SetRTCPApplicationSpecificData( 3118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com subType, 3119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com name, 3120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (const unsigned char*) data, 3121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com dataLengthInBytes) != 0) 3122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_SEND_ERROR, kTraceError, 3125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SendApplicationDefinedRTCPPacket() failed to send RTCP packet"); 3126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics( 3133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& averageJitterMs, 3134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& maxJitterMs, 3135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com unsigned int& discardedPackets) 3136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The jitter statistics is updated for each received RTP packet and is 3138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // based on received packets. 3139da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos if (_rtpRtcpModule->RTCP() == RtcpMode::kOff) { 314054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // If RTCP is off, there is no timed thread in the RTCP module regularly 314154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // generating new stats, trigger the update manually here instead. 314254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org StreamStatistician* statistician = 314354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); 314454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org if (statistician) { 314554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // Don't use returned statistics, use data from proxy instead so that 314654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // max jitter can be fetched atomically. 314754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org RtcpStatistics s; 314854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org statistician->GetStatistics(&s, true); 314954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org } 3150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 315254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org ChannelStatistics stats = statistics_proxy_->GetStats(); 3153eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org const int32_t playoutFrequency = audio_coding_->PlayoutFrequency(); 315454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org if (playoutFrequency > 0) { 315554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org // Scale RTP statistics given the current playout frequency 315654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org maxJitterMs = stats.max_jitter / (playoutFrequency / 1000); 315754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000); 3158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com discardedPackets = _numberOfDiscardedPackets; 3161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 31658a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.orgint Channel::GetRemoteRTCPReportBlocks( 31668a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org std::vector<ReportBlock>* report_blocks) { 31678a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org if (report_blocks == NULL) { 31688a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError, 31698a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org "GetRemoteRTCPReportBlock()s invalid report_blocks."); 31708a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org return -1; 31718a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org } 31728a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org 31738a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org // Get the report blocks from the latest received RTCP Sender or Receiver 31748a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org // Report. Each element in the vector contains the sender's SSRC and a 31758a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org // report block according to RFC 3550. 31768a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org std::vector<RTCPReportBlock> rtcp_report_blocks; 31778a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) { 31788a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org return -1; 31798a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org } 31808a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org 31818a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org if (rtcp_report_blocks.empty()) 31828a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org return 0; 31838a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org 31848a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin(); 31858a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org for (; it != rtcp_report_blocks.end(); ++it) { 31868a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org ReportBlock report_block; 31878a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.sender_SSRC = it->remoteSSRC; 31888a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.source_SSRC = it->sourceSSRC; 31898a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.fraction_lost = it->fractionLost; 31908a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.cumulative_num_packets_lost = it->cumulativeLost; 31918a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.extended_highest_sequence_number = it->extendedHighSeqNum; 31928a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.interarrival_jitter = it->jitter; 31938a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.last_SR_timestamp = it->lastSR; 31948a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_block.delay_since_last_SR = it->delaySinceLastSR; 31958a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org report_blocks->push_back(report_block); 31968a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org } 31978a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org return 0; 31988a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org} 31998a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org 3200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics(CallStatistics& stats) 3202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3203cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org // --- RtcpStatistics 3204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The jitter statistics is updated for each received RTP packet and is 3206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // based on received packets. 320754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org RtcpStatistics statistics; 3208286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org StreamStatistician* statistician = 3209286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); 3210da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos if (!statistician || 3211da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos !statistician->GetStatistics( 3212da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos &statistics, _rtpRtcpModule->RTCP() == RtcpMode::kOff)) { 3213822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org _engineStatisticsPtr->SetLastError( 3214822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning, 3215822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org "GetRTPStatistics() failed to read RTP statistics from the " 3216822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org "RTP/RTCP module"); 3217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3219822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org stats.fractionLost = statistics.fraction_lost; 3220822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org stats.cumulativeLost = statistics.cumulative_lost; 3221822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org stats.extendedMax = statistics.extended_max_sequence_number; 3222822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org stats.jitterSamples = statistics.jitter; 3223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3224cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org // --- RTT 32252013aeced2b7821a407f302802c4a16fd02728b1Minyue stats.rttMs = GetRTT(true); 3226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3227cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org // --- Data counters 3228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 32294591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t bytesSent(0); 32306141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint32_t packetsSent(0); 32314591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t bytesReceived(0); 32326141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint32_t packetsReceived(0); 3233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3234286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org if (statistician) { 3235286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org statistician->GetDataCounters(&bytesReceived, &packetsReceived); 3236286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 3237822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 32382853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org if (_rtpRtcpModule->DataCountersRTP(&bytesSent, 3239822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org &packetsSent) != 0) 3240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "GetRTPStatistics() failed to retrieve RTP datacounters =>" 3244fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org " output will not be complete"); 3245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stats.bytesSent = bytesSent; 3248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stats.packetsSent = packetsSent; 3249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stats.bytesReceived = bytesReceived; 3250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stats.packetsReceived = packetsReceived; 3251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3252cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org // --- Timestamps 3253cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org { 3254cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org CriticalSectionScoped lock(ts_stats_lock_.get()); 3255cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_; 3256cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org } 3257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3260c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint Channel::SetREDStatus(bool enable, int redPayloadtype) { 326142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3262c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org "Channel::SetREDStatus()"); 326342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 32648c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org if (enable) { 32658c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org if (redPayloadtype < 0 || redPayloadtype > 127) { 32668c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org _engineStatisticsPtr->SetLastError( 32678c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org VE_PLTYPE_ERROR, kTraceError, 3268c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org "SetREDStatus() invalid RED payload type"); 32698c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org return -1; 32708c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org } 32718c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org 32728c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org if (SetRedPayloadType(redPayloadtype) < 0) { 32738c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org _engineStatisticsPtr->SetLastError( 32748c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org VE_CODEC_ERROR, kTraceError, 32758c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org "SetSecondarySendCodec() Failed to register RED ACM"); 32768c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org return -1; 32778c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org } 327842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 32792cf22a6abce2d38e673505a4cfd5624a3710b5cdperkj@webrtc.org 3280aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org if (audio_coding_->SetREDStatus(enable) != 0) { 328142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org _engineStatisticsPtr->SetLastError( 328242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 3283aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org "SetREDStatus() failed to set RED state in the ACM"); 328442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return -1; 328542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 328642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return 0; 3287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3290c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgChannel::GetREDStatus(bool& enabled, int& redPayloadtype) 3291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3292aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org enabled = audio_coding_->REDStatus(); 3293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (enabled) 3294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 32955c1def8892390a336d1eecd9b61adacece858898danilchap int8_t payloadType = 0; 32965c1def8892390a336d1eecd9b61adacece858898danilchap if (_rtpRtcpModule->SendREDPayloadType(&payloadType) != 0) { 3297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3299c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org "GetREDStatus() failed to retrieve RED PT from RTP/RTCP " 3300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "module"); 3301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3303df9a41d2701d321dbc987201ec7cffe2a16bd2c4pkasting@chromium.org redPayloadtype = payloadType; 3304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3309c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint Channel::SetCodecFECStatus(bool enable) { 3310c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3311c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org "Channel::SetCodecFECStatus()"); 3312c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 3313c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org if (audio_coding_->SetCodecFEC(enable) != 0) { 3314c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org _engineStatisticsPtr->SetLastError( 3315c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 3316c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org "SetCodecFECStatus() failed to set FEC state"); 3317c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org return -1; 3318c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org } 3319c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org return 0; 3320c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org} 3321c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 3322c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgbool Channel::GetCodecFECStatus() { 3323c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org bool enabled = audio_coding_->CodecFEC(); 3324c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org return enabled; 3325c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org} 3326c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 3327db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.orgvoid Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) { 3328db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org // None of these functions can fail. 3329b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer // If pacing is enabled we always store packets. 3330b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer if (!pacing_enabled_) 3331b86d4e4a8dec1eb1b801244a2a97cda66f561d8eStefan Holmer _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets); 33327bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets); 33337bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff); 3334d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org if (enable) 3335eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org audio_coding_->EnableNack(maxNumberOfPackets); 3336d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org else 3337eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org audio_coding_->DisableNack(); 3338db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org} 3339db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org 3340d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org// Called when we are missing one or more packets. 3341d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.orgint Channel::ResendPackets(const uint16_t* sequence_numbers, int length) { 3342db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org return _rtpRtcpModule->SendNACK(sequence_numbers, length); 3343db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org} 3344db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org 33456141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t 3346755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.orgChannel::Demultiplex(const AudioFrame& audioFrame) 3347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3349755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org "Channel::Demultiplex()"); 3350ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org _audioFrame.CopyFrom(audioFrame); 335163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.id_ = _channelId; 3352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 33552f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.orgvoid Channel::Demultiplex(const int16_t* audio_data, 33568fff1f065ea9d25970c3839294acdd606a5ddf22xians@webrtc.org int sample_rate, 3357dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting size_t number_of_frames, 33586955870806624479723addfae6dcf5d13968796cPeter Kasting size_t number_of_channels) { 33592f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org CodecInst codec; 33602f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org GetSendCodec(codec); 33612f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org 3362cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs // Never upsample or upmix the capture signal here. This should be done at the 3363cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs // end of the send chain. 3364cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs _audioFrame.sample_rate_hz_ = std::min(codec.plfreq, sample_rate); 3365cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs _audioFrame.num_channels_ = std::min(number_of_channels, codec.channels); 3366cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs RemixAndResample(audio_data, number_of_frames, number_of_channels, 3367cdfe20bfc1146030aa59eb37635fd2fbcecd6cdbAlejandro Luebs sample_rate, &input_resampler_, &_audioFrame); 33682f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org} 33692f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org 33706141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t 33710b0665acc1464d68e878f203bbc8772a0e32402dxians@google.comChannel::PrepareEncodeAndSend(int mixingFrequency) 3372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PrepareEncodeAndSend()"); 3375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 337663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (_audioFrame.samples_per_channel_ == 0) 3377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::PrepareEncodeAndSend() invalid audio frame"); 3380eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org return 0xFFFFFFFF; 3381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3383944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().input_file_playing) 3384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com MixOrReplaceAudioWithFile(mixingFrequency); 3386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 338821299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org bool is_muted = Mute(); // Cache locally as Mute() takes a lock. 338921299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org if (is_muted) { 339021299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org AudioFrameOperations::Mute(_audioFrame); 3391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3393944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().input_external_media) 3394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 33959a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 339663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org const bool isStereo = (_audioFrame.num_channels_ == 2); 3397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputExternalMediaCallbackPtr) 3398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputExternalMediaCallbackPtr->Process( 3400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _channelId, 3401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kRecordingPerChannel, 34026141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org (int16_t*)_audioFrame.data_, 340363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.samples_per_channel_, 340463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.sample_rate_hz_, 3405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com isStereo); 3406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com InsertInbandDtmfTone(); 3410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 341160730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org if (_includeAudioLevelIndication) { 3412dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting size_t length = 3413dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting _audioFrame.samples_per_channel_ * _audioFrame.num_channels_; 341421299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org if (is_muted) { 341521299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org rms_level_.ProcessMuted(length); 341621299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org } else { 341721299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org rms_level_.Process(_audioFrame.data_, length); 341821299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org } 3419755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org } 3420755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org 3421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 34246141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t 3425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EncodeAndSend() 3426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::EncodeAndSend()"); 3429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 343063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org assert(_audioFrame.num_channels_ <= 2); 343163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (_audioFrame.samples_per_channel_ == 0) 3432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::EncodeAndSend() invalid audio frame"); 3435eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org return 0xFFFFFFFF; 3436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 343863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.id_ = _channelId; 3439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz. 3441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // The ACM resamples internally. 344363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org _audioFrame.timestamp_ = _timeStamp; 3444f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org // This call will trigger AudioPacketizationCallback::SendData if encoding 3445f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org // is done and payload is ready for packetization and transmission. 3446f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org // Otherwise, it will return without invoking the callback. 3447f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) 3448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 3450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::EncodeAndSend() ACM encoding failed"); 3451eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org return 0xFFFFFFFF; 3452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3454b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_); 3455f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org return 0; 3456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 34582013aeced2b7821a407f302802c4a16fd02728b1Minyuevoid Channel::DisassociateSendChannel(int channel_id) { 34592013aeced2b7821a407f302802c4a16fd02728b1Minyue CriticalSectionScoped lock(assoc_send_channel_lock_.get()); 34602013aeced2b7821a407f302802c4a16fd02728b1Minyue Channel* channel = associate_send_channel_.channel(); 34612013aeced2b7821a407f302802c4a16fd02728b1Minyue if (channel && channel->ChannelId() == channel_id) { 34622013aeced2b7821a407f302802c4a16fd02728b1Minyue // If this channel is associated with a send channel of the specified 34632013aeced2b7821a407f302802c4a16fd02728b1Minyue // Channel ID, disassociate with it. 34642013aeced2b7821a407f302802c4a16fd02728b1Minyue ChannelOwner ref(NULL); 34652013aeced2b7821a407f302802c4a16fd02728b1Minyue associate_send_channel_ = ref; 34662013aeced2b7821a407f302802c4a16fd02728b1Minyue } 34672013aeced2b7821a407f302802c4a16fd02728b1Minyue} 34682013aeced2b7821a407f302802c4a16fd02728b1Minyue 3469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::RegisterExternalMediaProcessing( 3470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ProcessingTypes type, 3471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEMediaProcess& processObject) 3472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterExternalMediaProcessing()"); 3475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 34769a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 3477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (kPlaybackPerChannel == type) 3479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputExternalMediaCallbackPtr) 3481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceError, 3484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterExternalMediaProcessing() " 3485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "output external media already enabled"); 3486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputExternalMediaCallbackPtr = &processObject; 3489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputExternalMedia = true; 3490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if (kRecordingPerChannel == type) 3492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputExternalMediaCallbackPtr) 3494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceError, 3497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterExternalMediaProcessing() " 3498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "output external media already enabled"); 3499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputExternalMediaCallbackPtr = &processObject; 3502944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputExternalMedia(true); 3503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type) 3508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterExternalMediaProcessing()"); 3511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 35129a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_callbackCritSect); 3513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (kPlaybackPerChannel == type) 3515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_outputExternalMediaCallbackPtr) 3517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceWarning, 3520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterExternalMediaProcessing() " 3521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "output external media already disabled"); 3522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputExternalMedia = false; 3525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputExternalMediaCallbackPtr = NULL; 3526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else if (kRecordingPerChannel == type) 3528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (!_inputExternalMediaCallbackPtr) 3530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_OPERATION, kTraceWarning, 3533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::DeRegisterExternalMediaProcessing() " 3534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "input external media already disabled"); 3535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3537944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org channel_state_.SetInputExternalMedia(false); 3538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inputExternalMediaCallbackPtr = NULL; 3539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 35441b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint Channel::SetExternalMixing(bool enabled) { 35451b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 35461b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com "Channel::SetExternalMixing(enabled=%d)", enabled); 35471b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 3548944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org if (channel_state_.Get().playing) 35491b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com { 35501b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com _engineStatisticsPtr->SetLastError( 35511b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com VE_INVALID_OPERATION, kTraceError, 35521b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com "Channel::SetExternalMixing() " 35531b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com "external mixing cannot be changed while playing."); 35541b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com return -1; 35551b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com } 35561b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 35571b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com _externalMixing = enabled; 35581b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 35591b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com return 0; 35601b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com} 35611b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com 3562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetNetworkStatistics(NetworkStatistics& stats) 3564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3565c0bd7be0df67735d63f5cdd302a3b85f88239874minyue@webrtc.org return audio_coding_->GetNetworkStatistics(&stats); 3566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 356824301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.orgvoid Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const { 356924301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org audio_coding_->GetDecodingCallStatistics(stats); 357024301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org} 357124301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org 35721de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgbool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms, 35731de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org int* playout_buffer_delay_ms) const { 3574743758816853df2040a21c5652b0d0e238b1512fdeadbeef CriticalSectionScoped cs(video_sync_lock_.get()); 35751de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org if (_average_jitter_buffer_delay_us == 0) { 35761de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org return false; 35771de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org } 35781de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org *jitter_buffer_delay_ms = (_average_jitter_buffer_delay_us + 500) / 1000 + 35791de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org _recPacketDelayMs; 35801de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org *playout_buffer_delay_ms = playout_delay_ms_; 35811de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org return true; 3582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3584358057b945725390bcecc330513160aa823f651esolenberguint32_t Channel::GetDelayEstimate() const { 3585358057b945725390bcecc330513160aa823f651esolenberg int jitter_buffer_delay_ms = 0; 3586358057b945725390bcecc330513160aa823f651esolenberg int playout_buffer_delay_ms = 0; 3587358057b945725390bcecc330513160aa823f651esolenberg GetDelayEstimate(&jitter_buffer_delay_ms, &playout_buffer_delay_ms); 3588358057b945725390bcecc330513160aa823f651esolenberg return jitter_buffer_delay_ms + playout_buffer_delay_ms; 3589358057b945725390bcecc330513160aa823f651esolenberg} 3590358057b945725390bcecc330513160aa823f651esolenberg 3591743758816853df2040a21c5652b0d0e238b1512fdeadbeefint Channel::LeastRequiredDelayMs() const { 3592743758816853df2040a21c5652b0d0e238b1512fdeadbeef return audio_coding_->LeastRequiredDelayMs(); 3593743758816853df2040a21c5652b0d0e238b1512fdeadbeef} 3594743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMinimumPlayoutDelay(int delayMs) 3597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetMinimumPlayoutDelay()"); 3600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) || 3601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) 3602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_INVALID_ARGUMENT, kTraceError, 3605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetMinimumPlayoutDelay() invalid min delay"); 3606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3608eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) 3609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _engineStatisticsPtr->SetLastError( 3611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 3612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "SetMinimumPlayoutDelay() failed to set min playout delay"); 3613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 36181de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgint Channel::GetPlayoutTimestamp(unsigned int& timestamp) { 3619743758816853df2040a21c5652b0d0e238b1512fdeadbeef uint32_t playout_timestamp_rtp = 0; 3620743758816853df2040a21c5652b0d0e238b1512fdeadbeef { 3621743758816853df2040a21c5652b0d0e238b1512fdeadbeef CriticalSectionScoped cs(video_sync_lock_.get()); 3622743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_timestamp_rtp = playout_timestamp_rtp_; 3623743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3624743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (playout_timestamp_rtp == 0) { 36251de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org _engineStatisticsPtr->SetLastError( 36261de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org VE_CANNOT_RETRIEVE_VALUE, kTraceError, 36271de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org "GetPlayoutTimestamp() failed to retrieve timestamp"); 36281de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org return -1; 36291de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org } 3630743758816853df2040a21c5652b0d0e238b1512fdeadbeef timestamp = playout_timestamp_rtp; 36311de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org return 0; 3632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3634d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint Channel::SetInitTimestamp(unsigned int timestamp) { 3635d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::SetInitTimestamp()"); 3637d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org if (channel_state_.Get().sending) { 3638d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org _engineStatisticsPtr->SetLastError(VE_SENDING, kTraceError, 3639d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org "SetInitTimestamp() already sending"); 3640d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org return -1; 3641d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org } 3642d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org _rtpRtcpModule->SetStartTimestamp(timestamp); 3643d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org return 0; 3644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3646d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint Channel::SetInitSequenceNumber(short sequenceNumber) { 3647d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3648d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org "Channel::SetInitSequenceNumber()"); 3649d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org if (channel_state_.Get().sending) { 3650d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org _engineStatisticsPtr->SetLastError( 3651d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org VE_SENDING, kTraceError, "SetInitSequenceNumber() already sending"); 3652d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org return -1; 3653d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org } 3654d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org _rtpRtcpModule->SetSequenceNumber(sequenceNumber); 3655d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org return 0; 3656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3659822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgChannel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const 3660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3661822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org *rtpRtcpModule = _rtpRtcpModule.get(); 3662822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org *rtp_receiver = rtp_receiver_.get(); 3663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3666e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use 3667e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// a shared helper. 36686141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 36699213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::MixOrReplaceAudioWithFile(int mixingFrequency) 3670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 367100b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]); 3672dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting size_t fileSamples(0); 3673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 36759a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 3676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inputFilePlayerPtr == NULL) 3678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::MixOrReplaceAudioWithFile() fileplayer" 3682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com " doesnt exist"); 3683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3686d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(), 3687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fileSamples, 3688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mixingFrequency) == -1) 3689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::MixOrReplaceAudioWithFile() file mixing " 3693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "failed"); 3694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (fileSamples == 0) 3697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::MixOrReplaceAudioWithFile() file is ended"); 3701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 370563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org assert(_audioFrame.samples_per_channel_ == fileSamples); 3706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_mixFileWithMicrophone) 3708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3709d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // Currently file stream is always mono. 3710d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // TODO(xians): Change the code when FilePlayer supports real stereo. 371140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org MixWithSat(_audioFrame.data_, 371240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org _audioFrame.num_channels_, 371340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org fileBuffer.get(), 371440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org 1, 371540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org fileSamples); 3716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 3718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3719d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // Replace ACM audio with file. 3720d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // Currently file stream is always mono. 3721d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // TODO(xians): Change the code when FilePlayer supports real stereo. 3722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _audioFrame.UpdateFrame(_channelId, 3723eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org 0xFFFFFFFF, 3724d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org fileBuffer.get(), 3725e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org fileSamples, 3726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mixingFrequency, 3727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com AudioFrame::kNormalSpeech, 3728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com AudioFrame::kVadUnknown, 3729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1); 3730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 37356141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t 3736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::MixAudioWithFile(AudioFrame& audioFrame, 37379213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org int mixingFrequency) 3738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 37392a8df7c375c73a3f477ee5cd9d85336a98f57ee2minyue@webrtc.org assert(mixingFrequency <= 48000); 3740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 374100b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org rtc::scoped_ptr<int16_t[]> fileBuffer(new int16_t[960]); 3742dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting size_t fileSamples(0); 3743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 37459a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org CriticalSectionScoped cs(&_fileCritSect); 3746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_outputFilePlayerPtr == NULL) 3748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::MixAudioWithFile() file mixing failed"); 3752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // We should get the frequency we ask for. 3756d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(), 3757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com fileSamples, 3758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com mixingFrequency) == -1) 3759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::MixAudioWithFile() file mixing failed"); 3763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 376763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (audioFrame.samples_per_channel_ == fileSamples) 3768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3769d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // Currently file stream is always mono. 3770d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org // TODO(xians): Change the code when FilePlayer supports real stereo. 377140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org MixWithSat(audioFrame.data_, 377240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org audioFrame.num_channels_, 377340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org fileBuffer.get(), 377440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org 1, 377540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org fileSamples); 3776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 3778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3780dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting "Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS ") != " 3781dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting "fileSamples(%" PRIuS ")", 378263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org audioFrame.samples_per_channel_, fileSamples); 3783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint 3790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::InsertInbandDtmfTone() 3791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3792af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org // Check if we should start a new tone. 3793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inbandDtmfQueue.PendingDtmf() && 3794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com !_inbandDtmfGenerator.IsAddingTone() && 3795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.DelaySinceLastTone() > 3796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kMinTelephoneEventSeparationMs) 3797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 37986141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int8_t eventCode(0); 37996141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint16_t lengthMs(0); 38006141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint8_t attenuationDb(0); 3801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb); 3803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb); 3804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_playInbandDtmfEvent) 3805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Add tone to output mixer using a reduced length to minimize 3807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // risk of echo. 3808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80, 3809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com attenuationDb); 3810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inbandDtmfGenerator.IsAddingTone()) 3814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 38156141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint16_t frequency(0); 3816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.GetSampleRate(frequency); 3817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 381863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org if (frequency != _audioFrame.sample_rate_hz_) 3819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Update sample rate of Dtmf tone since the mixing frequency 3821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // has changed. 3822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.SetSampleRate( 38236141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org (uint16_t) (_audioFrame.sample_rate_hz_)); 3824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Reset the tone to be added taking the new sample rate into 3825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // account. 3826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.ResetTone(); 3827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3828ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 38296141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org int16_t toneBuffer[320]; 38306141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org uint16_t toneSamples(0); 3831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Get 10ms tone segment and set time since last tone to zero 3832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1) 3833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::EncodeAndSend() inserting Dtmf failed"); 3837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return -1; 3838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3840af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org // Replace mixed audio with DTMF tone. 3841dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting for (size_t sample = 0; 384263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org sample < _audioFrame.samples_per_channel_; 3843af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org sample++) 3844af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org { 38456955870806624479723addfae6dcf5d13968796cPeter Kasting for (size_t channel = 0; 3846ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org channel < _audioFrame.num_channels_; 3847af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org channel++) 3848af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org { 3849dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting const size_t index = 3850dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting sample * _audioFrame.num_channels_ + channel; 3851ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org _audioFrame.data_[index] = toneBuffer[sample]; 3852af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org } 3853af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org } 3854ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org 385563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org assert(_audioFrame.samples_per_channel_ == toneSamples); 3856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 3857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Add 10ms to "delay-since-last-tone" counter 3859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com _inbandDtmfGenerator.UpdateDelaySinceLastTone(); 3860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return 0; 3862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3864743758816853df2040a21c5652b0d0e238b1512fdeadbeefvoid Channel::UpdatePlayoutTimestamp(bool rtcp) { 3865743758816853df2040a21c5652b0d0e238b1512fdeadbeef uint32_t playout_timestamp = 0; 3866743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3867743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (audio_coding_->PlayoutTimestamp(&playout_timestamp) == -1) { 3868743758816853df2040a21c5652b0d0e238b1512fdeadbeef // This can happen if this channel has not been received any RTP packet. In 3869743758816853df2040a21c5652b0d0e238b1512fdeadbeef // this case, NetEq is not capable of computing playout timestamp. 3870743758816853df2040a21c5652b0d0e238b1512fdeadbeef return; 3871743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3872743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3873743758816853df2040a21c5652b0d0e238b1512fdeadbeef uint16_t delay_ms = 0; 3874743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) { 3875743758816853df2040a21c5652b0d0e238b1512fdeadbeef WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3876743758816853df2040a21c5652b0d0e238b1512fdeadbeef "Channel::UpdatePlayoutTimestamp() failed to read playout" 3877743758816853df2040a21c5652b0d0e238b1512fdeadbeef " delay from the ADM"); 3878743758816853df2040a21c5652b0d0e238b1512fdeadbeef _engineStatisticsPtr->SetLastError( 3879743758816853df2040a21c5652b0d0e238b1512fdeadbeef VE_CANNOT_RETRIEVE_VALUE, kTraceError, 3880743758816853df2040a21c5652b0d0e238b1512fdeadbeef "UpdatePlayoutTimestamp() failed to retrieve playout delay"); 3881743758816853df2040a21c5652b0d0e238b1512fdeadbeef return; 3882743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3883743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3884743758816853df2040a21c5652b0d0e238b1512fdeadbeef jitter_buffer_playout_timestamp_ = playout_timestamp; 3885743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3886743758816853df2040a21c5652b0d0e238b1512fdeadbeef // Remove the playout delay. 3887743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_timestamp -= (delay_ms * (GetPlayoutFrequency() / 1000)); 3888743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3889743758816853df2040a21c5652b0d0e238b1512fdeadbeef WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3890743758816853df2040a21c5652b0d0e238b1512fdeadbeef "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu", 3891743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_timestamp); 3892743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3893743758816853df2040a21c5652b0d0e238b1512fdeadbeef { 3894743758816853df2040a21c5652b0d0e238b1512fdeadbeef CriticalSectionScoped cs(video_sync_lock_.get()); 3895743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (rtcp) { 3896743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_timestamp_rtcp_ = playout_timestamp; 3897743758816853df2040a21c5652b0d0e238b1512fdeadbeef } else { 3898743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_timestamp_rtp_ = playout_timestamp; 3899743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3900743758816853df2040a21c5652b0d0e238b1512fdeadbeef playout_delay_ms_ = delay_ms; 3901743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3902743758816853df2040a21c5652b0d0e238b1512fdeadbeef} 3903743758816853df2040a21c5652b0d0e238b1512fdeadbeef 39041de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org// Called for incoming RTP packets after successful RTP header parsing. 39051de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgvoid Channel::UpdatePacketDelay(uint32_t rtp_timestamp, 39061de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org uint16_t sequence_number) { 39071de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 39081de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)", 39091de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org rtp_timestamp, sequence_number); 3910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39111de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org // Get frequency of last received payload 391294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org int rtp_receive_frequency = GetPlayoutFrequency(); 3913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3914167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org // |jitter_buffer_playout_timestamp_| updated in UpdatePlayoutTimestamp for 3915167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org // every incoming packet. 3916167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org uint32_t timestamp_diff_ms = (rtp_timestamp - 3917167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org jitter_buffer_playout_timestamp_) / (rtp_receive_frequency / 1000); 3918d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org if (!IsNewerTimestamp(rtp_timestamp, jitter_buffer_playout_timestamp_) || 3919d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org timestamp_diff_ms > (2 * kVoiceEngineMaxMinPlayoutDelayMs)) { 3920d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org // If |jitter_buffer_playout_timestamp_| is newer than the incoming RTP 3921d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org // timestamp, the resulting difference is negative, but is set to zero. 3922d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org // This can happen when a network glitch causes a packet to arrive late, 3923d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org // and during long comfort noise periods with clock drift. 3924d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org timestamp_diff_ms = 0; 3925d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org } 3926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39271de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org uint16_t packet_delay_ms = (rtp_timestamp - _previousTimestamp) / 39281de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org (rtp_receive_frequency / 1000); 3929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39301de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org _previousTimestamp = rtp_timestamp; 3931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39321de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org if (timestamp_diff_ms == 0) return; 39331de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org 3934743758816853df2040a21c5652b0d0e238b1512fdeadbeef { 3935743758816853df2040a21c5652b0d0e238b1512fdeadbeef CriticalSectionScoped cs(video_sync_lock_.get()); 39361de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org 3937743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (packet_delay_ms >= 10 && packet_delay_ms <= 60) { 3938743758816853df2040a21c5652b0d0e238b1512fdeadbeef _recPacketDelayMs = packet_delay_ms; 3939743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 39401de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org 3941743758816853df2040a21c5652b0d0e238b1512fdeadbeef if (_average_jitter_buffer_delay_us == 0) { 3942743758816853df2040a21c5652b0d0e238b1512fdeadbeef _average_jitter_buffer_delay_us = timestamp_diff_ms * 1000; 3943743758816853df2040a21c5652b0d0e238b1512fdeadbeef return; 3944743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3945743758816853df2040a21c5652b0d0e238b1512fdeadbeef 3946743758816853df2040a21c5652b0d0e238b1512fdeadbeef // Filter average delay value using exponential filter (alpha is 3947743758816853df2040a21c5652b0d0e238b1512fdeadbeef // 7/8). We derive 1000 *_average_jitter_buffer_delay_us here (reduces 3948743758816853df2040a21c5652b0d0e238b1512fdeadbeef // risk of rounding error) and compensate for it in GetDelayEstimate() 3949743758816853df2040a21c5652b0d0e238b1512fdeadbeef // later. 3950743758816853df2040a21c5652b0d0e238b1512fdeadbeef _average_jitter_buffer_delay_us = (_average_jitter_buffer_delay_us * 7 + 3951743758816853df2040a21c5652b0d0e238b1512fdeadbeef 1000 * timestamp_diff_ms + 500) / 8; 3952743758816853df2040a21c5652b0d0e238b1512fdeadbeef } 3953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid 3956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterReceiveCodecsToRTPModule() 3957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 3958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterReceiveCodecsToRTPModule()"); 3960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com CodecInst codec; 39626141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs(); 3963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (int idx = 0; idx < nSupportedCodecs; idx++) 3965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com // Open up the RTP/RTCP receiver for all supported codecs 3967eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if ((audio_coding_->Codec(idx, &codec) == -1) || 3968822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (rtp_receiver_->RegisterReceivePayload( 3969822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plname, 3970822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.pltype, 3971822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.plfreq, 3972822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org codec.channels, 3973822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org (codec.rate < 0) ? 0 : codec.rate) == -1)) 3974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3975d5c75b1a0ba1548d3561109e3e5e63757509e9aePeter Boström WEBRTC_TRACE(kTraceWarning, 3976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceVoice, 3977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterReceiveCodecsToRTPModule() unable" 39796955870806624479723addfae6dcf5d13968796cPeter Kasting " to register %s (%d/%d/%" PRIuS "/%d) to RTP/RTCP " 39806955870806624479723addfae6dcf5d13968796cPeter Kasting "receiver", 3981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.plname, codec.pltype, codec.plfreq, 3982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.channels, codec.rate); 3983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 3985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 3986d5c75b1a0ba1548d3561109e3e5e63757509e9aePeter Boström WEBRTC_TRACE(kTraceInfo, 3987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kTraceVoice, 3988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com VoEId(_instanceId, _channelId), 3989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "Channel::RegisterReceiveCodecsToRTPModule() %s " 39906955870806624479723addfae6dcf5d13968796cPeter Kasting "(%d/%d/%" PRIuS "/%d) has been added to the RTP/RTCP " 3991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com "receiver", 3992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.plname, codec.pltype, codec.plfreq, 3993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com codec.channels, codec.rate); 3994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 3997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 39988c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org// Assuming this method is called with valid payload type. 399942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::SetRedPayloadType(int red_payload_type) { 400042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org CodecInst codec; 400142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org bool found_red = false; 400242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 400342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org // Get default RED settings from the ACM database 400442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org const int num_codecs = AudioCodingModule::NumberOfCodecs(); 400542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org for (int idx = 0; idx < num_codecs; idx++) { 4006eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org audio_coding_->Codec(idx, &codec); 400742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org if (!STR_CASE_CMP(codec.plname, "RED")) { 400842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org found_red = true; 400942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org break; 401042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 401142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 401242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 401342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org if (!found_red) { 401442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org _engineStatisticsPtr->SetLastError( 401542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org VE_CODEC_ERROR, kTraceError, 401642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org "SetRedPayloadType() RED is not supported"); 401742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return -1; 401842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 401942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 40209d532fd2752290e85aa804f29ab9aa6c017c9208turaj@webrtc.org codec.pltype = red_payload_type; 4021eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org if (audio_coding_->RegisterSendCodec(codec) < 0) { 402242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org _engineStatisticsPtr->SetLastError( 402342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 402442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org "SetRedPayloadType() RED registration in ACM module failed"); 402542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return -1; 402642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 402742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 402842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) { 402942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org _engineStatisticsPtr->SetLastError( 403042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org VE_RTP_RTCP_MODULE_ERROR, kTraceError, 403142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org "SetRedPayloadType() RED registration in RTP/RTCP module failed"); 403242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return -1; 403342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org } 403442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org return 0; 403542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org} 403642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org 4037ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, 4038ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org unsigned char id) { 4039ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org int error = 0; 4040ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type); 4041ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org if (enable) { 4042ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id); 4043ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org } 4044ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org return error; 4045ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org} 4046c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org 404794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.orgint32_t Channel::GetPlayoutFrequency() { 404894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org int32_t playout_frequency = audio_coding_->PlayoutFrequency(); 404994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org CodecInst current_recive_codec; 405094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org if (audio_coding_->ReceiveCodec(¤t_recive_codec) == 0) { 405194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) { 405294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // Even though the actual sampling rate for G.722 audio is 405394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // 16,000 Hz, the RTP clock rate for the G722 payload format is 405494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // 8,000 Hz because that value was erroneously assigned in 405594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // RFC 1890 and must remain unchanged for backward compatibility. 405694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org playout_frequency = 8000; 405794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) { 405894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // We are resampling Opus internally to 32,000 Hz until all our 405994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // DSP routines can operate at 48,000 Hz, but the RTP clock 406094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // rate for the Opus payload format is standardized to 48,000 Hz, 406194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org // because that is the maximum supported decoding sampling rate. 406294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org playout_frequency = 48000; 406394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org } 406494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org } 406594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org return playout_frequency; 406694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org} 406794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org 40682013aeced2b7821a407f302802c4a16fd02728b1Minyueint64_t Channel::GetRTT(bool allow_associate_channel) const { 4069da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos RtcpMode method = _rtpRtcpModule->RTCP(); 4070da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos if (method == RtcpMode::kOff) { 40712b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org return 0; 40722b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org } 40732b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org std::vector<RTCPReportBlock> report_blocks; 40742b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org _rtpRtcpModule->RemoteRTCPStat(&report_blocks); 40752013aeced2b7821a407f302802c4a16fd02728b1Minyue 40762013aeced2b7821a407f302802c4a16fd02728b1Minyue int64_t rtt = 0; 40772b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org if (report_blocks.empty()) { 40782013aeced2b7821a407f302802c4a16fd02728b1Minyue if (allow_associate_channel) { 40792013aeced2b7821a407f302802c4a16fd02728b1Minyue CriticalSectionScoped lock(assoc_send_channel_lock_.get()); 40802013aeced2b7821a407f302802c4a16fd02728b1Minyue Channel* channel = associate_send_channel_.channel(); 40812013aeced2b7821a407f302802c4a16fd02728b1Minyue // Tries to get RTT from an associated channel. This is important for 40822013aeced2b7821a407f302802c4a16fd02728b1Minyue // receive-only channels. 40832013aeced2b7821a407f302802c4a16fd02728b1Minyue if (channel) { 40842013aeced2b7821a407f302802c4a16fd02728b1Minyue // To prevent infinite recursion and deadlock, calling GetRTT of 40852013aeced2b7821a407f302802c4a16fd02728b1Minyue // associate channel should always use "false" for argument: 40862013aeced2b7821a407f302802c4a16fd02728b1Minyue // |allow_associate_channel|. 40872013aeced2b7821a407f302802c4a16fd02728b1Minyue rtt = channel->GetRTT(false); 40882013aeced2b7821a407f302802c4a16fd02728b1Minyue } 40892013aeced2b7821a407f302802c4a16fd02728b1Minyue } 40902013aeced2b7821a407f302802c4a16fd02728b1Minyue return rtt; 40912b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org } 40922b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org 40932b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org uint32_t remoteSSRC = rtp_receiver_->SSRC(); 40942b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin(); 40952b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org for (; it != report_blocks.end(); ++it) { 40962b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org if (it->remoteSSRC == remoteSSRC) 40972b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org break; 40982b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org } 40992b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org if (it == report_blocks.end()) { 41002b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org // We have not received packets with SSRC matching the report blocks. 41012b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org // To calculate RTT we try with the SSRC of the first report block. 41022b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org // This is very important for send-only channels where we don't know 41032b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org // the SSRC of the other end. 41042b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org remoteSSRC = report_blocks[0].remoteSSRC; 41052b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org } 41062013aeced2b7821a407f302802c4a16fd02728b1Minyue 410716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t avg_rtt = 0; 410816825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t max_rtt= 0; 410916825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t min_rtt = 0; 41102b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) 41112b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org != 0) { 41122b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org return 0; 41132b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org } 411416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org return rtt; 41152b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org} 41162b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org 4117d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org} // namespace voe 4118d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org} // namespace webrtc 4119