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