channel.cc revision 0870f02cdbcce7de8c6a4dceb6d1678c2c6c518f
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
11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "channel.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "audio_device.h"
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "audio_frame_operations.h"
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "audio_processing.h"
16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "critical_section_wrapper.h"
1750419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org#include "logging.h"
18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "output_mixer.h"
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "process_thread.h"
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "rtp_dump.h"
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "statistics.h"
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "trace.h"
23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "transmit_mixer.h"
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "utility.h"
25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "voe_base.h"
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "voe_external_media.h"
27813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org#include "voe_rtp_rtcp.h"
28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#if defined(_WIN32)
30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <Qos.h>
31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3350419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace webrtc {
3450419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgnamespace voe {
35470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendData(FrameType frameType,
38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  WebRtc_UWord8   payloadType,
39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  WebRtc_UWord32  timeStamp,
40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  const WebRtc_UWord8*  payloadData,
41470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  WebRtc_UWord16  payloadSize,
42470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                  const RTPFragmentationHeader* fragmentation)
43470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
46470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " payloadSize=%u, fragmentation=0x%x)",
47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 frameType, payloadType, timeStamp, payloadSize, fragmentation);
48470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_includeAudioLevelIndication)
50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
51755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        assert(_rtpAudioProc.get() != NULL);
52470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Store current audio level in the RTP/RTCP module.
53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // The level will be used in combination with voice-activity state
54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // (frameType) to add an RTP header extension
552853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->SetAudioLevel(_rtpAudioProc->level_estimator()->RMS());
56470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Push data from ACM to RTP/RTCP-module to deliver audio frame for
59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // packetization.
60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
612853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadType,
63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        timeStamp,
64ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // Leaving the time when this frame was
65ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // received from the capture device as
66ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // undefined for voice for now.
67ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        -1,
68470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadData,
69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadSize,
70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        fragmentation) == -1)
71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::SendData() failed to send data to RTP/RTCP module");
75470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastLocalTimeStamp = timeStamp;
79470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastPayloadType = payloadType;
80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::InFrameType(WebRtc_Word16 frameType)
86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::InFrameType(frameType=%d)", frameType);
89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
909a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 1 indicates speech
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _sendFrameType = (frameType == 1) ? 1 : 0;
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_DTMF_DETECTION
97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::IncomingDtmf(const WebRtc_UWord8 digitDtmf, const bool end)
99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::IncomingDtmf(digitDtmf=%u, end=%d)",
102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               digitDtmf, end);
103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (digitDtmf != 999)
105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1069a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_telephoneEventDetectionPtr)
108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _telephoneEventDetectionPtr->OnReceivedTelephoneEventInband(
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId, digitDtmf, end);
111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnRxVadDetected(const int vadDecision)
120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1249a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxVadObserverPtr)
126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendPacket(int channel, const void *data, int len)
135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    channel = VoEChannelId(channel);
137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_transportPtr == NULL)
143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() failed to send RTP packet due to"
146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " invalid transport object");
147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Insert extra RTP packet using if user has called the InsertExtraRTPPacket
151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // API
152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_insertExtraRTPPacket)
153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord8* rtpHdr = (WebRtc_UWord8*)data;
155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord8 M_PT(0);
156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_extraMarkerBit)
157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            M_PT = 0x80;            // set the M-bit
159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        M_PT += _extraPayloadType;  // set the payload type
161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        *(++rtpHdr) = M_PT;     // modify the M|PT-byte within the RTP header
162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _insertExtraRTPPacket = false;  // insert one packet only
163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 bufferLength = len;
167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTP packet to a file (if RTP dump is enabled).
169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTP dump to output file failed");
174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // SRTP or External encryption
177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encrypting)
178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1799a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_encryptionPtr)
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (!_encryptionRTPBufferPtr)
184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                // Allocate memory for encryption buffer one time only
186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _encryptionRTPBufferPtr =
187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
188512535097e543333584f268eb62fe81c9ac76cc6xians@webrtc.org                memset(_encryptionRTPBufferPtr, 0,
189512535097e543333584f268eb62fe81c9ac76cc6xians@webrtc.org                       kVoiceEngineMaxIpPacketSizeBytes);
190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Perform encryption (SRTP or external)
193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 encryptedBufferLength = 0;
194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _encryptionPtr->encrypt(_channelId,
195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    bufferToSendPtr,
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    _encryptionRTPBufferPtr,
197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    bufferLength,
198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    (int*)&encryptedBufferLength);
199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (encryptedBufferLength <= 0)
200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_ENCRYPTION_FAILED,
203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    kTraceError, "Channel::SendPacket() encryption failed");
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                return -1;
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Replace default data buffer with encrypted buffer
208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            bufferToSendPtr = _encryptionRTPBufferPtr;
209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            bufferLength = encryptedBufferLength;
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Packet transmission using WebRtc socket transport
214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_externalTransport)
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          bufferLength);
218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (n < 0)
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceError, kTraceVoice,
221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::SendPacket() RTP transmission using WebRtc"
223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " sockets failed");
224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return n;
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Packet transmission using external transport transport
230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2319a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        int n = _transportPtr->SendPacket(channel,
234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          bufferToSendPtr,
235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          bufferLength);
236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (n < 0)
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceError, kTraceVoice,
239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::SendPacket() RTP transmission using external"
241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " transport failed");
242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return n;
245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendRTCPPacket(int channel, const void *data, int len)
250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    channel = VoEChannelId(channel);
252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2589a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
25983661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        if (_transportPtr == NULL)
26083661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        {
26183661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org            WEBRTC_TRACE(kTraceError, kTraceVoice,
26283661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org                         VoEId(_instanceId,_channelId),
26383661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org                         "Channel::SendRTCPPacket() failed to send RTCP packet"
26483661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org                         " due to invalid transport object");
26583661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org            return -1;
26683661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        }
267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 bufferLength = len;
271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTCP packet to a file (if RTP dump is enabled).
273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTCP dump to output file failed");
278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // SRTP or External encryption
281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encrypting)
282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2839a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_encryptionPtr)
286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (!_encryptionRTCPBufferPtr)
288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                // Allocate memory for encryption buffer one time only
290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _encryptionRTCPBufferPtr =
291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Perform encryption (SRTP or external).
295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 encryptedBufferLength = 0;
296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _encryptionPtr->encrypt_rtcp(_channelId,
297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         bufferToSendPtr,
298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         _encryptionRTCPBufferPtr,
299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         bufferLength,
300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         (int*)&encryptedBufferLength);
301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (encryptedBufferLength <= 0)
302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_ENCRYPTION_FAILED, kTraceError,
305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "Channel::SendRTCPPacket() encryption failed");
306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                return -1;
307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Replace default data buffer with encrypted buffer
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            bufferToSendPtr = _encryptionRTCPBufferPtr;
311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            bufferLength = encryptedBufferLength;
312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Packet transmission using WebRtc socket transport
316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_externalTransport)
317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        int n = _transportPtr->SendRTCPPacket(channel,
319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              bufferToSendPtr,
320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              bufferLength);
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (n < 0)
322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::SendRTCPPacket() transmission using WebRtc"
326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " sockets failed");
327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return n;
330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Packet transmission using external transport transport
333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3349a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
335de727ab260115d1813b0a039fc74fca488d0c31dhenrike@webrtc.org        if (_transportPtr == NULL)
336de727ab260115d1813b0a039fc74fca488d0c31dhenrike@webrtc.org        {
337de727ab260115d1813b0a039fc74fca488d0c31dhenrike@webrtc.org            return -1;
338de727ab260115d1813b0a039fc74fca488d0c31dhenrike@webrtc.org        }
339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        int n = _transportPtr->SendRTCPPacket(channel,
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              bufferToSendPtr,
341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              bufferLength);
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (n < 0)
343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::SendRTCPPacket() transmission using external"
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " transport failed");
348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return n;
351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return len;
354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket,
358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           const WebRtc_Word32 rtpPacketLength,
359813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org                           const char* fromIP,
360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           const WebRtc_UWord16 fromPort)
361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IncomingRTPPacket(rtpPacketLength=%d,"
364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " fromIP=%s, fromPort=%u)",
365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtpPacketLength, fromIP, fromPort);
366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Store playout timestamp for the received RTP packet
368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // to be used for upcoming delay estimations
369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 playoutTimestamp(0);
370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _playoutTimeStampRTP = playoutTimestamp;
373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket;
376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 rtpBufferLength = rtpPacketLength;
377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // SRTP or External decryption
379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_decrypting)
380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3819a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_encryptionPtr)
384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (!_decryptionRTPBufferPtr)
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                // Allocate memory for decryption buffer one time only
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _decryptionRTPBufferPtr =
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Perform decryption (SRTP or external)
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 decryptedBufferLength = 0;
394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _encryptionPtr->decrypt(_channelId,
395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    rtpBufferPtr,
396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    _decryptionRTPBufferPtr,
397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    rtpBufferLength,
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    (int*)&decryptedBufferLength);
399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (decryptedBufferLength <= 0)
400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_DECRYPTION_FAILED, kTraceError,
403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "Channel::IncomingRTPPacket() decryption failed");
404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                return;
405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Replace default data buffer with decrypted buffer
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rtpBufferPtr = _decryptionRTPBufferPtr;
409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rtpBufferLength = decryptedBufferLength;
410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTP packet to a file (if RTP dump is enabled).
414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpDumpIn.DumpPacket(rtpBufferPtr,
415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              (WebRtc_UWord16)rtpBufferLength) == -1)
416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTP dump to input file failed");
420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Deliver RTP packet to RTP/RTCP module for parsing
423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The packet will be pushed back to the channel thru the
424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // OnReceivedPayloadData callback so we don't push it to the ACM here
4252853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr,
426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      (WebRtc_UWord16)rtpBufferLength) == -1)
427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::IncomingRTPPacket() RTP packet is invalid");
431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return;
432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket,
437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            const WebRtc_Word32 rtcpPacketLength,
438813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org                            const char* fromIP,
439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            const WebRtc_UWord16 fromPort)
440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s,"
443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " fromPort=%u)",
444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtcpPacketLength, fromIP, fromPort);
445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Temporary buffer pointer and size for decryption
447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket;
448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 rtcpBufferLength = rtcpPacketLength;
449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Store playout timestamp for the received RTCP packet
451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // which will be read by the GetRemoteRTCPData API
452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 playoutTimestamp(0);
453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _playoutTimeStampRTCP = playoutTimestamp;
456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // SRTP or External decryption
459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_decrypting)
460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4619a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_encryptionPtr)
464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (!_decryptionRTCPBufferPtr)
466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                // Allocate memory for decryption buffer one time only
468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _decryptionRTCPBufferPtr =
469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Perform decryption (SRTP or external).
473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 decryptedBufferLength = 0;
474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _encryptionPtr->decrypt_rtcp(_channelId,
475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         rtcpBufferPtr,
476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         _decryptionRTCPBufferPtr,
477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         rtcpBufferLength,
478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         (int*)&decryptedBufferLength);
479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (decryptedBufferLength <= 0)
480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_DECRYPTION_FAILED, kTraceError,
483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "Channel::IncomingRTCPPacket() decryption failed");
484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                return;
485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Replace default data buffer with decrypted buffer
488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rtcpBufferPtr = _decryptionRTCPBufferPtr;
489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rtcpBufferLength = decryptedBufferLength;
490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Dump the RTCP packet to a file (if RTP dump is enabled).
494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpDumpIn.DumpPacket(rtcpBufferPtr,
495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              (WebRtc_UWord16)rtcpBufferLength) == -1)
496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::SendPacket() RTCP dump to input file failed");
500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Deliver RTCP packet to RTP/RTCP module for parsing
5032853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr,
504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      (WebRtc_UWord16)rtcpBufferLength) == -1)
505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::IncomingRTPPacket() RTCP packet is invalid");
509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return;
510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnReceivedTelephoneEvent(const WebRtc_Word32 id,
515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                  const WebRtc_UWord8 event,
516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                  const bool endOfEvent)
517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnReceivedTelephoneEvent(id=%d, event=%u,"
520fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " endOfEvent=%d)", id, event, endOfEvent);
521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_DTMF_DETECTION
523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outOfBandTelephoneEventDetecion)
524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5259a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_telephoneEventDetectionPtr)
528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _telephoneEventDetectionPtr->OnReceivedTelephoneEventOutOfBand(
530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId, event, endOfEvent);
531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnPlayTelephoneEvent(const WebRtc_Word32 id,
538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              const WebRtc_UWord8 event,
539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              const WebRtc_UWord16 lengthMs,
540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              const WebRtc_UWord8 volume)
541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
544fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " volume=%u)", id, event, lengthMs, volume);
545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_playOutbandDtmfEvent || (event > 15))
547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Ignore callback since feedback is disabled or event is not a
549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Dtmf tone event.
550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return;
551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(_outputMixerPtr != NULL);
554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Start playing out the Dtmf tone (if playout is enabled).
556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Reduce length of tone with 80ms to the reduce risk of echo.
557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnIncomingSSRCChanged(const WebRtc_Word32 id,
562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               const WebRtc_UWord32 SSRC)
563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, SSRC);
567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 channel = VoEChannelId(id);
569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Reset RTP-module counters since a new incoming RTP stream is detected
5722853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->ResetReceiveDataCountersRTP();
5732853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->ResetStatisticsRTP();
574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpObserver)
576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5779a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_rtpObserverPtr)
580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Send new SSRC to registered observer using callback
582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid Channel::OnIncomingCSRCChanged(const WebRtc_Word32 id,
588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    const WebRtc_UWord32 CSRC,
589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                    const bool added)
590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, CSRC, added);
594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 channel = VoEChannelId(id);
596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpObserver)
599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6009a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_rtpObserverPtr)
603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnApplicationDataReceived(const WebRtc_Word32 id,
611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const WebRtc_UWord8 subType,
612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const WebRtc_UWord32 name,
613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const WebRtc_UWord16 length,
614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const WebRtc_UWord8* data)
615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " name=%u, length=%u)",
619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, subType, name, length);
620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 channel = VoEChannelId(id);
622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtcpObserver)
625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6269a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_rtcpObserverPtr)
629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _rtcpObserverPtr->OnApplicationDataReceived(channel,
631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        subType,
632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        name,
633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        data,
634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        length);
635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnInitializeDecoder(
641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_Word32 id,
642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_Word8 payloadType,
643813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    const char payloadName[RTP_PAYLOAD_NAME_SIZE],
6440b0665acc1464d68e878f203bbc8772a0e32402dxians@google.com    const int frequency,
645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord8 channels,
646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 rate)
647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, payloadType, payloadName, frequency, channels, rate);
652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
653ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org    assert(VoEChannelId(id) == _channelId);
654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
655f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    CodecInst receiveCodec = {0};
656f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    CodecInst dummyCodec = {0};
657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.pltype = payloadType;
659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.plfreq = frequency;
660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.channels = channels;
661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.rate = rate;
662f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org    strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
663f75901fa4c5f9a1bcefc265b98a480c72119650chenrika@webrtc.org
6644517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org    _audioCodingModule.Codec(payloadName, dummyCodec, frequency, channels);
665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    receiveCodec.pacsize = dummyCodec.pacsize;
666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Register the new codec to the ACM
668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterReceiveCodec(receiveCodec) == -1)
669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
671ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org                     VoEId(_instanceId, _channelId),
672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::OnInitializeDecoder() invalid codec ("
673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "pt=%d, name=%s) received - 1", payloadType, payloadName);
674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnPacketTimeout(const WebRtc_Word32 id)
683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnPacketTimeout(id=%d)", id);
686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6879a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(_callbackCritSectPtr);
688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_voiceEngineObserverPtr)
689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_receiving || _externalTransport)
691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 channel = VoEChannelId(id);
693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            assert(channel == _channelId);
694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Ensure that next OnReceivedPacket() callback will trigger
695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // a VE_PACKET_RECEIPT_RESTARTED callback.
696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _rtpPacketTimedOut = true;
697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Deliver callback to the observer
698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::OnPacketTimeout() => "
701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _voiceEngineObserverPtr->CallbackOnError(channel,
703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                     VE_RECEIVE_PACKET_TIMEOUT);
704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnReceivedPacket(const WebRtc_Word32 id,
710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          const RtpRtcpPacketType packetType)
711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, packetType);
715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
716ceb148ce593627ed0d30a1a8c01752bdebf9172dandrew@webrtc.org    assert(VoEChannelId(id) == _channelId);
717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Notify only for the case when we have restarted an RTP session.
719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpPacketTimedOut && (kPacketRtp == packetType))
720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
7219a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(_callbackCritSectPtr);
722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_voiceEngineObserverPtr)
723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_Word32 channel = VoEChannelId(id);
725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            assert(channel == _channelId);
726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Reset timeout mechanism
727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _rtpPacketTimedOut = false;
728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Deliver callback to the observer
729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::OnPacketTimeout() =>"
732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _voiceEngineObserverPtr->CallbackOnError(
734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                channel,
735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_PACKET_RECEIPT_RESTARTED);
736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               const RTPAliveType alive)
743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_connectionObserver)
748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return;
749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 channel = VoEChannelId(id);
751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(channel == _channelId);
752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Use Alive as default to limit risk of false Dead detections
754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool isAlive(true);
755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Always mark the connection as Dead when the module reports kRtpDead
757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (kRtpDead == alive)
758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        isAlive = false;
760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // It is possible that the connection is alive even if no RTP packet has
763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // been received for a long time since the other side might use VAD/DTX
764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // and a low SID-packet update rate.
765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((kRtpNoRtp == alive) && _playing)
766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Detect Alive for all NetEQ states except for the case when we are
768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // in PLC_CNG state.
769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // PLC_CNG <=> background noise only due to long expand or error.
770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Note that, the case where the other side stops sending during CNG
771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // state will be detected as Alive. Dead is is not set until after
772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // missing RTCP packets for at least twelve seconds (handled
773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // internally by the RTP/RTCP module).
774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    UpdateDeadOrAliveCounters(isAlive);
778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Send callback to the registered observer
780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_connectionObserver)
781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
7829a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_connectionObserverPtr)
784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               const WebRtc_UWord16 payloadSize,
793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               const WebRtcRTPHeader* rtpHeader)
794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::OnReceivedPayloadData(payloadSize=%d,"
797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " payloadType=%u, audioChannel=%u)",
798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 payloadSize,
799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtpHeader->header.payloadType,
800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 rtpHeader->type.Audio.channel);
801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
8020870f02cdbcce7de8c6a4dceb6d1678c2c6c518froosa@google.com    _lastRemoteTimeStamp = rtpHeader->header.timestamp;
8030870f02cdbcce7de8c6a4dceb6d1678c2c6c518froosa@google.com
804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_playing)
805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Avoid inserting into NetEQ when we are not playing. Count the
807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // packet as discarded.
808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStream, kTraceVoice,
809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "received packet is discarded since playing is not"
811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " activated");
812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _numberOfDiscardedPackets++;
813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Push the incoming payload (parsed and ready for decoding) into the ACM
81716b6b90a82b796460bb20762761182c7d104cd2dtina.legrand@webrtc.org    if (_audioCodingModule.IncomingPacket(payloadData,
818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          payloadSize,
819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          *rtpHeader) != 0)
820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::OnReceivedPayloadData() unable to push data to the ACM");
824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Update the packet delay
828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    UpdatePacketDelay(rtpHeader->header.timestamp,
829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      rtpHeader->header.sequenceNumber);
830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32 Channel::GetAudioFrame(const WebRtc_Word32 id,
835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     AudioFrame& audioFrame)
836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetAudioFrame(id=%d)", id);
839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
84163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (_audioCodingModule.PlayoutData10Ms(audioFrame.sample_rate_hz_,
8427859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org                                           audioFrame) == -1)
843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice,
845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
8477859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // In all likelihood, the audio in this frame is garbage. We return an
8487859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // error so that the audio mixer module doesn't add it to the mix. As
8497859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // a result, it won't be played out and the actions skipped here are
8507859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        // irrelevant.
8517859e109855b9536593892734aa65af974e6baa4andrew@webrtc.org        return -1;
852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_RxVadDetection)
855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UpdateRxVadDetection(audioFrame);
857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Convert module ID to internal VoE channel ID
86063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    audioFrame.id_ = VoEChannelId(audioFrame.id_);
861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Store speech type for dead-or-alive detection
86263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _outputSpeechType = audioFrame.speech_type_;
863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Perform far-end AudioProcessing module processing on the received signal
865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxApmIsEnabled)
866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        ApmProcessRx(audioFrame);
868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Output volume scaling
871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputGain < 0.99f || _outputGain > 1.01f)
872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Scale left and/or right channel(s) if stereo and master balance is
877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // active
878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_panLeft != 1.0f || _panRight != 1.0f)
880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
88163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (audioFrame.num_channels_ == 1)
882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Emulate stereo mode since panning is active.
884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // The mono signal is copied to both left and right channels here.
8854ecea3e1057eebf846af9b93abf8faf8571bc576andrew@webrtc.org            AudioFrameOperations::MonoToStereo(&audioFrame);
886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // For true stereo mode (when we are receiving a stereo signal), no
888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // action is needed.
889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Do the panning operation (the audio frame contains stereo at this
891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // stage)
892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Mix decoded PCM output with file if file mixing is enabled
896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlaying)
897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
89863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Place channel in on-hold state (~muted) if on-hold is activated
902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputIsOnHold)
903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        AudioFrameOperations::Mute(audioFrame);
905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // External media
908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputExternalMedia)
909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
9109a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
91163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        const bool isStereo = (audioFrame.num_channels_ == 2);
912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputExternalMediaCallbackPtr)
913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputExternalMediaCallbackPtr->Process(
915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId,
916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                kPlaybackPerChannel,
91763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                (WebRtc_Word16*)audioFrame.data_,
91863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                audioFrame.samples_per_channel_,
91963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                audioFrame.sample_rate_hz_,
920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                isStereo);
921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Record playout if enabled
925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
9269a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFileRecording && _outputFileRecorderPtr)
929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
9305398d9583b713f83db843a15f8bcc2ef8df23bccniklas.enbom@webrtc.org            _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Measure audio level (0-9)
935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.ComputeLevel(audioFrame);
936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::NeededFrequency(const WebRtc_Word32 id)
942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::NeededFrequency(id=%d)", id);
945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int highestNeeded = 0;
947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Determine highest needed receive frequency
949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 receiveFrequency = _audioCodingModule.ReceiveFrequency();
950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Return the bigger of playout and receive frequency in the ACM.
952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        highestNeeded = _audioCodingModule.PlayoutFrequency();
955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        highestNeeded = receiveFrequency;
959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Special case, if we're playing a file on the playout side
962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // we take that frequency into consideration as well
963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This is not needed on sending side, since the codec will
964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // limit the spectrum anyway.
965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlaying)
966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
9679a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFilePlayerPtr && _outputFilePlaying)
969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if(_outputFilePlayerPtr->Frequency()>highestNeeded)
971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                highestNeeded=_outputFilePlayerPtr->Frequency();
973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return(highestNeeded);
978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::CreateChannel(Channel*& channel,
982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       const WebRtc_Word32 channelId,
983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       const WebRtc_UWord32 instanceId)
984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        channelId, instanceId);
988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    channel = new Channel(channelId, instanceId);
990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (channel == NULL)
991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceMemory, kTraceVoice,
993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(instanceId,channelId),
994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::CreateChannel() unable to allocate memory for"
995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " channel");
996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
1002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::PlayNotification(const WebRtc_Word32 id,
1003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          const WebRtc_UWord32 durationMs)
1004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PlayNotification(id=%d, durationMs=%d)",
1007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, durationMs);
1008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Not implement yet
1010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
1013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RecordNotification(const WebRtc_Word32 id,
1014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            const WebRtc_UWord32 durationMs)
1015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordNotification(id=%d, durationMs=%d)",
1018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 id, durationMs);
1019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Not implement yet
1021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
1024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::PlayFileEnded(const WebRtc_Word32 id)
1025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PlayFileEnded(id=%d)", id);
1028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (id == _inputFilePlayerId)
1030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
10319a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
1032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlaying = false;
1034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PlayFileEnded() => input file player module is"
1037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " shutdown");
1038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (id == _outputFilePlayerId)
1040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
10419a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
1042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFilePlaying = false;
1044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PlayFileEnded() => output file player module is"
1047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " shutdown");
1048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
1052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RecordFileEnded(const WebRtc_Word32 id)
1053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordFileEnded(id=%d)", id);
1056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(id == _outputFileRecorderId);
1058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
10599a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
1060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = false;
1062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
1064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RecordFileEnded() => output file recorder module is"
1065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " shutdown");
1066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Channel(const WebRtc_Word32 channelId,
1069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 const WebRtc_UWord32 instanceId) :
1070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _instanceId(instanceId),
107322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _channelId(channelId),
1074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioCodingModule(*AudioCodingModule::Create(
107522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com        VoEModuleId(instanceId, channelId))),
1076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
107768f2168978548bb8dd80ba77a888722bf9e5ec66perkj@webrtc.org     _numSocketThreads(KNumSocketThreads),
107822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _socketTransportModule(*UdpTransport::Create(
107968f2168978548bb8dd80ba77a888722bf9e5ec66perkj@webrtc.org        VoEModuleId(instanceId, channelId), _numSocketThreads)),
1080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_SRTP
1082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId,
1083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                          channelId))),
1084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpDumpIn(*RtpDump::CreateRtpDump()),
1086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpDumpOut(*RtpDump::CreateRtpDump()),
1087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel(),
1088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport(false),
1089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr(NULL),
1090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFilePlayerPtr(NULL),
1091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr(NULL),
1092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Avoid conflict with other channels by adding 1024 - 1026,
1093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // won't use as much as 1024 channels.
1094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
1095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
1096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
1097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlaying(false),
1098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFilePlaying(false),
1099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording(false),
110022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
110122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
1102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputExternalMedia(false),
110322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _outputExternalMedia(false),
1104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputExternalMediaCallbackPtr(NULL),
1105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputExternalMediaCallbackPtr(NULL),
110622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _encryptionRTPBufferPtr(NULL),
110722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _decryptionRTPBufferPtr(NULL),
110822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _encryptionRTCPBufferPtr(NULL),
110922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _decryptionRTCPBufferPtr(NULL),
111022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
111122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _sendTelephoneEventPayloadType(106),
111222963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _playoutTimeStampRTP(0),
111322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _playoutTimeStampRTCP(0),
111422963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _numberOfDiscardedPackets(0),
111522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _engineStatisticsPtr(NULL),
11162919e95c2a59a087ba8297c2f551c3ebc3754c9ehenrika@webrtc.org    _outputMixerPtr(NULL),
11172919e95c2a59a087ba8297c2f551c3ebc3754c9ehenrika@webrtc.org    _transmitMixerPtr(NULL),
111822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _moduleProcessThreadPtr(NULL),
111922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _audioDeviceModulePtr(NULL),
112022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _voiceEngineObserverPtr(NULL),
112122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _callbackCritSectPtr(NULL),
112222963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _transportPtr(NULL),
112322963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _encryptionPtr(NULL),
1124755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    _rtpAudioProc(NULL),
112522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rxAudioProcessingModulePtr(NULL),
112622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com#ifdef WEBRTC_DTMF_DETECTION
112722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _telephoneEventDetectionPtr(NULL),
112822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com#endif
112922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rxVadObserverPtr(NULL),
113022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _oldVadDecision(-1),
113122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _sendFrameType(0),
1132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpObserverPtr(NULL),
1133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtcpObserverPtr(NULL),
113422963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _outputIsOnHold(false),
113522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _externalPlayout(false),
113622963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _inputIsOnHold(false),
113722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _playing(false),
113822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _sending(false),
113922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _receiving(false),
114022963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _mixFileWithMicrophone(false),
114122963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rtpObserver(false),
114222963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rtcpObserver(false),
1143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mute(false),
1144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panLeft(1.0f),
1145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panRight(1.0f),
1146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputGain(1.0f),
114722963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _encrypting(false),
114822963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _decrypting(false),
1149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playOutbandDtmfEvent(false),
1150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playInbandDtmfEvent(false),
1151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandTelephoneEventDetection(false),
1152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outOfBandTelephoneEventDetecion(false),
1153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _extraPayloadType(0),
1154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _insertExtraRTPPacket(false),
1155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _extraMarkerBit(false),
1156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastLocalTimeStamp(0),
11570870f02cdbcce7de8c6a4dceb6d1678c2c6c518froosa@google.com    _lastRemoteTimeStamp(0),
1158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _lastPayloadType(0),
115922963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _includeAudioLevelIndication(false),
1160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpPacketTimedOut(false),
1161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpPacketTimeOutIsEnabled(false),
1162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpTimeOutSeconds(0),
1163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserver(false),
1164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserverPtr(NULL),
1165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _countAliveDetections(0),
1166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _countDeadDetections(0),
1167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputSpeechType(AudioFrame::kNormalSpeech),
1168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _averageDelayMs(0),
1169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _previousSequenceNumber(0),
1170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _previousTimestamp(0),
1171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _recPacketDelayMs(20),
1172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection(false),
1173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxApmIsEnabled(false),
1174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxAgcIsEnabled(false),
117522963abffe4179e75f18a2e7be1d1c58c9518089xians@google.com    _rxNsIsEnabled(false)
1176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::Channel() - ctor");
1179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfQueue.ResetDtmf();
1180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfGenerator.Init();
1181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.Clear();
1182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11832853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RtpRtcp::Configuration configuration;
11842853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.id = VoEModuleId(instanceId, channelId);
11852853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.audio = true;
11862853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.incoming_data = this;
11872853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.incoming_messages = this;
11882853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.outgoing_transport = this;
11892853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.rtcp_feedback = this;
11902853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    configuration.audio_messages = this;
11912853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org
11922853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
11932853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org
1194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create far end AudioProcessing Module
1195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxAudioProcessingModulePtr = AudioProcessing::Create(
1196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        VoEModuleId(instanceId, channelId));
1197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::~Channel()
1200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::~Channel() - dtor");
1203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputExternalMedia)
1205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputExternalMedia)
1209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    StopSend();
1213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    StopReceiving();
1215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // De-register packet callback to ensure we're not in a callback when
1216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // deleting channel state, avoids race condition and deadlock.
1217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0)
1218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            != 0)
1219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
1222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register receive callback");
1223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    StopPlayout();
1226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
12289a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
1229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputFilePlayerPtr)
1230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr->StopPlayingFile();
1233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputFilePlayerPtr = NULL;
1235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFilePlayerPtr)
1237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr->StopPlayingFile();
1240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFilePlayerPtr = NULL;
1242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFileRecorderPtr)
1244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr->StopRecording();
1247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputFileRecorderPtr = NULL;
1249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The order to safely shutdown modules in a channel is:
1253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 1. De-register callbacks in modules
1254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 2. De-register modules in process thread
1255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // 3. Destroy modules
1256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register transport callback"
1261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " (Audio coding module)");
1262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register VAD callback"
1268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " (Audio coding module)");
1269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_DTMF_DETECTION
1271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterIncomingMessagesCallback(NULL) == -1)
1272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to de-register incoming messages "
1276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "callback (Audio coding module)");
1277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // De-register modules in process thread
1280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule)
1282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            == -1)
1283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to deregister socket module");
1287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
12892853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
1290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "~Channel() failed to deregister RTP/RTCP module");
1294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy modules
1297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    UdpTransport::Destroy(
1299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_socketTransportModule);
1300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    AudioCodingModule::Destroy(&_audioCodingModule);
1302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_SRTP
1303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    SrtpModule::DestroySrtpModule(&_srtpModule);
1304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr != NULL)
1306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        AudioProcessing::Destroy(_rxAudioProcessingModulePtr); // far end APM
1308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr = NULL;
1309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // End of modules shutdown
1312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Delete other objects
1314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump::DestroyRtpDump(&_rtpDumpIn);
1315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump::DestroyRtpDump(&_rtpDumpOut);
1316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete [] _encryptionRTPBufferPtr;
1317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete [] _decryptionRTPBufferPtr;
1318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete [] _encryptionRTCPBufferPtr;
1319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete [] _decryptionRTCPBufferPtr;
1320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete &_callbackCritSect;
1321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete &_fileCritSect;
1322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Init()
1326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::Init()");
1329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Initial sanity
1331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((_engineStatisticsPtr == NULL) ||
1333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_moduleProcessThreadPtr == NULL))
1334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice,
1336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId,_channelId),
1337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::Init() must call SetEngineInformation() first");
1338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Add modules to process thread (for periodic schedulation)
1342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool processThreadFail =
13442853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
1345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_moduleProcessThreadPtr->RegisterModule(
1347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                &_socketTransportModule) != 0));
1348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else
1349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        false);
1350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (processThreadFail)
1352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_INIT_CHANNEL, kTraceError,
1355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() modules not registered");
1356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1358c450a1966965fbb3c16ec6d02c3d5cbec67df500pwestin@webrtc.org    // --- ACM initialization
1359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((_audioCodingModule.InitializeReceiver() == -1) ||
1361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_CODEC_AVT
1362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // out-of-band Dtmf tones are played out by default
1363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_audioCodingModule.InitializeSender() == -1))
1366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() unable to initialize the ACM - 1");
1370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- RTP/RTCP module initialization
1374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Ensure that RTCP is enabled by default for the created channel.
1376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Note that, the module will keep generating RTCP until it is explicitly
1377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // disabled by the user.
1378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // After StopListen (when no sockets exists), RTCP packets will no longer
1379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // be transmitted since the Transport object will then be invalid.
1380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool rtpRtcpFail =
13822853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        ((_rtpRtcpModule->SetTelephoneEventStatus(false, true, true) == -1) ||
1383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // RTCP is enabled by default
13842853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1));
1385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpRtcpFail)
1386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() RTP/RTCP module not initialized");
1390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com     // --- Register all permanent callbacks
1394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool fail =
1395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_audioCodingModule.RegisterVADCallback(this) == -1);
1397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (fail)
1399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_INIT_CHANNEL, kTraceError,
1402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() callbacks not registered");
1403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Register all supported codecs to the receiving side of the
1407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // RTP/RTCP module
1408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
1410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (int idx = 0; idx < nSupportedCodecs; idx++)
1413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Open up the RTP/RTCP receiver for all supported codecs
1415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((_audioCodingModule.Codec(idx, codec) == -1) ||
14162853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org            (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
1417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
1420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "to RTP/RTCP receiver",
1422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
1423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
1424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
1426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
1429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "the RTP/RTCP receiver",
1431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
1432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
1433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Ensure that PCMU is used as default codec on the sending side
14364517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org        if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
1437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            SetSendCodec(codec);
1439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Register default PT for outband 'telephone-event'
1442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
14442853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org            if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
1445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register outband "
1450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "'telephone-event' (%d/%d) correctly",
1451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "CN"))
1456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
14592853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org                (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
1460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register CN (%d/%d) "
1464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "correctly - 1",
1465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_CODEC_RED
1469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Register RED to the receiving side of the ACM.
1470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // We will not receive an OnInitializeDecoder() callback for RED.
1471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!STR_CASE_CMP(codec.plname, "RED"))
1472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
1475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId,_channelId),
1477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "Channel::Init() failed to register RED (%d/%d) "
1478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "correctly",
1479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             codec.pltype, codec.plfreq);
1480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
1481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Ensure that the WebRtcSocketTransport implementation is used as
1486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Transport on the sending side
148783661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org    {
148883661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        // A lock is needed here since users can call
148983661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        // RegisterExternalTransport() at the same time.
14909a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
149183661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org        _transportPtr = &_socketTransportModule;
149283661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org    }
1493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Initialize the far end AP module
1496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Using 8 kHz as initial Fs, the same as in transmission. Might be
1497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // changed at the first receiving audio.
1498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr == NULL)
1499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NO_MEMORY, kTraceCritical,
1502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() failed to create the far-end AudioProcessing"
1503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            " module");
1504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->set_sample_rate_hz(8000))
1508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() failed to set the sample rate to 8K for"
1512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            " far-end AP module");
1513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->set_num_channels(1, 1) != 0)
1516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOUNDCARD_ERROR, kTraceWarning,
1519755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            "Init() failed to set channels for the primary audio stream");
1520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->high_pass_filter()->Enable(
1523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Channel::Init() failed to set the high-pass filter for"
1528fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            " far-end AP module");
1529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(
1532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Init() failed to set noise reduction level for far-end"
1537fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            " AP module");
1538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(
1540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Init() failed to set noise reduction state for far-end"
1545fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            " AP module");
1546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->set_mode(
1549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Init() failed to set AGC mode for far-end AP module");
1554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->Enable(
1556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceWarning,
1560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "Init() failed to set AGC state for far-end AP module");
1561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetEngineInformation(Statistics& engineStatistics,
1568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              OutputMixer& outputMixer,
1569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              voe::TransmitMixer& transmitMixer,
1570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              ProcessThread& moduleProcessThread,
1571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              AudioDeviceModule& audioDeviceModule,
1572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              VoiceEngineObserver* voiceEngineObserver,
1573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              CriticalSectionWrapper* callbackCritSect)
1574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetEngineInformation()");
1577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _engineStatisticsPtr = &engineStatistics;
1578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputMixerPtr = &outputMixer;
1579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transmitMixerPtr = &transmitMixer,
1580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _moduleProcessThreadPtr = &moduleProcessThread;
1581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioDeviceModulePtr = &audioDeviceModule;
1582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = voiceEngineObserver;
1583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _callbackCritSectPtr = callbackCritSect;
1584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateLocalTimeStamp()
1589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
159163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _timeStamp += _audioFrame.samples_per_channel_;
1592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartPlayout()
1597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayout()");
1600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_playing)
1601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Add participant as candidates for mixing.
1605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayout() failed to add participant to mixer");
1610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playing = true;
1614ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
1615ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
1616ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return -1;
1617ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
1618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopPlayout()
1623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayout()");
1626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_playing)
1627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Remove participant as candidates for mixing
1631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayout() failed to remove participant from mixer");
1636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playing = false;
1640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputAudioLevel.Clear();
1641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartSend()
1647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartSend()");
1650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1651e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        // A lock is needed because |_sending| can be accessed or modified by
1652e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        // another thread at the same time.
16539a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
1654e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
1655e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        if (_sending)
1656e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        {
1657e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org            return 0;
1658e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        }
1659e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        _sending = true;
1660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1661e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
16622853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSendingStatus(true) != 0)
1663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartSend() RTP/RTCP failed to start sending");
16679a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
1668e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        _sending = false;
1669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1671e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
1672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopSend()
1677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopSend()");
1680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1681e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        // A lock is needed because |_sending| can be accessed or modified by
1682e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        // another thread at the same time.
16839a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
1684e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
1685e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        if (!_sending)
1686e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        {
1687e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org            return 0;
1688e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        }
1689e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org        _sending = false;
1690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1691e07247af8d0888529e14156a9929cbd2376f8442xians@webrtc.org
1692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Reset sending SSRC and sequence number and triggers direct transmission
1693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // of RTCP BYE
16942853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
16952853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
1696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartSend() RTP/RTCP failed to stop sending");
1700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartReceiving()
1707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartReceiving()");
1710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_receiving)
1711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // If external transport is used, we will only initialize/set the variables
1715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // after this section, since we are not using the WebRtc transport but
1716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // still need to keep track of e.g. if we are receiving.
1717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_externalTransport)
1719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!_socketTransportModule.ReceiveSocketsInitialized())
1721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKETS_NOT_INITED, kTraceError,
1724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "StartReceive() must set local receiver first");
1725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0)
1728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "StartReceiving() failed to start receiving");
1732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _receiving = true;
1737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _numberOfDiscardedPackets = 0;
1738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopReceiving()
1743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopReceiving()");
1746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_receiving)
1747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
1749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_externalTransport &&
1753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _socketTransportModule.ReceiveSocketsInitialized())
1754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_socketTransportModule.StopReceiving() != 0)
1756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1759af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org                "StopReceiving() failed to stop receiving.");
1760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
17642853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    bool dtmfDetection = _rtpRtcpModule->TelephoneEvent();
1765af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org    // Recover DTMF detection status.
17662853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventStatus(dtmfDetection,
17672853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org                                                               true, true);
1768af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org    if (ret != 0) {
1769af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org        _engineStatisticsPtr->SetLastError(
1770af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org            VE_INVALID_OPERATION, kTraceWarning,
1771af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org            "StopReceiving() failed to restore telephone-event status.");
1772af71f0e5d98d894b22969d4714821b54218bc083henrika@webrtc.org    }
1773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RegisterReceiveCodecsToRTPModule();
1774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _receiving = false;
1775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetLocalReceiver(const WebRtc_UWord16 rtpPort,
1781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          const WebRtc_UWord16 rtcpPort,
1782813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org                          const char ipAddr[64],
1783813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org                          const char multicastIpAddr[64])
1784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetLocalReceiver()");
1787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
1789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalReceiver() conflict with external transport");
1793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
1797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_SENDING, kTraceError,
1800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalReceiver() already sending");
1801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_receiving)
1804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_LISTENING, kTraceError,
1807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalReceiver() already receiving");
1808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.InitializeReceiveSockets(this,
1812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        rtpPort,
1813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        ipAddr,
1814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        multicastIpAddr,
1815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        rtcpPort) != 0)
1816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UdpTransport::ErrorCode lastSockError(
1818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError());
1819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        switch (lastSockError)
1820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kIpAddressInvalid:
1822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_IP_ADDRESS, kTraceError,
1824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetLocalReceiver() invalid IP address");
1825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kSocketInvalid:
1827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_ERROR, kTraceError,
1829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetLocalReceiver() invalid socket");
1830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kPortInvalid:
1832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_PORT_NMBR, kTraceError,
1834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetLocalReceiver() invalid port");
1835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kFailedToBindPort:
1837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError,
1839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetLocalReceiver() binding failed");
1840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
1842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_ERROR, kTraceError,
1844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetLocalReceiver() undefined socket error");
1845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64])
1856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetLocalReceiver()");
1859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
1861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalReceiver() conflict with external transport");
1865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1868813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
1869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtpPort(0);
1870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtcpPort(0);
1871813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0};
1872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Acquire socket information from the socket module
1874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp,
1875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        rtpPort,
1876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        rtcpPort,
1877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        multicastIpAddr) != 0)
1878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetLocalReceiver() unable to retrieve socket information");
1882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Deliver valid results to the user
1886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    port = static_cast<int> (rtpPort);
1887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RTCPport = static_cast<int> (rtcpPort);
1888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (ipAddr != NULL)
1889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        strcpy(ipAddr, ipAddrTmp);
1891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
1893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
1895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
1897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
1898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendDestination(const WebRtc_UWord16 rtpPort,
1899813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org                            const char ipAddr[64],
1900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            const int sourcePort,
1901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            const WebRtc_UWord16 rtcpPort)
1902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendDestination()");
1905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
1907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
1909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendDestination() conflict with external transport");
1911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Initialize ports and IP address for the remote (destination) side.
1915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // By default, the sockets used for receiving are used for transmission as
1916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // well, hence the source ports for outgoing packets are the same as the
1917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // receiving ports specified in SetLocalReceiver.
1918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // If an extra send socket has been created, it will be utilized until a
1919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // new source port is specified or until the channel has been deleted and
1920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // recreated. If no socket exists, sockets will be created when the first
1921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // RTP and RTCP packets shall be transmitted (see e.g.
1922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // UdpTransportImpl::SendPacket()).
1923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    //
1924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // NOTE: this function does not require that sockets exists; all it does is
1925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // to build send structures to be used with the sockets when they exist.
1926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // It is therefore possible to call this method before SetLocalReceiver.
1927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // However, sockets must exist if a multi-cast address is given as input.
1928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Build send structures and enable QoS (if enabled and supported)
1930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.InitializeSendSockets(
1931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError)
1932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UdpTransport::ErrorCode lastSockError(
1934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError());
1935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        switch (lastSockError)
1936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kIpAddressInvalid:
1938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_IP_ADDRESS, kTraceError,
1940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() invalid IP address 1");
1941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kSocketInvalid:
1943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_ERROR, kTraceError,
1945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() invalid socket 1");
1946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kQosError:
1948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_GQOS_ERROR, kTraceError,
1950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() failed to set QoS");
1951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kMulticastAddressInvalid:
1953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_MULTICAST_ADDRESS, kTraceError,
1955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() invalid multicast address");
1956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
1958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SOCKET_ERROR, kTraceError,
1960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() undefined socket error 1");
1961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
1962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
1964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Check if the user has specified a non-default source port different from
1967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // the local receive port.
1968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // If so, an extra local socket will be created unless the source port is
1969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // not unique.
1970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (sourcePort != kVoEDefault)
1971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 receiverRtpPort(0);
1973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 rtcpNA(0);
1974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_socketTransportModule.ReceiveSocketInformation(NULL,
1975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                            receiverRtpPort,
1976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                            rtcpNA,
1977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                            NULL) != 0)
1978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
1980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendDestination() failed to retrieve socket information");
1982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
1983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
1984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 sourcePortUW16 =
1986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                static_cast<WebRtc_UWord16> (sourcePort);
1987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // An extra socket will only be created if the specified source port
1989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // differs from the local receive port.
1990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (sourcePortUW16 != receiverRtpPort)
1991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
1992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Initialize extra local socket to get a different source port
1993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // than the local
1994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // receiver port. Always use default source for RTCP.
1995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Note that, this calls UdpTransport::CloseSendSockets().
1996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (_socketTransportModule.InitializeSourcePorts(
1997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                sourcePortUW16,
1998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                sourcePortUW16+1) != 0)
1999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
2000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                UdpTransport::ErrorCode lastSockError(
2001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    _socketTransportModule.LastError());
2002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                switch (lastSockError)
2003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                {
2004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                case UdpTransport::kIpAddressInvalid:
2005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    _engineStatisticsPtr->SetLastError(
2006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        VE_INVALID_IP_ADDRESS, kTraceError,
2007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        "SetSendDestination() invalid IP address 2");
2008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    break;
2009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                case UdpTransport::kSocketInvalid:
2010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    _engineStatisticsPtr->SetLastError(
2011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        VE_SOCKET_ERROR, kTraceError,
2012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        "SetSendDestination() invalid socket 2");
2013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    break;
2014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                default:
2015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    _engineStatisticsPtr->SetLastError(
2016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        VE_SOCKET_ERROR, kTraceError,
2017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        "SetSendDestination() undefined socket error 2");
2018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    break;
2019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                }
2020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                return -1;
2021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
2022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
2024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "SetSendDestination() extra local socket is created"
2025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " to facilitate unique source port");
2026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
2028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
2031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "SetSendDestination() sourcePort equals the local"
2032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " receive port => no extra socket is created");
2033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
2039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
2041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendDestination(int& port,
2043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            char ipAddr[64],
2044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            int& sourcePort,
2045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            int& RTCPport)
2046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSendDestination()");
2049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
2051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
2054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetSendDestination() conflict with external transport");
2055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2058813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtpPort(0);
2060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtcpPort(0);
2061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtpSourcePort(0);
2062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtcpSourcePort(0);
2063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Acquire sending socket information from the socket module
2065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort);
2066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort);
2067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Deliver valid results to the user
2069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    port = static_cast<int> (rtpPort);
2070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RTCPport = static_cast<int> (rtcpPort);
2071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sourcePort = static_cast<int> (rtpSourcePort);
2072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (ipAddr != NULL)
2073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        strcpy(ipAddr, ipAddrTmp);
2075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
2080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetNetEQPlayoutMode(NetEqModes mode)
2084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetNetEQPlayoutMode()");
2087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    AudioPlayoutMode playoutMode(voice);
2088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
2089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNetEqDefault:
2091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            playoutMode = voice;
2092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNetEqStreaming:
2094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            playoutMode = streaming;
2095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNetEqFax:
2097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            playoutMode = fax;
2098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
2101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetNetEQPlayoutMode() failed to set playout mode");
2105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetNetEQPlayoutMode(NetEqModes& mode)
2112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
2114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (playoutMode)
2115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case voice:
2117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNetEqDefault;
2118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case streaming:
2120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNetEqStreaming;
2121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case fax:
2123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNetEqFax;
2124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
2128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
2129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetNetEQBGNMode(NetEqBgnModes mode)
2134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetNetEQPlayoutMode()");
2137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ACMBackgroundNoiseMode noiseMode(On);
2138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
2139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kBgnOn:
2141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            noiseMode = On;
2142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kBgnFade:
2144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            noiseMode = Fade;
2145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kBgnOff:
2147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            noiseMode = Off;
2148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetBackgroundNoiseMode(noiseMode) != 0)
2151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetBackgroundNoiseMode() failed to set noise mode");
2155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetOnHoldStatus(bool enable, OnHoldModes mode)
2162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetOnHoldStatus()");
2165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (mode == kHoldSendAndPlay)
2166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputIsOnHold = enable;
2168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputIsOnHold = enable;
2169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (mode == kHoldPlayOnly)
2171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputIsOnHold = enable;
2173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (mode == kHoldSendOnly)
2175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputIsOnHold = enable;
2177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
2183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetOnHoldStatus()");
2186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = (_outputIsOnHold || _inputIsOnHold);
2187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputIsOnHold && _inputIsOnHold)
2188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        mode = kHoldSendAndPlay;
2190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (_outputIsOnHold && !_inputIsOnHold)
2192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        mode = kHoldPlayOnly;
2194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (!_outputIsOnHold && _inputIsOnHold)
2196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        mode = kHoldSendOnly;
2198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
2201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 enabled, mode);
2202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
2207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterVoiceEngineObserver()");
22109a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
2211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_voiceEngineObserverPtr)
2213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
2216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterVoiceEngineObserver() observer already enabled");
2217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = &observer;
2220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterVoiceEngineObserver()
2225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterVoiceEngineObserver()");
22289a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
2229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_voiceEngineObserverPtr)
2231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
2234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterVoiceEngineObserver() observer already disabled");
2235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _voiceEngineObserverPtr = NULL;
2238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetNetEQBGNMode(NetEqBgnModes& mode)
2243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  ACMBackgroundNoiseMode noiseMode(On);
2245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioCodingModule.BackgroundNoiseMode(noiseMode);
2246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (noiseMode)
2247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case On:
2249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kBgnOn;
2250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case Fade:
2252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kBgnFade;
2253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case Off:
2255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kBgnOff;
2256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetNetEQBGNMode() => mode=%u", mode);
2260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendCodec(CodecInst& codec)
2265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (_audioCodingModule.SendCodec(codec));
2267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecCodec(CodecInst& codec)
2271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (_audioCodingModule.ReceiveCodec(codec));
2273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCodec(const CodecInst& codec)
2277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendCodec()");
2280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "SetSendCodec() failed to register codec to ACM");
2285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
22882853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
22902853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
22912853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
2294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "SetSendCodec() failed to register codec to"
2296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    " RTP/RTCP module");
2297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23012853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
2302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "SetSendCodec() failed to set audio packet size");
2305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
2313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetVADStatus(mode=%d)", mode);
2316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // To disable VAD, DTX must be disabled too
2317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    disableDTX = ((enableVAD == false) ? true : disableDTX);
2318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
2319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetVADStatus() failed to set VAD");
2323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
2330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetVADStatus");
2333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.VAD(disabledDTX, enabledVAD, mode) != 0)
2334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetVADStatus() failed to get VAD status");
2338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    disabledDTX = !disabledDTX;
2341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRecPayloadType(const CodecInst& codec)
2346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRecPayloadType()");
2349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_playing)
2351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
2354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRecPayloadType() unable to set PT while playing");
2355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_receiving)
2358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_LISTENING, kTraceError,
2361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRecPayloadType() unable to set PT while listening");
2362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (codec.pltype == -1)
2366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // De-register the selected codec (RTP/RTCP module and ACM)
2368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_Word8 pltype(-1);
2370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        CodecInst rxCodec = codec;
2371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Get payload type for the given codec
23732853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->ReceivePayloadType(rxCodec, &pltype);
2374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rxCodec.pltype = pltype;
2375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23762853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->DeRegisterReceivePayload(pltype) != 0)
2377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_RTP_RTCP_MODULE_ERROR,
2380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    kTraceError,
2381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "SetRecPayloadType() RTP/RTCP-module deregistration "
2382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "failed");
2383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
2386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() ACM deregistration failed - 1");
2390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
23952853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
2396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // First attempt to register failed => de-register and try again
23982853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->DeRegisterReceivePayload(codec.pltype);
23992853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
2400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() RTP/RTCP-module registration failed");
2404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
2410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRecPayloadType() ACM registration failed - 1");
2415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRecPayloadType(CodecInst& codec)
2423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRecPayloadType()");
2426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word8 payloadType(-1);
24272853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->ReceivePayloadType(codec, &payloadType) != 0)
2428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
243037198007eab6731fa0f77866155dd4f2b332a262henrika@webrtc.org            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
2431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRecPayloadType() failed to retrieve RX payload type");
2432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    codec.pltype = payloadType;
2435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
2437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetAMREncFormat(AmrMode mode)
2442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetAMREncFormat()");
2445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // ACM doesn't support AMR
2447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
2448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetAMRDecFormat(AmrMode mode)
2452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetAMRDecFormat()");
2455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // ACM doesn't support AMR
2457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
2458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetAMRWbEncFormat(AmrMode mode)
2462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetAMRWbEncFormat()");
2465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // ACM doesn't support AMR
2467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
2468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetAMRWbDecFormat(AmrMode mode)
2473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetAMRWbDecFormat()");
2476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // ACM doesn't support AMR
2478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
2479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
2483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendCNPayloadType()");
2486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
2488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 samplingFreqHz(-1);
24894517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org    const int kMono = 1;
2490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (frequency == kFreq32000Hz)
2491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        samplingFreqHz = 32000;
2492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (frequency == kFreq16000Hz)
2493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        samplingFreqHz = 16000;
2494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
24954517585db5f2f2a14fdd56a96f4b44f745967c8ctina.legrand@webrtc.org    if (_audioCodingModule.Codec("CN", codec, samplingFreqHz, kMono) == -1)
2496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendCNPayloadType() failed to retrieve default CN codec "
2500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "settings");
2501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Modify the payload type (must be set to dynamic range)
2505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    codec.pltype = type;
2506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendCNPayloadType() failed to register CN to ACM");
2512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
25152853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
25172853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
25182853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
2523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "module");
2524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
2532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetISACInitTargetRate()");
2535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst sendCodec;
2537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACInitTargetRate() failed to retrieve send codec");
2542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // This API is only valid if iSAC is setup to run in channel-adaptive
2547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // mode.
2548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // We do not validate the adaptive mode here. It is done later in the
2549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // ConfigISACBandwidthEstimator() API.
2550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACInitTargetRate() send codec is not iSAC");
2553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8 initFrameSizeMsec(0);
2557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (16000 == sendCodec.plfreq)
2558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Note that 0 is a valid and corresponds to "use default
2560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((rateBps != 0 &&
2561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
2562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
2563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com             _engineStatisticsPtr->SetLastError(
2565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACInitTargetRate() invalid target rate - 1");
2567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // 30 or 60ms
2570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 16);
2571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (32000 == sendCodec.plfreq)
2573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((rateBps != 0 &&
2575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
2576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
2577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACInitTargetRate() invalid target rate - 2");
2581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 32); // 30ms
2584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.ConfigISACBandwidthEstimator(
2587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACInitTargetRate() iSAC BWE config failed");
2592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetISACMaxRate(int rateBps)
2600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetISACMaxRate()");
2603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst sendCodec;
2605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxRate() failed to retrieve send codec");
2610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // This API is only valid if iSAC is selected as sending codec.
2615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxRate() send codec is not iSAC");
2618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (16000 == sendCodec.plfreq)
2621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACMaxRate() invalid max rate - 1");
2628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (32000 == sendCodec.plfreq)
2632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACMaxRate() invalid max rate - 2");
2639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
2643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SENDING, kTraceError,
2646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxRate() unable to set max rate while sending");
2647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Set the maximum instantaneous rate of iSAC (works for both adaptive
2651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // and non-adaptive mode)
2652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxRate() failed to set max rate");
2657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetISACMaxPayloadSize(int sizeBytes)
2665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetISACMaxPayloadSize()");
2668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst sendCodec;
2669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxPayloadSize() failed to retrieve send codec");
2674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CODEC_ERROR, kTraceError,
2680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxPayloadSize() send codec is not iSAC");
2681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (16000 == sendCodec.plfreq)
2684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACMaxPayloadSize() invalid max payload - 1");
2691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (32000 == sendCodec.plfreq)
2695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
2701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetISACMaxPayloadSize() invalid max payload - 2");
2702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
2703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
2706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SENDING, kTraceError,
2709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxPayloadSize() unable to set max rate while sending");
2710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetISACMaxPayloadSize() failed to set max payload size");
2718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport)
2724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::RegisterExternalTransport()");
2727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
27289a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
2729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
2731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Sanity checks for default (non external transport) to avoid conflict with
2732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // WebRtc sockets.
2733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.SendSocketsInitialized())
2734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT,
2736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           kTraceError,
2737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "RegisterExternalTransport() send sockets already initialized");
2738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.ReceiveSocketsInitialized())
2741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT,
2743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           kTraceError,
2744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com             "RegisterExternalTransport() receive sockets already initialized");
2745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
2748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
2749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           kTraceError,
2752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com              "RegisterExternalTransport() external transport already enabled");
2753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       return -1;
2754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport = true;
2756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transportPtr = &transport;
2757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterExternalTransport()
2762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterExternalTransport()");
2765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
27669a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
276783661f534e56dfaf3542963b54b1e208f223a377xians@webrtc.org
2768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_transportPtr)
2769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
2772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterExternalTransport() external transport already "
2773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "disabled");
2774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
2775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _externalTransport = false;
2777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_EXTERNAL_TRANSPORT
2778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transportPtr = NULL;
2779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "DeRegisterExternalTransport() all transport is disabled");
2781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#else
2782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _transportPtr = &_socketTransportModule;
2783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "DeRegisterExternalTransport() internal Transport is enabled");
2785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
2786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::ReceivedRTPPacket()");
2794813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    const char dummyIP[] = "127.0.0.1";
2795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    IncomingRTPPacket(data, length, dummyIP, 0);
2796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::ReceivedRTCPPacket()");
2804813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    const char dummyIP[] = "127.0.0.1";
2805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    IncomingRTCPPacket(data, length, dummyIP, 0);
2806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifndef WEBRTC_EXTERNAL_TRANSPORT
2810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64])
2812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSourceInfo()");
2815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtpPortModule;
2817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtcpPortModule;
2818813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0};
2819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.RemoteSocketInformation(ipaddr,
2821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       rtpPortModule,
2822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       rtcpPortModule) != 0)
2823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetSourceInfo() failed to retrieve remote socket information");
2827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    strcpy(ipAddr, ipaddr);
2830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rtpPort = rtpPortModule;
2831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rtcpPort = rtcpPortModule;
2832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rtpPort, rtcpPort, ipAddr);
2836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EnableIPv6()
2841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::EnableIPv6()");
2844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.ReceiveSocketsInitialized() ||
2845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _socketTransportModule.SendSocketsInitialized())
2846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
2849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableIPv6() socket layer is already initialized");
2850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.EnableIpV6() != 0)
2853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_ERROR, kTraceError,
2856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableIPv6() failed to enable IPv6");
2857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        const UdpTransport::ErrorCode lastError =
2858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError();
2859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "UdpTransport::LastError() => %d", lastError);
2861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
2867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::IPv6IsEnabled() const
2868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool isEnabled = _socketTransportModule.IpV6Enabled();
2870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "IPv6IsEnabled() => %d", isEnabled);
2872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return isEnabled;
2873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64])
2877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSourceFilter()");
2880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.SetFilterPorts(
2881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        static_cast<WebRtc_UWord16>(rtpPort),
2882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        static_cast<WebRtc_UWord16>(rtcpPort)) != 0)
2883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSourceFilter() failed to set filter ports");
2887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        const UdpTransport::ErrorCode lastError =
2888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError();
2889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "UdpTransport::LastError() => %d",
2891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     lastError);
2892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2894813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    const char* filterIpAddress = ipAddr;
2895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0)
2896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_IP_ADDRESS, kTraceError,
2899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSourceFilter() failed to set filter IP address");
2900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        const UdpTransport::ErrorCode lastError =
2901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com           _socketTransportModule.LastError();
2902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "UdpTransport::LastError() => %d", lastError);
2904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64])
2911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSourceFilter()");
2914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtpFilterPort(0);
2915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 rtcpFilterPort(0);
2916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0)
2917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
2919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetSourceFilter() failed to retrieve filter ports");
2921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2922813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.FilterIP(ipAddrTmp) != 0)
2924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // no filter has been configured (not seen as an error)
2926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        memset(ipAddrTmp,
2927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               0, UdpTransport::kIpAddressVersion6Length);
2928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rtpPort = static_cast<int> (rtpFilterPort);
2930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rtcpPort = static_cast<int> (rtcpFilterPort);
2931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    strcpy(ipAddr, ipAddrTmp);
2932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rtpPort, rtcpPort, ipAddr);
2935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
2936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
2939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendTOS(int DSCP, int priority, bool useSetSockopt)
2940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)",
2943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 DSCP, (int)useSetSockopt);
2944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Set TOS value and possibly try to force usage of setsockopt()
2946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0)
2947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UdpTransport::ErrorCode lastSockError(
2949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError());
2950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        switch (lastSockError)
2951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kTosError:
2953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendTOS() TOS error");
2955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kQosError:
2957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
2958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    VE_TOS_GQOS_CONFLICT, kTraceError,
2959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    "SetSendTOS() GQOS error");
2960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kTosInvalid:
2962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // can't switch SetSockOpt method without disabling TOS first, or
2963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // SetSockopt() call failed
2964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError,
2965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendTOS() invalid TOS");
2966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kSocketInvalid:
2968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
2969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendTOS() invalid Socket");
2970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
2972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendTOS() TOS error");
2974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
2975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
2976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "UdpTransport =>  lastError = %d",
2978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     lastSockError);
2979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
2980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Set priority (PCP) value, -1 means don't change
2983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (-1 != priority)
2984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
2985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_socketTransportModule.SetPCP(priority) != 0)
2986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
2987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            UdpTransport::ErrorCode lastSockError(
2988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _socketTransportModule.LastError());
2989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            switch (lastSockError)
2990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
2991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case UdpTransport::kPcpError:
2992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                   "SetSendTOS() PCP error");
2994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
2995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case UdpTransport::kQosError:
2996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
2997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        VE_TOS_GQOS_CONFLICT, kTraceError,
2998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        "SetSendTOS() GQOS conflict");
2999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
3000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            case UdpTransport::kSocketInvalid:
3001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(
3002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        VE_SOCKET_ERROR, kTraceError,
3003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                        "SetSendTOS() invalid Socket");
3004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
3005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            default:
3006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                   "SetSendTOS() PCP error");
3008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
3009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
3010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceError, kTraceVoice,
3011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId,_channelId),
3012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "UdpTransport =>  lastError = %d",
3013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         lastSockError);
3014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
3015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt)
3023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)");
3026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 dscp(0), prio(0);
3027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool setSockopt(false);
3028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.ToS(dscp, setSockopt) != 0)
3029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetSendTOS() failed to get TOS info");
3033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.PCP(prio) != 0)
3036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetSendTOS() failed to get PCP info");
3040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    DSCP = static_cast<int> (dscp);
3043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    priority = static_cast<int> (prio);
3044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    useSetSockopt = setSockopt;
3045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d",
3047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        DSCP, priority, (int)useSetSockopt);
3048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#if defined(_WIN32)
3052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP)
3054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetSendGQoS(enable=%d, serviceType=%d, "
3057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "overrideDSCP=%d)",
3058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enable, serviceType, overrideDSCP);
3059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(!_socketTransportModule.ReceiveSocketsInitialized())
3060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKETS_NOT_INITED, kTraceError,
3063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() GQoS state must be set after sockets are created");
3064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(!_socketTransportModule.SendSocketsInitialized())
3067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_DESTINATION_NOT_INITED, kTraceError,
3070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() GQoS state must be set after sending side is "
3071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "initialized");
3072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enable &&
3075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       (serviceType != SERVICETYPE_BESTEFFORT) &&
3076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       (serviceType != SERVICETYPE_CONTROLLEDLOAD) &&
3077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       (serviceType != SERVICETYPE_GUARANTEED) &&
3078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       (serviceType != SERVICETYPE_QUALITATIVE))
3079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() Invalid service type");
3083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enable && ((overrideDSCP <  0) || (overrideDSCP > 63)))
3086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() Invalid overrideDSCP value");
3090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Avoid GQoS/ToS conflict when user wants to override the default DSCP
3094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // mapping
3095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool QoS(false);
3096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 sType(0);
3097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 ovrDSCP(0);
3098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.QoS(QoS, sType, ovrDSCP))
3099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() failed to get QOS info");
3103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (QoS && ovrDSCP == 0 && overrideDSCP != 0)
3106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_TOS_GQOS_CONFLICT, kTraceError,
3109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendGQoS() QOS is already enabled and overrideDSCP differs,"
3110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            " not allowed");
3111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_Word32 maxBitrate(0);
3114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_socketTransportModule.SetQoS(enable,
3115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      static_cast<WebRtc_Word32>(serviceType),
3116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      maxBitrate,
3117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      static_cast<WebRtc_Word32>(overrideDSCP),
3118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                      true))
3119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        UdpTransport::ErrorCode lastSockError(
3121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _socketTransportModule.LastError());
3122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        switch (lastSockError)
3123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
3124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case UdpTransport::kQosError:
3125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError,
3126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendGQoS() QOS error");
3127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
3128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
3129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
3130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                               "SetSendGQoS() Socket error");
3131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
3132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
3133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "UdpTransport() => lastError = %d",
3135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     lastSockError);
3136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
3141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#if defined(_WIN32)
3143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP)
3145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSendGQoS(enable=?, serviceType=?, "
3148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "overrideDSCP=?)");
3149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool QoS(false);
3151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 serviceTypeModule(0);
3152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 overrideDSCPModule(0);
3153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule);
3154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = QoS;
3156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    serviceType = static_cast<int> (serviceTypeModule);
3157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    overrideDSCP = static_cast<int> (overrideDSCPModule);
3158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d",
3161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enabled, serviceType, overrideDSCP);
3162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
3165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
3166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds)
3169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetPacketTimeoutNotification()");
3172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enable)
3173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        const WebRtc_UWord32 RTPtimeoutMS = 1000*timeoutSeconds;
3175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        const WebRtc_UWord32 RTCPtimeoutMS = 0;
31762853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->SetPacketTimeout(RTPtimeoutMS, RTCPtimeoutMS);
3177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rtpPacketTimeOutIsEnabled = true;
3178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rtpTimeOutSeconds = timeoutSeconds;
3179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
3181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
31822853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->SetPacketTimeout(0, 0);
3183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rtpPacketTimeOutIsEnabled = false;
3184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rtpTimeOutSeconds = 0;
3185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetPacketTimeoutNotification(bool& enabled, int& timeoutSeconds)
3191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetPacketTimeoutNotification()");
3194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = _rtpPacketTimeOutIsEnabled;
3195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enabled)
3196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        timeoutSeconds = _rtpTimeOutSeconds;
3198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetPacketTimeoutNotification() => enabled=%d,"
3201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " timeoutSeconds=%d",
3202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 enabled, timeoutSeconds);
3203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterDeadOrAliveObserver(VoEConnectionObserver& observer)
3208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterDeadOrAliveObserver()");
32119a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
3212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_connectionObserverPtr)
3214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, kTraceError,
3216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterDeadOrAliveObserver() observer already enabled");
3217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserverPtr = &observer;
3221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserver = true;
3222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterDeadOrAliveObserver()
3228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterDeadOrAliveObserver()");
32319a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
3232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_connectionObserverPtr)
3234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
3237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterDeadOrAliveObserver() observer already disabled");
3238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserver = false;
3242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _connectionObserverPtr = NULL;
3243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetPeriodicDeadOrAliveStatus(bool enable, int sampleTimeSeconds)
3249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetPeriodicDeadOrAliveStatus()");
3252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_connectionObserverPtr)
3253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "SetPeriodicDeadOrAliveStatus() connection observer has"
3256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " not been registered");
3257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enable)
3259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        ResetDeadOrAliveCounters();
3261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool enabled(false);
3263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8 currentSampleTimeSec(0);
3264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Store last state (will be used later if dead-or-alive is disabled).
32652853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, currentSampleTimeSec);
3266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Update the dead-or-alive state.
32672853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetPeriodicDeadOrAliveStatus(
3268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        enable, (WebRtc_UWord8)sampleTimeSeconds) != 0)
3269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR,
3272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                kTraceError,
3273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetPeriodicDeadOrAliveStatus() failed to set dead-or-alive "
3274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "status");
3275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!enable)
3278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Restore last utilized sample time.
3280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Without this, the sample time would always be reset to default
3281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // (2 sec), each time dead-or-alived was disabled without sample-time
3282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // parameter.
32832853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->SetPeriodicDeadOrAliveStatus(enable,
3284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                    currentSampleTimeSec);
3285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds)
3291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
32922853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->PeriodicDeadOrAliveStatus(
3293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        enabled,
3294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (WebRtc_UWord8&)sampleTimeSeconds);
3295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetPeriodicDeadOrAliveStatus() => enabled=%d,"
3297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " sampleTimeSeconds=%d",
3298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 enabled, sampleTimeSeconds);
3299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
3303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendUDPPacket(const void* data,
3304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       unsigned int length,
3305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       int& transmittedBytes,
3306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       bool useRtcpSocket)
3307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendUDPPacket()");
3310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_externalTransport)
3311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
3314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendUDPPacket() external transport is enabled");
3315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
33172853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (useRtcpSocket && !_rtpRtcpModule->RTCP())
3318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTCP_ERROR, kTraceError,
3321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendUDPPacket() RTCP is disabled");
3322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_sending)
3325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NOT_SENDING, kTraceError,
3328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendUDPPacket() not sending");
3329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    char* dataC = new char[length];
3333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (NULL == dataC)
3334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NO_MEMORY, kTraceError,
3337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendUDPPacket() memory allocation failed");
3338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    memcpy(dataC, data, length);
3341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket);
3343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delete [] dataC;
3345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    dataC = NULL;
3346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (transmittedBytes <= 0)
3348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_SEND_ERROR, kTraceError,
3351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SendUDPPacket() transmission failed");
3352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        transmittedBytes = 0;
3353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "SendUDPPacket() => transmittedBytes=%d", transmittedBytes);
3357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(const char* fileName,
3362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const bool loop,
3363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const FileFormats format,
3364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const int startPosition,
3365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const float volumeScaling,
3366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const int stopPosition,
3367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const CodecInst* codecInst)
3368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
3371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
3372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 startPosition, stopPosition);
3374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlaying)
3376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
3379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() is already playing");
3380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
33849a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
3385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3386b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr)
3387b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
3388b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3389b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3390b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr = NULL;
3391b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
3392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3393b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3394b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerId, (const FileFormats)format);
3395b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3396b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr == NULL)
3397b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
3398b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
3399b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_INVALID_ARGUMENT, kTraceError,
340031d30700d638c4cfa47c26cac7cb00c7232874c9henrike@webrtc.org                "StartPlayingFileLocally() filePlayer format is not correct");
3401b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
3402b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
3403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3404b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        const WebRtc_UWord32 notificationTime(0);
3405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3406b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr->StartPlayingFile(
3407b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                fileName,
3408b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                loop,
3409b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                startPosition,
3410b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                volumeScaling,
3411b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                notificationTime,
3412b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                stopPosition,
3413b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                (const CodecInst*)codecInst) != 0)
3414b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
3415b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
3416b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_BAD_FILE, kTraceError,
3417b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                "StartPlayingFile() failed to start file playout");
3418b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr->StopPlayingFile();
3419b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3420b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _outputFilePlayerPtr = NULL;
3421b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
3422b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
3423b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3424b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlaying = true;
3425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3426ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
3427ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
3428066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
3429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileLocally(InStream* stream,
3434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const FileFormats format,
3435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const int startPosition,
3436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const float volumeScaling,
3437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const int stopPosition,
3438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     const CodecInst* codecInst)
3439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileLocally(format=%d,"
3442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 format, volumeScaling, startPosition, stopPosition);
3444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(stream == NULL)
3446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() NULL as input stream");
3450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlaying)
3455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceError,
3458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileLocally() is already playing");
3459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
34639a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org      CriticalSectionScoped cs(&_fileCritSect);
3464b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3465b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      // Destroy the old instance
3466b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr)
3467b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
3468b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3469b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3470b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr = NULL;
3471b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
3472b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3473b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      // Create the instance
3474b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3475b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerId,
3476b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          (const FileFormats)format);
3477b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3478b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr == NULL)
3479b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
3480b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _engineStatisticsPtr->SetLastError(
3481b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org              VE_INVALID_ARGUMENT, kTraceError,
3482b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org              "StartPlayingFileLocally() filePlayer format isnot correct");
3483b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          return -1;
3484b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
3485b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3486b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      const WebRtc_UWord32 notificationTime(0);
3487b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3488b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3489b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 volumeScaling,
3490b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 notificationTime,
3491b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                                 stopPosition, codecInst) != 0)
3492b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      {
3493b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3494b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                             "StartPlayingFile() failed to "
3495b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                                             "start file playout");
3496b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr->StopPlayingFile();
3497b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3498b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          _outputFilePlayerPtr = NULL;
3499b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org          return -1;
3500b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      }
3501b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3502b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org      _outputFilePlaying = true;
3503b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    }
3504ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
3505ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (RegisterFilePlayingToMixer() != 0)
3506066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
3507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileLocally()
3512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayingFileLocally()");
3515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_outputFilePlaying)
3517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
3520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFileLocally() isnot playing");
3521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
35259a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
3526b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org
3527b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        if (_outputFilePlayerPtr->StopPlayingFile() != 0)
3528b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        {
3529b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            _engineStatisticsPtr->SetLastError(
3530b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                VE_STOP_RECORDING_FAILED, kTraceError,
3531b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org                "StopPlayingFile() could not stop playing");
3532b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            return -1;
3533b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        }
3534b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3535b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3536b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlayerPtr = NULL;
3537b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org        _outputFilePlaying = false;
3538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3539b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // _fileCritSect cannot be taken while calling
3540b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // SetAnonymousMixibilityStatus. Refer to comments in
3541b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org    // StartPlayingFileLocally(const char* ...) for more details.
3542066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
3543066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    {
3544066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        _engineStatisticsPtr->SetLastError(
3545066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3546b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            "StopPlayingFile() failed to stop participant from playing as"
3547b37c628ae43a9086da607a638785723306bd9aedhenrike@webrtc.org            "file in the mixer");
3548066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org        return -1;
3549066f9e5a2fbb8e83ef88ceca0ab5a4ea057cc619henrike@webrtc.org    }
3550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileLocally() const
3555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IsPlayingFileLocally()");
3558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (WebRtc_Word32)_outputFilePlaying;
3560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3562ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.orgint Channel::RegisterFilePlayingToMixer()
3563ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org{
3564ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // Return success for not registering for file playing to mixer if:
3565ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // 1. playing file before playout is started on that channel.
3566ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // 2. starting playout without file playing on that channel.
3567ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (!_playing || !_outputFilePlaying)
3568ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    {
3569ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return 0;
3570ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    }
3571ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
3572ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // |_fileCritSect| cannot be taken while calling
3573ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // SetAnonymousMixabilityStatus() since as soon as the participant is added
3574ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // frames can be pulled by the mixer. Since the frames are generated from
3575ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    // the file, _fileCritSect will be taken. This would result in a deadlock.
3576ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3577ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    {
3578ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
3579ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _outputFilePlaying = false;
3580ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _engineStatisticsPtr->SetLastError(
3581ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3582ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org            "StartPlayingFile() failed to add participant as file to mixer");
3583ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _outputFilePlayerPtr->StopPlayingFile();
3584ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3585ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        _outputFilePlayerPtr = NULL;
3586ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org        return -1;
3587ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    }
3588ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
3589ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org    return 0;
3590ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org}
3591ab12990b1b8c2410b34c055e73ed04e8a7ee1d85braveyao@webrtc.org
3592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::ScaleLocalFilePlayout(const float scale)
3593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
3596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
35979a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_outputFilePlaying)
3600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
3603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "ScaleLocalFilePlayout() isnot playing");
3604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((_outputFilePlayerPtr == NULL) ||
3607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
3608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
3611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetAudioScaling() failed to scale the playout");
3612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::GetLocalPlayoutPosition(int& positionMs)
3619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetLocalPlayoutPosition(position=?)");
3622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 position;
3624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36259a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlayerPtr == NULL)
3628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
3631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
3632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
3636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetLocalPlayoutPosition() failed");
3640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    positionMs = position;
3643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(const char* fileName,
3648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const bool loop,
3649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const FileFormats format,
3650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const int startPosition,
3651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const float volumeScaling,
3652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const int stopPosition,
3653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const CodecInst* codecInst)
3654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
3657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
3658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 startPosition, stopPosition);
3660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlaying)
3662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceWarning,
3665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() filePlayer is playing");
3666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
36699a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
3672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr)
3673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
3677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create the instance
3680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerId, (const FileFormats)format);
3682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr == NULL)
3684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
3688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 notificationTime(0);
3692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StartPlayingFile(
3694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        fileName,
3695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        loop,
3696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        startPosition,
3697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        volumeScaling,
3698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        notificationTime,
3699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        stopPosition,
3700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (const CodecInst*)codecInst) != 0)
3701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFile() failed to start file playout");
3705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->StopPlayingFile();
3706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
3708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlaying = true;
3712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartPlayingFileAsMicrophone(InStream* stream,
3717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const FileFormats format,
3718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const int startPosition,
3719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const float volumeScaling,
3720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const int stopPosition,
3721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          const CodecInst* codecInst)
3722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartPlayingFileAsMicrophone(format=%d, "
3725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 format, volumeScaling, startPosition, stopPosition);
3727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(stream == NULL)
3729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone NULL as input stream");
3733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlaying)
3737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_PLAYING, kTraceWarning,
3740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingFileAsMicrophone() is playing");
3741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
37449a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
3747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr)
3748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
3752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create the instance
3755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerId, (const FileFormats)format);
3757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr == NULL)
3759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartPlayingInputFile() filePlayer format isnot correct");
3763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 notificationTime(0);
3767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              volumeScaling, notificationTime,
3770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                              stopPosition, codecInst) != 0)
3771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "StartPlayingFile() failed to start "
3774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "file playout");
3775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr->StopPlayingFile();
3776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputFilePlayerPtr = NULL;
3778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlaying = true;
3783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopPlayingFileAsMicrophone()
3788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopPlayingFileAsMicrophone()");
3791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_inputFilePlaying)
3793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
3796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFileAsMicrophone() isnot playing");
3797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38009a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlayerPtr->StopPlayingFile() != 0)
3802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_STOP_RECORDING_FAILED, kTraceError,
3805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopPlayingFile() could not stop playing");
3806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlayerPtr = NULL;
3811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inputFilePlaying = false;
3812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::IsPlayingFileAsMicrophone() const
3817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::IsPlayingFileAsMicrophone()");
3820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _inputFilePlaying;
3822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::ScaleFileAsMicrophonePlayout(const float scale)
3825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
3828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38299a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_inputFilePlaying)
3832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
3835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "ScaleFileAsMicrophonePlayout() isnot playing");
3836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((_inputFilePlayerPtr == NULL) ||
3840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
3841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
3844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetAudioScaling() failed to scale playout");
3845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3851813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.orgint Channel::StartRecordingPlayout(const char* fileName,
3852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const CodecInst* codecInst)
3853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
3856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecording)
3858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StartRecordingPlayout() is already recording");
3861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileFormats format;
3865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
386840197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org    if ((codecInst != NULL) &&
386940197d7b3b347f05b299a930641dad131c853e01niklas.enbom@webrtc.org      ((codecInst->channels < 1) || (codecInst->channels > 2)))
3870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
3873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() invalid compression");
3874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
3875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(codecInst == NULL)
3877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatPcm16kHzFile;
3879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        codecInst=&dummyCodec;
3880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatWavFile;
3886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
3888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatCompressedFile;
3890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
38929a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
3895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr)
3896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
3900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderId, (const FileFormats)format);
3904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr == NULL)
3905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() fileRecorder format isnot correct");
3909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StartRecordingAudioFile(
3913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
3914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
3917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingAudioFile() failed to start file recording");
3918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->StopRecording();
3919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
3921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = true;
3925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
3927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
3928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StartRecordingPlayout(OutStream* stream,
3930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                   const CodecInst* codecInst)
3931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
3932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRecordingPlayout()");
3934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecording)
3936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StartRecordingPlayout() is already recording");
3939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
3940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileFormats format;
3943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (codecInst != NULL && codecInst->channels != 1)
3947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_ARGUMENT, kTraceError,
3950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() invalid compression");
3951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
3952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(codecInst == NULL)
3954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatPcm16kHzFile;
3956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        codecInst=&dummyCodec;
3957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatWavFile;
3963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
3965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        format = kFileFormatCompressedFile;
3967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
39699a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
3970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Destroy the old instance
3972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr)
3973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
3977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderId, (const FileFormats)format);
3981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr == NULL)
3982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
3984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
3985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRecordingPlayout() fileRecorder format isnot correct");
3986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
3988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
3990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                        notificationTime) != 0)
3991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "StartRecordingPlayout() failed to "
3994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           "start file recording");
3995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr->StopRecording();
3996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputFileRecorderPtr = NULL;
3998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
3999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
4002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = true;
4003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::StopRecordingPlayout()
4008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
4010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopRecordingPlayout()");
4011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_outputFileRecording)
4013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
4015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "StopRecordingPlayout() isnot recording");
4016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
40209a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_fileCritSect);
4021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_outputFileRecorderPtr->StopRecording() != 0)
4023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_STOP_RECORDING_FAILED, kTraceError,
4026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopRecording() could not stop recording");
4027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return(-1);
4028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
4030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecorderPtr = NULL;
4032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputFileRecording = false;
4033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
4038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMixWithMicStatus(bool mix)
4039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mixFileWithMicrophone=mix;
4041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSpeechOutputLevel(WebRtc_UWord32& level) const
4045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word8 currentLevel = _outputAudioLevel.Level();
4047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    level = static_cast<WebRtc_Word32> (currentLevel);
4048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSpeechOutputLevel() => level=%u", level);
4051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSpeechOutputLevelFullRange(WebRtc_UWord32& level) const
4056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word16 currentLevel = _outputAudioLevel.LevelFullRange();
4058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    level = static_cast<WebRtc_Word32> (currentLevel);
4059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSpeechOutputLevelFullRange() => level=%u", level);
4062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMute(bool enable)
4067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetMute(enable=%d)", enable);
4070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _mute = enable;
4071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
4075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::Mute() const
4076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _mute;
4078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetOutputVolumePan(float left, float right)
4082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetOutputVolumePan()");
4085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panLeft = left;
4086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _panRight = right;
4087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetOutputVolumePan(float& left, float& right) const
4092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    left = _panLeft;
4094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    right = _panRight;
4095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
4098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetChannelOutputVolumeScaling(float scaling)
4103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetChannelOutputVolumeScaling()");
4106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outputGain = scaling;
4107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetChannelOutputVolumeScaling(float& scaling) const
4112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    scaling = _outputGain;
4114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
4117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_SRTP
4121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EnableSRTPSend(
4124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CipherTypes cipherType,
4125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int cipherKeyLength,
4126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    AuthenticationTypes authType,
4127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int authKeyLength,
4128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int authTagLength,
4129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    SecurityLevels level,
4130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool useForRTCP)
4132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::EnableSRTPSend()");
4135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
41369a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encrypting)
4139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPSend() encryption already enabled");
4143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (key == NULL)
4147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceWarning,
4150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPSend() invalid key string");
4151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (((kEncryption == level ||
4155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kEncryptionAndAuthentication == level) &&
4156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (cipherKeyLength < kVoiceEngineMinSrtpEncryptLength ||
4157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength)) ||
4158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        ((kAuthentication == level ||
4159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kEncryptionAndAuthentication == level) &&
4160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kAuthHmacSha1 == authType &&
4161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length ||
4162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            authTagLength > kVoiceEngineMaxSrtpAuthSha1Length)) ||
4163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        ((kAuthentication == level ||
4164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kEncryptionAndAuthentication == level) &&
4165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kAuthNull == authType &&
4166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength ||
4167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength)))
4168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
4171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPSend() invalid key length(s)");
4172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_srtpModule.EnableSRTPEncrypt(
4177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        !useForRTCP,
4178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::CipherTypes)cipherType,
4179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        cipherKeyLength,
4180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::AuthenticationTypes)authType,
4181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        authKeyLength, authTagLength,
4182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::SecurityLevels)level,
4183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        key) == -1)
4184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SRTP_ERROR, kTraceError,
4187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPSend() failed to enable SRTP encryption");
4188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encryptionPtr == NULL)
4192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _encryptionPtr = &_srtpModule;
4194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encrypting = true;
4196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DisableSRTPSend()
4202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::DisableSRTPSend()");
4205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
42069a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_encrypting)
4209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DisableSRTPSend() SRTP encryption already disabled");
4213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encrypting = false;
4217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_srtpModule.DisableSRTPEncrypt() == -1)
4219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SRTP_ERROR, kTraceError,
4222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DisableSRTPSend() failed to disable SRTP encryption");
4223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Both directions are disabled
4229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _encryptionPtr = NULL;
4230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EnableSRTPReceive(
4237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CipherTypes  cipherType,
4238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int cipherKeyLength,
4239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    AuthenticationTypes authType,
4240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int authKeyLength,
4241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int authTagLength,
4242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    SecurityLevels level,
4243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool useForRTCP)
4245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::EnableSRTPReceive()");
4248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
42499a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_decrypting)
4252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPReceive() SRTP decryption already enabled");
4256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (key == NULL)
4260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceWarning,
4263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPReceive() invalid key string");
4264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((((kEncryption == level) ||
4268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (kEncryptionAndAuthentication == level)) &&
4269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            ((cipherKeyLength < kVoiceEngineMinSrtpEncryptLength) ||
4270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength))) ||
4271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (((kAuthentication == level) ||
4272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (kEncryptionAndAuthentication == level)) &&
4273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (kAuthHmacSha1 == authType) &&
4274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            ((authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length) ||
4275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (authTagLength > kVoiceEngineMaxSrtpAuthSha1Length))) ||
4276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (((kAuthentication == level) ||
4277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (kEncryptionAndAuthentication == level)) &&
4278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (kAuthNull == authType) &&
4279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            ((authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength) ||
4280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            (authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength))))
4281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
4284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPReceive() invalid key length(s)");
4285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_srtpModule.EnableSRTPDecrypt(
4289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        !useForRTCP,
4290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::CipherTypes)cipherType,
4291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        cipherKeyLength,
4292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::AuthenticationTypes)authType,
4293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        authKeyLength,
4294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        authTagLength,
4295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (SrtpModule::SecurityLevels)level,
4296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        key) == -1)
4297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SRTP_ERROR, kTraceError,
4300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "EnableSRTPReceive() failed to enable SRTP decryption");
4301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encryptionPtr == NULL)
4305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _encryptionPtr = &_srtpModule;
4307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _decrypting = true;
4310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DisableSRTPReceive()
4316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::DisableSRTPReceive()");
4319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
43209a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_decrypting)
4323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DisableSRTPReceive() SRTP decryption already disabled");
4327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _decrypting = false;
4331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_srtpModule.DisableSRTPDecrypt() == -1)
4333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SRTP_ERROR, kTraceError,
4336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DisableSRTPReceive() failed to disable SRTP decryption");
4337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _encryptionPtr = NULL;
4343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif
4349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterExternalEncryption(Encryption& encryption)
4352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::RegisterExternalEncryption()");
4355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
43569a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_encryptionPtr)
4359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
4362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterExternalEncryption() encryption already enabled");
4363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encryptionPtr = &encryption;
4367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _decrypting = true;
4369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encrypting = true;
4370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterExternalEncryption()
4376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::DeRegisterExternalEncryption()");
4379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
43809a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_encryptionPtr)
4383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterExternalEncryption() encryption already disabled");
4387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _decrypting = false;
4391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encrypting = false;
4392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _encryptionPtr = NULL;
4394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventOutband(unsigned char eventCode,
4399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          int lengthMs, int attenuationDb,
4400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          bool playDtmfEvent)
4401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
4404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               playDtmfEvent);
4405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playOutbandDtmfEvent = playDtmfEvent;
4407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
44082853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
4409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                 attenuationDb) != 0)
4410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SEND_DTMF_FAILED,
4413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kTraceWarning,
4414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendTelephoneEventOutband() failed to send event");
4415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::SendTelephoneEventInband(unsigned char eventCode,
4421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         int lengthMs,
4422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         int attenuationDb,
4423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                         bool playDtmfEvent)
4424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
4427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               playDtmfEvent);
4428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _playInbandDtmfEvent = playDtmfEvent;
4430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
4431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetDtmfPlayoutStatus(bool enable)
4437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetDtmfPlayoutStatus()");
4440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
4441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
4444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetDtmfPlayoutStatus() failed to set Dtmf playout");
4445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
4451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DtmfPlayoutStatus() const
4452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _audioCodingModule.DtmfPlayoutStatus();
4454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetSendTelephoneEventPayloadType(unsigned char type)
4458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4459470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetSendTelephoneEventPayloadType()");
4461f81f9f8c2a18fb20ee60406ece45ff3210367ff9andrew@webrtc.org    if (type > 127)
4462470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
4465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendTelephoneEventPayloadType() invalid type");
4466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
44681da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    CodecInst codec;
44691da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    codec.plfreq = 8000;
44701da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    codec.pltype = type;
44711da1ce0da5fcc029dbc2a134a9760e1b398b02d7pwestin@webrtc.org    memcpy(codec.plname, "telephone-event", 16);
44722853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
4473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetSendTelephoneEventPayloadType() failed to register send"
4477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "payload type");
4478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _sendTelephoneEventPayloadType = type;
4481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetSendTelephoneEventPayloadType(unsigned char& type)
4486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetSendTelephoneEventPayloadType()");
4489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    type = _sendTelephoneEventPayloadType;
4490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetSendTelephoneEventPayloadType() => type=%u", type);
4493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_DTMF_DETECTION
4497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
4499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterTelephoneEventDetection(
4500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    TelephoneEventDetectionMethods detectionMethod,
4501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    VoETelephoneEventObserver& observer)
4502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterTelephoneEventDetection()");
45059a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_telephoneEventDetectionPtr)
4508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
4511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterTelephoneEventDetection() detection already enabled");
4512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _telephoneEventDetectionPtr = &observer;
4516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (detectionMethod)
4518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kInBand:
4520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandTelephoneEventDetection = true;
4521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outOfBandTelephoneEventDetecion = false;
4522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kOutOfBand:
4524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandTelephoneEventDetection = false;
4525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outOfBandTelephoneEventDetecion = true;
4526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kInAndOutOfBand:
4528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandTelephoneEventDetection = true;
4529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outOfBandTelephoneEventDetecion = true;
4530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
4532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
4533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
4534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "RegisterTelephoneEventDetection() invalid detection method");
4535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
4536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inbandTelephoneEventDetection)
4539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Enable in-band Dtmf detectin in the ACM.
4541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_audioCodingModule.RegisterIncomingMessagesCallback(this) != 0)
4542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
4544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "RegisterTelephoneEventDetection() failed to enable Dtmf "
4546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "detection");
4547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Enable/disable out-of-band detection of received telephone-events.
4551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // When enabled, RtpAudioFeedback::OnReceivedTelephoneEvent() will be
4552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // called two times by the RTP/RTCP module (start & end).
4553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool forwardToDecoder =
45542853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->TelephoneEventForwardToDecoder();
4555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool detectEndOfTone = true;
45562853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->SetTelephoneEventStatus(_outOfBandTelephoneEventDetecion,
4557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           forwardToDecoder,
4558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                           detectEndOfTone);
4559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterTelephoneEventDetection()
4565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterTelephoneEventDetection()");
4568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
45699a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_telephoneEventDetectionPtr)
4572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION,
4575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            kTraceWarning,
4576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterTelephoneEventDetection() detection already disabled");
4577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Disable out-of-band event detection
4581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const bool forwardToDecoder =
45822853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        _rtpRtcpModule->TelephoneEventForwardToDecoder();
45832853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->SetTelephoneEventStatus(false, forwardToDecoder);
4584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Disable in-band Dtmf detection
4586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioCodingModule.RegisterIncomingMessagesCallback(NULL);
4587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _inbandTelephoneEventDetection = false;
4589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _outOfBandTelephoneEventDetecion = false;
4590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _telephoneEventDetectionPtr = NULL;
4591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetTelephoneEventDetectionStatus(
4597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool& enabled,
4598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    TelephoneEventDetectionMethods& detectionMethod)
4599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetTelephoneEventDetectionStatus()");
4602470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
46049a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
4605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        enabled = (_telephoneEventDetectionPtr != NULL);
4606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enabled)
4609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inbandTelephoneEventDetection && !_outOfBandTelephoneEventDetecion)
4611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            detectionMethod = kInBand;
4612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else if (!_inbandTelephoneEventDetection
4613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            && _outOfBandTelephoneEventDetecion)
4614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            detectionMethod = kOutOfBand;
4615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else if (_inbandTelephoneEventDetection
4616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            && _outOfBandTelephoneEventDetecion)
4617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            detectionMethod = kInAndOutOfBand;
4618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
4619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
4620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            assert(false);
4621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
4622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
4623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId, _channelId),
4627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetTelephoneEventDetectionStatus() => enabled=%d,"
4628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "detectionMethod=%d", enabled, detectionMethod);
4629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif  // #ifdef WEBRTC_DTMF_DETECTION
4633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateRxVadDetection(AudioFrame& audioFrame)
4636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::UpdateRxVadDetection()");
4639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    int vadDecision = 1;
4641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
464263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
4643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
4645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        OnRxVadDetected(vadDecision);
4647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _oldVadDecision = vadDecision;
4648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::UpdateRxVadDetection() => vadDecision=%d",
4652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 vadDecision);
4653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterRxVadObserver(VoERxVadCallback &observer)
4658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterRxVadObserver()");
46619a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxVadObserverPtr)
4664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
4667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterRxVadObserver() observer already enabled");
4668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxVadObserverPtr = &observer;
4671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection = true;
4672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterRxVadObserver()
4677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterRxVadObserver()");
46809a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_rxVadObserverPtr)
4683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterRxVadObserver() observer already disabled");
4687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxVadObserverPtr = NULL;
4690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _RxVadDetection = false;
4691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::VoiceActivityIndicator(int &activity)
4696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    activity = _sendFrameType;
4698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::VoiceActivityIndicator(indicator=%d)", activity);
4701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_AGC
4705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRxAgcStatus(const bool enable, const AgcModes mode)
4708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
4711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enable, (int)mode);
4712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    GainControl::Mode agcMode(GainControl::kFixedDigital);
4714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
4715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcDefault:
4717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode = GainControl::kAdaptiveDigital;
4718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcUnchanged:
4720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode = _rxAudioProcessingModulePtr->gain_control()->mode();
4721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcFixedDigital:
4723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode = GainControl::kFixedDigital;
4724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kAgcAdaptiveDigital:
4726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            agcMode =GainControl::kAdaptiveDigital;
4727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
4729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
4730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_ARGUMENT, kTraceError,
4731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "SetRxAgcStatus() invalid Agc mode");
4732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
4733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->set_mode(agcMode) != 0)
4736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Agc mode");
4740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->Enable(enable) != 0)
4743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Agc state");
4747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxAgcIsEnabled = enable;
4751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
4758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetRxAgcStatus(enable=?, mode=?)");
4761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool enable = _rxAudioProcessingModulePtr->gain_control()->is_enabled();
4763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    GainControl::Mode agcMode =
4764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->gain_control()->mode();
4765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = enable;
4767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (agcMode)
4769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case GainControl::kFixedDigital:
4771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kAgcFixedDigital;
4772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case GainControl::kAdaptiveDigital:
4774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kAgcAdaptiveDigital;
4775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        default:
4777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
4778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_APM_ERROR, kTraceError,
4779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "GetRxAgcStatus() invalid Agc mode");
4780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
4781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRxAgcConfig(const AgcConfig config)
4788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxAgcConfig()");
4791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->set_target_level_dbfs(
4793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.targetLeveldBOv) != 0)
4794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set target peak |level|"
4798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "(or envelope) of the Agc");
4799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->set_compression_gain_db(
4802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.digitalCompressionGaindB) != 0)
4803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set the range in |gain| the"
4807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            " digital compression stage may apply");
4808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->gain_control()->enable_limiter(
4811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        config.limiterEnable) != 0)
4812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcConfig() failed to set hard limiter to the signal");
4816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxAgcConfig(AgcConfig& config)
4824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRxAgcConfig(config=%?)");
4827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.targetLeveldBOv =
4829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->gain_control()->target_level_dbfs();
4830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.digitalCompressionGaindB =
4831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->gain_control()->compression_gain_db();
4832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    config.limiterEnable =
4833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->gain_control()->is_limiter_enabled();
4834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
4837470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
4838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   " limiterEnable=%d",
4839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.targetLeveldBOv,
4840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.digitalCompressionGaindB,
4841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   config.limiterEnable);
4842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4844470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
4847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#ifdef WEBRTC_VOICE_ENGINE_NR
4849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRxNsStatus(const bool enable, const NsModes mode)
4852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
4855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 (int)enable, (int)mode);
4856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NoiseSuppression::Level nsLevel(
4858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
4859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (mode)
4860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsDefault:
4863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = (NoiseSuppression::Level)
4864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
4865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsUnchanged:
4867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = _rxAudioProcessingModulePtr->noise_suppression()->level();
4868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsConference:
4870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kHigh;
4871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsLowSuppression:
4873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kLow;
4874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsModerateSuppression:
4876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kModerate;
4877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsHighSuppression:
4879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kHigh;
4880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case kNsVeryHighSuppression:
4882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            nsLevel = NoiseSuppression::kVeryHigh;
4883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(nsLevel)
4887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        != 0)
4888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Ns level");
4892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(enable) != 0)
4895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_APM_ERROR, kTraceError,
4898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRxAgcStatus() failed to set Agc state");
4899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxNsIsEnabled = enable;
4903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRxNsStatus(bool& enabled, NsModes& mode)
4910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRxNsStatus(enable=?, mode=?)");
4913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool enable =
4915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->noise_suppression()->is_enabled();
4916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NoiseSuppression::Level ncLevel =
4917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _rxAudioProcessingModulePtr->noise_suppression()->level();
4918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = enable;
4920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    switch (ncLevel)
4922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kLow:
4924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsLowSuppression;
4925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kModerate:
4927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsModerateSuppression;
4928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kHigh:
4930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsHighSuppression;
4931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        case NoiseSuppression::kVeryHigh:
4933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            mode = kNsVeryHighSuppression;
4934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            break;
4935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId,_channelId),
4939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
4940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
4944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterRTPObserver(VoERTPObserver& observer)
4947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterRTPObserver()");
49509a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtpObserverPtr)
4953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
4956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterRTPObserver() observer already enabled");
4957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
4958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpObserverPtr = &observer;
4961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpObserver = true;
4962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterRTPObserver()
4968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterRTPObserver()");
49719a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_rtpObserverPtr)
4974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
4977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterRTPObserver() observer already disabled");
4978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
4979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
4980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpObserver = false;
4982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtpObserverPtr = NULL;
4983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
4985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
4986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
4988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterRTCPObserver(VoERTCPObserver& observer)
4989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterRTCPObserver()");
49929a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
4993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_rtcpObserverPtr)
4995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
4997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceError,
4998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RegisterRTCPObserver() observer already enabled");
4999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtcpObserverPtr = &observer;
5003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtcpObserver = true;
5004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::DeRegisterRTCPObserver()
5010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterRTCPObserver()");
50139a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
5014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_rtcpObserverPtr)
5016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_OPERATION, kTraceWarning,
5019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "DeRegisterRTCPObserver() observer already disabled");
5020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
5021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtcpObserver = false;
5024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _rtcpObserverPtr = NULL;
5025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetLocalSSRC(unsigned int ssrc)
5031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetLocalSSRC()");
5034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
5035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_ALREADY_SENDING, kTraceError,
5038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalSSRC() already sending");
5039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
50412853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
5042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetLocalSSRC() failed to set SSRC");
5046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetLocalSSRC(unsigned int& ssrc)
5053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
50542853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    ssrc = _rtpRtcpModule->SSRC();
5055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
5057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetLocalSSRC() => ssrc=%lu", ssrc);
5058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteSSRC(unsigned int& ssrc)
5063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
50642853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    ssrc = _rtpRtcpModule->RemoteSSRC();
5065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
5067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteSSRC() => ssrc=%lu", ssrc);
5068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteCSRCs(unsigned int arrCSRC[15])
5073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (arrCSRC == NULL)
5075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRemoteCSRCs() invalid array argument");
5079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize];
5082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 CSRCs(0);
50832853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    CSRCs = _rtpRtcpModule->CSRCs(arrOfCSRC);
5084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (CSRCs > 0)
5085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(WebRtc_UWord32));
5087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        for (int i = 0; i < (int) CSRCs; i++)
5088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       VoEId(_instanceId, _channelId),
5091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
5092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else
5094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   VoEId(_instanceId, _channelId),
5097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   "GetRemoteCSRCs() => list is empty!");
5098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return CSRCs;
5100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
5104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5105755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    if (_rtpAudioProc.get() == NULL)
5106755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    {
5107755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        _rtpAudioProc.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
5108755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                                                                _channelId)));
5109755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        if (_rtpAudioProc.get() == NULL)
5110755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        {
5111755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            _engineStatisticsPtr->SetLastError(VE_NO_MEMORY, kTraceCritical,
5112755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                "Failed to create AudioProcessing");
5113755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            return -1;
5114755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        }
5115755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    }
5116755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
5117755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    if (_rtpAudioProc->level_estimator()->Enable(enable) !=
5118755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        AudioProcessing::kNoError)
5119755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    {
5120755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceWarning,
5121755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            "Failed to enable AudioProcessing::level_estimator()");
5122755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    }
5123755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
5124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _includeAudioLevelIndication = enable;
51252853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
5126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
5129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
5132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
5133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 enabled, ID);
51342853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
5135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRTCPStatus(bool enable)
5139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRTCPStatus()");
51422853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetRTCPStatus(enable ?
5143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        kRtcpCompound : kRtcpOff) != 0)
5144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRTCPStatus() failed to set RTCP status");
5148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5150470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTCPStatus(bool& enabled)
5155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
51562853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RTCPMethod method = _rtpRtcpModule->RTCP();
5157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = (method != kRtcpOff);
5158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
5160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTCPStatus() => enabled=%d", enabled);
5161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetRTCP_CNAME(const char cName[256])
5166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetRTCP_CNAME()");
51692853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetCNAME(cName) != 0)
5170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetRTCP_CNAME() failed to set RTCP CNAME");
5174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTCP_CNAME(char cName[256])
5181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
51822853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->CNAME(cName) != 0)
5183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
5187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTCP_CNAME() => cName=%s", cName);
5192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCP_CNAME(char cName[256])
5197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (cName == NULL)
5199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
5203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5205813e4b0af06272dada388c2d8383b2e36a1da6a6leozwang@webrtc.org    char cname[RTCP_CNAME_SIZE];
52062853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    const WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
52072853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
5208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_RETRIEVE_CNAME, kTraceError,
5211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
5212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    strcpy(cName, cname);
5215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCP_CNAME() => cName=%s", cName);
5218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRemoteRTCPData(
5223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& NTPHigh,
5224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& NTPLow,
5225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& timestamp,
5226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int& playoutTimestamp,
5227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned int* jitter,
5228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    unsigned short* fractionLost)
5229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Information from sender info in received Sender Reports
5231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RTCPSenderInfo senderInfo;
52332853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
5234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5237fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            "GetRemoteRTCPData() failed to retrieve sender info for remote "
5238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "side");
5239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // We only utilize 12 out of 20 bytes in the sender info (ignores packet
5243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // and octet count)
5244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NTPHigh = senderInfo.NTPseconds;
5245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    NTPLow = senderInfo.NTPfraction;
5246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    timestamp = senderInfo.RTPtimeStamp;
5247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
5251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "timestamp=%lu",
5252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 NTPHigh, NTPLow, timestamp);
5253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Locally derived information
5255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This value is updated on each incoming RTCP packet (0 when no packet
5257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // has been received)
5258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    playoutTimestamp = _playoutTimeStampRTCP;
5259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRemoteRTCPData() => playoutTimestamp=%lu",
5263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 _playoutTimeStampRTCP);
5264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (NULL != jitter || NULL != fractionLost)
5266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5267ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // Get all RTCP receiver report blocks that have been received on this
5268ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // channel. If we receive RTP packets from a remote source we know the
5269ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // remote SSRC and use the report block from him.
5270ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        // Otherwise use the first report block.
5271ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        std::vector<RTCPReportBlock> remote_stats;
52722853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
5273ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org            remote_stats.empty()) {
5274ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5275ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       VoEId(_instanceId, _channelId),
5276ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       "GetRemoteRTCPData() failed to measure statistics due"
5277ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org                       " to lack of received RTP and/or RTCP packets");
5278ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          return -1;
5279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5280ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
52812853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5282ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
5283ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        for (; it != remote_stats.end(); ++it) {
5284ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          if (it->remoteSSRC == remoteSSRC)
5285ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org            break;
5286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5287ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
5288ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org        if (it == remote_stats.end()) {
5289ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // If we have not received any RTCP packets from this SSRC it probably
5290ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // means that we have not received any RTP packets.
5291ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          // Use the first received report block instead.
5292ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          it = remote_stats.begin();
5293ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org          remoteSSRC = it->remoteSSRC;
5294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5295ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
529679af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        if (jitter) {
529779af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          *jitter = it->jitter;
529879af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
529979af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       VoEId(_instanceId, _channelId),
530079af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       "GetRemoteRTCPData() => jitter = %lu", *jitter);
530179af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        }
5302ce5990cb0bbfbf5ee5306cf990e975a2faa090b7perkj@webrtc.org
530379af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        if (fractionLost) {
530479af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          *fractionLost = it->fractionLost;
530579af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
530679af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       VoEId(_instanceId, _channelId),
530779af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       "GetRemoteRTCPData() => fractionLost = %lu",
530879af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org                       *fractionLost);
530979af734807109d119573ce23daa1a2bff0f0eecaxians@webrtc.org        }
5310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendApplicationDefinedRTCPPacket(const unsigned char subType,
5316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             unsigned int name,
5317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             const char* data,
5318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                             unsigned short dataLengthInBytes)
5319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SendApplicationDefinedRTCPPacket()");
5322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_sending)
5323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NOT_SENDING, kTraceError,
5326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() not sending");
5327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (NULL == data)
5330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() invalid data value");
5334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (dataLengthInBytes % 4 != 0)
5337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5338470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() invalid length value");
5341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
53432853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RTCPMethod status = _rtpRtcpModule->RTCP();
5344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (status == kRtcpOff)
5345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTCP_ERROR, kTraceError,
5348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() RTCP is disabled");
5349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create and schedule the RTCP APP packet for transmission
53532853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
5354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        subType,
5355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        name,
5356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (const unsigned char*) data,
5357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        dataLengthInBytes) != 0)
5358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SEND_ERROR, kTraceError,
5361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
5362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics(
5369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& averageJitterMs,
5370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& maxJitterMs,
5371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        unsigned int& discardedPackets)
5372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8 fraction_lost(0);
5374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 cum_lost(0);
5375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 ext_max(0);
5376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 jitter(0);
5377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 max_jitter(0);
5378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The jitter statistics is updated for each received RTP packet and is
5380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // based on received packets.
53812853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
5382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &cum_lost,
5383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &ext_max,
5384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &jitter,
5385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &max_jitter) != 0)
5386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5389fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org            "GetRTPStatistics() failed to read RTP statistics from the "
5390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RTP/RTCP module");
5391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_Word32 playoutFrequency =
5394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _audioCodingModule.PlayoutFrequency();
5395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (playoutFrequency > 0)
5396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Scale RTP statistics given the current playout frequency
5398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        maxJitterMs = max_jitter / (playoutFrequency / 1000);
5399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        averageJitterMs = jitter / (playoutFrequency / 1000);
5400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    discardedPackets = _numberOfDiscardedPackets;
5403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               VoEId(_instanceId, _channelId),
5406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
5407fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org               " discardedPackets = %lu)",
5408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               averageJitterMs, maxJitterMs, discardedPackets);
5409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
54128a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.orgint Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
54138a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (sender_info == NULL) {
54148a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
54158a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org        "GetRemoteRTCPSenderInfo() invalid sender_info.");
54168a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
54178a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
54188a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54198a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // Get the sender info from the latest received RTCP Sender Report.
54208a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  RTCPSenderInfo rtcp_sender_info;
54218a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
54228a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
54238a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org        "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
54248a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
54258a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
54268a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54278a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
54288a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
54298a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
54308a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
54318a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
54328a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  return 0;
54338a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org}
54348a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54358a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.orgint Channel::GetRemoteRTCPReportBlocks(
54368a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    std::vector<ReportBlock>* report_blocks) {
54378a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (report_blocks == NULL) {
54388a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
54398a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org      "GetRemoteRTCPReportBlock()s invalid report_blocks.");
54408a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
54418a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
54428a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54438a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // Get the report blocks from the latest received RTCP Sender or Receiver
54448a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // Report. Each element in the vector contains the sender's SSRC and a
54458a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  // report block according to RFC 3550.
54468a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  std::vector<RTCPReportBlock> rtcp_report_blocks;
54478a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
54488a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
54498a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org        "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
54508a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return -1;
54518a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
54528a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54538a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  if (rtcp_report_blocks.empty())
54548a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    return 0;
54558a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
54568a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
54578a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  for (; it != rtcp_report_blocks.end(); ++it) {
54588a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    ReportBlock report_block;
54598a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.sender_SSRC = it->remoteSSRC;
54608a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.source_SSRC = it->sourceSSRC;
54618a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.fraction_lost = it->fractionLost;
54628a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.cumulative_num_packets_lost = it->cumulativeLost;
54638a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
54648a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.interarrival_jitter = it->jitter;
54658a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.last_SR_timestamp = it->lastSR;
54668a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_block.delay_since_last_SR = it->delaySinceLastSR;
54678a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org    report_blocks->push_back(report_block);
54688a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  }
54698a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org  return 0;
54708a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org}
54718a2fc88459dc507a67594e3127143e16af612fc9henrika@webrtc.org
5472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRTPStatistics(CallStatistics& stats)
5474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8 fraction_lost(0);
5476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 cum_lost(0);
5477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 ext_max(0);
5478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 jitter(0);
5479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 max_jitter(0);
5480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Part one of the final structure (four values)
5482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The jitter statistics is updated for each received RTP packet and is
5484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // based on received packets.
54852853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
5486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &cum_lost,
5487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &ext_max,
5488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &jitter,
5489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                     &max_jitter) != 0)
5490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetRTPStatistics() failed to read RTP statistics from the "
5494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RTP/RTCP module");
5495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.fractionLost = fraction_lost;
5498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.cumulativeLost = cum_lost;
5499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.extendedMax = ext_max;
5500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.jitterSamples = jitter;
5501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
5505fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " extendedMax=%lu, jitterSamples=%li)",
5506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
5507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.jitterSamples);
5508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Part two of the final structure (one value)
5510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 RTT(0);
55122853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    RTCPMethod method = _rtpRtcpModule->RTCP();
5513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (method == kRtcpOff)
5514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
5517fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                     "GetRTPStatistics() RTCP is disabled => valid RTT "
5518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "measurements cannot be retrieved");
5519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else
5520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // The remote SSRC will be zero if no RTP packet has been received.
55222853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (remoteSSRC > 0)
5524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_UWord16 avgRTT(0);
5526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_UWord16 maxRTT(0);
5527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_UWord16 minRTT(0);
5528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
55292853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org            if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
5530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                != 0)
5531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            {
5532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             VoEId(_instanceId, _channelId),
5534fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                             "GetRTPStatistics() failed to retrieve RTT from "
5535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             "the RTP/RTCP module");
5536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
5537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        } else
5538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
5541fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                         "GetRTPStatistics() failed to measure RTT since no "
5542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "RTP packets have been received yet");
5543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.rttMs = static_cast<int> (RTT);
5547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
5551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Part three of the final structure (four values)
5553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 bytesSent(0);
5555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 packetsSent(0);
5556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 bytesReceived(0);
5557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 packetsReceived(0);
5558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
55592853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
5560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                       &packetsSent,
5561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                       &bytesReceived,
5562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                       &packetsReceived) != 0)
5563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     VoEId(_instanceId, _channelId),
5566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "GetRTPStatistics() failed to retrieve RTP datacounters =>"
5567fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                     " output will not be complete");
5568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.bytesSent = bytesSent;
5571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.packetsSent = packetsSent;
5572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.bytesReceived = bytesReceived;
5573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    stats.packetsReceived = packetsReceived;
5574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
5578fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                 " bytesReceived=%d, packetsReceived=%d)",
5579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
5580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 stats.packetsReceived);
5581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
558542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::SetFECStatus(bool enable, int redPayloadtype) {
558642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
558742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org               "Channel::SetFECStatus()");
558842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
558942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (SetRedPayloadType(redPayloadtype) < 0) {
559042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
559142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_CODEC_ERROR, kTraceError,
559242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetSecondarySendCodec() Failed to register RED ACM");
559342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
559442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
55952cf22a6abce2d38e673505a4cfd5624a3710b5cdperkj@webrtc.org
559642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_audioCodingModule.SetFECStatus(enable) != 0) {
559742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
559842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
559942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetFECStatus() failed to set FEC state in the ACM");
560042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
560142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
560242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
5603470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetFECStatus(bool& enabled, int& redPayloadtype)
5607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    enabled = _audioCodingModule.FECStatus();
5609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (enabled)
5610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_Word8 payloadType(0);
56122853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org        if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
5613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
5615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
5617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "module");
5618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
5619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   VoEId(_instanceId, _channelId),
5622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   "GetFECStatus() => enabled=%d, redPayloadtype=%d",
5623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                   enabled, redPayloadtype);
5624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
5625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId, _channelId),
5628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetFECStatus() => enabled=%d", enabled);
5629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StartRTPDump(const char fileNameUTF8[1024],
5634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                      RTPDirections direction)
5635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StartRTPDump()");
5638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRTPDump() invalid RTP direction");
5643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
5647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr == NULL)
5648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        assert(false);
5650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr->IsActive())
5653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        rtpDumpPtr->Stop();
5655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr->Start(fileNameUTF8) != 0)
5657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_BAD_FILE, kTraceError,
5660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StartRTPDump() failed to create file");
5661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::StopRTPDump(RTPDirections direction)
5668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::StopRTPDump()");
5671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "StopRTPDump() invalid RTP direction");
5676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
5680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rtpDumpPtr == NULL)
5681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        assert(false);
5683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!rtpDumpPtr->IsActive())
5686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
5688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return rtpDumpPtr->Stop();
5690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.combool
5693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RTPDumpIsActive(RTPDirections direction)
5694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((direction != kRtpIncoming) &&
5696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (direction != kRtpOutgoing))
5697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "RTPDumpIsActive() invalid RTP direction");
5701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return false;
5702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        &_rtpDumpIn : &_rtpDumpOut;
5705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return rtpDumpPtr->IsActive();
5706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::InsertExtraRTPPacket(unsigned char payloadType,
5710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              bool markerBit,
5711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              const char* payloadData,
5712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                              unsigned short payloadSize)
5713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::InsertExtraRTPPacket()");
5716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (payloadType > 127)
5717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_PLTYPE, kTraceError,
5720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "InsertExtraRTPPacket() invalid payload type");
5721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (payloadData == NULL)
5724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "InsertExtraRTPPacket() invalid payload data");
5728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
57302853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (payloadSize > _rtpRtcpModule->MaxDataPayloadLength())
5731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
5734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "InsertExtraRTPPacket() invalid payload size");
5735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!_sending)
5738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_NOT_SENDING, kTraceError,
5741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "InsertExtraRTPPacket() not sending");
5742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
5746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Transport::SendPacket() will be called by the module when the RTP packet
5747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // is created.
5748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The call to SendOutgoingData() does *not* modify the timestamp and
5749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // payloadtype to ensure that the RTP module generates a valid RTP packet
5750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // (user might utilize a non-registered payload type).
5751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The marker bit and payload type will be replaced just before the actual
5752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // transmission, i.e., the actual modification is done *after* the RTP
5753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // module has delivered its RTP packet back to the VoE.
5754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // We will use the stored values above when the packet is modified
5755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // (see Channel::SendPacket()).
5756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _extraPayloadType = payloadType;
5758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _extraMarkerBit = markerBit;
5759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _insertExtraRTPPacket = true;
5760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
57612853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SendOutgoingData(kAudioFrameSpeech,
5762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        _lastPayloadType,
5763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        _lastLocalTimeStamp,
5764ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // Leaving the time when this frame was
5765ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // received from the capture device as
5766ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        // undefined for voice for now.
5767ddfdfed3b55de3da5fda9a55d34e46d6e422baafstefan@webrtc.org                                        -1,
5768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        (const WebRtc_UWord8*) payloadData,
5769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                        payloadSize) != 0)
5770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
5772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "InsertExtraRTPPacket() failed to send extra RTP packet");
5774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_UWord32
5781755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.orgChannel::Demultiplex(const AudioFrame& audioFrame)
5782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5784755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                 "Channel::Demultiplex()");
5785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _audioFrame = audioFrame;
578663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.id_ = _channelId;
5787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_UWord32
57910b0665acc1464d68e878f203bbc8772a0e32402dxians@google.comChannel::PrepareEncodeAndSend(int mixingFrequency)
5792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::PrepareEncodeAndSend()");
5795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
579663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (_audioFrame.samples_per_channel_ == 0)
5797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::PrepareEncodeAndSend() invalid audio frame");
5800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputFilePlaying)
5804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        MixOrReplaceAudioWithFile(mixingFrequency);
5806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_mute)
5809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        AudioFrameOperations::Mute(_audioFrame);
5811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inputExternalMedia)
5814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
58159a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_callbackCritSect);
581663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        const bool isStereo = (_audioFrame.num_channels_ == 2);
5817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputExternalMediaCallbackPtr)
5818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inputExternalMediaCallbackPtr->Process(
5820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _channelId,
5821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                kRecordingPerChannel,
582263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org               (WebRtc_Word16*)_audioFrame.data_,
582363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                _audioFrame.samples_per_channel_,
582463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                _audioFrame.sample_rate_hz_,
5825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                isStereo);
5826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    InsertInbandDtmfTone();
5830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5831755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    if (_includeAudioLevelIndication)
5832755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    {
5833755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        assert(_rtpAudioProc.get() != NULL);
5834755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
5835755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        // Check if settings need to be updated.
583663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (_rtpAudioProc->sample_rate_hz() != _audioFrame.sample_rate_hz_)
5837755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        {
583863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            if (_rtpAudioProc->set_sample_rate_hz(_audioFrame.sample_rate_hz_) !=
5839755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                AudioProcessing::kNoError)
5840755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            {
5841755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5842755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                             VoEId(_instanceId, _channelId),
5843755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                             "Error setting AudioProcessing sample rate");
5844755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                return -1;
5845755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            }
5846755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        }
5847755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
584863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (_rtpAudioProc->num_input_channels() != _audioFrame.num_channels_)
5849755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        {
585063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            if (_rtpAudioProc->set_num_channels(_audioFrame.num_channels_,
585163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                                                _audioFrame.num_channels_)
5852755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                != AudioProcessing::kNoError)
5853755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            {
5854755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5855755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                             VoEId(_instanceId, _channelId),
5856755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                             "Error setting AudioProcessing channels");
5857755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org                return -1;
5858755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org            }
5859755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        }
5860755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
5861755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        // Performs level analysis only; does not affect the signal.
5862755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org        _rtpAudioProc->ProcessStream(&_audioFrame);
5863755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org    }
5864755b04a06ec4ae91ae7fb601c641e683f4e9e87dandrew@webrtc.org
5865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_UWord32
5869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::EncodeAndSend()
5870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::EncodeAndSend()");
5873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
587463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    assert(_audioFrame.num_channels_ <= 2);
587563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (_audioFrame.samples_per_channel_ == 0)
5876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::EncodeAndSend() invalid audio frame");
5879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
588263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.id_ = _channelId;
5883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
5885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The ACM resamples internally.
588763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _audioFrame.timestamp_ = _timeStamp;
5888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
5889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
5891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::EncodeAndSend() ACM encoding failed");
5892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
5893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
589563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    _timeStamp += _audioFrame.samples_per_channel_;
5896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // --- Encode if complete frame is ready
5898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This call will trigger AudioPacketizationCallback::SendData if encoding
5900470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // is done and payload is ready for packetization and transmission.
5901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _audioCodingModule.Process();
5902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::RegisterExternalMediaProcessing(
5905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ProcessingTypes type,
5906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    VoEMediaProcess& processObject)
5907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterExternalMediaProcessing()");
5910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
59119a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
5912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (kPlaybackPerChannel == type)
5914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputExternalMediaCallbackPtr)
5916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
5918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceError,
5919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::RegisterExternalMediaProcessing() "
5920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already enabled");
5921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
5922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMediaCallbackPtr = &processObject;
5924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMedia = true;
5925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (kRecordingPerChannel == type)
5927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputExternalMediaCallbackPtr)
5929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
5931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceError,
5932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::RegisterExternalMediaProcessing() "
5933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already enabled");
5934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
5935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMediaCallbackPtr = &processObject;
5937470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMedia = true;
5938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
5943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::DeRegisterExternalMediaProcessing()");
5946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
59479a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org    CriticalSectionScoped cs(&_callbackCritSect);
5948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5949470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (kPlaybackPerChannel == type)
5950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!_outputExternalMediaCallbackPtr)
5952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
5954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceWarning,
5955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::DeRegisterExternalMediaProcessing() "
5956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "output external media already disabled");
5957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
5958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMedia = false;
5960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _outputExternalMediaCallbackPtr = NULL;
5961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (kRecordingPerChannel == type)
5963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (!_inputExternalMediaCallbackPtr)
5965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
5966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _engineStatisticsPtr->SetLastError(
5967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                VE_INVALID_OPERATION, kTraceWarning,
5968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "Channel::DeRegisterExternalMediaProcessing() "
5969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                "input external media already disabled");
5970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
5971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
5972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMedia = false;
5973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inputExternalMediaCallbackPtr = NULL;
5974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
5975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
5977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::ResetRTCPStatistics()
5981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::ResetRTCPStatistics()");
5984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 remoteSSRC(0);
59852853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    remoteSSRC = _rtpRtcpModule->RemoteSSRC();
59862853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    return _rtpRtcpModule->ResetRTT(remoteSSRC);
5987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
5988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
5990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRoundTripTimeSummary(StatVal& delaysMs) const
5991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRoundTripTimeSummary()");
5994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Override default module outputs for the case when RTCP is disabled.
5995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // This is done to ensure that we are backward compatible with the
5996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // VoiceEngine where we did not use RTP/RTCP module.
59972853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (!_rtpRtcpModule->RTCP())
5998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
5999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.min = -1;
6000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.max = -1;
6001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.average = -1;
6002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
6004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " valid RTT measurements cannot be retrieved");
6005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return 0;
6006470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6007470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6008470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 remoteSSRC;
6009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 RTT;
6010470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 avgRTT;
6011470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 maxRTT;
6012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 minRTT;
6013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // The remote SSRC will be zero if no RTP packet has been received.
60142853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    remoteSSRC = _rtpRtcpModule->RemoteSSRC();
6015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (remoteSSRC == 0)
6016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetRoundTripTimeSummary() unable to measure RTT"
6019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " since no RTP packet has been received yet");
6020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Retrieve RTT statistics from the RTP/RTCP module for the specified
6023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // channel and SSRC. The SSRC is required to parse out the correct source
6024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // in conference scenarios.
60252853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
6026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "GetRoundTripTimeSummary unable to retrieve RTT values"
6029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " from the RTCP layer");
6030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
6031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
6033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.min = minRTT;
6035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.max = maxRTT;
6036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        delaysMs.average = avgRTT;
6037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetNetworkStatistics(NetworkStatistics& stats)
6043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6044470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6045470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetNetworkStatistics()");
6046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return _audioCodingModule.NetworkStatistics(
6047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (ACMNetworkStatistics &)stats);
6048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetDelayEstimate(int& delayMs) const
6052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetDelayEstimate()");
6055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    delayMs = (_averageDelayMs + 5) / 10 + _recPacketDelayMs;
6056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6058470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6059470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6060470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetMinimumPlayoutDelay(int delayMs)
6061470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6063470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetMinimumPlayoutDelay()");
6064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
6065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
6066470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6067470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6068470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_INVALID_ARGUMENT, kTraceError,
6069470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetMinimumPlayoutDelay() invalid min delay");
6070470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6071470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6072470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
6073470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6074470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6075470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6076470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetMinimumPlayoutDelay() failed to set min playout delay");
6077470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6078470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6079470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetPlayoutTimestamp(unsigned int& timestamp)
6084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetPlayoutTimestamp()");
6087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 playoutTimestamp(0);
6088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (GetPlayoutTimeStamp(playoutTimestamp) != 0)
6089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_CANNOT_RETRIEVE_VALUE, kTraceError,
6092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "GetPlayoutTimestamp() failed to retrieve timestamp");
6093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    timestamp = playoutTimestamp;
6096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
6097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 VoEId(_instanceId,_channelId),
6098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
6099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetInitTimestamp(unsigned int timestamp)
6104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com               "Channel::SetInitTimestamp()");
6107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
6108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
6111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
61132853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
6114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetInitTimestamp() failed to set timestamp");
6118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SetInitSequenceNumber(short sequenceNumber)
6125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::SetInitSequenceNumber()");
6128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_sending)
6129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_SENDING, kTraceError,
6132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetInitSequenceNumber() already sending");
6133470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
61352853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
6136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _engineStatisticsPtr->SetLastError(
6138470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "SetInitSequenceNumber() failed to set sequence number");
6140470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetRtpRtcp(RtpRtcp* &rtpRtcpModule) const
6147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetRtpRtcp()");
61502853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    rtpRtcpModule = _rtpRtcpModule.get();
6151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6154e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
6155e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org// a shared helper.
6156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
61570b0665acc1464d68e878f203bbc8772a0e32402dxians@google.comChannel::MixOrReplaceAudioWithFile(const int mixingFrequency)
6158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6159d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
6160e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org    int fileSamples(0);
6161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
61639a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
6164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inputFilePlayerPtr == NULL)
6166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() fileplayer"
6170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             " doesnt exist");
6171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
6172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6174d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
6175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                      fileSamples,
6176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                      mixingFrequency) == -1)
6177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() file mixing "
6181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "failed");
6182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
6183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (fileSamples == 0)
6185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixOrReplaceAudioWithFile() file is ended");
6189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return 0;
6190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
619363a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    assert(_audioFrame.samples_per_channel_ == fileSamples);
6194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_mixFileWithMicrophone)
6196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6197d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
6198d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
619963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        Utility::MixWithSat(_audioFrame.data_,
6200e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                            _audioFrame.num_channels_,
6201d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                            fileBuffer.get(),
6202d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                            1,
6203e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                            fileSamples);
6204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
6206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6207d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Replace ACM audio with file.
6208d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
6209d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
6210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _audioFrame.UpdateFrame(_channelId,
6211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                -1,
6212d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                                fileBuffer.get(),
6213e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                                fileSamples,
6214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                mixingFrequency,
6215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                AudioFrame::kNormalSpeech,
6216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                AudioFrame::kVadUnknown,
6217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                1);
6218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
6224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::MixAudioWithFile(AudioFrame& audioFrame,
62250b0665acc1464d68e878f203bbc8772a0e32402dxians@google.com                          const int mixingFrequency)
6226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    assert(mixingFrequency <= 32000);
6228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6229d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
6230e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org    int fileSamples(0);
6231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
62339a065d1eae9ed296e1e2eaaad73d7ca1223bfe79mflodman@webrtc.org        CriticalSectionScoped cs(&_fileCritSect);
6234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_outputFilePlayerPtr == NULL)
6236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixAudioWithFile() file mixing failed");
6240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
6241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // We should get the frequency we ask for.
6244d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
6245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       fileSamples,
6246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                                       mixingFrequency) == -1)
6247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::MixAudioWithFile() file mixing failed");
6251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
6252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
625563a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org    if (audioFrame.samples_per_channel_ == fileSamples)
6256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6257d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // Currently file stream is always mono.
6258d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org        // TODO(xians): Change the code when FilePlayer supports real stereo.
625963a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        Utility::MixWithSat(audioFrame.data_,
6260e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                            audioFrame.num_channels_,
6261d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                            fileBuffer.get(),
6262d713143d99b205aaaa589b96443d82b36c3843e4braveyao@webrtc.org                            1,
6263e59a0aca6a0762592644ebc0282dbe244162eb8dandrew@webrtc.org                            fileSamples);
6264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
6266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
626863a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
6269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            "fileSamples(%d)",
627063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            audioFrame.samples_per_channel_, fileSamples);
6271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::InsertInbandDtmfTone()
6279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6280af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org    // Check if we should start a new tone.
6281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inbandDtmfQueue.PendingDtmf() &&
6282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        !_inbandDtmfGenerator.IsAddingTone() &&
6283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.DelaySinceLastTone() >
6284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        kMinTelephoneEventSeparationMs)
6285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_Word8 eventCode(0);
6287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 lengthMs(0);
6288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord8 attenuationDb(0);
6289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
6291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
6292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_playInbandDtmfEvent)
6293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Add tone to output mixer using a reduced length to minimize
6295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // risk of echo.
6296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
6297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                          attenuationDb);
6298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_inbandDtmfGenerator.IsAddingTone())
6302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 frequency(0);
6304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.GetSampleRate(frequency);
6305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
630663a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        if (frequency != _audioFrame.sample_rate_hz_)
6307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Update sample rate of Dtmf tone since the mixing frequency
6309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // has changed.
6310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandDtmfGenerator.SetSampleRate(
631163a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                (WebRtc_UWord16) (_audioFrame.sample_rate_hz_));
6312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Reset the tone to be added taking the new sample rate into
6313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // account.
6314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _inbandDtmfGenerator.ResetTone();
6315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6316af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org
6317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_Word16 toneBuffer[320];
6318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WebRtc_UWord16 toneSamples(0);
6319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Get 10ms tone segment and set time since last tone to zero
6320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
6321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       VoEId(_instanceId, _channelId),
6324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                       "Channel::EncodeAndSend() inserting Dtmf failed");
6325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            return -1;
6326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6328af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        // Replace mixed audio with DTMF tone.
6329af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        for (int sample = 0;
633063a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org            sample < _audioFrame.samples_per_channel_;
6331af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            sample++)
6332af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        {
6333af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            for (int channel = 0;
633463a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                channel < _audioFrame.num_channels_;
6335af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org                channel++)
6336af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            {
633763a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org                _audioFrame.data_[sample * _audioFrame.num_channels_ + channel] =
6338af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org                        toneBuffer[sample];
6339af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org            }
6340af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org        }
6341af26f646165e7e2a8747fd54e92e73f48118a807niklas.enbom@webrtc.org
634263a509858d3988299726640c664b699d6229a1d4andrew@webrtc.org        assert(_audioFrame.samples_per_channel_ == toneSamples);
6343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else
6344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Add 10ms to "delay-since-last-tone" counter
6346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _inbandDtmfGenerator.UpdateDelaySinceLastTone();
6347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
6352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetPlayoutTimeStamp(WebRtc_UWord32& playoutTimestamp)
6353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 timestamp(0);
6355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst currRecCodec;
6356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioCodingModule.PlayoutTimestamp(timestamp) == -1)
6358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetPlayoutTimeStamp() failed to read playout"
6361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " timestamp from the ACM");
6362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord16 delayMS(0);
6366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_audioDeviceModulePtr->PlayoutDelay(&delayMS) == -1)
6367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     "Channel::GetPlayoutTimeStamp() failed to read playout"
6370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                     " delay from the ADM");
6371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
6375a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6376a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6377a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        playoutFrequency = 8000;
6378a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6379a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        playoutFrequency = 48000;
6380a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      }
6381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6382470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    timestamp -= (delayMS * (playoutFrequency/1000));
6383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    playoutTimestamp = timestamp;
6385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::GetPlayoutTimeStamp() => playoutTimestamp = %lu",
6388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 playoutTimestamp);
6389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
6393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::ResetDeadOrAliveCounters()
6394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _countDeadDetections = 0;
6396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _countAliveDetections = 0;
6397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
6400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdateDeadOrAliveCounters(bool alive)
6401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (alive)
6403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _countAliveDetections++;
6404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
6405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        _countDeadDetections++;
6406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint
6409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
6410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    bool enabled;
6412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord8 timeSec;
6413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
64142853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org    _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, timeSec);
6415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!enabled)
6416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return (-1);
6417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    countDead = static_cast<int> (_countDeadDetections);
6419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    countAlive = static_cast<int> (_countAliveDetections);
6420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
6424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::SendPacketRaw(const void *data, int len, bool RTCP)
6425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (_transportPtr == NULL)
6427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return -1;
6429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (!RTCP)
6431470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return _transportPtr->SendPacket(_channelId, data, len);
6433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
6435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        return _transportPtr->SendRTCPPacket(_channelId, data, len);
6437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comWebRtc_Word32
6441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::UpdatePacketDelay(const WebRtc_UWord32 timestamp,
6442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                           const WebRtc_UWord16 sequenceNumber)
6443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
6446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 timestamp, sequenceNumber);
6447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_Word32 rtpReceiveFrequency(0);
6449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    // Get frequency of last received payload
6451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
6452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst currRecCodec;
6454a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6455a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6456a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // Even though the actual sampling rate for G.722 audio is
6457a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // 16,000 Hz, the RTP clock rate for the G722 payload format is
6458a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // 8,000 Hz because that value was erroneously assigned in
6459a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // RFC 1890 and must remain unchanged for backward compatibility.
6460a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        rtpReceiveFrequency = 8000;
6461a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6462a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // We are resampling Opus internally to 32,000 Hz until all our
6463a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // DSP routines can operate at 48,000 Hz, but the RTP clock
6464a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // rate for the Opus payload format is standardized to 48,000 Hz,
6465a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        // because that is the maximum supported decoding sampling rate.
6466a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        rtpReceiveFrequency = 48000;
6467a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org      }
6468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
6471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WebRtc_UWord32 timeStampDiffMs(0);
6472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (timeStampDiff > 0)
6474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6475a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org        switch (rtpReceiveFrequency) {
6476a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org          case 8000:
6477a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 3);
6478a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            break;
6479a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org          case 16000:
6480a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 4);
6481a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            break;
6482a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org          case 32000:
6483a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 5);
6484a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            break;
6485a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org          case 48000:
6486a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff / 48);
6487a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            break;
6488a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org          default:
6489a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6490a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                         VoEId(_instanceId, _channelId),
6491a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                         "Channel::UpdatePacketDelay() invalid sample rate");
6492a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            timeStampDiffMs = 0;
6493a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            return -1;
6494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (timeStampDiffMs > 5000)
6496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            timeStampDiffMs = 0;
6498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (_averageDelayMs == 0)
6501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _averageDelayMs = timeStampDiffMs;
6503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
6505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // Filter average delay value using exponential filter (alpha is
6507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // 7/8). We derive 10*_averageDelayMs here (reduces risk of
6508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // rounding error) and compensate for it in GetDelayEstimate()
6509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            // later. Adding 4/8 results in correct rounding.
6510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            _averageDelayMs = ((_averageDelayMs*7 + 10*timeStampDiffMs + 4)>>3);
6511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if (sequenceNumber - _previousSequenceNumber == 1)
6514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WebRtc_UWord16 packetDelayMs = 0;
6516a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org            switch (rtpReceiveFrequency) {
6517a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org              case 8000:
6518a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                packetDelayMs = static_cast<WebRtc_UWord16>(
6519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    (timestamp - _previousTimestamp) >> 3);
6520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
6521a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org              case 16000:
6522a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                packetDelayMs = static_cast<WebRtc_UWord16>(
6523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    (timestamp - _previousTimestamp) >> 4);
6524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
6525a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org              case 32000:
6526a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                packetDelayMs = static_cast<WebRtc_UWord16>(
6527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                    (timestamp - _previousTimestamp) >> 5);
6528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                break;
6529a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org              case 48000:
6530a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                packetDelayMs = static_cast<WebRtc_UWord16>(
6531a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                    (timestamp - _previousTimestamp) / 48);
6532a7d8387bdd7f7c8901292ad57eb531aa82cef817tina.legrand@webrtc.org                break;
6533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            }
6534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            if (packetDelayMs >= 10 && packetDelayMs <= 60)
6536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                _recPacketDelayMs = packetDelayMs;
6537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _previousSequenceNumber = sequenceNumber;
6541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    _previousTimestamp = timestamp;
6542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return 0;
6544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid
6547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comChannel::RegisterReceiveCodecsToRTPModule()
6548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
6549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                 "Channel::RegisterReceiveCodecsToRTPModule()");
6551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CodecInst codec;
6554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
6555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
6556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (int idx = 0; idx < nSupportedCodecs; idx++)
6557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
6558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        // Open up the RTP/RTCP receiver for all supported codecs
6559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        if ((_audioCodingModule.Codec(idx, codec) == -1) ||
65602853dde5201d9ddc284ce5efb9688f6340487acepwestin@webrtc.org            (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
6561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
6563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceWarning,
6564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceVoice,
6565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::RegisterReceiveCodecsToRTPModule() unable"
6567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
6568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
6569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
6570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        else
6572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        {
6573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com            WEBRTC_TRACE(
6574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceInfo,
6575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         kTraceVoice,
6576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         VoEId(_instanceId, _channelId),
6577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "Channel::RegisterReceiveCodecsToRTPModule() %s "
6578fcd12b3b7d7e92d6f8cdfdf8277808ae52a07c36wu@webrtc.org                         "(%d/%d/%d/%d) has been added to the RTP/RTCP "
6579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         "receiver",
6580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.plname, codec.pltype, codec.plfreq,
6581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                         codec.channels, codec.rate);
6582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        }
6583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
6584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
658650419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.orgint Channel::ApmProcessRx(AudioFrame& frame) {
658750419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  AudioProcessing* audioproc = _rxAudioProcessingModulePtr;
658850419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  // Register the (possibly new) frame parameters.
658950419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  if (audioproc->set_sample_rate_hz(frame.sample_rate_hz_) != 0) {
6590655d8f56f61eef7bd074748e1f6f5c5d2cd767d5andrew@webrtc.org    LOG_FERR1(LS_WARNING, set_sample_rate_hz, frame.sample_rate_hz_);
659150419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  }
659250419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  if (audioproc->set_num_channels(frame.num_channels_,
659350419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org                                  frame.num_channels_) != 0) {
6594655d8f56f61eef7bd074748e1f6f5c5d2cd767d5andrew@webrtc.org    LOG_FERR1(LS_WARNING, set_num_channels, frame.num_channels_);
659550419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  }
659650419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  if (audioproc->ProcessStream(&frame) != 0) {
6597655d8f56f61eef7bd074748e1f6f5c5d2cd767d5andrew@webrtc.org    LOG_FERR0(LS_WARNING, ProcessStream);
659850419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  }
659950419b07772de974964072478886c4c35ab9c8ccandrew@webrtc.org  return 0;
6600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
6601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
660242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::SetSecondarySendCodec(const CodecInst& codec,
660342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org                                   int red_payload_type) {
660442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (SetRedPayloadType(red_payload_type) < 0) {
660542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
660642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
660742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetSecondarySendCodec() Failed to register RED ACM");
660842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
660942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
661042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_audioCodingModule.RegisterSecondarySendCodec(codec) < 0) {
661142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
661242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
661342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetSecondarySendCodec() Failed to register secondary send codec in "
661442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "ACM");
661542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
661642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
661742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
661842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
661942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org}
662042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
662142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgvoid Channel::RemoveSecondarySendCodec() {
662242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  _audioCodingModule.UnregisterSecondarySendCodec();
662342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org}
662442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
662542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::GetSecondarySendCodec(CodecInst* codec) {
662642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_audioCodingModule.SecondarySendCodec(codec) < 0) {
662742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
662842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
662942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "GetSecondarySendCodec() Failed to get secondary sent codec from ACM");
663042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
663142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
663242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
663342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org}
663442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
663542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.orgint Channel::SetRedPayloadType(int red_payload_type) {
663642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (red_payload_type < 0) {
663742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
663842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_PLTYPE_ERROR, kTraceError,
663942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() invalid RED paylaod type");
664042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
664142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
664242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
664342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  CodecInst codec;
664442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  bool found_red = false;
664542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
664642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  // Get default RED settings from the ACM database
664742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  const int num_codecs = AudioCodingModule::NumberOfCodecs();
664842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  for (int idx = 0; idx < num_codecs; idx++) {
664942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _audioCodingModule.Codec(idx, codec);
665042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    if (!STR_CASE_CMP(codec.plname, "RED")) {
665142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org      found_red = true;
665242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org      break;
665342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    }
665442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
665542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
665642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (!found_red) {
665742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
665842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_CODEC_ERROR, kTraceError,
665942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED is not supported");
666042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
666142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
666242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
666342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  codec.pltype = red_payload_type;
666442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_audioCodingModule.RegisterSendCodec(codec) < 0) {
666542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
666642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
666742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED registration in ACM module failed");
666842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
666942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
667042259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
667142259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
667242259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    _engineStatisticsPtr->SetLastError(
667342259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        VE_RTP_RTCP_MODULE_ERROR, kTraceError,
667442259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org        "SetRedPayloadType() RED registration in RTP/RTCP module failed");
667542259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org    return -1;
667642259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  }
667742259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org  return 0;
667842259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org}
667942259e7ebc7126f5a7036940fcab65b3f8d2af38turaj@webrtc.org
6680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} // namespace voe
6681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} // namespace webrtc
6682