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