channel.cc revision 0870f02cdbcce7de8c6a4dceb6d1678c2c6c518f
1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "channel.h"
12
13#include "audio_device.h"
14#include "audio_frame_operations.h"
15#include "audio_processing.h"
16#include "critical_section_wrapper.h"
17#include "logging.h"
18#include "output_mixer.h"
19#include "process_thread.h"
20#include "rtp_dump.h"
21#include "statistics.h"
22#include "trace.h"
23#include "transmit_mixer.h"
24#include "utility.h"
25#include "voe_base.h"
26#include "voe_external_media.h"
27#include "voe_rtp_rtcp.h"
28
29#if defined(_WIN32)
30#include <Qos.h>
31#endif
32
33namespace webrtc {
34namespace voe {
35
36WebRtc_Word32
37Channel::SendData(FrameType frameType,
38                  WebRtc_UWord8   payloadType,
39                  WebRtc_UWord32  timeStamp,
40                  const WebRtc_UWord8*  payloadData,
41                  WebRtc_UWord16  payloadSize,
42                  const RTPFragmentationHeader* fragmentation)
43{
44    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
45                 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
46                 " payloadSize=%u, fragmentation=0x%x)",
47                 frameType, payloadType, timeStamp, payloadSize, fragmentation);
48
49    if (_includeAudioLevelIndication)
50    {
51        assert(_rtpAudioProc.get() != NULL);
52        // Store current audio level in the RTP/RTCP module.
53        // The level will be used in combination with voice-activity state
54        // (frameType) to add an RTP header extension
55        _rtpRtcpModule->SetAudioLevel(_rtpAudioProc->level_estimator()->RMS());
56    }
57
58    // Push data from ACM to RTP/RTCP-module to deliver audio frame for
59    // packetization.
60    // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
61    if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
62                                        payloadType,
63                                        timeStamp,
64                                        // Leaving the time when this frame was
65                                        // received from the capture device as
66                                        // undefined for voice for now.
67                                        -1,
68                                        payloadData,
69                                        payloadSize,
70                                        fragmentation) == -1)
71    {
72        _engineStatisticsPtr->SetLastError(
73            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
74            "Channel::SendData() failed to send data to RTP/RTCP module");
75        return -1;
76    }
77
78    _lastLocalTimeStamp = timeStamp;
79    _lastPayloadType = payloadType;
80
81    return 0;
82}
83
84WebRtc_Word32
85Channel::InFrameType(WebRtc_Word16 frameType)
86{
87    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
88                 "Channel::InFrameType(frameType=%d)", frameType);
89
90    CriticalSectionScoped cs(&_callbackCritSect);
91    // 1 indicates speech
92    _sendFrameType = (frameType == 1) ? 1 : 0;
93    return 0;
94}
95
96#ifdef WEBRTC_DTMF_DETECTION
97int
98Channel::IncomingDtmf(const WebRtc_UWord8 digitDtmf, const bool end)
99{
100    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
101               "Channel::IncomingDtmf(digitDtmf=%u, end=%d)",
102               digitDtmf, end);
103
104    if (digitDtmf != 999)
105    {
106        CriticalSectionScoped cs(&_callbackCritSect);
107        if (_telephoneEventDetectionPtr)
108        {
109            _telephoneEventDetectionPtr->OnReceivedTelephoneEventInband(
110                _channelId, digitDtmf, end);
111        }
112    }
113
114    return 0;
115}
116#endif
117
118WebRtc_Word32
119Channel::OnRxVadDetected(const int vadDecision)
120{
121    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
122                 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
123
124    CriticalSectionScoped cs(&_callbackCritSect);
125    if (_rxVadObserverPtr)
126    {
127        _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
128    }
129
130    return 0;
131}
132
133int
134Channel::SendPacket(int channel, const void *data, int len)
135{
136    channel = VoEChannelId(channel);
137    assert(channel == _channelId);
138
139    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
140                 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
141
142    if (_transportPtr == NULL)
143    {
144        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
145                     "Channel::SendPacket() failed to send RTP packet due to"
146                     " invalid transport object");
147        return -1;
148    }
149
150    // Insert extra RTP packet using if user has called the InsertExtraRTPPacket
151    // API
152    if (_insertExtraRTPPacket)
153    {
154        WebRtc_UWord8* rtpHdr = (WebRtc_UWord8*)data;
155        WebRtc_UWord8 M_PT(0);
156        if (_extraMarkerBit)
157        {
158            M_PT = 0x80;            // set the M-bit
159        }
160        M_PT += _extraPayloadType;  // set the payload type
161        *(++rtpHdr) = M_PT;     // modify the M|PT-byte within the RTP header
162        _insertExtraRTPPacket = false;  // insert one packet only
163    }
164
165    WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
166    WebRtc_Word32 bufferLength = len;
167
168    // Dump the RTP packet to a file (if RTP dump is enabled).
169    if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
170    {
171        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
172                     VoEId(_instanceId,_channelId),
173                     "Channel::SendPacket() RTP dump to output file failed");
174    }
175
176    // SRTP or External encryption
177    if (_encrypting)
178    {
179        CriticalSectionScoped cs(&_callbackCritSect);
180
181        if (_encryptionPtr)
182        {
183            if (!_encryptionRTPBufferPtr)
184            {
185                // Allocate memory for encryption buffer one time only
186                _encryptionRTPBufferPtr =
187                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
188                memset(_encryptionRTPBufferPtr, 0,
189                       kVoiceEngineMaxIpPacketSizeBytes);
190            }
191
192            // Perform encryption (SRTP or external)
193            WebRtc_Word32 encryptedBufferLength = 0;
194            _encryptionPtr->encrypt(_channelId,
195                                    bufferToSendPtr,
196                                    _encryptionRTPBufferPtr,
197                                    bufferLength,
198                                    (int*)&encryptedBufferLength);
199            if (encryptedBufferLength <= 0)
200            {
201                _engineStatisticsPtr->SetLastError(
202                    VE_ENCRYPTION_FAILED,
203                    kTraceError, "Channel::SendPacket() encryption failed");
204                return -1;
205            }
206
207            // Replace default data buffer with encrypted buffer
208            bufferToSendPtr = _encryptionRTPBufferPtr;
209            bufferLength = encryptedBufferLength;
210        }
211    }
212
213    // Packet transmission using WebRtc socket transport
214    if (!_externalTransport)
215    {
216        int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
217                                          bufferLength);
218        if (n < 0)
219        {
220            WEBRTC_TRACE(kTraceError, kTraceVoice,
221                         VoEId(_instanceId,_channelId),
222                         "Channel::SendPacket() RTP transmission using WebRtc"
223                         " sockets failed");
224            return -1;
225        }
226        return n;
227    }
228
229    // Packet transmission using external transport transport
230    {
231        CriticalSectionScoped cs(&_callbackCritSect);
232
233        int n = _transportPtr->SendPacket(channel,
234                                          bufferToSendPtr,
235                                          bufferLength);
236        if (n < 0)
237        {
238            WEBRTC_TRACE(kTraceError, kTraceVoice,
239                         VoEId(_instanceId,_channelId),
240                         "Channel::SendPacket() RTP transmission using external"
241                         " transport failed");
242            return -1;
243        }
244        return n;
245    }
246}
247
248int
249Channel::SendRTCPPacket(int channel, const void *data, int len)
250{
251    channel = VoEChannelId(channel);
252    assert(channel == _channelId);
253
254    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
255                 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
256
257    {
258        CriticalSectionScoped cs(&_callbackCritSect);
259        if (_transportPtr == NULL)
260        {
261            WEBRTC_TRACE(kTraceError, kTraceVoice,
262                         VoEId(_instanceId,_channelId),
263                         "Channel::SendRTCPPacket() failed to send RTCP packet"
264                         " due to invalid transport object");
265            return -1;
266        }
267    }
268
269    WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
270    WebRtc_Word32 bufferLength = len;
271
272    // Dump the RTCP packet to a file (if RTP dump is enabled).
273    if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
274    {
275        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
276                     VoEId(_instanceId,_channelId),
277                     "Channel::SendPacket() RTCP dump to output file failed");
278    }
279
280    // SRTP or External encryption
281    if (_encrypting)
282    {
283        CriticalSectionScoped cs(&_callbackCritSect);
284
285        if (_encryptionPtr)
286        {
287            if (!_encryptionRTCPBufferPtr)
288            {
289                // Allocate memory for encryption buffer one time only
290                _encryptionRTCPBufferPtr =
291                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
292            }
293
294            // Perform encryption (SRTP or external).
295            WebRtc_Word32 encryptedBufferLength = 0;
296            _encryptionPtr->encrypt_rtcp(_channelId,
297                                         bufferToSendPtr,
298                                         _encryptionRTCPBufferPtr,
299                                         bufferLength,
300                                         (int*)&encryptedBufferLength);
301            if (encryptedBufferLength <= 0)
302            {
303                _engineStatisticsPtr->SetLastError(
304                    VE_ENCRYPTION_FAILED, kTraceError,
305                    "Channel::SendRTCPPacket() encryption failed");
306                return -1;
307            }
308
309            // Replace default data buffer with encrypted buffer
310            bufferToSendPtr = _encryptionRTCPBufferPtr;
311            bufferLength = encryptedBufferLength;
312        }
313    }
314
315    // Packet transmission using WebRtc socket transport
316    if (!_externalTransport)
317    {
318        int n = _transportPtr->SendRTCPPacket(channel,
319                                              bufferToSendPtr,
320                                              bufferLength);
321        if (n < 0)
322        {
323            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
324                         VoEId(_instanceId,_channelId),
325                         "Channel::SendRTCPPacket() transmission using WebRtc"
326                         " sockets failed");
327            return -1;
328        }
329        return n;
330    }
331
332    // Packet transmission using external transport transport
333    {
334        CriticalSectionScoped cs(&_callbackCritSect);
335        if (_transportPtr == NULL)
336        {
337            return -1;
338        }
339        int n = _transportPtr->SendRTCPPacket(channel,
340                                              bufferToSendPtr,
341                                              bufferLength);
342        if (n < 0)
343        {
344            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
345                         VoEId(_instanceId,_channelId),
346                         "Channel::SendRTCPPacket() transmission using external"
347                         " transport failed");
348            return -1;
349        }
350        return n;
351    }
352
353    return len;
354}
355
356void
357Channel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket,
358                           const WebRtc_Word32 rtpPacketLength,
359                           const char* fromIP,
360                           const WebRtc_UWord16 fromPort)
361{
362    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
363                 "Channel::IncomingRTPPacket(rtpPacketLength=%d,"
364                 " fromIP=%s, fromPort=%u)",
365                 rtpPacketLength, fromIP, fromPort);
366
367    // Store playout timestamp for the received RTP packet
368    // to be used for upcoming delay estimations
369    WebRtc_UWord32 playoutTimestamp(0);
370    if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
371    {
372        _playoutTimeStampRTP = playoutTimestamp;
373    }
374
375    WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket;
376    WebRtc_Word32 rtpBufferLength = rtpPacketLength;
377
378    // SRTP or External decryption
379    if (_decrypting)
380    {
381        CriticalSectionScoped cs(&_callbackCritSect);
382
383        if (_encryptionPtr)
384        {
385            if (!_decryptionRTPBufferPtr)
386            {
387                // Allocate memory for decryption buffer one time only
388                _decryptionRTPBufferPtr =
389                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
390            }
391
392            // Perform decryption (SRTP or external)
393            WebRtc_Word32 decryptedBufferLength = 0;
394            _encryptionPtr->decrypt(_channelId,
395                                    rtpBufferPtr,
396                                    _decryptionRTPBufferPtr,
397                                    rtpBufferLength,
398                                    (int*)&decryptedBufferLength);
399            if (decryptedBufferLength <= 0)
400            {
401                _engineStatisticsPtr->SetLastError(
402                    VE_DECRYPTION_FAILED, kTraceError,
403                    "Channel::IncomingRTPPacket() decryption failed");
404                return;
405            }
406
407            // Replace default data buffer with decrypted buffer
408            rtpBufferPtr = _decryptionRTPBufferPtr;
409            rtpBufferLength = decryptedBufferLength;
410        }
411    }
412
413    // Dump the RTP packet to a file (if RTP dump is enabled).
414    if (_rtpDumpIn.DumpPacket(rtpBufferPtr,
415                              (WebRtc_UWord16)rtpBufferLength) == -1)
416    {
417        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
418                     VoEId(_instanceId,_channelId),
419                     "Channel::SendPacket() RTP dump to input file failed");
420    }
421
422    // Deliver RTP packet to RTP/RTCP module for parsing
423    // The packet will be pushed back to the channel thru the
424    // OnReceivedPayloadData callback so we don't push it to the ACM here
425    if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr,
426                                      (WebRtc_UWord16)rtpBufferLength) == -1)
427    {
428        _engineStatisticsPtr->SetLastError(
429            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
430            "Channel::IncomingRTPPacket() RTP packet is invalid");
431        return;
432    }
433}
434
435void
436Channel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket,
437                            const WebRtc_Word32 rtcpPacketLength,
438                            const char* fromIP,
439                            const WebRtc_UWord16 fromPort)
440{
441    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
442                 "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s,"
443                 " fromPort=%u)",
444                 rtcpPacketLength, fromIP, fromPort);
445
446    // Temporary buffer pointer and size for decryption
447    WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket;
448    WebRtc_Word32 rtcpBufferLength = rtcpPacketLength;
449
450    // Store playout timestamp for the received RTCP packet
451    // which will be read by the GetRemoteRTCPData API
452    WebRtc_UWord32 playoutTimestamp(0);
453    if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
454    {
455        _playoutTimeStampRTCP = playoutTimestamp;
456    }
457
458    // SRTP or External decryption
459    if (_decrypting)
460    {
461        CriticalSectionScoped cs(&_callbackCritSect);
462
463        if (_encryptionPtr)
464        {
465            if (!_decryptionRTCPBufferPtr)
466            {
467                // Allocate memory for decryption buffer one time only
468                _decryptionRTCPBufferPtr =
469                    new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
470            }
471
472            // Perform decryption (SRTP or external).
473            WebRtc_Word32 decryptedBufferLength = 0;
474            _encryptionPtr->decrypt_rtcp(_channelId,
475                                         rtcpBufferPtr,
476                                         _decryptionRTCPBufferPtr,
477                                         rtcpBufferLength,
478                                         (int*)&decryptedBufferLength);
479            if (decryptedBufferLength <= 0)
480            {
481                _engineStatisticsPtr->SetLastError(
482                    VE_DECRYPTION_FAILED, kTraceError,
483                    "Channel::IncomingRTCPPacket() decryption failed");
484                return;
485            }
486
487            // Replace default data buffer with decrypted buffer
488            rtcpBufferPtr = _decryptionRTCPBufferPtr;
489            rtcpBufferLength = decryptedBufferLength;
490        }
491    }
492
493    // Dump the RTCP packet to a file (if RTP dump is enabled).
494    if (_rtpDumpIn.DumpPacket(rtcpBufferPtr,
495                              (WebRtc_UWord16)rtcpBufferLength) == -1)
496    {
497        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
498                     VoEId(_instanceId,_channelId),
499                     "Channel::SendPacket() RTCP dump to input file failed");
500    }
501
502    // Deliver RTCP packet to RTP/RTCP module for parsing
503    if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr,
504                                      (WebRtc_UWord16)rtcpBufferLength) == -1)
505    {
506        _engineStatisticsPtr->SetLastError(
507            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
508            "Channel::IncomingRTPPacket() RTCP packet is invalid");
509        return;
510    }
511}
512
513void
514Channel::OnReceivedTelephoneEvent(const WebRtc_Word32 id,
515                                  const WebRtc_UWord8 event,
516                                  const bool endOfEvent)
517{
518    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
519                 "Channel::OnReceivedTelephoneEvent(id=%d, event=%u,"
520                 " endOfEvent=%d)", id, event, endOfEvent);
521
522#ifdef WEBRTC_DTMF_DETECTION
523    if (_outOfBandTelephoneEventDetecion)
524    {
525        CriticalSectionScoped cs(&_callbackCritSect);
526
527        if (_telephoneEventDetectionPtr)
528        {
529            _telephoneEventDetectionPtr->OnReceivedTelephoneEventOutOfBand(
530                _channelId, event, endOfEvent);
531        }
532    }
533#endif
534}
535
536void
537Channel::OnPlayTelephoneEvent(const WebRtc_Word32 id,
538                              const WebRtc_UWord8 event,
539                              const WebRtc_UWord16 lengthMs,
540                              const WebRtc_UWord8 volume)
541{
542    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
543                 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
544                 " volume=%u)", id, event, lengthMs, volume);
545
546    if (!_playOutbandDtmfEvent || (event > 15))
547    {
548        // Ignore callback since feedback is disabled or event is not a
549        // Dtmf tone event.
550        return;
551    }
552
553    assert(_outputMixerPtr != NULL);
554
555    // Start playing out the Dtmf tone (if playout is enabled).
556    // Reduce length of tone with 80ms to the reduce risk of echo.
557    _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
558}
559
560void
561Channel::OnIncomingSSRCChanged(const WebRtc_Word32 id,
562                               const WebRtc_UWord32 SSRC)
563{
564    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
565                 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
566                 id, SSRC);
567
568    WebRtc_Word32 channel = VoEChannelId(id);
569    assert(channel == _channelId);
570
571    // Reset RTP-module counters since a new incoming RTP stream is detected
572    _rtpRtcpModule->ResetReceiveDataCountersRTP();
573    _rtpRtcpModule->ResetStatisticsRTP();
574
575    if (_rtpObserver)
576    {
577        CriticalSectionScoped cs(&_callbackCritSect);
578
579        if (_rtpObserverPtr)
580        {
581            // Send new SSRC to registered observer using callback
582            _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
583        }
584    }
585}
586
587void Channel::OnIncomingCSRCChanged(const WebRtc_Word32 id,
588                                    const WebRtc_UWord32 CSRC,
589                                    const bool added)
590{
591    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
592                 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
593                 id, CSRC, added);
594
595    WebRtc_Word32 channel = VoEChannelId(id);
596    assert(channel == _channelId);
597
598    if (_rtpObserver)
599    {
600        CriticalSectionScoped cs(&_callbackCritSect);
601
602        if (_rtpObserverPtr)
603        {
604            _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
605        }
606    }
607}
608
609void
610Channel::OnApplicationDataReceived(const WebRtc_Word32 id,
611                                   const WebRtc_UWord8 subType,
612                                   const WebRtc_UWord32 name,
613                                   const WebRtc_UWord16 length,
614                                   const WebRtc_UWord8* data)
615{
616    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
617                 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
618                 " name=%u, length=%u)",
619                 id, subType, name, length);
620
621    WebRtc_Word32 channel = VoEChannelId(id);
622    assert(channel == _channelId);
623
624    if (_rtcpObserver)
625    {
626        CriticalSectionScoped cs(&_callbackCritSect);
627
628        if (_rtcpObserverPtr)
629        {
630            _rtcpObserverPtr->OnApplicationDataReceived(channel,
631                                                        subType,
632                                                        name,
633                                                        data,
634                                                        length);
635        }
636    }
637}
638
639WebRtc_Word32
640Channel::OnInitializeDecoder(
641    const WebRtc_Word32 id,
642    const WebRtc_Word8 payloadType,
643    const char payloadName[RTP_PAYLOAD_NAME_SIZE],
644    const int frequency,
645    const WebRtc_UWord8 channels,
646    const WebRtc_UWord32 rate)
647{
648    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
649                 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
650                 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
651                 id, payloadType, payloadName, frequency, channels, rate);
652
653    assert(VoEChannelId(id) == _channelId);
654
655    CodecInst receiveCodec = {0};
656    CodecInst dummyCodec = {0};
657
658    receiveCodec.pltype = payloadType;
659    receiveCodec.plfreq = frequency;
660    receiveCodec.channels = channels;
661    receiveCodec.rate = rate;
662    strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
663
664    _audioCodingModule.Codec(payloadName, dummyCodec, frequency, channels);
665    receiveCodec.pacsize = dummyCodec.pacsize;
666
667    // Register the new codec to the ACM
668    if (_audioCodingModule.RegisterReceiveCodec(receiveCodec) == -1)
669    {
670        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
671                     VoEId(_instanceId, _channelId),
672                     "Channel::OnInitializeDecoder() invalid codec ("
673                     "pt=%d, name=%s) received - 1", payloadType, payloadName);
674        _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
675        return -1;
676    }
677
678    return 0;
679}
680
681void
682Channel::OnPacketTimeout(const WebRtc_Word32 id)
683{
684    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
685                 "Channel::OnPacketTimeout(id=%d)", id);
686
687    CriticalSectionScoped cs(_callbackCritSectPtr);
688    if (_voiceEngineObserverPtr)
689    {
690        if (_receiving || _externalTransport)
691        {
692            WebRtc_Word32 channel = VoEChannelId(id);
693            assert(channel == _channelId);
694            // Ensure that next OnReceivedPacket() callback will trigger
695            // a VE_PACKET_RECEIPT_RESTARTED callback.
696            _rtpPacketTimedOut = true;
697            // Deliver callback to the observer
698            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
699                         VoEId(_instanceId,_channelId),
700                         "Channel::OnPacketTimeout() => "
701                         "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
702            _voiceEngineObserverPtr->CallbackOnError(channel,
703                                                     VE_RECEIVE_PACKET_TIMEOUT);
704        }
705    }
706}
707
708void
709Channel::OnReceivedPacket(const WebRtc_Word32 id,
710                          const RtpRtcpPacketType packetType)
711{
712    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
713                 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
714                 id, packetType);
715
716    assert(VoEChannelId(id) == _channelId);
717
718    // Notify only for the case when we have restarted an RTP session.
719    if (_rtpPacketTimedOut && (kPacketRtp == packetType))
720    {
721        CriticalSectionScoped cs(_callbackCritSectPtr);
722        if (_voiceEngineObserverPtr)
723        {
724            WebRtc_Word32 channel = VoEChannelId(id);
725            assert(channel == _channelId);
726            // Reset timeout mechanism
727            _rtpPacketTimedOut = false;
728            // Deliver callback to the observer
729            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
730                         VoEId(_instanceId,_channelId),
731                         "Channel::OnPacketTimeout() =>"
732                         " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
733            _voiceEngineObserverPtr->CallbackOnError(
734                channel,
735                VE_PACKET_RECEIPT_RESTARTED);
736        }
737    }
738}
739
740void
741Channel::OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
742                               const RTPAliveType alive)
743{
744    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
745                 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
746
747    if (!_connectionObserver)
748        return;
749
750    WebRtc_Word32 channel = VoEChannelId(id);
751    assert(channel == _channelId);
752
753    // Use Alive as default to limit risk of false Dead detections
754    bool isAlive(true);
755
756    // Always mark the connection as Dead when the module reports kRtpDead
757    if (kRtpDead == alive)
758    {
759        isAlive = false;
760    }
761
762    // It is possible that the connection is alive even if no RTP packet has
763    // been received for a long time since the other side might use VAD/DTX
764    // and a low SID-packet update rate.
765    if ((kRtpNoRtp == alive) && _playing)
766    {
767        // Detect Alive for all NetEQ states except for the case when we are
768        // in PLC_CNG state.
769        // PLC_CNG <=> background noise only due to long expand or error.
770        // Note that, the case where the other side stops sending during CNG
771        // state will be detected as Alive. Dead is is not set until after
772        // missing RTCP packets for at least twelve seconds (handled
773        // internally by the RTP/RTCP module).
774        isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
775    }
776
777    UpdateDeadOrAliveCounters(isAlive);
778
779    // Send callback to the registered observer
780    if (_connectionObserver)
781    {
782        CriticalSectionScoped cs(&_callbackCritSect);
783        if (_connectionObserverPtr)
784        {
785            _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
786        }
787    }
788}
789
790WebRtc_Word32
791Channel::OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
792                               const WebRtc_UWord16 payloadSize,
793                               const WebRtcRTPHeader* rtpHeader)
794{
795    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
796                 "Channel::OnReceivedPayloadData(payloadSize=%d,"
797                 " payloadType=%u, audioChannel=%u)",
798                 payloadSize,
799                 rtpHeader->header.payloadType,
800                 rtpHeader->type.Audio.channel);
801
802    _lastRemoteTimeStamp = rtpHeader->header.timestamp;
803
804    if (!_playing)
805    {
806        // Avoid inserting into NetEQ when we are not playing. Count the
807        // packet as discarded.
808        WEBRTC_TRACE(kTraceStream, kTraceVoice,
809                     VoEId(_instanceId, _channelId),
810                     "received packet is discarded since playing is not"
811                     " activated");
812        _numberOfDiscardedPackets++;
813        return 0;
814    }
815
816    // Push the incoming payload (parsed and ready for decoding) into the ACM
817    if (_audioCodingModule.IncomingPacket(payloadData,
818                                          payloadSize,
819                                          *rtpHeader) != 0)
820    {
821        _engineStatisticsPtr->SetLastError(
822            VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
823            "Channel::OnReceivedPayloadData() unable to push data to the ACM");
824        return -1;
825    }
826
827    // Update the packet delay
828    UpdatePacketDelay(rtpHeader->header.timestamp,
829                      rtpHeader->header.sequenceNumber);
830
831    return 0;
832}
833
834WebRtc_Word32 Channel::GetAudioFrame(const WebRtc_Word32 id,
835                                     AudioFrame& audioFrame)
836{
837    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
838                 "Channel::GetAudioFrame(id=%d)", id);
839
840    // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
841    if (_audioCodingModule.PlayoutData10Ms(audioFrame.sample_rate_hz_,
842                                           audioFrame) == -1)
843    {
844        WEBRTC_TRACE(kTraceError, kTraceVoice,
845                     VoEId(_instanceId,_channelId),
846                     "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
847        // In all likelihood, the audio in this frame is garbage. We return an
848        // error so that the audio mixer module doesn't add it to the mix. As
849        // a result, it won't be played out and the actions skipped here are
850        // irrelevant.
851        return -1;
852    }
853
854    if (_RxVadDetection)
855    {
856        UpdateRxVadDetection(audioFrame);
857    }
858
859    // Convert module ID to internal VoE channel ID
860    audioFrame.id_ = VoEChannelId(audioFrame.id_);
861    // Store speech type for dead-or-alive detection
862    _outputSpeechType = audioFrame.speech_type_;
863
864    // Perform far-end AudioProcessing module processing on the received signal
865    if (_rxApmIsEnabled)
866    {
867        ApmProcessRx(audioFrame);
868    }
869
870    // Output volume scaling
871    if (_outputGain < 0.99f || _outputGain > 1.01f)
872    {
873        AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
874    }
875
876    // Scale left and/or right channel(s) if stereo and master balance is
877    // active
878
879    if (_panLeft != 1.0f || _panRight != 1.0f)
880    {
881        if (audioFrame.num_channels_ == 1)
882        {
883            // Emulate stereo mode since panning is active.
884            // The mono signal is copied to both left and right channels here.
885            AudioFrameOperations::MonoToStereo(&audioFrame);
886        }
887        // For true stereo mode (when we are receiving a stereo signal), no
888        // action is needed.
889
890        // Do the panning operation (the audio frame contains stereo at this
891        // stage)
892        AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
893    }
894
895    // Mix decoded PCM output with file if file mixing is enabled
896    if (_outputFilePlaying)
897    {
898        MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
899    }
900
901    // Place channel in on-hold state (~muted) if on-hold is activated
902    if (_outputIsOnHold)
903    {
904        AudioFrameOperations::Mute(audioFrame);
905    }
906
907    // External media
908    if (_outputExternalMedia)
909    {
910        CriticalSectionScoped cs(&_callbackCritSect);
911        const bool isStereo = (audioFrame.num_channels_ == 2);
912        if (_outputExternalMediaCallbackPtr)
913        {
914            _outputExternalMediaCallbackPtr->Process(
915                _channelId,
916                kPlaybackPerChannel,
917                (WebRtc_Word16*)audioFrame.data_,
918                audioFrame.samples_per_channel_,
919                audioFrame.sample_rate_hz_,
920                isStereo);
921        }
922    }
923
924    // Record playout if enabled
925    {
926        CriticalSectionScoped cs(&_fileCritSect);
927
928        if (_outputFileRecording && _outputFileRecorderPtr)
929        {
930            _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
931        }
932    }
933
934    // Measure audio level (0-9)
935    _outputAudioLevel.ComputeLevel(audioFrame);
936
937    return 0;
938}
939
940WebRtc_Word32
941Channel::NeededFrequency(const WebRtc_Word32 id)
942{
943    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
944                 "Channel::NeededFrequency(id=%d)", id);
945
946    int highestNeeded = 0;
947
948    // Determine highest needed receive frequency
949    WebRtc_Word32 receiveFrequency = _audioCodingModule.ReceiveFrequency();
950
951    // Return the bigger of playout and receive frequency in the ACM.
952    if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
953    {
954        highestNeeded = _audioCodingModule.PlayoutFrequency();
955    }
956    else
957    {
958        highestNeeded = receiveFrequency;
959    }
960
961    // Special case, if we're playing a file on the playout side
962    // we take that frequency into consideration as well
963    // This is not needed on sending side, since the codec will
964    // limit the spectrum anyway.
965    if (_outputFilePlaying)
966    {
967        CriticalSectionScoped cs(&_fileCritSect);
968        if (_outputFilePlayerPtr && _outputFilePlaying)
969        {
970            if(_outputFilePlayerPtr->Frequency()>highestNeeded)
971            {
972                highestNeeded=_outputFilePlayerPtr->Frequency();
973            }
974        }
975    }
976
977    return(highestNeeded);
978}
979
980WebRtc_Word32
981Channel::CreateChannel(Channel*& channel,
982                       const WebRtc_Word32 channelId,
983                       const WebRtc_UWord32 instanceId)
984{
985    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
986                 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
987        channelId, instanceId);
988
989    channel = new Channel(channelId, instanceId);
990    if (channel == NULL)
991    {
992        WEBRTC_TRACE(kTraceMemory, kTraceVoice,
993                     VoEId(instanceId,channelId),
994                     "Channel::CreateChannel() unable to allocate memory for"
995                     " channel");
996        return -1;
997    }
998    return 0;
999}
1000
1001void
1002Channel::PlayNotification(const WebRtc_Word32 id,
1003                          const WebRtc_UWord32 durationMs)
1004{
1005    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1006                 "Channel::PlayNotification(id=%d, durationMs=%d)",
1007                 id, durationMs);
1008
1009    // Not implement yet
1010}
1011
1012void
1013Channel::RecordNotification(const WebRtc_Word32 id,
1014                            const WebRtc_UWord32 durationMs)
1015{
1016    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1017                 "Channel::RecordNotification(id=%d, durationMs=%d)",
1018                 id, durationMs);
1019
1020    // Not implement yet
1021}
1022
1023void
1024Channel::PlayFileEnded(const WebRtc_Word32 id)
1025{
1026    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1027                 "Channel::PlayFileEnded(id=%d)", id);
1028
1029    if (id == _inputFilePlayerId)
1030    {
1031        CriticalSectionScoped cs(&_fileCritSect);
1032
1033        _inputFilePlaying = false;
1034        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1035                     VoEId(_instanceId,_channelId),
1036                     "Channel::PlayFileEnded() => input file player module is"
1037                     " shutdown");
1038    }
1039    else if (id == _outputFilePlayerId)
1040    {
1041        CriticalSectionScoped cs(&_fileCritSect);
1042
1043        _outputFilePlaying = false;
1044        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1045                     VoEId(_instanceId,_channelId),
1046                     "Channel::PlayFileEnded() => output file player module is"
1047                     " shutdown");
1048    }
1049}
1050
1051void
1052Channel::RecordFileEnded(const WebRtc_Word32 id)
1053{
1054    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1055                 "Channel::RecordFileEnded(id=%d)", id);
1056
1057    assert(id == _outputFileRecorderId);
1058
1059    CriticalSectionScoped cs(&_fileCritSect);
1060
1061    _outputFileRecording = false;
1062    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1063                 VoEId(_instanceId,_channelId),
1064                 "Channel::RecordFileEnded() => output file recorder module is"
1065                 " shutdown");
1066}
1067
1068Channel::Channel(const WebRtc_Word32 channelId,
1069                 const WebRtc_UWord32 instanceId) :
1070    _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1071    _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1072    _instanceId(instanceId),
1073    _channelId(channelId),
1074    _audioCodingModule(*AudioCodingModule::Create(
1075        VoEModuleId(instanceId, channelId))),
1076#ifndef WEBRTC_EXTERNAL_TRANSPORT
1077     _numSocketThreads(KNumSocketThreads),
1078    _socketTransportModule(*UdpTransport::Create(
1079        VoEModuleId(instanceId, channelId), _numSocketThreads)),
1080#endif
1081#ifdef WEBRTC_SRTP
1082    _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId,
1083                                                          channelId))),
1084#endif
1085    _rtpDumpIn(*RtpDump::CreateRtpDump()),
1086    _rtpDumpOut(*RtpDump::CreateRtpDump()),
1087    _outputAudioLevel(),
1088    _externalTransport(false),
1089    _inputFilePlayerPtr(NULL),
1090    _outputFilePlayerPtr(NULL),
1091    _outputFileRecorderPtr(NULL),
1092    // Avoid conflict with other channels by adding 1024 - 1026,
1093    // won't use as much as 1024 channels.
1094    _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
1095    _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
1096    _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
1097    _inputFilePlaying(false),
1098    _outputFilePlaying(false),
1099    _outputFileRecording(false),
1100    _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
1101    _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
1102    _inputExternalMedia(false),
1103    _outputExternalMedia(false),
1104    _inputExternalMediaCallbackPtr(NULL),
1105    _outputExternalMediaCallbackPtr(NULL),
1106    _encryptionRTPBufferPtr(NULL),
1107    _decryptionRTPBufferPtr(NULL),
1108    _encryptionRTCPBufferPtr(NULL),
1109    _decryptionRTCPBufferPtr(NULL),
1110    _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
1111    _sendTelephoneEventPayloadType(106),
1112    _playoutTimeStampRTP(0),
1113    _playoutTimeStampRTCP(0),
1114    _numberOfDiscardedPackets(0),
1115    _engineStatisticsPtr(NULL),
1116    _outputMixerPtr(NULL),
1117    _transmitMixerPtr(NULL),
1118    _moduleProcessThreadPtr(NULL),
1119    _audioDeviceModulePtr(NULL),
1120    _voiceEngineObserverPtr(NULL),
1121    _callbackCritSectPtr(NULL),
1122    _transportPtr(NULL),
1123    _encryptionPtr(NULL),
1124    _rtpAudioProc(NULL),
1125    _rxAudioProcessingModulePtr(NULL),
1126#ifdef WEBRTC_DTMF_DETECTION
1127    _telephoneEventDetectionPtr(NULL),
1128#endif
1129    _rxVadObserverPtr(NULL),
1130    _oldVadDecision(-1),
1131    _sendFrameType(0),
1132    _rtpObserverPtr(NULL),
1133    _rtcpObserverPtr(NULL),
1134    _outputIsOnHold(false),
1135    _externalPlayout(false),
1136    _inputIsOnHold(false),
1137    _playing(false),
1138    _sending(false),
1139    _receiving(false),
1140    _mixFileWithMicrophone(false),
1141    _rtpObserver(false),
1142    _rtcpObserver(false),
1143    _mute(false),
1144    _panLeft(1.0f),
1145    _panRight(1.0f),
1146    _outputGain(1.0f),
1147    _encrypting(false),
1148    _decrypting(false),
1149    _playOutbandDtmfEvent(false),
1150    _playInbandDtmfEvent(false),
1151    _inbandTelephoneEventDetection(false),
1152    _outOfBandTelephoneEventDetecion(false),
1153    _extraPayloadType(0),
1154    _insertExtraRTPPacket(false),
1155    _extraMarkerBit(false),
1156    _lastLocalTimeStamp(0),
1157    _lastRemoteTimeStamp(0),
1158    _lastPayloadType(0),
1159    _includeAudioLevelIndication(false),
1160    _rtpPacketTimedOut(false),
1161    _rtpPacketTimeOutIsEnabled(false),
1162    _rtpTimeOutSeconds(0),
1163    _connectionObserver(false),
1164    _connectionObserverPtr(NULL),
1165    _countAliveDetections(0),
1166    _countDeadDetections(0),
1167    _outputSpeechType(AudioFrame::kNormalSpeech),
1168    _averageDelayMs(0),
1169    _previousSequenceNumber(0),
1170    _previousTimestamp(0),
1171    _recPacketDelayMs(20),
1172    _RxVadDetection(false),
1173    _rxApmIsEnabled(false),
1174    _rxAgcIsEnabled(false),
1175    _rxNsIsEnabled(false)
1176{
1177    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1178                 "Channel::Channel() - ctor");
1179    _inbandDtmfQueue.ResetDtmf();
1180    _inbandDtmfGenerator.Init();
1181    _outputAudioLevel.Clear();
1182
1183    RtpRtcp::Configuration configuration;
1184    configuration.id = VoEModuleId(instanceId, channelId);
1185    configuration.audio = true;
1186    configuration.incoming_data = this;
1187    configuration.incoming_messages = this;
1188    configuration.outgoing_transport = this;
1189    configuration.rtcp_feedback = this;
1190    configuration.audio_messages = this;
1191
1192    _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
1193
1194    // Create far end AudioProcessing Module
1195    _rxAudioProcessingModulePtr = AudioProcessing::Create(
1196        VoEModuleId(instanceId, channelId));
1197}
1198
1199Channel::~Channel()
1200{
1201    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1202                 "Channel::~Channel() - dtor");
1203
1204    if (_outputExternalMedia)
1205    {
1206        DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1207    }
1208    if (_inputExternalMedia)
1209    {
1210        DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1211    }
1212    StopSend();
1213#ifndef WEBRTC_EXTERNAL_TRANSPORT
1214    StopReceiving();
1215    // De-register packet callback to ensure we're not in a callback when
1216    // deleting channel state, avoids race condition and deadlock.
1217    if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0)
1218            != 0)
1219    {
1220        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1221                     VoEId(_instanceId, _channelId),
1222                     "~Channel() failed to de-register receive callback");
1223    }
1224#endif
1225    StopPlayout();
1226
1227    {
1228        CriticalSectionScoped cs(&_fileCritSect);
1229        if (_inputFilePlayerPtr)
1230        {
1231            _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1232            _inputFilePlayerPtr->StopPlayingFile();
1233            FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1234            _inputFilePlayerPtr = NULL;
1235        }
1236        if (_outputFilePlayerPtr)
1237        {
1238            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1239            _outputFilePlayerPtr->StopPlayingFile();
1240            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1241            _outputFilePlayerPtr = NULL;
1242        }
1243        if (_outputFileRecorderPtr)
1244        {
1245            _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1246            _outputFileRecorderPtr->StopRecording();
1247            FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1248            _outputFileRecorderPtr = NULL;
1249        }
1250    }
1251
1252    // The order to safely shutdown modules in a channel is:
1253    // 1. De-register callbacks in modules
1254    // 2. De-register modules in process thread
1255    // 3. Destroy modules
1256    if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1257    {
1258        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1259                     VoEId(_instanceId,_channelId),
1260                     "~Channel() failed to de-register transport callback"
1261                     " (Audio coding module)");
1262    }
1263    if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1264    {
1265        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1266                     VoEId(_instanceId,_channelId),
1267                     "~Channel() failed to de-register VAD callback"
1268                     " (Audio coding module)");
1269    }
1270#ifdef WEBRTC_DTMF_DETECTION
1271    if (_audioCodingModule.RegisterIncomingMessagesCallback(NULL) == -1)
1272    {
1273        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1274                     VoEId(_instanceId,_channelId),
1275                     "~Channel() failed to de-register incoming messages "
1276                     "callback (Audio coding module)");
1277    }
1278#endif
1279    // De-register modules in process thread
1280#ifndef WEBRTC_EXTERNAL_TRANSPORT
1281    if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule)
1282            == -1)
1283    {
1284        WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1285                     VoEId(_instanceId,_channelId),
1286                     "~Channel() failed to deregister socket module");
1287    }
1288#endif
1289    if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
1290    {
1291        WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1292                     VoEId(_instanceId,_channelId),
1293                     "~Channel() failed to deregister RTP/RTCP module");
1294    }
1295
1296    // Destroy modules
1297#ifndef WEBRTC_EXTERNAL_TRANSPORT
1298    UdpTransport::Destroy(
1299        &_socketTransportModule);
1300#endif
1301    AudioCodingModule::Destroy(&_audioCodingModule);
1302#ifdef WEBRTC_SRTP
1303    SrtpModule::DestroySrtpModule(&_srtpModule);
1304#endif
1305    if (_rxAudioProcessingModulePtr != NULL)
1306    {
1307        AudioProcessing::Destroy(_rxAudioProcessingModulePtr); // far end APM
1308        _rxAudioProcessingModulePtr = NULL;
1309    }
1310
1311    // End of modules shutdown
1312
1313    // Delete other objects
1314    RtpDump::DestroyRtpDump(&_rtpDumpIn);
1315    RtpDump::DestroyRtpDump(&_rtpDumpOut);
1316    delete [] _encryptionRTPBufferPtr;
1317    delete [] _decryptionRTPBufferPtr;
1318    delete [] _encryptionRTCPBufferPtr;
1319    delete [] _decryptionRTCPBufferPtr;
1320    delete &_callbackCritSect;
1321    delete &_fileCritSect;
1322}
1323
1324WebRtc_Word32
1325Channel::Init()
1326{
1327    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1328                 "Channel::Init()");
1329
1330    // --- Initial sanity
1331
1332    if ((_engineStatisticsPtr == NULL) ||
1333        (_moduleProcessThreadPtr == NULL))
1334    {
1335        WEBRTC_TRACE(kTraceError, kTraceVoice,
1336                     VoEId(_instanceId,_channelId),
1337                     "Channel::Init() must call SetEngineInformation() first");
1338        return -1;
1339    }
1340
1341    // --- Add modules to process thread (for periodic schedulation)
1342
1343    const bool processThreadFail =
1344        ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
1345#ifndef WEBRTC_EXTERNAL_TRANSPORT
1346        (_moduleProcessThreadPtr->RegisterModule(
1347                &_socketTransportModule) != 0));
1348#else
1349        false);
1350#endif
1351    if (processThreadFail)
1352    {
1353        _engineStatisticsPtr->SetLastError(
1354            VE_CANNOT_INIT_CHANNEL, kTraceError,
1355            "Channel::Init() modules not registered");
1356        return -1;
1357    }
1358    // --- ACM initialization
1359
1360    if ((_audioCodingModule.InitializeReceiver() == -1) ||
1361#ifdef WEBRTC_CODEC_AVT
1362        // out-of-band Dtmf tones are played out by default
1363        (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1364#endif
1365        (_audioCodingModule.InitializeSender() == -1))
1366    {
1367        _engineStatisticsPtr->SetLastError(
1368            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1369            "Channel::Init() unable to initialize the ACM - 1");
1370        return -1;
1371    }
1372
1373    // --- RTP/RTCP module initialization
1374
1375    // Ensure that RTCP is enabled by default for the created channel.
1376    // Note that, the module will keep generating RTCP until it is explicitly
1377    // disabled by the user.
1378    // After StopListen (when no sockets exists), RTCP packets will no longer
1379    // be transmitted since the Transport object will then be invalid.
1380
1381    const bool rtpRtcpFail =
1382        ((_rtpRtcpModule->SetTelephoneEventStatus(false, true, true) == -1) ||
1383        // RTCP is enabled by default
1384        (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1));
1385    if (rtpRtcpFail)
1386    {
1387        _engineStatisticsPtr->SetLastError(
1388            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1389            "Channel::Init() RTP/RTCP module not initialized");
1390        return -1;
1391    }
1392
1393     // --- Register all permanent callbacks
1394    const bool fail =
1395        (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1396        (_audioCodingModule.RegisterVADCallback(this) == -1);
1397
1398    if (fail)
1399    {
1400        _engineStatisticsPtr->SetLastError(
1401            VE_CANNOT_INIT_CHANNEL, kTraceError,
1402            "Channel::Init() callbacks not registered");
1403        return -1;
1404    }
1405
1406    // --- Register all supported codecs to the receiving side of the
1407    // RTP/RTCP module
1408
1409    CodecInst codec;
1410    const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1411
1412    for (int idx = 0; idx < nSupportedCodecs; idx++)
1413    {
1414        // Open up the RTP/RTCP receiver for all supported codecs
1415        if ((_audioCodingModule.Codec(idx, codec) == -1) ||
1416            (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
1417        {
1418            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1419                         VoEId(_instanceId,_channelId),
1420                         "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1421                         "to RTP/RTCP receiver",
1422                         codec.plname, codec.pltype, codec.plfreq,
1423                         codec.channels, codec.rate);
1424        }
1425        else
1426        {
1427            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1428                         VoEId(_instanceId,_channelId),
1429                         "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1430                         "the RTP/RTCP receiver",
1431                         codec.plname, codec.pltype, codec.plfreq,
1432                         codec.channels, codec.rate);
1433        }
1434
1435        // Ensure that PCMU is used as default codec on the sending side
1436        if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
1437        {
1438            SetSendCodec(codec);
1439        }
1440
1441        // Register default PT for outband 'telephone-event'
1442        if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1443        {
1444            if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
1445                (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1446            {
1447                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1448                             VoEId(_instanceId,_channelId),
1449                             "Channel::Init() failed to register outband "
1450                             "'telephone-event' (%d/%d) correctly",
1451                             codec.pltype, codec.plfreq);
1452            }
1453        }
1454
1455        if (!STR_CASE_CMP(codec.plname, "CN"))
1456        {
1457            if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1458                (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
1459                (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
1460            {
1461                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1462                             VoEId(_instanceId,_channelId),
1463                             "Channel::Init() failed to register CN (%d/%d) "
1464                             "correctly - 1",
1465                             codec.pltype, codec.plfreq);
1466            }
1467        }
1468#ifdef WEBRTC_CODEC_RED
1469        // Register RED to the receiving side of the ACM.
1470        // We will not receive an OnInitializeDecoder() callback for RED.
1471        if (!STR_CASE_CMP(codec.plname, "RED"))
1472        {
1473            if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1474            {
1475                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1476                             VoEId(_instanceId,_channelId),
1477                             "Channel::Init() failed to register RED (%d/%d) "
1478                             "correctly",
1479                             codec.pltype, codec.plfreq);
1480            }
1481        }
1482#endif
1483    }
1484#ifndef WEBRTC_EXTERNAL_TRANSPORT
1485    // Ensure that the WebRtcSocketTransport implementation is used as
1486    // Transport on the sending side
1487    {
1488        // A lock is needed here since users can call
1489        // RegisterExternalTransport() at the same time.
1490        CriticalSectionScoped cs(&_callbackCritSect);
1491        _transportPtr = &_socketTransportModule;
1492    }
1493#endif
1494
1495    // Initialize the far end AP module
1496    // Using 8 kHz as initial Fs, the same as in transmission. Might be
1497    // changed at the first receiving audio.
1498    if (_rxAudioProcessingModulePtr == NULL)
1499    {
1500        _engineStatisticsPtr->SetLastError(
1501            VE_NO_MEMORY, kTraceCritical,
1502            "Channel::Init() failed to create the far-end AudioProcessing"
1503            " module");
1504        return -1;
1505    }
1506
1507    if (_rxAudioProcessingModulePtr->set_sample_rate_hz(8000))
1508    {
1509        _engineStatisticsPtr->SetLastError(
1510            VE_APM_ERROR, kTraceWarning,
1511            "Channel::Init() failed to set the sample rate to 8K for"
1512            " far-end AP module");
1513    }
1514
1515    if (_rxAudioProcessingModulePtr->set_num_channels(1, 1) != 0)
1516    {
1517        _engineStatisticsPtr->SetLastError(
1518            VE_SOUNDCARD_ERROR, kTraceWarning,
1519            "Init() failed to set channels for the primary audio stream");
1520    }
1521
1522    if (_rxAudioProcessingModulePtr->high_pass_filter()->Enable(
1523        WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1524    {
1525        _engineStatisticsPtr->SetLastError(
1526            VE_APM_ERROR, kTraceWarning,
1527            "Channel::Init() failed to set the high-pass filter for"
1528            " far-end AP module");
1529    }
1530
1531    if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(
1532        (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1533    {
1534        _engineStatisticsPtr->SetLastError(
1535            VE_APM_ERROR, kTraceWarning,
1536            "Init() failed to set noise reduction level for far-end"
1537            " AP module");
1538    }
1539    if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(
1540        WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1541    {
1542        _engineStatisticsPtr->SetLastError(
1543            VE_APM_ERROR, kTraceWarning,
1544            "Init() failed to set noise reduction state for far-end"
1545            " AP module");
1546    }
1547
1548    if (_rxAudioProcessingModulePtr->gain_control()->set_mode(
1549        (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1550    {
1551        _engineStatisticsPtr->SetLastError(
1552            VE_APM_ERROR, kTraceWarning,
1553            "Init() failed to set AGC mode for far-end AP module");
1554    }
1555    if (_rxAudioProcessingModulePtr->gain_control()->Enable(
1556        WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1557    {
1558        _engineStatisticsPtr->SetLastError(
1559            VE_APM_ERROR, kTraceWarning,
1560            "Init() failed to set AGC state for far-end AP module");
1561    }
1562
1563    return 0;
1564}
1565
1566WebRtc_Word32
1567Channel::SetEngineInformation(Statistics& engineStatistics,
1568                              OutputMixer& outputMixer,
1569                              voe::TransmitMixer& transmitMixer,
1570                              ProcessThread& moduleProcessThread,
1571                              AudioDeviceModule& audioDeviceModule,
1572                              VoiceEngineObserver* voiceEngineObserver,
1573                              CriticalSectionWrapper* callbackCritSect)
1574{
1575    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1576                 "Channel::SetEngineInformation()");
1577    _engineStatisticsPtr = &engineStatistics;
1578    _outputMixerPtr = &outputMixer;
1579    _transmitMixerPtr = &transmitMixer,
1580    _moduleProcessThreadPtr = &moduleProcessThread;
1581    _audioDeviceModulePtr = &audioDeviceModule;
1582    _voiceEngineObserverPtr = voiceEngineObserver;
1583    _callbackCritSectPtr = callbackCritSect;
1584    return 0;
1585}
1586
1587WebRtc_Word32
1588Channel::UpdateLocalTimeStamp()
1589{
1590
1591    _timeStamp += _audioFrame.samples_per_channel_;
1592    return 0;
1593}
1594
1595WebRtc_Word32
1596Channel::StartPlayout()
1597{
1598    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1599                 "Channel::StartPlayout()");
1600    if (_playing)
1601    {
1602        return 0;
1603    }
1604    // Add participant as candidates for mixing.
1605    if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1606    {
1607        _engineStatisticsPtr->SetLastError(
1608            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1609            "StartPlayout() failed to add participant to mixer");
1610        return -1;
1611    }
1612
1613    _playing = true;
1614
1615    if (RegisterFilePlayingToMixer() != 0)
1616        return -1;
1617
1618    return 0;
1619}
1620
1621WebRtc_Word32
1622Channel::StopPlayout()
1623{
1624    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1625                 "Channel::StopPlayout()");
1626    if (!_playing)
1627    {
1628        return 0;
1629    }
1630    // Remove participant as candidates for mixing
1631    if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1632    {
1633        _engineStatisticsPtr->SetLastError(
1634            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1635            "StartPlayout() failed to remove participant from mixer");
1636        return -1;
1637    }
1638
1639    _playing = false;
1640    _outputAudioLevel.Clear();
1641
1642    return 0;
1643}
1644
1645WebRtc_Word32
1646Channel::StartSend()
1647{
1648    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1649                 "Channel::StartSend()");
1650    {
1651        // A lock is needed because |_sending| can be accessed or modified by
1652        // another thread at the same time.
1653        CriticalSectionScoped cs(&_callbackCritSect);
1654
1655        if (_sending)
1656        {
1657            return 0;
1658        }
1659        _sending = true;
1660    }
1661
1662    if (_rtpRtcpModule->SetSendingStatus(true) != 0)
1663    {
1664        _engineStatisticsPtr->SetLastError(
1665            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1666            "StartSend() RTP/RTCP failed to start sending");
1667        CriticalSectionScoped cs(&_callbackCritSect);
1668        _sending = false;
1669        return -1;
1670    }
1671
1672    return 0;
1673}
1674
1675WebRtc_Word32
1676Channel::StopSend()
1677{
1678    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1679                 "Channel::StopSend()");
1680    {
1681        // A lock is needed because |_sending| can be accessed or modified by
1682        // another thread at the same time.
1683        CriticalSectionScoped cs(&_callbackCritSect);
1684
1685        if (!_sending)
1686        {
1687            return 0;
1688        }
1689        _sending = false;
1690    }
1691
1692    // Reset sending SSRC and sequence number and triggers direct transmission
1693    // of RTCP BYE
1694    if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
1695        _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
1696    {
1697        _engineStatisticsPtr->SetLastError(
1698            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1699            "StartSend() RTP/RTCP failed to stop sending");
1700    }
1701
1702    return 0;
1703}
1704
1705WebRtc_Word32
1706Channel::StartReceiving()
1707{
1708    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1709                 "Channel::StartReceiving()");
1710    if (_receiving)
1711    {
1712        return 0;
1713    }
1714    // If external transport is used, we will only initialize/set the variables
1715    // after this section, since we are not using the WebRtc transport but
1716    // still need to keep track of e.g. if we are receiving.
1717#ifndef WEBRTC_EXTERNAL_TRANSPORT
1718    if (!_externalTransport)
1719    {
1720        if (!_socketTransportModule.ReceiveSocketsInitialized())
1721        {
1722            _engineStatisticsPtr->SetLastError(
1723                VE_SOCKETS_NOT_INITED, kTraceError,
1724                "StartReceive() must set local receiver first");
1725            return -1;
1726        }
1727        if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0)
1728        {
1729            _engineStatisticsPtr->SetLastError(
1730                VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1731                "StartReceiving() failed to start receiving");
1732            return -1;
1733        }
1734    }
1735#endif
1736    _receiving = true;
1737    _numberOfDiscardedPackets = 0;
1738    return 0;
1739}
1740
1741WebRtc_Word32
1742Channel::StopReceiving()
1743{
1744    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1745                 "Channel::StopReceiving()");
1746    if (!_receiving)
1747    {
1748        return 0;
1749    }
1750
1751#ifndef WEBRTC_EXTERNAL_TRANSPORT
1752    if (!_externalTransport &&
1753        _socketTransportModule.ReceiveSocketsInitialized())
1754    {
1755        if (_socketTransportModule.StopReceiving() != 0)
1756        {
1757            _engineStatisticsPtr->SetLastError(
1758                VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1759                "StopReceiving() failed to stop receiving.");
1760            return -1;
1761        }
1762    }
1763#endif
1764    bool dtmfDetection = _rtpRtcpModule->TelephoneEvent();
1765    // Recover DTMF detection status.
1766    WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventStatus(dtmfDetection,
1767                                                               true, true);
1768    if (ret != 0) {
1769        _engineStatisticsPtr->SetLastError(
1770            VE_INVALID_OPERATION, kTraceWarning,
1771            "StopReceiving() failed to restore telephone-event status.");
1772    }
1773    RegisterReceiveCodecsToRTPModule();
1774    _receiving = false;
1775    return 0;
1776}
1777
1778#ifndef WEBRTC_EXTERNAL_TRANSPORT
1779WebRtc_Word32
1780Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort,
1781                          const WebRtc_UWord16 rtcpPort,
1782                          const char ipAddr[64],
1783                          const char multicastIpAddr[64])
1784{
1785    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1786                 "Channel::SetLocalReceiver()");
1787
1788    if (_externalTransport)
1789    {
1790        _engineStatisticsPtr->SetLastError(
1791            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1792            "SetLocalReceiver() conflict with external transport");
1793        return -1;
1794    }
1795
1796    if (_sending)
1797    {
1798        _engineStatisticsPtr->SetLastError(
1799            VE_ALREADY_SENDING, kTraceError,
1800            "SetLocalReceiver() already sending");
1801        return -1;
1802    }
1803    if (_receiving)
1804    {
1805        _engineStatisticsPtr->SetLastError(
1806            VE_ALREADY_LISTENING, kTraceError,
1807            "SetLocalReceiver() already receiving");
1808        return -1;
1809    }
1810
1811    if (_socketTransportModule.InitializeReceiveSockets(this,
1812                                                        rtpPort,
1813                                                        ipAddr,
1814                                                        multicastIpAddr,
1815                                                        rtcpPort) != 0)
1816    {
1817        UdpTransport::ErrorCode lastSockError(
1818            _socketTransportModule.LastError());
1819        switch (lastSockError)
1820        {
1821        case UdpTransport::kIpAddressInvalid:
1822            _engineStatisticsPtr->SetLastError(
1823                VE_INVALID_IP_ADDRESS, kTraceError,
1824                "SetLocalReceiver() invalid IP address");
1825            break;
1826        case UdpTransport::kSocketInvalid:
1827            _engineStatisticsPtr->SetLastError(
1828                VE_SOCKET_ERROR, kTraceError,
1829                "SetLocalReceiver() invalid socket");
1830            break;
1831        case UdpTransport::kPortInvalid:
1832            _engineStatisticsPtr->SetLastError(
1833                VE_INVALID_PORT_NMBR, kTraceError,
1834                "SetLocalReceiver() invalid port");
1835            break;
1836        case UdpTransport::kFailedToBindPort:
1837            _engineStatisticsPtr->SetLastError(
1838                VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError,
1839                "SetLocalReceiver() binding failed");
1840            break;
1841        default:
1842            _engineStatisticsPtr->SetLastError(
1843                VE_SOCKET_ERROR, kTraceError,
1844                "SetLocalReceiver() undefined socket error");
1845            break;
1846        }
1847        return -1;
1848    }
1849    return 0;
1850}
1851#endif
1852
1853#ifndef WEBRTC_EXTERNAL_TRANSPORT
1854WebRtc_Word32
1855Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64])
1856{
1857    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1858                 "Channel::GetLocalReceiver()");
1859
1860    if (_externalTransport)
1861    {
1862        _engineStatisticsPtr->SetLastError(
1863            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1864            "SetLocalReceiver() conflict with external transport");
1865        return -1;
1866    }
1867
1868    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
1869    WebRtc_UWord16 rtpPort(0);
1870    WebRtc_UWord16 rtcpPort(0);
1871    char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0};
1872
1873    // Acquire socket information from the socket module
1874    if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp,
1875                                                        rtpPort,
1876                                                        rtcpPort,
1877                                                        multicastIpAddr) != 0)
1878    {
1879        _engineStatisticsPtr->SetLastError(
1880            VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1881            "GetLocalReceiver() unable to retrieve socket information");
1882        return -1;
1883    }
1884
1885    // Deliver valid results to the user
1886    port = static_cast<int> (rtpPort);
1887    RTCPport = static_cast<int> (rtcpPort);
1888    if (ipAddr != NULL)
1889    {
1890        strcpy(ipAddr, ipAddrTmp);
1891    }
1892    return 0;
1893}
1894#endif
1895
1896#ifndef WEBRTC_EXTERNAL_TRANSPORT
1897WebRtc_Word32
1898Channel::SetSendDestination(const WebRtc_UWord16 rtpPort,
1899                            const char ipAddr[64],
1900                            const int sourcePort,
1901                            const WebRtc_UWord16 rtcpPort)
1902{
1903    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1904                 "Channel::SetSendDestination()");
1905
1906    if (_externalTransport)
1907    {
1908        _engineStatisticsPtr->SetLastError(
1909            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1910            "SetSendDestination() conflict with external transport");
1911        return -1;
1912    }
1913
1914    // Initialize ports and IP address for the remote (destination) side.
1915    // By default, the sockets used for receiving are used for transmission as
1916    // well, hence the source ports for outgoing packets are the same as the
1917    // receiving ports specified in SetLocalReceiver.
1918    // If an extra send socket has been created, it will be utilized until a
1919    // new source port is specified or until the channel has been deleted and
1920    // recreated. If no socket exists, sockets will be created when the first
1921    // RTP and RTCP packets shall be transmitted (see e.g.
1922    // UdpTransportImpl::SendPacket()).
1923    //
1924    // NOTE: this function does not require that sockets exists; all it does is
1925    // to build send structures to be used with the sockets when they exist.
1926    // It is therefore possible to call this method before SetLocalReceiver.
1927    // However, sockets must exist if a multi-cast address is given as input.
1928
1929    // Build send structures and enable QoS (if enabled and supported)
1930    if (_socketTransportModule.InitializeSendSockets(
1931        ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError)
1932    {
1933        UdpTransport::ErrorCode lastSockError(
1934            _socketTransportModule.LastError());
1935        switch (lastSockError)
1936        {
1937        case UdpTransport::kIpAddressInvalid:
1938            _engineStatisticsPtr->SetLastError(
1939                VE_INVALID_IP_ADDRESS, kTraceError,
1940                "SetSendDestination() invalid IP address 1");
1941            break;
1942        case UdpTransport::kSocketInvalid:
1943            _engineStatisticsPtr->SetLastError(
1944                VE_SOCKET_ERROR, kTraceError,
1945                "SetSendDestination() invalid socket 1");
1946            break;
1947        case UdpTransport::kQosError:
1948            _engineStatisticsPtr->SetLastError(
1949                VE_GQOS_ERROR, kTraceError,
1950                "SetSendDestination() failed to set QoS");
1951            break;
1952        case UdpTransport::kMulticastAddressInvalid:
1953            _engineStatisticsPtr->SetLastError(
1954                VE_INVALID_MULTICAST_ADDRESS, kTraceError,
1955                "SetSendDestination() invalid multicast address");
1956            break;
1957        default:
1958            _engineStatisticsPtr->SetLastError(
1959                VE_SOCKET_ERROR, kTraceError,
1960                "SetSendDestination() undefined socket error 1");
1961            break;
1962        }
1963        return -1;
1964    }
1965
1966    // Check if the user has specified a non-default source port different from
1967    // the local receive port.
1968    // If so, an extra local socket will be created unless the source port is
1969    // not unique.
1970    if (sourcePort != kVoEDefault)
1971    {
1972        WebRtc_UWord16 receiverRtpPort(0);
1973        WebRtc_UWord16 rtcpNA(0);
1974        if (_socketTransportModule.ReceiveSocketInformation(NULL,
1975                                                            receiverRtpPort,
1976                                                            rtcpNA,
1977                                                            NULL) != 0)
1978        {
1979            _engineStatisticsPtr->SetLastError(
1980                VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1981                "SetSendDestination() failed to retrieve socket information");
1982            return -1;
1983        }
1984
1985        WebRtc_UWord16 sourcePortUW16 =
1986                static_cast<WebRtc_UWord16> (sourcePort);
1987
1988        // An extra socket will only be created if the specified source port
1989        // differs from the local receive port.
1990        if (sourcePortUW16 != receiverRtpPort)
1991        {
1992            // Initialize extra local socket to get a different source port
1993            // than the local
1994            // receiver port. Always use default source for RTCP.
1995            // Note that, this calls UdpTransport::CloseSendSockets().
1996            if (_socketTransportModule.InitializeSourcePorts(
1997                sourcePortUW16,
1998                sourcePortUW16+1) != 0)
1999            {
2000                UdpTransport::ErrorCode lastSockError(
2001                    _socketTransportModule.LastError());
2002                switch (lastSockError)
2003                {
2004                case UdpTransport::kIpAddressInvalid:
2005                    _engineStatisticsPtr->SetLastError(
2006                        VE_INVALID_IP_ADDRESS, kTraceError,
2007                        "SetSendDestination() invalid IP address 2");
2008                    break;
2009                case UdpTransport::kSocketInvalid:
2010                    _engineStatisticsPtr->SetLastError(
2011                        VE_SOCKET_ERROR, kTraceError,
2012                        "SetSendDestination() invalid socket 2");
2013                    break;
2014                default:
2015                    _engineStatisticsPtr->SetLastError(
2016                        VE_SOCKET_ERROR, kTraceError,
2017                        "SetSendDestination() undefined socket error 2");
2018                    break;
2019                }
2020                return -1;
2021            }
2022            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2023                         VoEId(_instanceId,_channelId),
2024                         "SetSendDestination() extra local socket is created"
2025                         " to facilitate unique source port");
2026        }
2027        else
2028        {
2029            WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2030                         VoEId(_instanceId,_channelId),
2031                         "SetSendDestination() sourcePort equals the local"
2032                         " receive port => no extra socket is created");
2033        }
2034    }
2035
2036    return 0;
2037}
2038#endif
2039
2040#ifndef WEBRTC_EXTERNAL_TRANSPORT
2041WebRtc_Word32
2042Channel::GetSendDestination(int& port,
2043                            char ipAddr[64],
2044                            int& sourcePort,
2045                            int& RTCPport)
2046{
2047    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2048                 "Channel::GetSendDestination()");
2049
2050    if (_externalTransport)
2051    {
2052        _engineStatisticsPtr->SetLastError(
2053            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
2054            "GetSendDestination() conflict with external transport");
2055        return -1;
2056    }
2057
2058    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2059    WebRtc_UWord16 rtpPort(0);
2060    WebRtc_UWord16 rtcpPort(0);
2061    WebRtc_UWord16 rtpSourcePort(0);
2062    WebRtc_UWord16 rtcpSourcePort(0);
2063
2064    // Acquire sending socket information from the socket module
2065    _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort);
2066    _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort);
2067
2068    // Deliver valid results to the user
2069    port = static_cast<int> (rtpPort);
2070    RTCPport = static_cast<int> (rtcpPort);
2071    sourcePort = static_cast<int> (rtpSourcePort);
2072    if (ipAddr != NULL)
2073    {
2074        strcpy(ipAddr, ipAddrTmp);
2075    }
2076
2077    return 0;
2078}
2079#endif
2080
2081
2082WebRtc_Word32
2083Channel::SetNetEQPlayoutMode(NetEqModes mode)
2084{
2085    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2086                 "Channel::SetNetEQPlayoutMode()");
2087    AudioPlayoutMode playoutMode(voice);
2088    switch (mode)
2089    {
2090        case kNetEqDefault:
2091            playoutMode = voice;
2092            break;
2093        case kNetEqStreaming:
2094            playoutMode = streaming;
2095            break;
2096        case kNetEqFax:
2097            playoutMode = fax;
2098            break;
2099    }
2100    if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
2101    {
2102        _engineStatisticsPtr->SetLastError(
2103            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2104            "SetNetEQPlayoutMode() failed to set playout mode");
2105        return -1;
2106    }
2107    return 0;
2108}
2109
2110WebRtc_Word32
2111Channel::GetNetEQPlayoutMode(NetEqModes& mode)
2112{
2113    const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
2114    switch (playoutMode)
2115    {
2116        case voice:
2117            mode = kNetEqDefault;
2118            break;
2119        case streaming:
2120            mode = kNetEqStreaming;
2121            break;
2122        case fax:
2123            mode = kNetEqFax;
2124            break;
2125    }
2126    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2127                 VoEId(_instanceId,_channelId),
2128                 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
2129    return 0;
2130}
2131
2132WebRtc_Word32
2133Channel::SetNetEQBGNMode(NetEqBgnModes mode)
2134{
2135    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2136                 "Channel::SetNetEQPlayoutMode()");
2137    ACMBackgroundNoiseMode noiseMode(On);
2138    switch (mode)
2139    {
2140        case kBgnOn:
2141            noiseMode = On;
2142            break;
2143        case kBgnFade:
2144            noiseMode = Fade;
2145            break;
2146        case kBgnOff:
2147            noiseMode = Off;
2148            break;
2149    }
2150    if (_audioCodingModule.SetBackgroundNoiseMode(noiseMode) != 0)
2151    {
2152        _engineStatisticsPtr->SetLastError(
2153            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2154            "SetBackgroundNoiseMode() failed to set noise mode");
2155        return -1;
2156    }
2157    return 0;
2158}
2159
2160WebRtc_Word32
2161Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
2162{
2163    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2164                 "Channel::SetOnHoldStatus()");
2165    if (mode == kHoldSendAndPlay)
2166    {
2167        _outputIsOnHold = enable;
2168        _inputIsOnHold = enable;
2169    }
2170    else if (mode == kHoldPlayOnly)
2171    {
2172        _outputIsOnHold = enable;
2173    }
2174    if (mode == kHoldSendOnly)
2175    {
2176        _inputIsOnHold = enable;
2177    }
2178    return 0;
2179}
2180
2181WebRtc_Word32
2182Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
2183{
2184    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2185                 "Channel::GetOnHoldStatus()");
2186    enabled = (_outputIsOnHold || _inputIsOnHold);
2187    if (_outputIsOnHold && _inputIsOnHold)
2188    {
2189        mode = kHoldSendAndPlay;
2190    }
2191    else if (_outputIsOnHold && !_inputIsOnHold)
2192    {
2193        mode = kHoldPlayOnly;
2194    }
2195    else if (!_outputIsOnHold && _inputIsOnHold)
2196    {
2197        mode = kHoldSendOnly;
2198    }
2199    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2200                 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
2201                 enabled, mode);
2202    return 0;
2203}
2204
2205WebRtc_Word32
2206Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
2207{
2208    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2209                 "Channel::RegisterVoiceEngineObserver()");
2210    CriticalSectionScoped cs(&_callbackCritSect);
2211
2212    if (_voiceEngineObserverPtr)
2213    {
2214        _engineStatisticsPtr->SetLastError(
2215            VE_INVALID_OPERATION, kTraceError,
2216            "RegisterVoiceEngineObserver() observer already enabled");
2217        return -1;
2218    }
2219    _voiceEngineObserverPtr = &observer;
2220    return 0;
2221}
2222
2223WebRtc_Word32
2224Channel::DeRegisterVoiceEngineObserver()
2225{
2226    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2227                 "Channel::DeRegisterVoiceEngineObserver()");
2228    CriticalSectionScoped cs(&_callbackCritSect);
2229
2230    if (!_voiceEngineObserverPtr)
2231    {
2232        _engineStatisticsPtr->SetLastError(
2233            VE_INVALID_OPERATION, kTraceWarning,
2234            "DeRegisterVoiceEngineObserver() observer already disabled");
2235        return 0;
2236    }
2237    _voiceEngineObserverPtr = NULL;
2238    return 0;
2239}
2240
2241WebRtc_Word32
2242Channel::GetNetEQBGNMode(NetEqBgnModes& mode)
2243{
2244  ACMBackgroundNoiseMode noiseMode(On);
2245    _audioCodingModule.BackgroundNoiseMode(noiseMode);
2246    switch (noiseMode)
2247    {
2248        case On:
2249            mode = kBgnOn;
2250            break;
2251        case Fade:
2252            mode = kBgnFade;
2253            break;
2254        case Off:
2255            mode = kBgnOff;
2256            break;
2257    }
2258    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2259                 "Channel::GetNetEQBGNMode() => mode=%u", mode);
2260    return 0;
2261}
2262
2263WebRtc_Word32
2264Channel::GetSendCodec(CodecInst& codec)
2265{
2266    return (_audioCodingModule.SendCodec(codec));
2267}
2268
2269WebRtc_Word32
2270Channel::GetRecCodec(CodecInst& codec)
2271{
2272    return (_audioCodingModule.ReceiveCodec(codec));
2273}
2274
2275WebRtc_Word32
2276Channel::SetSendCodec(const CodecInst& codec)
2277{
2278    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2279                 "Channel::SetSendCodec()");
2280
2281    if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2282    {
2283        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2284                     "SetSendCodec() failed to register codec to ACM");
2285        return -1;
2286    }
2287
2288    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2289    {
2290        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2291        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2292        {
2293            WEBRTC_TRACE(
2294                    kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2295                    "SetSendCodec() failed to register codec to"
2296                    " RTP/RTCP module");
2297            return -1;
2298        }
2299    }
2300
2301    if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
2302    {
2303        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2304                     "SetSendCodec() failed to set audio packet size");
2305        return -1;
2306    }
2307
2308    return 0;
2309}
2310
2311WebRtc_Word32
2312Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
2313{
2314    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2315                 "Channel::SetVADStatus(mode=%d)", mode);
2316    // To disable VAD, DTX must be disabled too
2317    disableDTX = ((enableVAD == false) ? true : disableDTX);
2318    if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
2319    {
2320        _engineStatisticsPtr->SetLastError(
2321            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2322            "SetVADStatus() failed to set VAD");
2323        return -1;
2324    }
2325    return 0;
2326}
2327
2328WebRtc_Word32
2329Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
2330{
2331    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2332                 "Channel::GetVADStatus");
2333    if (_audioCodingModule.VAD(disabledDTX, enabledVAD, mode) != 0)
2334    {
2335        _engineStatisticsPtr->SetLastError(
2336            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2337            "GetVADStatus() failed to get VAD status");
2338        return -1;
2339    }
2340    disabledDTX = !disabledDTX;
2341    return 0;
2342}
2343
2344WebRtc_Word32
2345Channel::SetRecPayloadType(const CodecInst& codec)
2346{
2347    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2348                 "Channel::SetRecPayloadType()");
2349
2350    if (_playing)
2351    {
2352        _engineStatisticsPtr->SetLastError(
2353            VE_ALREADY_PLAYING, kTraceError,
2354            "SetRecPayloadType() unable to set PT while playing");
2355        return -1;
2356    }
2357    if (_receiving)
2358    {
2359        _engineStatisticsPtr->SetLastError(
2360            VE_ALREADY_LISTENING, kTraceError,
2361            "SetRecPayloadType() unable to set PT while listening");
2362        return -1;
2363    }
2364
2365    if (codec.pltype == -1)
2366    {
2367        // De-register the selected codec (RTP/RTCP module and ACM)
2368
2369        WebRtc_Word8 pltype(-1);
2370        CodecInst rxCodec = codec;
2371
2372        // Get payload type for the given codec
2373        _rtpRtcpModule->ReceivePayloadType(rxCodec, &pltype);
2374        rxCodec.pltype = pltype;
2375
2376        if (_rtpRtcpModule->DeRegisterReceivePayload(pltype) != 0)
2377        {
2378            _engineStatisticsPtr->SetLastError(
2379                    VE_RTP_RTCP_MODULE_ERROR,
2380                    kTraceError,
2381                    "SetRecPayloadType() RTP/RTCP-module deregistration "
2382                    "failed");
2383            return -1;
2384        }
2385        if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
2386        {
2387            _engineStatisticsPtr->SetLastError(
2388                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2389                "SetRecPayloadType() ACM deregistration failed - 1");
2390            return -1;
2391        }
2392        return 0;
2393    }
2394
2395    if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
2396    {
2397        // First attempt to register failed => de-register and try again
2398        _rtpRtcpModule->DeRegisterReceivePayload(codec.pltype);
2399        if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
2400        {
2401            _engineStatisticsPtr->SetLastError(
2402                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2403                "SetRecPayloadType() RTP/RTCP-module registration failed");
2404            return -1;
2405        }
2406    }
2407    if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2408    {
2409        _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
2410        if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2411        {
2412            _engineStatisticsPtr->SetLastError(
2413                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2414                "SetRecPayloadType() ACM registration failed - 1");
2415            return -1;
2416        }
2417    }
2418    return 0;
2419}
2420
2421WebRtc_Word32
2422Channel::GetRecPayloadType(CodecInst& codec)
2423{
2424    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2425                 "Channel::GetRecPayloadType()");
2426    WebRtc_Word8 payloadType(-1);
2427    if (_rtpRtcpModule->ReceivePayloadType(codec, &payloadType) != 0)
2428    {
2429        _engineStatisticsPtr->SetLastError(
2430            VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
2431            "GetRecPayloadType() failed to retrieve RX payload type");
2432        return -1;
2433    }
2434    codec.pltype = payloadType;
2435    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2436                 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
2437    return 0;
2438}
2439
2440WebRtc_Word32
2441Channel::SetAMREncFormat(AmrMode mode)
2442{
2443    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2444                 "Channel::SetAMREncFormat()");
2445
2446    // ACM doesn't support AMR
2447    return -1;
2448}
2449
2450WebRtc_Word32
2451Channel::SetAMRDecFormat(AmrMode mode)
2452{
2453    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2454                 "Channel::SetAMRDecFormat()");
2455
2456    // ACM doesn't support AMR
2457    return -1;
2458}
2459
2460WebRtc_Word32
2461Channel::SetAMRWbEncFormat(AmrMode mode)
2462{
2463    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2464                 "Channel::SetAMRWbEncFormat()");
2465
2466    // ACM doesn't support AMR
2467    return -1;
2468
2469}
2470
2471WebRtc_Word32
2472Channel::SetAMRWbDecFormat(AmrMode mode)
2473{
2474    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2475                 "Channel::SetAMRWbDecFormat()");
2476
2477    // ACM doesn't support AMR
2478    return -1;
2479}
2480
2481WebRtc_Word32
2482Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
2483{
2484    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2485                 "Channel::SetSendCNPayloadType()");
2486
2487    CodecInst codec;
2488    WebRtc_Word32 samplingFreqHz(-1);
2489    const int kMono = 1;
2490    if (frequency == kFreq32000Hz)
2491        samplingFreqHz = 32000;
2492    else if (frequency == kFreq16000Hz)
2493        samplingFreqHz = 16000;
2494
2495    if (_audioCodingModule.Codec("CN", codec, samplingFreqHz, kMono) == -1)
2496    {
2497        _engineStatisticsPtr->SetLastError(
2498            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2499            "SetSendCNPayloadType() failed to retrieve default CN codec "
2500            "settings");
2501        return -1;
2502    }
2503
2504    // Modify the payload type (must be set to dynamic range)
2505    codec.pltype = type;
2506
2507    if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2508    {
2509        _engineStatisticsPtr->SetLastError(
2510            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2511            "SetSendCNPayloadType() failed to register CN to ACM");
2512        return -1;
2513    }
2514
2515    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2516    {
2517        _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2518        if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2519        {
2520            _engineStatisticsPtr->SetLastError(
2521                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2522                "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
2523                "module");
2524            return -1;
2525        }
2526    }
2527    return 0;
2528}
2529
2530WebRtc_Word32
2531Channel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
2532{
2533    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2534                 "Channel::SetISACInitTargetRate()");
2535
2536    CodecInst sendCodec;
2537    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2538    {
2539        _engineStatisticsPtr->SetLastError(
2540            VE_CODEC_ERROR, kTraceError,
2541            "SetISACInitTargetRate() failed to retrieve send codec");
2542        return -1;
2543    }
2544    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2545    {
2546        // This API is only valid if iSAC is setup to run in channel-adaptive
2547        // mode.
2548        // We do not validate the adaptive mode here. It is done later in the
2549        // ConfigISACBandwidthEstimator() API.
2550        _engineStatisticsPtr->SetLastError(
2551            VE_CODEC_ERROR, kTraceError,
2552            "SetISACInitTargetRate() send codec is not iSAC");
2553        return -1;
2554    }
2555
2556    WebRtc_UWord8 initFrameSizeMsec(0);
2557    if (16000 == sendCodec.plfreq)
2558    {
2559        // Note that 0 is a valid and corresponds to "use default
2560        if ((rateBps != 0 &&
2561            rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
2562            (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
2563        {
2564             _engineStatisticsPtr->SetLastError(
2565                VE_INVALID_ARGUMENT, kTraceError,
2566                "SetISACInitTargetRate() invalid target rate - 1");
2567            return -1;
2568        }
2569        // 30 or 60ms
2570        initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 16);
2571    }
2572    else if (32000 == sendCodec.plfreq)
2573    {
2574        if ((rateBps != 0 &&
2575            rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
2576            (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
2577        {
2578            _engineStatisticsPtr->SetLastError(
2579                VE_INVALID_ARGUMENT, kTraceError,
2580                "SetISACInitTargetRate() invalid target rate - 2");
2581            return -1;
2582        }
2583        initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 32); // 30ms
2584    }
2585
2586    if (_audioCodingModule.ConfigISACBandwidthEstimator(
2587        initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2588    {
2589        _engineStatisticsPtr->SetLastError(
2590            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2591            "SetISACInitTargetRate() iSAC BWE config failed");
2592        return -1;
2593    }
2594
2595    return 0;
2596}
2597
2598WebRtc_Word32
2599Channel::SetISACMaxRate(int rateBps)
2600{
2601    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2602                 "Channel::SetISACMaxRate()");
2603
2604    CodecInst sendCodec;
2605    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2606    {
2607        _engineStatisticsPtr->SetLastError(
2608            VE_CODEC_ERROR, kTraceError,
2609            "SetISACMaxRate() failed to retrieve send codec");
2610        return -1;
2611    }
2612    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2613    {
2614        // This API is only valid if iSAC is selected as sending codec.
2615        _engineStatisticsPtr->SetLastError(
2616            VE_CODEC_ERROR, kTraceError,
2617            "SetISACMaxRate() send codec is not iSAC");
2618        return -1;
2619    }
2620    if (16000 == sendCodec.plfreq)
2621    {
2622        if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2623            (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2624        {
2625            _engineStatisticsPtr->SetLastError(
2626                VE_INVALID_ARGUMENT, kTraceError,
2627                "SetISACMaxRate() invalid max rate - 1");
2628            return -1;
2629        }
2630    }
2631    else if (32000 == sendCodec.plfreq)
2632    {
2633        if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2634            (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2635        {
2636            _engineStatisticsPtr->SetLastError(
2637                VE_INVALID_ARGUMENT, kTraceError,
2638                "SetISACMaxRate() invalid max rate - 2");
2639            return -1;
2640        }
2641    }
2642    if (_sending)
2643    {
2644        _engineStatisticsPtr->SetLastError(
2645            VE_SENDING, kTraceError,
2646            "SetISACMaxRate() unable to set max rate while sending");
2647        return -1;
2648    }
2649
2650    // Set the maximum instantaneous rate of iSAC (works for both adaptive
2651    // and non-adaptive mode)
2652    if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2653    {
2654        _engineStatisticsPtr->SetLastError(
2655            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2656            "SetISACMaxRate() failed to set max rate");
2657        return -1;
2658    }
2659
2660    return 0;
2661}
2662
2663WebRtc_Word32
2664Channel::SetISACMaxPayloadSize(int sizeBytes)
2665{
2666    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2667                 "Channel::SetISACMaxPayloadSize()");
2668    CodecInst sendCodec;
2669    if (_audioCodingModule.SendCodec(sendCodec) == -1)
2670    {
2671        _engineStatisticsPtr->SetLastError(
2672            VE_CODEC_ERROR, kTraceError,
2673            "SetISACMaxPayloadSize() failed to retrieve send codec");
2674        return -1;
2675    }
2676    if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2677    {
2678        _engineStatisticsPtr->SetLastError(
2679            VE_CODEC_ERROR, kTraceError,
2680            "SetISACMaxPayloadSize() send codec is not iSAC");
2681        return -1;
2682    }
2683    if (16000 == sendCodec.plfreq)
2684    {
2685        if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2686            (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2687        {
2688            _engineStatisticsPtr->SetLastError(
2689                VE_INVALID_ARGUMENT, kTraceError,
2690                "SetISACMaxPayloadSize() invalid max payload - 1");
2691            return -1;
2692        }
2693    }
2694    else if (32000 == sendCodec.plfreq)
2695    {
2696        if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2697            (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2698        {
2699            _engineStatisticsPtr->SetLastError(
2700                VE_INVALID_ARGUMENT, kTraceError,
2701                "SetISACMaxPayloadSize() invalid max payload - 2");
2702            return -1;
2703        }
2704    }
2705    if (_sending)
2706    {
2707        _engineStatisticsPtr->SetLastError(
2708            VE_SENDING, kTraceError,
2709            "SetISACMaxPayloadSize() unable to set max rate while sending");
2710        return -1;
2711    }
2712
2713    if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2714    {
2715        _engineStatisticsPtr->SetLastError(
2716            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2717            "SetISACMaxPayloadSize() failed to set max payload size");
2718        return -1;
2719    }
2720    return 0;
2721}
2722
2723WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport)
2724{
2725    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2726               "Channel::RegisterExternalTransport()");
2727
2728    CriticalSectionScoped cs(&_callbackCritSect);
2729
2730#ifndef WEBRTC_EXTERNAL_TRANSPORT
2731    // Sanity checks for default (non external transport) to avoid conflict with
2732    // WebRtc sockets.
2733    if (_socketTransportModule.SendSocketsInitialized())
2734    {
2735        _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT,
2736                                           kTraceError,
2737                "RegisterExternalTransport() send sockets already initialized");
2738        return -1;
2739    }
2740    if (_socketTransportModule.ReceiveSocketsInitialized())
2741    {
2742        _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT,
2743                                           kTraceError,
2744             "RegisterExternalTransport() receive sockets already initialized");
2745        return -1;
2746    }
2747#endif
2748    if (_externalTransport)
2749    {
2750        _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2751                                           kTraceError,
2752              "RegisterExternalTransport() external transport already enabled");
2753       return -1;
2754    }
2755    _externalTransport = true;
2756    _transportPtr = &transport;
2757    return 0;
2758}
2759
2760WebRtc_Word32
2761Channel::DeRegisterExternalTransport()
2762{
2763    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2764                 "Channel::DeRegisterExternalTransport()");
2765
2766    CriticalSectionScoped cs(&_callbackCritSect);
2767
2768    if (!_transportPtr)
2769    {
2770        _engineStatisticsPtr->SetLastError(
2771            VE_INVALID_OPERATION, kTraceWarning,
2772            "DeRegisterExternalTransport() external transport already "
2773            "disabled");
2774        return 0;
2775    }
2776    _externalTransport = false;
2777#ifdef WEBRTC_EXTERNAL_TRANSPORT
2778    _transportPtr = NULL;
2779    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2780                 "DeRegisterExternalTransport() all transport is disabled");
2781#else
2782    _transportPtr = &_socketTransportModule;
2783    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2784                 "DeRegisterExternalTransport() internal Transport is enabled");
2785#endif
2786    return 0;
2787}
2788
2789WebRtc_Word32
2790Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2791{
2792    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2793                 "Channel::ReceivedRTPPacket()");
2794    const char dummyIP[] = "127.0.0.1";
2795    IncomingRTPPacket(data, length, dummyIP, 0);
2796    return 0;
2797}
2798
2799WebRtc_Word32
2800Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2801{
2802    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2803                 "Channel::ReceivedRTCPPacket()");
2804    const char dummyIP[] = "127.0.0.1";
2805    IncomingRTCPPacket(data, length, dummyIP, 0);
2806    return 0;
2807}
2808
2809#ifndef WEBRTC_EXTERNAL_TRANSPORT
2810WebRtc_Word32
2811Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64])
2812{
2813    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2814                 "Channel::GetSourceInfo()");
2815
2816    WebRtc_UWord16 rtpPortModule;
2817    WebRtc_UWord16 rtcpPortModule;
2818    char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0};
2819
2820    if (_socketTransportModule.RemoteSocketInformation(ipaddr,
2821                                                       rtpPortModule,
2822                                                       rtcpPortModule) != 0)
2823    {
2824        _engineStatisticsPtr->SetLastError(
2825            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2826            "GetSourceInfo() failed to retrieve remote socket information");
2827        return -1;
2828    }
2829    strcpy(ipAddr, ipaddr);
2830    rtpPort = rtpPortModule;
2831    rtcpPort = rtcpPortModule;
2832
2833    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2834        "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2835        rtpPort, rtcpPort, ipAddr);
2836    return 0;
2837}
2838
2839WebRtc_Word32
2840Channel::EnableIPv6()
2841{
2842    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2843                 "Channel::EnableIPv6()");
2844    if (_socketTransportModule.ReceiveSocketsInitialized() ||
2845        _socketTransportModule.SendSocketsInitialized())
2846    {
2847        _engineStatisticsPtr->SetLastError(
2848            VE_INVALID_OPERATION, kTraceError,
2849            "EnableIPv6() socket layer is already initialized");
2850        return -1;
2851    }
2852    if (_socketTransportModule.EnableIpV6() != 0)
2853    {
2854        _engineStatisticsPtr->SetLastError(
2855            VE_SOCKET_ERROR, kTraceError,
2856            "EnableIPv6() failed to enable IPv6");
2857        const UdpTransport::ErrorCode lastError =
2858            _socketTransportModule.LastError();
2859        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2860                     "UdpTransport::LastError() => %d", lastError);
2861        return -1;
2862    }
2863    return 0;
2864}
2865
2866bool
2867Channel::IPv6IsEnabled() const
2868{
2869    bool isEnabled = _socketTransportModule.IpV6Enabled();
2870    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2871                 "IPv6IsEnabled() => %d", isEnabled);
2872    return isEnabled;
2873}
2874
2875WebRtc_Word32
2876Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64])
2877{
2878    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2879                 "Channel::SetSourceFilter()");
2880    if (_socketTransportModule.SetFilterPorts(
2881        static_cast<WebRtc_UWord16>(rtpPort),
2882        static_cast<WebRtc_UWord16>(rtcpPort)) != 0)
2883    {
2884        _engineStatisticsPtr->SetLastError(
2885            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2886            "SetSourceFilter() failed to set filter ports");
2887        const UdpTransport::ErrorCode lastError =
2888            _socketTransportModule.LastError();
2889        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2890                     "UdpTransport::LastError() => %d",
2891                     lastError);
2892        return -1;
2893    }
2894    const char* filterIpAddress = ipAddr;
2895    if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0)
2896    {
2897        _engineStatisticsPtr->SetLastError(
2898            VE_INVALID_IP_ADDRESS, kTraceError,
2899            "SetSourceFilter() failed to set filter IP address");
2900        const UdpTransport::ErrorCode lastError =
2901           _socketTransportModule.LastError();
2902        WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2903                     "UdpTransport::LastError() => %d", lastError);
2904        return -1;
2905    }
2906    return 0;
2907}
2908
2909WebRtc_Word32
2910Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64])
2911{
2912    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2913                 "Channel::GetSourceFilter()");
2914    WebRtc_UWord16 rtpFilterPort(0);
2915    WebRtc_UWord16 rtcpFilterPort(0);
2916    if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0)
2917    {
2918        _engineStatisticsPtr->SetLastError(
2919            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2920            "GetSourceFilter() failed to retrieve filter ports");
2921    }
2922    char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2923    if (_socketTransportModule.FilterIP(ipAddrTmp) != 0)
2924    {
2925        // no filter has been configured (not seen as an error)
2926        memset(ipAddrTmp,
2927               0, UdpTransport::kIpAddressVersion6Length);
2928    }
2929    rtpPort = static_cast<int> (rtpFilterPort);
2930    rtcpPort = static_cast<int> (rtcpFilterPort);
2931    strcpy(ipAddr, ipAddrTmp);
2932    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2933        "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2934        rtpPort, rtcpPort, ipAddr);
2935    return 0;
2936}
2937
2938WebRtc_Word32
2939Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt)
2940{
2941    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2942                 "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)",
2943                 DSCP, (int)useSetSockopt);
2944
2945    // Set TOS value and possibly try to force usage of setsockopt()
2946    if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0)
2947    {
2948        UdpTransport::ErrorCode lastSockError(
2949            _socketTransportModule.LastError());
2950        switch (lastSockError)
2951        {
2952        case UdpTransport::kTosError:
2953            _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2954                                               "SetSendTOS() TOS error");
2955            break;
2956        case UdpTransport::kQosError:
2957            _engineStatisticsPtr->SetLastError(
2958                    VE_TOS_GQOS_CONFLICT, kTraceError,
2959                    "SetSendTOS() GQOS error");
2960            break;
2961        case UdpTransport::kTosInvalid:
2962            // can't switch SetSockOpt method without disabling TOS first, or
2963            // SetSockopt() call failed
2964            _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError,
2965                                               "SetSendTOS() invalid TOS");
2966            break;
2967        case UdpTransport::kSocketInvalid:
2968            _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
2969                                               "SetSendTOS() invalid Socket");
2970            break;
2971        default:
2972            _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2973                                               "SetSendTOS() TOS error");
2974            break;
2975        }
2976        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2977                     "UdpTransport =>  lastError = %d",
2978                     lastSockError);
2979        return -1;
2980    }
2981
2982    // Set priority (PCP) value, -1 means don't change
2983    if (-1 != priority)
2984    {
2985        if (_socketTransportModule.SetPCP(priority) != 0)
2986        {
2987            UdpTransport::ErrorCode lastSockError(
2988                _socketTransportModule.LastError());
2989            switch (lastSockError)
2990            {
2991            case UdpTransport::kPcpError:
2992                _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2993                                                   "SetSendTOS() PCP error");
2994                break;
2995            case UdpTransport::kQosError:
2996                _engineStatisticsPtr->SetLastError(
2997                        VE_TOS_GQOS_CONFLICT, kTraceError,
2998                        "SetSendTOS() GQOS conflict");
2999                break;
3000            case UdpTransport::kSocketInvalid:
3001                _engineStatisticsPtr->SetLastError(
3002                        VE_SOCKET_ERROR, kTraceError,
3003                        "SetSendTOS() invalid Socket");
3004                break;
3005            default:
3006                _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3007                                                   "SetSendTOS() PCP error");
3008                break;
3009            }
3010            WEBRTC_TRACE(kTraceError, kTraceVoice,
3011                         VoEId(_instanceId,_channelId),
3012                         "UdpTransport =>  lastError = %d",
3013                         lastSockError);
3014            return -1;
3015        }
3016    }
3017
3018    return 0;
3019}
3020
3021WebRtc_Word32
3022Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt)
3023{
3024    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3025                 "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)");
3026    WebRtc_Word32 dscp(0), prio(0);
3027    bool setSockopt(false);
3028    if (_socketTransportModule.ToS(dscp, setSockopt) != 0)
3029    {
3030        _engineStatisticsPtr->SetLastError(
3031            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3032            "GetSendTOS() failed to get TOS info");
3033        return -1;
3034    }
3035    if (_socketTransportModule.PCP(prio) != 0)
3036    {
3037        _engineStatisticsPtr->SetLastError(
3038            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3039            "GetSendTOS() failed to get PCP info");
3040        return -1;
3041    }
3042    DSCP = static_cast<int> (dscp);
3043    priority = static_cast<int> (prio);
3044    useSetSockopt = setSockopt;
3045    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3046                 "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d",
3047        DSCP, priority, (int)useSetSockopt);
3048    return 0;
3049}
3050
3051#if defined(_WIN32)
3052WebRtc_Word32
3053Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP)
3054{
3055    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3056                 "Channel::SetSendGQoS(enable=%d, serviceType=%d, "
3057                 "overrideDSCP=%d)",
3058                 (int)enable, serviceType, overrideDSCP);
3059    if(!_socketTransportModule.ReceiveSocketsInitialized())
3060    {
3061        _engineStatisticsPtr->SetLastError(
3062            VE_SOCKETS_NOT_INITED, kTraceError,
3063            "SetSendGQoS() GQoS state must be set after sockets are created");
3064        return -1;
3065    }
3066    if(!_socketTransportModule.SendSocketsInitialized())
3067    {
3068        _engineStatisticsPtr->SetLastError(
3069            VE_DESTINATION_NOT_INITED, kTraceError,
3070            "SetSendGQoS() GQoS state must be set after sending side is "
3071            "initialized");
3072        return -1;
3073    }
3074    if (enable &&
3075       (serviceType != SERVICETYPE_BESTEFFORT) &&
3076       (serviceType != SERVICETYPE_CONTROLLEDLOAD) &&
3077       (serviceType != SERVICETYPE_GUARANTEED) &&
3078       (serviceType != SERVICETYPE_QUALITATIVE))
3079    {
3080        _engineStatisticsPtr->SetLastError(
3081            VE_INVALID_ARGUMENT, kTraceError,
3082            "SetSendGQoS() Invalid service type");
3083        return -1;
3084    }
3085    if (enable && ((overrideDSCP <  0) || (overrideDSCP > 63)))
3086    {
3087        _engineStatisticsPtr->SetLastError(
3088            VE_INVALID_ARGUMENT, kTraceError,
3089            "SetSendGQoS() Invalid overrideDSCP value");
3090        return -1;
3091    }
3092
3093    // Avoid GQoS/ToS conflict when user wants to override the default DSCP
3094    // mapping
3095    bool QoS(false);
3096    WebRtc_Word32 sType(0);
3097    WebRtc_Word32 ovrDSCP(0);
3098    if (_socketTransportModule.QoS(QoS, sType, ovrDSCP))
3099    {
3100        _engineStatisticsPtr->SetLastError(
3101            VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3102            "SetSendGQoS() failed to get QOS info");
3103        return -1;
3104    }
3105    if (QoS && ovrDSCP == 0 && overrideDSCP != 0)
3106    {
3107        _engineStatisticsPtr->SetLastError(
3108            VE_TOS_GQOS_CONFLICT, kTraceError,
3109            "SetSendGQoS() QOS is already enabled and overrideDSCP differs,"
3110            " not allowed");
3111        return -1;
3112    }
3113    const WebRtc_Word32 maxBitrate(0);
3114    if (_socketTransportModule.SetQoS(enable,
3115                                      static_cast<WebRtc_Word32>(serviceType),
3116                                      maxBitrate,
3117                                      static_cast<WebRtc_Word32>(overrideDSCP),
3118                                      true))
3119    {
3120        UdpTransport::ErrorCode lastSockError(
3121            _socketTransportModule.LastError());
3122        switch (lastSockError)
3123        {
3124        case UdpTransport::kQosError:
3125            _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError,
3126                                               "SetSendGQoS() QOS error");
3127            break;
3128        default:
3129            _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
3130                                               "SetSendGQoS() Socket error");
3131            break;
3132        }
3133        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3134                     "UdpTransport() => lastError = %d",
3135                     lastSockError);
3136        return -1;
3137    }
3138    return 0;
3139}
3140#endif
3141
3142#if defined(_WIN32)
3143WebRtc_Word32
3144Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP)
3145{
3146    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3147                 "Channel::GetSendGQoS(enable=?, serviceType=?, "
3148                 "overrideDSCP=?)");
3149
3150    bool QoS(false);
3151    WebRtc_Word32 serviceTypeModule(0);
3152    WebRtc_Word32 overrideDSCPModule(0);
3153    _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule);
3154
3155    enabled = QoS;
3156    serviceType = static_cast<int> (serviceTypeModule);
3157    overrideDSCP = static_cast<int> (overrideDSCPModule);
3158
3159    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3160                 "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d",
3161                 (int)enabled, serviceType, overrideDSCP);
3162    return 0;
3163}
3164#endif
3165#endif
3166
3167WebRtc_Word32
3168Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds)
3169{
3170    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3171                 "Channel::SetPacketTimeoutNotification()");
3172    if (enable)
3173    {
3174        const WebRtc_UWord32 RTPtimeoutMS = 1000*timeoutSeconds;
3175        const WebRtc_UWord32 RTCPtimeoutMS = 0;
3176        _rtpRtcpModule->SetPacketTimeout(RTPtimeoutMS, RTCPtimeoutMS);
3177        _rtpPacketTimeOutIsEnabled = true;
3178        _rtpTimeOutSeconds = timeoutSeconds;
3179    }
3180    else
3181    {
3182        _rtpRtcpModule->SetPacketTimeout(0, 0);
3183        _rtpPacketTimeOutIsEnabled = false;
3184        _rtpTimeOutSeconds = 0;
3185    }
3186    return 0;
3187}
3188
3189WebRtc_Word32
3190Channel::GetPacketTimeoutNotification(bool& enabled, int& timeoutSeconds)
3191{
3192    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3193                 "Channel::GetPacketTimeoutNotification()");
3194    enabled = _rtpPacketTimeOutIsEnabled;
3195    if (enabled)
3196    {
3197        timeoutSeconds = _rtpTimeOutSeconds;
3198    }
3199    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3200                 "GetPacketTimeoutNotification() => enabled=%d,"
3201                 " timeoutSeconds=%d",
3202                 enabled, timeoutSeconds);
3203    return 0;
3204}
3205
3206WebRtc_Word32
3207Channel::RegisterDeadOrAliveObserver(VoEConnectionObserver& observer)
3208{
3209    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3210                 "Channel::RegisterDeadOrAliveObserver()");
3211    CriticalSectionScoped cs(&_callbackCritSect);
3212
3213    if (_connectionObserverPtr)
3214    {
3215        _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, kTraceError,
3216            "RegisterDeadOrAliveObserver() observer already enabled");
3217        return -1;
3218    }
3219
3220    _connectionObserverPtr = &observer;
3221    _connectionObserver = true;
3222
3223    return 0;
3224}
3225
3226WebRtc_Word32
3227Channel::DeRegisterDeadOrAliveObserver()
3228{
3229    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3230                 "Channel::DeRegisterDeadOrAliveObserver()");
3231    CriticalSectionScoped cs(&_callbackCritSect);
3232
3233    if (!_connectionObserverPtr)
3234    {
3235        _engineStatisticsPtr->SetLastError(
3236            VE_INVALID_OPERATION, kTraceWarning,
3237            "DeRegisterDeadOrAliveObserver() observer already disabled");
3238        return 0;
3239    }
3240
3241    _connectionObserver = false;
3242    _connectionObserverPtr = NULL;
3243
3244    return 0;
3245}
3246
3247WebRtc_Word32
3248Channel::SetPeriodicDeadOrAliveStatus(bool enable, int sampleTimeSeconds)
3249{
3250    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3251                 "Channel::SetPeriodicDeadOrAliveStatus()");
3252    if (!_connectionObserverPtr)
3253    {
3254        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3255                     "SetPeriodicDeadOrAliveStatus() connection observer has"
3256                     " not been registered");
3257    }
3258    if (enable)
3259    {
3260        ResetDeadOrAliveCounters();
3261    }
3262    bool enabled(false);
3263    WebRtc_UWord8 currentSampleTimeSec(0);
3264    // Store last state (will be used later if dead-or-alive is disabled).
3265    _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, currentSampleTimeSec);
3266    // Update the dead-or-alive state.
3267    if (_rtpRtcpModule->SetPeriodicDeadOrAliveStatus(
3268        enable, (WebRtc_UWord8)sampleTimeSeconds) != 0)
3269    {
3270        _engineStatisticsPtr->SetLastError(
3271                VE_RTP_RTCP_MODULE_ERROR,
3272                kTraceError,
3273                "SetPeriodicDeadOrAliveStatus() failed to set dead-or-alive "
3274                "status");
3275        return -1;
3276    }
3277    if (!enable)
3278    {
3279        // Restore last utilized sample time.
3280        // Without this, the sample time would always be reset to default
3281        // (2 sec), each time dead-or-alived was disabled without sample-time
3282        // parameter.
3283        _rtpRtcpModule->SetPeriodicDeadOrAliveStatus(enable,
3284                                                    currentSampleTimeSec);
3285    }
3286    return 0;
3287}
3288
3289WebRtc_Word32
3290Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds)
3291{
3292    _rtpRtcpModule->PeriodicDeadOrAliveStatus(
3293        enabled,
3294        (WebRtc_UWord8&)sampleTimeSeconds);
3295    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3296                 "GetPeriodicDeadOrAliveStatus() => enabled=%d,"
3297                 " sampleTimeSeconds=%d",
3298                 enabled, sampleTimeSeconds);
3299    return 0;
3300}
3301
3302WebRtc_Word32
3303Channel::SendUDPPacket(const void* data,
3304                       unsigned int length,
3305                       int& transmittedBytes,
3306                       bool useRtcpSocket)
3307{
3308    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3309                 "Channel::SendUDPPacket()");
3310    if (_externalTransport)
3311    {
3312        _engineStatisticsPtr->SetLastError(
3313            VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
3314            "SendUDPPacket() external transport is enabled");
3315        return -1;
3316    }
3317    if (useRtcpSocket && !_rtpRtcpModule->RTCP())
3318    {
3319        _engineStatisticsPtr->SetLastError(
3320            VE_RTCP_ERROR, kTraceError,
3321            "SendUDPPacket() RTCP is disabled");
3322        return -1;
3323    }
3324    if (!_sending)
3325    {
3326        _engineStatisticsPtr->SetLastError(
3327            VE_NOT_SENDING, kTraceError,
3328            "SendUDPPacket() not sending");
3329        return -1;
3330    }
3331
3332    char* dataC = new char[length];
3333    if (NULL == dataC)
3334    {
3335        _engineStatisticsPtr->SetLastError(
3336            VE_NO_MEMORY, kTraceError,
3337            "SendUDPPacket() memory allocation failed");
3338        return -1;
3339    }
3340    memcpy(dataC, data, length);
3341
3342    transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket);
3343
3344    delete [] dataC;
3345    dataC = NULL;
3346
3347    if (transmittedBytes <= 0)
3348    {
3349        _engineStatisticsPtr->SetLastError(
3350                VE_SEND_ERROR, kTraceError,
3351                "SendUDPPacket() transmission failed");
3352        transmittedBytes = 0;
3353        return -1;
3354    }
3355    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3356                 "SendUDPPacket() => transmittedBytes=%d", transmittedBytes);
3357    return 0;
3358}
3359
3360
3361int Channel::StartPlayingFileLocally(const char* fileName,
3362                                     const bool loop,
3363                                     const FileFormats format,
3364                                     const int startPosition,
3365                                     const float volumeScaling,
3366                                     const int stopPosition,
3367                                     const CodecInst* codecInst)
3368{
3369    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3370                 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
3371                 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
3372                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3373                 startPosition, stopPosition);
3374
3375    if (_outputFilePlaying)
3376    {
3377        _engineStatisticsPtr->SetLastError(
3378            VE_ALREADY_PLAYING, kTraceError,
3379            "StartPlayingFileLocally() is already playing");
3380        return -1;
3381    }
3382
3383    {
3384        CriticalSectionScoped cs(&_fileCritSect);
3385
3386        if (_outputFilePlayerPtr)
3387        {
3388            _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3389            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3390            _outputFilePlayerPtr = NULL;
3391        }
3392
3393        _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3394            _outputFilePlayerId, (const FileFormats)format);
3395
3396        if (_outputFilePlayerPtr == NULL)
3397        {
3398            _engineStatisticsPtr->SetLastError(
3399                VE_INVALID_ARGUMENT, kTraceError,
3400                "StartPlayingFileLocally() filePlayer format is not correct");
3401            return -1;
3402        }
3403
3404        const WebRtc_UWord32 notificationTime(0);
3405
3406        if (_outputFilePlayerPtr->StartPlayingFile(
3407                fileName,
3408                loop,
3409                startPosition,
3410                volumeScaling,
3411                notificationTime,
3412                stopPosition,
3413                (const CodecInst*)codecInst) != 0)
3414        {
3415            _engineStatisticsPtr->SetLastError(
3416                VE_BAD_FILE, kTraceError,
3417                "StartPlayingFile() failed to start file playout");
3418            _outputFilePlayerPtr->StopPlayingFile();
3419            FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3420            _outputFilePlayerPtr = NULL;
3421            return -1;
3422        }
3423        _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3424        _outputFilePlaying = true;
3425    }
3426
3427    if (RegisterFilePlayingToMixer() != 0)
3428        return -1;
3429
3430    return 0;
3431}
3432
3433int Channel::StartPlayingFileLocally(InStream* stream,
3434                                     const FileFormats format,
3435                                     const int startPosition,
3436                                     const float volumeScaling,
3437                                     const int stopPosition,
3438                                     const CodecInst* codecInst)
3439{
3440    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3441                 "Channel::StartPlayingFileLocally(format=%d,"
3442                 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3443                 format, volumeScaling, startPosition, stopPosition);
3444
3445    if(stream == NULL)
3446    {
3447        _engineStatisticsPtr->SetLastError(
3448            VE_BAD_FILE, kTraceError,
3449            "StartPlayingFileLocally() NULL as input stream");
3450        return -1;
3451    }
3452
3453
3454    if (_outputFilePlaying)
3455    {
3456        _engineStatisticsPtr->SetLastError(
3457            VE_ALREADY_PLAYING, kTraceError,
3458            "StartPlayingFileLocally() is already playing");
3459        return -1;
3460    }
3461
3462    {
3463      CriticalSectionScoped cs(&_fileCritSect);
3464
3465      // Destroy the old instance
3466      if (_outputFilePlayerPtr)
3467      {
3468          _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3469          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3470          _outputFilePlayerPtr = NULL;
3471      }
3472
3473      // Create the instance
3474      _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3475          _outputFilePlayerId,
3476          (const FileFormats)format);
3477
3478      if (_outputFilePlayerPtr == NULL)
3479      {
3480          _engineStatisticsPtr->SetLastError(
3481              VE_INVALID_ARGUMENT, kTraceError,
3482              "StartPlayingFileLocally() filePlayer format isnot correct");
3483          return -1;
3484      }
3485
3486      const WebRtc_UWord32 notificationTime(0);
3487
3488      if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3489                                                 volumeScaling,
3490                                                 notificationTime,
3491                                                 stopPosition, codecInst) != 0)
3492      {
3493          _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3494                                             "StartPlayingFile() failed to "
3495                                             "start file playout");
3496          _outputFilePlayerPtr->StopPlayingFile();
3497          FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3498          _outputFilePlayerPtr = NULL;
3499          return -1;
3500      }
3501      _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3502      _outputFilePlaying = true;
3503    }
3504
3505    if (RegisterFilePlayingToMixer() != 0)
3506        return -1;
3507
3508    return 0;
3509}
3510
3511int Channel::StopPlayingFileLocally()
3512{
3513    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3514                 "Channel::StopPlayingFileLocally()");
3515
3516    if (!_outputFilePlaying)
3517    {
3518        _engineStatisticsPtr->SetLastError(
3519            VE_INVALID_OPERATION, kTraceWarning,
3520            "StopPlayingFileLocally() isnot playing");
3521        return 0;
3522    }
3523
3524    {
3525        CriticalSectionScoped cs(&_fileCritSect);
3526
3527        if (_outputFilePlayerPtr->StopPlayingFile() != 0)
3528        {
3529            _engineStatisticsPtr->SetLastError(
3530                VE_STOP_RECORDING_FAILED, kTraceError,
3531                "StopPlayingFile() could not stop playing");
3532            return -1;
3533        }
3534        _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3535        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3536        _outputFilePlayerPtr = NULL;
3537        _outputFilePlaying = false;
3538    }
3539    // _fileCritSect cannot be taken while calling
3540    // SetAnonymousMixibilityStatus. Refer to comments in
3541    // StartPlayingFileLocally(const char* ...) for more details.
3542    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
3543    {
3544        _engineStatisticsPtr->SetLastError(
3545            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3546            "StopPlayingFile() failed to stop participant from playing as"
3547            "file in the mixer");
3548        return -1;
3549    }
3550
3551    return 0;
3552}
3553
3554int Channel::IsPlayingFileLocally() const
3555{
3556    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3557                 "Channel::IsPlayingFileLocally()");
3558
3559    return (WebRtc_Word32)_outputFilePlaying;
3560}
3561
3562int Channel::RegisterFilePlayingToMixer()
3563{
3564    // Return success for not registering for file playing to mixer if:
3565    // 1. playing file before playout is started on that channel.
3566    // 2. starting playout without file playing on that channel.
3567    if (!_playing || !_outputFilePlaying)
3568    {
3569        return 0;
3570    }
3571
3572    // |_fileCritSect| cannot be taken while calling
3573    // SetAnonymousMixabilityStatus() since as soon as the participant is added
3574    // frames can be pulled by the mixer. Since the frames are generated from
3575    // the file, _fileCritSect will be taken. This would result in a deadlock.
3576    if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3577    {
3578        CriticalSectionScoped cs(&_fileCritSect);
3579        _outputFilePlaying = false;
3580        _engineStatisticsPtr->SetLastError(
3581            VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3582            "StartPlayingFile() failed to add participant as file to mixer");
3583        _outputFilePlayerPtr->StopPlayingFile();
3584        FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3585        _outputFilePlayerPtr = NULL;
3586        return -1;
3587    }
3588
3589    return 0;
3590}
3591
3592int Channel::ScaleLocalFilePlayout(const float scale)
3593{
3594    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3595                 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
3596
3597    CriticalSectionScoped cs(&_fileCritSect);
3598
3599    if (!_outputFilePlaying)
3600    {
3601        _engineStatisticsPtr->SetLastError(
3602            VE_INVALID_OPERATION, kTraceError,
3603            "ScaleLocalFilePlayout() isnot playing");
3604        return -1;
3605    }
3606    if ((_outputFilePlayerPtr == NULL) ||
3607        (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
3608    {
3609        _engineStatisticsPtr->SetLastError(
3610            VE_BAD_ARGUMENT, kTraceError,
3611            "SetAudioScaling() failed to scale the playout");
3612        return -1;
3613    }
3614
3615    return 0;
3616}
3617
3618int Channel::GetLocalPlayoutPosition(int& positionMs)
3619{
3620    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3621                 "Channel::GetLocalPlayoutPosition(position=?)");
3622
3623    WebRtc_UWord32 position;
3624
3625    CriticalSectionScoped cs(&_fileCritSect);
3626
3627    if (_outputFilePlayerPtr == NULL)
3628    {
3629        _engineStatisticsPtr->SetLastError(
3630            VE_INVALID_OPERATION, kTraceError,
3631            "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
3632        return -1;
3633    }
3634
3635    if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
3636    {
3637        _engineStatisticsPtr->SetLastError(
3638            VE_BAD_FILE, kTraceError,
3639            "GetLocalPlayoutPosition() failed");
3640        return -1;
3641    }
3642    positionMs = position;
3643
3644    return 0;
3645}
3646
3647int Channel::StartPlayingFileAsMicrophone(const char* fileName,
3648                                          const bool loop,
3649                                          const FileFormats format,
3650                                          const int startPosition,
3651                                          const float volumeScaling,
3652                                          const int stopPosition,
3653                                          const CodecInst* codecInst)
3654{
3655    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3656                 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
3657                 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
3658                 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3659                 startPosition, stopPosition);
3660
3661    if (_inputFilePlaying)
3662    {
3663        _engineStatisticsPtr->SetLastError(
3664            VE_ALREADY_PLAYING, kTraceWarning,
3665            "StartPlayingFileAsMicrophone() filePlayer is playing");
3666        return 0;
3667    }
3668
3669    CriticalSectionScoped cs(&_fileCritSect);
3670
3671    // Destroy the old instance
3672    if (_inputFilePlayerPtr)
3673    {
3674        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3675        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3676        _inputFilePlayerPtr = NULL;
3677    }
3678
3679    // Create the instance
3680    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3681        _inputFilePlayerId, (const FileFormats)format);
3682
3683    if (_inputFilePlayerPtr == NULL)
3684    {
3685        _engineStatisticsPtr->SetLastError(
3686            VE_INVALID_ARGUMENT, kTraceError,
3687            "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
3688        return -1;
3689    }
3690
3691    const WebRtc_UWord32 notificationTime(0);
3692
3693    if (_inputFilePlayerPtr->StartPlayingFile(
3694        fileName,
3695        loop,
3696        startPosition,
3697        volumeScaling,
3698        notificationTime,
3699        stopPosition,
3700        (const CodecInst*)codecInst) != 0)
3701    {
3702        _engineStatisticsPtr->SetLastError(
3703            VE_BAD_FILE, kTraceError,
3704            "StartPlayingFile() failed to start file playout");
3705        _inputFilePlayerPtr->StopPlayingFile();
3706        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3707        _inputFilePlayerPtr = NULL;
3708        return -1;
3709    }
3710    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3711    _inputFilePlaying = true;
3712
3713    return 0;
3714}
3715
3716int Channel::StartPlayingFileAsMicrophone(InStream* stream,
3717                                          const FileFormats format,
3718                                          const int startPosition,
3719                                          const float volumeScaling,
3720                                          const int stopPosition,
3721                                          const CodecInst* codecInst)
3722{
3723    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3724                 "Channel::StartPlayingFileAsMicrophone(format=%d, "
3725                 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3726                 format, volumeScaling, startPosition, stopPosition);
3727
3728    if(stream == NULL)
3729    {
3730        _engineStatisticsPtr->SetLastError(
3731            VE_BAD_FILE, kTraceError,
3732            "StartPlayingFileAsMicrophone NULL as input stream");
3733        return -1;
3734    }
3735
3736    if (_inputFilePlaying)
3737    {
3738        _engineStatisticsPtr->SetLastError(
3739            VE_ALREADY_PLAYING, kTraceWarning,
3740            "StartPlayingFileAsMicrophone() is playing");
3741        return 0;
3742    }
3743
3744    CriticalSectionScoped cs(&_fileCritSect);
3745
3746    // Destroy the old instance
3747    if (_inputFilePlayerPtr)
3748    {
3749        _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3750        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3751        _inputFilePlayerPtr = NULL;
3752    }
3753
3754    // Create the instance
3755    _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3756        _inputFilePlayerId, (const FileFormats)format);
3757
3758    if (_inputFilePlayerPtr == NULL)
3759    {
3760        _engineStatisticsPtr->SetLastError(
3761            VE_INVALID_ARGUMENT, kTraceError,
3762            "StartPlayingInputFile() filePlayer format isnot correct");
3763        return -1;
3764    }
3765
3766    const WebRtc_UWord32 notificationTime(0);
3767
3768    if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3769                                              volumeScaling, notificationTime,
3770                                              stopPosition, codecInst) != 0)
3771    {
3772        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3773                                           "StartPlayingFile() failed to start "
3774                                           "file playout");
3775        _inputFilePlayerPtr->StopPlayingFile();
3776        FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3777        _inputFilePlayerPtr = NULL;
3778        return -1;
3779    }
3780
3781    _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3782    _inputFilePlaying = true;
3783
3784    return 0;
3785}
3786
3787int Channel::StopPlayingFileAsMicrophone()
3788{
3789    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3790                 "Channel::StopPlayingFileAsMicrophone()");
3791
3792    if (!_inputFilePlaying)
3793    {
3794        _engineStatisticsPtr->SetLastError(
3795            VE_INVALID_OPERATION, kTraceWarning,
3796            "StopPlayingFileAsMicrophone() isnot playing");
3797        return 0;
3798    }
3799
3800    CriticalSectionScoped cs(&_fileCritSect);
3801    if (_inputFilePlayerPtr->StopPlayingFile() != 0)
3802    {
3803        _engineStatisticsPtr->SetLastError(
3804            VE_STOP_RECORDING_FAILED, kTraceError,
3805            "StopPlayingFile() could not stop playing");
3806        return -1;
3807    }
3808    _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3809    FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3810    _inputFilePlayerPtr = NULL;
3811    _inputFilePlaying = false;
3812
3813    return 0;
3814}
3815
3816int Channel::IsPlayingFileAsMicrophone() const
3817{
3818    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3819                 "Channel::IsPlayingFileAsMicrophone()");
3820
3821    return _inputFilePlaying;
3822}
3823
3824int Channel::ScaleFileAsMicrophonePlayout(const float scale)
3825{
3826    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3827                 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
3828
3829    CriticalSectionScoped cs(&_fileCritSect);
3830
3831    if (!_inputFilePlaying)
3832    {
3833        _engineStatisticsPtr->SetLastError(
3834            VE_INVALID_OPERATION, kTraceError,
3835            "ScaleFileAsMicrophonePlayout() isnot playing");
3836        return -1;
3837    }
3838
3839    if ((_inputFilePlayerPtr == NULL) ||
3840        (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
3841    {
3842        _engineStatisticsPtr->SetLastError(
3843            VE_BAD_ARGUMENT, kTraceError,
3844            "SetAudioScaling() failed to scale playout");
3845        return -1;
3846    }
3847
3848    return 0;
3849}
3850
3851int Channel::StartRecordingPlayout(const char* fileName,
3852                                   const CodecInst* codecInst)
3853{
3854    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3855                 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
3856
3857    if (_outputFileRecording)
3858    {
3859        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3860                     "StartRecordingPlayout() is already recording");
3861        return 0;
3862    }
3863
3864    FileFormats format;
3865    const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3866    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3867
3868    if ((codecInst != NULL) &&
3869      ((codecInst->channels < 1) || (codecInst->channels > 2)))
3870    {
3871        _engineStatisticsPtr->SetLastError(
3872            VE_BAD_ARGUMENT, kTraceError,
3873            "StartRecordingPlayout() invalid compression");
3874        return(-1);
3875    }
3876    if(codecInst == NULL)
3877    {
3878        format = kFileFormatPcm16kHzFile;
3879        codecInst=&dummyCodec;
3880    }
3881    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3882        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3883        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3884    {
3885        format = kFileFormatWavFile;
3886    }
3887    else
3888    {
3889        format = kFileFormatCompressedFile;
3890    }
3891
3892    CriticalSectionScoped cs(&_fileCritSect);
3893
3894    // Destroy the old instance
3895    if (_outputFileRecorderPtr)
3896    {
3897        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3898        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3899        _outputFileRecorderPtr = NULL;
3900    }
3901
3902    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3903        _outputFileRecorderId, (const FileFormats)format);
3904    if (_outputFileRecorderPtr == NULL)
3905    {
3906        _engineStatisticsPtr->SetLastError(
3907            VE_INVALID_ARGUMENT, kTraceError,
3908            "StartRecordingPlayout() fileRecorder format isnot correct");
3909        return -1;
3910    }
3911
3912    if (_outputFileRecorderPtr->StartRecordingAudioFile(
3913        fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
3914    {
3915        _engineStatisticsPtr->SetLastError(
3916            VE_BAD_FILE, kTraceError,
3917            "StartRecordingAudioFile() failed to start file recording");
3918        _outputFileRecorderPtr->StopRecording();
3919        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3920        _outputFileRecorderPtr = NULL;
3921        return -1;
3922    }
3923    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3924    _outputFileRecording = true;
3925
3926    return 0;
3927}
3928
3929int Channel::StartRecordingPlayout(OutStream* stream,
3930                                   const CodecInst* codecInst)
3931{
3932    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3933                 "Channel::StartRecordingPlayout()");
3934
3935    if (_outputFileRecording)
3936    {
3937        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3938                     "StartRecordingPlayout() is already recording");
3939        return 0;
3940    }
3941
3942    FileFormats format;
3943    const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3944    CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3945
3946    if (codecInst != NULL && codecInst->channels != 1)
3947    {
3948        _engineStatisticsPtr->SetLastError(
3949            VE_BAD_ARGUMENT, kTraceError,
3950            "StartRecordingPlayout() invalid compression");
3951        return(-1);
3952    }
3953    if(codecInst == NULL)
3954    {
3955        format = kFileFormatPcm16kHzFile;
3956        codecInst=&dummyCodec;
3957    }
3958    else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3959        (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3960        (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3961    {
3962        format = kFileFormatWavFile;
3963    }
3964    else
3965    {
3966        format = kFileFormatCompressedFile;
3967    }
3968
3969    CriticalSectionScoped cs(&_fileCritSect);
3970
3971    // Destroy the old instance
3972    if (_outputFileRecorderPtr)
3973    {
3974        _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3975        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3976        _outputFileRecorderPtr = NULL;
3977    }
3978
3979    _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3980        _outputFileRecorderId, (const FileFormats)format);
3981    if (_outputFileRecorderPtr == NULL)
3982    {
3983        _engineStatisticsPtr->SetLastError(
3984            VE_INVALID_ARGUMENT, kTraceError,
3985            "StartRecordingPlayout() fileRecorder format isnot correct");
3986        return -1;
3987    }
3988
3989    if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
3990                                                        notificationTime) != 0)
3991    {
3992        _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3993                                           "StartRecordingPlayout() failed to "
3994                                           "start file recording");
3995        _outputFileRecorderPtr->StopRecording();
3996        FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3997        _outputFileRecorderPtr = NULL;
3998        return -1;
3999    }
4000
4001    _outputFileRecorderPtr->RegisterModuleFileCallback(this);
4002    _outputFileRecording = true;
4003
4004    return 0;
4005}
4006
4007int Channel::StopRecordingPlayout()
4008{
4009    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
4010                 "Channel::StopRecordingPlayout()");
4011
4012    if (!_outputFileRecording)
4013    {
4014        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
4015                     "StopRecordingPlayout() isnot recording");
4016        return -1;
4017    }
4018
4019
4020    CriticalSectionScoped cs(&_fileCritSect);
4021
4022    if (_outputFileRecorderPtr->StopRecording() != 0)
4023    {
4024        _engineStatisticsPtr->SetLastError(
4025            VE_STOP_RECORDING_FAILED, kTraceError,
4026            "StopRecording() could not stop recording");
4027        return(-1);
4028    }
4029    _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
4030    FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4031    _outputFileRecorderPtr = NULL;
4032    _outputFileRecording = false;
4033
4034    return 0;
4035}
4036
4037void
4038Channel::SetMixWithMicStatus(bool mix)
4039{
4040    _mixFileWithMicrophone=mix;
4041}
4042
4043int
4044Channel::GetSpeechOutputLevel(WebRtc_UWord32& level) const
4045{
4046    WebRtc_Word8 currentLevel = _outputAudioLevel.Level();
4047    level = static_cast<WebRtc_Word32> (currentLevel);
4048    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4049               VoEId(_instanceId,_channelId),
4050               "GetSpeechOutputLevel() => level=%u", level);
4051    return 0;
4052}
4053
4054int
4055Channel::GetSpeechOutputLevelFullRange(WebRtc_UWord32& level) const
4056{
4057    WebRtc_Word16 currentLevel = _outputAudioLevel.LevelFullRange();
4058    level = static_cast<WebRtc_Word32> (currentLevel);
4059    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4060               VoEId(_instanceId,_channelId),
4061               "GetSpeechOutputLevelFullRange() => level=%u", level);
4062    return 0;
4063}
4064
4065int
4066Channel::SetMute(bool enable)
4067{
4068    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4069               "Channel::SetMute(enable=%d)", enable);
4070    _mute = enable;
4071    return 0;
4072}
4073
4074bool
4075Channel::Mute() const
4076{
4077    return _mute;
4078}
4079
4080int
4081Channel::SetOutputVolumePan(float left, float right)
4082{
4083    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4084               "Channel::SetOutputVolumePan()");
4085    _panLeft = left;
4086    _panRight = right;
4087    return 0;
4088}
4089
4090int
4091Channel::GetOutputVolumePan(float& left, float& right) const
4092{
4093    left = _panLeft;
4094    right = _panRight;
4095    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4096               VoEId(_instanceId,_channelId),
4097               "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
4098    return 0;
4099}
4100
4101int
4102Channel::SetChannelOutputVolumeScaling(float scaling)
4103{
4104    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4105               "Channel::SetChannelOutputVolumeScaling()");
4106    _outputGain = scaling;
4107    return 0;
4108}
4109
4110int
4111Channel::GetChannelOutputVolumeScaling(float& scaling) const
4112{
4113    scaling = _outputGain;
4114    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4115               VoEId(_instanceId,_channelId),
4116               "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
4117    return 0;
4118}
4119
4120#ifdef WEBRTC_SRTP
4121
4122int
4123Channel::EnableSRTPSend(
4124    CipherTypes cipherType,
4125    int cipherKeyLength,
4126    AuthenticationTypes authType,
4127    int authKeyLength,
4128    int authTagLength,
4129    SecurityLevels level,
4130    const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4131    bool useForRTCP)
4132{
4133    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4134               "Channel::EnableSRTPSend()");
4135
4136    CriticalSectionScoped cs(&_callbackCritSect);
4137
4138    if (_encrypting)
4139    {
4140        _engineStatisticsPtr->SetLastError(
4141            VE_INVALID_OPERATION, kTraceWarning,
4142            "EnableSRTPSend() encryption already enabled");
4143        return -1;
4144    }
4145
4146    if (key == NULL)
4147    {
4148        _engineStatisticsPtr->SetLastError(
4149            VE_INVALID_ARGUMENT, kTraceWarning,
4150            "EnableSRTPSend() invalid key string");
4151        return -1;
4152    }
4153
4154    if (((kEncryption == level ||
4155            kEncryptionAndAuthentication == level) &&
4156            (cipherKeyLength < kVoiceEngineMinSrtpEncryptLength ||
4157            cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength)) ||
4158        ((kAuthentication == level ||
4159            kEncryptionAndAuthentication == level) &&
4160            kAuthHmacSha1 == authType &&
4161            (authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length ||
4162            authTagLength > kVoiceEngineMaxSrtpAuthSha1Length)) ||
4163        ((kAuthentication == level ||
4164            kEncryptionAndAuthentication == level) &&
4165            kAuthNull == authType &&
4166            (authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength ||
4167            authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength)))
4168    {
4169        _engineStatisticsPtr->SetLastError(
4170            VE_INVALID_ARGUMENT, kTraceError,
4171            "EnableSRTPSend() invalid key length(s)");
4172        return -1;
4173    }
4174
4175
4176    if (_srtpModule.EnableSRTPEncrypt(
4177        !useForRTCP,
4178        (SrtpModule::CipherTypes)cipherType,
4179        cipherKeyLength,
4180        (SrtpModule::AuthenticationTypes)authType,
4181        authKeyLength, authTagLength,
4182        (SrtpModule::SecurityLevels)level,
4183        key) == -1)
4184    {
4185        _engineStatisticsPtr->SetLastError(
4186            VE_SRTP_ERROR, kTraceError,
4187            "EnableSRTPSend() failed to enable SRTP encryption");
4188        return -1;
4189    }
4190
4191    if (_encryptionPtr == NULL)
4192    {
4193        _encryptionPtr = &_srtpModule;
4194    }
4195    _encrypting = true;
4196
4197    return 0;
4198}
4199
4200int
4201Channel::DisableSRTPSend()
4202{
4203    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4204               "Channel::DisableSRTPSend()");
4205
4206    CriticalSectionScoped cs(&_callbackCritSect);
4207
4208    if (!_encrypting)
4209    {
4210        _engineStatisticsPtr->SetLastError(
4211            VE_INVALID_OPERATION, kTraceWarning,
4212            "DisableSRTPSend() SRTP encryption already disabled");
4213        return 0;
4214    }
4215
4216    _encrypting = false;
4217
4218    if (_srtpModule.DisableSRTPEncrypt() == -1)
4219    {
4220        _engineStatisticsPtr->SetLastError(
4221            VE_SRTP_ERROR, kTraceError,
4222            "DisableSRTPSend() failed to disable SRTP encryption");
4223        return -1;
4224    }
4225
4226    if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4227    {
4228        // Both directions are disabled
4229        _encryptionPtr = NULL;
4230    }
4231
4232    return 0;
4233}
4234
4235int
4236Channel::EnableSRTPReceive(
4237    CipherTypes  cipherType,
4238    int cipherKeyLength,
4239    AuthenticationTypes authType,
4240    int authKeyLength,
4241    int authTagLength,
4242    SecurityLevels level,
4243    const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4244    bool useForRTCP)
4245{
4246    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4247               "Channel::EnableSRTPReceive()");
4248
4249    CriticalSectionScoped cs(&_callbackCritSect);
4250
4251    if (_decrypting)
4252    {
4253        _engineStatisticsPtr->SetLastError(
4254            VE_INVALID_OPERATION, kTraceWarning,
4255            "EnableSRTPReceive() SRTP decryption already enabled");
4256        return -1;
4257    }
4258
4259    if (key == NULL)
4260    {
4261        _engineStatisticsPtr->SetLastError(
4262            VE_INVALID_ARGUMENT, kTraceWarning,
4263            "EnableSRTPReceive() invalid key string");
4264        return -1;
4265    }
4266
4267    if ((((kEncryption == level) ||
4268            (kEncryptionAndAuthentication == level)) &&
4269            ((cipherKeyLength < kVoiceEngineMinSrtpEncryptLength) ||
4270            (cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength))) ||
4271        (((kAuthentication == level) ||
4272            (kEncryptionAndAuthentication == level)) &&
4273            (kAuthHmacSha1 == authType) &&
4274            ((authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length) ||
4275            (authTagLength > kVoiceEngineMaxSrtpAuthSha1Length))) ||
4276        (((kAuthentication == level) ||
4277            (kEncryptionAndAuthentication == level)) &&
4278            (kAuthNull == authType) &&
4279            ((authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength) ||
4280            (authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength))))
4281    {
4282        _engineStatisticsPtr->SetLastError(
4283            VE_INVALID_ARGUMENT, kTraceError,
4284            "EnableSRTPReceive() invalid key length(s)");
4285        return -1;
4286    }
4287
4288    if (_srtpModule.EnableSRTPDecrypt(
4289        !useForRTCP,
4290        (SrtpModule::CipherTypes)cipherType,
4291        cipherKeyLength,
4292        (SrtpModule::AuthenticationTypes)authType,
4293        authKeyLength,
4294        authTagLength,
4295        (SrtpModule::SecurityLevels)level,
4296        key) == -1)
4297    {
4298        _engineStatisticsPtr->SetLastError(
4299            VE_SRTP_ERROR, kTraceError,
4300            "EnableSRTPReceive() failed to enable SRTP decryption");
4301        return -1;
4302    }
4303
4304    if (_encryptionPtr == NULL)
4305    {
4306        _encryptionPtr = &_srtpModule;
4307    }
4308
4309    _decrypting = true;
4310
4311    return 0;
4312}
4313
4314int
4315Channel::DisableSRTPReceive()
4316{
4317    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4318               "Channel::DisableSRTPReceive()");
4319
4320    CriticalSectionScoped cs(&_callbackCritSect);
4321
4322    if (!_decrypting)
4323    {
4324        _engineStatisticsPtr->SetLastError(
4325            VE_INVALID_OPERATION, kTraceWarning,
4326            "DisableSRTPReceive() SRTP decryption already disabled");
4327        return 0;
4328    }
4329
4330    _decrypting = false;
4331
4332    if (_srtpModule.DisableSRTPDecrypt() == -1)
4333    {
4334        _engineStatisticsPtr->SetLastError(
4335            VE_SRTP_ERROR, kTraceError,
4336            "DisableSRTPReceive() failed to disable SRTP decryption");
4337        return -1;
4338    }
4339
4340    if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4341    {
4342        _encryptionPtr = NULL;
4343    }
4344
4345    return 0;
4346}
4347
4348#endif
4349
4350int
4351Channel::RegisterExternalEncryption(Encryption& encryption)
4352{
4353    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4354               "Channel::RegisterExternalEncryption()");
4355
4356    CriticalSectionScoped cs(&_callbackCritSect);
4357
4358    if (_encryptionPtr)
4359    {
4360        _engineStatisticsPtr->SetLastError(
4361            VE_INVALID_OPERATION, kTraceError,
4362            "RegisterExternalEncryption() encryption already enabled");
4363        return -1;
4364    }
4365
4366    _encryptionPtr = &encryption;
4367
4368    _decrypting = true;
4369    _encrypting = true;
4370
4371    return 0;
4372}
4373
4374int
4375Channel::DeRegisterExternalEncryption()
4376{
4377    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4378               "Channel::DeRegisterExternalEncryption()");
4379
4380    CriticalSectionScoped cs(&_callbackCritSect);
4381
4382    if (!_encryptionPtr)
4383    {
4384        _engineStatisticsPtr->SetLastError(
4385            VE_INVALID_OPERATION, kTraceWarning,
4386            "DeRegisterExternalEncryption() encryption already disabled");
4387        return 0;
4388    }
4389
4390    _decrypting = false;
4391    _encrypting = false;
4392
4393    _encryptionPtr = NULL;
4394
4395    return 0;
4396}
4397
4398int Channel::SendTelephoneEventOutband(unsigned char eventCode,
4399                                          int lengthMs, int attenuationDb,
4400                                          bool playDtmfEvent)
4401{
4402    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4403               "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
4404               playDtmfEvent);
4405
4406    _playOutbandDtmfEvent = playDtmfEvent;
4407
4408    if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
4409                                                 attenuationDb) != 0)
4410    {
4411        _engineStatisticsPtr->SetLastError(
4412            VE_SEND_DTMF_FAILED,
4413            kTraceWarning,
4414            "SendTelephoneEventOutband() failed to send event");
4415        return -1;
4416    }
4417    return 0;
4418}
4419
4420int Channel::SendTelephoneEventInband(unsigned char eventCode,
4421                                         int lengthMs,
4422                                         int attenuationDb,
4423                                         bool playDtmfEvent)
4424{
4425    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4426               "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
4427               playDtmfEvent);
4428
4429    _playInbandDtmfEvent = playDtmfEvent;
4430    _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
4431
4432    return 0;
4433}
4434
4435int
4436Channel::SetDtmfPlayoutStatus(bool enable)
4437{
4438    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4439               "Channel::SetDtmfPlayoutStatus()");
4440    if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
4441    {
4442        _engineStatisticsPtr->SetLastError(
4443            VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
4444            "SetDtmfPlayoutStatus() failed to set Dtmf playout");
4445        return -1;
4446    }
4447    return 0;
4448}
4449
4450bool
4451Channel::DtmfPlayoutStatus() const
4452{
4453    return _audioCodingModule.DtmfPlayoutStatus();
4454}
4455
4456int
4457Channel::SetSendTelephoneEventPayloadType(unsigned char type)
4458{
4459    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4460               "Channel::SetSendTelephoneEventPayloadType()");
4461    if (type > 127)
4462    {
4463        _engineStatisticsPtr->SetLastError(
4464            VE_INVALID_ARGUMENT, kTraceError,
4465            "SetSendTelephoneEventPayloadType() invalid type");
4466        return -1;
4467    }
4468    CodecInst codec;
4469    codec.plfreq = 8000;
4470    codec.pltype = type;
4471    memcpy(codec.plname, "telephone-event", 16);
4472    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
4473    {
4474        _engineStatisticsPtr->SetLastError(
4475            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4476            "SetSendTelephoneEventPayloadType() failed to register send"
4477            "payload type");
4478        return -1;
4479    }
4480    _sendTelephoneEventPayloadType = type;
4481    return 0;
4482}
4483
4484int
4485Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
4486{
4487    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4488                 "Channel::GetSendTelephoneEventPayloadType()");
4489    type = _sendTelephoneEventPayloadType;
4490    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4491               VoEId(_instanceId,_channelId),
4492               "GetSendTelephoneEventPayloadType() => type=%u", type);
4493    return 0;
4494}
4495
4496#ifdef WEBRTC_DTMF_DETECTION
4497
4498WebRtc_Word32
4499Channel::RegisterTelephoneEventDetection(
4500    TelephoneEventDetectionMethods detectionMethod,
4501    VoETelephoneEventObserver& observer)
4502{
4503    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4504                 "Channel::RegisterTelephoneEventDetection()");
4505    CriticalSectionScoped cs(&_callbackCritSect);
4506
4507    if (_telephoneEventDetectionPtr)
4508    {
4509        _engineStatisticsPtr->SetLastError(
4510            VE_INVALID_OPERATION, kTraceError,
4511            "RegisterTelephoneEventDetection() detection already enabled");
4512        return -1;
4513    }
4514
4515    _telephoneEventDetectionPtr = &observer;
4516
4517    switch (detectionMethod)
4518    {
4519        case kInBand:
4520            _inbandTelephoneEventDetection = true;
4521            _outOfBandTelephoneEventDetecion = false;
4522            break;
4523        case kOutOfBand:
4524            _inbandTelephoneEventDetection = false;
4525            _outOfBandTelephoneEventDetecion = true;
4526            break;
4527        case kInAndOutOfBand:
4528            _inbandTelephoneEventDetection = true;
4529            _outOfBandTelephoneEventDetecion = true;
4530            break;
4531        default:
4532            _engineStatisticsPtr->SetLastError(
4533                VE_INVALID_ARGUMENT, kTraceError,
4534                "RegisterTelephoneEventDetection() invalid detection method");
4535            return -1;
4536    }
4537
4538    if (_inbandTelephoneEventDetection)
4539    {
4540        // Enable in-band Dtmf detectin in the ACM.
4541        if (_audioCodingModule.RegisterIncomingMessagesCallback(this) != 0)
4542        {
4543            _engineStatisticsPtr->SetLastError(
4544                VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4545                "RegisterTelephoneEventDetection() failed to enable Dtmf "
4546                "detection");
4547        }
4548    }
4549
4550    // Enable/disable out-of-band detection of received telephone-events.
4551    // When enabled, RtpAudioFeedback::OnReceivedTelephoneEvent() will be
4552    // called two times by the RTP/RTCP module (start & end).
4553    const bool forwardToDecoder =
4554        _rtpRtcpModule->TelephoneEventForwardToDecoder();
4555    const bool detectEndOfTone = true;
4556    _rtpRtcpModule->SetTelephoneEventStatus(_outOfBandTelephoneEventDetecion,
4557                                           forwardToDecoder,
4558                                           detectEndOfTone);
4559
4560    return 0;
4561}
4562
4563int
4564Channel::DeRegisterTelephoneEventDetection()
4565{
4566    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4567                 "Channel::DeRegisterTelephoneEventDetection()");
4568
4569    CriticalSectionScoped cs(&_callbackCritSect);
4570
4571    if (!_telephoneEventDetectionPtr)
4572    {
4573        _engineStatisticsPtr->SetLastError(
4574            VE_INVALID_OPERATION,
4575            kTraceWarning,
4576            "DeRegisterTelephoneEventDetection() detection already disabled");
4577        return 0;
4578    }
4579
4580    // Disable out-of-band event detection
4581    const bool forwardToDecoder =
4582        _rtpRtcpModule->TelephoneEventForwardToDecoder();
4583    _rtpRtcpModule->SetTelephoneEventStatus(false, forwardToDecoder);
4584
4585    // Disable in-band Dtmf detection
4586    _audioCodingModule.RegisterIncomingMessagesCallback(NULL);
4587
4588    _inbandTelephoneEventDetection = false;
4589    _outOfBandTelephoneEventDetecion = false;
4590    _telephoneEventDetectionPtr = NULL;
4591
4592    return 0;
4593}
4594
4595int
4596Channel::GetTelephoneEventDetectionStatus(
4597    bool& enabled,
4598    TelephoneEventDetectionMethods& detectionMethod)
4599{
4600    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4601                 "Channel::GetTelephoneEventDetectionStatus()");
4602
4603    {
4604        CriticalSectionScoped cs(&_callbackCritSect);
4605        enabled = (_telephoneEventDetectionPtr != NULL);
4606    }
4607
4608    if (enabled)
4609    {
4610        if (_inbandTelephoneEventDetection && !_outOfBandTelephoneEventDetecion)
4611            detectionMethod = kInBand;
4612        else if (!_inbandTelephoneEventDetection
4613            && _outOfBandTelephoneEventDetecion)
4614            detectionMethod = kOutOfBand;
4615        else if (_inbandTelephoneEventDetection
4616            && _outOfBandTelephoneEventDetecion)
4617            detectionMethod = kInAndOutOfBand;
4618        else
4619        {
4620            assert(false);
4621            return -1;
4622        }
4623    }
4624
4625    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4626               VoEId(_instanceId, _channelId),
4627               "GetTelephoneEventDetectionStatus() => enabled=%d,"
4628               "detectionMethod=%d", enabled, detectionMethod);
4629    return 0;
4630}
4631
4632#endif  // #ifdef WEBRTC_DTMF_DETECTION
4633
4634int
4635Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
4636{
4637    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4638                 "Channel::UpdateRxVadDetection()");
4639
4640    int vadDecision = 1;
4641
4642    vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
4643
4644    if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
4645    {
4646        OnRxVadDetected(vadDecision);
4647        _oldVadDecision = vadDecision;
4648    }
4649
4650    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4651                 "Channel::UpdateRxVadDetection() => vadDecision=%d",
4652                 vadDecision);
4653    return 0;
4654}
4655
4656int
4657Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
4658{
4659    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4660                 "Channel::RegisterRxVadObserver()");
4661    CriticalSectionScoped cs(&_callbackCritSect);
4662
4663    if (_rxVadObserverPtr)
4664    {
4665        _engineStatisticsPtr->SetLastError(
4666            VE_INVALID_OPERATION, kTraceError,
4667            "RegisterRxVadObserver() observer already enabled");
4668        return -1;
4669    }
4670    _rxVadObserverPtr = &observer;
4671    _RxVadDetection = true;
4672    return 0;
4673}
4674
4675int
4676Channel::DeRegisterRxVadObserver()
4677{
4678    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4679                 "Channel::DeRegisterRxVadObserver()");
4680    CriticalSectionScoped cs(&_callbackCritSect);
4681
4682    if (!_rxVadObserverPtr)
4683    {
4684        _engineStatisticsPtr->SetLastError(
4685            VE_INVALID_OPERATION, kTraceWarning,
4686            "DeRegisterRxVadObserver() observer already disabled");
4687        return 0;
4688    }
4689    _rxVadObserverPtr = NULL;
4690    _RxVadDetection = false;
4691    return 0;
4692}
4693
4694int
4695Channel::VoiceActivityIndicator(int &activity)
4696{
4697    activity = _sendFrameType;
4698
4699    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4700               "Channel::VoiceActivityIndicator(indicator=%d)", activity);
4701    return 0;
4702}
4703
4704#ifdef WEBRTC_VOICE_ENGINE_AGC
4705
4706int
4707Channel::SetRxAgcStatus(const bool enable, const AgcModes mode)
4708{
4709    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4710                 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
4711                 (int)enable, (int)mode);
4712
4713    GainControl::Mode agcMode(GainControl::kFixedDigital);
4714    switch (mode)
4715    {
4716        case kAgcDefault:
4717            agcMode = GainControl::kAdaptiveDigital;
4718            break;
4719        case kAgcUnchanged:
4720            agcMode = _rxAudioProcessingModulePtr->gain_control()->mode();
4721            break;
4722        case kAgcFixedDigital:
4723            agcMode = GainControl::kFixedDigital;
4724            break;
4725        case kAgcAdaptiveDigital:
4726            agcMode =GainControl::kAdaptiveDigital;
4727            break;
4728        default:
4729            _engineStatisticsPtr->SetLastError(
4730                VE_INVALID_ARGUMENT, kTraceError,
4731                "SetRxAgcStatus() invalid Agc mode");
4732            return -1;
4733    }
4734
4735    if (_rxAudioProcessingModulePtr->gain_control()->set_mode(agcMode) != 0)
4736    {
4737        _engineStatisticsPtr->SetLastError(
4738            VE_APM_ERROR, kTraceError,
4739            "SetRxAgcStatus() failed to set Agc mode");
4740        return -1;
4741    }
4742    if (_rxAudioProcessingModulePtr->gain_control()->Enable(enable) != 0)
4743    {
4744        _engineStatisticsPtr->SetLastError(
4745            VE_APM_ERROR, kTraceError,
4746            "SetRxAgcStatus() failed to set Agc state");
4747        return -1;
4748    }
4749
4750    _rxAgcIsEnabled = enable;
4751    _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4752
4753    return 0;
4754}
4755
4756int
4757Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
4758{
4759    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4760                     "Channel::GetRxAgcStatus(enable=?, mode=?)");
4761
4762    bool enable = _rxAudioProcessingModulePtr->gain_control()->is_enabled();
4763    GainControl::Mode agcMode =
4764        _rxAudioProcessingModulePtr->gain_control()->mode();
4765
4766    enabled = enable;
4767
4768    switch (agcMode)
4769    {
4770        case GainControl::kFixedDigital:
4771            mode = kAgcFixedDigital;
4772            break;
4773        case GainControl::kAdaptiveDigital:
4774            mode = kAgcAdaptiveDigital;
4775            break;
4776        default:
4777            _engineStatisticsPtr->SetLastError(
4778                VE_APM_ERROR, kTraceError,
4779                "GetRxAgcStatus() invalid Agc mode");
4780            return -1;
4781    }
4782
4783    return 0;
4784}
4785
4786int
4787Channel::SetRxAgcConfig(const AgcConfig config)
4788{
4789    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4790                 "Channel::SetRxAgcConfig()");
4791
4792    if (_rxAudioProcessingModulePtr->gain_control()->set_target_level_dbfs(
4793        config.targetLeveldBOv) != 0)
4794    {
4795        _engineStatisticsPtr->SetLastError(
4796            VE_APM_ERROR, kTraceError,
4797            "SetRxAgcConfig() failed to set target peak |level|"
4798            "(or envelope) of the Agc");
4799        return -1;
4800    }
4801    if (_rxAudioProcessingModulePtr->gain_control()->set_compression_gain_db(
4802        config.digitalCompressionGaindB) != 0)
4803    {
4804        _engineStatisticsPtr->SetLastError(
4805            VE_APM_ERROR, kTraceError,
4806            "SetRxAgcConfig() failed to set the range in |gain| the"
4807            " digital compression stage may apply");
4808        return -1;
4809    }
4810    if (_rxAudioProcessingModulePtr->gain_control()->enable_limiter(
4811        config.limiterEnable) != 0)
4812    {
4813        _engineStatisticsPtr->SetLastError(
4814            VE_APM_ERROR, kTraceError,
4815            "SetRxAgcConfig() failed to set hard limiter to the signal");
4816        return -1;
4817    }
4818
4819    return 0;
4820}
4821
4822int
4823Channel::GetRxAgcConfig(AgcConfig& config)
4824{
4825    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4826                 "Channel::GetRxAgcConfig(config=%?)");
4827
4828    config.targetLeveldBOv =
4829        _rxAudioProcessingModulePtr->gain_control()->target_level_dbfs();
4830    config.digitalCompressionGaindB =
4831        _rxAudioProcessingModulePtr->gain_control()->compression_gain_db();
4832    config.limiterEnable =
4833        _rxAudioProcessingModulePtr->gain_control()->is_limiter_enabled();
4834
4835    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4836               VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
4837                   "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
4838                   " limiterEnable=%d",
4839                   config.targetLeveldBOv,
4840                   config.digitalCompressionGaindB,
4841                   config.limiterEnable);
4842
4843    return 0;
4844}
4845
4846#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
4847
4848#ifdef WEBRTC_VOICE_ENGINE_NR
4849
4850int
4851Channel::SetRxNsStatus(const bool enable, const NsModes mode)
4852{
4853    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4854                 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
4855                 (int)enable, (int)mode);
4856
4857    NoiseSuppression::Level nsLevel(
4858        (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
4859    switch (mode)
4860    {
4861
4862        case kNsDefault:
4863            nsLevel = (NoiseSuppression::Level)
4864                WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
4865            break;
4866        case kNsUnchanged:
4867            nsLevel = _rxAudioProcessingModulePtr->noise_suppression()->level();
4868            break;
4869        case kNsConference:
4870            nsLevel = NoiseSuppression::kHigh;
4871            break;
4872        case kNsLowSuppression:
4873            nsLevel = NoiseSuppression::kLow;
4874            break;
4875        case kNsModerateSuppression:
4876            nsLevel = NoiseSuppression::kModerate;
4877            break;
4878        case kNsHighSuppression:
4879            nsLevel = NoiseSuppression::kHigh;
4880            break;
4881        case kNsVeryHighSuppression:
4882            nsLevel = NoiseSuppression::kVeryHigh;
4883            break;
4884    }
4885
4886    if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(nsLevel)
4887        != 0)
4888    {
4889        _engineStatisticsPtr->SetLastError(
4890            VE_APM_ERROR, kTraceError,
4891            "SetRxAgcStatus() failed to set Ns level");
4892        return -1;
4893    }
4894    if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(enable) != 0)
4895    {
4896        _engineStatisticsPtr->SetLastError(
4897            VE_APM_ERROR, kTraceError,
4898            "SetRxAgcStatus() failed to set Agc state");
4899        return -1;
4900    }
4901
4902    _rxNsIsEnabled = enable;
4903    _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4904
4905    return 0;
4906}
4907
4908int
4909Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
4910{
4911    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4912                 "Channel::GetRxNsStatus(enable=?, mode=?)");
4913
4914    bool enable =
4915        _rxAudioProcessingModulePtr->noise_suppression()->is_enabled();
4916    NoiseSuppression::Level ncLevel =
4917        _rxAudioProcessingModulePtr->noise_suppression()->level();
4918
4919    enabled = enable;
4920
4921    switch (ncLevel)
4922    {
4923        case NoiseSuppression::kLow:
4924            mode = kNsLowSuppression;
4925            break;
4926        case NoiseSuppression::kModerate:
4927            mode = kNsModerateSuppression;
4928            break;
4929        case NoiseSuppression::kHigh:
4930            mode = kNsHighSuppression;
4931            break;
4932        case NoiseSuppression::kVeryHigh:
4933            mode = kNsVeryHighSuppression;
4934            break;
4935    }
4936
4937    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4938               VoEId(_instanceId,_channelId),
4939               "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
4940    return 0;
4941}
4942
4943#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
4944
4945int
4946Channel::RegisterRTPObserver(VoERTPObserver& observer)
4947{
4948    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4949                 "Channel::RegisterRTPObserver()");
4950    CriticalSectionScoped cs(&_callbackCritSect);
4951
4952    if (_rtpObserverPtr)
4953    {
4954        _engineStatisticsPtr->SetLastError(
4955            VE_INVALID_OPERATION, kTraceError,
4956            "RegisterRTPObserver() observer already enabled");
4957        return -1;
4958    }
4959
4960    _rtpObserverPtr = &observer;
4961    _rtpObserver = true;
4962
4963    return 0;
4964}
4965
4966int
4967Channel::DeRegisterRTPObserver()
4968{
4969    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4970                 "Channel::DeRegisterRTPObserver()");
4971    CriticalSectionScoped cs(&_callbackCritSect);
4972
4973    if (!_rtpObserverPtr)
4974    {
4975        _engineStatisticsPtr->SetLastError(
4976            VE_INVALID_OPERATION, kTraceWarning,
4977            "DeRegisterRTPObserver() observer already disabled");
4978        return 0;
4979    }
4980
4981    _rtpObserver = false;
4982    _rtpObserverPtr = NULL;
4983
4984    return 0;
4985}
4986
4987int
4988Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
4989{
4990    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4991                 "Channel::RegisterRTCPObserver()");
4992    CriticalSectionScoped cs(&_callbackCritSect);
4993
4994    if (_rtcpObserverPtr)
4995    {
4996        _engineStatisticsPtr->SetLastError(
4997            VE_INVALID_OPERATION, kTraceError,
4998            "RegisterRTCPObserver() observer already enabled");
4999        return -1;
5000    }
5001
5002    _rtcpObserverPtr = &observer;
5003    _rtcpObserver = true;
5004
5005    return 0;
5006}
5007
5008int
5009Channel::DeRegisterRTCPObserver()
5010{
5011    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5012                 "Channel::DeRegisterRTCPObserver()");
5013    CriticalSectionScoped cs(&_callbackCritSect);
5014
5015    if (!_rtcpObserverPtr)
5016    {
5017        _engineStatisticsPtr->SetLastError(
5018            VE_INVALID_OPERATION, kTraceWarning,
5019            "DeRegisterRTCPObserver() observer already disabled");
5020        return 0;
5021    }
5022
5023    _rtcpObserver = false;
5024    _rtcpObserverPtr = NULL;
5025
5026    return 0;
5027}
5028
5029int
5030Channel::SetLocalSSRC(unsigned int ssrc)
5031{
5032    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5033                 "Channel::SetLocalSSRC()");
5034    if (_sending)
5035    {
5036        _engineStatisticsPtr->SetLastError(
5037            VE_ALREADY_SENDING, kTraceError,
5038            "SetLocalSSRC() already sending");
5039        return -1;
5040    }
5041    if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
5042    {
5043        _engineStatisticsPtr->SetLastError(
5044            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5045            "SetLocalSSRC() failed to set SSRC");
5046        return -1;
5047    }
5048    return 0;
5049}
5050
5051int
5052Channel::GetLocalSSRC(unsigned int& ssrc)
5053{
5054    ssrc = _rtpRtcpModule->SSRC();
5055    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5056                 VoEId(_instanceId,_channelId),
5057                 "GetLocalSSRC() => ssrc=%lu", ssrc);
5058    return 0;
5059}
5060
5061int
5062Channel::GetRemoteSSRC(unsigned int& ssrc)
5063{
5064    ssrc = _rtpRtcpModule->RemoteSSRC();
5065    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5066                 VoEId(_instanceId,_channelId),
5067                 "GetRemoteSSRC() => ssrc=%lu", ssrc);
5068    return 0;
5069}
5070
5071int
5072Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
5073{
5074    if (arrCSRC == NULL)
5075    {
5076        _engineStatisticsPtr->SetLastError(
5077            VE_INVALID_ARGUMENT, kTraceError,
5078            "GetRemoteCSRCs() invalid array argument");
5079        return -1;
5080    }
5081    WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize];
5082    WebRtc_Word32 CSRCs(0);
5083    CSRCs = _rtpRtcpModule->CSRCs(arrOfCSRC);
5084    if (CSRCs > 0)
5085    {
5086        memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(WebRtc_UWord32));
5087        for (int i = 0; i < (int) CSRCs; i++)
5088        {
5089            WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5090                       VoEId(_instanceId, _channelId),
5091                       "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
5092        }
5093    } else
5094    {
5095        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5096                   VoEId(_instanceId, _channelId),
5097                   "GetRemoteCSRCs() => list is empty!");
5098    }
5099    return CSRCs;
5100}
5101
5102int
5103Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
5104{
5105    if (_rtpAudioProc.get() == NULL)
5106    {
5107        _rtpAudioProc.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
5108                                                                _channelId)));
5109        if (_rtpAudioProc.get() == NULL)
5110        {
5111            _engineStatisticsPtr->SetLastError(VE_NO_MEMORY, kTraceCritical,
5112                "Failed to create AudioProcessing");
5113            return -1;
5114        }
5115    }
5116
5117    if (_rtpAudioProc->level_estimator()->Enable(enable) !=
5118        AudioProcessing::kNoError)
5119    {
5120        _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceWarning,
5121            "Failed to enable AudioProcessing::level_estimator()");
5122    }
5123
5124    _includeAudioLevelIndication = enable;
5125    return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
5126}
5127int
5128Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
5129{
5130    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5131                 VoEId(_instanceId,_channelId),
5132                 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
5133                 enabled, ID);
5134    return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
5135}
5136
5137int
5138Channel::SetRTCPStatus(bool enable)
5139{
5140    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5141                 "Channel::SetRTCPStatus()");
5142    if (_rtpRtcpModule->SetRTCPStatus(enable ?
5143        kRtcpCompound : kRtcpOff) != 0)
5144    {
5145        _engineStatisticsPtr->SetLastError(
5146            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5147            "SetRTCPStatus() failed to set RTCP status");
5148        return -1;
5149    }
5150    return 0;
5151}
5152
5153int
5154Channel::GetRTCPStatus(bool& enabled)
5155{
5156    RTCPMethod method = _rtpRtcpModule->RTCP();
5157    enabled = (method != kRtcpOff);
5158    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5159                 VoEId(_instanceId,_channelId),
5160                 "GetRTCPStatus() => enabled=%d", enabled);
5161    return 0;
5162}
5163
5164int
5165Channel::SetRTCP_CNAME(const char cName[256])
5166{
5167    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5168                 "Channel::SetRTCP_CNAME()");
5169    if (_rtpRtcpModule->SetCNAME(cName) != 0)
5170    {
5171        _engineStatisticsPtr->SetLastError(
5172            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5173            "SetRTCP_CNAME() failed to set RTCP CNAME");
5174        return -1;
5175    }
5176    return 0;
5177}
5178
5179int
5180Channel::GetRTCP_CNAME(char cName[256])
5181{
5182    if (_rtpRtcpModule->CNAME(cName) != 0)
5183    {
5184        _engineStatisticsPtr->SetLastError(
5185            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5186            "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
5187        return -1;
5188    }
5189    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5190                 VoEId(_instanceId, _channelId),
5191                 "GetRTCP_CNAME() => cName=%s", cName);
5192    return 0;
5193}
5194
5195int
5196Channel::GetRemoteRTCP_CNAME(char cName[256])
5197{
5198    if (cName == NULL)
5199    {
5200        _engineStatisticsPtr->SetLastError(
5201            VE_INVALID_ARGUMENT, kTraceError,
5202            "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
5203        return -1;
5204    }
5205    char cname[RTCP_CNAME_SIZE];
5206    const WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5207    if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
5208    {
5209        _engineStatisticsPtr->SetLastError(
5210            VE_CANNOT_RETRIEVE_CNAME, kTraceError,
5211            "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
5212        return -1;
5213    }
5214    strcpy(cName, cname);
5215    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5216                 VoEId(_instanceId, _channelId),
5217                 "GetRemoteRTCP_CNAME() => cName=%s", cName);
5218    return 0;
5219}
5220
5221int
5222Channel::GetRemoteRTCPData(
5223    unsigned int& NTPHigh,
5224    unsigned int& NTPLow,
5225    unsigned int& timestamp,
5226    unsigned int& playoutTimestamp,
5227    unsigned int* jitter,
5228    unsigned short* fractionLost)
5229{
5230    // --- Information from sender info in received Sender Reports
5231
5232    RTCPSenderInfo senderInfo;
5233    if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
5234    {
5235        _engineStatisticsPtr->SetLastError(
5236            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5237            "GetRemoteRTCPData() failed to retrieve sender info for remote "
5238            "side");
5239        return -1;
5240    }
5241
5242    // We only utilize 12 out of 20 bytes in the sender info (ignores packet
5243    // and octet count)
5244    NTPHigh = senderInfo.NTPseconds;
5245    NTPLow = senderInfo.NTPfraction;
5246    timestamp = senderInfo.RTPtimeStamp;
5247
5248    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5249                 VoEId(_instanceId, _channelId),
5250                 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
5251                 "timestamp=%lu",
5252                 NTPHigh, NTPLow, timestamp);
5253
5254    // --- Locally derived information
5255
5256    // This value is updated on each incoming RTCP packet (0 when no packet
5257    // has been received)
5258    playoutTimestamp = _playoutTimeStampRTCP;
5259
5260    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5261                 VoEId(_instanceId, _channelId),
5262                 "GetRemoteRTCPData() => playoutTimestamp=%lu",
5263                 _playoutTimeStampRTCP);
5264
5265    if (NULL != jitter || NULL != fractionLost)
5266    {
5267        // Get all RTCP receiver report blocks that have been received on this
5268        // channel. If we receive RTP packets from a remote source we know the
5269        // remote SSRC and use the report block from him.
5270        // Otherwise use the first report block.
5271        std::vector<RTCPReportBlock> remote_stats;
5272        if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
5273            remote_stats.empty()) {
5274          WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5275                       VoEId(_instanceId, _channelId),
5276                       "GetRemoteRTCPData() failed to measure statistics due"
5277                       " to lack of received RTP and/or RTCP packets");
5278          return -1;
5279        }
5280
5281        WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5282        std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
5283        for (; it != remote_stats.end(); ++it) {
5284          if (it->remoteSSRC == remoteSSRC)
5285            break;
5286        }
5287
5288        if (it == remote_stats.end()) {
5289          // If we have not received any RTCP packets from this SSRC it probably
5290          // means that we have not received any RTP packets.
5291          // Use the first received report block instead.
5292          it = remote_stats.begin();
5293          remoteSSRC = it->remoteSSRC;
5294        }
5295
5296        if (jitter) {
5297          *jitter = it->jitter;
5298          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5299                       VoEId(_instanceId, _channelId),
5300                       "GetRemoteRTCPData() => jitter = %lu", *jitter);
5301        }
5302
5303        if (fractionLost) {
5304          *fractionLost = it->fractionLost;
5305          WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5306                       VoEId(_instanceId, _channelId),
5307                       "GetRemoteRTCPData() => fractionLost = %lu",
5308                       *fractionLost);
5309        }
5310    }
5311    return 0;
5312}
5313
5314int
5315Channel::SendApplicationDefinedRTCPPacket(const unsigned char subType,
5316                                             unsigned int name,
5317                                             const char* data,
5318                                             unsigned short dataLengthInBytes)
5319{
5320    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5321                 "Channel::SendApplicationDefinedRTCPPacket()");
5322    if (!_sending)
5323    {
5324        _engineStatisticsPtr->SetLastError(
5325            VE_NOT_SENDING, kTraceError,
5326            "SendApplicationDefinedRTCPPacket() not sending");
5327        return -1;
5328    }
5329    if (NULL == data)
5330    {
5331        _engineStatisticsPtr->SetLastError(
5332            VE_INVALID_ARGUMENT, kTraceError,
5333            "SendApplicationDefinedRTCPPacket() invalid data value");
5334        return -1;
5335    }
5336    if (dataLengthInBytes % 4 != 0)
5337    {
5338        _engineStatisticsPtr->SetLastError(
5339            VE_INVALID_ARGUMENT, kTraceError,
5340            "SendApplicationDefinedRTCPPacket() invalid length value");
5341        return -1;
5342    }
5343    RTCPMethod status = _rtpRtcpModule->RTCP();
5344    if (status == kRtcpOff)
5345    {
5346        _engineStatisticsPtr->SetLastError(
5347            VE_RTCP_ERROR, kTraceError,
5348            "SendApplicationDefinedRTCPPacket() RTCP is disabled");
5349        return -1;
5350    }
5351
5352    // Create and schedule the RTCP APP packet for transmission
5353    if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
5354        subType,
5355        name,
5356        (const unsigned char*) data,
5357        dataLengthInBytes) != 0)
5358    {
5359        _engineStatisticsPtr->SetLastError(
5360            VE_SEND_ERROR, kTraceError,
5361            "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
5362        return -1;
5363    }
5364    return 0;
5365}
5366
5367int
5368Channel::GetRTPStatistics(
5369        unsigned int& averageJitterMs,
5370        unsigned int& maxJitterMs,
5371        unsigned int& discardedPackets)
5372{
5373    WebRtc_UWord8 fraction_lost(0);
5374    WebRtc_UWord32 cum_lost(0);
5375    WebRtc_UWord32 ext_max(0);
5376    WebRtc_UWord32 jitter(0);
5377    WebRtc_UWord32 max_jitter(0);
5378
5379    // The jitter statistics is updated for each received RTP packet and is
5380    // based on received packets.
5381    if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
5382                                     &cum_lost,
5383                                     &ext_max,
5384                                     &jitter,
5385                                     &max_jitter) != 0)
5386    {
5387        _engineStatisticsPtr->SetLastError(
5388            VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5389            "GetRTPStatistics() failed to read RTP statistics from the "
5390            "RTP/RTCP module");
5391    }
5392
5393    const WebRtc_Word32 playoutFrequency =
5394        _audioCodingModule.PlayoutFrequency();
5395    if (playoutFrequency > 0)
5396    {
5397        // Scale RTP statistics given the current playout frequency
5398        maxJitterMs = max_jitter / (playoutFrequency / 1000);
5399        averageJitterMs = jitter / (playoutFrequency / 1000);
5400    }
5401
5402    discardedPackets = _numberOfDiscardedPackets;
5403
5404    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5405               VoEId(_instanceId, _channelId),
5406               "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
5407               " discardedPackets = %lu)",
5408               averageJitterMs, maxJitterMs, discardedPackets);
5409    return 0;
5410}
5411
5412int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
5413  if (sender_info == NULL) {
5414    _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5415        "GetRemoteRTCPSenderInfo() invalid sender_info.");
5416    return -1;
5417  }
5418
5419  // Get the sender info from the latest received RTCP Sender Report.
5420  RTCPSenderInfo rtcp_sender_info;
5421  if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
5422    _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5423        "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
5424    return -1;
5425  }
5426
5427  sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
5428  sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
5429  sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
5430  sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
5431  sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
5432  return 0;
5433}
5434
5435int Channel::GetRemoteRTCPReportBlocks(
5436    std::vector<ReportBlock>* report_blocks) {
5437  if (report_blocks == NULL) {
5438    _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5439      "GetRemoteRTCPReportBlock()s invalid report_blocks.");
5440    return -1;
5441  }
5442
5443  // Get the report blocks from the latest received RTCP Sender or Receiver
5444  // Report. Each element in the vector contains the sender's SSRC and a
5445  // report block according to RFC 3550.
5446  std::vector<RTCPReportBlock> rtcp_report_blocks;
5447  if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
5448    _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5449        "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
5450    return -1;
5451  }
5452
5453  if (rtcp_report_blocks.empty())
5454    return 0;
5455
5456  std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
5457  for (; it != rtcp_report_blocks.end(); ++it) {
5458    ReportBlock report_block;
5459    report_block.sender_SSRC = it->remoteSSRC;
5460    report_block.source_SSRC = it->sourceSSRC;
5461    report_block.fraction_lost = it->fractionLost;
5462    report_block.cumulative_num_packets_lost = it->cumulativeLost;
5463    report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
5464    report_block.interarrival_jitter = it->jitter;
5465    report_block.last_SR_timestamp = it->lastSR;
5466    report_block.delay_since_last_SR = it->delaySinceLastSR;
5467    report_blocks->push_back(report_block);
5468  }
5469  return 0;
5470}
5471
5472int
5473Channel::GetRTPStatistics(CallStatistics& stats)
5474{
5475    WebRtc_UWord8 fraction_lost(0);
5476    WebRtc_UWord32 cum_lost(0);
5477    WebRtc_UWord32 ext_max(0);
5478    WebRtc_UWord32 jitter(0);
5479    WebRtc_UWord32 max_jitter(0);
5480
5481    // --- Part one of the final structure (four values)
5482
5483    // The jitter statistics is updated for each received RTP packet and is
5484    // based on received packets.
5485    if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
5486                                     &cum_lost,
5487                                     &ext_max,
5488                                     &jitter,
5489                                     &max_jitter) != 0)
5490    {
5491        _engineStatisticsPtr->SetLastError(
5492            VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5493            "GetRTPStatistics() failed to read RTP statistics from the "
5494            "RTP/RTCP module");
5495    }
5496
5497    stats.fractionLost = fraction_lost;
5498    stats.cumulativeLost = cum_lost;
5499    stats.extendedMax = ext_max;
5500    stats.jitterSamples = jitter;
5501
5502    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5503                 VoEId(_instanceId, _channelId),
5504                 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
5505                 " extendedMax=%lu, jitterSamples=%li)",
5506                 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
5507                 stats.jitterSamples);
5508
5509    // --- Part two of the final structure (one value)
5510
5511    WebRtc_UWord16 RTT(0);
5512    RTCPMethod method = _rtpRtcpModule->RTCP();
5513    if (method == kRtcpOff)
5514    {
5515        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5516                     VoEId(_instanceId, _channelId),
5517                     "GetRTPStatistics() RTCP is disabled => valid RTT "
5518                     "measurements cannot be retrieved");
5519    } else
5520    {
5521        // The remote SSRC will be zero if no RTP packet has been received.
5522        WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5523        if (remoteSSRC > 0)
5524        {
5525            WebRtc_UWord16 avgRTT(0);
5526            WebRtc_UWord16 maxRTT(0);
5527            WebRtc_UWord16 minRTT(0);
5528
5529            if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
5530                != 0)
5531            {
5532                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5533                             VoEId(_instanceId, _channelId),
5534                             "GetRTPStatistics() failed to retrieve RTT from "
5535                             "the RTP/RTCP module");
5536            }
5537        } else
5538        {
5539            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5540                         VoEId(_instanceId, _channelId),
5541                         "GetRTPStatistics() failed to measure RTT since no "
5542                         "RTP packets have been received yet");
5543        }
5544    }
5545
5546    stats.rttMs = static_cast<int> (RTT);
5547
5548    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5549                 VoEId(_instanceId, _channelId),
5550                 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
5551
5552    // --- Part three of the final structure (four values)
5553
5554    WebRtc_UWord32 bytesSent(0);
5555    WebRtc_UWord32 packetsSent(0);
5556    WebRtc_UWord32 bytesReceived(0);
5557    WebRtc_UWord32 packetsReceived(0);
5558
5559    if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
5560                                       &packetsSent,
5561                                       &bytesReceived,
5562                                       &packetsReceived) != 0)
5563    {
5564        WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5565                     VoEId(_instanceId, _channelId),
5566                     "GetRTPStatistics() failed to retrieve RTP datacounters =>"
5567                     " output will not be complete");
5568    }
5569
5570    stats.bytesSent = bytesSent;
5571    stats.packetsSent = packetsSent;
5572    stats.bytesReceived = bytesReceived;
5573    stats.packetsReceived = packetsReceived;
5574
5575    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5576                 VoEId(_instanceId, _channelId),
5577                 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
5578                 " bytesReceived=%d, packetsReceived=%d)",
5579                 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
5580                 stats.packetsReceived);
5581
5582    return 0;
5583}
5584
5585int Channel::SetFECStatus(bool enable, int redPayloadtype) {
5586  WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5587               "Channel::SetFECStatus()");
5588
5589  if (SetRedPayloadType(redPayloadtype) < 0) {
5590    _engineStatisticsPtr->SetLastError(
5591        VE_CODEC_ERROR, kTraceError,
5592        "SetSecondarySendCodec() Failed to register RED ACM");
5593    return -1;
5594  }
5595
5596  if (_audioCodingModule.SetFECStatus(enable) != 0) {
5597    _engineStatisticsPtr->SetLastError(
5598        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5599        "SetFECStatus() failed to set FEC state in the ACM");
5600    return -1;
5601  }
5602  return 0;
5603}
5604
5605int
5606Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
5607{
5608    enabled = _audioCodingModule.FECStatus();
5609    if (enabled)
5610    {
5611        WebRtc_Word8 payloadType(0);
5612        if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
5613        {
5614            _engineStatisticsPtr->SetLastError(
5615                VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5616                "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
5617                "module");
5618            return -1;
5619        }
5620        WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5621                   VoEId(_instanceId, _channelId),
5622                   "GetFECStatus() => enabled=%d, redPayloadtype=%d",
5623                   enabled, redPayloadtype);
5624        return 0;
5625    }
5626    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5627                 VoEId(_instanceId, _channelId),
5628                 "GetFECStatus() => enabled=%d", enabled);
5629    return 0;
5630}
5631
5632int
5633Channel::StartRTPDump(const char fileNameUTF8[1024],
5634                      RTPDirections direction)
5635{
5636    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5637                 "Channel::StartRTPDump()");
5638    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5639    {
5640        _engineStatisticsPtr->SetLastError(
5641            VE_INVALID_ARGUMENT, kTraceError,
5642            "StartRTPDump() invalid RTP direction");
5643        return -1;
5644    }
5645    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5646        &_rtpDumpIn : &_rtpDumpOut;
5647    if (rtpDumpPtr == NULL)
5648    {
5649        assert(false);
5650        return -1;
5651    }
5652    if (rtpDumpPtr->IsActive())
5653    {
5654        rtpDumpPtr->Stop();
5655    }
5656    if (rtpDumpPtr->Start(fileNameUTF8) != 0)
5657    {
5658        _engineStatisticsPtr->SetLastError(
5659            VE_BAD_FILE, kTraceError,
5660            "StartRTPDump() failed to create file");
5661        return -1;
5662    }
5663    return 0;
5664}
5665
5666int
5667Channel::StopRTPDump(RTPDirections direction)
5668{
5669    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5670                 "Channel::StopRTPDump()");
5671    if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5672    {
5673        _engineStatisticsPtr->SetLastError(
5674            VE_INVALID_ARGUMENT, kTraceError,
5675            "StopRTPDump() invalid RTP direction");
5676        return -1;
5677    }
5678    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5679        &_rtpDumpIn : &_rtpDumpOut;
5680    if (rtpDumpPtr == NULL)
5681    {
5682        assert(false);
5683        return -1;
5684    }
5685    if (!rtpDumpPtr->IsActive())
5686    {
5687        return 0;
5688    }
5689    return rtpDumpPtr->Stop();
5690}
5691
5692bool
5693Channel::RTPDumpIsActive(RTPDirections direction)
5694{
5695    if ((direction != kRtpIncoming) &&
5696        (direction != kRtpOutgoing))
5697    {
5698        _engineStatisticsPtr->SetLastError(
5699            VE_INVALID_ARGUMENT, kTraceError,
5700            "RTPDumpIsActive() invalid RTP direction");
5701        return false;
5702    }
5703    RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5704        &_rtpDumpIn : &_rtpDumpOut;
5705    return rtpDumpPtr->IsActive();
5706}
5707
5708int
5709Channel::InsertExtraRTPPacket(unsigned char payloadType,
5710                              bool markerBit,
5711                              const char* payloadData,
5712                              unsigned short payloadSize)
5713{
5714    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5715               "Channel::InsertExtraRTPPacket()");
5716    if (payloadType > 127)
5717    {
5718        _engineStatisticsPtr->SetLastError(
5719            VE_INVALID_PLTYPE, kTraceError,
5720            "InsertExtraRTPPacket() invalid payload type");
5721        return -1;
5722    }
5723    if (payloadData == NULL)
5724    {
5725        _engineStatisticsPtr->SetLastError(
5726            VE_INVALID_ARGUMENT, kTraceError,
5727            "InsertExtraRTPPacket() invalid payload data");
5728        return -1;
5729    }
5730    if (payloadSize > _rtpRtcpModule->MaxDataPayloadLength())
5731    {
5732        _engineStatisticsPtr->SetLastError(
5733            VE_INVALID_ARGUMENT, kTraceError,
5734            "InsertExtraRTPPacket() invalid payload size");
5735        return -1;
5736    }
5737    if (!_sending)
5738    {
5739        _engineStatisticsPtr->SetLastError(
5740            VE_NOT_SENDING, kTraceError,
5741            "InsertExtraRTPPacket() not sending");
5742        return -1;
5743    }
5744
5745    // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
5746    // Transport::SendPacket() will be called by the module when the RTP packet
5747    // is created.
5748    // The call to SendOutgoingData() does *not* modify the timestamp and
5749    // payloadtype to ensure that the RTP module generates a valid RTP packet
5750    // (user might utilize a non-registered payload type).
5751    // The marker bit and payload type will be replaced just before the actual
5752    // transmission, i.e., the actual modification is done *after* the RTP
5753    // module has delivered its RTP packet back to the VoE.
5754    // We will use the stored values above when the packet is modified
5755    // (see Channel::SendPacket()).
5756
5757    _extraPayloadType = payloadType;
5758    _extraMarkerBit = markerBit;
5759    _insertExtraRTPPacket = true;
5760
5761    if (_rtpRtcpModule->SendOutgoingData(kAudioFrameSpeech,
5762                                        _lastPayloadType,
5763                                        _lastLocalTimeStamp,
5764                                        // Leaving the time when this frame was
5765                                        // received from the capture device as
5766                                        // undefined for voice for now.
5767                                        -1,
5768                                        (const WebRtc_UWord8*) payloadData,
5769                                        payloadSize) != 0)
5770    {
5771        _engineStatisticsPtr->SetLastError(
5772            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5773            "InsertExtraRTPPacket() failed to send extra RTP packet");
5774        return -1;
5775    }
5776
5777    return 0;
5778}
5779
5780WebRtc_UWord32
5781Channel::Demultiplex(const AudioFrame& audioFrame)
5782{
5783    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5784                 "Channel::Demultiplex()");
5785    _audioFrame = audioFrame;
5786    _audioFrame.id_ = _channelId;
5787    return 0;
5788}
5789
5790WebRtc_UWord32
5791Channel::PrepareEncodeAndSend(int mixingFrequency)
5792{
5793    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5794                 "Channel::PrepareEncodeAndSend()");
5795
5796    if (_audioFrame.samples_per_channel_ == 0)
5797    {
5798        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5799                     "Channel::PrepareEncodeAndSend() invalid audio frame");
5800        return -1;
5801    }
5802
5803    if (_inputFilePlaying)
5804    {
5805        MixOrReplaceAudioWithFile(mixingFrequency);
5806    }
5807
5808    if (_mute)
5809    {
5810        AudioFrameOperations::Mute(_audioFrame);
5811    }
5812
5813    if (_inputExternalMedia)
5814    {
5815        CriticalSectionScoped cs(&_callbackCritSect);
5816        const bool isStereo = (_audioFrame.num_channels_ == 2);
5817        if (_inputExternalMediaCallbackPtr)
5818        {
5819            _inputExternalMediaCallbackPtr->Process(
5820                _channelId,
5821                kRecordingPerChannel,
5822               (WebRtc_Word16*)_audioFrame.data_,
5823                _audioFrame.samples_per_channel_,
5824                _audioFrame.sample_rate_hz_,
5825                isStereo);
5826        }
5827    }
5828
5829    InsertInbandDtmfTone();
5830
5831    if (_includeAudioLevelIndication)
5832    {
5833        assert(_rtpAudioProc.get() != NULL);
5834
5835        // Check if settings need to be updated.
5836        if (_rtpAudioProc->sample_rate_hz() != _audioFrame.sample_rate_hz_)
5837        {
5838            if (_rtpAudioProc->set_sample_rate_hz(_audioFrame.sample_rate_hz_) !=
5839                AudioProcessing::kNoError)
5840            {
5841                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5842                             VoEId(_instanceId, _channelId),
5843                             "Error setting AudioProcessing sample rate");
5844                return -1;
5845            }
5846        }
5847
5848        if (_rtpAudioProc->num_input_channels() != _audioFrame.num_channels_)
5849        {
5850            if (_rtpAudioProc->set_num_channels(_audioFrame.num_channels_,
5851                                                _audioFrame.num_channels_)
5852                != AudioProcessing::kNoError)
5853            {
5854                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5855                             VoEId(_instanceId, _channelId),
5856                             "Error setting AudioProcessing channels");
5857                return -1;
5858            }
5859        }
5860
5861        // Performs level analysis only; does not affect the signal.
5862        _rtpAudioProc->ProcessStream(&_audioFrame);
5863    }
5864
5865    return 0;
5866}
5867
5868WebRtc_UWord32
5869Channel::EncodeAndSend()
5870{
5871    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5872                 "Channel::EncodeAndSend()");
5873
5874    assert(_audioFrame.num_channels_ <= 2);
5875    if (_audioFrame.samples_per_channel_ == 0)
5876    {
5877        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5878                     "Channel::EncodeAndSend() invalid audio frame");
5879        return -1;
5880    }
5881
5882    _audioFrame.id_ = _channelId;
5883
5884    // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
5885
5886    // The ACM resamples internally.
5887    _audioFrame.timestamp_ = _timeStamp;
5888    if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
5889    {
5890        WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
5891                     "Channel::EncodeAndSend() ACM encoding failed");
5892        return -1;
5893    }
5894
5895    _timeStamp += _audioFrame.samples_per_channel_;
5896
5897    // --- Encode if complete frame is ready
5898
5899    // This call will trigger AudioPacketizationCallback::SendData if encoding
5900    // is done and payload is ready for packetization and transmission.
5901    return _audioCodingModule.Process();
5902}
5903
5904int Channel::RegisterExternalMediaProcessing(
5905    ProcessingTypes type,
5906    VoEMediaProcess& processObject)
5907{
5908    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5909                 "Channel::RegisterExternalMediaProcessing()");
5910
5911    CriticalSectionScoped cs(&_callbackCritSect);
5912
5913    if (kPlaybackPerChannel == type)
5914    {
5915        if (_outputExternalMediaCallbackPtr)
5916        {
5917            _engineStatisticsPtr->SetLastError(
5918                VE_INVALID_OPERATION, kTraceError,
5919                "Channel::RegisterExternalMediaProcessing() "
5920                "output external media already enabled");
5921            return -1;
5922        }
5923        _outputExternalMediaCallbackPtr = &processObject;
5924        _outputExternalMedia = true;
5925    }
5926    else if (kRecordingPerChannel == type)
5927    {
5928        if (_inputExternalMediaCallbackPtr)
5929        {
5930            _engineStatisticsPtr->SetLastError(
5931                VE_INVALID_OPERATION, kTraceError,
5932                "Channel::RegisterExternalMediaProcessing() "
5933                "output external media already enabled");
5934            return -1;
5935        }
5936        _inputExternalMediaCallbackPtr = &processObject;
5937        _inputExternalMedia = true;
5938    }
5939    return 0;
5940}
5941
5942int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
5943{
5944    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5945                 "Channel::DeRegisterExternalMediaProcessing()");
5946
5947    CriticalSectionScoped cs(&_callbackCritSect);
5948
5949    if (kPlaybackPerChannel == type)
5950    {
5951        if (!_outputExternalMediaCallbackPtr)
5952        {
5953            _engineStatisticsPtr->SetLastError(
5954                VE_INVALID_OPERATION, kTraceWarning,
5955                "Channel::DeRegisterExternalMediaProcessing() "
5956                "output external media already disabled");
5957            return 0;
5958        }
5959        _outputExternalMedia = false;
5960        _outputExternalMediaCallbackPtr = NULL;
5961    }
5962    else if (kRecordingPerChannel == type)
5963    {
5964        if (!_inputExternalMediaCallbackPtr)
5965        {
5966            _engineStatisticsPtr->SetLastError(
5967                VE_INVALID_OPERATION, kTraceWarning,
5968                "Channel::DeRegisterExternalMediaProcessing() "
5969                "input external media already disabled");
5970            return 0;
5971        }
5972        _inputExternalMedia = false;
5973        _inputExternalMediaCallbackPtr = NULL;
5974    }
5975
5976    return 0;
5977}
5978
5979int
5980Channel::ResetRTCPStatistics()
5981{
5982    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5983                 "Channel::ResetRTCPStatistics()");
5984    WebRtc_UWord32 remoteSSRC(0);
5985    remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5986    return _rtpRtcpModule->ResetRTT(remoteSSRC);
5987}
5988
5989int
5990Channel::GetRoundTripTimeSummary(StatVal& delaysMs) const
5991{
5992    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5993                 "Channel::GetRoundTripTimeSummary()");
5994    // Override default module outputs for the case when RTCP is disabled.
5995    // This is done to ensure that we are backward compatible with the
5996    // VoiceEngine where we did not use RTP/RTCP module.
5997    if (!_rtpRtcpModule->RTCP())
5998    {
5999        delaysMs.min = -1;
6000        delaysMs.max = -1;
6001        delaysMs.average = -1;
6002        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6003                     "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
6004                     " valid RTT measurements cannot be retrieved");
6005        return 0;
6006    }
6007
6008    WebRtc_UWord32 remoteSSRC;
6009    WebRtc_UWord16 RTT;
6010    WebRtc_UWord16 avgRTT;
6011    WebRtc_UWord16 maxRTT;
6012    WebRtc_UWord16 minRTT;
6013    // The remote SSRC will be zero if no RTP packet has been received.
6014    remoteSSRC = _rtpRtcpModule->RemoteSSRC();
6015    if (remoteSSRC == 0)
6016    {
6017        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6018                     "Channel::GetRoundTripTimeSummary() unable to measure RTT"
6019                     " since no RTP packet has been received yet");
6020    }
6021
6022    // Retrieve RTT statistics from the RTP/RTCP module for the specified
6023    // channel and SSRC. The SSRC is required to parse out the correct source
6024    // in conference scenarios.
6025    if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
6026    {
6027        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6028                     "GetRoundTripTimeSummary unable to retrieve RTT values"
6029                     " from the RTCP layer");
6030        delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
6031    }
6032    else
6033    {
6034        delaysMs.min = minRTT;
6035        delaysMs.max = maxRTT;
6036        delaysMs.average = avgRTT;
6037    }
6038    return 0;
6039}
6040
6041int
6042Channel::GetNetworkStatistics(NetworkStatistics& stats)
6043{
6044    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6045                 "Channel::GetNetworkStatistics()");
6046    return _audioCodingModule.NetworkStatistics(
6047        (ACMNetworkStatistics &)stats);
6048}
6049
6050int
6051Channel::GetDelayEstimate(int& delayMs) const
6052{
6053    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6054                 "Channel::GetDelayEstimate()");
6055    delayMs = (_averageDelayMs + 5) / 10 + _recPacketDelayMs;
6056    return 0;
6057}
6058
6059int
6060Channel::SetMinimumPlayoutDelay(int delayMs)
6061{
6062    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6063                 "Channel::SetMinimumPlayoutDelay()");
6064    if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
6065        (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
6066    {
6067        _engineStatisticsPtr->SetLastError(
6068            VE_INVALID_ARGUMENT, kTraceError,
6069            "SetMinimumPlayoutDelay() invalid min delay");
6070        return -1;
6071    }
6072    if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
6073    {
6074        _engineStatisticsPtr->SetLastError(
6075            VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6076            "SetMinimumPlayoutDelay() failed to set min playout delay");
6077        return -1;
6078    }
6079    return 0;
6080}
6081
6082int
6083Channel::GetPlayoutTimestamp(unsigned int& timestamp)
6084{
6085    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6086                 "Channel::GetPlayoutTimestamp()");
6087    WebRtc_UWord32 playoutTimestamp(0);
6088    if (GetPlayoutTimeStamp(playoutTimestamp) != 0)
6089    {
6090        _engineStatisticsPtr->SetLastError(
6091            VE_CANNOT_RETRIEVE_VALUE, kTraceError,
6092            "GetPlayoutTimestamp() failed to retrieve timestamp");
6093        return -1;
6094    }
6095    timestamp = playoutTimestamp;
6096    WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
6097                 VoEId(_instanceId,_channelId),
6098                 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
6099    return 0;
6100}
6101
6102int
6103Channel::SetInitTimestamp(unsigned int timestamp)
6104{
6105    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6106               "Channel::SetInitTimestamp()");
6107    if (_sending)
6108    {
6109        _engineStatisticsPtr->SetLastError(
6110            VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
6111        return -1;
6112    }
6113    if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
6114    {
6115        _engineStatisticsPtr->SetLastError(
6116            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6117            "SetInitTimestamp() failed to set timestamp");
6118        return -1;
6119    }
6120    return 0;
6121}
6122
6123int
6124Channel::SetInitSequenceNumber(short sequenceNumber)
6125{
6126    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6127                 "Channel::SetInitSequenceNumber()");
6128    if (_sending)
6129    {
6130        _engineStatisticsPtr->SetLastError(
6131            VE_SENDING, kTraceError,
6132            "SetInitSequenceNumber() already sending");
6133        return -1;
6134    }
6135    if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
6136    {
6137        _engineStatisticsPtr->SetLastError(
6138            VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6139            "SetInitSequenceNumber() failed to set sequence number");
6140        return -1;
6141    }
6142    return 0;
6143}
6144
6145int
6146Channel::GetRtpRtcp(RtpRtcp* &rtpRtcpModule) const
6147{
6148    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6149                 "Channel::GetRtpRtcp()");
6150    rtpRtcpModule = _rtpRtcpModule.get();
6151    return 0;
6152}
6153
6154// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
6155// a shared helper.
6156WebRtc_Word32
6157Channel::MixOrReplaceAudioWithFile(const int mixingFrequency)
6158{
6159    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
6160    int fileSamples(0);
6161
6162    {
6163        CriticalSectionScoped cs(&_fileCritSect);
6164
6165        if (_inputFilePlayerPtr == NULL)
6166        {
6167            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6168                         VoEId(_instanceId, _channelId),
6169                         "Channel::MixOrReplaceAudioWithFile() fileplayer"
6170                             " doesnt exist");
6171            return -1;
6172        }
6173
6174        if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
6175                                                      fileSamples,
6176                                                      mixingFrequency) == -1)
6177        {
6178            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6179                         VoEId(_instanceId, _channelId),
6180                         "Channel::MixOrReplaceAudioWithFile() file mixing "
6181                         "failed");
6182            return -1;
6183        }
6184        if (fileSamples == 0)
6185        {
6186            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6187                         VoEId(_instanceId, _channelId),
6188                         "Channel::MixOrReplaceAudioWithFile() file is ended");
6189            return 0;
6190        }
6191    }
6192
6193    assert(_audioFrame.samples_per_channel_ == fileSamples);
6194
6195    if (_mixFileWithMicrophone)
6196    {
6197        // Currently file stream is always mono.
6198        // TODO(xians): Change the code when FilePlayer supports real stereo.
6199        Utility::MixWithSat(_audioFrame.data_,
6200                            _audioFrame.num_channels_,
6201                            fileBuffer.get(),
6202                            1,
6203                            fileSamples);
6204    }
6205    else
6206    {
6207        // Replace ACM audio with file.
6208        // Currently file stream is always mono.
6209        // TODO(xians): Change the code when FilePlayer supports real stereo.
6210        _audioFrame.UpdateFrame(_channelId,
6211                                -1,
6212                                fileBuffer.get(),
6213                                fileSamples,
6214                                mixingFrequency,
6215                                AudioFrame::kNormalSpeech,
6216                                AudioFrame::kVadUnknown,
6217                                1);
6218
6219    }
6220    return 0;
6221}
6222
6223WebRtc_Word32
6224Channel::MixAudioWithFile(AudioFrame& audioFrame,
6225                          const int mixingFrequency)
6226{
6227    assert(mixingFrequency <= 32000);
6228
6229    scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
6230    int fileSamples(0);
6231
6232    {
6233        CriticalSectionScoped cs(&_fileCritSect);
6234
6235        if (_outputFilePlayerPtr == NULL)
6236        {
6237            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6238                         VoEId(_instanceId, _channelId),
6239                         "Channel::MixAudioWithFile() file mixing failed");
6240            return -1;
6241        }
6242
6243        // We should get the frequency we ask for.
6244        if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
6245                                                       fileSamples,
6246                                                       mixingFrequency) == -1)
6247        {
6248            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6249                         VoEId(_instanceId, _channelId),
6250                         "Channel::MixAudioWithFile() file mixing failed");
6251            return -1;
6252        }
6253    }
6254
6255    if (audioFrame.samples_per_channel_ == fileSamples)
6256    {
6257        // Currently file stream is always mono.
6258        // TODO(xians): Change the code when FilePlayer supports real stereo.
6259        Utility::MixWithSat(audioFrame.data_,
6260                            audioFrame.num_channels_,
6261                            fileBuffer.get(),
6262                            1,
6263                            fileSamples);
6264    }
6265    else
6266    {
6267        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6268            "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
6269            "fileSamples(%d)",
6270            audioFrame.samples_per_channel_, fileSamples);
6271        return -1;
6272    }
6273
6274    return 0;
6275}
6276
6277int
6278Channel::InsertInbandDtmfTone()
6279{
6280    // Check if we should start a new tone.
6281    if (_inbandDtmfQueue.PendingDtmf() &&
6282        !_inbandDtmfGenerator.IsAddingTone() &&
6283        _inbandDtmfGenerator.DelaySinceLastTone() >
6284        kMinTelephoneEventSeparationMs)
6285    {
6286        WebRtc_Word8 eventCode(0);
6287        WebRtc_UWord16 lengthMs(0);
6288        WebRtc_UWord8 attenuationDb(0);
6289
6290        eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
6291        _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
6292        if (_playInbandDtmfEvent)
6293        {
6294            // Add tone to output mixer using a reduced length to minimize
6295            // risk of echo.
6296            _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
6297                                          attenuationDb);
6298        }
6299    }
6300
6301    if (_inbandDtmfGenerator.IsAddingTone())
6302    {
6303        WebRtc_UWord16 frequency(0);
6304        _inbandDtmfGenerator.GetSampleRate(frequency);
6305
6306        if (frequency != _audioFrame.sample_rate_hz_)
6307        {
6308            // Update sample rate of Dtmf tone since the mixing frequency
6309            // has changed.
6310            _inbandDtmfGenerator.SetSampleRate(
6311                (WebRtc_UWord16) (_audioFrame.sample_rate_hz_));
6312            // Reset the tone to be added taking the new sample rate into
6313            // account.
6314            _inbandDtmfGenerator.ResetTone();
6315        }
6316
6317        WebRtc_Word16 toneBuffer[320];
6318        WebRtc_UWord16 toneSamples(0);
6319        // Get 10ms tone segment and set time since last tone to zero
6320        if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
6321        {
6322            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6323                       VoEId(_instanceId, _channelId),
6324                       "Channel::EncodeAndSend() inserting Dtmf failed");
6325            return -1;
6326        }
6327
6328        // Replace mixed audio with DTMF tone.
6329        for (int sample = 0;
6330            sample < _audioFrame.samples_per_channel_;
6331            sample++)
6332        {
6333            for (int channel = 0;
6334                channel < _audioFrame.num_channels_;
6335                channel++)
6336            {
6337                _audioFrame.data_[sample * _audioFrame.num_channels_ + channel] =
6338                        toneBuffer[sample];
6339            }
6340        }
6341
6342        assert(_audioFrame.samples_per_channel_ == toneSamples);
6343    } else
6344    {
6345        // Add 10ms to "delay-since-last-tone" counter
6346        _inbandDtmfGenerator.UpdateDelaySinceLastTone();
6347    }
6348    return 0;
6349}
6350
6351WebRtc_Word32
6352Channel::GetPlayoutTimeStamp(WebRtc_UWord32& playoutTimestamp)
6353{
6354    WebRtc_UWord32 timestamp(0);
6355    CodecInst currRecCodec;
6356
6357    if (_audioCodingModule.PlayoutTimestamp(timestamp) == -1)
6358    {
6359        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6360                     "Channel::GetPlayoutTimeStamp() failed to read playout"
6361                     " timestamp from the ACM");
6362        return -1;
6363    }
6364
6365    WebRtc_UWord16 delayMS(0);
6366    if (_audioDeviceModulePtr->PlayoutDelay(&delayMS) == -1)
6367    {
6368        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6369                     "Channel::GetPlayoutTimeStamp() failed to read playout"
6370                     " delay from the ADM");
6371        return -1;
6372    }
6373
6374    WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
6375    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6376      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6377        playoutFrequency = 8000;
6378      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6379        playoutFrequency = 48000;
6380      }
6381    }
6382    timestamp -= (delayMS * (playoutFrequency/1000));
6383
6384    playoutTimestamp = timestamp;
6385
6386    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6387                 "Channel::GetPlayoutTimeStamp() => playoutTimestamp = %lu",
6388                 playoutTimestamp);
6389    return 0;
6390}
6391
6392void
6393Channel::ResetDeadOrAliveCounters()
6394{
6395    _countDeadDetections = 0;
6396    _countAliveDetections = 0;
6397}
6398
6399void
6400Channel::UpdateDeadOrAliveCounters(bool alive)
6401{
6402    if (alive)
6403        _countAliveDetections++;
6404    else
6405        _countDeadDetections++;
6406}
6407
6408int
6409Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
6410{
6411    bool enabled;
6412    WebRtc_UWord8 timeSec;
6413
6414    _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, timeSec);
6415    if (!enabled)
6416        return (-1);
6417
6418    countDead = static_cast<int> (_countDeadDetections);
6419    countAlive = static_cast<int> (_countAliveDetections);
6420    return 0;
6421}
6422
6423WebRtc_Word32
6424Channel::SendPacketRaw(const void *data, int len, bool RTCP)
6425{
6426    if (_transportPtr == NULL)
6427    {
6428        return -1;
6429    }
6430    if (!RTCP)
6431    {
6432        return _transportPtr->SendPacket(_channelId, data, len);
6433    }
6434    else
6435    {
6436        return _transportPtr->SendRTCPPacket(_channelId, data, len);
6437    }
6438}
6439
6440WebRtc_Word32
6441Channel::UpdatePacketDelay(const WebRtc_UWord32 timestamp,
6442                           const WebRtc_UWord16 sequenceNumber)
6443{
6444    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6445                 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
6446                 timestamp, sequenceNumber);
6447
6448    WebRtc_Word32 rtpReceiveFrequency(0);
6449
6450    // Get frequency of last received payload
6451    rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
6452
6453    CodecInst currRecCodec;
6454    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6455      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6456        // Even though the actual sampling rate for G.722 audio is
6457        // 16,000 Hz, the RTP clock rate for the G722 payload format is
6458        // 8,000 Hz because that value was erroneously assigned in
6459        // RFC 1890 and must remain unchanged for backward compatibility.
6460        rtpReceiveFrequency = 8000;
6461      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6462        // We are resampling Opus internally to 32,000 Hz until all our
6463        // DSP routines can operate at 48,000 Hz, but the RTP clock
6464        // rate for the Opus payload format is standardized to 48,000 Hz,
6465        // because that is the maximum supported decoding sampling rate.
6466        rtpReceiveFrequency = 48000;
6467      }
6468    }
6469
6470    const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
6471    WebRtc_UWord32 timeStampDiffMs(0);
6472
6473    if (timeStampDiff > 0)
6474    {
6475        switch (rtpReceiveFrequency) {
6476          case 8000:
6477            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 3);
6478            break;
6479          case 16000:
6480            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 4);
6481            break;
6482          case 32000:
6483            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 5);
6484            break;
6485          case 48000:
6486            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff / 48);
6487            break;
6488          default:
6489            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6490                         VoEId(_instanceId, _channelId),
6491                         "Channel::UpdatePacketDelay() invalid sample rate");
6492            timeStampDiffMs = 0;
6493            return -1;
6494        }
6495        if (timeStampDiffMs > 5000)
6496        {
6497            timeStampDiffMs = 0;
6498        }
6499
6500        if (_averageDelayMs == 0)
6501        {
6502            _averageDelayMs = timeStampDiffMs;
6503        }
6504        else
6505        {
6506            // Filter average delay value using exponential filter (alpha is
6507            // 7/8). We derive 10*_averageDelayMs here (reduces risk of
6508            // rounding error) and compensate for it in GetDelayEstimate()
6509            // later. Adding 4/8 results in correct rounding.
6510            _averageDelayMs = ((_averageDelayMs*7 + 10*timeStampDiffMs + 4)>>3);
6511        }
6512
6513        if (sequenceNumber - _previousSequenceNumber == 1)
6514        {
6515            WebRtc_UWord16 packetDelayMs = 0;
6516            switch (rtpReceiveFrequency) {
6517              case 8000:
6518                packetDelayMs = static_cast<WebRtc_UWord16>(
6519                    (timestamp - _previousTimestamp) >> 3);
6520                break;
6521              case 16000:
6522                packetDelayMs = static_cast<WebRtc_UWord16>(
6523                    (timestamp - _previousTimestamp) >> 4);
6524                break;
6525              case 32000:
6526                packetDelayMs = static_cast<WebRtc_UWord16>(
6527                    (timestamp - _previousTimestamp) >> 5);
6528                break;
6529              case 48000:
6530                packetDelayMs = static_cast<WebRtc_UWord16>(
6531                    (timestamp - _previousTimestamp) / 48);
6532                break;
6533            }
6534
6535            if (packetDelayMs >= 10 && packetDelayMs <= 60)
6536                _recPacketDelayMs = packetDelayMs;
6537        }
6538    }
6539
6540    _previousSequenceNumber = sequenceNumber;
6541    _previousTimestamp = timestamp;
6542
6543    return 0;
6544}
6545
6546void
6547Channel::RegisterReceiveCodecsToRTPModule()
6548{
6549    WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6550                 "Channel::RegisterReceiveCodecsToRTPModule()");
6551
6552
6553    CodecInst codec;
6554    const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
6555
6556    for (int idx = 0; idx < nSupportedCodecs; idx++)
6557    {
6558        // Open up the RTP/RTCP receiver for all supported codecs
6559        if ((_audioCodingModule.Codec(idx, codec) == -1) ||
6560            (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
6561        {
6562            WEBRTC_TRACE(
6563                         kTraceWarning,
6564                         kTraceVoice,
6565                         VoEId(_instanceId, _channelId),
6566                         "Channel::RegisterReceiveCodecsToRTPModule() unable"
6567                         " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
6568                         codec.plname, codec.pltype, codec.plfreq,
6569                         codec.channels, codec.rate);
6570        }
6571        else
6572        {
6573            WEBRTC_TRACE(
6574                         kTraceInfo,
6575                         kTraceVoice,
6576                         VoEId(_instanceId, _channelId),
6577                         "Channel::RegisterReceiveCodecsToRTPModule() %s "
6578                         "(%d/%d/%d/%d) has been added to the RTP/RTCP "
6579                         "receiver",
6580                         codec.plname, codec.pltype, codec.plfreq,
6581                         codec.channels, codec.rate);
6582        }
6583    }
6584}
6585
6586int Channel::ApmProcessRx(AudioFrame& frame) {
6587  AudioProcessing* audioproc = _rxAudioProcessingModulePtr;
6588  // Register the (possibly new) frame parameters.
6589  if (audioproc->set_sample_rate_hz(frame.sample_rate_hz_) != 0) {
6590    LOG_FERR1(LS_WARNING, set_sample_rate_hz, frame.sample_rate_hz_);
6591  }
6592  if (audioproc->set_num_channels(frame.num_channels_,
6593                                  frame.num_channels_) != 0) {
6594    LOG_FERR1(LS_WARNING, set_num_channels, frame.num_channels_);
6595  }
6596  if (audioproc->ProcessStream(&frame) != 0) {
6597    LOG_FERR0(LS_WARNING, ProcessStream);
6598  }
6599  return 0;
6600}
6601
6602int Channel::SetSecondarySendCodec(const CodecInst& codec,
6603                                   int red_payload_type) {
6604  if (SetRedPayloadType(red_payload_type) < 0) {
6605    _engineStatisticsPtr->SetLastError(
6606        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6607        "SetSecondarySendCodec() Failed to register RED ACM");
6608    return -1;
6609  }
6610  if (_audioCodingModule.RegisterSecondarySendCodec(codec) < 0) {
6611    _engineStatisticsPtr->SetLastError(
6612        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6613        "SetSecondarySendCodec() Failed to register secondary send codec in "
6614        "ACM");
6615    return -1;
6616  }
6617
6618  return 0;
6619}
6620
6621void Channel::RemoveSecondarySendCodec() {
6622  _audioCodingModule.UnregisterSecondarySendCodec();
6623}
6624
6625int Channel::GetSecondarySendCodec(CodecInst* codec) {
6626  if (_audioCodingModule.SecondarySendCodec(codec) < 0) {
6627    _engineStatisticsPtr->SetLastError(
6628        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6629        "GetSecondarySendCodec() Failed to get secondary sent codec from ACM");
6630    return -1;
6631  }
6632  return 0;
6633}
6634
6635int Channel::SetRedPayloadType(int red_payload_type) {
6636  if (red_payload_type < 0) {
6637    _engineStatisticsPtr->SetLastError(
6638        VE_PLTYPE_ERROR, kTraceError,
6639        "SetRedPayloadType() invalid RED paylaod type");
6640    return -1;
6641  }
6642
6643  CodecInst codec;
6644  bool found_red = false;
6645
6646  // Get default RED settings from the ACM database
6647  const int num_codecs = AudioCodingModule::NumberOfCodecs();
6648  for (int idx = 0; idx < num_codecs; idx++) {
6649    _audioCodingModule.Codec(idx, codec);
6650    if (!STR_CASE_CMP(codec.plname, "RED")) {
6651      found_red = true;
6652      break;
6653    }
6654  }
6655
6656  if (!found_red) {
6657    _engineStatisticsPtr->SetLastError(
6658        VE_CODEC_ERROR, kTraceError,
6659        "SetRedPayloadType() RED is not supported");
6660    return -1;
6661  }
6662
6663  codec.pltype = red_payload_type;
6664  if (_audioCodingModule.RegisterSendCodec(codec) < 0) {
6665    _engineStatisticsPtr->SetLastError(
6666        VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6667        "SetRedPayloadType() RED registration in ACM module failed");
6668    return -1;
6669  }
6670
6671  if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
6672    _engineStatisticsPtr->SetLastError(
6673        VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6674        "SetRedPayloadType() RED registration in RTP/RTCP module failed");
6675    return -1;
6676  }
6677  return 0;
6678}
6679
6680} // namespace voe
6681} // namespace webrtc
6682