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