channel.cc revision adf89b7e33cc54dab9365dddead687a46a074cf0
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
134591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org#include "webrtc/base/format_macros.h"
1494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org#include "webrtc/base/timeutils.h"
15e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org#include "webrtc/common.h"
166388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/audio_device/include/audio_device.h"
176388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/audio_processing/include/audio_processing.h"
18d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org#include "webrtc/modules/interface/module_common_types.h"
19822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
20822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
21822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
22822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
236388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/utility/interface/audio_frame_operations.h"
246388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/utility/interface/process_thread.h"
256388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/modules/utility/interface/rtp_dump.h"
266388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
276388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
286388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
29b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org#include "webrtc/video_engine/include/vie_network.h"
306388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_base.h"
316388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_external_media.h"
326388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
336388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/output_mixer.h"
346388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/statistics.h"
356388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/transmit_mixer.h"
366388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org#include "webrtc/voice_engine/utility.h"
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#if defined(_WIN32)
39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <Qos.h>
40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4250419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace webrtc {
4350419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace voe {
44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// Extend the default RTCP statistics struct with max_jitter, defined as the
4654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// maximum jitter value seen in an RTCP report block.
4754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgstruct ChannelStatistics : public RtcpStatistics {
4854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  ChannelStatistics() : rtcp(), max_jitter(0) {}
4954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
5054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  RtcpStatistics rtcp;
5154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  uint32_t max_jitter;
5254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org};
5354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
5454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org// Statistics callback, called at each generation of a new RTCP report block.
5554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgclass StatisticsProxy : public RtcpStatisticsCallback {
5654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org public:
5754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  StatisticsProxy(uint32_t ssrc)
5854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org   : stats_lock_(CriticalSectionWrapper::CreateCriticalSection()),
5954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org     ssrc_(ssrc) {}
6054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  virtual ~StatisticsProxy() {}
6154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
6214665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void StatisticsUpdated(const RtcpStatistics& statistics,
6314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org                         uint32_t ssrc) override {
6454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    if (ssrc != ssrc_)
6554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      return;
6654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
6754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    CriticalSectionScoped cs(stats_lock_.get());
6854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    stats_.rtcp = statistics;
6954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    if (statistics.jitter > stats_.max_jitter) {
7054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      stats_.max_jitter = statistics.jitter;
7154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    }
7254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  }
7354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
7414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void CNameChanged(const char* cname, uint32_t ssrc) override {}
75ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org
7654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  void ResetStatistics() {
7754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    CriticalSectionScoped cs(stats_lock_.get());
7854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    stats_ = ChannelStatistics();
7954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  }
8054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
8154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  ChannelStatistics GetStats() {
8254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    CriticalSectionScoped cs(stats_lock_.get());
8354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    return stats_;
8454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  }
8554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
8654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org private:
8754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  // StatisticsUpdated calls are triggered from threads in the RTP module,
8854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  // while GetStats calls can be triggered from the public voice engine API,
8954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  // hence synchronization is needed.
9000b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<CriticalSectionWrapper> stats_lock_;
9154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  const uint32_t ssrc_;
9254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  ChannelStatistics stats_;
9354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org};
9454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
950a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.orgclass VoERtcpObserver : public RtcpBandwidthObserver {
96c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org public:
970a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  explicit VoERtcpObserver(Channel* owner) : owner_(owner) {}
980a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  virtual ~VoERtcpObserver() {}
990a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
1000a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
1010a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // Not used for Voice Engine.
1020a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  }
1030a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
10414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
10514665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org                                    int64_t rtt,
10614665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org                                    int64_t now_ms) override {
1070a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // TODO(mflodman): Do we need to aggregate reports here or can we jut send
1080a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // what we get? I.e. do we ever get multiple reports bundled into one RTCP
1090a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // report for VoiceEngine?
1100a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    if (report_blocks.empty())
1110a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      return;
1120a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
1130a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    int fraction_lost_aggregate = 0;
1140a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    int total_number_of_packets = 0;
1150a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
1160a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // If receiving multiple report blocks, calculate the weighted average based
1170a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    // on the number of packets a report refers to.
1180a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    for (ReportBlockList::const_iterator block_it = report_blocks.begin();
1190a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org         block_it != report_blocks.end(); ++block_it) {
1200a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      // Find the previous extended high sequence number for this remote SSRC,
1210a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      // to calculate the number of RTP packets this report refers to. Ignore if
1220a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      // we haven't seen this SSRC before.
1230a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      std::map<uint32_t, uint32_t>::iterator seq_num_it =
1240a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org          extended_max_sequence_number_.find(block_it->sourceSSRC);
1250a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      int number_of_packets = 0;
1260a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      if (seq_num_it != extended_max_sequence_number_.end()) {
1270a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org        number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second;
1280a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      }
1290a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      fraction_lost_aggregate += number_of_packets * block_it->fractionLost;
1300a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      total_number_of_packets += number_of_packets;
1310a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
1320a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      extended_max_sequence_number_[block_it->sourceSSRC] =
1330a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org          block_it->extendedHighSeqNum;
1340a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    }
1350a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    int weighted_fraction_lost = 0;
1360a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    if (total_number_of_packets > 0) {
1370a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      weighted_fraction_lost = (fraction_lost_aggregate +
1380a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org          total_number_of_packets / 2) / total_number_of_packets;
1390a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    }
1400a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    owner_->OnIncomingFractionLoss(weighted_fraction_lost);
141c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
142c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
143c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org private:
144c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  Channel* owner_;
1450a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  // Maps remote side ssrc to extended highest sequence number received.
1460a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  std::map<uint32_t, uint32_t> extended_max_sequence_number_;
147c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org};
148c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
1496141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendData(FrameType frameType,
1516141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                  uint8_t   payloadType,
1526141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                  uint32_t  timeStamp,
1536141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                  const uint8_t*  payloadData,
1544591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                  size_t    payloadSize,
155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  const RTPFragmentationHeader* fragmentation)
156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
1594591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 " payloadSize=%" PRIuS ", fragmentation=0x%x)",
1604591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 frameType, payloadType, timeStamp,
1614591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 payloadSize, fragmentation);
162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_includeAudioLevelIndication)
164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Store current audio level in the RTP/RTCP module.
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // The level will be used in combination with voice-activity state
167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // (frameType) to add an RTP header extension
168382c0c209d323c1e6972d988a7b26f08fc2e8a6bandrew@webrtc.org        _rtpRtcpModule->SetAudioLevel(rms_level_.RMS());
169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Push data from ACM to RTP/RTCP-module to deliver audio frame for
172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // packetization.
173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
1742853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadType,
176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        timeStamp,
177ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // Leaving the time when this frame was
178ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // received from the capture device as
179ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // undefined for voice for now.
180ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        -1,
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadData,
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadSize,
183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        fragmentation) == -1)
184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::SendData() failed to send data to RTP/RTCP module");
188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastLocalTimeStamp = timeStamp;
192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastPayloadType = payloadType;
193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1976141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
198e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.orgChannel::InFrameType(FrameType frame_type)
199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
201e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.org                 "Channel::InFrameType(frame_type=%d)", frame_type);
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2039a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
204e9217b4bdbf9a8fd8b4882b2f995665927f28ad2henrik.lundin@webrtc.org    _sendFrameType = (frame_type == kAudioFrameSpeech);
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2086141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
2099213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::OnRxVadDetected(int vadDecision)
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2149a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxVadObserverPtr)
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2244591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgChannel::SendPacket(int channel, const void *data, size_t len)
225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    channel = VoEChannelId(channel);
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2304591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 "Channel::SendPacket(channel=%d, len=%" PRIuS ")", channel,
2314591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 len);
232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
233fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
234fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org
235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_transportPtr == NULL)
236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() failed to send RTP packet due to"
239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " invalid transport object");
240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2436141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    uint8_t* bufferToSendPtr = (uint8_t*)data;
2444591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t bufferLength = len;
245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTP packet to a file (if RTP dump is enabled).
2476141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTP dump to output file failed");
252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
254fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
255fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                                      bufferLength);
256fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    if (n < 0) {
257fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      std::string transport_name =
258fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org          _externalTransport ? "external transport" : "WebRtc sockets";
259fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      WEBRTC_TRACE(kTraceError, kTraceVoice,
260fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   VoEId(_instanceId,_channelId),
261fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   "Channel::SendPacket() RTP transmission using %s failed",
262fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   transport_name.c_str());
263fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      return -1;
264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
265fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    return n;
266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2694591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgChannel::SendRTCPPacket(int channel, const void *data, size_t len)
270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    channel = VoEChannelId(channel);
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2754591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 "Channel::SendRTCPPacket(channel=%d, len=%" PRIuS ")", channel,
2764591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 len);
277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
278fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
279fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    if (_transportPtr == NULL)
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
281fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceVoice,
282fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                     VoEId(_instanceId,_channelId),
283fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                     "Channel::SendRTCPPacket() failed to send RTCP packet"
284fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                     " due to invalid transport object");
285fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org        return -1;
286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2886141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    uint8_t* bufferToSendPtr = (uint8_t*)data;
2894591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t bufferLength = len;
290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTCP packet to a file (if RTP dump is enabled).
2926141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTCP dump to output file failed");
297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
299fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    int n = _transportPtr->SendRTCPPacket(channel,
300fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                                          bufferToSendPtr,
301fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                                          bufferLength);
302fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    if (n < 0) {
303fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      std::string transport_name =
304fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org          _externalTransport ? "external transport" : "WebRtc sockets";
305fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      WEBRTC_TRACE(kTraceInfo, kTraceVoice,
306fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   VoEId(_instanceId,_channelId),
307fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   "Channel::SendRTCPPacket() transmission using %s failed",
308fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org                   transport_name.c_str());
309fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org      return -1;
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
311fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    return n;
312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
3159213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::OnPlayTelephoneEvent(int32_t id,
3169213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                              uint8_t event,
3179213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                              uint16_t lengthMs,
3189213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                              uint8_t volume)
319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
322fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " volume=%u)", id, event, lengthMs, volume);
323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_playOutbandDtmfEvent || (event > 15))
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Ignore callback since feedback is disabled or event is not a
327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Dtmf tone event.
328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return;
329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(_outputMixerPtr != NULL);
332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Start playing out the Dtmf tone (if playout is enabled).
334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Reduce length of tone with 80ms to the reduce risk of echo.
335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
339286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgChannel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc)
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
343286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org                 id, ssrc);
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
345b295a3f5920e2706d42c960c5180c7cc6e1f435edwkang@webrtc.org    // Update ssrc so that NTP for AV sync can be updated.
346b295a3f5920e2706d42c960c5180c7cc6e1f435edwkang@webrtc.org    _rtpRtcpModule->SetRemoteSSRC(ssrc);
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3499213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgvoid Channel::OnIncomingCSRCChanged(int32_t id,
3509213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                    uint32_t CSRC,
3519213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                    bool added)
352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, CSRC, added);
356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
358286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid Channel::ResetStatistics(uint32_t ssrc) {
359286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  StreamStatistician* statistician =
360286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(ssrc);
361286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  if (statistician) {
362286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    statistician->ResetStatistics();
363286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  }
36454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  statistics_proxy_->ResetStatistics();
365822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
366822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
3676141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnInitializeDecoder(
3699213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org    int32_t id,
3709213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org    int8_t payloadType,
371813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    const char payloadName[RTP_PAYLOAD_NAME_SIZE],
3729213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org    int frequency,
3739213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org    uint8_t channels,
3749213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org    uint32_t rate)
375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, payloadType, payloadName, frequency, channels, rate);
380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
381ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org    assert(VoEChannelId(id) == _channelId);
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
383f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    CodecInst receiveCodec = {0};
384f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    CodecInst dummyCodec = {0};
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.pltype = payloadType;
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.plfreq = frequency;
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.channels = channels;
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.rate = rate;
390f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
391ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org
392eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.pacsize = dummyCodec.pacsize;
394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Register the new codec to the ACM
396eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterReceiveCodec(receiveCodec) == -1)
397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
399ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org                     VoEId(_instanceId, _channelId),
400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::OnInitializeDecoder() invalid codec ("
401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "pt=%d, name=%s) received - 1", payloadType, payloadName);
402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4096141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
4106141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::OnReceivedPayloadData(const uint8_t* payloadData,
4114591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                               size_t payloadSize,
412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               const WebRtcRTPHeader* rtpHeader)
413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4154591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS ","
416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " payloadType=%u, audioChannel=%u)",
417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 payloadSize,
418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtpHeader->header.payloadType,
419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtpHeader->type.Audio.channel);
420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
421944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().playing)
422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Avoid inserting into NetEQ when we are not playing. Count the
424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // packet as discarded.
425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStream, kTraceVoice,
426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "received packet is discarded since playing is not"
428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " activated");
429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _numberOfDiscardedPackets++;
430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Push the incoming payload (parsed and ready for decoding) into the ACM
434eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->IncomingPacket(payloadData,
435eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org                                      payloadSize,
436eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org                                      *rtpHeader) != 0)
437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::OnReceivedPayloadData() unable to push data to the ACM");
441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
444d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org    // Update the packet delay.
445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    UpdatePacketDelay(rtpHeader->header.timestamp,
446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      rtpHeader->header.sequenceNumber);
447d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org
44816825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org    int64_t round_trip_time = 0;
449822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time,
450822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                        NULL, NULL, NULL);
451822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
452eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    std::vector<uint16_t> nack_list = audio_coding_->GetNackList(
453822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        round_trip_time);
454822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    if (!nack_list.empty()) {
455822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org      // Can't use nack_list.data() since it's not supported by all
456822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org      // compilers.
457822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org      ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
458d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org    }
459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4627bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
4634591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                size_t rtp_packet_length) {
4647bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  RTPHeader header;
4657bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
4667bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
4677bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                 "IncomingPacket invalid RTP header");
4687bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
4697bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  }
4707bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  header.payload_type_frequency =
4717bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
4727bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (header.payload_type_frequency < 0)
4737bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
4747bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
4757bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
4767bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
4779213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgint32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame)
478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetAudioFrame(id=%d)", id);
481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
483eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->PlayoutData10Ms(audioFrame.sample_rate_hz_,
484eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org                                       &audioFrame) == -1)
485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice,
487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
4897859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // In all likelihood, the audio in this frame is garbage. We return an
4907859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // error so that the audio mixer module doesn't add it to the mix. As
4917859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // a result, it won't be played out and the actions skipped here are
4927859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // irrelevant.
4937859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        return -1;
494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_RxVadDetection)
497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UpdateRxVadDetection(audioFrame);
499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Convert module ID to internal VoE channel ID
50263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    audioFrame.id_ = VoEChannelId(audioFrame.id_);
503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Store speech type for dead-or-alive detection
50463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _outputSpeechType = audioFrame.speech_type_;
505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
506944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    ChannelState::State state = channel_state_.Get();
507944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org
508944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (state.rx_apm_is_enabled) {
50960730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org      int err = rx_audioproc_->ProcessStream(&audioFrame);
51060730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org      if (err) {
51160730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org        LOG(LS_ERROR) << "ProcessStream() error: " << err;
51260730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org        assert(false);
51360730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org      }
514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
51663420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    float output_gain = 1.0f;
51763420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    float left_pan =  1.0f;
51863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    float right_pan =  1.0f;
51963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    {
52063420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org      CriticalSectionScoped cs(&volume_settings_critsect_);
52163420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org      output_gain = _outputGain;
52263420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org      left_pan = _panLeft;
52363420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org      right_pan= _panRight;
52463420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    }
52563420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org
526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Output volume scaling
52763420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    if (output_gain < 0.99f || output_gain > 1.01f)
528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
52963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org        AudioFrameOperations::ScaleWithSat(output_gain, audioFrame);
530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Scale left and/or right channel(s) if stereo and master balance is
533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // active
534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
53563420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    if (left_pan != 1.0f || right_pan != 1.0f)
536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
53763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (audioFrame.num_channels_ == 1)
538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Emulate stereo mode since panning is active.
540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // The mono signal is copied to both left and right channels here.
5414ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org            AudioFrameOperations::MonoToStereo(&audioFrame);
542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // For true stereo mode (when we are receiving a stereo signal), no
544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // action is needed.
545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Do the panning operation (the audio frame contains stereo at this
547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // stage)
54863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org        AudioFrameOperations::Scale(left_pan, right_pan, audioFrame);
549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Mix decoded PCM output with file if file mixing is enabled
552944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (state.output_file_playing)
553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
55463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // External media
558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputExternalMedia)
559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5609a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
56163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        const bool isStereo = (audioFrame.num_channels_ == 2);
562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputExternalMediaCallbackPtr)
563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputExternalMediaCallbackPtr->Process(
565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId,
566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                kPlaybackPerChannel,
5676141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                (int16_t*)audioFrame.data_,
56863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                audioFrame.samples_per_channel_,
56963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                audioFrame.sample_rate_hz_,
570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                isStereo);
571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Record playout if enabled
575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5769a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFileRecording && _outputFileRecorderPtr)
579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5805398d9583b713f83db843a15f8bcc2ef8df23bccniklas.enbom@webrtc.org            _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Measure audio level (0-9)
585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.ComputeLevel(audioFrame);
586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
58794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    if (capture_start_rtp_time_stamp_ < 0 && audioFrame.timestamp_ != 0) {
58894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // The first frame with a valid rtp timestamp.
589cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org      capture_start_rtp_time_stamp_ = audioFrame.timestamp_;
59094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    }
59194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org
59294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    if (capture_start_rtp_time_stamp_ >= 0) {
59394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // audioFrame.timestamp_ should be valid from now on.
59494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org
59594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // Compute elapsed time.
59694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      int64_t unwrap_timestamp =
59794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org          rtp_ts_wraparound_handler_->Unwrap(audioFrame.timestamp_);
59894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      audioFrame.elapsed_time_ms_ =
59994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org          (unwrap_timestamp - capture_start_rtp_time_stamp_) /
60094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org          (GetPlayoutFrequency() / 1000);
60194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org
6028e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org      {
603cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org        CriticalSectionScoped lock(ts_stats_lock_.get());
6048e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org        // Compute ntp time.
6058e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org        audioFrame.ntp_time_ms_ = ntp_estimator_.Estimate(
6068e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org            audioFrame.timestamp_);
6078e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org        // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
6088e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org        if (audioFrame.ntp_time_ms_ > 0) {
6098e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org          // Compute |capture_start_ntp_time_ms_| so that
6108e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org          // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
6118e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org          capture_start_ntp_time_ms_ =
6128e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org              audioFrame.ntp_time_ms_ - audioFrame.elapsed_time_ms_;
6138e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org        }
614cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org      }
615cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    }
616cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org
617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6206141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
6219213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::NeededFrequency(int32_t id)
622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::NeededFrequency(id=%d)", id);
625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int highestNeeded = 0;
627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Determine highest needed receive frequency
629eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Return the bigger of playout and receive frequency in the ACM.
632eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->PlayoutFrequency() > receiveFrequency)
633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
634eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        highestNeeded = audio_coding_->PlayoutFrequency();
635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        highestNeeded = receiveFrequency;
639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Special case, if we're playing a file on the playout side
642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // we take that frequency into consideration as well
643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This is not needed on sending side, since the codec will
644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // limit the spectrum anyway.
645944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().output_file_playing)
646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6479a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
648944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        if (_outputFilePlayerPtr)
649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if(_outputFilePlayerPtr->Frequency()>highestNeeded)
651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                highestNeeded=_outputFilePlayerPtr->Frequency();
653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return(highestNeeded);
658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6606141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::CreateChannel(Channel*& channel,
6629213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                       int32_t channelId,
663e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org                       uint32_t instanceId,
664e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org                       const Config& config)
665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        channelId, instanceId);
669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
670e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org    channel = new Channel(channelId, instanceId, config);
671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (channel == NULL)
672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceMemory, kTraceVoice,
674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(instanceId,channelId),
675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::CreateChannel() unable to allocate memory for"
676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " channel");
677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
6839213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::PlayNotification(int32_t id, uint32_t durationMs)
684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PlayNotification(id=%d, durationMs=%d)",
687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, durationMs);
688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Not implement yet
690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
6939213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::RecordNotification(int32_t id, uint32_t durationMs)
694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordNotification(id=%d, durationMs=%d)",
697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, durationMs);
698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Not implement yet
700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
7039213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::PlayFileEnded(int32_t id)
704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PlayFileEnded(id=%d)", id);
707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (id == _inputFilePlayerId)
709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
710944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetInputFilePlaying(false);
711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PlayFileEnded() => input file player module is"
714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " shutdown");
715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (id == _outputFilePlayerId)
717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
718944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetOutputFilePlaying(false);
719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PlayFileEnded() => output file player module is"
722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " shutdown");
723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
7279213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::RecordFileEnded(int32_t id)
728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordFileEnded(id=%d)", id);
731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(id == _outputFileRecorderId);
733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7349a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = false;
737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordFileEnded() => output file recorder module is"
740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " shutdown");
741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7439213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::Channel(int32_t channelId,
744e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org                 uint32_t instanceId,
745e509f943eded156f7a8365b0b001abe73646acfaminyue@webrtc.org                 const Config& config) :
746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
74863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    volume_settings_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _instanceId(instanceId),
75022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _channelId(channelId),
751a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    rtp_header_parser_(RtpHeaderParser::Create()),
752822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    rtp_payload_registry_(
753dc80bae2a62a1bdbe0d342b3260a7e5b2cb958dfandresp@webrtc.org        new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))),
754822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    rtp_receive_statistics_(ReceiveStatistics::Create(
755822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        Clock::GetRealTimeClock())),
756822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    rtp_receiver_(RtpReceiver::CreateAudioReceiver(
757822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        VoEModuleId(instanceId, channelId), Clock::GetRealTimeClock(), this,
758822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        this, this, rtp_payload_registry_.get())),
759822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
76034fe0153b90c3e616a0fd5aba8aa8118ae600760henrik.lundin@webrtc.org    audio_coding_(AudioCodingModule::Create(
76122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com        VoEModuleId(instanceId, channelId))),
762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpDumpIn(*RtpDump::CreateRtpDump()),
763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpDumpOut(*RtpDump::CreateRtpDump()),
764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel(),
765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport(false),
766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr(NULL),
767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFilePlayerPtr(NULL),
768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr(NULL),
769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Avoid conflict with other channels by adding 1024 - 1026,
770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // won't use as much as 1024 channels.
771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording(false),
77522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
77622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
77722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _outputExternalMedia(false),
778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputExternalMediaCallbackPtr(NULL),
779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputExternalMediaCallbackPtr(NULL),
78022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
78122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _sendTelephoneEventPayloadType(106),
7828e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org    ntp_estimator_(Clock::GetRealTimeClock()),
783167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org    jitter_buffer_playout_timestamp_(0),
7841de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    playout_timestamp_rtp_(0),
7851de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    playout_timestamp_rtcp_(0),
78654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    playout_delay_ms_(0),
78722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _numberOfDiscardedPackets(0),
78809e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    send_sequence_number_(0),
789cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    ts_stats_lock_(CriticalSectionWrapper::CreateCriticalSection()),
79094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
79194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    capture_start_rtp_time_stamp_(-1),
792cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    capture_start_ntp_time_ms_(-1),
79322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _engineStatisticsPtr(NULL),
7942919e95c2a59a087ba8297c2f551c3ebc3754c9ehenrika@webrtc.org    _outputMixerPtr(NULL),
7952919e95c2a59a087ba8297c2f551c3ebc3754c9ehenrika@webrtc.org    _transmitMixerPtr(NULL),
79622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _moduleProcessThreadPtr(NULL),
79722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _audioDeviceModulePtr(NULL),
79822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _voiceEngineObserverPtr(NULL),
79922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _callbackCritSectPtr(NULL),
80022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _transportPtr(NULL),
80122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rxVadObserverPtr(NULL),
80222963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _oldVadDecision(-1),
80322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _sendFrameType(0),
8041b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    _externalMixing(false),
80522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _mixFileWithMicrophone(false),
806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mute(false),
807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panLeft(1.0f),
808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panRight(1.0f),
809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputGain(1.0f),
810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playOutbandDtmfEvent(false),
811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playInbandDtmfEvent(false),
812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastLocalTimeStamp(0),
813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastPayloadType(0),
81422963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _includeAudioLevelIndication(false),
815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputSpeechType(AudioFrame::kNormalSpeech),
816b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    vie_network_(NULL),
817b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    video_channel_(-1),
8181de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    _average_jitter_buffer_delay_us(0),
819e46c8d387587ba148e229a7bb18f1cc0708a2a87turaj@webrtc.org    least_required_delay_ms_(0),
820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _previousTimestamp(0),
821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _recPacketDelayMs(20),
822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection(false),
823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxAgcIsEnabled(false),
8247bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    _rxNsIsEnabled(false),
825c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    restored_packet_in_use_(false),
8260a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    rtcp_observer_(new VoERtcpObserver(this)),
82774aaf29a0ff1b211dbfdbb6309791111a7871779minyue@webrtc.org    network_predictor_(new NetworkPredictor(Clock::GetRealTimeClock()))
828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::Channel() - ctor");
831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfQueue.ResetDtmf();
832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfGenerator.Init();
833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.Clear();
834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
8352853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RtpRtcp::Configuration configuration;
8362853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.id = VoEModuleId(instanceId, channelId);
8372853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.audio = true;
8382853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.outgoing_transport = this;
8392853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.audio_messages = this;
840822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    configuration.receive_statistics = rtp_receive_statistics_.get();
8410a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org    configuration.bandwidth_callback = rtcp_observer_.get();
8422853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org
8432853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
84454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org
84554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC()));
84654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    rtp_receive_statistics_->RegisterRtcpStatisticsCallback(
84754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org        statistics_proxy_.get());
848f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org
849f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org    Config audioproc_config;
850f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org    audioproc_config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
851f927fd64812b4a42a0f4e2686683a43d74b4bf08aluebs@webrtc.org    rx_audioproc_.reset(AudioProcessing::Create(audioproc_config));
852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::~Channel()
855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
85654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::~Channel() - dtor");
859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputExternalMedia)
861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
864944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().input_external_media)
865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        DeRegisterExternalMediaProcessing(kRecordingPerChannel);
867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    StopSend();
869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    StopPlayout();
870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
8729a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputFilePlayerPtr)
874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr->StopPlayingFile();
877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr = NULL;
879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFilePlayerPtr)
881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr->StopPlayingFile();
884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr = NULL;
886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFileRecorderPtr)
888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr->StopRecording();
891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr = NULL;
893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The order to safely shutdown modules in a channel is:
897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 1. De-register callbacks in modules
898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 2. De-register modules in process thread
899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 3. Destroy modules
900eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterTransportCallback(NULL) == -1)
901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register transport callback"
905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " (Audio coding module)");
906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
907eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterVADCallback(NULL) == -1)
908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register VAD callback"
912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " (Audio coding module)");
913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // De-register modules in process thread
9153985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org    _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
9163985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org
917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // End of modules shutdown
918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Delete other objects
920b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    if (vie_network_) {
921b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      vie_network_->Release();
922b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      vie_network_ = NULL;
923b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    }
924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump::DestroyRtpDump(&_rtpDumpIn);
925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump::DestroyRtpDump(&_rtpDumpOut);
926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete &_callbackCritSect;
927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete &_fileCritSect;
92863420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    delete &volume_settings_critsect_;
929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9316141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Init()
933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::Init()");
936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
937944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.Reset();
938944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org
939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Initial sanity
940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((_engineStatisticsPtr == NULL) ||
942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_moduleProcessThreadPtr == NULL))
943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice,
945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::Init() must call SetEngineInformation() first");
947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Add modules to process thread (for periodic schedulation)
951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9523985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org    _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
9533985f0151aff9b91418733795a98140079c19a73tommi@webrtc.org
954c450a1966965fbb3c16ec6d02c3d5cbec67df500pwestin@webrtc.org    // --- ACM initialization
955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
95645c6449114ab69cab755410f69567fa7e20f8106Henrik Lundin    if ((audio_coding_->InitializeReceiver() == -1)
957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_CODEC_AVT
958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // out-of-band Dtmf tones are played out by default
95945c6449114ab69cab755410f69567fa7e20f8106Henrik Lundin        || (audio_coding_->SetDtmfPlayoutStatus(true) == -1)
960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
96145c6449114ab69cab755410f69567fa7e20f8106Henrik Lundin       )
962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() unable to initialize the ACM - 1");
966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- RTP/RTCP module initialization
970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Ensure that RTCP is enabled by default for the created channel.
972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Note that, the module will keep generating RTCP until it is explicitly
973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // disabled by the user.
974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // After StopListen (when no sockets exists), RTCP packets will no longer
975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // be transmitted since the Transport object will then be invalid.
976822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
977822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    // RTCP is enabled by default.
978d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    _rtpRtcpModule->SetRTCPStatus(kRtcpCompound);
979d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    // --- Register all permanent callbacks
980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool fail =
981eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        (audio_coding_->RegisterTransportCallback(this) == -1) ||
982eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        (audio_coding_->RegisterVADCallback(this) == -1);
983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (fail)
985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_INIT_CHANNEL, kTraceError,
988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() callbacks not registered");
989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Register all supported codecs to the receiving side of the
993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // RTP/RTCP module
994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
9966141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (int idx = 0; idx < nSupportedCodecs; idx++)
999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Open up the RTP/RTCP receiver for all supported codecs
1001eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        if ((audio_coding_->Codec(idx, &codec) == -1) ||
1002822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            (rtp_receiver_->RegisterReceivePayload(
1003822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.plname,
1004822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.pltype,
1005822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.plfreq,
1006822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.channels,
1007822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                (codec.rate < 0) ? 0 : codec.rate) == -1))
1008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
1011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "to RTP/RTCP receiver",
1013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
1014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
1015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
1017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
1020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "the RTP/RTCP receiver",
1022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
1023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
1024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Ensure that PCMU is used as default codec on the sending side
10274517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org        if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
1028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            SetSendCodec(codec);
1030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Register default PT for outband 'telephone-event'
1033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
10352853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org            if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
1036eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org                (audio_coding_->RegisterReceiveCodec(codec) == -1))
1037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register outband "
1041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "'telephone-event' (%d/%d) correctly",
1042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "CN"))
1047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1048eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org            if ((audio_coding_->RegisterSendCodec(codec) == -1) ||
1049eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org                (audio_coding_->RegisterReceiveCodec(codec) == -1) ||
10502853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org                (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
1051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register CN (%d/%d) "
1055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "correctly - 1",
1056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_CODEC_RED
1060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Register RED to the receiving side of the ACM.
1061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // We will not receive an OnInitializeDecoder() callback for RED.
1062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "RED"))
1063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1064eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org            if (audio_coding_->RegisterReceiveCodec(codec) == -1)
1065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register RED (%d/%d) "
1069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "correctly",
1070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1075684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
10766c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org    if (rx_audioproc_->noise_suppression()->set_level(kDefaultNsMode) != 0) {
10776c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org      LOG_FERR1(LS_ERROR, noise_suppression()->set_level, kDefaultNsMode);
10786c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org      return -1;
1079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
10806c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org    if (rx_audioproc_->gain_control()->set_mode(kDefaultRxAgcMode) != 0) {
10816c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org      LOG_FERR1(LS_ERROR, gain_control()->set_mode, kDefaultRxAgcMode);
10826c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org      return -1;
1083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
10886141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetEngineInformation(Statistics& engineStatistics,
1090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              OutputMixer& outputMixer,
1091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              voe::TransmitMixer& transmitMixer,
1092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              ProcessThread& moduleProcessThread,
1093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              AudioDeviceModule& audioDeviceModule,
1094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              VoiceEngineObserver* voiceEngineObserver,
1095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              CriticalSectionWrapper* callbackCritSect)
1096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetEngineInformation()");
1099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _engineStatisticsPtr = &engineStatistics;
1100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputMixerPtr = &outputMixer;
1101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transmitMixerPtr = &transmitMixer,
1102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _moduleProcessThreadPtr = &moduleProcessThread;
1103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioDeviceModulePtr = &audioDeviceModule;
1104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = voiceEngineObserver;
1105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _callbackCritSectPtr = callbackCritSect;
1106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11096141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateLocalTimeStamp()
1111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
111363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _timeStamp += _audioFrame.samples_per_channel_;
1114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11176141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartPlayout()
1119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayout()");
1122944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().playing)
1123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
11261b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
11271b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    if (!_externalMixing) {
11281b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        // Add participant as candidates for mixing.
11291b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
11301b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        {
11311b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            _engineStatisticsPtr->SetLastError(
11321b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
11331b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                "StartPlayout() failed to add participant to mixer");
11341b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            return -1;
11351b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        }
1136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1138944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetPlaying(true);
1139ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
1140ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return -1;
1141ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
1142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11456141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopPlayout()
1147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayout()");
1150944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().playing)
1151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
11541b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
11551b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    if (!_externalMixing) {
11561b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        // Remove participant as candidates for mixing
11571b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
11581b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        {
11591b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            _engineStatisticsPtr->SetLastError(
11601b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
11611b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                "StopPlayout() failed to remove participant from mixer");
11621b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            return -1;
11631b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        }
1164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1166944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetPlaying(false);
1167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.Clear();
1168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11726141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartSend()
1174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartSend()");
117709e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // Resume the previous sequence number which was reset by StopSend().
1178944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    // This needs to be done before |sending| is set to true.
117909e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    if (send_sequence_number_)
118009e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org      SetInitSequenceNumber(send_sequence_number_);
118109e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org
1182944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().sending)
1183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1184944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org      return 0;
1185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1186944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetSending(true);
1187e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
11882853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSendingStatus(true) != 0)
1189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartSend() RTP/RTCP failed to start sending");
11939a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
1194944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetSending(false);
1195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1197e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
1198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12016141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopSend()
1203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopSend()");
1206944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().sending)
1207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1208944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org      return 0;
1209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1210944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetSending(false);
1211e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
121209e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // Store the sequence number to be able to pick up the same sequence for
121309e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // the next StartSend(). This is needed for restarting device, otherwise
121409e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // it might cause libSRTP to complain about packets being replayed.
121509e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
121609e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // CL is landed. See issue
121709e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    // https://code.google.com/p/webrtc/issues/detail?id=2111 .
121809e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org    send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
121909e8c47ee5c58e5e86b09dc1950f8d3f9f24cd9fxians@webrtc.org
1220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Reset sending SSRC and sequence number and triggers direct transmission
1221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // of RTCP BYE
12222853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
12232853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
1224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartSend() RTP/RTCP failed to stop sending");
1228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12336141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartReceiving()
1235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartReceiving()");
1238944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().receiving)
1239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1242944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetReceiving(true);
1243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _numberOfDiscardedPackets = 0;
1244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12476141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopReceiving()
1249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopReceiving()");
1252944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().receiving)
1253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1256684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
1257944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetReceiving(false);
1258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12616141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
1263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterVoiceEngineObserver()");
12669a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
1267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_voiceEngineObserverPtr)
1269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
1272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterVoiceEngineObserver() observer already enabled");
1273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = &observer;
1276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12796141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterVoiceEngineObserver()
1281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterVoiceEngineObserver()");
12849a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
1285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_voiceEngineObserverPtr)
1287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
1290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterVoiceEngineObserver() observer already disabled");
1291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = NULL;
1294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
12976141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendCodec(CodecInst& codec)
1299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1300eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    return (audio_coding_->SendCodec(&codec));
1301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13036141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecCodec(CodecInst& codec)
1305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1306eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    return (audio_coding_->ReceiveCodec(&codec));
1307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13096141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCodec(const CodecInst& codec)
1311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendCodec()");
1314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1315eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterSendCodec(codec) != 0)
1316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "SetSendCodec() failed to register codec to ACM");
1319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13222853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
13242853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
13252853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
1328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "SetSendCodec() failed to register codec to"
1330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    " RTP/RTCP module");
1331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13352853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
1336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "SetSendCodec() failed to set audio packet size");
1339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1345adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusenvoid Channel::SetBitRate(int bitrate_bps) {
1346adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1347adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen               "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
1348adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen  audio_coding_->SetBitRate(bitrate_bps);
1349adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen}
1350adf89b7e33cc54dab9365dddead687a46a074cf0Ivo Creusen
13510a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.orgvoid Channel::OnIncomingFractionLoss(int fraction_lost) {
135274aaf29a0ff1b211dbfdbb6309791111a7871779minyue@webrtc.org  network_predictor_->UpdatePacketLossRate(fraction_lost);
13530a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  uint8_t average_fraction_loss = network_predictor_->GetLossRate();
13540a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org
1355c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  // Normalizes rate to 0 - 100.
13560a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org  if (audio_coding_->SetPacketLossRate(
13570a7d4eed98ccec0c2b3e7522e7b2dde1919a4ae3mflodman@webrtc.org      100 * average_fraction_loss / 255) != 0) {
1358c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    assert(false);  // This should not happen.
1359c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
1360c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}
1361c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
13626141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
1364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetVADStatus(mode=%d)", mode);
1367664ccb7d8da3adfffdb7c56f885b633224555e6ehenrik.lundin@webrtc.org    assert(!(disableDTX && enableVAD));  // disableDTX mode is deprecated.
1368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // To disable VAD, DTX must be disabled too
1369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    disableDTX = ((enableVAD == false) ? true : disableDTX);
1370eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->SetVAD(!disableDTX, enableVAD, mode) != 0)
1371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetVADStatus() failed to set VAD");
1375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
1382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetVADStatus");
1385eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->VAD(&disabledDTX, &enabledVAD, &mode) != 0)
1386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetVADStatus() failed to get VAD status");
1390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    disabledDTX = !disabledDTX;
1393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13966141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRecPayloadType(const CodecInst& codec)
1398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRecPayloadType()");
1401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1402944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().playing)
1403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
1406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRecPayloadType() unable to set PT while playing");
1407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1409944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().receiving)
1410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_LISTENING, kTraceError,
1413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRecPayloadType() unable to set PT while listening");
1414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (codec.pltype == -1)
1418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // De-register the selected codec (RTP/RTCP module and ACM)
1420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
14216141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        int8_t pltype(-1);
1422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        CodecInst rxCodec = codec;
1423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Get payload type for the given codec
1425822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        rtp_payload_registry_->ReceivePayloadType(
1426822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            rxCodec.plname,
1427822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            rxCodec.plfreq,
1428822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            rxCodec.channels,
1429822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            (rxCodec.rate < 0) ? 0 : rxCodec.rate,
1430822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            &pltype);
1431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rxCodec.pltype = pltype;
1432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1433822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0)
1434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_RTP_RTCP_MODULE_ERROR,
1437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    kTraceError,
1438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "SetRecPayloadType() RTP/RTCP-module deregistration "
1439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "failed");
1440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1442eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0)
1443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() ACM deregistration failed - 1");
1447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1452822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    if (rtp_receiver_->RegisterReceivePayload(
1453822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.plname,
1454822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.pltype,
1455822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.plfreq,
1456822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.channels,
1457822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        (codec.rate < 0) ? 0 : codec.rate) != 0)
1458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // First attempt to register failed => de-register and try again
1460822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
1461822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        if (rtp_receiver_->RegisterReceivePayload(
1462822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            codec.plname,
1463822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            codec.pltype,
1464822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            codec.plfreq,
1465822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            codec.channels,
1466822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            (codec.rate < 0) ? 0 : codec.rate) != 0)
1467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() RTP/RTCP-module registration failed");
1471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1474eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterReceiveCodec(codec) != 0)
1475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1476eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        audio_coding_->UnregisterReceiveCodec(codec.pltype);
1477eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        if (audio_coding_->RegisterReceiveCodec(codec) != 0)
1478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() ACM registration failed - 1");
1482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
14886141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecPayloadType(CodecInst& codec)
1490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRecPayloadType()");
14936141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    int8_t payloadType(-1);
1494822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    if (rtp_payload_registry_->ReceivePayloadType(
1495822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.plname,
1496822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.plfreq,
1497822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        codec.channels,
1498822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        (codec.rate < 0) ? 0 : codec.rate,
1499822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        &payloadType) != 0)
1500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
150237198007eab6731fa0f77866155dd4f2b332a262henrika@webrtc.org            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRecPayloadType() failed to retrieve RX payload type");
1504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    codec.pltype = payloadType;
1507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1508d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org                 "Channel::GetRecPayloadType() => pltype=%d", codec.pltype);
1509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
15126141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
1514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendCNPayloadType()");
1517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
15196141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    int32_t samplingFreqHz(-1);
15204517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org    const int kMono = 1;
1521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (frequency == kFreq32000Hz)
1522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        samplingFreqHz = 32000;
1523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (frequency == kFreq16000Hz)
1524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        samplingFreqHz = 16000;
1525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1526eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1)
1527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendCNPayloadType() failed to retrieve default CN codec "
1531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "settings");
1532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Modify the payload type (must be set to dynamic range)
1536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    codec.pltype = type;
1537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1538eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->RegisterSendCodec(codec) != 0)
1539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendCNPayloadType() failed to register CN to ACM");
1543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
15462853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
15482853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
15492853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "module");
1555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1561adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.orgint Channel::SetOpusMaxPlaybackRate(int frequency_hz) {
15626aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1563adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org               "Channel::SetOpusMaxPlaybackRate()");
15646aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org
1565adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org  if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) {
15666aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    _engineStatisticsPtr->SetLastError(
15676aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1568adee8f924224e116f041564ddde83c979880e35fminyue@webrtc.org        "SetOpusMaxPlaybackRate() failed to set maximum playback rate");
15696aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org    return -1;
15706aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  }
15716aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org  return 0;
15726aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org}
15736aac93bd9c3da92e92b016d83c8f84c65aae65b6minyue@webrtc.org
15749b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.orgint Channel::SetOpusDtx(bool enable_dtx) {
15759b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
15769b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org               "Channel::SetOpusDtx(%d)", enable_dtx);
15779b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  int ret = enable_dtx ? audio_coding_->EnableOpusDtx(true)
15789b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org                       : audio_coding_->DisableOpusDtx();
15799b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  if (ret != 0) {
15809b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    _engineStatisticsPtr->SetLastError(
15819b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError, "SetOpusDtx() failed");
15829b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org    return -1;
15839b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  }
15849b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org  return 0;
15859b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org}
15869b2e1144df6e3622354caca00baf4a7462a0809cminyue@webrtc.org
15876141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t Channel::RegisterExternalTransport(Transport& transport)
1588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::RegisterExternalTransport()");
1591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
15929a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
1593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
1595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
1597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           kTraceError,
1598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              "RegisterExternalTransport() external transport already enabled");
1599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       return -1;
1600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport = true;
1602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transportPtr = &transport;
1603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16066141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
1607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterExternalTransport()
1608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterExternalTransport()");
1611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16129a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
161383661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org
1614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_transportPtr)
1615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
1618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterExternalTransport() external transport already "
1619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "disabled");
1620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport = false;
1623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transportPtr = NULL;
1624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "DeRegisterExternalTransport() all transport is disabled");
1626684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org    return 0;
1627684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org}
1628684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
16294591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t Channel::ReceivedRTPPacket(const int8_t* data, size_t length,
1630b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org                                   const PacketTime& packet_time) {
16310c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
16320c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org               "Channel::ReceivedRTPPacket()");
1633684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
16340c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  // Store playout timestamp for the received RTP packet
16351de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  UpdatePlayoutTimestamp(false);
1636684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
16370c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  // Dump the RTP packet to a file (if RTP dump is enabled).
16386141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org  if (_rtpDumpIn.DumpPacket((const uint8_t*)data,
16396141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                            (uint16_t)length) == -1) {
16400c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceVoice,
16410c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org                 VoEId(_instanceId,_channelId),
16420c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org                 "Channel::SendPacket() RTP dump to input file failed");
16430c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  }
16447bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  const uint8_t* received_packet = reinterpret_cast<const uint8_t*>(data);
1645a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  RTPHeader header;
16467bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
16477bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
16487bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                 "Incoming packet: invalid RTP header");
1649a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org    return -1;
1650a5cb98cbbd11e93cb6d0a6232387814aac168c7dstefan@webrtc.org  }
1651822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  header.payload_type_frequency =
1652822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org      rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
16537bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (header.payload_type_frequency < 0)
1654822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    return -1;
165548df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org  bool in_order = IsPacketInOrder(header);
16567bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_receive_statistics_->IncomingPacket(header, length,
165748df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org      IsPacketRetransmitted(header, in_order));
16587bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_payload_registry_->SetIncomingPayloadType(header);
1659b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org
1660b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  // Forward any packets to ViE bandwidth estimator, if enabled.
1661b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  {
1662b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
1663b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    if (vie_network_) {
1664b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      int64_t arrival_time_ms;
1665b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      if (packet_time.timestamp != -1) {
1666b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org        arrival_time_ms = (packet_time.timestamp + 500) / 1000;
1667b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      } else {
1668b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org        arrival_time_ms = TickTime::MillisecondTimestamp();
1669b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      }
16704591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org      size_t payload_length = length - header.headerLength;
1671b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      vie_network_->ReceivedBWEPacket(video_channel_, arrival_time_ms,
1672b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org                                      payload_length, header);
1673b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    }
1674b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  }
1675b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org
167648df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org  return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1;
16777bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
16787bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
16797bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::ReceivePacket(const uint8_t* packet,
16804591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                            size_t packet_length,
16817bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                            const RTPHeader& header,
16827bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                            bool in_order) {
1683456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org  if (rtp_payload_registry_->IsRtx(header)) {
1684456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org    return HandleRtxPacket(packet, packet_length, header);
1685822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  }
16867bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  const uint8_t* payload = packet + header.headerLength;
16874591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  assert(packet_length >= header.headerLength);
16884591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  size_t payload_length = packet_length - header.headerLength;
1689822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  PayloadUnion payload_specific;
1690822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
16917bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                                  &payload_specific)) {
16927bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
1693822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org  }
16947bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
16957bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                                          payload_specific, in_order);
16967bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
16977bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
1698456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.orgbool Channel::HandleRtxPacket(const uint8_t* packet,
1699456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org                              size_t packet_length,
1700456f01441aa4f8c0c8b98aa6d9c2af4a4817e8dbminyue@webrtc.org                              const RTPHeader& header) {
17017bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!rtp_payload_registry_->IsRtx(header))
17027bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17037bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
17047bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  // Remove the RTX header and parse the original RTP header.
17057bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (packet_length < header.headerLength)
17067bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17077bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
17087bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17097bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (restored_packet_in_use_) {
17107bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
17117bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                 "Multiple RTX headers detected, dropping packet");
17127bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17130c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  }
17147bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  uint8_t* restored_packet_ptr = restored_packet_;
17157bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!rtp_payload_registry_->RestoreOriginalPacket(
17167bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
17177bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      header)) {
17187bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
17197bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org                 "Incoming RTX packet: invalid RTP header");
17207bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17217bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  }
17227bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  restored_packet_in_use_ = true;
17237bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
17247bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  restored_packet_in_use_ = false;
17257bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return ret;
17267bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org}
17277bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org
17287bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool Channel::IsPacketInOrder(const RTPHeader& header) const {
17297bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  StreamStatistician* statistician =
17307bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
17317bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!statistician)
17327bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17337bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  return statistician->IsPacketInOrder(header.sequenceNumber);
17340c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org}
17350c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org
173648df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.orgbool Channel::IsPacketRetransmitted(const RTPHeader& header,
173748df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org                                    bool in_order) const {
17387bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  // Retransmissions are handled separately if RTX is enabled.
17397bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (rtp_payload_registry_->RtxEnabled())
17407bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17417bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  StreamStatistician* statistician =
17427bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      rtp_receive_statistics_->GetStatistician(header.ssrc);
17437bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  if (!statistician)
17447bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org    return false;
17457bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  // Check if this is a retransmission.
174616825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t min_rtt = 0;
17477bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
174848df38114d9502f4b4ad700c011190c608a702d5stefan@webrtc.org  return !in_order &&
17497bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org      statistician->IsRetransmitOfOldPacket(header, min_rtt);
1750822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org}
1751822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
17524591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgint32_t Channel::ReceivedRTCPPacket(const int8_t* data, size_t length) {
17530c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
17540c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org               "Channel::ReceivedRTCPPacket()");
17550c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  // Store playout timestamp for the received RTCP packet
17561de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  UpdatePlayoutTimestamp(true);
17570c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org
17580c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  // Dump the RTCP packet to a file (if RTP dump is enabled).
17594591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  if (_rtpDumpIn.DumpPacket((const uint8_t*)data, length) == -1) {
17600c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceVoice,
17610c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org                 VoEId(_instanceId,_channelId),
17620c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org                 "Channel::SendPacket() RTCP dump to input file failed");
17630c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  }
1764684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
17650c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  // Deliver RTCP packet to RTP/RTCP module for parsing
17664591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data, length) == -1) {
17670c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org    _engineStatisticsPtr->SetLastError(
17680c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org        VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
17690c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org        "Channel::IncomingRTPPacket() RTCP packet is invalid");
17700c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  }
177182c4b8531c2c4c2aaf82ff57ee1805037a43ed50wu@webrtc.org
17728e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org  {
17738e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org    CriticalSectionScoped lock(ts_stats_lock_.get());
177416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org    int64_t rtt = GetRTT();
17752c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    if (rtt == 0) {
17762c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org      // Waiting for valid RTT.
17772c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org      return 0;
17782c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    }
17792c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    uint32_t ntp_secs = 0;
17802c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    uint32_t ntp_frac = 0;
17812c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    uint32_t rtp_timestamp = 0;
17822c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    if (0 != _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
17832c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org                                       &rtp_timestamp)) {
17842c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org      // Waiting for RTCP.
17852c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org      return 0;
17862c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    }
17872c0cdbce226137a8f755ae0fb51c28a335b2ea5dminyue@webrtc.org    ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
17888e24d8777849951ed86fb01e0bf556d4eda65161stefan@webrtc.org  }
17890c45957e3a6963e1460c0b5b62a6adf43cf44314pwestin@webrtc.org  return 0;
1790684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org}
1791684f0577fbe4ea393fef1dddf2ca7d02e3205b49pwestin@webrtc.org
1792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(const char* fileName,
17939213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     bool loop,
17949213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     FileFormats format,
17959213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     int startPosition,
17969213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     float volumeScaling,
17979213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     int stopPosition,
1798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const CodecInst* codecInst)
1799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
1804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 startPosition, stopPosition);
1805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1806944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().output_file_playing)
1807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
1810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() is already playing");
1811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
18159a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
1816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1817b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr)
1818b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
1819b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1820b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1821b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr = NULL;
1822b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
1823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1824b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
1825b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerId, (const FileFormats)format);
1826b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1827b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr == NULL)
1828b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
1829b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
1830b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_INVALID_ARGUMENT, kTraceError,
183131d30700d638c4cfa47c26cac7cb00c7232874c9henrike@webrtc.org                "StartPlayingFileLocally() filePlayer format is not correct");
1832b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
1833b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
1834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
18356141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        const uint32_t notificationTime(0);
1836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1837b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr->StartPlayingFile(
1838b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                fileName,
1839b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                loop,
1840b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                startPosition,
1841b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                volumeScaling,
1842b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                notificationTime,
1843b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                stopPosition,
1844b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                (const CodecInst*)codecInst) != 0)
1845b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
1846b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
1847b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_BAD_FILE, kTraceError,
1848b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                "StartPlayingFile() failed to start file playout");
1849b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr->StopPlayingFile();
1850b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1851b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr = NULL;
1852b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
1853b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
1854b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr->RegisterModuleFileCallback(this);
1855944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetOutputFilePlaying(true);
1856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1857ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
1858ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
1859066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
1860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(InStream* stream,
18659213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     FileFormats format,
18669213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     int startPosition,
18679213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     float volumeScaling,
18689213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                     int stopPosition,
1869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const CodecInst* codecInst)
1870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileLocally(format=%d,"
1873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 format, volumeScaling, startPosition, stopPosition);
1875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(stream == NULL)
1877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
1880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() NULL as input stream");
1881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1885944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().output_file_playing)
1886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
1889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() is already playing");
1890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
18949a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org      CriticalSectionScoped cs(&_fileCritSect);
1895b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1896b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      // Destroy the old instance
1897b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr)
1898b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
1899b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1900b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1901b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr = NULL;
1902b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
1903b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1904b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      // Create the instance
1905b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
1906b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerId,
1907b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          (const FileFormats)format);
1908b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1909b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr == NULL)
1910b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
1911b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _engineStatisticsPtr->SetLastError(
1912b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org              VE_INVALID_ARGUMENT, kTraceError,
1913b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org              "StartPlayingFileLocally() filePlayer format isnot correct");
1914b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          return -1;
1915b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
1916b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
19176141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org      const uint32_t notificationTime(0);
1918b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1919b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
1920b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 volumeScaling,
1921b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 notificationTime,
1922b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 stopPosition, codecInst) != 0)
1923b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
1924b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
1925b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                             "StartPlayingFile() failed to "
1926b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                             "start file playout");
1927b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr->StopPlayingFile();
1928b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1929b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr = NULL;
1930b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          return -1;
1931b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
1932b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      _outputFilePlayerPtr->RegisterModuleFileCallback(this);
1933944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org      channel_state_.SetOutputFilePlaying(true);
1934b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    }
1935ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
1936ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
1937066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
1938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileLocally()
1943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayingFileLocally()");
1946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1947944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().output_file_playing)
1948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
1951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFileLocally() isnot playing");
1952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
19569a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
1957b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
1958b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr->StopPlayingFile() != 0)
1959b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
1960b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
1961b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_STOP_RECORDING_FAILED, kTraceError,
1962b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                "StopPlayingFile() could not stop playing");
1963b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
1964b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
1965b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1966b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1967b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr = NULL;
1968944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetOutputFilePlaying(false);
1969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1970b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // _fileCritSect cannot be taken while calling
1971b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // SetAnonymousMixibilityStatus. Refer to comments in
1972b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // StartPlayingFileLocally(const char* ...) for more details.
1973066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
1974066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    {
1975066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        _engineStatisticsPtr->SetLastError(
1976066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1977b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            "StopPlayingFile() failed to stop participant from playing as"
1978b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            "file in the mixer");
1979066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
1980066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    }
1981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileLocally() const
1986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IsPlayingFileLocally()");
1989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1990944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    return channel_state_.Get().output_file_playing;
1991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1993ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.orgint Channel::RegisterFilePlayingToMixer()
1994ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org{
1995ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // Return success for not registering for file playing to mixer if:
1996ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // 1. playing file before playout is started on that channel.
1997ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // 2. starting playout without file playing on that channel.
1998944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().playing ||
1999944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        !channel_state_.Get().output_file_playing)
2000ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    {
2001ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return 0;
2002ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    }
2003ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
2004ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // |_fileCritSect| cannot be taken while calling
2005ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // SetAnonymousMixabilityStatus() since as soon as the participant is added
2006ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // frames can be pulled by the mixer. Since the frames are generated from
2007ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // the file, _fileCritSect will be taken. This would result in a deadlock.
2008ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
2009ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    {
2010944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetOutputFilePlaying(false);
2011ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
2012ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _engineStatisticsPtr->SetLastError(
2013ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
2014ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org            "StartPlayingFile() failed to add participant as file to mixer");
2015ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _outputFilePlayerPtr->StopPlayingFile();
2016ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2017ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _outputFilePlayerPtr = NULL;
2018ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return -1;
2019ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    }
2020ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
2021ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    return 0;
2022ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org}
2023ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
2024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(const char* fileName,
20259213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          bool loop,
20269213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          FileFormats format,
20279213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          int startPosition,
20289213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          float volumeScaling,
20299213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          int stopPosition,
2030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const CodecInst* codecInst)
2031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
2034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
2035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
2036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 startPosition, stopPosition);
2037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2038944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2039944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org
2040944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().input_file_playing)
2041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceWarning,
2044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() filePlayer is playing");
2045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
2049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr)
2050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
2054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create the instance
2057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerId, (const FileFormats)format);
2059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr == NULL)
2061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
2065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
20686141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint32_t notificationTime(0);
2069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StartPlayingFile(
2071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        fileName,
2072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        loop,
2073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        startPosition,
2074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        volumeScaling,
2075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        notificationTime,
2076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        stopPosition,
2077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (const CodecInst*)codecInst) != 0)
2078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
2081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFile() failed to start file playout");
2082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->StopPlayingFile();
2083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
2085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2088944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetInputFilePlaying(true);
2089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(InStream* stream,
20949213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          FileFormats format,
20959213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          int startPosition,
20969213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          float volumeScaling,
20979213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                                          int stopPosition,
2098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const CodecInst* codecInst)
2099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileAsMicrophone(format=%d, "
2102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 format, volumeScaling, startPosition, stopPosition);
2104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(stream == NULL)
2106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
2109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone NULL as input stream");
2110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2113944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2114944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org
2115944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().input_file_playing)
2116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceWarning,
2119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() is playing");
2120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
2124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr)
2125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
2129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create the instance
2132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerId, (const FileFormats)format);
2134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr == NULL)
2136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingInputFile() filePlayer format isnot correct");
2140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
21436141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint32_t notificationTime(0);
2144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
2146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              volumeScaling, notificationTime,
2147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              stopPosition, codecInst) != 0)
2148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "StartPlayingFile() failed to start "
2151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "file playout");
2152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->StopPlayingFile();
2153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
2155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2157ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org
2158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2159944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetInputFilePlaying(true);
2160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileAsMicrophone()
2165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayingFileAsMicrophone()");
2168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2169944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2170944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org
2171944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().input_file_playing)
2172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
2175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFileAsMicrophone() isnot playing");
2176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StopPlayingFile() != 0)
2180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_STOP_RECORDING_FAILED, kTraceError,
2183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFile() could not stop playing");
2184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = NULL;
2189944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetInputFilePlaying(false);
2190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileAsMicrophone() const
2195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IsPlayingFileAsMicrophone()");
2198944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    return channel_state_.Get().input_file_playing;
2199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2201813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.orgint Channel::StartRecordingPlayout(const char* fileName,
2202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const CodecInst* codecInst)
2203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
2206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecording)
2208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StartRecordingPlayout() is already recording");
2211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileFormats format;
22156141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
2216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
221840197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org    if ((codecInst != NULL) &&
221940197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org      ((codecInst->channels < 1) || (codecInst->channels > 2)))
2220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
2223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() invalid compression");
2224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
2225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(codecInst == NULL)
2227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatPcm16kHzFile;
2229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        codecInst=&dummyCodec;
2230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatWavFile;
2236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
2238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatCompressedFile;
2240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
22429a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
2245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr)
2246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
2250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderId, (const FileFormats)format);
2254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr == NULL)
2255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() fileRecorder format isnot correct");
2259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StartRecordingAudioFile(
2263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
2264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
2267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingAudioFile() failed to start file recording");
2268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->StopRecording();
2269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
2271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = true;
2275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartRecordingPlayout(OutStream* stream,
2280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const CodecInst* codecInst)
2281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRecordingPlayout()");
2284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecording)
2286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StartRecordingPlayout() is already recording");
2289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileFormats format;
22936141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint32_t notificationTime(0); // Not supported in VoE
2294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (codecInst != NULL && codecInst->channels != 1)
2297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
2300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() invalid compression");
2301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
2302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(codecInst == NULL)
2304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatPcm16kHzFile;
2306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        codecInst=&dummyCodec;
2307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatWavFile;
2313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
2315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatCompressedFile;
2317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23199a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
2322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr)
2323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
2327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderId, (const FileFormats)format);
2331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr == NULL)
2332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() fileRecorder format isnot correct");
2336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
2340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        notificationTime) != 0)
2341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "StartRecordingPlayout() failed to "
2344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "start file recording");
2345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->StopRecording();
2346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
2348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2350ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org
2351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = true;
2353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopRecordingPlayout()
2358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
2360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopRecordingPlayout()");
2361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_outputFileRecording)
2363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
2365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StopRecordingPlayout() isnot recording");
2366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23709a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StopRecording() != 0)
2373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_STOP_RECORDING_FAILED, kTraceError,
2376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopRecording() could not stop recording");
2377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
2378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = NULL;
2382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = false;
2383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
2388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMixWithMicStatus(bool mix)
2389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2390944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
2391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mixFileWithMicrophone=mix;
2392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
23956141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::GetSpeechOutputLevel(uint32_t& level) const
2396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
23976141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    int8_t currentLevel = _outputAudioLevel.Level();
23986141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    level = static_cast<int32_t> (currentLevel);
2399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSpeechOutputLevel() => level=%u", level);
2402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
24066141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgChannel::GetSpeechOutputLevelFullRange(uint32_t& level) const
2407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
24086141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    int16_t currentLevel = _outputAudioLevel.LevelFullRange();
24096141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    level = static_cast<int32_t> (currentLevel);
2410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSpeechOutputLevelFullRange() => level=%u", level);
2413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMute(bool enable)
2418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
241963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetMute(enable=%d)", enable);
2422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mute = enable;
2423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
2427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Mute() const
2428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
242963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _mute;
2431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetOutputVolumePan(float left, float right)
2435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
243663420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetOutputVolumePan()");
2439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panLeft = left;
2440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panRight = right;
2441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetOutputVolumePan(float& left, float& right) const
2446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
244763420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    left = _panLeft;
2449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    right = _panRight;
2450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
2453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetChannelOutputVolumeScaling(float scaling)
2458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
245963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetChannelOutputVolumeScaling()");
2462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputGain = scaling;
2463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetChannelOutputVolumeScaling(float& scaling) const
2468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
246963420669746cfca6ed1d902c68c656b79ffa5a1bwu@webrtc.org    CriticalSectionScoped cs(&volume_settings_critsect_);
2470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    scaling = _outputGain;
2471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
2474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventOutband(unsigned char eventCode,
2478822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                       int lengthMs, int attenuationDb,
2479822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                       bool playDtmfEvent)
2480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
2483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               playDtmfEvent);
2484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playOutbandDtmfEvent = playDtmfEvent;
2486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
24872853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
2488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                 attenuationDb) != 0)
2489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SEND_DTMF_FAILED,
2492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kTraceWarning,
2493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendTelephoneEventOutband() failed to send event");
2494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventInband(unsigned char eventCode,
2500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         int lengthMs,
2501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         int attenuationDb,
2502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         bool playDtmfEvent)
2503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
2506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               playDtmfEvent);
2507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playInbandDtmfEvent = playDtmfEvent;
2509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
2510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendTelephoneEventPayloadType(unsigned char type)
2516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetSendTelephoneEventPayloadType()");
2519f81f9f8c2a18fb20ee60406ece45ff3210367ff9andrew@webrtc.org    if (type > 127)
2520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendTelephoneEventPayloadType() invalid type");
2524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
25265b10d8fb184db0192091bf407c8166b5d03b932epbos@webrtc.org    CodecInst codec = {};
25271da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    codec.plfreq = 8000;
25281da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    codec.pltype = type;
25291da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    memcpy(codec.plname, "telephone-event", 16);
25302853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
25324392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
25334392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
25344392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org            _engineStatisticsPtr->SetLastError(
25354392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
25364392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org                "SetSendTelephoneEventPayloadType() failed to register send"
25374392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org                "payload type");
25384392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org            return -1;
25394392d5f9f859b5d55b8017fafb09a496a110beb3henrika@webrtc.org        }
2540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _sendTelephoneEventPayloadType = type;
2542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendTelephoneEventPayloadType(unsigned char& type)
2547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSendTelephoneEventPayloadType()");
2550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    type = _sendTelephoneEventPayloadType;
2551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSendTelephoneEventPayloadType() => type=%u", type);
2554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateRxVadDetection(AudioFrame& audioFrame)
2559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::UpdateRxVadDetection()");
2562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int vadDecision = 1;
2564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
256563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
2566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
2568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        OnRxVadDetected(vadDecision);
2570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _oldVadDecision = vadDecision;
2571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::UpdateRxVadDetection() => vadDecision=%d",
2575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 vadDecision);
2576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterRxVadObserver(VoERxVadCallback &observer)
2581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterRxVadObserver()");
25849a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
2585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxVadObserverPtr)
2587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
2590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterRxVadObserver() observer already enabled");
2591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxVadObserverPtr = &observer;
2594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection = true;
2595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterRxVadObserver()
2600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterRxVadObserver()");
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, kTraceWarning,
2609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterRxVadObserver() observer already disabled");
2610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxVadObserverPtr = NULL;
2613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection = false;
2614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::VoiceActivityIndicator(int &activity)
2619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    activity = _sendFrameType;
2621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
26236c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org                 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
2624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_AGC
2628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
26309213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxAgcStatus(bool enable, AgcModes mode)
2631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
2634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enable, (int)mode);
2635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
26366c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org    GainControl::Mode agcMode = kDefaultRxAgcMode;
2637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
2638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcDefault:
2640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcUnchanged:
2642f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org            agcMode = rx_audioproc_->gain_control()->mode();
2643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcFixedDigital:
2645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode = GainControl::kFixedDigital;
2646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcAdaptiveDigital:
2648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode =GainControl::kAdaptiveDigital;
2649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
2651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRxAgcStatus() invalid Agc mode");
2654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2657f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->gain_control()->set_mode(agcMode) != 0)
2658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
2661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Agc mode");
2662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2664f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->gain_control()->Enable(enable) != 0)
2665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
2668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Agc state");
2669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxAgcIsEnabled = enable;
2673944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
2674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
2680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetRxAgcStatus(enable=?, mode=?)");
2683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2684f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    bool enable = rx_audioproc_->gain_control()->is_enabled();
2685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    GainControl::Mode agcMode =
2686f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->gain_control()->mode();
2687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = enable;
2689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (agcMode)
2691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case GainControl::kFixedDigital:
2693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kAgcFixedDigital;
2694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case GainControl::kAdaptiveDigital:
2696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kAgcAdaptiveDigital;
2697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
2699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_APM_ERROR, kTraceError,
2701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "GetRxAgcStatus() invalid Agc mode");
2702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
27099213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxAgcConfig(AgcConfig config)
2710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxAgcConfig()");
2713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2714f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->gain_control()->set_target_level_dbfs(
2715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.targetLeveldBOv) != 0)
2716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
2719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set target peak |level|"
2720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "(or envelope) of the Agc");
2721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2723f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->gain_control()->set_compression_gain_db(
2724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.digitalCompressionGaindB) != 0)
2725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
2728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set the range in |gain| the"
2729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            " digital compression stage may apply");
2730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2732f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->gain_control()->enable_limiter(
2733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.limiterEnable) != 0)
2734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
2737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set hard limiter to the signal");
2738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcConfig(AgcConfig& config)
2746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRxAgcConfig(config=%?)");
2749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.targetLeveldBOv =
2751f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->gain_control()->target_level_dbfs();
2752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.digitalCompressionGaindB =
2753f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->gain_control()->compression_gain_db();
2754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.limiterEnable =
2755f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->gain_control()->is_limiter_enabled();
2756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
2759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
2760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   " limiterEnable=%d",
2761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.targetLeveldBOv,
2762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.digitalCompressionGaindB,
2763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.limiterEnable);
2764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
2769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_NR
2771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
27739213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SetRxNsStatus(bool enable, NsModes mode)
2774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
2777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enable, (int)mode);
2778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
27796c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org    NoiseSuppression::Level nsLevel = kDefaultNsMode;
2780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
2781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsDefault:
2784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsUnchanged:
2786f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org            nsLevel = rx_audioproc_->noise_suppression()->level();
2787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsConference:
2789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kHigh;
2790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsLowSuppression:
2792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kLow;
2793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsModerateSuppression:
2795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kModerate;
2796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsHighSuppression:
2798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kHigh;
2799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsVeryHighSuppression:
2801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kVeryHigh;
2802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2805f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->noise_suppression()->set_level(nsLevel)
2806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        != 0)
2807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
28106c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org            "SetRxNsStatus() failed to set NS level");
2811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2813f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org    if (rx_audioproc_->noise_suppression()->Enable(enable) != 0)
2814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
28176c264cc92eb554716814db200b84752d4dfb6ba3andrew@webrtc.org            "SetRxNsStatus() failed to set NS state");
2818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxNsIsEnabled = enable;
2822944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
2823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxNsStatus(bool& enabled, NsModes& mode)
2829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRxNsStatus(enable=?, mode=?)");
2832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool enable =
2834f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->noise_suppression()->is_enabled();
2835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NoiseSuppression::Level ncLevel =
2836f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org        rx_audioproc_->noise_suppression()->level();
2837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = enable;
2839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (ncLevel)
2841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kLow:
2843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsLowSuppression;
2844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kModerate:
2846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsModerateSuppression;
2847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kHigh:
2849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsHighSuppression;
2850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kVeryHigh:
2852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsVeryHighSuppression;
2853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
2858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
2859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
2863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetLocalSSRC(unsigned int ssrc)
2866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetLocalSSRC()");
2869944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().sending)
2870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_SENDING, kTraceError,
2873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalSSRC() already sending");
2874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2876ef92755780253c6a7940c89598a206e58e05b810stefan@webrtc.org    _rtpRtcpModule->SetSSRC(ssrc);
2877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetLocalSSRC(unsigned int& ssrc)
2882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
28832853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    ssrc = _rtpRtcpModule->SSRC();
2884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
2886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetLocalSSRC() => ssrc=%lu", ssrc);
2887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteSSRC(unsigned int& ssrc)
2892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2893822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    ssrc = rtp_receiver_->SSRC();
2894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
2896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteSSRC() => ssrc=%lu", ssrc);
2897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2900ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
2901f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org  _includeAudioLevelIndication = enable;
2902ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
2903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2904f3930e941c15da48c037c62cdb1eebbcbf89c9c7andrew@webrtc.org
290593fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.orgint Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
290693fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org                                                  unsigned char id) {
290793fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org  rtp_header_parser_->DeregisterRtpHeaderExtension(
290893fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org      kRtpExtensionAudioLevel);
290993fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org  if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension(
291093fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org          kRtpExtensionAudioLevel, id)) {
291193fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org    return -1;
291293fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org  }
291393fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org  return 0;
291493fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org}
291593fd25c20c688961569d3631b875c8ee0dfc2a80wu@webrtc.org
2916ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
2917ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  return SetSendRtpHeaderExtension(enable, kRtpExtensionAbsoluteSendTime, id);
2918ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org}
2919ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org
2920ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
2921ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  rtp_header_parser_->DeregisterRtpHeaderExtension(
2922ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org      kRtpExtensionAbsoluteSendTime);
2923b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension(
2924b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org      kRtpExtensionAbsoluteSendTime, id)) {
2925b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    return -1;
2926ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  }
2927ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  return 0;
2928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2930d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid Channel::SetRTCPStatus(bool enable) {
2931d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2932d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org               "Channel::SetRTCPStatus()");
2933d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  _rtpRtcpModule->SetRTCPStatus(enable ? kRtcpCompound : kRtcpOff);
2934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTCPStatus(bool& enabled)
2938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
29392853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RTCPMethod method = _rtpRtcpModule->RTCP();
2940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = (method != kRtcpOff);
2941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
2943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTCPStatus() => enabled=%d", enabled);
2944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRTCP_CNAME(const char cName[256])
2949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRTCP_CNAME()");
29522853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetCNAME(cName) != 0)
2953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRTCP_CNAME() failed to set RTCP CNAME");
2957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCP_CNAME(char cName[256])
2964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (cName == NULL)
2966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
2969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
2970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2972813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char cname[RTCP_CNAME_SIZE];
2973822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    const uint32_t remoteSSRC = rtp_receiver_->SSRC();
29742853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
2975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_RETRIEVE_CNAME, kTraceError,
2978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
2979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    strcpy(cName, cname);
2982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
2984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCP_CNAME() => cName=%s", cName);
2985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
2989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCPData(
2990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& NTPHigh,
2991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& NTPLow,
2992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& timestamp,
2993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& playoutTimestamp,
2994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int* jitter,
2995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned short* fractionLost)
2996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Information from sender info in received Sender Reports
2998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RTCPSenderInfo senderInfo;
30002853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
3001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3004fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            "GetRemoteRTCPData() failed to retrieve sender info for remote "
3005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "side");
3006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // We only utilize 12 out of 20 bytes in the sender info (ignores packet
3010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // and octet count)
3011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NTPHigh = senderInfo.NTPseconds;
3012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NTPLow = senderInfo.NTPfraction;
3013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    timestamp = senderInfo.RTPtimeStamp;
3014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
3017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
3018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "timestamp=%lu",
3019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 NTPHigh, NTPLow, timestamp);
3020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Locally derived information
3022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This value is updated on each incoming RTCP packet (0 when no packet
3024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // has been received)
30251de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    playoutTimestamp = playout_timestamp_rtcp_;
3026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
3029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCPData() => playoutTimestamp=%lu",
30301de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                 playout_timestamp_rtcp_);
3031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (NULL != jitter || NULL != fractionLost)
3033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3034ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // Get all RTCP receiver report blocks that have been received on this
3035ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // channel. If we receive RTP packets from a remote source we know the
3036ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // remote SSRC and use the report block from him.
3037ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // Otherwise use the first report block.
3038ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        std::vector<RTCPReportBlock> remote_stats;
30392853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
3040ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org            remote_stats.empty()) {
3041ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3042ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       VoEId(_instanceId, _channelId),
3043ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       "GetRemoteRTCPData() failed to measure statistics due"
3044ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       " to lack of received RTP and/or RTCP packets");
3045ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          return -1;
3046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3047ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
3048822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        uint32_t remoteSSRC = rtp_receiver_->SSRC();
3049ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
3050ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        for (; it != remote_stats.end(); ++it) {
3051ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          if (it->remoteSSRC == remoteSSRC)
3052ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org            break;
3053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3054ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
3055ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        if (it == remote_stats.end()) {
3056ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // If we have not received any RTCP packets from this SSRC it probably
3057ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // means that we have not received any RTP packets.
3058ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // Use the first received report block instead.
3059ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          it = remote_stats.begin();
3060ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          remoteSSRC = it->remoteSSRC;
3061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3062ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
306379af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        if (jitter) {
306479af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          *jitter = it->jitter;
306579af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
306679af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       VoEId(_instanceId, _channelId),
306779af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       "GetRemoteRTCPData() => jitter = %lu", *jitter);
306879af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        }
3069ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
307079af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        if (fractionLost) {
307179af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          *fractionLost = it->fractionLost;
307279af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
307379af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       VoEId(_instanceId, _channelId),
307479af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       "GetRemoteRTCPData() => fractionLost = %lu",
307579af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       *fractionLost);
307679af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        }
3077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
30829213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::SendApplicationDefinedRTCPPacket(unsigned char subType,
3083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             unsigned int name,
3084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             const char* data,
3085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             unsigned short dataLengthInBytes)
3086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendApplicationDefinedRTCPPacket()");
3089944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (!channel_state_.Get().sending)
3090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NOT_SENDING, kTraceError,
3093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() not sending");
3094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (NULL == data)
3097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() invalid data value");
3101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (dataLengthInBytes % 4 != 0)
3104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() invalid length value");
3108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
31102853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RTCPMethod status = _rtpRtcpModule->RTCP();
3111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (status == kRtcpOff)
3112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTCP_ERROR, kTraceError,
3115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() RTCP is disabled");
3116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create and schedule the RTCP APP packet for transmission
31202853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
3121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        subType,
3122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        name,
3123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (const unsigned char*) data,
3124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        dataLengthInBytes) != 0)
3125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SEND_ERROR, kTraceError,
3128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
3129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics(
3136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& averageJitterMs,
3137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& maxJitterMs,
3138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& discardedPackets)
3139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The jitter statistics is updated for each received RTP packet and is
3141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // based on received packets.
314254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    if (_rtpRtcpModule->RTCP() == kRtcpOff) {
314354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      // If RTCP is off, there is no timed thread in the RTCP module regularly
314454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      // generating new stats, trigger the update manually here instead.
314554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      StreamStatistician* statistician =
314654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org          rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
314754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      if (statistician) {
314854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org        // Don't use returned statistics, use data from proxy instead so that
314954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org        // max jitter can be fetched atomically.
315054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org        RtcpStatistics s;
315154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org        statistician->GetStatistics(&s, true);
315254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      }
3153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
315554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    ChannelStatistics stats = statistics_proxy_->GetStats();
3156eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    const int32_t playoutFrequency = audio_coding_->PlayoutFrequency();
315754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    if (playoutFrequency > 0) {
315854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      // Scale RTP statistics given the current playout frequency
315954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      maxJitterMs = stats.max_jitter / (playoutFrequency / 1000);
316054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org      averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000);
3161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    discardedPackets = _numberOfDiscardedPackets;
3164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId, _channelId),
3167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
3168fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org               " discardedPackets = %lu)",
3169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               averageJitterMs, maxJitterMs, discardedPackets);
3170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
31738a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.orgint Channel::GetRemoteRTCPReportBlocks(
31748a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    std::vector<ReportBlock>* report_blocks) {
31758a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (report_blocks == NULL) {
31768a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
31778a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org      "GetRemoteRTCPReportBlock()s invalid report_blocks.");
31788a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
31798a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
31808a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
31818a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // Get the report blocks from the latest received RTCP Sender or Receiver
31828a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // Report. Each element in the vector contains the sender's SSRC and a
31838a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // report block according to RFC 3550.
31848a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  std::vector<RTCPReportBlock> rtcp_report_blocks;
31858a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
31868a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
31878a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org        "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
31888a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
31898a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
31908a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
31918a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (rtcp_report_blocks.empty())
31928a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return 0;
31938a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
31948a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
31958a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  for (; it != rtcp_report_blocks.end(); ++it) {
31968a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    ReportBlock report_block;
31978a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.sender_SSRC = it->remoteSSRC;
31988a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.source_SSRC = it->sourceSSRC;
31998a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.fraction_lost = it->fractionLost;
32008a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.cumulative_num_packets_lost = it->cumulativeLost;
32018a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
32028a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.interarrival_jitter = it->jitter;
32038a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.last_SR_timestamp = it->lastSR;
32048a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.delay_since_last_SR = it->delaySinceLastSR;
32058a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_blocks->push_back(report_block);
32068a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
32078a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  return 0;
32088a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org}
32098a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
3210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics(CallStatistics& stats)
3212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3213cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    // --- RtcpStatistics
3214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The jitter statistics is updated for each received RTP packet and is
3216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // based on received packets.
321754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org    RtcpStatistics statistics;
3218286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    StreamStatistician* statistician =
3219286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org        rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
3220286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    if (!statistician || !statistician->GetStatistics(
3221822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org        &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
3222822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org      _engineStatisticsPtr->SetLastError(
3223822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org          VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
3224822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org          "GetRTPStatistics() failed to read RTP statistics from the "
3225822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org          "RTP/RTCP module");
3226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3228822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    stats.fractionLost = statistics.fraction_lost;
3229822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    stats.cumulativeLost = statistics.cumulative_lost;
3230822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    stats.extendedMax = statistics.extended_max_sequence_number;
3231822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    stats.jitterSamples = statistics.jitter;
3232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
3235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
3236fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " extendedMax=%lu, jitterSamples=%li)",
3237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
3238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.jitterSamples);
3239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3240cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    // --- RTT
32412b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    stats.rttMs = GetRTT();
32426fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org    if (stats.rttMs == 0) {
32436fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org      WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
32446fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org                   "GetRTPStatistics() failed to get RTT");
32456fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org    } else {
32466fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org      WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
324716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org                   "GetRTPStatistics() => rttMs=%" PRId64, stats.rttMs);
32486fd930842055525b5c7cff412735515dd463571aminyue@webrtc.org    }
3249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3250cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    // --- Data counters
3251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
32524591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t bytesSent(0);
32536141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    uint32_t packetsSent(0);
32544591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t bytesReceived(0);
32556141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    uint32_t packetsReceived(0);
3256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3257286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    if (statistician) {
3258286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org      statistician->GetDataCounters(&bytesReceived, &packetsReceived);
3259286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    }
3260822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org
32612853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
3262822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                                        &packetsSent) != 0)
3263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
3266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "GetRTPStatistics() failed to retrieve RTP datacounters =>"
3267fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                     " output will not be complete");
3268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.bytesSent = bytesSent;
3271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.packetsSent = packetsSent;
3272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.bytesReceived = bytesReceived;
3273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.packetsReceived = packetsReceived;
3274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
32774591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 "GetRTPStatistics() => bytesSent=%" PRIuS ", packetsSent=%d,"
32784591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                 " bytesReceived=%" PRIuS ", packetsReceived=%d)",
3279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
3280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.packetsReceived);
3281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3282cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    // --- Timestamps
3283cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    {
3284cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org      CriticalSectionScoped lock(ts_stats_lock_.get());
3285cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org      stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
3286cb711f77d2ff9ebd42678869a73353809b3af66ewu@webrtc.org    }
3287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3290c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint Channel::SetREDStatus(bool enable, int redPayloadtype) {
329142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3292c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org               "Channel::SetREDStatus()");
329342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
32948c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org  if (enable) {
32958c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org    if (redPayloadtype < 0 || redPayloadtype > 127) {
32968c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org      _engineStatisticsPtr->SetLastError(
32978c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org          VE_PLTYPE_ERROR, kTraceError,
3298c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org          "SetREDStatus() invalid RED payload type");
32998c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org      return -1;
33008c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org    }
33018c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org
33028c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org    if (SetRedPayloadType(redPayloadtype) < 0) {
33038c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org      _engineStatisticsPtr->SetLastError(
33048c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org          VE_CODEC_ERROR, kTraceError,
33058c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org          "SetSecondarySendCodec() Failed to register RED ACM");
33068c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org      return -1;
33078c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org    }
330842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
33092cf22a6abce2d38e673505a4cfd5624a3710b5cdperkj@webrtc.org
3310aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org  if (audio_coding_->SetREDStatus(enable) != 0) {
331142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
331242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
3313aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org        "SetREDStatus() failed to set RED state in the ACM");
331442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
331542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
331642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
3317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3320c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgChannel::GetREDStatus(bool& enabled, int& redPayloadtype)
3321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3322aa5ea1c0f9d0df583ae0f791f6715a0764aff3cfminyue@webrtc.org    enabled = audio_coding_->REDStatus();
3323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enabled)
3324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
33256141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        int8_t payloadType(0);
33262853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
3327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
3329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3330c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org                "GetREDStatus() failed to retrieve RED PT from RTP/RTCP "
3331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "module");
3332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3334df9a41d2701d321dbc987201ec7cffe2a16bd2c4pkasting@chromium.org        redPayloadtype = payloadType;
3335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   VoEId(_instanceId, _channelId),
3337c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org                   "GetREDStatus() => enabled=%d, redPayloadtype=%d",
3338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   enabled, redPayloadtype);
3339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
3343c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org                 "GetREDStatus() => enabled=%d", enabled);
3344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3347c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgint Channel::SetCodecFECStatus(bool enable) {
3348c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3349c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org               "Channel::SetCodecFECStatus()");
3350c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
3351c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  if (audio_coding_->SetCodecFEC(enable) != 0) {
3352c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    _engineStatisticsPtr->SetLastError(
3353c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
3354c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org        "SetCodecFECStatus() failed to set FEC state");
3355c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org    return -1;
3356c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  }
3357c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  return 0;
3358c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}
3359c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
3360c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.orgbool Channel::GetCodecFECStatus() {
3361c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  bool enabled = audio_coding_->CodecFEC();
3362c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3363c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org               VoEId(_instanceId, _channelId),
3364c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org               "GetCodecFECStatus() => enabled=%d", enabled);
3365c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org  return enabled;
3366c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org}
3367c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
3368db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.orgvoid Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
3369db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org  // None of these functions can fail.
3370db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org  _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
33717bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
33727bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org  rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
3373d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org  if (enable)
3374eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    audio_coding_->EnableNack(maxNumberOfPackets);
3375d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org  else
3376eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    audio_coding_->DisableNack();
3377db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org}
3378db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org
3379d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.org// Called when we are missing one or more packets.
3380d30859e58e2c0b0676ab2b52b8a2723e10d49e28pwestin@webrtc.orgint Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
3381db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org  return _rtpRtcpModule->SendNACK(sequence_numbers, length);
3382db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org}
3383db249956807d916729aacfaf3382923e8239d533pwestin@webrtc.org
3384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartRTPDump(const char fileNameUTF8[1024],
3386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      RTPDirections direction)
3387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRTPDump()");
3390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
3391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRTPDump() invalid RTP direction");
3395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
3399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr == NULL)
3400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        assert(false);
3402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr->IsActive())
3405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rtpDumpPtr->Stop();
3407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr->Start(fileNameUTF8) != 0)
3409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRTPDump() failed to create file");
3413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopRTPDump(RTPDirections direction)
3420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopRTPDump()");
3423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
3424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopRTPDump() invalid RTP direction");
3428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
3432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr == NULL)
3433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        assert(false);
3435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!rtpDumpPtr->IsActive())
3438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return rtpDumpPtr->Stop();
3442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
3445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RTPDumpIsActive(RTPDirections direction)
3446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) &&
3448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (direction != kRtpOutgoing))
3449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RTPDumpIsActive() invalid RTP direction");
3453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return false;
3454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
3457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return rtpDumpPtr->IsActive();
3458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3460b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.orgvoid Channel::SetVideoEngineBWETarget(ViENetwork* vie_network,
3461b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org                                      int video_channel) {
3462b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  CriticalSectionScoped cs(&_callbackCritSect);
3463b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  if (vie_network_) {
3464b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    vie_network_->Release();
3465b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    vie_network_ = NULL;
3466b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  }
3467b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  video_channel_ = -1;
3468b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org
3469b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  if (vie_network != NULL && video_channel != -1) {
3470b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    vie_network_ = vie_network;
3471b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org    video_channel_ = video_channel;
3472b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org  }
3473b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org}
3474b1f50100757036cf475072c26f5f374eee9588casolenberg@webrtc.org
34756141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t
3476755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.orgChannel::Demultiplex(const AudioFrame& audioFrame)
3477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3479755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                 "Channel::Demultiplex()");
3480ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org    _audioFrame.CopyFrom(audioFrame);
348163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.id_ = _channelId;
3482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
34852f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.orgvoid Channel::Demultiplex(const int16_t* audio_data,
34868fff1f065ea9d25970c3839294acdd606a5ddf22xians@webrtc.org                          int sample_rate,
34872f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org                          int number_of_frames,
34888fff1f065ea9d25970c3839294acdd606a5ddf22xians@webrtc.org                          int number_of_channels) {
34892f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org  CodecInst codec;
34902f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org  GetSendCodec(codec);
34912f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org
349240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  if (!mono_recording_audio_.get()) {
349340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    // Temporary space for DownConvertToCodecFormat.
349440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org    mono_recording_audio_.reset(new int16_t[kMaxMonoDataSizeSamples]);
34952f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org  }
349640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org  DownConvertToCodecFormat(audio_data,
349740ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           number_of_frames,
349840ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           number_of_channels,
349940ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           sample_rate,
350040ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           codec.channels,
350140ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           codec.plfreq,
350240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           mono_recording_audio_.get(),
350340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           &input_resampler_,
350440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                           &_audioFrame);
35052f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org}
35062f84afad30b088ddebb4063bc47ac9a79d735a2bxians@webrtc.org
35076141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t
35080b0665acc1464d68e878f203bbc8772a0e32402dxians@google.comChannel::PrepareEncodeAndSend(int mixingFrequency)
3509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PrepareEncodeAndSend()");
3512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
351363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (_audioFrame.samples_per_channel_ == 0)
3514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PrepareEncodeAndSend() invalid audio frame");
3517eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org        return 0xFFFFFFFF;
3518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3520944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().input_file_playing)
3521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        MixOrReplaceAudioWithFile(mixingFrequency);
3523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
352521299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org    bool is_muted = Mute();  // Cache locally as Mute() takes a lock.
352621299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org    if (is_muted) {
352721299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org      AudioFrameOperations::Mute(_audioFrame);
3528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3530944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().input_external_media)
3531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
35329a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
353363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        const bool isStereo = (_audioFrame.num_channels_ == 2);
3534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputExternalMediaCallbackPtr)
3535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputExternalMediaCallbackPtr->Process(
3537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId,
3538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                kRecordingPerChannel,
35396141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org               (int16_t*)_audioFrame.data_,
354063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                _audioFrame.samples_per_channel_,
354163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                _audioFrame.sample_rate_hz_,
3542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                isStereo);
3543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    InsertInbandDtmfTone();
3547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
354860730cfe3ce80e4023cd678373456cb703f000a4andrew@webrtc.org    if (_includeAudioLevelIndication) {
3549382c0c209d323c1e6972d988a7b26f08fc2e8a6bandrew@webrtc.org      int length = _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
355021299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org      if (is_muted) {
355121299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org        rms_level_.ProcessMuted(length);
355221299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org      } else {
355321299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org        rms_level_.Process(_audioFrame.data_, length);
355421299d4e00781e199a53ba33ec192cdce920acecandrew@webrtc.org      }
3555755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    }
3556755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
3557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
35606141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orguint32_t
3561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EncodeAndSend()
3562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::EncodeAndSend()");
3565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
356663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    assert(_audioFrame.num_channels_ <= 2);
356763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (_audioFrame.samples_per_channel_ == 0)
3568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::EncodeAndSend() invalid audio frame");
3571eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org        return 0xFFFFFFFF;
3572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
357463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.id_ = _channelId;
3575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
3577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The ACM resamples internally.
357963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.timestamp_ = _timeStamp;
3580f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    // This call will trigger AudioPacketizationCallback::SendData if encoding
3581f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    // is done and payload is ready for packetization and transmission.
3582f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    // Otherwise, it will return without invoking the callback.
3583f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0)
3584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::EncodeAndSend() ACM encoding failed");
3587eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org        return 0xFFFFFFFF;
3588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
359063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _timeStamp += _audioFrame.samples_per_channel_;
3591f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    return 0;
3592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::RegisterExternalMediaProcessing(
3595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ProcessingTypes type,
3596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    VoEMediaProcess& processObject)
3597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterExternalMediaProcessing()");
3600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36019a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
3602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (kPlaybackPerChannel == type)
3604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputExternalMediaCallbackPtr)
3606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
3608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceError,
3609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::RegisterExternalMediaProcessing() "
3610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already enabled");
3611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMediaCallbackPtr = &processObject;
3614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMedia = true;
3615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (kRecordingPerChannel == type)
3617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputExternalMediaCallbackPtr)
3619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
3621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceError,
3622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::RegisterExternalMediaProcessing() "
3623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already enabled");
3624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMediaCallbackPtr = &processObject;
3627944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetInputExternalMedia(true);
3628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
3633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterExternalMediaProcessing()");
3636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36379a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
3638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (kPlaybackPerChannel == type)
3640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!_outputExternalMediaCallbackPtr)
3642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
3644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceWarning,
3645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::DeRegisterExternalMediaProcessing() "
3646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already disabled");
3647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
3648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMedia = false;
3650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMediaCallbackPtr = NULL;
3651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (kRecordingPerChannel == type)
3653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!_inputExternalMediaCallbackPtr)
3655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
3657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceWarning,
3658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::DeRegisterExternalMediaProcessing() "
3659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "input external media already disabled");
3660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
3661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3662944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org        channel_state_.SetInputExternalMedia(false);
3663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMediaCallbackPtr = NULL;
3664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36691b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.comint Channel::SetExternalMixing(bool enabled) {
36701b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
36711b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com                 "Channel::SetExternalMixing(enabled=%d)", enabled);
36721b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
3673944cbeb2926feb86a687e5fda9e2ac88ea8e3001henrika@webrtc.org    if (channel_state_.Get().playing)
36741b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    {
36751b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        _engineStatisticsPtr->SetLastError(
36761b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            VE_INVALID_OPERATION, kTraceError,
36771b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            "Channel::SetExternalMixing() "
36781b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com            "external mixing cannot be changed while playing.");
36791b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com        return -1;
36801b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    }
36811b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
36821b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    _externalMixing = enabled;
36831b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
36841b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com    return 0;
36851b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com}
36861b60ceb499ee35460886f2bfaecee1f47319f925roosa@google.com
3687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetNetworkStatistics(NetworkStatistics& stats)
3689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetNetworkStatistics()");
3692c0bd7be0df67735d63f5cdd302a3b85f88239874minyue@webrtc.org    return audio_coding_->GetNetworkStatistics(&stats);
3693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
369524301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.orgvoid Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
369624301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org  audio_coding_->GetDecodingCallStatistics(stats);
369724301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org}
369824301a67c66e6091418e83da49cfb367ef2c6645wu@webrtc.org
36991de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgbool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms,
37001de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                               int* playout_buffer_delay_ms) const {
37011de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (_average_jitter_buffer_delay_us == 0) {
3702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
37031de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                 "Channel::GetDelayEstimate() no valid estimate.");
37041de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    return false;
37051de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
37061de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  *jitter_buffer_delay_ms = (_average_jitter_buffer_delay_us + 500) / 1000 +
37071de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org      _recPacketDelayMs;
37081de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  *playout_buffer_delay_ms = playout_delay_ms_;
37091de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
37101de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               "Channel::GetDelayEstimate()");
37111de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  return true;
3712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
37146388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.orgint Channel::SetInitialPlayoutDelay(int delay_ms)
37156388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org{
37166388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
37176388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org               "Channel::SetInitialPlayoutDelay()");
37186388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
37196388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org      (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs))
37206388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  {
37216388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
37226388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org        VE_INVALID_ARGUMENT, kTraceError,
37236388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org        "SetInitialPlayoutDelay() invalid min delay");
37246388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org    return -1;
37256388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  }
3726eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org  if (audio_coding_->SetInitialPlayoutDelay(delay_ms) != 0)
37276388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  {
37286388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
37296388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
37306388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org        "SetInitialPlayoutDelay() failed to set min playout delay");
37316388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org    return -1;
37326388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  }
37336388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org  return 0;
37346388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org}
37356388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org
37366388c3e2fdfc91b3648fb7d408a14ddb25e41cd1turaj@webrtc.org
3737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMinimumPlayoutDelay(int delayMs)
3739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetMinimumPlayoutDelay()");
3742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
3743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
3744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetMinimumPlayoutDelay() invalid min delay");
3748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3750eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0)
3751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
3754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetMinimumPlayoutDelay() failed to set min playout delay");
3755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
37601de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgvoid Channel::UpdatePlayoutTimestamp(bool rtcp) {
37611de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  uint32_t playout_timestamp = 0;
37621de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
3763eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org  if (audio_coding_->PlayoutTimestamp(&playout_timestamp) == -1)  {
37641ebd2e96df5b6d1c30d18b3ce8b928f99666c53fturaj@webrtc.org    // This can happen if this channel has not been received any RTP packet. In
37651ebd2e96df5b6d1c30d18b3ce8b928f99666c53fturaj@webrtc.org    // this case, NetEq is not capable of computing playout timestamp.
37661de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    return;
37671de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
37681de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
37691de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  uint16_t delay_ms = 0;
37701de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
37711de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
37721de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                 "Channel::UpdatePlayoutTimestamp() failed to read playout"
37731de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                 " delay from the ADM");
37741de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    _engineStatisticsPtr->SetLastError(
37751de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org        VE_CANNOT_RETRIEVE_VALUE, kTraceError,
37761de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org        "UpdatePlayoutTimestamp() failed to retrieve playout delay");
37771de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    return;
37781de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
37791de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
3780167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org  jitter_buffer_playout_timestamp_ = playout_timestamp;
3781167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org
37821de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // Remove the playout delay.
378394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  playout_timestamp -= (delay_ms * (GetPlayoutFrequency() / 1000));
37841de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
37851de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
37861de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
37871de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               playout_timestamp);
37881de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
37891de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (rtcp) {
37901de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    playout_timestamp_rtcp_ = playout_timestamp;
37911de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  } else {
37921de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    playout_timestamp_rtp_ = playout_timestamp;
37931de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
37941de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  playout_delay_ms_ = delay_ms;
37951de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org}
37961de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
37971de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgint Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
37981de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
37991de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               "Channel::GetPlayoutTimestamp()");
38001de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (playout_timestamp_rtp_ == 0)  {
38011de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    _engineStatisticsPtr->SetLastError(
38021de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org        VE_CANNOT_RETRIEVE_VALUE, kTraceError,
38031de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org        "GetPlayoutTimestamp() failed to retrieve timestamp");
38041de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    return -1;
38051de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
38061de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  timestamp = playout_timestamp_rtp_;
38071de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
38081de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               VoEId(_instanceId,_channelId),
38091de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               "GetPlayoutTimestamp() => timestamp=%u", timestamp);
38101de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  return 0;
3811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3813d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint Channel::SetInitTimestamp(unsigned int timestamp) {
3814d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetInitTimestamp()");
3816d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  if (channel_state_.Get().sending) {
3817d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    _engineStatisticsPtr->SetLastError(VE_SENDING, kTraceError,
3818d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                       "SetInitTimestamp() already sending");
3819d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    return -1;
3820d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  }
3821d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  _rtpRtcpModule->SetStartTimestamp(timestamp);
3822d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  return 0;
3823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3825d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint Channel::SetInitSequenceNumber(short sequenceNumber) {
3826d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3827d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org               "Channel::SetInitSequenceNumber()");
3828d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  if (channel_state_.Get().sending) {
3829d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    _engineStatisticsPtr->SetLastError(
3830d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org        VE_SENDING, kTraceError, "SetInitSequenceNumber() already sending");
3831d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    return -1;
3832d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  }
3833d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  _rtpRtcpModule->SetSequenceNumber(sequenceNumber);
3834d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  return 0;
3835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3838822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgChannel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const
3839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRtpRtcp()");
3842822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    *rtpRtcpModule = _rtpRtcpModule.get();
3843822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org    *rtp_receiver = rtp_receiver_.get();
3844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3847e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
3848e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// a shared helper.
38496141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
38509213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.orgChannel::MixOrReplaceAudioWithFile(int mixingFrequency)
3851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
385200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]);
3853e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org    int fileSamples(0);
3854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
38569a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
3857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputFilePlayerPtr == NULL)
3859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
3862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() fileplayer"
3863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             " doesnt exist");
3864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3867d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
3868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                      fileSamples,
3869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                      mixingFrequency) == -1)
3870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
3873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() file mixing "
3874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "failed");
3875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (fileSamples == 0)
3878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
3881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() file is ended");
3882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
3883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
388663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    assert(_audioFrame.samples_per_channel_ == fileSamples);
3887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_mixFileWithMicrophone)
3889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3890d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
3891d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
389240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        MixWithSat(_audioFrame.data_,
389340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   _audioFrame.num_channels_,
389440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileBuffer.get(),
389540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   1,
389640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileSamples);
3897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
3899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3900d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Replace ACM audio with file.
3901d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
3902d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
3903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _audioFrame.UpdateFrame(_channelId,
3904eec6ecdb1e249871dd25d04b62fc9ddc03dc8a34tommi@webrtc.org                                0xFFFFFFFF,
3905d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                                fileBuffer.get(),
3906e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                                fileSamples,
3907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                mixingFrequency,
3908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                AudioFrame::kNormalSpeech,
3909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                AudioFrame::kVadUnknown,
3910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                1);
3911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
39166141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
3917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::MixAudioWithFile(AudioFrame& audioFrame,
39189213521ea98b0977c7cdabd2853060835af226f3pbos@webrtc.org                          int mixingFrequency)
3919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
39202a8df7c375c73a3f477ee5cd9d85336a98f57ee2minyue@webrtc.org    assert(mixingFrequency <= 48000);
3921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
392200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<int16_t[]> fileBuffer(new int16_t[960]);
3923e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org    int fileSamples(0);
3924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
39269a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
3927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFilePlayerPtr == NULL)
3929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
3932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixAudioWithFile() file mixing failed");
3933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // We should get the frequency we ask for.
3937d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
3938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       fileSamples,
3939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       mixingFrequency) == -1)
3940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
3943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixAudioWithFile() file mixing failed");
3944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
394863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (audioFrame.samples_per_channel_ == fileSamples)
3949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3950d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
3951d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
395240ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org        MixWithSat(audioFrame.data_,
395340ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   audioFrame.num_channels_,
395440ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileBuffer.get(),
395540ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   1,
395640ee3d07eda24b8e8214429d9885d9ad9a2c04f7andrew@webrtc.org                   fileSamples);
3957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
3959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
396163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
3962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "fileSamples(%d)",
396363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            audioFrame.samples_per_channel_, fileSamples);
3964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
3971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::InsertInbandDtmfTone()
3972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3973af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org    // Check if we should start a new tone.
3974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inbandDtmfQueue.PendingDtmf() &&
3975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        !_inbandDtmfGenerator.IsAddingTone() &&
3976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.DelaySinceLastTone() >
3977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        kMinTelephoneEventSeparationMs)
3978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
39796141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        int8_t eventCode(0);
39806141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        uint16_t lengthMs(0);
39816141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        uint8_t attenuationDb(0);
3982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
3984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
3985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_playInbandDtmfEvent)
3986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Add tone to output mixer using a reduced length to minimize
3988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // risk of echo.
3989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
3990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          attenuationDb);
3991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inbandDtmfGenerator.IsAddingTone())
3995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
39966141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        uint16_t frequency(0);
3997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.GetSampleRate(frequency);
3998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
399963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (frequency != _audioFrame.sample_rate_hz_)
4000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Update sample rate of Dtmf tone since the mixing frequency
4002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // has changed.
4003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandDtmfGenerator.SetSampleRate(
40046141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org                (uint16_t) (_audioFrame.sample_rate_hz_));
4005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Reset the tone to be added taking the new sample rate into
4006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // account.
4007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandDtmfGenerator.ResetTone();
4008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4009ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org
40106141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        int16_t toneBuffer[320];
40116141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org        uint16_t toneSamples(0);
4012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Get 10ms tone segment and set time since last tone to zero
4013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
4014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       VoEId(_instanceId, _channelId),
4017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       "Channel::EncodeAndSend() inserting Dtmf failed");
4018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
4019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4021af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        // Replace mixed audio with DTMF tone.
4022ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org        for (int sample = 0;
402363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            sample < _audioFrame.samples_per_channel_;
4024af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            sample++)
4025af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        {
4026ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org            for (int channel = 0;
4027ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org                channel < _audioFrame.num_channels_;
4028af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org                channel++)
4029af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            {
4030ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org                const int index = sample * _audioFrame.num_channels_ + channel;
4031ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org                _audioFrame.data_[index] = toneBuffer[sample];
4032af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            }
4033af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        }
4034ae1a58bba4f926d149a5f39243269c3f6625f494andrew@webrtc.org
403563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        assert(_audioFrame.samples_per_channel_ == toneSamples);
4036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else
4037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Add 10ms to "delay-since-last-tone" counter
4039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.UpdateDelaySinceLastTone();
4040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40446141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.orgint32_t
40454591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.orgChannel::SendPacketRaw(const void *data, size_t len, bool RTCP)
4046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4047fb648da2b9d33e8641c88a7f0559508539104b6dwu@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_transportPtr == NULL)
4049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!RTCP)
4053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return _transportPtr->SendPacket(_channelId, data, len);
4055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
4057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return _transportPtr->SendRTCPPacket(_channelId, data, len);
4059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40621de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org// Called for incoming RTP packets after successful RTP header parsing.
40631de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.orgvoid Channel::UpdatePacketDelay(uint32_t rtp_timestamp,
40641de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org                                uint16_t sequence_number) {
40651de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
40661de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
40671de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org               rtp_timestamp, sequence_number);
4068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40691de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // Get frequency of last received payload
407094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  int rtp_receive_frequency = GetPlayoutFrequency();
4071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4072e46c8d387587ba148e229a7bb18f1cc0708a2a87turaj@webrtc.org  // Update the least required delay.
4073eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org  least_required_delay_ms_ = audio_coding_->LeastRequiredDelayMs();
4074e46c8d387587ba148e229a7bb18f1cc0708a2a87turaj@webrtc.org
4075167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org  // |jitter_buffer_playout_timestamp_| updated in UpdatePlayoutTimestamp for
4076167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org  // every incoming packet.
4077167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org  uint32_t timestamp_diff_ms = (rtp_timestamp -
4078167b6dfc73fc2f4c47713bcbd89b58c52612983bturaj@webrtc.org      jitter_buffer_playout_timestamp_) / (rtp_receive_frequency / 1000);
4079d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org  if (!IsNewerTimestamp(rtp_timestamp, jitter_buffer_playout_timestamp_) ||
4080d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org      timestamp_diff_ms > (2 * kVoiceEngineMaxMinPlayoutDelayMs)) {
4081d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org    // If |jitter_buffer_playout_timestamp_| is newer than the incoming RTP
4082d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org    // timestamp, the resulting difference is negative, but is set to zero.
4083d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org    // This can happen when a network glitch causes a packet to arrive late,
4084d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org    // and during long comfort noise periods with clock drift.
4085d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org    timestamp_diff_ms = 0;
4086d66929995ff62e92c6cb5177d059e85b902fd388henrik.lundin@webrtc.org  }
4087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40881de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  uint16_t packet_delay_ms = (rtp_timestamp - _previousTimestamp) /
40891de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org      (rtp_receive_frequency / 1000);
4090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40911de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  _previousTimestamp = rtp_timestamp;
4092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40931de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (timestamp_diff_ms == 0) return;
40941de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
40951de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (packet_delay_ms >= 10 && packet_delay_ms <= 60) {
40961de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    _recPacketDelayMs = packet_delay_ms;
40971de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
40981de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
40991de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  if (_average_jitter_buffer_delay_us == 0) {
41001de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    _average_jitter_buffer_delay_us = timestamp_diff_ms * 1000;
41011de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org    return;
41021de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  }
41031de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org
41041de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // Filter average delay value using exponential filter (alpha is
41051de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // 7/8). We derive 1000 *_average_jitter_buffer_delay_us here (reduces
41061de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // risk of rounding error) and compensate for it in GetDelayEstimate()
41071de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  // later.
41081de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org  _average_jitter_buffer_delay_us = (_average_jitter_buffer_delay_us * 7 +
41091de01354e68da71bc62c81af17afeac8ed374a18pwestin@webrtc.org      1000 * timestamp_diff_ms + 500) / 8;
4110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
4113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterReceiveCodecsToRTPModule()
4114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterReceiveCodecsToRTPModule()");
4117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
41206141e13873d0fdea626de08dfec2efa2c9171c76pbos@webrtc.org    const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
4121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (int idx = 0; idx < nSupportedCodecs; idx++)
4123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Open up the RTP/RTCP receiver for all supported codecs
4125eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org        if ((audio_coding_->Codec(idx, &codec) == -1) ||
4126822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org            (rtp_receiver_->RegisterReceivePayload(
4127822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.plname,
4128822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.pltype,
4129822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.plfreq,
4130822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                codec.channels,
4131822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org                (codec.rate < 0) ? 0 : codec.rate) == -1))
4132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
4134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceWarning,
4135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceVoice,
4136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
4137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::RegisterReceiveCodecsToRTPModule() unable"
4138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
4139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
4140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
4141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
4143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
4145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceInfo,
4146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceVoice,
4147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
4148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::RegisterReceiveCodecsToRTPModule() %s "
4149fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                         "(%d/%d/%d/%d) has been added to the RTP/RTCP "
4150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "receiver",
4151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
4152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
4153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
41578c8ad85c5d70c38cea82f5b17794a4e7ab4cf531turaj@webrtc.org// Assuming this method is called with valid payload type.
415842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::SetRedPayloadType(int red_payload_type) {
415942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  CodecInst codec;
416042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  bool found_red = false;
416142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
416242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  // Get default RED settings from the ACM database
416342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  const int num_codecs = AudioCodingModule::NumberOfCodecs();
416442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  for (int idx = 0; idx < num_codecs; idx++) {
4165eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org    audio_coding_->Codec(idx, &codec);
416642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    if (!STR_CASE_CMP(codec.plname, "RED")) {
416742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org      found_red = true;
416842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org      break;
416942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    }
417042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
417142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
417242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (!found_red) {
417342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
417442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_CODEC_ERROR, kTraceError,
417542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED is not supported");
417642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
417742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
417842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
41799d532fd2752290e85aa804f29ab9aa6c017c9208turaj@webrtc.org  codec.pltype = red_payload_type;
4180eb524d997b877ba9b0bcaf8c85eae52bd40c37e3andrew@webrtc.org  if (audio_coding_->RegisterSendCodec(codec) < 0) {
418142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
418242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
418342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED registration in ACM module failed");
418442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
418542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
418642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
418742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
418842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
418942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_RTP_RTCP_MODULE_ERROR, kTraceError,
419042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED registration in RTP/RTCP module failed");
419142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
419242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
419342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
419442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org}
419542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
4196ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.orgint Channel::SetSendRtpHeaderExtension(bool enable, RTPExtensionType type,
4197ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org                                       unsigned char id) {
4198ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  int error = 0;
4199ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
4200ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  if (enable) {
4201ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org    error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
4202ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  }
4203ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org  return error;
4204ebdb0e3ad0a787bee066d12cdcd115a38b0a10d1wu@webrtc.org}
4205c1a40a7b68a8d253b0ba32b89f3126931eeaeab3minyue@webrtc.org
420694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.orgint32_t Channel::GetPlayoutFrequency() {
420794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  int32_t playout_frequency = audio_coding_->PlayoutFrequency();
420894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  CodecInst current_recive_codec;
420994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  if (audio_coding_->ReceiveCodec(&current_recive_codec) == 0) {
421094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) {
421194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // Even though the actual sampling rate for G.722 audio is
421294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // 16,000 Hz, the RTP clock rate for the G722 payload format is
421394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // 8,000 Hz because that value was erroneously assigned in
421494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // RFC 1890 and must remain unchanged for backward compatibility.
421594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      playout_frequency = 8000;
421694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) {
421794454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // We are resampling Opus internally to 32,000 Hz until all our
421894454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // DSP routines can operate at 48,000 Hz, but the RTP clock
421994454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // rate for the Opus payload format is standardized to 48,000 Hz,
422094454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      // because that is the maximum supported decoding sampling rate.
422194454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org      playout_frequency = 48000;
422294454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org    }
422394454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  }
422494454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org  return playout_frequency;
422594454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org}
422694454b71adc37e15fd3f5a5fc432063f05caabcbwu@webrtc.org
422716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint64_t Channel::GetRTT() const {
42282b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  RTCPMethod method = _rtpRtcpModule->RTCP();
42292b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  if (method == kRtcpOff) {
42302b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    return 0;
42312b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  }
42322b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  std::vector<RTCPReportBlock> report_blocks;
42332b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
42342b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  if (report_blocks.empty()) {
42352b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    return 0;
42362b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  }
42372b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org
42382b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  uint32_t remoteSSRC = rtp_receiver_->SSRC();
42392b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
42402b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  for (; it != report_blocks.end(); ++it) {
42412b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    if (it->remoteSSRC == remoteSSRC)
42422b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org      break;
42432b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  }
42442b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  if (it == report_blocks.end()) {
42452b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    // We have not received packets with SSRC matching the report blocks.
42462b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    // To calculate RTT we try with the SSRC of the first report block.
42472b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    // This is very important for send-only channels where we don't know
42482b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    // the SSRC of the other end.
42492b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    remoteSSRC = report_blocks[0].remoteSSRC;
42502b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  }
425116825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t rtt = 0;
425216825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t avg_rtt = 0;
425316825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t max_rtt= 0;
425416825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  int64_t min_rtt = 0;
42552b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt)
42562b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org      != 0) {
42572b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org    return 0;
42582b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org  }
425916825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org  return rtt;
42602b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org}
42612b58a4433f16c510d56b1d16d2e3bb882b184861minyue@webrtc.org
4262d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org}  // namespace voe
4263d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org}  // namespace webrtc
4264