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