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