blob: 015518c28a4a7a72bce17ca2759242337bd6986f [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
802 if (!_playing)
803 {
804 // Avoid inserting into NetEQ when we are not playing. Count the
805 // packet as discarded.
806 WEBRTC_TRACE(kTraceStream, kTraceVoice,
807 VoEId(_instanceId, _channelId),
808 "received packet is discarded since playing is not"
809 " activated");
810 _numberOfDiscardedPackets++;
811 return 0;
812 }
813
814 // Push the incoming payload (parsed and ready for decoding) into the ACM
tina.legrand@webrtc.org16b6b902012-04-12 11:02:38 +0000815 if (_audioCodingModule.IncomingPacket(payloadData,
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 payloadSize,
817 *rtpHeader) != 0)
818 {
819 _engineStatisticsPtr->SetLastError(
820 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
821 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
822 return -1;
823 }
824
825 // Update the packet delay
826 UpdatePacketDelay(rtpHeader->header.timestamp,
827 rtpHeader->header.sequenceNumber);
828
829 return 0;
830}
831
832WebRtc_Word32 Channel::GetAudioFrame(const WebRtc_Word32 id,
833 AudioFrame& audioFrame)
834{
835 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
836 "Channel::GetAudioFrame(id=%d)", id);
837
838 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000839 if (_audioCodingModule.PlayoutData10Ms(audioFrame.sample_rate_hz_,
andrew@webrtc.org7859e102012-01-13 00:30:11 +0000840 audioFrame) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000841 {
842 WEBRTC_TRACE(kTraceError, kTraceVoice,
843 VoEId(_instanceId,_channelId),
844 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
andrew@webrtc.org7859e102012-01-13 00:30:11 +0000845 // In all likelihood, the audio in this frame is garbage. We return an
846 // error so that the audio mixer module doesn't add it to the mix. As
847 // a result, it won't be played out and the actions skipped here are
848 // irrelevant.
849 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000850 }
851
852 if (_RxVadDetection)
853 {
854 UpdateRxVadDetection(audioFrame);
855 }
856
857 // Convert module ID to internal VoE channel ID
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000858 audioFrame.id_ = VoEChannelId(audioFrame.id_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000859 // Store speech type for dead-or-alive detection
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000860 _outputSpeechType = audioFrame.speech_type_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000861
862 // Perform far-end AudioProcessing module processing on the received signal
863 if (_rxApmIsEnabled)
864 {
865 ApmProcessRx(audioFrame);
866 }
867
868 // Output volume scaling
869 if (_outputGain < 0.99f || _outputGain > 1.01f)
870 {
871 AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
872 }
873
874 // Scale left and/or right channel(s) if stereo and master balance is
875 // active
876
877 if (_panLeft != 1.0f || _panRight != 1.0f)
878 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000879 if (audioFrame.num_channels_ == 1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000880 {
881 // Emulate stereo mode since panning is active.
882 // The mono signal is copied to both left and right channels here.
andrew@webrtc.org4ecea3e2012-06-27 03:25:31 +0000883 AudioFrameOperations::MonoToStereo(&audioFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000884 }
885 // For true stereo mode (when we are receiving a stereo signal), no
886 // action is needed.
887
888 // Do the panning operation (the audio frame contains stereo at this
889 // stage)
890 AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
891 }
892
893 // Mix decoded PCM output with file if file mixing is enabled
894 if (_outputFilePlaying)
895 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000896 MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000897 }
898
899 // Place channel in on-hold state (~muted) if on-hold is activated
900 if (_outputIsOnHold)
901 {
902 AudioFrameOperations::Mute(audioFrame);
903 }
904
905 // External media
906 if (_outputExternalMedia)
907 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000908 CriticalSectionScoped cs(&_callbackCritSect);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000909 const bool isStereo = (audioFrame.num_channels_ == 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000910 if (_outputExternalMediaCallbackPtr)
911 {
912 _outputExternalMediaCallbackPtr->Process(
913 _channelId,
914 kPlaybackPerChannel,
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000915 (WebRtc_Word16*)audioFrame.data_,
916 audioFrame.samples_per_channel_,
917 audioFrame.sample_rate_hz_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000918 isStereo);
919 }
920 }
921
922 // Record playout if enabled
923 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000924 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000925
926 if (_outputFileRecording && _outputFileRecorderPtr)
927 {
niklas.enbom@webrtc.org5398d952012-03-26 08:11:25 +0000928 _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000929 }
930 }
931
932 // Measure audio level (0-9)
933 _outputAudioLevel.ComputeLevel(audioFrame);
934
935 return 0;
936}
937
938WebRtc_Word32
939Channel::NeededFrequency(const WebRtc_Word32 id)
940{
941 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
942 "Channel::NeededFrequency(id=%d)", id);
943
944 int highestNeeded = 0;
945
946 // Determine highest needed receive frequency
947 WebRtc_Word32 receiveFrequency = _audioCodingModule.ReceiveFrequency();
948
949 // Return the bigger of playout and receive frequency in the ACM.
950 if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
951 {
952 highestNeeded = _audioCodingModule.PlayoutFrequency();
953 }
954 else
955 {
956 highestNeeded = receiveFrequency;
957 }
958
959 // Special case, if we're playing a file on the playout side
960 // we take that frequency into consideration as well
961 // This is not needed on sending side, since the codec will
962 // limit the spectrum anyway.
963 if (_outputFilePlaying)
964 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000965 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000966 if (_outputFilePlayerPtr && _outputFilePlaying)
967 {
968 if(_outputFilePlayerPtr->Frequency()>highestNeeded)
969 {
970 highestNeeded=_outputFilePlayerPtr->Frequency();
971 }
972 }
973 }
974
975 return(highestNeeded);
976}
977
niklase@google.com470e71d2011-07-07 08:21:25 +0000978WebRtc_Word32
979Channel::CreateChannel(Channel*& channel,
980 const WebRtc_Word32 channelId,
981 const WebRtc_UWord32 instanceId)
982{
983 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
984 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
985 channelId, instanceId);
986
987 channel = new Channel(channelId, instanceId);
988 if (channel == NULL)
989 {
990 WEBRTC_TRACE(kTraceMemory, kTraceVoice,
991 VoEId(instanceId,channelId),
992 "Channel::CreateChannel() unable to allocate memory for"
993 " channel");
994 return -1;
995 }
996 return 0;
997}
998
999void
1000Channel::PlayNotification(const WebRtc_Word32 id,
1001 const WebRtc_UWord32 durationMs)
1002{
1003 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1004 "Channel::PlayNotification(id=%d, durationMs=%d)",
1005 id, durationMs);
1006
1007 // Not implement yet
1008}
1009
1010void
1011Channel::RecordNotification(const WebRtc_Word32 id,
1012 const WebRtc_UWord32 durationMs)
1013{
1014 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1015 "Channel::RecordNotification(id=%d, durationMs=%d)",
1016 id, durationMs);
1017
1018 // Not implement yet
1019}
1020
1021void
1022Channel::PlayFileEnded(const WebRtc_Word32 id)
1023{
1024 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1025 "Channel::PlayFileEnded(id=%d)", id);
1026
1027 if (id == _inputFilePlayerId)
1028 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001029 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001030
1031 _inputFilePlaying = false;
1032 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1033 VoEId(_instanceId,_channelId),
1034 "Channel::PlayFileEnded() => input file player module is"
1035 " shutdown");
1036 }
1037 else if (id == _outputFilePlayerId)
1038 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001039 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001040
1041 _outputFilePlaying = false;
1042 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1043 VoEId(_instanceId,_channelId),
1044 "Channel::PlayFileEnded() => output file player module is"
1045 " shutdown");
1046 }
1047}
1048
1049void
1050Channel::RecordFileEnded(const WebRtc_Word32 id)
1051{
1052 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1053 "Channel::RecordFileEnded(id=%d)", id);
1054
1055 assert(id == _outputFileRecorderId);
1056
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001057 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001058
1059 _outputFileRecording = false;
1060 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1061 VoEId(_instanceId,_channelId),
1062 "Channel::RecordFileEnded() => output file recorder module is"
1063 " shutdown");
1064}
1065
1066Channel::Channel(const WebRtc_Word32 channelId,
1067 const WebRtc_UWord32 instanceId) :
1068 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1069 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001070 _instanceId(instanceId),
xians@google.com22963ab2011-08-03 12:40:23 +00001071 _channelId(channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001072 _audioCodingModule(*AudioCodingModule::Create(
xians@google.com22963ab2011-08-03 12:40:23 +00001073 VoEModuleId(instanceId, channelId))),
niklase@google.com470e71d2011-07-07 08:21:25 +00001074#ifndef WEBRTC_EXTERNAL_TRANSPORT
perkj@webrtc.org68f21682011-11-30 18:11:23 +00001075 _numSocketThreads(KNumSocketThreads),
xians@google.com22963ab2011-08-03 12:40:23 +00001076 _socketTransportModule(*UdpTransport::Create(
perkj@webrtc.org68f21682011-11-30 18:11:23 +00001077 VoEModuleId(instanceId, channelId), _numSocketThreads)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001078#endif
1079#ifdef WEBRTC_SRTP
1080 _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId,
1081 channelId))),
1082#endif
1083 _rtpDumpIn(*RtpDump::CreateRtpDump()),
1084 _rtpDumpOut(*RtpDump::CreateRtpDump()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001085 _outputAudioLevel(),
niklase@google.com470e71d2011-07-07 08:21:25 +00001086 _externalTransport(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001087 _inputFilePlayerPtr(NULL),
1088 _outputFilePlayerPtr(NULL),
1089 _outputFileRecorderPtr(NULL),
1090 // Avoid conflict with other channels by adding 1024 - 1026,
1091 // won't use as much as 1024 channels.
1092 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
1093 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
1094 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
1095 _inputFilePlaying(false),
1096 _outputFilePlaying(false),
1097 _outputFileRecording(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001098 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
1099 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001100 _inputExternalMedia(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001101 _outputExternalMedia(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001102 _inputExternalMediaCallbackPtr(NULL),
1103 _outputExternalMediaCallbackPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001104 _encryptionRTPBufferPtr(NULL),
1105 _decryptionRTPBufferPtr(NULL),
1106 _encryptionRTCPBufferPtr(NULL),
1107 _decryptionRTCPBufferPtr(NULL),
1108 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
1109 _sendTelephoneEventPayloadType(106),
1110 _playoutTimeStampRTP(0),
1111 _playoutTimeStampRTCP(0),
1112 _numberOfDiscardedPackets(0),
1113 _engineStatisticsPtr(NULL),
henrika@webrtc.org2919e952012-01-31 08:45:03 +00001114 _outputMixerPtr(NULL),
1115 _transmitMixerPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001116 _moduleProcessThreadPtr(NULL),
1117 _audioDeviceModulePtr(NULL),
1118 _voiceEngineObserverPtr(NULL),
1119 _callbackCritSectPtr(NULL),
1120 _transportPtr(NULL),
1121 _encryptionPtr(NULL),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001122 _rtpAudioProc(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001123 _rxAudioProcessingModulePtr(NULL),
1124#ifdef WEBRTC_DTMF_DETECTION
1125 _telephoneEventDetectionPtr(NULL),
1126#endif
1127 _rxVadObserverPtr(NULL),
1128 _oldVadDecision(-1),
1129 _sendFrameType(0),
niklase@google.com470e71d2011-07-07 08:21:25 +00001130 _rtpObserverPtr(NULL),
1131 _rtcpObserverPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001132 _outputIsOnHold(false),
1133 _externalPlayout(false),
1134 _inputIsOnHold(false),
1135 _playing(false),
1136 _sending(false),
1137 _receiving(false),
1138 _mixFileWithMicrophone(false),
1139 _rtpObserver(false),
1140 _rtcpObserver(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001141 _mute(false),
1142 _panLeft(1.0f),
1143 _panRight(1.0f),
1144 _outputGain(1.0f),
xians@google.com22963ab2011-08-03 12:40:23 +00001145 _encrypting(false),
1146 _decrypting(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001147 _playOutbandDtmfEvent(false),
1148 _playInbandDtmfEvent(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001149 _inbandTelephoneEventDetection(false),
1150 _outOfBandTelephoneEventDetecion(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001151 _extraPayloadType(0),
1152 _insertExtraRTPPacket(false),
1153 _extraMarkerBit(false),
1154 _lastLocalTimeStamp(0),
1155 _lastPayloadType(0),
xians@google.com22963ab2011-08-03 12:40:23 +00001156 _includeAudioLevelIndication(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001157 _rtpPacketTimedOut(false),
1158 _rtpPacketTimeOutIsEnabled(false),
1159 _rtpTimeOutSeconds(0),
1160 _connectionObserver(false),
1161 _connectionObserverPtr(NULL),
1162 _countAliveDetections(0),
1163 _countDeadDetections(0),
1164 _outputSpeechType(AudioFrame::kNormalSpeech),
1165 _averageDelayMs(0),
1166 _previousSequenceNumber(0),
1167 _previousTimestamp(0),
1168 _recPacketDelayMs(20),
1169 _RxVadDetection(false),
1170 _rxApmIsEnabled(false),
1171 _rxAgcIsEnabled(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001172 _rxNsIsEnabled(false)
niklase@google.com470e71d2011-07-07 08:21:25 +00001173{
1174 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1175 "Channel::Channel() - ctor");
1176 _inbandDtmfQueue.ResetDtmf();
1177 _inbandDtmfGenerator.Init();
1178 _outputAudioLevel.Clear();
1179
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001180 RtpRtcp::Configuration configuration;
1181 configuration.id = VoEModuleId(instanceId, channelId);
1182 configuration.audio = true;
1183 configuration.incoming_data = this;
1184 configuration.incoming_messages = this;
1185 configuration.outgoing_transport = this;
1186 configuration.rtcp_feedback = this;
1187 configuration.audio_messages = this;
1188
1189 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
1190
niklase@google.com470e71d2011-07-07 08:21:25 +00001191 // Create far end AudioProcessing Module
1192 _rxAudioProcessingModulePtr = AudioProcessing::Create(
1193 VoEModuleId(instanceId, channelId));
1194}
1195
1196Channel::~Channel()
1197{
1198 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1199 "Channel::~Channel() - dtor");
1200
1201 if (_outputExternalMedia)
1202 {
1203 DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1204 }
1205 if (_inputExternalMedia)
1206 {
1207 DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1208 }
1209 StopSend();
1210#ifndef WEBRTC_EXTERNAL_TRANSPORT
1211 StopReceiving();
1212 // De-register packet callback to ensure we're not in a callback when
1213 // deleting channel state, avoids race condition and deadlock.
1214 if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0)
1215 != 0)
1216 {
1217 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1218 VoEId(_instanceId, _channelId),
1219 "~Channel() failed to de-register receive callback");
1220 }
1221#endif
1222 StopPlayout();
1223
1224 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001225 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001226 if (_inputFilePlayerPtr)
1227 {
1228 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1229 _inputFilePlayerPtr->StopPlayingFile();
1230 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1231 _inputFilePlayerPtr = NULL;
1232 }
1233 if (_outputFilePlayerPtr)
1234 {
1235 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1236 _outputFilePlayerPtr->StopPlayingFile();
1237 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1238 _outputFilePlayerPtr = NULL;
1239 }
1240 if (_outputFileRecorderPtr)
1241 {
1242 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1243 _outputFileRecorderPtr->StopRecording();
1244 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1245 _outputFileRecorderPtr = NULL;
1246 }
1247 }
1248
1249 // The order to safely shutdown modules in a channel is:
1250 // 1. De-register callbacks in modules
1251 // 2. De-register modules in process thread
1252 // 3. Destroy modules
niklase@google.com470e71d2011-07-07 08:21:25 +00001253 if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1254 {
1255 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1256 VoEId(_instanceId,_channelId),
1257 "~Channel() failed to de-register transport callback"
1258 " (Audio coding module)");
1259 }
1260 if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1261 {
1262 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1263 VoEId(_instanceId,_channelId),
1264 "~Channel() failed to de-register VAD callback"
1265 " (Audio coding module)");
1266 }
1267#ifdef WEBRTC_DTMF_DETECTION
1268 if (_audioCodingModule.RegisterIncomingMessagesCallback(NULL) == -1)
1269 {
1270 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1271 VoEId(_instanceId,_channelId),
1272 "~Channel() failed to de-register incoming messages "
1273 "callback (Audio coding module)");
1274 }
1275#endif
1276 // De-register modules in process thread
1277#ifndef WEBRTC_EXTERNAL_TRANSPORT
1278 if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule)
1279 == -1)
1280 {
1281 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1282 VoEId(_instanceId,_channelId),
1283 "~Channel() failed to deregister socket module");
1284 }
1285#endif
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001286 if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00001287 {
1288 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1289 VoEId(_instanceId,_channelId),
1290 "~Channel() failed to deregister RTP/RTCP module");
1291 }
1292
1293 // Destroy modules
1294#ifndef WEBRTC_EXTERNAL_TRANSPORT
1295 UdpTransport::Destroy(
1296 &_socketTransportModule);
1297#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 AudioCodingModule::Destroy(&_audioCodingModule);
1299#ifdef WEBRTC_SRTP
1300 SrtpModule::DestroySrtpModule(&_srtpModule);
1301#endif
1302 if (_rxAudioProcessingModulePtr != NULL)
1303 {
1304 AudioProcessing::Destroy(_rxAudioProcessingModulePtr); // far end APM
1305 _rxAudioProcessingModulePtr = NULL;
1306 }
1307
1308 // End of modules shutdown
1309
1310 // Delete other objects
1311 RtpDump::DestroyRtpDump(&_rtpDumpIn);
1312 RtpDump::DestroyRtpDump(&_rtpDumpOut);
1313 delete [] _encryptionRTPBufferPtr;
1314 delete [] _decryptionRTPBufferPtr;
1315 delete [] _encryptionRTCPBufferPtr;
1316 delete [] _decryptionRTCPBufferPtr;
1317 delete &_callbackCritSect;
niklase@google.com470e71d2011-07-07 08:21:25 +00001318 delete &_fileCritSect;
1319}
1320
1321WebRtc_Word32
1322Channel::Init()
1323{
1324 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1325 "Channel::Init()");
1326
1327 // --- Initial sanity
1328
1329 if ((_engineStatisticsPtr == NULL) ||
1330 (_moduleProcessThreadPtr == NULL))
1331 {
1332 WEBRTC_TRACE(kTraceError, kTraceVoice,
1333 VoEId(_instanceId,_channelId),
1334 "Channel::Init() must call SetEngineInformation() first");
1335 return -1;
1336 }
1337
1338 // --- Add modules to process thread (for periodic schedulation)
1339
1340 const bool processThreadFail =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001341 ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001342#ifndef WEBRTC_EXTERNAL_TRANSPORT
1343 (_moduleProcessThreadPtr->RegisterModule(
1344 &_socketTransportModule) != 0));
1345#else
1346 false);
1347#endif
1348 if (processThreadFail)
1349 {
1350 _engineStatisticsPtr->SetLastError(
1351 VE_CANNOT_INIT_CHANNEL, kTraceError,
1352 "Channel::Init() modules not registered");
1353 return -1;
1354 }
pwestin@webrtc.orgc450a192012-01-04 15:00:12 +00001355 // --- ACM initialization
niklase@google.com470e71d2011-07-07 08:21:25 +00001356
1357 if ((_audioCodingModule.InitializeReceiver() == -1) ||
1358#ifdef WEBRTC_CODEC_AVT
1359 // out-of-band Dtmf tones are played out by default
1360 (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1361#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001362 (_audioCodingModule.InitializeSender() == -1))
1363 {
1364 _engineStatisticsPtr->SetLastError(
1365 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1366 "Channel::Init() unable to initialize the ACM - 1");
1367 return -1;
1368 }
1369
1370 // --- RTP/RTCP module initialization
1371
1372 // Ensure that RTCP is enabled by default for the created channel.
1373 // Note that, the module will keep generating RTCP until it is explicitly
1374 // disabled by the user.
1375 // After StopListen (when no sockets exists), RTCP packets will no longer
1376 // be transmitted since the Transport object will then be invalid.
1377
1378 const bool rtpRtcpFail =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001379 ((_rtpRtcpModule->SetTelephoneEventStatus(false, true, true) == -1) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001380 // RTCP is enabled by default
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001381 (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1));
niklase@google.com470e71d2011-07-07 08:21:25 +00001382 if (rtpRtcpFail)
1383 {
1384 _engineStatisticsPtr->SetLastError(
1385 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1386 "Channel::Init() RTP/RTCP module not initialized");
1387 return -1;
1388 }
1389
1390 // --- Register all permanent callbacks
niklase@google.com470e71d2011-07-07 08:21:25 +00001391 const bool fail =
niklase@google.com470e71d2011-07-07 08:21:25 +00001392 (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1393 (_audioCodingModule.RegisterVADCallback(this) == -1);
1394
1395 if (fail)
1396 {
1397 _engineStatisticsPtr->SetLastError(
1398 VE_CANNOT_INIT_CHANNEL, kTraceError,
1399 "Channel::Init() callbacks not registered");
1400 return -1;
1401 }
1402
1403 // --- Register all supported codecs to the receiving side of the
1404 // RTP/RTCP module
1405
1406 CodecInst codec;
1407 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1408
1409 for (int idx = 0; idx < nSupportedCodecs; idx++)
1410 {
1411 // Open up the RTP/RTCP receiver for all supported codecs
1412 if ((_audioCodingModule.Codec(idx, codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001413 (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001414 {
1415 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1416 VoEId(_instanceId,_channelId),
1417 "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1418 "to RTP/RTCP receiver",
1419 codec.plname, codec.pltype, codec.plfreq,
1420 codec.channels, codec.rate);
1421 }
1422 else
1423 {
1424 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1425 VoEId(_instanceId,_channelId),
1426 "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1427 "the RTP/RTCP receiver",
1428 codec.plname, codec.pltype, codec.plfreq,
1429 codec.channels, codec.rate);
1430 }
1431
1432 // Ensure that PCMU is used as default codec on the sending side
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +00001433 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001434 {
1435 SetSendCodec(codec);
1436 }
1437
1438 // Register default PT for outband 'telephone-event'
1439 if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1440 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001441 if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001442 (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1443 {
1444 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1445 VoEId(_instanceId,_channelId),
1446 "Channel::Init() failed to register outband "
1447 "'telephone-event' (%d/%d) correctly",
1448 codec.pltype, codec.plfreq);
1449 }
1450 }
1451
1452 if (!STR_CASE_CMP(codec.plname, "CN"))
1453 {
1454 if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1455 (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001456 (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001457 {
1458 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1459 VoEId(_instanceId,_channelId),
1460 "Channel::Init() failed to register CN (%d/%d) "
1461 "correctly - 1",
1462 codec.pltype, codec.plfreq);
1463 }
1464 }
1465#ifdef WEBRTC_CODEC_RED
1466 // Register RED to the receiving side of the ACM.
1467 // We will not receive an OnInitializeDecoder() callback for RED.
1468 if (!STR_CASE_CMP(codec.plname, "RED"))
1469 {
1470 if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1471 {
1472 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1473 VoEId(_instanceId,_channelId),
1474 "Channel::Init() failed to register RED (%d/%d) "
1475 "correctly",
1476 codec.pltype, codec.plfreq);
1477 }
1478 }
1479#endif
1480 }
1481#ifndef WEBRTC_EXTERNAL_TRANSPORT
1482 // Ensure that the WebRtcSocketTransport implementation is used as
1483 // Transport on the sending side
xians@webrtc.org83661f52011-11-25 10:58:15 +00001484 {
1485 // A lock is needed here since users can call
1486 // RegisterExternalTransport() at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001487 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +00001488 _transportPtr = &_socketTransportModule;
1489 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001490#endif
1491
1492 // Initialize the far end AP module
1493 // Using 8 kHz as initial Fs, the same as in transmission. Might be
1494 // changed at the first receiving audio.
1495 if (_rxAudioProcessingModulePtr == NULL)
1496 {
1497 _engineStatisticsPtr->SetLastError(
1498 VE_NO_MEMORY, kTraceCritical,
1499 "Channel::Init() failed to create the far-end AudioProcessing"
1500 " module");
1501 return -1;
1502 }
1503
niklase@google.com470e71d2011-07-07 08:21:25 +00001504 if (_rxAudioProcessingModulePtr->set_sample_rate_hz(8000))
1505 {
1506 _engineStatisticsPtr->SetLastError(
1507 VE_APM_ERROR, kTraceWarning,
1508 "Channel::Init() failed to set the sample rate to 8K for"
1509 " far-end AP module");
1510 }
1511
1512 if (_rxAudioProcessingModulePtr->set_num_channels(1, 1) != 0)
1513 {
1514 _engineStatisticsPtr->SetLastError(
1515 VE_SOUNDCARD_ERROR, kTraceWarning,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001516 "Init() failed to set channels for the primary audio stream");
niklase@google.com470e71d2011-07-07 08:21:25 +00001517 }
1518
1519 if (_rxAudioProcessingModulePtr->high_pass_filter()->Enable(
1520 WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1521 {
1522 _engineStatisticsPtr->SetLastError(
1523 VE_APM_ERROR, kTraceWarning,
1524 "Channel::Init() failed to set the high-pass filter for"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001525 " far-end AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001526 }
1527
1528 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(
1529 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1530 {
1531 _engineStatisticsPtr->SetLastError(
1532 VE_APM_ERROR, kTraceWarning,
1533 "Init() failed to set noise reduction level for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001534 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001535 }
1536 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(
1537 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1538 {
1539 _engineStatisticsPtr->SetLastError(
1540 VE_APM_ERROR, kTraceWarning,
1541 "Init() failed to set noise reduction state for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001542 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001543 }
1544
1545 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(
1546 (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1547 {
1548 _engineStatisticsPtr->SetLastError(
1549 VE_APM_ERROR, kTraceWarning,
1550 "Init() failed to set AGC mode for far-end AP module");
1551 }
1552 if (_rxAudioProcessingModulePtr->gain_control()->Enable(
1553 WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1554 {
1555 _engineStatisticsPtr->SetLastError(
1556 VE_APM_ERROR, kTraceWarning,
1557 "Init() failed to set AGC state for far-end AP module");
1558 }
1559
1560 return 0;
1561}
1562
1563WebRtc_Word32
1564Channel::SetEngineInformation(Statistics& engineStatistics,
1565 OutputMixer& outputMixer,
1566 voe::TransmitMixer& transmitMixer,
1567 ProcessThread& moduleProcessThread,
1568 AudioDeviceModule& audioDeviceModule,
1569 VoiceEngineObserver* voiceEngineObserver,
1570 CriticalSectionWrapper* callbackCritSect)
1571{
1572 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1573 "Channel::SetEngineInformation()");
1574 _engineStatisticsPtr = &engineStatistics;
1575 _outputMixerPtr = &outputMixer;
1576 _transmitMixerPtr = &transmitMixer,
1577 _moduleProcessThreadPtr = &moduleProcessThread;
1578 _audioDeviceModulePtr = &audioDeviceModule;
1579 _voiceEngineObserverPtr = voiceEngineObserver;
1580 _callbackCritSectPtr = callbackCritSect;
1581 return 0;
1582}
1583
1584WebRtc_Word32
1585Channel::UpdateLocalTimeStamp()
1586{
1587
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001588 _timeStamp += _audioFrame.samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001589 return 0;
1590}
1591
1592WebRtc_Word32
1593Channel::StartPlayout()
1594{
1595 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1596 "Channel::StartPlayout()");
1597 if (_playing)
1598 {
1599 return 0;
1600 }
1601 // Add participant as candidates for mixing.
1602 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1603 {
1604 _engineStatisticsPtr->SetLastError(
1605 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1606 "StartPlayout() failed to add participant to mixer");
1607 return -1;
1608 }
1609
1610 _playing = true;
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001611
1612 if (RegisterFilePlayingToMixer() != 0)
1613 return -1;
1614
niklase@google.com470e71d2011-07-07 08:21:25 +00001615 return 0;
1616}
1617
1618WebRtc_Word32
1619Channel::StopPlayout()
1620{
1621 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1622 "Channel::StopPlayout()");
1623 if (!_playing)
1624 {
1625 return 0;
1626 }
1627 // Remove participant as candidates for mixing
1628 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1629 {
1630 _engineStatisticsPtr->SetLastError(
1631 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1632 "StartPlayout() failed to remove participant from mixer");
1633 return -1;
1634 }
1635
1636 _playing = false;
1637 _outputAudioLevel.Clear();
1638
1639 return 0;
1640}
1641
1642WebRtc_Word32
1643Channel::StartSend()
1644{
1645 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1646 "Channel::StartSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001647 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001648 // A lock is needed because |_sending| can be accessed or modified by
1649 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001650 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001651
1652 if (_sending)
1653 {
1654 return 0;
1655 }
1656 _sending = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001657 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001658
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001659 if (_rtpRtcpModule->SetSendingStatus(true) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001660 {
1661 _engineStatisticsPtr->SetLastError(
1662 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1663 "StartSend() RTP/RTCP failed to start sending");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001664 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001665 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001666 return -1;
1667 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001668
niklase@google.com470e71d2011-07-07 08:21:25 +00001669 return 0;
1670}
1671
1672WebRtc_Word32
1673Channel::StopSend()
1674{
1675 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1676 "Channel::StopSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001677 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001678 // A lock is needed because |_sending| can be accessed or modified by
1679 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001680 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001681
1682 if (!_sending)
1683 {
1684 return 0;
1685 }
1686 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001687 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001688
niklase@google.com470e71d2011-07-07 08:21:25 +00001689 // Reset sending SSRC and sequence number and triggers direct transmission
1690 // of RTCP BYE
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001691 if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
1692 _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00001693 {
1694 _engineStatisticsPtr->SetLastError(
1695 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1696 "StartSend() RTP/RTCP failed to stop sending");
1697 }
1698
niklase@google.com470e71d2011-07-07 08:21:25 +00001699 return 0;
1700}
1701
1702WebRtc_Word32
1703Channel::StartReceiving()
1704{
1705 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1706 "Channel::StartReceiving()");
1707 if (_receiving)
1708 {
1709 return 0;
1710 }
1711 // If external transport is used, we will only initialize/set the variables
1712 // after this section, since we are not using the WebRtc transport but
1713 // still need to keep track of e.g. if we are receiving.
1714#ifndef WEBRTC_EXTERNAL_TRANSPORT
1715 if (!_externalTransport)
1716 {
1717 if (!_socketTransportModule.ReceiveSocketsInitialized())
1718 {
1719 _engineStatisticsPtr->SetLastError(
1720 VE_SOCKETS_NOT_INITED, kTraceError,
1721 "StartReceive() must set local receiver first");
1722 return -1;
1723 }
1724 if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0)
1725 {
1726 _engineStatisticsPtr->SetLastError(
1727 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1728 "StartReceiving() failed to start receiving");
1729 return -1;
1730 }
1731 }
1732#endif
1733 _receiving = true;
1734 _numberOfDiscardedPackets = 0;
1735 return 0;
1736}
1737
1738WebRtc_Word32
1739Channel::StopReceiving()
1740{
1741 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1742 "Channel::StopReceiving()");
1743 if (!_receiving)
1744 {
1745 return 0;
1746 }
1747
1748#ifndef WEBRTC_EXTERNAL_TRANSPORT
1749 if (!_externalTransport &&
1750 _socketTransportModule.ReceiveSocketsInitialized())
1751 {
1752 if (_socketTransportModule.StopReceiving() != 0)
1753 {
1754 _engineStatisticsPtr->SetLastError(
1755 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001756 "StopReceiving() failed to stop receiving.");
niklase@google.com470e71d2011-07-07 08:21:25 +00001757 return -1;
1758 }
1759 }
1760#endif
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001761 bool dtmfDetection = _rtpRtcpModule->TelephoneEvent();
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001762 // Recover DTMF detection status.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001763 WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventStatus(dtmfDetection,
1764 true, true);
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001765 if (ret != 0) {
1766 _engineStatisticsPtr->SetLastError(
1767 VE_INVALID_OPERATION, kTraceWarning,
1768 "StopReceiving() failed to restore telephone-event status.");
1769 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001770 RegisterReceiveCodecsToRTPModule();
1771 _receiving = false;
1772 return 0;
1773}
1774
1775#ifndef WEBRTC_EXTERNAL_TRANSPORT
1776WebRtc_Word32
1777Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort,
1778 const WebRtc_UWord16 rtcpPort,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001779 const char ipAddr[64],
1780 const char multicastIpAddr[64])
niklase@google.com470e71d2011-07-07 08:21:25 +00001781{
1782 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1783 "Channel::SetLocalReceiver()");
1784
1785 if (_externalTransport)
1786 {
1787 _engineStatisticsPtr->SetLastError(
1788 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1789 "SetLocalReceiver() conflict with external transport");
1790 return -1;
1791 }
1792
1793 if (_sending)
1794 {
1795 _engineStatisticsPtr->SetLastError(
1796 VE_ALREADY_SENDING, kTraceError,
1797 "SetLocalReceiver() already sending");
1798 return -1;
1799 }
1800 if (_receiving)
1801 {
1802 _engineStatisticsPtr->SetLastError(
1803 VE_ALREADY_LISTENING, kTraceError,
1804 "SetLocalReceiver() already receiving");
1805 return -1;
1806 }
1807
1808 if (_socketTransportModule.InitializeReceiveSockets(this,
1809 rtpPort,
1810 ipAddr,
1811 multicastIpAddr,
1812 rtcpPort) != 0)
1813 {
1814 UdpTransport::ErrorCode lastSockError(
1815 _socketTransportModule.LastError());
1816 switch (lastSockError)
1817 {
1818 case UdpTransport::kIpAddressInvalid:
1819 _engineStatisticsPtr->SetLastError(
1820 VE_INVALID_IP_ADDRESS, kTraceError,
1821 "SetLocalReceiver() invalid IP address");
1822 break;
1823 case UdpTransport::kSocketInvalid:
1824 _engineStatisticsPtr->SetLastError(
1825 VE_SOCKET_ERROR, kTraceError,
1826 "SetLocalReceiver() invalid socket");
1827 break;
1828 case UdpTransport::kPortInvalid:
1829 _engineStatisticsPtr->SetLastError(
1830 VE_INVALID_PORT_NMBR, kTraceError,
1831 "SetLocalReceiver() invalid port");
1832 break;
1833 case UdpTransport::kFailedToBindPort:
1834 _engineStatisticsPtr->SetLastError(
1835 VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError,
1836 "SetLocalReceiver() binding failed");
1837 break;
1838 default:
1839 _engineStatisticsPtr->SetLastError(
1840 VE_SOCKET_ERROR, kTraceError,
1841 "SetLocalReceiver() undefined socket error");
1842 break;
1843 }
1844 return -1;
1845 }
1846 return 0;
1847}
1848#endif
1849
1850#ifndef WEBRTC_EXTERNAL_TRANSPORT
1851WebRtc_Word32
1852Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64])
1853{
1854 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1855 "Channel::GetLocalReceiver()");
1856
1857 if (_externalTransport)
1858 {
1859 _engineStatisticsPtr->SetLastError(
1860 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1861 "SetLocalReceiver() conflict with external transport");
1862 return -1;
1863 }
1864
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001865 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00001866 WebRtc_UWord16 rtpPort(0);
1867 WebRtc_UWord16 rtcpPort(0);
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001868 char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00001869
1870 // Acquire socket information from the socket module
1871 if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp,
1872 rtpPort,
1873 rtcpPort,
1874 multicastIpAddr) != 0)
1875 {
1876 _engineStatisticsPtr->SetLastError(
1877 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1878 "GetLocalReceiver() unable to retrieve socket information");
1879 return -1;
1880 }
1881
1882 // Deliver valid results to the user
1883 port = static_cast<int> (rtpPort);
1884 RTCPport = static_cast<int> (rtcpPort);
1885 if (ipAddr != NULL)
1886 {
1887 strcpy(ipAddr, ipAddrTmp);
1888 }
1889 return 0;
1890}
1891#endif
1892
1893#ifndef WEBRTC_EXTERNAL_TRANSPORT
1894WebRtc_Word32
1895Channel::SetSendDestination(const WebRtc_UWord16 rtpPort,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001896 const char ipAddr[64],
niklase@google.com470e71d2011-07-07 08:21:25 +00001897 const int sourcePort,
1898 const WebRtc_UWord16 rtcpPort)
1899{
1900 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1901 "Channel::SetSendDestination()");
1902
1903 if (_externalTransport)
1904 {
1905 _engineStatisticsPtr->SetLastError(
1906 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1907 "SetSendDestination() conflict with external transport");
1908 return -1;
1909 }
1910
1911 // Initialize ports and IP address for the remote (destination) side.
1912 // By default, the sockets used for receiving are used for transmission as
1913 // well, hence the source ports for outgoing packets are the same as the
1914 // receiving ports specified in SetLocalReceiver.
1915 // If an extra send socket has been created, it will be utilized until a
1916 // new source port is specified or until the channel has been deleted and
1917 // recreated. If no socket exists, sockets will be created when the first
1918 // RTP and RTCP packets shall be transmitted (see e.g.
1919 // UdpTransportImpl::SendPacket()).
1920 //
1921 // NOTE: this function does not require that sockets exists; all it does is
1922 // to build send structures to be used with the sockets when they exist.
1923 // It is therefore possible to call this method before SetLocalReceiver.
1924 // However, sockets must exist if a multi-cast address is given as input.
1925
1926 // Build send structures and enable QoS (if enabled and supported)
1927 if (_socketTransportModule.InitializeSendSockets(
1928 ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError)
1929 {
1930 UdpTransport::ErrorCode lastSockError(
1931 _socketTransportModule.LastError());
1932 switch (lastSockError)
1933 {
1934 case UdpTransport::kIpAddressInvalid:
1935 _engineStatisticsPtr->SetLastError(
1936 VE_INVALID_IP_ADDRESS, kTraceError,
1937 "SetSendDestination() invalid IP address 1");
1938 break;
1939 case UdpTransport::kSocketInvalid:
1940 _engineStatisticsPtr->SetLastError(
1941 VE_SOCKET_ERROR, kTraceError,
1942 "SetSendDestination() invalid socket 1");
1943 break;
1944 case UdpTransport::kQosError:
1945 _engineStatisticsPtr->SetLastError(
1946 VE_GQOS_ERROR, kTraceError,
1947 "SetSendDestination() failed to set QoS");
1948 break;
1949 case UdpTransport::kMulticastAddressInvalid:
1950 _engineStatisticsPtr->SetLastError(
1951 VE_INVALID_MULTICAST_ADDRESS, kTraceError,
1952 "SetSendDestination() invalid multicast address");
1953 break;
1954 default:
1955 _engineStatisticsPtr->SetLastError(
1956 VE_SOCKET_ERROR, kTraceError,
1957 "SetSendDestination() undefined socket error 1");
1958 break;
1959 }
1960 return -1;
1961 }
1962
1963 // Check if the user has specified a non-default source port different from
1964 // the local receive port.
1965 // If so, an extra local socket will be created unless the source port is
1966 // not unique.
1967 if (sourcePort != kVoEDefault)
1968 {
1969 WebRtc_UWord16 receiverRtpPort(0);
1970 WebRtc_UWord16 rtcpNA(0);
1971 if (_socketTransportModule.ReceiveSocketInformation(NULL,
1972 receiverRtpPort,
1973 rtcpNA,
1974 NULL) != 0)
1975 {
1976 _engineStatisticsPtr->SetLastError(
1977 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1978 "SetSendDestination() failed to retrieve socket information");
1979 return -1;
1980 }
1981
1982 WebRtc_UWord16 sourcePortUW16 =
1983 static_cast<WebRtc_UWord16> (sourcePort);
1984
1985 // An extra socket will only be created if the specified source port
1986 // differs from the local receive port.
1987 if (sourcePortUW16 != receiverRtpPort)
1988 {
1989 // Initialize extra local socket to get a different source port
1990 // than the local
1991 // receiver port. Always use default source for RTCP.
1992 // Note that, this calls UdpTransport::CloseSendSockets().
1993 if (_socketTransportModule.InitializeSourcePorts(
1994 sourcePortUW16,
1995 sourcePortUW16+1) != 0)
1996 {
1997 UdpTransport::ErrorCode lastSockError(
1998 _socketTransportModule.LastError());
1999 switch (lastSockError)
2000 {
2001 case UdpTransport::kIpAddressInvalid:
2002 _engineStatisticsPtr->SetLastError(
2003 VE_INVALID_IP_ADDRESS, kTraceError,
2004 "SetSendDestination() invalid IP address 2");
2005 break;
2006 case UdpTransport::kSocketInvalid:
2007 _engineStatisticsPtr->SetLastError(
2008 VE_SOCKET_ERROR, kTraceError,
2009 "SetSendDestination() invalid socket 2");
2010 break;
2011 default:
2012 _engineStatisticsPtr->SetLastError(
2013 VE_SOCKET_ERROR, kTraceError,
2014 "SetSendDestination() undefined socket error 2");
2015 break;
2016 }
2017 return -1;
2018 }
2019 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2020 VoEId(_instanceId,_channelId),
2021 "SetSendDestination() extra local socket is created"
2022 " to facilitate unique source port");
2023 }
2024 else
2025 {
2026 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2027 VoEId(_instanceId,_channelId),
2028 "SetSendDestination() sourcePort equals the local"
2029 " receive port => no extra socket is created");
2030 }
2031 }
2032
2033 return 0;
2034}
2035#endif
2036
2037#ifndef WEBRTC_EXTERNAL_TRANSPORT
2038WebRtc_Word32
2039Channel::GetSendDestination(int& port,
2040 char ipAddr[64],
2041 int& sourcePort,
2042 int& RTCPport)
2043{
2044 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2045 "Channel::GetSendDestination()");
2046
2047 if (_externalTransport)
2048 {
2049 _engineStatisticsPtr->SetLastError(
2050 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
2051 "GetSendDestination() conflict with external transport");
2052 return -1;
2053 }
2054
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002055 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002056 WebRtc_UWord16 rtpPort(0);
2057 WebRtc_UWord16 rtcpPort(0);
2058 WebRtc_UWord16 rtpSourcePort(0);
2059 WebRtc_UWord16 rtcpSourcePort(0);
2060
2061 // Acquire sending socket information from the socket module
2062 _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort);
2063 _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort);
2064
2065 // Deliver valid results to the user
2066 port = static_cast<int> (rtpPort);
2067 RTCPport = static_cast<int> (rtcpPort);
2068 sourcePort = static_cast<int> (rtpSourcePort);
2069 if (ipAddr != NULL)
2070 {
2071 strcpy(ipAddr, ipAddrTmp);
2072 }
2073
2074 return 0;
2075}
2076#endif
2077
2078
2079WebRtc_Word32
2080Channel::SetNetEQPlayoutMode(NetEqModes mode)
2081{
2082 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2083 "Channel::SetNetEQPlayoutMode()");
2084 AudioPlayoutMode playoutMode(voice);
2085 switch (mode)
2086 {
2087 case kNetEqDefault:
2088 playoutMode = voice;
2089 break;
2090 case kNetEqStreaming:
2091 playoutMode = streaming;
2092 break;
2093 case kNetEqFax:
2094 playoutMode = fax;
2095 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002096 }
2097 if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
2098 {
2099 _engineStatisticsPtr->SetLastError(
2100 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2101 "SetNetEQPlayoutMode() failed to set playout mode");
2102 return -1;
2103 }
2104 return 0;
2105}
2106
2107WebRtc_Word32
2108Channel::GetNetEQPlayoutMode(NetEqModes& mode)
2109{
2110 const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
2111 switch (playoutMode)
2112 {
2113 case voice:
2114 mode = kNetEqDefault;
2115 break;
2116 case streaming:
2117 mode = kNetEqStreaming;
2118 break;
2119 case fax:
2120 mode = kNetEqFax;
2121 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002122 }
2123 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2124 VoEId(_instanceId,_channelId),
2125 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
2126 return 0;
2127}
2128
2129WebRtc_Word32
2130Channel::SetNetEQBGNMode(NetEqBgnModes mode)
2131{
2132 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2133 "Channel::SetNetEQPlayoutMode()");
2134 ACMBackgroundNoiseMode noiseMode(On);
2135 switch (mode)
2136 {
2137 case kBgnOn:
2138 noiseMode = On;
2139 break;
2140 case kBgnFade:
2141 noiseMode = Fade;
2142 break;
2143 case kBgnOff:
2144 noiseMode = Off;
2145 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002146 }
2147 if (_audioCodingModule.SetBackgroundNoiseMode(noiseMode) != 0)
2148 {
2149 _engineStatisticsPtr->SetLastError(
2150 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2151 "SetBackgroundNoiseMode() failed to set noise mode");
2152 return -1;
2153 }
2154 return 0;
2155}
2156
2157WebRtc_Word32
2158Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
2159{
2160 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2161 "Channel::SetOnHoldStatus()");
2162 if (mode == kHoldSendAndPlay)
2163 {
2164 _outputIsOnHold = enable;
2165 _inputIsOnHold = enable;
2166 }
2167 else if (mode == kHoldPlayOnly)
2168 {
2169 _outputIsOnHold = enable;
2170 }
2171 if (mode == kHoldSendOnly)
2172 {
2173 _inputIsOnHold = enable;
2174 }
2175 return 0;
2176}
2177
2178WebRtc_Word32
2179Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
2180{
2181 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2182 "Channel::GetOnHoldStatus()");
2183 enabled = (_outputIsOnHold || _inputIsOnHold);
2184 if (_outputIsOnHold && _inputIsOnHold)
2185 {
2186 mode = kHoldSendAndPlay;
2187 }
2188 else if (_outputIsOnHold && !_inputIsOnHold)
2189 {
2190 mode = kHoldPlayOnly;
2191 }
2192 else if (!_outputIsOnHold && _inputIsOnHold)
2193 {
2194 mode = kHoldSendOnly;
2195 }
2196 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2197 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
2198 enabled, mode);
2199 return 0;
2200}
2201
2202WebRtc_Word32
2203Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
2204{
2205 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2206 "Channel::RegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002207 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002208
2209 if (_voiceEngineObserverPtr)
2210 {
2211 _engineStatisticsPtr->SetLastError(
2212 VE_INVALID_OPERATION, kTraceError,
2213 "RegisterVoiceEngineObserver() observer already enabled");
2214 return -1;
2215 }
2216 _voiceEngineObserverPtr = &observer;
2217 return 0;
2218}
2219
2220WebRtc_Word32
2221Channel::DeRegisterVoiceEngineObserver()
2222{
2223 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2224 "Channel::DeRegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002225 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002226
2227 if (!_voiceEngineObserverPtr)
2228 {
2229 _engineStatisticsPtr->SetLastError(
2230 VE_INVALID_OPERATION, kTraceWarning,
2231 "DeRegisterVoiceEngineObserver() observer already disabled");
2232 return 0;
2233 }
2234 _voiceEngineObserverPtr = NULL;
2235 return 0;
2236}
2237
2238WebRtc_Word32
2239Channel::GetNetEQBGNMode(NetEqBgnModes& mode)
2240{
2241 ACMBackgroundNoiseMode noiseMode(On);
2242 _audioCodingModule.BackgroundNoiseMode(noiseMode);
2243 switch (noiseMode)
2244 {
2245 case On:
2246 mode = kBgnOn;
2247 break;
2248 case Fade:
2249 mode = kBgnFade;
2250 break;
2251 case Off:
2252 mode = kBgnOff;
2253 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002254 }
2255 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2256 "Channel::GetNetEQBGNMode() => mode=%u", mode);
2257 return 0;
2258}
2259
2260WebRtc_Word32
2261Channel::GetSendCodec(CodecInst& codec)
2262{
2263 return (_audioCodingModule.SendCodec(codec));
2264}
2265
2266WebRtc_Word32
2267Channel::GetRecCodec(CodecInst& codec)
2268{
2269 return (_audioCodingModule.ReceiveCodec(codec));
2270}
2271
2272WebRtc_Word32
2273Channel::SetSendCodec(const CodecInst& codec)
2274{
2275 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2276 "Channel::SetSendCodec()");
2277
2278 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2279 {
2280 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2281 "SetSendCodec() failed to register codec to ACM");
2282 return -1;
2283 }
2284
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002285 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002286 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002287 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2288 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002289 {
2290 WEBRTC_TRACE(
2291 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2292 "SetSendCodec() failed to register codec to"
2293 " RTP/RTCP module");
2294 return -1;
2295 }
2296 }
2297
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002298 if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002299 {
2300 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2301 "SetSendCodec() failed to set audio packet size");
2302 return -1;
2303 }
2304
2305 return 0;
2306}
2307
2308WebRtc_Word32
2309Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
2310{
2311 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2312 "Channel::SetVADStatus(mode=%d)", mode);
2313 // To disable VAD, DTX must be disabled too
2314 disableDTX = ((enableVAD == false) ? true : disableDTX);
2315 if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
2316 {
2317 _engineStatisticsPtr->SetLastError(
2318 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2319 "SetVADStatus() failed to set VAD");
2320 return -1;
2321 }
2322 return 0;
2323}
2324
2325WebRtc_Word32
2326Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
2327{
2328 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2329 "Channel::GetVADStatus");
2330 if (_audioCodingModule.VAD(disabledDTX, enabledVAD, mode) != 0)
2331 {
2332 _engineStatisticsPtr->SetLastError(
2333 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2334 "GetVADStatus() failed to get VAD status");
2335 return -1;
2336 }
2337 disabledDTX = !disabledDTX;
2338 return 0;
2339}
2340
2341WebRtc_Word32
2342Channel::SetRecPayloadType(const CodecInst& codec)
2343{
2344 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2345 "Channel::SetRecPayloadType()");
2346
2347 if (_playing)
2348 {
2349 _engineStatisticsPtr->SetLastError(
2350 VE_ALREADY_PLAYING, kTraceError,
2351 "SetRecPayloadType() unable to set PT while playing");
2352 return -1;
2353 }
2354 if (_receiving)
2355 {
2356 _engineStatisticsPtr->SetLastError(
2357 VE_ALREADY_LISTENING, kTraceError,
2358 "SetRecPayloadType() unable to set PT while listening");
2359 return -1;
2360 }
2361
2362 if (codec.pltype == -1)
2363 {
2364 // De-register the selected codec (RTP/RTCP module and ACM)
2365
2366 WebRtc_Word8 pltype(-1);
2367 CodecInst rxCodec = codec;
2368
2369 // Get payload type for the given codec
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002370 _rtpRtcpModule->ReceivePayloadType(rxCodec, &pltype);
niklase@google.com470e71d2011-07-07 08:21:25 +00002371 rxCodec.pltype = pltype;
2372
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002373 if (_rtpRtcpModule->DeRegisterReceivePayload(pltype) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002374 {
2375 _engineStatisticsPtr->SetLastError(
2376 VE_RTP_RTCP_MODULE_ERROR,
2377 kTraceError,
2378 "SetRecPayloadType() RTP/RTCP-module deregistration "
2379 "failed");
2380 return -1;
2381 }
2382 if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
2383 {
2384 _engineStatisticsPtr->SetLastError(
2385 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2386 "SetRecPayloadType() ACM deregistration failed - 1");
2387 return -1;
2388 }
2389 return 0;
2390 }
2391
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002392 if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002393 {
2394 // First attempt to register failed => de-register and try again
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002395 _rtpRtcpModule->DeRegisterReceivePayload(codec.pltype);
2396 if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002397 {
2398 _engineStatisticsPtr->SetLastError(
2399 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2400 "SetRecPayloadType() RTP/RTCP-module registration failed");
2401 return -1;
2402 }
2403 }
2404 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2405 {
2406 _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
2407 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2408 {
2409 _engineStatisticsPtr->SetLastError(
2410 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2411 "SetRecPayloadType() ACM registration failed - 1");
2412 return -1;
2413 }
2414 }
2415 return 0;
2416}
2417
2418WebRtc_Word32
2419Channel::GetRecPayloadType(CodecInst& codec)
2420{
2421 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2422 "Channel::GetRecPayloadType()");
2423 WebRtc_Word8 payloadType(-1);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002424 if (_rtpRtcpModule->ReceivePayloadType(codec, &payloadType) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002425 {
2426 _engineStatisticsPtr->SetLastError(
henrika@webrtc.org37198002012-06-18 11:00:12 +00002427 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +00002428 "GetRecPayloadType() failed to retrieve RX payload type");
2429 return -1;
2430 }
2431 codec.pltype = payloadType;
2432 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2433 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
2434 return 0;
2435}
2436
2437WebRtc_Word32
2438Channel::SetAMREncFormat(AmrMode mode)
2439{
2440 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2441 "Channel::SetAMREncFormat()");
2442
2443 // ACM doesn't support AMR
2444 return -1;
2445}
2446
2447WebRtc_Word32
2448Channel::SetAMRDecFormat(AmrMode mode)
2449{
2450 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2451 "Channel::SetAMRDecFormat()");
2452
2453 // ACM doesn't support AMR
2454 return -1;
2455}
2456
2457WebRtc_Word32
2458Channel::SetAMRWbEncFormat(AmrMode mode)
2459{
2460 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2461 "Channel::SetAMRWbEncFormat()");
2462
2463 // ACM doesn't support AMR
2464 return -1;
2465
2466}
2467
2468WebRtc_Word32
2469Channel::SetAMRWbDecFormat(AmrMode mode)
2470{
2471 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2472 "Channel::SetAMRWbDecFormat()");
2473
2474 // ACM doesn't support AMR
2475 return -1;
2476}
2477
2478WebRtc_Word32
2479Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
2480{
2481 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2482 "Channel::SetSendCNPayloadType()");
2483
2484 CodecInst codec;
2485 WebRtc_Word32 samplingFreqHz(-1);
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +00002486 const int kMono = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002487 if (frequency == kFreq32000Hz)
2488 samplingFreqHz = 32000;
2489 else if (frequency == kFreq16000Hz)
2490 samplingFreqHz = 16000;
2491
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +00002492 if (_audioCodingModule.Codec("CN", codec, samplingFreqHz, kMono) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00002493 {
2494 _engineStatisticsPtr->SetLastError(
2495 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2496 "SetSendCNPayloadType() failed to retrieve default CN codec "
2497 "settings");
2498 return -1;
2499 }
2500
2501 // Modify the payload type (must be set to dynamic range)
2502 codec.pltype = type;
2503
2504 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2505 {
2506 _engineStatisticsPtr->SetLastError(
2507 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2508 "SetSendCNPayloadType() failed to register CN to ACM");
2509 return -1;
2510 }
2511
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002512 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002513 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002514 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2515 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002516 {
2517 _engineStatisticsPtr->SetLastError(
2518 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2519 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
2520 "module");
2521 return -1;
2522 }
2523 }
2524 return 0;
2525}
2526
2527WebRtc_Word32
2528Channel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
2529{
2530 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2531 "Channel::SetISACInitTargetRate()");
2532
2533 CodecInst sendCodec;
2534 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2535 {
2536 _engineStatisticsPtr->SetLastError(
2537 VE_CODEC_ERROR, kTraceError,
2538 "SetISACInitTargetRate() failed to retrieve send codec");
2539 return -1;
2540 }
2541 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2542 {
2543 // This API is only valid if iSAC is setup to run in channel-adaptive
2544 // mode.
2545 // We do not validate the adaptive mode here. It is done later in the
2546 // ConfigISACBandwidthEstimator() API.
2547 _engineStatisticsPtr->SetLastError(
2548 VE_CODEC_ERROR, kTraceError,
2549 "SetISACInitTargetRate() send codec is not iSAC");
2550 return -1;
2551 }
2552
2553 WebRtc_UWord8 initFrameSizeMsec(0);
2554 if (16000 == sendCodec.plfreq)
2555 {
2556 // Note that 0 is a valid and corresponds to "use default
2557 if ((rateBps != 0 &&
2558 rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
2559 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
2560 {
2561 _engineStatisticsPtr->SetLastError(
2562 VE_INVALID_ARGUMENT, kTraceError,
2563 "SetISACInitTargetRate() invalid target rate - 1");
2564 return -1;
2565 }
2566 // 30 or 60ms
2567 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 16);
2568 }
2569 else if (32000 == sendCodec.plfreq)
2570 {
2571 if ((rateBps != 0 &&
2572 rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
2573 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
2574 {
2575 _engineStatisticsPtr->SetLastError(
2576 VE_INVALID_ARGUMENT, kTraceError,
2577 "SetISACInitTargetRate() invalid target rate - 2");
2578 return -1;
2579 }
2580 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 32); // 30ms
2581 }
2582
2583 if (_audioCodingModule.ConfigISACBandwidthEstimator(
2584 initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2585 {
2586 _engineStatisticsPtr->SetLastError(
2587 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2588 "SetISACInitTargetRate() iSAC BWE config failed");
2589 return -1;
2590 }
2591
2592 return 0;
2593}
2594
2595WebRtc_Word32
2596Channel::SetISACMaxRate(int rateBps)
2597{
2598 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2599 "Channel::SetISACMaxRate()");
2600
2601 CodecInst sendCodec;
2602 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2603 {
2604 _engineStatisticsPtr->SetLastError(
2605 VE_CODEC_ERROR, kTraceError,
2606 "SetISACMaxRate() failed to retrieve send codec");
2607 return -1;
2608 }
2609 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2610 {
2611 // This API is only valid if iSAC is selected as sending codec.
2612 _engineStatisticsPtr->SetLastError(
2613 VE_CODEC_ERROR, kTraceError,
2614 "SetISACMaxRate() send codec is not iSAC");
2615 return -1;
2616 }
2617 if (16000 == sendCodec.plfreq)
2618 {
2619 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2620 (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2621 {
2622 _engineStatisticsPtr->SetLastError(
2623 VE_INVALID_ARGUMENT, kTraceError,
2624 "SetISACMaxRate() invalid max rate - 1");
2625 return -1;
2626 }
2627 }
2628 else if (32000 == sendCodec.plfreq)
2629 {
2630 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2631 (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2632 {
2633 _engineStatisticsPtr->SetLastError(
2634 VE_INVALID_ARGUMENT, kTraceError,
2635 "SetISACMaxRate() invalid max rate - 2");
2636 return -1;
2637 }
2638 }
2639 if (_sending)
2640 {
2641 _engineStatisticsPtr->SetLastError(
2642 VE_SENDING, kTraceError,
2643 "SetISACMaxRate() unable to set max rate while sending");
2644 return -1;
2645 }
2646
2647 // Set the maximum instantaneous rate of iSAC (works for both adaptive
2648 // and non-adaptive mode)
2649 if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2650 {
2651 _engineStatisticsPtr->SetLastError(
2652 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2653 "SetISACMaxRate() failed to set max rate");
2654 return -1;
2655 }
2656
2657 return 0;
2658}
2659
2660WebRtc_Word32
2661Channel::SetISACMaxPayloadSize(int sizeBytes)
2662{
2663 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2664 "Channel::SetISACMaxPayloadSize()");
2665 CodecInst sendCodec;
2666 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2667 {
2668 _engineStatisticsPtr->SetLastError(
2669 VE_CODEC_ERROR, kTraceError,
2670 "SetISACMaxPayloadSize() failed to retrieve send codec");
2671 return -1;
2672 }
2673 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2674 {
2675 _engineStatisticsPtr->SetLastError(
2676 VE_CODEC_ERROR, kTraceError,
2677 "SetISACMaxPayloadSize() send codec is not iSAC");
2678 return -1;
2679 }
2680 if (16000 == sendCodec.plfreq)
2681 {
2682 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2683 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2684 {
2685 _engineStatisticsPtr->SetLastError(
2686 VE_INVALID_ARGUMENT, kTraceError,
2687 "SetISACMaxPayloadSize() invalid max payload - 1");
2688 return -1;
2689 }
2690 }
2691 else if (32000 == sendCodec.plfreq)
2692 {
2693 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2694 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2695 {
2696 _engineStatisticsPtr->SetLastError(
2697 VE_INVALID_ARGUMENT, kTraceError,
2698 "SetISACMaxPayloadSize() invalid max payload - 2");
2699 return -1;
2700 }
2701 }
2702 if (_sending)
2703 {
2704 _engineStatisticsPtr->SetLastError(
2705 VE_SENDING, kTraceError,
2706 "SetISACMaxPayloadSize() unable to set max rate while sending");
2707 return -1;
2708 }
2709
2710 if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2711 {
2712 _engineStatisticsPtr->SetLastError(
2713 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2714 "SetISACMaxPayloadSize() failed to set max payload size");
2715 return -1;
2716 }
2717 return 0;
2718}
2719
2720WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport)
2721{
2722 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2723 "Channel::RegisterExternalTransport()");
2724
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002725 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002726
2727#ifndef WEBRTC_EXTERNAL_TRANSPORT
2728 // Sanity checks for default (non external transport) to avoid conflict with
2729 // WebRtc sockets.
2730 if (_socketTransportModule.SendSocketsInitialized())
2731 {
2732 _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT,
2733 kTraceError,
2734 "RegisterExternalTransport() send sockets already initialized");
2735 return -1;
2736 }
2737 if (_socketTransportModule.ReceiveSocketsInitialized())
2738 {
2739 _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT,
2740 kTraceError,
2741 "RegisterExternalTransport() receive sockets already initialized");
2742 return -1;
2743 }
2744#endif
2745 if (_externalTransport)
2746 {
2747 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2748 kTraceError,
2749 "RegisterExternalTransport() external transport already enabled");
2750 return -1;
2751 }
2752 _externalTransport = true;
2753 _transportPtr = &transport;
2754 return 0;
2755}
2756
2757WebRtc_Word32
2758Channel::DeRegisterExternalTransport()
2759{
2760 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2761 "Channel::DeRegisterExternalTransport()");
2762
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002763 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +00002764
niklase@google.com470e71d2011-07-07 08:21:25 +00002765 if (!_transportPtr)
2766 {
2767 _engineStatisticsPtr->SetLastError(
2768 VE_INVALID_OPERATION, kTraceWarning,
2769 "DeRegisterExternalTransport() external transport already "
2770 "disabled");
2771 return 0;
2772 }
2773 _externalTransport = false;
2774#ifdef WEBRTC_EXTERNAL_TRANSPORT
2775 _transportPtr = NULL;
2776 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2777 "DeRegisterExternalTransport() all transport is disabled");
2778#else
2779 _transportPtr = &_socketTransportModule;
2780 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2781 "DeRegisterExternalTransport() internal Transport is enabled");
2782#endif
2783 return 0;
2784}
2785
2786WebRtc_Word32
2787Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2788{
2789 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2790 "Channel::ReceivedRTPPacket()");
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002791 const char dummyIP[] = "127.0.0.1";
niklase@google.com470e71d2011-07-07 08:21:25 +00002792 IncomingRTPPacket(data, length, dummyIP, 0);
2793 return 0;
2794}
2795
2796WebRtc_Word32
2797Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2798{
2799 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2800 "Channel::ReceivedRTCPPacket()");
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002801 const char dummyIP[] = "127.0.0.1";
niklase@google.com470e71d2011-07-07 08:21:25 +00002802 IncomingRTCPPacket(data, length, dummyIP, 0);
2803 return 0;
2804}
2805
2806#ifndef WEBRTC_EXTERNAL_TRANSPORT
2807WebRtc_Word32
2808Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64])
2809{
2810 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2811 "Channel::GetSourceInfo()");
2812
2813 WebRtc_UWord16 rtpPortModule;
2814 WebRtc_UWord16 rtcpPortModule;
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002815 char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002816
2817 if (_socketTransportModule.RemoteSocketInformation(ipaddr,
2818 rtpPortModule,
2819 rtcpPortModule) != 0)
2820 {
2821 _engineStatisticsPtr->SetLastError(
2822 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2823 "GetSourceInfo() failed to retrieve remote socket information");
2824 return -1;
2825 }
2826 strcpy(ipAddr, ipaddr);
2827 rtpPort = rtpPortModule;
2828 rtcpPort = rtcpPortModule;
2829
2830 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2831 "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2832 rtpPort, rtcpPort, ipAddr);
2833 return 0;
2834}
2835
2836WebRtc_Word32
2837Channel::EnableIPv6()
2838{
2839 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2840 "Channel::EnableIPv6()");
2841 if (_socketTransportModule.ReceiveSocketsInitialized() ||
2842 _socketTransportModule.SendSocketsInitialized())
2843 {
2844 _engineStatisticsPtr->SetLastError(
2845 VE_INVALID_OPERATION, kTraceError,
2846 "EnableIPv6() socket layer is already initialized");
2847 return -1;
2848 }
2849 if (_socketTransportModule.EnableIpV6() != 0)
2850 {
2851 _engineStatisticsPtr->SetLastError(
2852 VE_SOCKET_ERROR, kTraceError,
2853 "EnableIPv6() failed to enable IPv6");
2854 const UdpTransport::ErrorCode lastError =
2855 _socketTransportModule.LastError();
2856 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2857 "UdpTransport::LastError() => %d", lastError);
2858 return -1;
2859 }
2860 return 0;
2861}
2862
2863bool
2864Channel::IPv6IsEnabled() const
2865{
2866 bool isEnabled = _socketTransportModule.IpV6Enabled();
2867 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2868 "IPv6IsEnabled() => %d", isEnabled);
2869 return isEnabled;
2870}
2871
2872WebRtc_Word32
2873Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64])
2874{
2875 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2876 "Channel::SetSourceFilter()");
2877 if (_socketTransportModule.SetFilterPorts(
2878 static_cast<WebRtc_UWord16>(rtpPort),
2879 static_cast<WebRtc_UWord16>(rtcpPort)) != 0)
2880 {
2881 _engineStatisticsPtr->SetLastError(
2882 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2883 "SetSourceFilter() failed to set filter ports");
2884 const UdpTransport::ErrorCode lastError =
2885 _socketTransportModule.LastError();
2886 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2887 "UdpTransport::LastError() => %d",
2888 lastError);
2889 return -1;
2890 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002891 const char* filterIpAddress = ipAddr;
niklase@google.com470e71d2011-07-07 08:21:25 +00002892 if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0)
2893 {
2894 _engineStatisticsPtr->SetLastError(
2895 VE_INVALID_IP_ADDRESS, kTraceError,
2896 "SetSourceFilter() failed to set filter IP address");
2897 const UdpTransport::ErrorCode lastError =
2898 _socketTransportModule.LastError();
2899 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2900 "UdpTransport::LastError() => %d", lastError);
2901 return -1;
2902 }
2903 return 0;
2904}
2905
2906WebRtc_Word32
2907Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64])
2908{
2909 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2910 "Channel::GetSourceFilter()");
2911 WebRtc_UWord16 rtpFilterPort(0);
2912 WebRtc_UWord16 rtcpFilterPort(0);
2913 if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0)
2914 {
2915 _engineStatisticsPtr->SetLastError(
2916 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2917 "GetSourceFilter() failed to retrieve filter ports");
2918 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002919 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002920 if (_socketTransportModule.FilterIP(ipAddrTmp) != 0)
2921 {
2922 // no filter has been configured (not seen as an error)
2923 memset(ipAddrTmp,
2924 0, UdpTransport::kIpAddressVersion6Length);
2925 }
2926 rtpPort = static_cast<int> (rtpFilterPort);
2927 rtcpPort = static_cast<int> (rtcpFilterPort);
2928 strcpy(ipAddr, ipAddrTmp);
2929 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2930 "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2931 rtpPort, rtcpPort, ipAddr);
2932 return 0;
2933}
2934
2935WebRtc_Word32
2936Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt)
2937{
2938 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2939 "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)",
2940 DSCP, (int)useSetSockopt);
2941
2942 // Set TOS value and possibly try to force usage of setsockopt()
2943 if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0)
2944 {
2945 UdpTransport::ErrorCode lastSockError(
2946 _socketTransportModule.LastError());
2947 switch (lastSockError)
2948 {
2949 case UdpTransport::kTosError:
2950 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2951 "SetSendTOS() TOS error");
2952 break;
2953 case UdpTransport::kQosError:
2954 _engineStatisticsPtr->SetLastError(
2955 VE_TOS_GQOS_CONFLICT, kTraceError,
2956 "SetSendTOS() GQOS error");
2957 break;
2958 case UdpTransport::kTosInvalid:
2959 // can't switch SetSockOpt method without disabling TOS first, or
2960 // SetSockopt() call failed
2961 _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError,
2962 "SetSendTOS() invalid TOS");
2963 break;
2964 case UdpTransport::kSocketInvalid:
2965 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
2966 "SetSendTOS() invalid Socket");
2967 break;
2968 default:
2969 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2970 "SetSendTOS() TOS error");
2971 break;
2972 }
2973 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2974 "UdpTransport => lastError = %d",
2975 lastSockError);
2976 return -1;
2977 }
2978
2979 // Set priority (PCP) value, -1 means don't change
2980 if (-1 != priority)
2981 {
2982 if (_socketTransportModule.SetPCP(priority) != 0)
2983 {
2984 UdpTransport::ErrorCode lastSockError(
2985 _socketTransportModule.LastError());
2986 switch (lastSockError)
2987 {
2988 case UdpTransport::kPcpError:
2989 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2990 "SetSendTOS() PCP error");
2991 break;
2992 case UdpTransport::kQosError:
2993 _engineStatisticsPtr->SetLastError(
2994 VE_TOS_GQOS_CONFLICT, kTraceError,
2995 "SetSendTOS() GQOS conflict");
2996 break;
2997 case UdpTransport::kSocketInvalid:
2998 _engineStatisticsPtr->SetLastError(
2999 VE_SOCKET_ERROR, kTraceError,
3000 "SetSendTOS() invalid Socket");
3001 break;
3002 default:
3003 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3004 "SetSendTOS() PCP error");
3005 break;
3006 }
3007 WEBRTC_TRACE(kTraceError, kTraceVoice,
3008 VoEId(_instanceId,_channelId),
3009 "UdpTransport => lastError = %d",
3010 lastSockError);
3011 return -1;
3012 }
3013 }
3014
3015 return 0;
3016}
3017
3018WebRtc_Word32
3019Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt)
3020{
3021 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3022 "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)");
3023 WebRtc_Word32 dscp(0), prio(0);
3024 bool setSockopt(false);
3025 if (_socketTransportModule.ToS(dscp, setSockopt) != 0)
3026 {
3027 _engineStatisticsPtr->SetLastError(
3028 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3029 "GetSendTOS() failed to get TOS info");
3030 return -1;
3031 }
3032 if (_socketTransportModule.PCP(prio) != 0)
3033 {
3034 _engineStatisticsPtr->SetLastError(
3035 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3036 "GetSendTOS() failed to get PCP info");
3037 return -1;
3038 }
3039 DSCP = static_cast<int> (dscp);
3040 priority = static_cast<int> (prio);
3041 useSetSockopt = setSockopt;
3042 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3043 "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d",
3044 DSCP, priority, (int)useSetSockopt);
3045 return 0;
3046}
3047
3048#if defined(_WIN32)
3049WebRtc_Word32
3050Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP)
3051{
3052 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3053 "Channel::SetSendGQoS(enable=%d, serviceType=%d, "
3054 "overrideDSCP=%d)",
3055 (int)enable, serviceType, overrideDSCP);
3056 if(!_socketTransportModule.ReceiveSocketsInitialized())
3057 {
3058 _engineStatisticsPtr->SetLastError(
3059 VE_SOCKETS_NOT_INITED, kTraceError,
3060 "SetSendGQoS() GQoS state must be set after sockets are created");
3061 return -1;
3062 }
3063 if(!_socketTransportModule.SendSocketsInitialized())
3064 {
3065 _engineStatisticsPtr->SetLastError(
3066 VE_DESTINATION_NOT_INITED, kTraceError,
3067 "SetSendGQoS() GQoS state must be set after sending side is "
3068 "initialized");
3069 return -1;
3070 }
3071 if (enable &&
3072 (serviceType != SERVICETYPE_BESTEFFORT) &&
3073 (serviceType != SERVICETYPE_CONTROLLEDLOAD) &&
3074 (serviceType != SERVICETYPE_GUARANTEED) &&
3075 (serviceType != SERVICETYPE_QUALITATIVE))
3076 {
3077 _engineStatisticsPtr->SetLastError(
3078 VE_INVALID_ARGUMENT, kTraceError,
3079 "SetSendGQoS() Invalid service type");
3080 return -1;
3081 }
3082 if (enable && ((overrideDSCP < 0) || (overrideDSCP > 63)))
3083 {
3084 _engineStatisticsPtr->SetLastError(
3085 VE_INVALID_ARGUMENT, kTraceError,
3086 "SetSendGQoS() Invalid overrideDSCP value");
3087 return -1;
3088 }
3089
3090 // Avoid GQoS/ToS conflict when user wants to override the default DSCP
3091 // mapping
3092 bool QoS(false);
3093 WebRtc_Word32 sType(0);
3094 WebRtc_Word32 ovrDSCP(0);
3095 if (_socketTransportModule.QoS(QoS, sType, ovrDSCP))
3096 {
3097 _engineStatisticsPtr->SetLastError(
3098 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3099 "SetSendGQoS() failed to get QOS info");
3100 return -1;
3101 }
3102 if (QoS && ovrDSCP == 0 && overrideDSCP != 0)
3103 {
3104 _engineStatisticsPtr->SetLastError(
3105 VE_TOS_GQOS_CONFLICT, kTraceError,
3106 "SetSendGQoS() QOS is already enabled and overrideDSCP differs,"
3107 " not allowed");
3108 return -1;
3109 }
3110 const WebRtc_Word32 maxBitrate(0);
3111 if (_socketTransportModule.SetQoS(enable,
3112 static_cast<WebRtc_Word32>(serviceType),
3113 maxBitrate,
3114 static_cast<WebRtc_Word32>(overrideDSCP),
3115 true))
3116 {
3117 UdpTransport::ErrorCode lastSockError(
3118 _socketTransportModule.LastError());
3119 switch (lastSockError)
3120 {
3121 case UdpTransport::kQosError:
3122 _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError,
3123 "SetSendGQoS() QOS error");
3124 break;
3125 default:
3126 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
3127 "SetSendGQoS() Socket error");
3128 break;
3129 }
3130 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3131 "UdpTransport() => lastError = %d",
3132 lastSockError);
3133 return -1;
3134 }
3135 return 0;
3136}
3137#endif
3138
3139#if defined(_WIN32)
3140WebRtc_Word32
3141Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP)
3142{
3143 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3144 "Channel::GetSendGQoS(enable=?, serviceType=?, "
3145 "overrideDSCP=?)");
3146
3147 bool QoS(false);
3148 WebRtc_Word32 serviceTypeModule(0);
3149 WebRtc_Word32 overrideDSCPModule(0);
3150 _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule);
3151
3152 enabled = QoS;
3153 serviceType = static_cast<int> (serviceTypeModule);
3154 overrideDSCP = static_cast<int> (overrideDSCPModule);
3155
3156 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3157 "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d",
3158 (int)enabled, serviceType, overrideDSCP);
3159 return 0;
3160}
3161#endif
3162#endif
3163
3164WebRtc_Word32
3165Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds)
3166{
3167 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3168 "Channel::SetPacketTimeoutNotification()");
3169 if (enable)
3170 {
3171 const WebRtc_UWord32 RTPtimeoutMS = 1000*timeoutSeconds;
3172 const WebRtc_UWord32 RTCPtimeoutMS = 0;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003173 _rtpRtcpModule->SetPacketTimeout(RTPtimeoutMS, RTCPtimeoutMS);
niklase@google.com470e71d2011-07-07 08:21:25 +00003174 _rtpPacketTimeOutIsEnabled = true;
3175 _rtpTimeOutSeconds = timeoutSeconds;
3176 }
3177 else
3178 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003179 _rtpRtcpModule->SetPacketTimeout(0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +00003180 _rtpPacketTimeOutIsEnabled = false;
3181 _rtpTimeOutSeconds = 0;
3182 }
3183 return 0;
3184}
3185
3186WebRtc_Word32
3187Channel::GetPacketTimeoutNotification(bool& enabled, int& timeoutSeconds)
3188{
3189 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3190 "Channel::GetPacketTimeoutNotification()");
3191 enabled = _rtpPacketTimeOutIsEnabled;
3192 if (enabled)
3193 {
3194 timeoutSeconds = _rtpTimeOutSeconds;
3195 }
3196 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3197 "GetPacketTimeoutNotification() => enabled=%d,"
3198 " timeoutSeconds=%d",
3199 enabled, timeoutSeconds);
3200 return 0;
3201}
3202
3203WebRtc_Word32
3204Channel::RegisterDeadOrAliveObserver(VoEConnectionObserver& observer)
3205{
3206 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3207 "Channel::RegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003208 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003209
3210 if (_connectionObserverPtr)
3211 {
3212 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, kTraceError,
3213 "RegisterDeadOrAliveObserver() observer already enabled");
3214 return -1;
3215 }
3216
3217 _connectionObserverPtr = &observer;
3218 _connectionObserver = true;
3219
3220 return 0;
3221}
3222
3223WebRtc_Word32
3224Channel::DeRegisterDeadOrAliveObserver()
3225{
3226 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3227 "Channel::DeRegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003228 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003229
3230 if (!_connectionObserverPtr)
3231 {
3232 _engineStatisticsPtr->SetLastError(
3233 VE_INVALID_OPERATION, kTraceWarning,
3234 "DeRegisterDeadOrAliveObserver() observer already disabled");
3235 return 0;
3236 }
3237
3238 _connectionObserver = false;
3239 _connectionObserverPtr = NULL;
3240
3241 return 0;
3242}
3243
3244WebRtc_Word32
3245Channel::SetPeriodicDeadOrAliveStatus(bool enable, int sampleTimeSeconds)
3246{
3247 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3248 "Channel::SetPeriodicDeadOrAliveStatus()");
3249 if (!_connectionObserverPtr)
3250 {
3251 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3252 "SetPeriodicDeadOrAliveStatus() connection observer has"
3253 " not been registered");
3254 }
3255 if (enable)
3256 {
3257 ResetDeadOrAliveCounters();
3258 }
3259 bool enabled(false);
3260 WebRtc_UWord8 currentSampleTimeSec(0);
3261 // Store last state (will be used later if dead-or-alive is disabled).
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003262 _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, currentSampleTimeSec);
niklase@google.com470e71d2011-07-07 08:21:25 +00003263 // Update the dead-or-alive state.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003264 if (_rtpRtcpModule->SetPeriodicDeadOrAliveStatus(
niklase@google.com470e71d2011-07-07 08:21:25 +00003265 enable, (WebRtc_UWord8)sampleTimeSeconds) != 0)
3266 {
3267 _engineStatisticsPtr->SetLastError(
3268 VE_RTP_RTCP_MODULE_ERROR,
3269 kTraceError,
3270 "SetPeriodicDeadOrAliveStatus() failed to set dead-or-alive "
3271 "status");
3272 return -1;
3273 }
3274 if (!enable)
3275 {
3276 // Restore last utilized sample time.
3277 // Without this, the sample time would always be reset to default
3278 // (2 sec), each time dead-or-alived was disabled without sample-time
3279 // parameter.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003280 _rtpRtcpModule->SetPeriodicDeadOrAliveStatus(enable,
niklase@google.com470e71d2011-07-07 08:21:25 +00003281 currentSampleTimeSec);
3282 }
3283 return 0;
3284}
3285
3286WebRtc_Word32
3287Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds)
3288{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003289 _rtpRtcpModule->PeriodicDeadOrAliveStatus(
niklase@google.com470e71d2011-07-07 08:21:25 +00003290 enabled,
3291 (WebRtc_UWord8&)sampleTimeSeconds);
3292 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3293 "GetPeriodicDeadOrAliveStatus() => enabled=%d,"
3294 " sampleTimeSeconds=%d",
3295 enabled, sampleTimeSeconds);
3296 return 0;
3297}
3298
3299WebRtc_Word32
3300Channel::SendUDPPacket(const void* data,
3301 unsigned int length,
3302 int& transmittedBytes,
3303 bool useRtcpSocket)
3304{
3305 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3306 "Channel::SendUDPPacket()");
3307 if (_externalTransport)
3308 {
3309 _engineStatisticsPtr->SetLastError(
3310 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
3311 "SendUDPPacket() external transport is enabled");
3312 return -1;
3313 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003314 if (useRtcpSocket && !_rtpRtcpModule->RTCP())
niklase@google.com470e71d2011-07-07 08:21:25 +00003315 {
3316 _engineStatisticsPtr->SetLastError(
3317 VE_RTCP_ERROR, kTraceError,
3318 "SendUDPPacket() RTCP is disabled");
3319 return -1;
3320 }
3321 if (!_sending)
3322 {
3323 _engineStatisticsPtr->SetLastError(
3324 VE_NOT_SENDING, kTraceError,
3325 "SendUDPPacket() not sending");
3326 return -1;
3327 }
3328
3329 char* dataC = new char[length];
3330 if (NULL == dataC)
3331 {
3332 _engineStatisticsPtr->SetLastError(
3333 VE_NO_MEMORY, kTraceError,
3334 "SendUDPPacket() memory allocation failed");
3335 return -1;
3336 }
3337 memcpy(dataC, data, length);
3338
3339 transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket);
3340
3341 delete [] dataC;
3342 dataC = NULL;
3343
3344 if (transmittedBytes <= 0)
3345 {
3346 _engineStatisticsPtr->SetLastError(
3347 VE_SEND_ERROR, kTraceError,
3348 "SendUDPPacket() transmission failed");
3349 transmittedBytes = 0;
3350 return -1;
3351 }
3352 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3353 "SendUDPPacket() => transmittedBytes=%d", transmittedBytes);
3354 return 0;
3355}
3356
3357
3358int Channel::StartPlayingFileLocally(const char* fileName,
3359 const bool loop,
3360 const FileFormats format,
3361 const int startPosition,
3362 const float volumeScaling,
3363 const int stopPosition,
3364 const CodecInst* codecInst)
3365{
3366 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3367 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
3368 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
3369 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3370 startPosition, stopPosition);
3371
3372 if (_outputFilePlaying)
3373 {
3374 _engineStatisticsPtr->SetLastError(
3375 VE_ALREADY_PLAYING, kTraceError,
3376 "StartPlayingFileLocally() is already playing");
3377 return -1;
3378 }
3379
niklase@google.com470e71d2011-07-07 08:21:25 +00003380 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003381 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003382
3383 if (_outputFilePlayerPtr)
3384 {
3385 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3386 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3387 _outputFilePlayerPtr = NULL;
3388 }
3389
3390 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3391 _outputFilePlayerId, (const FileFormats)format);
3392
3393 if (_outputFilePlayerPtr == NULL)
3394 {
3395 _engineStatisticsPtr->SetLastError(
3396 VE_INVALID_ARGUMENT, kTraceError,
henrike@webrtc.org31d30702011-11-18 19:59:32 +00003397 "StartPlayingFileLocally() filePlayer format is not correct");
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003398 return -1;
3399 }
3400
3401 const WebRtc_UWord32 notificationTime(0);
3402
3403 if (_outputFilePlayerPtr->StartPlayingFile(
3404 fileName,
3405 loop,
3406 startPosition,
3407 volumeScaling,
3408 notificationTime,
3409 stopPosition,
3410 (const CodecInst*)codecInst) != 0)
3411 {
3412 _engineStatisticsPtr->SetLastError(
3413 VE_BAD_FILE, kTraceError,
3414 "StartPlayingFile() failed to start file playout");
3415 _outputFilePlayerPtr->StopPlayingFile();
3416 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3417 _outputFilePlayerPtr = NULL;
3418 return -1;
3419 }
3420 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3421 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003422 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003423
3424 if (RegisterFilePlayingToMixer() != 0)
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003425 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00003426
3427 return 0;
3428}
3429
3430int Channel::StartPlayingFileLocally(InStream* stream,
3431 const FileFormats format,
3432 const int startPosition,
3433 const float volumeScaling,
3434 const int stopPosition,
3435 const CodecInst* codecInst)
3436{
3437 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3438 "Channel::StartPlayingFileLocally(format=%d,"
3439 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3440 format, volumeScaling, startPosition, stopPosition);
3441
3442 if(stream == NULL)
3443 {
3444 _engineStatisticsPtr->SetLastError(
3445 VE_BAD_FILE, kTraceError,
3446 "StartPlayingFileLocally() NULL as input stream");
3447 return -1;
3448 }
3449
3450
3451 if (_outputFilePlaying)
3452 {
3453 _engineStatisticsPtr->SetLastError(
3454 VE_ALREADY_PLAYING, kTraceError,
3455 "StartPlayingFileLocally() is already playing");
3456 return -1;
3457 }
3458
niklase@google.com470e71d2011-07-07 08:21:25 +00003459 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003460 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003461
3462 // Destroy the old instance
3463 if (_outputFilePlayerPtr)
3464 {
3465 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3466 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3467 _outputFilePlayerPtr = NULL;
3468 }
3469
3470 // Create the instance
3471 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3472 _outputFilePlayerId,
3473 (const FileFormats)format);
3474
3475 if (_outputFilePlayerPtr == NULL)
3476 {
3477 _engineStatisticsPtr->SetLastError(
3478 VE_INVALID_ARGUMENT, kTraceError,
3479 "StartPlayingFileLocally() filePlayer format isnot correct");
3480 return -1;
3481 }
3482
3483 const WebRtc_UWord32 notificationTime(0);
3484
3485 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3486 volumeScaling,
3487 notificationTime,
3488 stopPosition, codecInst) != 0)
3489 {
3490 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3491 "StartPlayingFile() failed to "
3492 "start file playout");
3493 _outputFilePlayerPtr->StopPlayingFile();
3494 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3495 _outputFilePlayerPtr = NULL;
3496 return -1;
3497 }
3498 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3499 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003500 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003501
3502 if (RegisterFilePlayingToMixer() != 0)
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003503 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00003504
niklase@google.com470e71d2011-07-07 08:21:25 +00003505 return 0;
3506}
3507
3508int Channel::StopPlayingFileLocally()
3509{
3510 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3511 "Channel::StopPlayingFileLocally()");
3512
3513 if (!_outputFilePlaying)
3514 {
3515 _engineStatisticsPtr->SetLastError(
3516 VE_INVALID_OPERATION, kTraceWarning,
3517 "StopPlayingFileLocally() isnot playing");
3518 return 0;
3519 }
3520
niklase@google.com470e71d2011-07-07 08:21:25 +00003521 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003522 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003523
3524 if (_outputFilePlayerPtr->StopPlayingFile() != 0)
3525 {
3526 _engineStatisticsPtr->SetLastError(
3527 VE_STOP_RECORDING_FAILED, kTraceError,
3528 "StopPlayingFile() could not stop playing");
3529 return -1;
3530 }
3531 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3532 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3533 _outputFilePlayerPtr = NULL;
3534 _outputFilePlaying = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00003535 }
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003536 // _fileCritSect cannot be taken while calling
3537 // SetAnonymousMixibilityStatus. Refer to comments in
3538 // StartPlayingFileLocally(const char* ...) for more details.
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003539 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
3540 {
3541 _engineStatisticsPtr->SetLastError(
3542 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003543 "StopPlayingFile() failed to stop participant from playing as"
3544 "file in the mixer");
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003545 return -1;
3546 }
niklase@google.com470e71d2011-07-07 08:21:25 +00003547
3548 return 0;
3549}
3550
3551int Channel::IsPlayingFileLocally() const
3552{
3553 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3554 "Channel::IsPlayingFileLocally()");
3555
3556 return (WebRtc_Word32)_outputFilePlaying;
3557}
3558
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003559int Channel::RegisterFilePlayingToMixer()
3560{
3561 // Return success for not registering for file playing to mixer if:
3562 // 1. playing file before playout is started on that channel.
3563 // 2. starting playout without file playing on that channel.
3564 if (!_playing || !_outputFilePlaying)
3565 {
3566 return 0;
3567 }
3568
3569 // |_fileCritSect| cannot be taken while calling
3570 // SetAnonymousMixabilityStatus() since as soon as the participant is added
3571 // frames can be pulled by the mixer. Since the frames are generated from
3572 // the file, _fileCritSect will be taken. This would result in a deadlock.
3573 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3574 {
3575 CriticalSectionScoped cs(&_fileCritSect);
3576 _outputFilePlaying = false;
3577 _engineStatisticsPtr->SetLastError(
3578 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3579 "StartPlayingFile() failed to add participant as file to mixer");
3580 _outputFilePlayerPtr->StopPlayingFile();
3581 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3582 _outputFilePlayerPtr = NULL;
3583 return -1;
3584 }
3585
3586 return 0;
3587}
3588
niklase@google.com470e71d2011-07-07 08:21:25 +00003589int Channel::ScaleLocalFilePlayout(const float scale)
3590{
3591 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3592 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
3593
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003594 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003595
3596 if (!_outputFilePlaying)
3597 {
3598 _engineStatisticsPtr->SetLastError(
3599 VE_INVALID_OPERATION, kTraceError,
3600 "ScaleLocalFilePlayout() isnot playing");
3601 return -1;
3602 }
3603 if ((_outputFilePlayerPtr == NULL) ||
3604 (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
3605 {
3606 _engineStatisticsPtr->SetLastError(
3607 VE_BAD_ARGUMENT, kTraceError,
3608 "SetAudioScaling() failed to scale the playout");
3609 return -1;
3610 }
3611
3612 return 0;
3613}
3614
3615int Channel::GetLocalPlayoutPosition(int& positionMs)
3616{
3617 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3618 "Channel::GetLocalPlayoutPosition(position=?)");
3619
3620 WebRtc_UWord32 position;
3621
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003622 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003623
3624 if (_outputFilePlayerPtr == NULL)
3625 {
3626 _engineStatisticsPtr->SetLastError(
3627 VE_INVALID_OPERATION, kTraceError,
3628 "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
3629 return -1;
3630 }
3631
3632 if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
3633 {
3634 _engineStatisticsPtr->SetLastError(
3635 VE_BAD_FILE, kTraceError,
3636 "GetLocalPlayoutPosition() failed");
3637 return -1;
3638 }
3639 positionMs = position;
3640
3641 return 0;
3642}
3643
3644int Channel::StartPlayingFileAsMicrophone(const char* fileName,
3645 const bool loop,
3646 const FileFormats format,
3647 const int startPosition,
3648 const float volumeScaling,
3649 const int stopPosition,
3650 const CodecInst* codecInst)
3651{
3652 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3653 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
3654 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
3655 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3656 startPosition, stopPosition);
3657
3658 if (_inputFilePlaying)
3659 {
3660 _engineStatisticsPtr->SetLastError(
3661 VE_ALREADY_PLAYING, kTraceWarning,
3662 "StartPlayingFileAsMicrophone() filePlayer is playing");
3663 return 0;
3664 }
3665
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003666 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003667
3668 // Destroy the old instance
3669 if (_inputFilePlayerPtr)
3670 {
3671 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3672 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3673 _inputFilePlayerPtr = NULL;
3674 }
3675
3676 // Create the instance
3677 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3678 _inputFilePlayerId, (const FileFormats)format);
3679
3680 if (_inputFilePlayerPtr == NULL)
3681 {
3682 _engineStatisticsPtr->SetLastError(
3683 VE_INVALID_ARGUMENT, kTraceError,
3684 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
3685 return -1;
3686 }
3687
3688 const WebRtc_UWord32 notificationTime(0);
3689
3690 if (_inputFilePlayerPtr->StartPlayingFile(
3691 fileName,
3692 loop,
3693 startPosition,
3694 volumeScaling,
3695 notificationTime,
3696 stopPosition,
3697 (const CodecInst*)codecInst) != 0)
3698 {
3699 _engineStatisticsPtr->SetLastError(
3700 VE_BAD_FILE, kTraceError,
3701 "StartPlayingFile() failed to start file playout");
3702 _inputFilePlayerPtr->StopPlayingFile();
3703 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3704 _inputFilePlayerPtr = NULL;
3705 return -1;
3706 }
3707 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3708 _inputFilePlaying = true;
3709
3710 return 0;
3711}
3712
3713int Channel::StartPlayingFileAsMicrophone(InStream* stream,
3714 const FileFormats format,
3715 const int startPosition,
3716 const float volumeScaling,
3717 const int stopPosition,
3718 const CodecInst* codecInst)
3719{
3720 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3721 "Channel::StartPlayingFileAsMicrophone(format=%d, "
3722 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3723 format, volumeScaling, startPosition, stopPosition);
3724
3725 if(stream == NULL)
3726 {
3727 _engineStatisticsPtr->SetLastError(
3728 VE_BAD_FILE, kTraceError,
3729 "StartPlayingFileAsMicrophone NULL as input stream");
3730 return -1;
3731 }
3732
3733 if (_inputFilePlaying)
3734 {
3735 _engineStatisticsPtr->SetLastError(
3736 VE_ALREADY_PLAYING, kTraceWarning,
3737 "StartPlayingFileAsMicrophone() is playing");
3738 return 0;
3739 }
3740
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003741 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003742
3743 // Destroy the old instance
3744 if (_inputFilePlayerPtr)
3745 {
3746 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3747 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3748 _inputFilePlayerPtr = NULL;
3749 }
3750
3751 // Create the instance
3752 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3753 _inputFilePlayerId, (const FileFormats)format);
3754
3755 if (_inputFilePlayerPtr == NULL)
3756 {
3757 _engineStatisticsPtr->SetLastError(
3758 VE_INVALID_ARGUMENT, kTraceError,
3759 "StartPlayingInputFile() filePlayer format isnot correct");
3760 return -1;
3761 }
3762
3763 const WebRtc_UWord32 notificationTime(0);
3764
3765 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3766 volumeScaling, notificationTime,
3767 stopPosition, codecInst) != 0)
3768 {
3769 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3770 "StartPlayingFile() failed to start "
3771 "file playout");
3772 _inputFilePlayerPtr->StopPlayingFile();
3773 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3774 _inputFilePlayerPtr = NULL;
3775 return -1;
3776 }
3777
3778 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3779 _inputFilePlaying = true;
3780
3781 return 0;
3782}
3783
3784int Channel::StopPlayingFileAsMicrophone()
3785{
3786 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3787 "Channel::StopPlayingFileAsMicrophone()");
3788
3789 if (!_inputFilePlaying)
3790 {
3791 _engineStatisticsPtr->SetLastError(
3792 VE_INVALID_OPERATION, kTraceWarning,
3793 "StopPlayingFileAsMicrophone() isnot playing");
3794 return 0;
3795 }
3796
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003797 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003798 if (_inputFilePlayerPtr->StopPlayingFile() != 0)
3799 {
3800 _engineStatisticsPtr->SetLastError(
3801 VE_STOP_RECORDING_FAILED, kTraceError,
3802 "StopPlayingFile() could not stop playing");
3803 return -1;
3804 }
3805 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3806 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3807 _inputFilePlayerPtr = NULL;
3808 _inputFilePlaying = false;
3809
3810 return 0;
3811}
3812
3813int Channel::IsPlayingFileAsMicrophone() const
3814{
3815 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3816 "Channel::IsPlayingFileAsMicrophone()");
3817
3818 return _inputFilePlaying;
3819}
3820
3821int Channel::ScaleFileAsMicrophonePlayout(const float scale)
3822{
3823 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3824 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
3825
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003826 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003827
3828 if (!_inputFilePlaying)
3829 {
3830 _engineStatisticsPtr->SetLastError(
3831 VE_INVALID_OPERATION, kTraceError,
3832 "ScaleFileAsMicrophonePlayout() isnot playing");
3833 return -1;
3834 }
3835
3836 if ((_inputFilePlayerPtr == NULL) ||
3837 (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
3838 {
3839 _engineStatisticsPtr->SetLastError(
3840 VE_BAD_ARGUMENT, kTraceError,
3841 "SetAudioScaling() failed to scale playout");
3842 return -1;
3843 }
3844
3845 return 0;
3846}
3847
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00003848int Channel::StartRecordingPlayout(const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +00003849 const CodecInst* codecInst)
3850{
3851 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3852 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
3853
3854 if (_outputFileRecording)
3855 {
3856 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3857 "StartRecordingPlayout() is already recording");
3858 return 0;
3859 }
3860
3861 FileFormats format;
3862 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3863 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3864
niklas.enbom@webrtc.org40197d72012-03-26 08:45:47 +00003865 if ((codecInst != NULL) &&
3866 ((codecInst->channels < 1) || (codecInst->channels > 2)))
niklase@google.com470e71d2011-07-07 08:21:25 +00003867 {
3868 _engineStatisticsPtr->SetLastError(
3869 VE_BAD_ARGUMENT, kTraceError,
3870 "StartRecordingPlayout() invalid compression");
3871 return(-1);
3872 }
3873 if(codecInst == NULL)
3874 {
3875 format = kFileFormatPcm16kHzFile;
3876 codecInst=&dummyCodec;
3877 }
3878 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3879 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3880 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3881 {
3882 format = kFileFormatWavFile;
3883 }
3884 else
3885 {
3886 format = kFileFormatCompressedFile;
3887 }
3888
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003889 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003890
3891 // Destroy the old instance
3892 if (_outputFileRecorderPtr)
3893 {
3894 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3895 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3896 _outputFileRecorderPtr = NULL;
3897 }
3898
3899 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3900 _outputFileRecorderId, (const FileFormats)format);
3901 if (_outputFileRecorderPtr == NULL)
3902 {
3903 _engineStatisticsPtr->SetLastError(
3904 VE_INVALID_ARGUMENT, kTraceError,
3905 "StartRecordingPlayout() fileRecorder format isnot correct");
3906 return -1;
3907 }
3908
3909 if (_outputFileRecorderPtr->StartRecordingAudioFile(
3910 fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
3911 {
3912 _engineStatisticsPtr->SetLastError(
3913 VE_BAD_FILE, kTraceError,
3914 "StartRecordingAudioFile() failed to start file recording");
3915 _outputFileRecorderPtr->StopRecording();
3916 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3917 _outputFileRecorderPtr = NULL;
3918 return -1;
3919 }
3920 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3921 _outputFileRecording = true;
3922
3923 return 0;
3924}
3925
3926int Channel::StartRecordingPlayout(OutStream* stream,
3927 const CodecInst* codecInst)
3928{
3929 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3930 "Channel::StartRecordingPlayout()");
3931
3932 if (_outputFileRecording)
3933 {
3934 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3935 "StartRecordingPlayout() is already recording");
3936 return 0;
3937 }
3938
3939 FileFormats format;
3940 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3941 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3942
3943 if (codecInst != NULL && codecInst->channels != 1)
3944 {
3945 _engineStatisticsPtr->SetLastError(
3946 VE_BAD_ARGUMENT, kTraceError,
3947 "StartRecordingPlayout() invalid compression");
3948 return(-1);
3949 }
3950 if(codecInst == NULL)
3951 {
3952 format = kFileFormatPcm16kHzFile;
3953 codecInst=&dummyCodec;
3954 }
3955 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3956 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3957 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3958 {
3959 format = kFileFormatWavFile;
3960 }
3961 else
3962 {
3963 format = kFileFormatCompressedFile;
3964 }
3965
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003966 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003967
3968 // Destroy the old instance
3969 if (_outputFileRecorderPtr)
3970 {
3971 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3972 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3973 _outputFileRecorderPtr = NULL;
3974 }
3975
3976 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3977 _outputFileRecorderId, (const FileFormats)format);
3978 if (_outputFileRecorderPtr == NULL)
3979 {
3980 _engineStatisticsPtr->SetLastError(
3981 VE_INVALID_ARGUMENT, kTraceError,
3982 "StartRecordingPlayout() fileRecorder format isnot correct");
3983 return -1;
3984 }
3985
3986 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
3987 notificationTime) != 0)
3988 {
3989 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3990 "StartRecordingPlayout() failed to "
3991 "start file recording");
3992 _outputFileRecorderPtr->StopRecording();
3993 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3994 _outputFileRecorderPtr = NULL;
3995 return -1;
3996 }
3997
3998 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3999 _outputFileRecording = true;
4000
4001 return 0;
4002}
4003
4004int Channel::StopRecordingPlayout()
4005{
4006 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
4007 "Channel::StopRecordingPlayout()");
4008
4009 if (!_outputFileRecording)
4010 {
4011 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
4012 "StopRecordingPlayout() isnot recording");
4013 return -1;
4014 }
4015
4016
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004017 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004018
4019 if (_outputFileRecorderPtr->StopRecording() != 0)
4020 {
4021 _engineStatisticsPtr->SetLastError(
4022 VE_STOP_RECORDING_FAILED, kTraceError,
4023 "StopRecording() could not stop recording");
4024 return(-1);
4025 }
4026 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
4027 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4028 _outputFileRecorderPtr = NULL;
4029 _outputFileRecording = false;
4030
4031 return 0;
4032}
4033
4034void
4035Channel::SetMixWithMicStatus(bool mix)
4036{
4037 _mixFileWithMicrophone=mix;
4038}
4039
4040int
4041Channel::GetSpeechOutputLevel(WebRtc_UWord32& level) const
4042{
4043 WebRtc_Word8 currentLevel = _outputAudioLevel.Level();
4044 level = static_cast<WebRtc_Word32> (currentLevel);
4045 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4046 VoEId(_instanceId,_channelId),
4047 "GetSpeechOutputLevel() => level=%u", level);
4048 return 0;
4049}
4050
4051int
4052Channel::GetSpeechOutputLevelFullRange(WebRtc_UWord32& level) const
4053{
4054 WebRtc_Word16 currentLevel = _outputAudioLevel.LevelFullRange();
4055 level = static_cast<WebRtc_Word32> (currentLevel);
4056 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4057 VoEId(_instanceId,_channelId),
4058 "GetSpeechOutputLevelFullRange() => level=%u", level);
4059 return 0;
4060}
4061
4062int
4063Channel::SetMute(bool enable)
4064{
4065 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4066 "Channel::SetMute(enable=%d)", enable);
4067 _mute = enable;
4068 return 0;
4069}
4070
4071bool
4072Channel::Mute() const
4073{
4074 return _mute;
4075}
4076
4077int
4078Channel::SetOutputVolumePan(float left, float right)
4079{
4080 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4081 "Channel::SetOutputVolumePan()");
4082 _panLeft = left;
4083 _panRight = right;
4084 return 0;
4085}
4086
4087int
4088Channel::GetOutputVolumePan(float& left, float& right) const
4089{
4090 left = _panLeft;
4091 right = _panRight;
4092 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4093 VoEId(_instanceId,_channelId),
4094 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
4095 return 0;
4096}
4097
4098int
4099Channel::SetChannelOutputVolumeScaling(float scaling)
4100{
4101 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4102 "Channel::SetChannelOutputVolumeScaling()");
4103 _outputGain = scaling;
4104 return 0;
4105}
4106
4107int
4108Channel::GetChannelOutputVolumeScaling(float& scaling) const
4109{
4110 scaling = _outputGain;
4111 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4112 VoEId(_instanceId,_channelId),
4113 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
4114 return 0;
4115}
4116
4117#ifdef WEBRTC_SRTP
4118
4119int
4120Channel::EnableSRTPSend(
4121 CipherTypes cipherType,
4122 int cipherKeyLength,
4123 AuthenticationTypes authType,
4124 int authKeyLength,
4125 int authTagLength,
4126 SecurityLevels level,
4127 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4128 bool useForRTCP)
4129{
4130 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4131 "Channel::EnableSRTPSend()");
4132
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004133 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004134
4135 if (_encrypting)
4136 {
4137 _engineStatisticsPtr->SetLastError(
4138 VE_INVALID_OPERATION, kTraceWarning,
4139 "EnableSRTPSend() encryption already enabled");
4140 return -1;
4141 }
4142
4143 if (key == NULL)
4144 {
4145 _engineStatisticsPtr->SetLastError(
4146 VE_INVALID_ARGUMENT, kTraceWarning,
4147 "EnableSRTPSend() invalid key string");
4148 return -1;
4149 }
4150
4151 if (((kEncryption == level ||
4152 kEncryptionAndAuthentication == level) &&
4153 (cipherKeyLength < kVoiceEngineMinSrtpEncryptLength ||
4154 cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength)) ||
4155 ((kAuthentication == level ||
4156 kEncryptionAndAuthentication == level) &&
4157 kAuthHmacSha1 == authType &&
4158 (authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length ||
4159 authTagLength > kVoiceEngineMaxSrtpAuthSha1Length)) ||
4160 ((kAuthentication == level ||
4161 kEncryptionAndAuthentication == level) &&
4162 kAuthNull == authType &&
4163 (authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength ||
4164 authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength)))
4165 {
4166 _engineStatisticsPtr->SetLastError(
4167 VE_INVALID_ARGUMENT, kTraceError,
4168 "EnableSRTPSend() invalid key length(s)");
4169 return -1;
4170 }
4171
4172
4173 if (_srtpModule.EnableSRTPEncrypt(
4174 !useForRTCP,
4175 (SrtpModule::CipherTypes)cipherType,
4176 cipherKeyLength,
4177 (SrtpModule::AuthenticationTypes)authType,
4178 authKeyLength, authTagLength,
4179 (SrtpModule::SecurityLevels)level,
4180 key) == -1)
4181 {
4182 _engineStatisticsPtr->SetLastError(
4183 VE_SRTP_ERROR, kTraceError,
4184 "EnableSRTPSend() failed to enable SRTP encryption");
4185 return -1;
4186 }
4187
4188 if (_encryptionPtr == NULL)
4189 {
4190 _encryptionPtr = &_srtpModule;
4191 }
4192 _encrypting = true;
4193
4194 return 0;
4195}
4196
4197int
4198Channel::DisableSRTPSend()
4199{
4200 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4201 "Channel::DisableSRTPSend()");
4202
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004203 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004204
4205 if (!_encrypting)
4206 {
4207 _engineStatisticsPtr->SetLastError(
4208 VE_INVALID_OPERATION, kTraceWarning,
4209 "DisableSRTPSend() SRTP encryption already disabled");
4210 return 0;
4211 }
4212
4213 _encrypting = false;
4214
4215 if (_srtpModule.DisableSRTPEncrypt() == -1)
4216 {
4217 _engineStatisticsPtr->SetLastError(
4218 VE_SRTP_ERROR, kTraceError,
4219 "DisableSRTPSend() failed to disable SRTP encryption");
4220 return -1;
4221 }
4222
4223 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4224 {
4225 // Both directions are disabled
4226 _encryptionPtr = NULL;
4227 }
4228
4229 return 0;
4230}
4231
4232int
4233Channel::EnableSRTPReceive(
4234 CipherTypes cipherType,
4235 int cipherKeyLength,
4236 AuthenticationTypes authType,
4237 int authKeyLength,
4238 int authTagLength,
4239 SecurityLevels level,
4240 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4241 bool useForRTCP)
4242{
4243 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4244 "Channel::EnableSRTPReceive()");
4245
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004246 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004247
4248 if (_decrypting)
4249 {
4250 _engineStatisticsPtr->SetLastError(
4251 VE_INVALID_OPERATION, kTraceWarning,
4252 "EnableSRTPReceive() SRTP decryption already enabled");
4253 return -1;
4254 }
4255
4256 if (key == NULL)
4257 {
4258 _engineStatisticsPtr->SetLastError(
4259 VE_INVALID_ARGUMENT, kTraceWarning,
4260 "EnableSRTPReceive() invalid key string");
4261 return -1;
4262 }
4263
4264 if ((((kEncryption == level) ||
4265 (kEncryptionAndAuthentication == level)) &&
4266 ((cipherKeyLength < kVoiceEngineMinSrtpEncryptLength) ||
4267 (cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength))) ||
4268 (((kAuthentication == level) ||
4269 (kEncryptionAndAuthentication == level)) &&
4270 (kAuthHmacSha1 == authType) &&
4271 ((authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length) ||
4272 (authTagLength > kVoiceEngineMaxSrtpAuthSha1Length))) ||
4273 (((kAuthentication == level) ||
4274 (kEncryptionAndAuthentication == level)) &&
4275 (kAuthNull == authType) &&
4276 ((authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength) ||
4277 (authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength))))
4278 {
4279 _engineStatisticsPtr->SetLastError(
4280 VE_INVALID_ARGUMENT, kTraceError,
4281 "EnableSRTPReceive() invalid key length(s)");
4282 return -1;
4283 }
4284
4285 if (_srtpModule.EnableSRTPDecrypt(
4286 !useForRTCP,
4287 (SrtpModule::CipherTypes)cipherType,
4288 cipherKeyLength,
4289 (SrtpModule::AuthenticationTypes)authType,
4290 authKeyLength,
4291 authTagLength,
4292 (SrtpModule::SecurityLevels)level,
4293 key) == -1)
4294 {
4295 _engineStatisticsPtr->SetLastError(
4296 VE_SRTP_ERROR, kTraceError,
4297 "EnableSRTPReceive() failed to enable SRTP decryption");
4298 return -1;
4299 }
4300
4301 if (_encryptionPtr == NULL)
4302 {
4303 _encryptionPtr = &_srtpModule;
4304 }
4305
4306 _decrypting = true;
4307
4308 return 0;
4309}
4310
4311int
4312Channel::DisableSRTPReceive()
4313{
4314 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4315 "Channel::DisableSRTPReceive()");
4316
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004317 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004318
4319 if (!_decrypting)
4320 {
4321 _engineStatisticsPtr->SetLastError(
4322 VE_INVALID_OPERATION, kTraceWarning,
4323 "DisableSRTPReceive() SRTP decryption already disabled");
4324 return 0;
4325 }
4326
4327 _decrypting = false;
4328
4329 if (_srtpModule.DisableSRTPDecrypt() == -1)
4330 {
4331 _engineStatisticsPtr->SetLastError(
4332 VE_SRTP_ERROR, kTraceError,
4333 "DisableSRTPReceive() failed to disable SRTP decryption");
4334 return -1;
4335 }
4336
4337 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4338 {
4339 _encryptionPtr = NULL;
4340 }
4341
4342 return 0;
4343}
4344
4345#endif
4346
4347int
4348Channel::RegisterExternalEncryption(Encryption& encryption)
4349{
4350 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4351 "Channel::RegisterExternalEncryption()");
4352
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004353 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004354
4355 if (_encryptionPtr)
4356 {
4357 _engineStatisticsPtr->SetLastError(
4358 VE_INVALID_OPERATION, kTraceError,
4359 "RegisterExternalEncryption() encryption already enabled");
4360 return -1;
4361 }
4362
4363 _encryptionPtr = &encryption;
4364
4365 _decrypting = true;
4366 _encrypting = true;
4367
4368 return 0;
4369}
4370
4371int
4372Channel::DeRegisterExternalEncryption()
4373{
4374 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4375 "Channel::DeRegisterExternalEncryption()");
4376
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004377 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004378
4379 if (!_encryptionPtr)
4380 {
4381 _engineStatisticsPtr->SetLastError(
4382 VE_INVALID_OPERATION, kTraceWarning,
4383 "DeRegisterExternalEncryption() encryption already disabled");
4384 return 0;
4385 }
4386
4387 _decrypting = false;
4388 _encrypting = false;
4389
4390 _encryptionPtr = NULL;
4391
4392 return 0;
4393}
4394
4395int Channel::SendTelephoneEventOutband(unsigned char eventCode,
4396 int lengthMs, int attenuationDb,
4397 bool playDtmfEvent)
4398{
4399 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4400 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
4401 playDtmfEvent);
4402
4403 _playOutbandDtmfEvent = playDtmfEvent;
4404
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004405 if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
niklase@google.com470e71d2011-07-07 08:21:25 +00004406 attenuationDb) != 0)
4407 {
4408 _engineStatisticsPtr->SetLastError(
4409 VE_SEND_DTMF_FAILED,
4410 kTraceWarning,
4411 "SendTelephoneEventOutband() failed to send event");
4412 return -1;
4413 }
4414 return 0;
4415}
4416
4417int Channel::SendTelephoneEventInband(unsigned char eventCode,
4418 int lengthMs,
4419 int attenuationDb,
4420 bool playDtmfEvent)
4421{
4422 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4423 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
4424 playDtmfEvent);
4425
4426 _playInbandDtmfEvent = playDtmfEvent;
4427 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
4428
4429 return 0;
4430}
4431
4432int
4433Channel::SetDtmfPlayoutStatus(bool enable)
4434{
4435 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4436 "Channel::SetDtmfPlayoutStatus()");
4437 if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
4438 {
4439 _engineStatisticsPtr->SetLastError(
4440 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
4441 "SetDtmfPlayoutStatus() failed to set Dtmf playout");
4442 return -1;
4443 }
4444 return 0;
4445}
4446
4447bool
4448Channel::DtmfPlayoutStatus() const
4449{
4450 return _audioCodingModule.DtmfPlayoutStatus();
4451}
4452
4453int
4454Channel::SetSendTelephoneEventPayloadType(unsigned char type)
4455{
4456 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4457 "Channel::SetSendTelephoneEventPayloadType()");
andrew@webrtc.orgf81f9f82011-08-19 22:56:22 +00004458 if (type > 127)
niklase@google.com470e71d2011-07-07 08:21:25 +00004459 {
4460 _engineStatisticsPtr->SetLastError(
4461 VE_INVALID_ARGUMENT, kTraceError,
4462 "SetSendTelephoneEventPayloadType() invalid type");
4463 return -1;
4464 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00004465 CodecInst codec;
4466 codec.plfreq = 8000;
4467 codec.pltype = type;
4468 memcpy(codec.plname, "telephone-event", 16);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004469 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004470 {
4471 _engineStatisticsPtr->SetLastError(
4472 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4473 "SetSendTelephoneEventPayloadType() failed to register send"
4474 "payload type");
4475 return -1;
4476 }
4477 _sendTelephoneEventPayloadType = type;
4478 return 0;
4479}
4480
4481int
4482Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
4483{
4484 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4485 "Channel::GetSendTelephoneEventPayloadType()");
4486 type = _sendTelephoneEventPayloadType;
4487 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4488 VoEId(_instanceId,_channelId),
4489 "GetSendTelephoneEventPayloadType() => type=%u", type);
4490 return 0;
4491}
4492
4493#ifdef WEBRTC_DTMF_DETECTION
4494
4495WebRtc_Word32
4496Channel::RegisterTelephoneEventDetection(
4497 TelephoneEventDetectionMethods detectionMethod,
4498 VoETelephoneEventObserver& observer)
4499{
4500 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4501 "Channel::RegisterTelephoneEventDetection()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004502 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004503
4504 if (_telephoneEventDetectionPtr)
4505 {
4506 _engineStatisticsPtr->SetLastError(
4507 VE_INVALID_OPERATION, kTraceError,
4508 "RegisterTelephoneEventDetection() detection already enabled");
4509 return -1;
4510 }
4511
4512 _telephoneEventDetectionPtr = &observer;
4513
4514 switch (detectionMethod)
4515 {
4516 case kInBand:
4517 _inbandTelephoneEventDetection = true;
4518 _outOfBandTelephoneEventDetecion = false;
4519 break;
4520 case kOutOfBand:
4521 _inbandTelephoneEventDetection = false;
4522 _outOfBandTelephoneEventDetecion = true;
4523 break;
4524 case kInAndOutOfBand:
4525 _inbandTelephoneEventDetection = true;
4526 _outOfBandTelephoneEventDetecion = true;
4527 break;
4528 default:
4529 _engineStatisticsPtr->SetLastError(
4530 VE_INVALID_ARGUMENT, kTraceError,
4531 "RegisterTelephoneEventDetection() invalid detection method");
4532 return -1;
4533 }
4534
4535 if (_inbandTelephoneEventDetection)
4536 {
4537 // Enable in-band Dtmf detectin in the ACM.
4538 if (_audioCodingModule.RegisterIncomingMessagesCallback(this) != 0)
4539 {
4540 _engineStatisticsPtr->SetLastError(
4541 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4542 "RegisterTelephoneEventDetection() failed to enable Dtmf "
4543 "detection");
4544 }
4545 }
4546
4547 // Enable/disable out-of-band detection of received telephone-events.
4548 // When enabled, RtpAudioFeedback::OnReceivedTelephoneEvent() will be
4549 // called two times by the RTP/RTCP module (start & end).
4550 const bool forwardToDecoder =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004551 _rtpRtcpModule->TelephoneEventForwardToDecoder();
niklase@google.com470e71d2011-07-07 08:21:25 +00004552 const bool detectEndOfTone = true;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004553 _rtpRtcpModule->SetTelephoneEventStatus(_outOfBandTelephoneEventDetecion,
niklase@google.com470e71d2011-07-07 08:21:25 +00004554 forwardToDecoder,
4555 detectEndOfTone);
4556
4557 return 0;
4558}
4559
4560int
4561Channel::DeRegisterTelephoneEventDetection()
4562{
4563 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4564 "Channel::DeRegisterTelephoneEventDetection()");
4565
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004566 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004567
4568 if (!_telephoneEventDetectionPtr)
4569 {
4570 _engineStatisticsPtr->SetLastError(
4571 VE_INVALID_OPERATION,
4572 kTraceWarning,
4573 "DeRegisterTelephoneEventDetection() detection already disabled");
4574 return 0;
4575 }
4576
4577 // Disable out-of-band event detection
4578 const bool forwardToDecoder =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004579 _rtpRtcpModule->TelephoneEventForwardToDecoder();
4580 _rtpRtcpModule->SetTelephoneEventStatus(false, forwardToDecoder);
niklase@google.com470e71d2011-07-07 08:21:25 +00004581
4582 // Disable in-band Dtmf detection
4583 _audioCodingModule.RegisterIncomingMessagesCallback(NULL);
4584
4585 _inbandTelephoneEventDetection = false;
4586 _outOfBandTelephoneEventDetecion = false;
4587 _telephoneEventDetectionPtr = NULL;
4588
4589 return 0;
4590}
4591
4592int
4593Channel::GetTelephoneEventDetectionStatus(
4594 bool& enabled,
4595 TelephoneEventDetectionMethods& detectionMethod)
4596{
4597 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4598 "Channel::GetTelephoneEventDetectionStatus()");
4599
4600 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004601 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004602 enabled = (_telephoneEventDetectionPtr != NULL);
4603 }
4604
4605 if (enabled)
4606 {
4607 if (_inbandTelephoneEventDetection && !_outOfBandTelephoneEventDetecion)
4608 detectionMethod = kInBand;
4609 else if (!_inbandTelephoneEventDetection
4610 && _outOfBandTelephoneEventDetecion)
4611 detectionMethod = kOutOfBand;
4612 else if (_inbandTelephoneEventDetection
4613 && _outOfBandTelephoneEventDetecion)
4614 detectionMethod = kInAndOutOfBand;
4615 else
4616 {
4617 assert(false);
4618 return -1;
4619 }
4620 }
4621
4622 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4623 VoEId(_instanceId, _channelId),
4624 "GetTelephoneEventDetectionStatus() => enabled=%d,"
4625 "detectionMethod=%d", enabled, detectionMethod);
4626 return 0;
4627}
4628
4629#endif // #ifdef WEBRTC_DTMF_DETECTION
4630
4631int
4632Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
4633{
4634 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4635 "Channel::UpdateRxVadDetection()");
4636
4637 int vadDecision = 1;
4638
andrew@webrtc.org63a50982012-05-02 23:56:37 +00004639 vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00004640
4641 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
4642 {
4643 OnRxVadDetected(vadDecision);
4644 _oldVadDecision = vadDecision;
4645 }
4646
4647 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4648 "Channel::UpdateRxVadDetection() => vadDecision=%d",
4649 vadDecision);
4650 return 0;
4651}
4652
4653int
4654Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
4655{
4656 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4657 "Channel::RegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004658 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004659
4660 if (_rxVadObserverPtr)
4661 {
4662 _engineStatisticsPtr->SetLastError(
4663 VE_INVALID_OPERATION, kTraceError,
4664 "RegisterRxVadObserver() observer already enabled");
4665 return -1;
4666 }
niklase@google.com470e71d2011-07-07 08:21:25 +00004667 _rxVadObserverPtr = &observer;
4668 _RxVadDetection = true;
4669 return 0;
4670}
4671
4672int
4673Channel::DeRegisterRxVadObserver()
4674{
4675 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4676 "Channel::DeRegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004677 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004678
4679 if (!_rxVadObserverPtr)
4680 {
4681 _engineStatisticsPtr->SetLastError(
4682 VE_INVALID_OPERATION, kTraceWarning,
4683 "DeRegisterRxVadObserver() observer already disabled");
4684 return 0;
4685 }
4686 _rxVadObserverPtr = NULL;
4687 _RxVadDetection = false;
4688 return 0;
4689}
4690
4691int
4692Channel::VoiceActivityIndicator(int &activity)
4693{
4694 activity = _sendFrameType;
4695
4696 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4697 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
4698 return 0;
4699}
4700
4701#ifdef WEBRTC_VOICE_ENGINE_AGC
4702
4703int
4704Channel::SetRxAgcStatus(const bool enable, const AgcModes mode)
4705{
4706 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4707 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
4708 (int)enable, (int)mode);
4709
4710 GainControl::Mode agcMode(GainControl::kFixedDigital);
4711 switch (mode)
4712 {
4713 case kAgcDefault:
4714 agcMode = GainControl::kAdaptiveDigital;
4715 break;
4716 case kAgcUnchanged:
4717 agcMode = _rxAudioProcessingModulePtr->gain_control()->mode();
4718 break;
4719 case kAgcFixedDigital:
4720 agcMode = GainControl::kFixedDigital;
4721 break;
4722 case kAgcAdaptiveDigital:
4723 agcMode =GainControl::kAdaptiveDigital;
4724 break;
4725 default:
4726 _engineStatisticsPtr->SetLastError(
4727 VE_INVALID_ARGUMENT, kTraceError,
4728 "SetRxAgcStatus() invalid Agc mode");
4729 return -1;
4730 }
4731
4732 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(agcMode) != 0)
4733 {
4734 _engineStatisticsPtr->SetLastError(
4735 VE_APM_ERROR, kTraceError,
4736 "SetRxAgcStatus() failed to set Agc mode");
4737 return -1;
4738 }
4739 if (_rxAudioProcessingModulePtr->gain_control()->Enable(enable) != 0)
4740 {
4741 _engineStatisticsPtr->SetLastError(
4742 VE_APM_ERROR, kTraceError,
4743 "SetRxAgcStatus() failed to set Agc state");
4744 return -1;
4745 }
4746
4747 _rxAgcIsEnabled = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +00004748 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4749
4750 return 0;
4751}
4752
4753int
4754Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
4755{
4756 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4757 "Channel::GetRxAgcStatus(enable=?, mode=?)");
4758
4759 bool enable = _rxAudioProcessingModulePtr->gain_control()->is_enabled();
4760 GainControl::Mode agcMode =
4761 _rxAudioProcessingModulePtr->gain_control()->mode();
4762
4763 enabled = enable;
4764
4765 switch (agcMode)
4766 {
4767 case GainControl::kFixedDigital:
4768 mode = kAgcFixedDigital;
4769 break;
4770 case GainControl::kAdaptiveDigital:
4771 mode = kAgcAdaptiveDigital;
4772 break;
4773 default:
4774 _engineStatisticsPtr->SetLastError(
4775 VE_APM_ERROR, kTraceError,
4776 "GetRxAgcStatus() invalid Agc mode");
4777 return -1;
4778 }
4779
4780 return 0;
4781}
4782
4783int
4784Channel::SetRxAgcConfig(const AgcConfig config)
4785{
4786 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4787 "Channel::SetRxAgcConfig()");
4788
4789 if (_rxAudioProcessingModulePtr->gain_control()->set_target_level_dbfs(
4790 config.targetLeveldBOv) != 0)
4791 {
4792 _engineStatisticsPtr->SetLastError(
4793 VE_APM_ERROR, kTraceError,
4794 "SetRxAgcConfig() failed to set target peak |level|"
4795 "(or envelope) of the Agc");
4796 return -1;
4797 }
4798 if (_rxAudioProcessingModulePtr->gain_control()->set_compression_gain_db(
4799 config.digitalCompressionGaindB) != 0)
4800 {
4801 _engineStatisticsPtr->SetLastError(
4802 VE_APM_ERROR, kTraceError,
4803 "SetRxAgcConfig() failed to set the range in |gain| the"
4804 " digital compression stage may apply");
4805 return -1;
4806 }
4807 if (_rxAudioProcessingModulePtr->gain_control()->enable_limiter(
4808 config.limiterEnable) != 0)
4809 {
4810 _engineStatisticsPtr->SetLastError(
4811 VE_APM_ERROR, kTraceError,
4812 "SetRxAgcConfig() failed to set hard limiter to the signal");
4813 return -1;
4814 }
4815
4816 return 0;
4817}
4818
4819int
4820Channel::GetRxAgcConfig(AgcConfig& config)
4821{
4822 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4823 "Channel::GetRxAgcConfig(config=%?)");
4824
4825 config.targetLeveldBOv =
4826 _rxAudioProcessingModulePtr->gain_control()->target_level_dbfs();
4827 config.digitalCompressionGaindB =
4828 _rxAudioProcessingModulePtr->gain_control()->compression_gain_db();
4829 config.limiterEnable =
4830 _rxAudioProcessingModulePtr->gain_control()->is_limiter_enabled();
4831
4832 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4833 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
4834 "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
4835 " limiterEnable=%d",
4836 config.targetLeveldBOv,
4837 config.digitalCompressionGaindB,
4838 config.limiterEnable);
4839
4840 return 0;
4841}
4842
4843#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
4844
4845#ifdef WEBRTC_VOICE_ENGINE_NR
4846
4847int
4848Channel::SetRxNsStatus(const bool enable, const NsModes mode)
4849{
4850 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4851 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
4852 (int)enable, (int)mode);
4853
4854 NoiseSuppression::Level nsLevel(
4855 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
4856 switch (mode)
4857 {
4858
4859 case kNsDefault:
4860 nsLevel = (NoiseSuppression::Level)
4861 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
4862 break;
4863 case kNsUnchanged:
4864 nsLevel = _rxAudioProcessingModulePtr->noise_suppression()->level();
4865 break;
4866 case kNsConference:
4867 nsLevel = NoiseSuppression::kHigh;
4868 break;
4869 case kNsLowSuppression:
4870 nsLevel = NoiseSuppression::kLow;
4871 break;
4872 case kNsModerateSuppression:
4873 nsLevel = NoiseSuppression::kModerate;
4874 break;
4875 case kNsHighSuppression:
4876 nsLevel = NoiseSuppression::kHigh;
4877 break;
4878 case kNsVeryHighSuppression:
4879 nsLevel = NoiseSuppression::kVeryHigh;
4880 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004881 }
4882
4883 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(nsLevel)
4884 != 0)
4885 {
4886 _engineStatisticsPtr->SetLastError(
4887 VE_APM_ERROR, kTraceError,
4888 "SetRxAgcStatus() failed to set Ns level");
4889 return -1;
4890 }
4891 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(enable) != 0)
4892 {
4893 _engineStatisticsPtr->SetLastError(
4894 VE_APM_ERROR, kTraceError,
4895 "SetRxAgcStatus() failed to set Agc state");
4896 return -1;
4897 }
4898
4899 _rxNsIsEnabled = enable;
4900 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4901
4902 return 0;
4903}
4904
4905int
4906Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
4907{
4908 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4909 "Channel::GetRxNsStatus(enable=?, mode=?)");
4910
4911 bool enable =
4912 _rxAudioProcessingModulePtr->noise_suppression()->is_enabled();
4913 NoiseSuppression::Level ncLevel =
4914 _rxAudioProcessingModulePtr->noise_suppression()->level();
4915
4916 enabled = enable;
4917
4918 switch (ncLevel)
4919 {
4920 case NoiseSuppression::kLow:
4921 mode = kNsLowSuppression;
4922 break;
4923 case NoiseSuppression::kModerate:
4924 mode = kNsModerateSuppression;
4925 break;
4926 case NoiseSuppression::kHigh:
4927 mode = kNsHighSuppression;
4928 break;
4929 case NoiseSuppression::kVeryHigh:
4930 mode = kNsVeryHighSuppression;
4931 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004932 }
4933
4934 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4935 VoEId(_instanceId,_channelId),
4936 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
4937 return 0;
4938}
4939
4940#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
4941
4942int
4943Channel::RegisterRTPObserver(VoERTPObserver& observer)
4944{
4945 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4946 "Channel::RegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004947 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004948
4949 if (_rtpObserverPtr)
4950 {
4951 _engineStatisticsPtr->SetLastError(
4952 VE_INVALID_OPERATION, kTraceError,
4953 "RegisterRTPObserver() observer already enabled");
4954 return -1;
4955 }
4956
4957 _rtpObserverPtr = &observer;
4958 _rtpObserver = true;
4959
4960 return 0;
4961}
4962
4963int
4964Channel::DeRegisterRTPObserver()
4965{
4966 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4967 "Channel::DeRegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004968 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004969
4970 if (!_rtpObserverPtr)
4971 {
4972 _engineStatisticsPtr->SetLastError(
4973 VE_INVALID_OPERATION, kTraceWarning,
4974 "DeRegisterRTPObserver() observer already disabled");
4975 return 0;
4976 }
4977
4978 _rtpObserver = false;
4979 _rtpObserverPtr = NULL;
4980
4981 return 0;
4982}
4983
4984int
4985Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
4986{
4987 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4988 "Channel::RegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004989 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004990
4991 if (_rtcpObserverPtr)
4992 {
4993 _engineStatisticsPtr->SetLastError(
4994 VE_INVALID_OPERATION, kTraceError,
4995 "RegisterRTCPObserver() observer already enabled");
4996 return -1;
4997 }
4998
4999 _rtcpObserverPtr = &observer;
5000 _rtcpObserver = true;
5001
5002 return 0;
5003}
5004
5005int
5006Channel::DeRegisterRTCPObserver()
5007{
5008 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5009 "Channel::DeRegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005010 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005011
5012 if (!_rtcpObserverPtr)
5013 {
5014 _engineStatisticsPtr->SetLastError(
5015 VE_INVALID_OPERATION, kTraceWarning,
5016 "DeRegisterRTCPObserver() observer already disabled");
5017 return 0;
5018 }
5019
5020 _rtcpObserver = false;
5021 _rtcpObserverPtr = NULL;
5022
5023 return 0;
5024}
5025
5026int
5027Channel::SetLocalSSRC(unsigned int ssrc)
5028{
5029 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5030 "Channel::SetLocalSSRC()");
5031 if (_sending)
5032 {
5033 _engineStatisticsPtr->SetLastError(
5034 VE_ALREADY_SENDING, kTraceError,
5035 "SetLocalSSRC() already sending");
5036 return -1;
5037 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005038 if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005039 {
5040 _engineStatisticsPtr->SetLastError(
5041 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5042 "SetLocalSSRC() failed to set SSRC");
5043 return -1;
5044 }
5045 return 0;
5046}
5047
5048int
5049Channel::GetLocalSSRC(unsigned int& ssrc)
5050{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005051 ssrc = _rtpRtcpModule->SSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00005052 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5053 VoEId(_instanceId,_channelId),
5054 "GetLocalSSRC() => ssrc=%lu", ssrc);
5055 return 0;
5056}
5057
5058int
5059Channel::GetRemoteSSRC(unsigned int& ssrc)
5060{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005061 ssrc = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00005062 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5063 VoEId(_instanceId,_channelId),
5064 "GetRemoteSSRC() => ssrc=%lu", ssrc);
5065 return 0;
5066}
5067
5068int
5069Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
5070{
5071 if (arrCSRC == NULL)
5072 {
5073 _engineStatisticsPtr->SetLastError(
5074 VE_INVALID_ARGUMENT, kTraceError,
5075 "GetRemoteCSRCs() invalid array argument");
5076 return -1;
5077 }
5078 WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize];
5079 WebRtc_Word32 CSRCs(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005080 CSRCs = _rtpRtcpModule->CSRCs(arrOfCSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00005081 if (CSRCs > 0)
5082 {
5083 memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(WebRtc_UWord32));
5084 for (int i = 0; i < (int) CSRCs; i++)
5085 {
5086 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5087 VoEId(_instanceId, _channelId),
5088 "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
5089 }
5090 } else
5091 {
5092 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5093 VoEId(_instanceId, _channelId),
5094 "GetRemoteCSRCs() => list is empty!");
5095 }
5096 return CSRCs;
5097}
5098
5099int
5100Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
5101{
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005102 if (_rtpAudioProc.get() == NULL)
5103 {
5104 _rtpAudioProc.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
5105 _channelId)));
5106 if (_rtpAudioProc.get() == NULL)
5107 {
5108 _engineStatisticsPtr->SetLastError(VE_NO_MEMORY, kTraceCritical,
5109 "Failed to create AudioProcessing");
5110 return -1;
5111 }
5112 }
5113
5114 if (_rtpAudioProc->level_estimator()->Enable(enable) !=
5115 AudioProcessing::kNoError)
5116 {
5117 _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceWarning,
5118 "Failed to enable AudioProcessing::level_estimator()");
5119 }
5120
niklase@google.com470e71d2011-07-07 08:21:25 +00005121 _includeAudioLevelIndication = enable;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005122 return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
niklase@google.com470e71d2011-07-07 08:21:25 +00005123}
5124int
5125Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
5126{
5127 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5128 VoEId(_instanceId,_channelId),
5129 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
5130 enabled, ID);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005131 return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
niklase@google.com470e71d2011-07-07 08:21:25 +00005132}
5133
5134int
5135Channel::SetRTCPStatus(bool enable)
5136{
5137 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5138 "Channel::SetRTCPStatus()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005139 if (_rtpRtcpModule->SetRTCPStatus(enable ?
niklase@google.com470e71d2011-07-07 08:21:25 +00005140 kRtcpCompound : kRtcpOff) != 0)
5141 {
5142 _engineStatisticsPtr->SetLastError(
5143 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5144 "SetRTCPStatus() failed to set RTCP status");
5145 return -1;
5146 }
5147 return 0;
5148}
5149
5150int
5151Channel::GetRTCPStatus(bool& enabled)
5152{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005153 RTCPMethod method = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00005154 enabled = (method != kRtcpOff);
5155 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5156 VoEId(_instanceId,_channelId),
5157 "GetRTCPStatus() => enabled=%d", enabled);
5158 return 0;
5159}
5160
5161int
5162Channel::SetRTCP_CNAME(const char cName[256])
5163{
5164 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5165 "Channel::SetRTCP_CNAME()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005166 if (_rtpRtcpModule->SetCNAME(cName) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005167 {
5168 _engineStatisticsPtr->SetLastError(
5169 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5170 "SetRTCP_CNAME() failed to set RTCP CNAME");
5171 return -1;
5172 }
5173 return 0;
5174}
5175
5176int
5177Channel::GetRTCP_CNAME(char cName[256])
5178{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005179 if (_rtpRtcpModule->CNAME(cName) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005180 {
5181 _engineStatisticsPtr->SetLastError(
5182 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5183 "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
5184 return -1;
5185 }
5186 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5187 VoEId(_instanceId, _channelId),
5188 "GetRTCP_CNAME() => cName=%s", cName);
5189 return 0;
5190}
5191
5192int
5193Channel::GetRemoteRTCP_CNAME(char cName[256])
5194{
5195 if (cName == NULL)
5196 {
5197 _engineStatisticsPtr->SetLastError(
5198 VE_INVALID_ARGUMENT, kTraceError,
5199 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
5200 return -1;
5201 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00005202 char cname[RTCP_CNAME_SIZE];
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005203 const WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5204 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005205 {
5206 _engineStatisticsPtr->SetLastError(
5207 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
5208 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
5209 return -1;
5210 }
5211 strcpy(cName, cname);
5212 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5213 VoEId(_instanceId, _channelId),
5214 "GetRemoteRTCP_CNAME() => cName=%s", cName);
5215 return 0;
5216}
5217
5218int
5219Channel::GetRemoteRTCPData(
5220 unsigned int& NTPHigh,
5221 unsigned int& NTPLow,
5222 unsigned int& timestamp,
5223 unsigned int& playoutTimestamp,
5224 unsigned int* jitter,
5225 unsigned short* fractionLost)
5226{
5227 // --- Information from sender info in received Sender Reports
5228
5229 RTCPSenderInfo senderInfo;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005230 if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005231 {
5232 _engineStatisticsPtr->SetLastError(
5233 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005234 "GetRemoteRTCPData() failed to retrieve sender info for remote "
niklase@google.com470e71d2011-07-07 08:21:25 +00005235 "side");
5236 return -1;
5237 }
5238
5239 // We only utilize 12 out of 20 bytes in the sender info (ignores packet
5240 // and octet count)
5241 NTPHigh = senderInfo.NTPseconds;
5242 NTPLow = senderInfo.NTPfraction;
5243 timestamp = senderInfo.RTPtimeStamp;
5244
5245 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5246 VoEId(_instanceId, _channelId),
5247 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
5248 "timestamp=%lu",
5249 NTPHigh, NTPLow, timestamp);
5250
5251 // --- Locally derived information
5252
5253 // This value is updated on each incoming RTCP packet (0 when no packet
5254 // has been received)
5255 playoutTimestamp = _playoutTimeStampRTCP;
5256
5257 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5258 VoEId(_instanceId, _channelId),
5259 "GetRemoteRTCPData() => playoutTimestamp=%lu",
5260 _playoutTimeStampRTCP);
5261
5262 if (NULL != jitter || NULL != fractionLost)
5263 {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005264 // Get all RTCP receiver report blocks that have been received on this
5265 // channel. If we receive RTP packets from a remote source we know the
5266 // remote SSRC and use the report block from him.
5267 // Otherwise use the first report block.
5268 std::vector<RTCPReportBlock> remote_stats;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005269 if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005270 remote_stats.empty()) {
5271 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5272 VoEId(_instanceId, _channelId),
5273 "GetRemoteRTCPData() failed to measure statistics due"
5274 " to lack of received RTP and/or RTCP packets");
5275 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00005276 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005277
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005278 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005279 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
5280 for (; it != remote_stats.end(); ++it) {
5281 if (it->remoteSSRC == remoteSSRC)
5282 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00005283 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005284
5285 if (it == remote_stats.end()) {
5286 // If we have not received any RTCP packets from this SSRC it probably
5287 // means that we have not received any RTP packets.
5288 // Use the first received report block instead.
5289 it = remote_stats.begin();
5290 remoteSSRC = it->remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00005291 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005292
xians@webrtc.org79af7342012-01-31 12:22:14 +00005293 if (jitter) {
5294 *jitter = it->jitter;
5295 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5296 VoEId(_instanceId, _channelId),
5297 "GetRemoteRTCPData() => jitter = %lu", *jitter);
5298 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005299
xians@webrtc.org79af7342012-01-31 12:22:14 +00005300 if (fractionLost) {
5301 *fractionLost = it->fractionLost;
5302 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5303 VoEId(_instanceId, _channelId),
5304 "GetRemoteRTCPData() => fractionLost = %lu",
5305 *fractionLost);
5306 }
niklase@google.com470e71d2011-07-07 08:21:25 +00005307 }
5308 return 0;
5309}
5310
5311int
5312Channel::SendApplicationDefinedRTCPPacket(const unsigned char subType,
5313 unsigned int name,
5314 const char* data,
5315 unsigned short dataLengthInBytes)
5316{
5317 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5318 "Channel::SendApplicationDefinedRTCPPacket()");
5319 if (!_sending)
5320 {
5321 _engineStatisticsPtr->SetLastError(
5322 VE_NOT_SENDING, kTraceError,
5323 "SendApplicationDefinedRTCPPacket() not sending");
5324 return -1;
5325 }
5326 if (NULL == data)
5327 {
5328 _engineStatisticsPtr->SetLastError(
5329 VE_INVALID_ARGUMENT, kTraceError,
5330 "SendApplicationDefinedRTCPPacket() invalid data value");
5331 return -1;
5332 }
5333 if (dataLengthInBytes % 4 != 0)
5334 {
5335 _engineStatisticsPtr->SetLastError(
5336 VE_INVALID_ARGUMENT, kTraceError,
5337 "SendApplicationDefinedRTCPPacket() invalid length value");
5338 return -1;
5339 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005340 RTCPMethod status = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00005341 if (status == kRtcpOff)
5342 {
5343 _engineStatisticsPtr->SetLastError(
5344 VE_RTCP_ERROR, kTraceError,
5345 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
5346 return -1;
5347 }
5348
5349 // Create and schedule the RTCP APP packet for transmission
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005350 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
niklase@google.com470e71d2011-07-07 08:21:25 +00005351 subType,
5352 name,
5353 (const unsigned char*) data,
5354 dataLengthInBytes) != 0)
5355 {
5356 _engineStatisticsPtr->SetLastError(
5357 VE_SEND_ERROR, kTraceError,
5358 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
5359 return -1;
5360 }
5361 return 0;
5362}
5363
5364int
5365Channel::GetRTPStatistics(
5366 unsigned int& averageJitterMs,
5367 unsigned int& maxJitterMs,
5368 unsigned int& discardedPackets)
5369{
5370 WebRtc_UWord8 fraction_lost(0);
5371 WebRtc_UWord32 cum_lost(0);
5372 WebRtc_UWord32 ext_max(0);
5373 WebRtc_UWord32 jitter(0);
5374 WebRtc_UWord32 max_jitter(0);
5375
5376 // The jitter statistics is updated for each received RTP packet and is
5377 // based on received packets.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005378 if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
niklase@google.com470e71d2011-07-07 08:21:25 +00005379 &cum_lost,
5380 &ext_max,
5381 &jitter,
5382 &max_jitter) != 0)
5383 {
5384 _engineStatisticsPtr->SetLastError(
5385 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005386 "GetRTPStatistics() failed to read RTP statistics from the "
niklase@google.com470e71d2011-07-07 08:21:25 +00005387 "RTP/RTCP module");
5388 }
5389
5390 const WebRtc_Word32 playoutFrequency =
5391 _audioCodingModule.PlayoutFrequency();
5392 if (playoutFrequency > 0)
5393 {
5394 // Scale RTP statistics given the current playout frequency
5395 maxJitterMs = max_jitter / (playoutFrequency / 1000);
5396 averageJitterMs = jitter / (playoutFrequency / 1000);
5397 }
5398
5399 discardedPackets = _numberOfDiscardedPackets;
5400
5401 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5402 VoEId(_instanceId, _channelId),
5403 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005404 " discardedPackets = %lu)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005405 averageJitterMs, maxJitterMs, discardedPackets);
5406 return 0;
5407}
5408
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00005409int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
5410 if (sender_info == NULL) {
5411 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5412 "GetRemoteRTCPSenderInfo() invalid sender_info.");
5413 return -1;
5414 }
5415
5416 // Get the sender info from the latest received RTCP Sender Report.
5417 RTCPSenderInfo rtcp_sender_info;
5418 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
5419 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5420 "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
5421 return -1;
5422 }
5423
5424 sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
5425 sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
5426 sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
5427 sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
5428 sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
5429 return 0;
5430}
5431
5432int Channel::GetRemoteRTCPReportBlocks(
5433 std::vector<ReportBlock>* report_blocks) {
5434 if (report_blocks == NULL) {
5435 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5436 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
5437 return -1;
5438 }
5439
5440 // Get the report blocks from the latest received RTCP Sender or Receiver
5441 // Report. Each element in the vector contains the sender's SSRC and a
5442 // report block according to RFC 3550.
5443 std::vector<RTCPReportBlock> rtcp_report_blocks;
5444 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
5445 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5446 "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
5447 return -1;
5448 }
5449
5450 if (rtcp_report_blocks.empty())
5451 return 0;
5452
5453 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
5454 for (; it != rtcp_report_blocks.end(); ++it) {
5455 ReportBlock report_block;
5456 report_block.sender_SSRC = it->remoteSSRC;
5457 report_block.source_SSRC = it->sourceSSRC;
5458 report_block.fraction_lost = it->fractionLost;
5459 report_block.cumulative_num_packets_lost = it->cumulativeLost;
5460 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
5461 report_block.interarrival_jitter = it->jitter;
5462 report_block.last_SR_timestamp = it->lastSR;
5463 report_block.delay_since_last_SR = it->delaySinceLastSR;
5464 report_blocks->push_back(report_block);
5465 }
5466 return 0;
5467}
5468
niklase@google.com470e71d2011-07-07 08:21:25 +00005469int
5470Channel::GetRTPStatistics(CallStatistics& stats)
5471{
5472 WebRtc_UWord8 fraction_lost(0);
5473 WebRtc_UWord32 cum_lost(0);
5474 WebRtc_UWord32 ext_max(0);
5475 WebRtc_UWord32 jitter(0);
5476 WebRtc_UWord32 max_jitter(0);
5477
5478 // --- Part one of the final structure (four values)
5479
5480 // The jitter statistics is updated for each received RTP packet and is
5481 // based on received packets.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005482 if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
niklase@google.com470e71d2011-07-07 08:21:25 +00005483 &cum_lost,
5484 &ext_max,
5485 &jitter,
5486 &max_jitter) != 0)
5487 {
5488 _engineStatisticsPtr->SetLastError(
5489 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5490 "GetRTPStatistics() failed to read RTP statistics from the "
5491 "RTP/RTCP module");
5492 }
5493
5494 stats.fractionLost = fraction_lost;
5495 stats.cumulativeLost = cum_lost;
5496 stats.extendedMax = ext_max;
5497 stats.jitterSamples = jitter;
5498
5499 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5500 VoEId(_instanceId, _channelId),
5501 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005502 " extendedMax=%lu, jitterSamples=%li)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005503 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
5504 stats.jitterSamples);
5505
5506 // --- Part two of the final structure (one value)
5507
5508 WebRtc_UWord16 RTT(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005509 RTCPMethod method = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00005510 if (method == kRtcpOff)
5511 {
5512 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5513 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005514 "GetRTPStatistics() RTCP is disabled => valid RTT "
niklase@google.com470e71d2011-07-07 08:21:25 +00005515 "measurements cannot be retrieved");
5516 } else
5517 {
5518 // The remote SSRC will be zero if no RTP packet has been received.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005519 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00005520 if (remoteSSRC > 0)
5521 {
5522 WebRtc_UWord16 avgRTT(0);
5523 WebRtc_UWord16 maxRTT(0);
5524 WebRtc_UWord16 minRTT(0);
5525
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005526 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
niklase@google.com470e71d2011-07-07 08:21:25 +00005527 != 0)
5528 {
5529 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5530 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005531 "GetRTPStatistics() failed to retrieve RTT from "
niklase@google.com470e71d2011-07-07 08:21:25 +00005532 "the RTP/RTCP module");
5533 }
5534 } else
5535 {
5536 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5537 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005538 "GetRTPStatistics() failed to measure RTT since no "
niklase@google.com470e71d2011-07-07 08:21:25 +00005539 "RTP packets have been received yet");
5540 }
5541 }
5542
5543 stats.rttMs = static_cast<int> (RTT);
5544
5545 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5546 VoEId(_instanceId, _channelId),
5547 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
5548
5549 // --- Part three of the final structure (four values)
5550
5551 WebRtc_UWord32 bytesSent(0);
5552 WebRtc_UWord32 packetsSent(0);
5553 WebRtc_UWord32 bytesReceived(0);
5554 WebRtc_UWord32 packetsReceived(0);
5555
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005556 if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
niklase@google.com470e71d2011-07-07 08:21:25 +00005557 &packetsSent,
5558 &bytesReceived,
5559 &packetsReceived) != 0)
5560 {
5561 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5562 VoEId(_instanceId, _channelId),
5563 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005564 " output will not be complete");
niklase@google.com470e71d2011-07-07 08:21:25 +00005565 }
5566
5567 stats.bytesSent = bytesSent;
5568 stats.packetsSent = packetsSent;
5569 stats.bytesReceived = bytesReceived;
5570 stats.packetsReceived = packetsReceived;
5571
5572 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5573 VoEId(_instanceId, _channelId),
5574 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005575 " bytesReceived=%d, packetsReceived=%d)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005576 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
5577 stats.packetsReceived);
5578
5579 return 0;
5580}
5581
5582int
5583Channel::SetFECStatus(bool enable, int redPayloadtype)
5584{
5585 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5586 "Channel::SetFECStatus()");
5587
5588 CodecInst codec;
5589
5590 // Get default RED settings from the ACM database
5591 bool foundRED(false);
5592 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
5593 for (int idx = 0; (!foundRED && idx < nSupportedCodecs); idx++)
5594 {
5595 _audioCodingModule.Codec(idx, codec);
5596 if (!STR_CASE_CMP(codec.plname, "RED"))
5597 {
5598 foundRED = true;
5599 }
5600 }
5601 if (!foundRED)
5602 {
5603 _engineStatisticsPtr->SetLastError(
5604 VE_CODEC_ERROR, kTraceError,
5605 "SetFECStatus() RED is not supported");
5606 return -1;
5607 }
5608
5609 if (redPayloadtype != -1)
5610 {
5611 codec.pltype = redPayloadtype;
5612 }
5613
5614 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
5615 {
5616 _engineStatisticsPtr->SetLastError(
5617 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5618 "SetFECStatus() RED registration in ACM module failed");
5619 return -1;
5620 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005621 if (_rtpRtcpModule->SetSendREDPayloadType(codec.pltype) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005622 {
5623 _engineStatisticsPtr->SetLastError(
5624 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5625 "SetFECStatus() RED registration in RTP/RTCP module failed");
5626 return -1;
5627 }
5628 if (_audioCodingModule.SetFECStatus(enable) != 0)
5629 {
5630 _engineStatisticsPtr->SetLastError(
5631 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5632 "SetFECStatus() failed to set FEC state in the ACM");
5633 return -1;
5634 }
5635 return 0;
5636}
5637
5638int
5639Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
5640{
5641 enabled = _audioCodingModule.FECStatus();
5642 if (enabled)
5643 {
5644 WebRtc_Word8 payloadType(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005645 if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005646 {
5647 _engineStatisticsPtr->SetLastError(
5648 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5649 "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
5650 "module");
5651 return -1;
5652 }
5653 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5654 VoEId(_instanceId, _channelId),
5655 "GetFECStatus() => enabled=%d, redPayloadtype=%d",
5656 enabled, redPayloadtype);
5657 return 0;
5658 }
5659 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5660 VoEId(_instanceId, _channelId),
5661 "GetFECStatus() => enabled=%d", enabled);
5662 return 0;
5663}
5664
5665int
niklase@google.com470e71d2011-07-07 08:21:25 +00005666Channel::StartRTPDump(const char fileNameUTF8[1024],
5667 RTPDirections direction)
5668{
5669 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5670 "Channel::StartRTPDump()");
5671 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5672 {
5673 _engineStatisticsPtr->SetLastError(
5674 VE_INVALID_ARGUMENT, kTraceError,
5675 "StartRTPDump() invalid RTP direction");
5676 return -1;
5677 }
5678 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5679 &_rtpDumpIn : &_rtpDumpOut;
5680 if (rtpDumpPtr == NULL)
5681 {
5682 assert(false);
5683 return -1;
5684 }
5685 if (rtpDumpPtr->IsActive())
5686 {
5687 rtpDumpPtr->Stop();
5688 }
5689 if (rtpDumpPtr->Start(fileNameUTF8) != 0)
5690 {
5691 _engineStatisticsPtr->SetLastError(
5692 VE_BAD_FILE, kTraceError,
5693 "StartRTPDump() failed to create file");
5694 return -1;
5695 }
5696 return 0;
5697}
5698
5699int
5700Channel::StopRTPDump(RTPDirections direction)
5701{
5702 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5703 "Channel::StopRTPDump()");
5704 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5705 {
5706 _engineStatisticsPtr->SetLastError(
5707 VE_INVALID_ARGUMENT, kTraceError,
5708 "StopRTPDump() invalid RTP direction");
5709 return -1;
5710 }
5711 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5712 &_rtpDumpIn : &_rtpDumpOut;
5713 if (rtpDumpPtr == NULL)
5714 {
5715 assert(false);
5716 return -1;
5717 }
5718 if (!rtpDumpPtr->IsActive())
5719 {
5720 return 0;
5721 }
5722 return rtpDumpPtr->Stop();
5723}
5724
5725bool
5726Channel::RTPDumpIsActive(RTPDirections direction)
5727{
5728 if ((direction != kRtpIncoming) &&
5729 (direction != kRtpOutgoing))
5730 {
5731 _engineStatisticsPtr->SetLastError(
5732 VE_INVALID_ARGUMENT, kTraceError,
5733 "RTPDumpIsActive() invalid RTP direction");
5734 return false;
5735 }
5736 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5737 &_rtpDumpIn : &_rtpDumpOut;
5738 return rtpDumpPtr->IsActive();
5739}
5740
5741int
5742Channel::InsertExtraRTPPacket(unsigned char payloadType,
5743 bool markerBit,
5744 const char* payloadData,
5745 unsigned short payloadSize)
5746{
5747 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5748 "Channel::InsertExtraRTPPacket()");
5749 if (payloadType > 127)
5750 {
5751 _engineStatisticsPtr->SetLastError(
5752 VE_INVALID_PLTYPE, kTraceError,
5753 "InsertExtraRTPPacket() invalid payload type");
5754 return -1;
5755 }
5756 if (payloadData == NULL)
5757 {
5758 _engineStatisticsPtr->SetLastError(
5759 VE_INVALID_ARGUMENT, kTraceError,
5760 "InsertExtraRTPPacket() invalid payload data");
5761 return -1;
5762 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005763 if (payloadSize > _rtpRtcpModule->MaxDataPayloadLength())
niklase@google.com470e71d2011-07-07 08:21:25 +00005764 {
5765 _engineStatisticsPtr->SetLastError(
5766 VE_INVALID_ARGUMENT, kTraceError,
5767 "InsertExtraRTPPacket() invalid payload size");
5768 return -1;
5769 }
5770 if (!_sending)
5771 {
5772 _engineStatisticsPtr->SetLastError(
5773 VE_NOT_SENDING, kTraceError,
5774 "InsertExtraRTPPacket() not sending");
5775 return -1;
5776 }
5777
5778 // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
5779 // Transport::SendPacket() will be called by the module when the RTP packet
5780 // is created.
5781 // The call to SendOutgoingData() does *not* modify the timestamp and
5782 // payloadtype to ensure that the RTP module generates a valid RTP packet
5783 // (user might utilize a non-registered payload type).
5784 // The marker bit and payload type will be replaced just before the actual
5785 // transmission, i.e., the actual modification is done *after* the RTP
5786 // module has delivered its RTP packet back to the VoE.
5787 // We will use the stored values above when the packet is modified
5788 // (see Channel::SendPacket()).
5789
5790 _extraPayloadType = payloadType;
5791 _extraMarkerBit = markerBit;
5792 _insertExtraRTPPacket = true;
5793
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005794 if (_rtpRtcpModule->SendOutgoingData(kAudioFrameSpeech,
niklase@google.com470e71d2011-07-07 08:21:25 +00005795 _lastPayloadType,
5796 _lastLocalTimeStamp,
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +00005797 // Leaving the time when this frame was
5798 // received from the capture device as
5799 // undefined for voice for now.
5800 -1,
niklase@google.com470e71d2011-07-07 08:21:25 +00005801 (const WebRtc_UWord8*) payloadData,
5802 payloadSize) != 0)
5803 {
5804 _engineStatisticsPtr->SetLastError(
5805 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5806 "InsertExtraRTPPacket() failed to send extra RTP packet");
5807 return -1;
5808 }
5809
5810 return 0;
5811}
5812
5813WebRtc_UWord32
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005814Channel::Demultiplex(const AudioFrame& audioFrame)
niklase@google.com470e71d2011-07-07 08:21:25 +00005815{
5816 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005817 "Channel::Demultiplex()");
niklase@google.com470e71d2011-07-07 08:21:25 +00005818 _audioFrame = audioFrame;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005819 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00005820 return 0;
5821}
5822
5823WebRtc_UWord32
xians@google.com0b0665a2011-08-08 08:18:44 +00005824Channel::PrepareEncodeAndSend(int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00005825{
5826 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5827 "Channel::PrepareEncodeAndSend()");
5828
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005829 if (_audioFrame.samples_per_channel_ == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005830 {
5831 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5832 "Channel::PrepareEncodeAndSend() invalid audio frame");
5833 return -1;
5834 }
5835
5836 if (_inputFilePlaying)
5837 {
5838 MixOrReplaceAudioWithFile(mixingFrequency);
5839 }
5840
5841 if (_mute)
5842 {
5843 AudioFrameOperations::Mute(_audioFrame);
5844 }
5845
5846 if (_inputExternalMedia)
5847 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005848 CriticalSectionScoped cs(&_callbackCritSect);
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005849 const bool isStereo = (_audioFrame.num_channels_ == 2);
niklase@google.com470e71d2011-07-07 08:21:25 +00005850 if (_inputExternalMediaCallbackPtr)
5851 {
5852 _inputExternalMediaCallbackPtr->Process(
5853 _channelId,
5854 kRecordingPerChannel,
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005855 (WebRtc_Word16*)_audioFrame.data_,
5856 _audioFrame.samples_per_channel_,
5857 _audioFrame.sample_rate_hz_,
niklase@google.com470e71d2011-07-07 08:21:25 +00005858 isStereo);
5859 }
5860 }
5861
5862 InsertInbandDtmfTone();
5863
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005864 if (_includeAudioLevelIndication)
5865 {
5866 assert(_rtpAudioProc.get() != NULL);
5867
5868 // Check if settings need to be updated.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005869 if (_rtpAudioProc->sample_rate_hz() != _audioFrame.sample_rate_hz_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005870 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005871 if (_rtpAudioProc->set_sample_rate_hz(_audioFrame.sample_rate_hz_) !=
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005872 AudioProcessing::kNoError)
5873 {
5874 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5875 VoEId(_instanceId, _channelId),
5876 "Error setting AudioProcessing sample rate");
5877 return -1;
5878 }
5879 }
5880
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005881 if (_rtpAudioProc->num_input_channels() != _audioFrame.num_channels_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005882 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005883 if (_rtpAudioProc->set_num_channels(_audioFrame.num_channels_,
5884 _audioFrame.num_channels_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005885 != AudioProcessing::kNoError)
5886 {
5887 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5888 VoEId(_instanceId, _channelId),
5889 "Error setting AudioProcessing channels");
5890 return -1;
5891 }
5892 }
5893
5894 // Performs level analysis only; does not affect the signal.
5895 _rtpAudioProc->ProcessStream(&_audioFrame);
5896 }
5897
niklase@google.com470e71d2011-07-07 08:21:25 +00005898 return 0;
5899}
5900
5901WebRtc_UWord32
5902Channel::EncodeAndSend()
5903{
5904 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5905 "Channel::EncodeAndSend()");
5906
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005907 assert(_audioFrame.num_channels_ <= 2);
5908 if (_audioFrame.samples_per_channel_ == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005909 {
5910 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5911 "Channel::EncodeAndSend() invalid audio frame");
5912 return -1;
5913 }
5914
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005915 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00005916
5917 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
5918
5919 // The ACM resamples internally.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005920 _audioFrame.timestamp_ = _timeStamp;
niklase@google.com470e71d2011-07-07 08:21:25 +00005921 if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
5922 {
5923 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
5924 "Channel::EncodeAndSend() ACM encoding failed");
5925 return -1;
5926 }
5927
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005928 _timeStamp += _audioFrame.samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +00005929
5930 // --- Encode if complete frame is ready
5931
5932 // This call will trigger AudioPacketizationCallback::SendData if encoding
5933 // is done and payload is ready for packetization and transmission.
5934 return _audioCodingModule.Process();
5935}
5936
5937int Channel::RegisterExternalMediaProcessing(
5938 ProcessingTypes type,
5939 VoEMediaProcess& processObject)
5940{
5941 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5942 "Channel::RegisterExternalMediaProcessing()");
5943
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005944 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005945
5946 if (kPlaybackPerChannel == type)
5947 {
5948 if (_outputExternalMediaCallbackPtr)
5949 {
5950 _engineStatisticsPtr->SetLastError(
5951 VE_INVALID_OPERATION, kTraceError,
5952 "Channel::RegisterExternalMediaProcessing() "
5953 "output external media already enabled");
5954 return -1;
5955 }
5956 _outputExternalMediaCallbackPtr = &processObject;
5957 _outputExternalMedia = true;
5958 }
5959 else if (kRecordingPerChannel == type)
5960 {
5961 if (_inputExternalMediaCallbackPtr)
5962 {
5963 _engineStatisticsPtr->SetLastError(
5964 VE_INVALID_OPERATION, kTraceError,
5965 "Channel::RegisterExternalMediaProcessing() "
5966 "output external media already enabled");
5967 return -1;
5968 }
5969 _inputExternalMediaCallbackPtr = &processObject;
5970 _inputExternalMedia = true;
5971 }
5972 return 0;
5973}
5974
5975int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
5976{
5977 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5978 "Channel::DeRegisterExternalMediaProcessing()");
5979
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005980 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005981
5982 if (kPlaybackPerChannel == type)
5983 {
5984 if (!_outputExternalMediaCallbackPtr)
5985 {
5986 _engineStatisticsPtr->SetLastError(
5987 VE_INVALID_OPERATION, kTraceWarning,
5988 "Channel::DeRegisterExternalMediaProcessing() "
5989 "output external media already disabled");
5990 return 0;
5991 }
5992 _outputExternalMedia = false;
5993 _outputExternalMediaCallbackPtr = NULL;
5994 }
5995 else if (kRecordingPerChannel == type)
5996 {
5997 if (!_inputExternalMediaCallbackPtr)
5998 {
5999 _engineStatisticsPtr->SetLastError(
6000 VE_INVALID_OPERATION, kTraceWarning,
6001 "Channel::DeRegisterExternalMediaProcessing() "
6002 "input external media already disabled");
6003 return 0;
6004 }
6005 _inputExternalMedia = false;
6006 _inputExternalMediaCallbackPtr = NULL;
6007 }
6008
6009 return 0;
6010}
6011
6012int
6013Channel::ResetRTCPStatistics()
6014{
6015 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6016 "Channel::ResetRTCPStatistics()");
6017 WebRtc_UWord32 remoteSSRC(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006018 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
6019 return _rtpRtcpModule->ResetRTT(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00006020}
6021
6022int
6023Channel::GetRoundTripTimeSummary(StatVal& delaysMs) const
6024{
6025 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6026 "Channel::GetRoundTripTimeSummary()");
6027 // Override default module outputs for the case when RTCP is disabled.
6028 // This is done to ensure that we are backward compatible with the
6029 // VoiceEngine where we did not use RTP/RTCP module.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006030 if (!_rtpRtcpModule->RTCP())
niklase@google.com470e71d2011-07-07 08:21:25 +00006031 {
6032 delaysMs.min = -1;
6033 delaysMs.max = -1;
6034 delaysMs.average = -1;
6035 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6036 "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
6037 " valid RTT measurements cannot be retrieved");
6038 return 0;
6039 }
6040
6041 WebRtc_UWord32 remoteSSRC;
6042 WebRtc_UWord16 RTT;
6043 WebRtc_UWord16 avgRTT;
6044 WebRtc_UWord16 maxRTT;
6045 WebRtc_UWord16 minRTT;
6046 // The remote SSRC will be zero if no RTP packet has been received.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006047 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00006048 if (remoteSSRC == 0)
6049 {
6050 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6051 "Channel::GetRoundTripTimeSummary() unable to measure RTT"
6052 " since no RTP packet has been received yet");
6053 }
6054
6055 // Retrieve RTT statistics from the RTP/RTCP module for the specified
6056 // channel and SSRC. The SSRC is required to parse out the correct source
6057 // in conference scenarios.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006058 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00006059 {
6060 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6061 "GetRoundTripTimeSummary unable to retrieve RTT values"
6062 " from the RTCP layer");
6063 delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
6064 }
6065 else
6066 {
6067 delaysMs.min = minRTT;
6068 delaysMs.max = maxRTT;
6069 delaysMs.average = avgRTT;
6070 }
6071 return 0;
6072}
6073
6074int
6075Channel::GetNetworkStatistics(NetworkStatistics& stats)
6076{
6077 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6078 "Channel::GetNetworkStatistics()");
6079 return _audioCodingModule.NetworkStatistics(
6080 (ACMNetworkStatistics &)stats);
6081}
6082
6083int
niklase@google.com470e71d2011-07-07 08:21:25 +00006084Channel::GetDelayEstimate(int& delayMs) const
6085{
6086 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6087 "Channel::GetDelayEstimate()");
6088 delayMs = (_averageDelayMs + 5) / 10 + _recPacketDelayMs;
6089 return 0;
6090}
6091
6092int
6093Channel::SetMinimumPlayoutDelay(int delayMs)
6094{
6095 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6096 "Channel::SetMinimumPlayoutDelay()");
6097 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
6098 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
6099 {
6100 _engineStatisticsPtr->SetLastError(
6101 VE_INVALID_ARGUMENT, kTraceError,
6102 "SetMinimumPlayoutDelay() invalid min delay");
6103 return -1;
6104 }
6105 if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
6106 {
6107 _engineStatisticsPtr->SetLastError(
6108 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6109 "SetMinimumPlayoutDelay() failed to set min playout delay");
6110 return -1;
6111 }
6112 return 0;
6113}
6114
6115int
6116Channel::GetPlayoutTimestamp(unsigned int& timestamp)
6117{
6118 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6119 "Channel::GetPlayoutTimestamp()");
6120 WebRtc_UWord32 playoutTimestamp(0);
6121 if (GetPlayoutTimeStamp(playoutTimestamp) != 0)
6122 {
6123 _engineStatisticsPtr->SetLastError(
6124 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
6125 "GetPlayoutTimestamp() failed to retrieve timestamp");
6126 return -1;
6127 }
6128 timestamp = playoutTimestamp;
6129 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
6130 VoEId(_instanceId,_channelId),
6131 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
6132 return 0;
6133}
6134
6135int
6136Channel::SetInitTimestamp(unsigned int timestamp)
6137{
6138 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6139 "Channel::SetInitTimestamp()");
6140 if (_sending)
6141 {
6142 _engineStatisticsPtr->SetLastError(
6143 VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
6144 return -1;
6145 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006146 if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00006147 {
6148 _engineStatisticsPtr->SetLastError(
6149 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6150 "SetInitTimestamp() failed to set timestamp");
6151 return -1;
6152 }
6153 return 0;
6154}
6155
6156int
6157Channel::SetInitSequenceNumber(short sequenceNumber)
6158{
6159 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6160 "Channel::SetInitSequenceNumber()");
6161 if (_sending)
6162 {
6163 _engineStatisticsPtr->SetLastError(
6164 VE_SENDING, kTraceError,
6165 "SetInitSequenceNumber() already sending");
6166 return -1;
6167 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006168 if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00006169 {
6170 _engineStatisticsPtr->SetLastError(
6171 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6172 "SetInitSequenceNumber() failed to set sequence number");
6173 return -1;
6174 }
6175 return 0;
6176}
6177
6178int
6179Channel::GetRtpRtcp(RtpRtcp* &rtpRtcpModule) const
6180{
6181 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6182 "Channel::GetRtpRtcp()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006183 rtpRtcpModule = _rtpRtcpModule.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00006184 return 0;
6185}
6186
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006187// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
6188// a shared helper.
niklase@google.com470e71d2011-07-07 08:21:25 +00006189WebRtc_Word32
xians@google.com0b0665a2011-08-08 08:18:44 +00006190Channel::MixOrReplaceAudioWithFile(const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00006191{
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006192 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006193 int fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00006194
6195 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00006196 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00006197
6198 if (_inputFilePlayerPtr == NULL)
6199 {
6200 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6201 VoEId(_instanceId, _channelId),
6202 "Channel::MixOrReplaceAudioWithFile() fileplayer"
6203 " doesnt exist");
6204 return -1;
6205 }
6206
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006207 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00006208 fileSamples,
6209 mixingFrequency) == -1)
6210 {
6211 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6212 VoEId(_instanceId, _channelId),
6213 "Channel::MixOrReplaceAudioWithFile() file mixing "
6214 "failed");
6215 return -1;
6216 }
6217 if (fileSamples == 0)
6218 {
6219 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6220 VoEId(_instanceId, _channelId),
6221 "Channel::MixOrReplaceAudioWithFile() file is ended");
6222 return 0;
6223 }
6224 }
6225
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006226 assert(_audioFrame.samples_per_channel_ == fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006227
6228 if (_mixFileWithMicrophone)
6229 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006230 // Currently file stream is always mono.
6231 // TODO(xians): Change the code when FilePlayer supports real stereo.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006232 Utility::MixWithSat(_audioFrame.data_,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006233 _audioFrame.num_channels_,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006234 fileBuffer.get(),
6235 1,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006236 fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006237 }
6238 else
6239 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006240 // Replace ACM audio with file.
6241 // Currently file stream is always mono.
6242 // TODO(xians): Change the code when FilePlayer supports real stereo.
niklase@google.com470e71d2011-07-07 08:21:25 +00006243 _audioFrame.UpdateFrame(_channelId,
6244 -1,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006245 fileBuffer.get(),
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006246 fileSamples,
niklase@google.com470e71d2011-07-07 08:21:25 +00006247 mixingFrequency,
6248 AudioFrame::kNormalSpeech,
6249 AudioFrame::kVadUnknown,
6250 1);
6251
6252 }
6253 return 0;
6254}
6255
6256WebRtc_Word32
6257Channel::MixAudioWithFile(AudioFrame& audioFrame,
xians@google.com0b0665a2011-08-08 08:18:44 +00006258 const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00006259{
6260 assert(mixingFrequency <= 32000);
6261
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006262 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006263 int fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00006264
6265 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00006266 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00006267
6268 if (_outputFilePlayerPtr == NULL)
6269 {
6270 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6271 VoEId(_instanceId, _channelId),
6272 "Channel::MixAudioWithFile() file mixing failed");
6273 return -1;
6274 }
6275
6276 // We should get the frequency we ask for.
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006277 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00006278 fileSamples,
6279 mixingFrequency) == -1)
6280 {
6281 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6282 VoEId(_instanceId, _channelId),
6283 "Channel::MixAudioWithFile() file mixing failed");
6284 return -1;
6285 }
6286 }
6287
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006288 if (audioFrame.samples_per_channel_ == fileSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +00006289 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006290 // Currently file stream is always mono.
6291 // TODO(xians): Change the code when FilePlayer supports real stereo.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006292 Utility::MixWithSat(audioFrame.data_,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006293 audioFrame.num_channels_,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006294 fileBuffer.get(),
6295 1,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006296 fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006297 }
6298 else
6299 {
6300 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006301 "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
niklase@google.com470e71d2011-07-07 08:21:25 +00006302 "fileSamples(%d)",
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006303 audioFrame.samples_per_channel_, fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006304 return -1;
6305 }
6306
6307 return 0;
6308}
6309
6310int
6311Channel::InsertInbandDtmfTone()
6312{
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006313 // Check if we should start a new tone.
niklase@google.com470e71d2011-07-07 08:21:25 +00006314 if (_inbandDtmfQueue.PendingDtmf() &&
6315 !_inbandDtmfGenerator.IsAddingTone() &&
6316 _inbandDtmfGenerator.DelaySinceLastTone() >
6317 kMinTelephoneEventSeparationMs)
6318 {
6319 WebRtc_Word8 eventCode(0);
6320 WebRtc_UWord16 lengthMs(0);
6321 WebRtc_UWord8 attenuationDb(0);
6322
6323 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
6324 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
6325 if (_playInbandDtmfEvent)
6326 {
6327 // Add tone to output mixer using a reduced length to minimize
6328 // risk of echo.
6329 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
6330 attenuationDb);
6331 }
6332 }
6333
6334 if (_inbandDtmfGenerator.IsAddingTone())
6335 {
6336 WebRtc_UWord16 frequency(0);
6337 _inbandDtmfGenerator.GetSampleRate(frequency);
6338
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006339 if (frequency != _audioFrame.sample_rate_hz_)
niklase@google.com470e71d2011-07-07 08:21:25 +00006340 {
6341 // Update sample rate of Dtmf tone since the mixing frequency
6342 // has changed.
6343 _inbandDtmfGenerator.SetSampleRate(
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006344 (WebRtc_UWord16) (_audioFrame.sample_rate_hz_));
niklase@google.com470e71d2011-07-07 08:21:25 +00006345 // Reset the tone to be added taking the new sample rate into
6346 // account.
6347 _inbandDtmfGenerator.ResetTone();
6348 }
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006349
niklase@google.com470e71d2011-07-07 08:21:25 +00006350 WebRtc_Word16 toneBuffer[320];
6351 WebRtc_UWord16 toneSamples(0);
6352 // Get 10ms tone segment and set time since last tone to zero
6353 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
6354 {
6355 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6356 VoEId(_instanceId, _channelId),
6357 "Channel::EncodeAndSend() inserting Dtmf failed");
6358 return -1;
6359 }
6360
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006361 // Replace mixed audio with DTMF tone.
6362 for (int sample = 0;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006363 sample < _audioFrame.samples_per_channel_;
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006364 sample++)
6365 {
6366 for (int channel = 0;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006367 channel < _audioFrame.num_channels_;
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006368 channel++)
6369 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006370 _audioFrame.data_[sample * _audioFrame.num_channels_ + channel] =
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006371 toneBuffer[sample];
6372 }
6373 }
6374
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006375 assert(_audioFrame.samples_per_channel_ == toneSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006376 } else
6377 {
6378 // Add 10ms to "delay-since-last-tone" counter
6379 _inbandDtmfGenerator.UpdateDelaySinceLastTone();
6380 }
6381 return 0;
6382}
6383
6384WebRtc_Word32
6385Channel::GetPlayoutTimeStamp(WebRtc_UWord32& playoutTimestamp)
6386{
6387 WebRtc_UWord32 timestamp(0);
6388 CodecInst currRecCodec;
6389
6390 if (_audioCodingModule.PlayoutTimestamp(timestamp) == -1)
6391 {
6392 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6393 "Channel::GetPlayoutTimeStamp() failed to read playout"
6394 " timestamp from the ACM");
6395 return -1;
6396 }
6397
6398 WebRtc_UWord16 delayMS(0);
6399 if (_audioDeviceModulePtr->PlayoutDelay(&delayMS) == -1)
6400 {
6401 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6402 "Channel::GetPlayoutTimeStamp() failed to read playout"
6403 " delay from the ADM");
6404 return -1;
6405 }
6406
6407 WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006408 if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6409 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6410 playoutFrequency = 8000;
6411 } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6412 playoutFrequency = 48000;
6413 }
niklase@google.com470e71d2011-07-07 08:21:25 +00006414 }
6415 timestamp -= (delayMS * (playoutFrequency/1000));
6416
6417 playoutTimestamp = timestamp;
6418
6419 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6420 "Channel::GetPlayoutTimeStamp() => playoutTimestamp = %lu",
6421 playoutTimestamp);
6422 return 0;
6423}
6424
6425void
6426Channel::ResetDeadOrAliveCounters()
6427{
6428 _countDeadDetections = 0;
6429 _countAliveDetections = 0;
6430}
6431
6432void
6433Channel::UpdateDeadOrAliveCounters(bool alive)
6434{
6435 if (alive)
6436 _countAliveDetections++;
6437 else
6438 _countDeadDetections++;
6439}
6440
6441int
6442Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
6443{
6444 bool enabled;
6445 WebRtc_UWord8 timeSec;
6446
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006447 _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, timeSec);
niklase@google.com470e71d2011-07-07 08:21:25 +00006448 if (!enabled)
6449 return (-1);
6450
6451 countDead = static_cast<int> (_countDeadDetections);
6452 countAlive = static_cast<int> (_countAliveDetections);
6453 return 0;
6454}
6455
6456WebRtc_Word32
6457Channel::SendPacketRaw(const void *data, int len, bool RTCP)
6458{
6459 if (_transportPtr == NULL)
6460 {
6461 return -1;
6462 }
6463 if (!RTCP)
6464 {
6465 return _transportPtr->SendPacket(_channelId, data, len);
6466 }
6467 else
6468 {
6469 return _transportPtr->SendRTCPPacket(_channelId, data, len);
6470 }
6471}
6472
6473WebRtc_Word32
6474Channel::UpdatePacketDelay(const WebRtc_UWord32 timestamp,
6475 const WebRtc_UWord16 sequenceNumber)
6476{
6477 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6478 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
6479 timestamp, sequenceNumber);
6480
6481 WebRtc_Word32 rtpReceiveFrequency(0);
6482
6483 // Get frequency of last received payload
6484 rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
6485
6486 CodecInst currRecCodec;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006487 if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
6488 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6489 // Even though the actual sampling rate for G.722 audio is
6490 // 16,000 Hz, the RTP clock rate for the G722 payload format is
6491 // 8,000 Hz because that value was erroneously assigned in
6492 // RFC 1890 and must remain unchanged for backward compatibility.
6493 rtpReceiveFrequency = 8000;
6494 } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6495 // We are resampling Opus internally to 32,000 Hz until all our
6496 // DSP routines can operate at 48,000 Hz, but the RTP clock
6497 // rate for the Opus payload format is standardized to 48,000 Hz,
6498 // because that is the maximum supported decoding sampling rate.
6499 rtpReceiveFrequency = 48000;
6500 }
niklase@google.com470e71d2011-07-07 08:21:25 +00006501 }
6502
6503 const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
6504 WebRtc_UWord32 timeStampDiffMs(0);
6505
6506 if (timeStampDiff > 0)
6507 {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006508 switch (rtpReceiveFrequency) {
6509 case 8000:
6510 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 3);
6511 break;
6512 case 16000:
6513 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 4);
6514 break;
6515 case 32000:
6516 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 5);
6517 break;
6518 case 48000:
6519 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff / 48);
6520 break;
6521 default:
6522 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6523 VoEId(_instanceId, _channelId),
6524 "Channel::UpdatePacketDelay() invalid sample rate");
6525 timeStampDiffMs = 0;
6526 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00006527 }
6528 if (timeStampDiffMs > 5000)
6529 {
6530 timeStampDiffMs = 0;
6531 }
6532
6533 if (_averageDelayMs == 0)
6534 {
6535 _averageDelayMs = timeStampDiffMs;
6536 }
6537 else
6538 {
6539 // Filter average delay value using exponential filter (alpha is
6540 // 7/8). We derive 10*_averageDelayMs here (reduces risk of
6541 // rounding error) and compensate for it in GetDelayEstimate()
6542 // later. Adding 4/8 results in correct rounding.
6543 _averageDelayMs = ((_averageDelayMs*7 + 10*timeStampDiffMs + 4)>>3);
6544 }
6545
6546 if (sequenceNumber - _previousSequenceNumber == 1)
6547 {
6548 WebRtc_UWord16 packetDelayMs = 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006549 switch (rtpReceiveFrequency) {
6550 case 8000:
6551 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006552 (timestamp - _previousTimestamp) >> 3);
6553 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006554 case 16000:
6555 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006556 (timestamp - _previousTimestamp) >> 4);
6557 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006558 case 32000:
6559 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006560 (timestamp - _previousTimestamp) >> 5);
6561 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006562 case 48000:
6563 packetDelayMs = static_cast<WebRtc_UWord16>(
6564 (timestamp - _previousTimestamp) / 48);
6565 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00006566 }
6567
6568 if (packetDelayMs >= 10 && packetDelayMs <= 60)
6569 _recPacketDelayMs = packetDelayMs;
6570 }
6571 }
6572
6573 _previousSequenceNumber = sequenceNumber;
6574 _previousTimestamp = timestamp;
6575
6576 return 0;
6577}
6578
6579void
6580Channel::RegisterReceiveCodecsToRTPModule()
6581{
6582 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6583 "Channel::RegisterReceiveCodecsToRTPModule()");
6584
6585
6586 CodecInst codec;
6587 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
6588
6589 for (int idx = 0; idx < nSupportedCodecs; idx++)
6590 {
6591 // Open up the RTP/RTCP receiver for all supported codecs
6592 if ((_audioCodingModule.Codec(idx, codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006593 (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00006594 {
6595 WEBRTC_TRACE(
6596 kTraceWarning,
6597 kTraceVoice,
6598 VoEId(_instanceId, _channelId),
6599 "Channel::RegisterReceiveCodecsToRTPModule() unable"
6600 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
6601 codec.plname, codec.pltype, codec.plfreq,
6602 codec.channels, codec.rate);
6603 }
6604 else
6605 {
6606 WEBRTC_TRACE(
6607 kTraceInfo,
6608 kTraceVoice,
6609 VoEId(_instanceId, _channelId),
6610 "Channel::RegisterReceiveCodecsToRTPModule() %s "
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00006611 "(%d/%d/%d/%d) has been added to the RTP/RTCP "
niklase@google.com470e71d2011-07-07 08:21:25 +00006612 "receiver",
6613 codec.plname, codec.pltype, codec.plfreq,
6614 codec.channels, codec.rate);
6615 }
6616 }
6617}
6618
andrew@webrtc.org50419b02012-11-14 19:07:54 +00006619int Channel::ApmProcessRx(AudioFrame& frame) {
6620 AudioProcessing* audioproc = _rxAudioProcessingModulePtr;
6621 // Register the (possibly new) frame parameters.
6622 if (audioproc->set_sample_rate_hz(frame.sample_rate_hz_) != 0) {
6623 LOG_FERR1(WARNING, set_sample_rate_hz, frame.sample_rate_hz_);
6624 }
6625 if (audioproc->set_num_channels(frame.num_channels_,
6626 frame.num_channels_) != 0) {
6627 LOG_FERR1(WARNING, set_num_channels, frame.num_channels_);
6628 }
6629 if (audioproc->ProcessStream(&frame) != 0) {
6630 LOG_FERR0(WARNING, ProcessStream);
6631 }
6632 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00006633}
6634
6635} // namespace voe
niklase@google.com470e71d2011-07-07 08:21:25 +00006636} // namespace webrtc