blob: 94b6dd457f8186cca97d9682dd2619d1d9a7897e [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
andrew@webrtc.org755b04a2011-11-15 16:57:56 +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.
63 if (_rtpRtcpModule.SendOutgoingData((FrameType&)frameType,
64 payloadType,
65 timeStamp,
66 payloadData,
67 payloadSize,
68 fragmentation) == -1)
69 {
70 _engineStatisticsPtr->SetLastError(
71 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
72 "Channel::SendData() failed to send data to RTP/RTCP module");
73 return -1;
74 }
75
76 _lastLocalTimeStamp = timeStamp;
77 _lastPayloadType = payloadType;
78
79 return 0;
80}
81
82WebRtc_Word32
83Channel::InFrameType(WebRtc_Word16 frameType)
84{
85 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
86 "Channel::InFrameType(frameType=%d)", frameType);
87
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +000088 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000089 // 1 indicates speech
90 _sendFrameType = (frameType == 1) ? 1 : 0;
91 return 0;
92}
93
94#ifdef WEBRTC_DTMF_DETECTION
95int
96Channel::IncomingDtmf(const WebRtc_UWord8 digitDtmf, const bool end)
97{
98 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
99 "Channel::IncomingDtmf(digitDtmf=%u, end=%d)",
100 digitDtmf, end);
101
102 if (digitDtmf != 999)
103 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000104 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 if (_telephoneEventDetectionPtr)
106 {
107 _telephoneEventDetectionPtr->OnReceivedTelephoneEventInband(
108 _channelId, digitDtmf, end);
109 }
110 }
111
112 return 0;
113}
114#endif
115
116WebRtc_Word32
117Channel::OnRxVadDetected(const int vadDecision)
118{
119 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
120 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
121
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000122 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 if (_rxVadObserverPtr)
124 {
125 _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
126 }
127
128 return 0;
129}
130
131int
132Channel::SendPacket(int channel, const void *data, int len)
133{
134 channel = VoEChannelId(channel);
135 assert(channel == _channelId);
136
137 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
138 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
139
140 if (_transportPtr == NULL)
141 {
142 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
143 "Channel::SendPacket() failed to send RTP packet due to"
144 " invalid transport object");
145 return -1;
146 }
147
148 // Insert extra RTP packet using if user has called the InsertExtraRTPPacket
149 // API
150 if (_insertExtraRTPPacket)
151 {
152 WebRtc_UWord8* rtpHdr = (WebRtc_UWord8*)data;
153 WebRtc_UWord8 M_PT(0);
154 if (_extraMarkerBit)
155 {
156 M_PT = 0x80; // set the M-bit
157 }
158 M_PT += _extraPayloadType; // set the payload type
159 *(++rtpHdr) = M_PT; // modify the M|PT-byte within the RTP header
160 _insertExtraRTPPacket = false; // insert one packet only
161 }
162
163 WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
164 WebRtc_Word32 bufferLength = len;
165
166 // Dump the RTP packet to a file (if RTP dump is enabled).
167 if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
168 {
169 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
170 VoEId(_instanceId,_channelId),
171 "Channel::SendPacket() RTP dump to output file failed");
172 }
173
174 // SRTP or External encryption
175 if (_encrypting)
176 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000177 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
179 if (_encryptionPtr)
180 {
181 if (!_encryptionRTPBufferPtr)
182 {
183 // Allocate memory for encryption buffer one time only
184 _encryptionRTPBufferPtr =
185 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
186 }
187
188 // Perform encryption (SRTP or external)
189 WebRtc_Word32 encryptedBufferLength = 0;
190 _encryptionPtr->encrypt(_channelId,
191 bufferToSendPtr,
192 _encryptionRTPBufferPtr,
193 bufferLength,
194 (int*)&encryptedBufferLength);
195 if (encryptedBufferLength <= 0)
196 {
197 _engineStatisticsPtr->SetLastError(
198 VE_ENCRYPTION_FAILED,
199 kTraceError, "Channel::SendPacket() encryption failed");
200 return -1;
201 }
202
203 // Replace default data buffer with encrypted buffer
204 bufferToSendPtr = _encryptionRTPBufferPtr;
205 bufferLength = encryptedBufferLength;
206 }
207 }
208
209 // Packet transmission using WebRtc socket transport
210 if (!_externalTransport)
211 {
212 int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
213 bufferLength);
214 if (n < 0)
215 {
216 WEBRTC_TRACE(kTraceError, kTraceVoice,
217 VoEId(_instanceId,_channelId),
218 "Channel::SendPacket() RTP transmission using WebRtc"
219 " sockets failed");
220 return -1;
221 }
222 return n;
223 }
224
225 // Packet transmission using external transport transport
226 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000227 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000228
229 int n = _transportPtr->SendPacket(channel,
230 bufferToSendPtr,
231 bufferLength);
232 if (n < 0)
233 {
234 WEBRTC_TRACE(kTraceError, kTraceVoice,
235 VoEId(_instanceId,_channelId),
236 "Channel::SendPacket() RTP transmission using external"
237 " transport failed");
238 return -1;
239 }
240 return n;
241 }
242}
243
244int
245Channel::SendRTCPPacket(int channel, const void *data, int len)
246{
247 channel = VoEChannelId(channel);
248 assert(channel == _channelId);
249
250 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
251 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
252
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000254 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +0000255 if (_transportPtr == NULL)
256 {
257 WEBRTC_TRACE(kTraceError, kTraceVoice,
258 VoEId(_instanceId,_channelId),
259 "Channel::SendRTCPPacket() failed to send RTCP packet"
260 " due to invalid transport object");
261 return -1;
262 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000263 }
264
265 WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
266 WebRtc_Word32 bufferLength = len;
267
268 // Dump the RTCP packet to a file (if RTP dump is enabled).
269 if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
270 {
271 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
272 VoEId(_instanceId,_channelId),
273 "Channel::SendPacket() RTCP dump to output file failed");
274 }
275
276 // SRTP or External encryption
277 if (_encrypting)
278 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000279 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000280
281 if (_encryptionPtr)
282 {
283 if (!_encryptionRTCPBufferPtr)
284 {
285 // Allocate memory for encryption buffer one time only
286 _encryptionRTCPBufferPtr =
287 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
288 }
289
290 // Perform encryption (SRTP or external).
291 WebRtc_Word32 encryptedBufferLength = 0;
292 _encryptionPtr->encrypt_rtcp(_channelId,
293 bufferToSendPtr,
294 _encryptionRTCPBufferPtr,
295 bufferLength,
296 (int*)&encryptedBufferLength);
297 if (encryptedBufferLength <= 0)
298 {
299 _engineStatisticsPtr->SetLastError(
300 VE_ENCRYPTION_FAILED, kTraceError,
301 "Channel::SendRTCPPacket() encryption failed");
302 return -1;
303 }
304
305 // Replace default data buffer with encrypted buffer
306 bufferToSendPtr = _encryptionRTCPBufferPtr;
307 bufferLength = encryptedBufferLength;
308 }
309 }
310
311 // Packet transmission using WebRtc socket transport
312 if (!_externalTransport)
313 {
314 int n = _transportPtr->SendRTCPPacket(channel,
315 bufferToSendPtr,
316 bufferLength);
317 if (n < 0)
318 {
319 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
320 VoEId(_instanceId,_channelId),
321 "Channel::SendRTCPPacket() transmission using WebRtc"
322 " sockets failed");
323 return -1;
324 }
325 return n;
326 }
327
328 // Packet transmission using external transport transport
329 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000330 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000331
332 int n = _transportPtr->SendRTCPPacket(channel,
333 bufferToSendPtr,
334 bufferLength);
335 if (n < 0)
336 {
337 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
338 VoEId(_instanceId,_channelId),
339 "Channel::SendRTCPPacket() transmission using external"
340 " transport failed");
341 return -1;
342 }
343 return n;
344 }
345
346 return len;
347}
348
349void
350Channel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket,
351 const WebRtc_Word32 rtpPacketLength,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000352 const char* fromIP,
niklase@google.com470e71d2011-07-07 08:21:25 +0000353 const WebRtc_UWord16 fromPort)
354{
355 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
356 "Channel::IncomingRTPPacket(rtpPacketLength=%d,"
357 " fromIP=%s, fromPort=%u)",
358 rtpPacketLength, fromIP, fromPort);
359
360 // Store playout timestamp for the received RTP packet
361 // to be used for upcoming delay estimations
362 WebRtc_UWord32 playoutTimestamp(0);
363 if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
364 {
365 _playoutTimeStampRTP = playoutTimestamp;
366 }
367
368 WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket;
369 WebRtc_Word32 rtpBufferLength = rtpPacketLength;
370
371 // SRTP or External decryption
372 if (_decrypting)
373 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000374 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
376 if (_encryptionPtr)
377 {
378 if (!_decryptionRTPBufferPtr)
379 {
380 // Allocate memory for decryption buffer one time only
381 _decryptionRTPBufferPtr =
382 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
383 }
384
385 // Perform decryption (SRTP or external)
386 WebRtc_Word32 decryptedBufferLength = 0;
387 _encryptionPtr->decrypt(_channelId,
388 rtpBufferPtr,
389 _decryptionRTPBufferPtr,
390 rtpBufferLength,
391 (int*)&decryptedBufferLength);
392 if (decryptedBufferLength <= 0)
393 {
394 _engineStatisticsPtr->SetLastError(
395 VE_DECRYPTION_FAILED, kTraceError,
396 "Channel::IncomingRTPPacket() decryption failed");
397 return;
398 }
399
400 // Replace default data buffer with decrypted buffer
401 rtpBufferPtr = _decryptionRTPBufferPtr;
402 rtpBufferLength = decryptedBufferLength;
403 }
404 }
405
406 // Dump the RTP packet to a file (if RTP dump is enabled).
407 if (_rtpDumpIn.DumpPacket(rtpBufferPtr,
408 (WebRtc_UWord16)rtpBufferLength) == -1)
409 {
410 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
411 VoEId(_instanceId,_channelId),
412 "Channel::SendPacket() RTP dump to input file failed");
413 }
414
415 // Deliver RTP packet to RTP/RTCP module for parsing
416 // The packet will be pushed back to the channel thru the
417 // OnReceivedPayloadData callback so we don't push it to the ACM here
418 if (_rtpRtcpModule.IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr,
419 (WebRtc_UWord16)rtpBufferLength) == -1)
420 {
421 _engineStatisticsPtr->SetLastError(
422 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
423 "Channel::IncomingRTPPacket() RTP packet is invalid");
424 return;
425 }
426}
427
428void
429Channel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket,
430 const WebRtc_Word32 rtcpPacketLength,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000431 const char* fromIP,
niklase@google.com470e71d2011-07-07 08:21:25 +0000432 const WebRtc_UWord16 fromPort)
433{
434 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
435 "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s,"
436 " fromPort=%u)",
437 rtcpPacketLength, fromIP, fromPort);
438
439 // Temporary buffer pointer and size for decryption
440 WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket;
441 WebRtc_Word32 rtcpBufferLength = rtcpPacketLength;
442
443 // Store playout timestamp for the received RTCP packet
444 // which will be read by the GetRemoteRTCPData API
445 WebRtc_UWord32 playoutTimestamp(0);
446 if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
447 {
448 _playoutTimeStampRTCP = playoutTimestamp;
449 }
450
451 // SRTP or External decryption
452 if (_decrypting)
453 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000454 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
456 if (_encryptionPtr)
457 {
458 if (!_decryptionRTCPBufferPtr)
459 {
460 // Allocate memory for decryption buffer one time only
461 _decryptionRTCPBufferPtr =
462 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
463 }
464
465 // Perform decryption (SRTP or external).
466 WebRtc_Word32 decryptedBufferLength = 0;
467 _encryptionPtr->decrypt_rtcp(_channelId,
468 rtcpBufferPtr,
469 _decryptionRTCPBufferPtr,
470 rtcpBufferLength,
471 (int*)&decryptedBufferLength);
472 if (decryptedBufferLength <= 0)
473 {
474 _engineStatisticsPtr->SetLastError(
475 VE_DECRYPTION_FAILED, kTraceError,
476 "Channel::IncomingRTCPPacket() decryption failed");
477 return;
478 }
479
480 // Replace default data buffer with decrypted buffer
481 rtcpBufferPtr = _decryptionRTCPBufferPtr;
482 rtcpBufferLength = decryptedBufferLength;
483 }
484 }
485
486 // Dump the RTCP packet to a file (if RTP dump is enabled).
487 if (_rtpDumpIn.DumpPacket(rtcpBufferPtr,
488 (WebRtc_UWord16)rtcpBufferLength) == -1)
489 {
490 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
491 VoEId(_instanceId,_channelId),
492 "Channel::SendPacket() RTCP dump to input file failed");
493 }
494
495 // Deliver RTCP packet to RTP/RTCP module for parsing
496 if (_rtpRtcpModule.IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr,
497 (WebRtc_UWord16)rtcpBufferLength) == -1)
498 {
499 _engineStatisticsPtr->SetLastError(
500 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
501 "Channel::IncomingRTPPacket() RTCP packet is invalid");
502 return;
503 }
504}
505
506void
507Channel::OnReceivedTelephoneEvent(const WebRtc_Word32 id,
508 const WebRtc_UWord8 event,
509 const bool endOfEvent)
510{
511 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
512 "Channel::OnReceivedTelephoneEvent(id=%d, event=%u,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +0000513 " endOfEvent=%d)", id, event, endOfEvent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000514
515#ifdef WEBRTC_DTMF_DETECTION
516 if (_outOfBandTelephoneEventDetecion)
517 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000518 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
520 if (_telephoneEventDetectionPtr)
521 {
522 _telephoneEventDetectionPtr->OnReceivedTelephoneEventOutOfBand(
523 _channelId, event, endOfEvent);
524 }
525 }
526#endif
527}
528
529void
530Channel::OnPlayTelephoneEvent(const WebRtc_Word32 id,
531 const WebRtc_UWord8 event,
532 const WebRtc_UWord16 lengthMs,
533 const WebRtc_UWord8 volume)
534{
535 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
536 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +0000537 " volume=%u)", id, event, lengthMs, volume);
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
539 if (!_playOutbandDtmfEvent || (event > 15))
540 {
541 // Ignore callback since feedback is disabled or event is not a
542 // Dtmf tone event.
543 return;
544 }
545
546 assert(_outputMixerPtr != NULL);
547
548 // Start playing out the Dtmf tone (if playout is enabled).
549 // Reduce length of tone with 80ms to the reduce risk of echo.
550 _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
551}
552
553void
554Channel::OnIncomingSSRCChanged(const WebRtc_Word32 id,
555 const WebRtc_UWord32 SSRC)
556{
557 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
558 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
559 id, SSRC);
560
561 WebRtc_Word32 channel = VoEChannelId(id);
562 assert(channel == _channelId);
563
564 // Reset RTP-module counters since a new incoming RTP stream is detected
565 _rtpRtcpModule.ResetReceiveDataCountersRTP();
566 _rtpRtcpModule.ResetStatisticsRTP();
567
568 if (_rtpObserver)
569 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000570 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
572 if (_rtpObserverPtr)
573 {
574 // Send new SSRC to registered observer using callback
575 _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
576 }
577 }
578}
579
580void Channel::OnIncomingCSRCChanged(const WebRtc_Word32 id,
581 const WebRtc_UWord32 CSRC,
582 const bool added)
583{
584 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
585 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
586 id, CSRC, added);
587
588 WebRtc_Word32 channel = VoEChannelId(id);
589 assert(channel == _channelId);
590
591 if (_rtpObserver)
592 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000593 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000594
595 if (_rtpObserverPtr)
596 {
597 _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
598 }
599 }
600}
601
602void
603Channel::OnApplicationDataReceived(const WebRtc_Word32 id,
604 const WebRtc_UWord8 subType,
605 const WebRtc_UWord32 name,
606 const WebRtc_UWord16 length,
607 const WebRtc_UWord8* data)
608{
609 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
610 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
611 " name=%u, length=%u)",
612 id, subType, name, length);
613
614 WebRtc_Word32 channel = VoEChannelId(id);
615 assert(channel == _channelId);
616
617 if (_rtcpObserver)
618 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000619 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
621 if (_rtcpObserverPtr)
622 {
623 _rtcpObserverPtr->OnApplicationDataReceived(channel,
624 subType,
625 name,
626 data,
627 length);
628 }
629 }
630}
631
632WebRtc_Word32
633Channel::OnInitializeDecoder(
634 const WebRtc_Word32 id,
635 const WebRtc_Word8 payloadType,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000636 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
xians@google.com0b0665a2011-08-08 08:18:44 +0000637 const int frequency,
niklase@google.com470e71d2011-07-07 08:21:25 +0000638 const WebRtc_UWord8 channels,
639 const WebRtc_UWord32 rate)
640{
641 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
642 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
643 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
644 id, payloadType, payloadName, frequency, channels, rate);
645
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000646 assert(VoEChannelId(id) == _channelId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
henrika@webrtc.orgf75901f2012-01-16 08:45:42 +0000648 CodecInst receiveCodec = {0};
649 CodecInst dummyCodec = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
651 receiveCodec.pltype = payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000652 receiveCodec.plfreq = frequency;
653 receiveCodec.channels = channels;
654 receiveCodec.rate = rate;
henrika@webrtc.orgf75901f2012-01-16 08:45:42 +0000655 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
656
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 _audioCodingModule.Codec(payloadName, dummyCodec, frequency);
658 receiveCodec.pacsize = dummyCodec.pacsize;
659
660 // Register the new codec to the ACM
661 if (_audioCodingModule.RegisterReceiveCodec(receiveCodec) == -1)
662 {
663 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000664 VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +0000665 "Channel::OnInitializeDecoder() invalid codec ("
666 "pt=%d, name=%s) received - 1", payloadType, payloadName);
667 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
668 return -1;
669 }
670
671 return 0;
672}
673
674void
675Channel::OnPacketTimeout(const WebRtc_Word32 id)
676{
677 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
678 "Channel::OnPacketTimeout(id=%d)", id);
679
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000680 CriticalSectionScoped cs(_callbackCritSectPtr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000681 if (_voiceEngineObserverPtr)
682 {
683 if (_receiving || _externalTransport)
684 {
685 WebRtc_Word32 channel = VoEChannelId(id);
686 assert(channel == _channelId);
687 // Ensure that next OnReceivedPacket() callback will trigger
688 // a VE_PACKET_RECEIPT_RESTARTED callback.
689 _rtpPacketTimedOut = true;
690 // Deliver callback to the observer
691 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
692 VoEId(_instanceId,_channelId),
693 "Channel::OnPacketTimeout() => "
694 "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
695 _voiceEngineObserverPtr->CallbackOnError(channel,
696 VE_RECEIVE_PACKET_TIMEOUT);
697 }
698 }
699}
700
701void
702Channel::OnReceivedPacket(const WebRtc_Word32 id,
703 const RtpRtcpPacketType packetType)
704{
705 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
706 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
707 id, packetType);
708
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000709 assert(VoEChannelId(id) == _channelId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000710
711 // Notify only for the case when we have restarted an RTP session.
712 if (_rtpPacketTimedOut && (kPacketRtp == packetType))
713 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000714 CriticalSectionScoped cs(_callbackCritSectPtr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000715 if (_voiceEngineObserverPtr)
716 {
717 WebRtc_Word32 channel = VoEChannelId(id);
718 assert(channel == _channelId);
719 // Reset timeout mechanism
720 _rtpPacketTimedOut = false;
721 // Deliver callback to the observer
722 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
723 VoEId(_instanceId,_channelId),
724 "Channel::OnPacketTimeout() =>"
725 " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
726 _voiceEngineObserverPtr->CallbackOnError(
727 channel,
728 VE_PACKET_RECEIPT_RESTARTED);
729 }
730 }
731}
732
733void
734Channel::OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
735 const RTPAliveType alive)
736{
737 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
738 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
739
740 if (!_connectionObserver)
741 return;
742
743 WebRtc_Word32 channel = VoEChannelId(id);
744 assert(channel == _channelId);
745
746 // Use Alive as default to limit risk of false Dead detections
747 bool isAlive(true);
748
749 // Always mark the connection as Dead when the module reports kRtpDead
750 if (kRtpDead == alive)
751 {
752 isAlive = false;
753 }
754
755 // It is possible that the connection is alive even if no RTP packet has
756 // been received for a long time since the other side might use VAD/DTX
757 // and a low SID-packet update rate.
758 if ((kRtpNoRtp == alive) && _playing)
759 {
760 // Detect Alive for all NetEQ states except for the case when we are
761 // in PLC_CNG state.
762 // PLC_CNG <=> background noise only due to long expand or error.
763 // Note that, the case where the other side stops sending during CNG
764 // state will be detected as Alive. Dead is is not set until after
765 // missing RTCP packets for at least twelve seconds (handled
766 // internally by the RTP/RTCP module).
767 isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
768 }
769
770 UpdateDeadOrAliveCounters(isAlive);
771
772 // Send callback to the registered observer
773 if (_connectionObserver)
774 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000775 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776 if (_connectionObserverPtr)
777 {
778 _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
779 }
780 }
781}
782
783WebRtc_Word32
784Channel::OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
785 const WebRtc_UWord16 payloadSize,
786 const WebRtcRTPHeader* rtpHeader)
787{
788 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
789 "Channel::OnReceivedPayloadData(payloadSize=%d,"
790 " payloadType=%u, audioChannel=%u)",
791 payloadSize,
792 rtpHeader->header.payloadType,
793 rtpHeader->type.Audio.channel);
794
795 if (!_playing)
796 {
797 // Avoid inserting into NetEQ when we are not playing. Count the
798 // packet as discarded.
799 WEBRTC_TRACE(kTraceStream, kTraceVoice,
800 VoEId(_instanceId, _channelId),
801 "received packet is discarded since playing is not"
802 " activated");
803 _numberOfDiscardedPackets++;
804 return 0;
805 }
806
807 // Push the incoming payload (parsed and ready for decoding) into the ACM
808 if (_audioCodingModule.IncomingPacket((const WebRtc_Word8*) payloadData,
809 payloadSize,
810 *rtpHeader) != 0)
811 {
812 _engineStatisticsPtr->SetLastError(
813 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
814 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
815 return -1;
816 }
817
818 // Update the packet delay
819 UpdatePacketDelay(rtpHeader->header.timestamp,
820 rtpHeader->header.sequenceNumber);
821
822 return 0;
823}
824
825WebRtc_Word32 Channel::GetAudioFrame(const WebRtc_Word32 id,
826 AudioFrame& audioFrame)
827{
828 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
829 "Channel::GetAudioFrame(id=%d)", id);
830
831 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
andrew@webrtc.org7859e102012-01-13 00:30:11 +0000832 if (_audioCodingModule.PlayoutData10Ms(audioFrame._frequencyInHz,
833 audioFrame) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000834 {
835 WEBRTC_TRACE(kTraceError, kTraceVoice,
836 VoEId(_instanceId,_channelId),
837 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
andrew@webrtc.org7859e102012-01-13 00:30:11 +0000838 // In all likelihood, the audio in this frame is garbage. We return an
839 // error so that the audio mixer module doesn't add it to the mix. As
840 // a result, it won't be played out and the actions skipped here are
841 // irrelevant.
842 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000843 }
844
845 if (_RxVadDetection)
846 {
847 UpdateRxVadDetection(audioFrame);
848 }
849
850 // Convert module ID to internal VoE channel ID
851 audioFrame._id = VoEChannelId(audioFrame._id);
852 // Store speech type for dead-or-alive detection
853 _outputSpeechType = audioFrame._speechType;
854
855 // Perform far-end AudioProcessing module processing on the received signal
856 if (_rxApmIsEnabled)
857 {
858 ApmProcessRx(audioFrame);
859 }
860
861 // Output volume scaling
862 if (_outputGain < 0.99f || _outputGain > 1.01f)
863 {
864 AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
865 }
866
867 // Scale left and/or right channel(s) if stereo and master balance is
868 // active
869
870 if (_panLeft != 1.0f || _panRight != 1.0f)
871 {
872 if (audioFrame._audioChannel == 1)
873 {
874 // Emulate stereo mode since panning is active.
875 // The mono signal is copied to both left and right channels here.
876 AudioFrameOperations::MonoToStereo(audioFrame);
877 }
878 // For true stereo mode (when we are receiving a stereo signal), no
879 // action is needed.
880
881 // Do the panning operation (the audio frame contains stereo at this
882 // stage)
883 AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
884 }
885
886 // Mix decoded PCM output with file if file mixing is enabled
887 if (_outputFilePlaying)
888 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000889 MixAudioWithFile(audioFrame, audioFrame._frequencyInHz);
890 }
891
892 // Place channel in on-hold state (~muted) if on-hold is activated
893 if (_outputIsOnHold)
894 {
895 AudioFrameOperations::Mute(audioFrame);
896 }
897
898 // External media
899 if (_outputExternalMedia)
900 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000901 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000902 const bool isStereo = (audioFrame._audioChannel == 2);
903 if (_outputExternalMediaCallbackPtr)
904 {
905 _outputExternalMediaCallbackPtr->Process(
906 _channelId,
907 kPlaybackPerChannel,
908 (WebRtc_Word16*)audioFrame._payloadData,
909 audioFrame._payloadDataLengthInSamples,
910 audioFrame._frequencyInHz,
911 isStereo);
912 }
913 }
914
915 // Record playout if enabled
916 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000917 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
919 if (_outputFileRecording && _outputFileRecorderPtr)
920 {
niklas.enbom@webrtc.org5398d952012-03-26 08:11:25 +0000921 _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000922 }
923 }
924
925 // Measure audio level (0-9)
926 _outputAudioLevel.ComputeLevel(audioFrame);
927
928 return 0;
929}
930
931WebRtc_Word32
932Channel::NeededFrequency(const WebRtc_Word32 id)
933{
934 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
935 "Channel::NeededFrequency(id=%d)", id);
936
937 int highestNeeded = 0;
938
939 // Determine highest needed receive frequency
940 WebRtc_Word32 receiveFrequency = _audioCodingModule.ReceiveFrequency();
941
942 // Return the bigger of playout and receive frequency in the ACM.
943 if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
944 {
945 highestNeeded = _audioCodingModule.PlayoutFrequency();
946 }
947 else
948 {
949 highestNeeded = receiveFrequency;
950 }
951
952 // Special case, if we're playing a file on the playout side
953 // we take that frequency into consideration as well
954 // This is not needed on sending side, since the codec will
955 // limit the spectrum anyway.
956 if (_outputFilePlaying)
957 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000958 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000959 if (_outputFilePlayerPtr && _outputFilePlaying)
960 {
961 if(_outputFilePlayerPtr->Frequency()>highestNeeded)
962 {
963 highestNeeded=_outputFilePlayerPtr->Frequency();
964 }
965 }
966 }
967
968 return(highestNeeded);
969}
970
niklase@google.com470e71d2011-07-07 08:21:25 +0000971WebRtc_Word32
972Channel::CreateChannel(Channel*& channel,
973 const WebRtc_Word32 channelId,
974 const WebRtc_UWord32 instanceId)
975{
976 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
977 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
978 channelId, instanceId);
979
980 channel = new Channel(channelId, instanceId);
981 if (channel == NULL)
982 {
983 WEBRTC_TRACE(kTraceMemory, kTraceVoice,
984 VoEId(instanceId,channelId),
985 "Channel::CreateChannel() unable to allocate memory for"
986 " channel");
987 return -1;
988 }
989 return 0;
990}
991
992void
993Channel::PlayNotification(const WebRtc_Word32 id,
994 const WebRtc_UWord32 durationMs)
995{
996 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
997 "Channel::PlayNotification(id=%d, durationMs=%d)",
998 id, durationMs);
999
1000 // Not implement yet
1001}
1002
1003void
1004Channel::RecordNotification(const WebRtc_Word32 id,
1005 const WebRtc_UWord32 durationMs)
1006{
1007 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1008 "Channel::RecordNotification(id=%d, durationMs=%d)",
1009 id, durationMs);
1010
1011 // Not implement yet
1012}
1013
1014void
1015Channel::PlayFileEnded(const WebRtc_Word32 id)
1016{
1017 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1018 "Channel::PlayFileEnded(id=%d)", id);
1019
1020 if (id == _inputFilePlayerId)
1021 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001022 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001023
1024 _inputFilePlaying = false;
1025 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1026 VoEId(_instanceId,_channelId),
1027 "Channel::PlayFileEnded() => input file player module is"
1028 " shutdown");
1029 }
1030 else if (id == _outputFilePlayerId)
1031 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001032 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001033
1034 _outputFilePlaying = false;
1035 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1036 VoEId(_instanceId,_channelId),
1037 "Channel::PlayFileEnded() => output file player module is"
1038 " shutdown");
1039 }
1040}
1041
1042void
1043Channel::RecordFileEnded(const WebRtc_Word32 id)
1044{
1045 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1046 "Channel::RecordFileEnded(id=%d)", id);
1047
1048 assert(id == _outputFileRecorderId);
1049
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001050 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001051
1052 _outputFileRecording = false;
1053 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1054 VoEId(_instanceId,_channelId),
1055 "Channel::RecordFileEnded() => output file recorder module is"
1056 " shutdown");
1057}
1058
1059Channel::Channel(const WebRtc_Word32 channelId,
1060 const WebRtc_UWord32 instanceId) :
1061 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1062 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001063 _instanceId(instanceId),
xians@google.com22963ab2011-08-03 12:40:23 +00001064 _channelId(channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001065 _rtpRtcpModule(*RtpRtcp::CreateRtpRtcp(VoEModuleId(
xians@google.com22963ab2011-08-03 12:40:23 +00001066 instanceId, channelId), true)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001067 _audioCodingModule(*AudioCodingModule::Create(
xians@google.com22963ab2011-08-03 12:40:23 +00001068 VoEModuleId(instanceId, channelId))),
niklase@google.com470e71d2011-07-07 08:21:25 +00001069#ifndef WEBRTC_EXTERNAL_TRANSPORT
perkj@webrtc.org68f21682011-11-30 18:11:23 +00001070 _numSocketThreads(KNumSocketThreads),
xians@google.com22963ab2011-08-03 12:40:23 +00001071 _socketTransportModule(*UdpTransport::Create(
perkj@webrtc.org68f21682011-11-30 18:11:23 +00001072 VoEModuleId(instanceId, channelId), _numSocketThreads)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001073#endif
1074#ifdef WEBRTC_SRTP
1075 _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId,
1076 channelId))),
1077#endif
1078 _rtpDumpIn(*RtpDump::CreateRtpDump()),
1079 _rtpDumpOut(*RtpDump::CreateRtpDump()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001080 _outputAudioLevel(),
niklase@google.com470e71d2011-07-07 08:21:25 +00001081 _externalTransport(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001082 _inputFilePlayerPtr(NULL),
1083 _outputFilePlayerPtr(NULL),
1084 _outputFileRecorderPtr(NULL),
1085 // Avoid conflict with other channels by adding 1024 - 1026,
1086 // won't use as much as 1024 channels.
1087 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
1088 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
1089 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
1090 _inputFilePlaying(false),
1091 _outputFilePlaying(false),
1092 _outputFileRecording(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001093 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
1094 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001095 _inputExternalMedia(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001096 _outputExternalMedia(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001097 _inputExternalMediaCallbackPtr(NULL),
1098 _outputExternalMediaCallbackPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001099 _encryptionRTPBufferPtr(NULL),
1100 _decryptionRTPBufferPtr(NULL),
1101 _encryptionRTCPBufferPtr(NULL),
1102 _decryptionRTCPBufferPtr(NULL),
1103 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
1104 _sendTelephoneEventPayloadType(106),
1105 _playoutTimeStampRTP(0),
1106 _playoutTimeStampRTCP(0),
1107 _numberOfDiscardedPackets(0),
1108 _engineStatisticsPtr(NULL),
henrika@webrtc.org2919e952012-01-31 08:45:03 +00001109 _outputMixerPtr(NULL),
1110 _transmitMixerPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001111 _moduleProcessThreadPtr(NULL),
1112 _audioDeviceModulePtr(NULL),
1113 _voiceEngineObserverPtr(NULL),
1114 _callbackCritSectPtr(NULL),
1115 _transportPtr(NULL),
1116 _encryptionPtr(NULL),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001117 _rtpAudioProc(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001118 _rxAudioProcessingModulePtr(NULL),
1119#ifdef WEBRTC_DTMF_DETECTION
1120 _telephoneEventDetectionPtr(NULL),
1121#endif
1122 _rxVadObserverPtr(NULL),
1123 _oldVadDecision(-1),
1124 _sendFrameType(0),
niklase@google.com470e71d2011-07-07 08:21:25 +00001125 _rtpObserverPtr(NULL),
1126 _rtcpObserverPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001127 _outputIsOnHold(false),
1128 _externalPlayout(false),
1129 _inputIsOnHold(false),
1130 _playing(false),
1131 _sending(false),
1132 _receiving(false),
1133 _mixFileWithMicrophone(false),
1134 _rtpObserver(false),
1135 _rtcpObserver(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001136 _mute(false),
1137 _panLeft(1.0f),
1138 _panRight(1.0f),
1139 _outputGain(1.0f),
xians@google.com22963ab2011-08-03 12:40:23 +00001140 _encrypting(false),
1141 _decrypting(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001142 _playOutbandDtmfEvent(false),
1143 _playInbandDtmfEvent(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001144 _inbandTelephoneEventDetection(false),
1145 _outOfBandTelephoneEventDetecion(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001146 _extraPayloadType(0),
1147 _insertExtraRTPPacket(false),
1148 _extraMarkerBit(false),
1149 _lastLocalTimeStamp(0),
1150 _lastPayloadType(0),
xians@google.com22963ab2011-08-03 12:40:23 +00001151 _includeAudioLevelIndication(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001152 _rtpPacketTimedOut(false),
1153 _rtpPacketTimeOutIsEnabled(false),
1154 _rtpTimeOutSeconds(0),
1155 _connectionObserver(false),
1156 _connectionObserverPtr(NULL),
1157 _countAliveDetections(0),
1158 _countDeadDetections(0),
1159 _outputSpeechType(AudioFrame::kNormalSpeech),
1160 _averageDelayMs(0),
1161 _previousSequenceNumber(0),
1162 _previousTimestamp(0),
1163 _recPacketDelayMs(20),
1164 _RxVadDetection(false),
1165 _rxApmIsEnabled(false),
1166 _rxAgcIsEnabled(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001167 _rxNsIsEnabled(false)
niklase@google.com470e71d2011-07-07 08:21:25 +00001168{
1169 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1170 "Channel::Channel() - ctor");
1171 _inbandDtmfQueue.ResetDtmf();
1172 _inbandDtmfGenerator.Init();
1173 _outputAudioLevel.Clear();
1174
1175 // Create far end AudioProcessing Module
1176 _rxAudioProcessingModulePtr = AudioProcessing::Create(
1177 VoEModuleId(instanceId, channelId));
1178}
1179
1180Channel::~Channel()
1181{
1182 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1183 "Channel::~Channel() - dtor");
1184
1185 if (_outputExternalMedia)
1186 {
1187 DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1188 }
1189 if (_inputExternalMedia)
1190 {
1191 DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1192 }
1193 StopSend();
1194#ifndef WEBRTC_EXTERNAL_TRANSPORT
1195 StopReceiving();
1196 // De-register packet callback to ensure we're not in a callback when
1197 // deleting channel state, avoids race condition and deadlock.
1198 if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0)
1199 != 0)
1200 {
1201 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1202 VoEId(_instanceId, _channelId),
1203 "~Channel() failed to de-register receive callback");
1204 }
1205#endif
1206 StopPlayout();
1207
1208 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001209 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001210 if (_inputFilePlayerPtr)
1211 {
1212 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1213 _inputFilePlayerPtr->StopPlayingFile();
1214 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1215 _inputFilePlayerPtr = NULL;
1216 }
1217 if (_outputFilePlayerPtr)
1218 {
1219 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1220 _outputFilePlayerPtr->StopPlayingFile();
1221 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1222 _outputFilePlayerPtr = NULL;
1223 }
1224 if (_outputFileRecorderPtr)
1225 {
1226 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1227 _outputFileRecorderPtr->StopRecording();
1228 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1229 _outputFileRecorderPtr = NULL;
1230 }
1231 }
1232
1233 // The order to safely shutdown modules in a channel is:
1234 // 1. De-register callbacks in modules
1235 // 2. De-register modules in process thread
1236 // 3. Destroy modules
1237
1238 // De-register all RTP module callbacks to ensure geting no callbacks
1239 // (Receive socket callback was de-registered above)
1240 if (_rtpRtcpModule.RegisterIncomingDataCallback(NULL) == -1)
1241 {
1242 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1243 VoEId(_instanceId,_channelId),
1244 "~Channel() failed to de-register incoming data callback"
1245 " (RTP module)");
1246 }
1247 if (_rtpRtcpModule.RegisterSendTransport(NULL) == -1)
1248 {
1249 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1250 VoEId(_instanceId,_channelId),
1251 "~Channel() failed to de-register send transport "
1252 "(RTP module)");
1253 }
1254 if (_rtpRtcpModule.RegisterIncomingRTPCallback(NULL) == -1)
1255 {
1256 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1257 VoEId(_instanceId,_channelId),
1258 "~Channel() failed to de-register incoming RTP"
1259 " callback (RTP module)");
1260 }
1261 if (_rtpRtcpModule.RegisterIncomingRTCPCallback(NULL) == -1)
1262 {
1263 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1264 VoEId(_instanceId,_channelId),
1265 "~Channel() failed to de-register incoming RTCP "
1266 "callback (RTP module)");
1267 }
1268 if (_rtpRtcpModule.RegisterAudioCallback(NULL) == -1)
1269 {
1270 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1271 VoEId(_instanceId,_channelId),
1272 "~Channel() failed to de-register audio callback "
1273 "(RTP module)");
1274 }
1275 if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1276 {
1277 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1278 VoEId(_instanceId,_channelId),
1279 "~Channel() failed to de-register transport callback"
1280 " (Audio coding module)");
1281 }
1282 if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1283 {
1284 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1285 VoEId(_instanceId,_channelId),
1286 "~Channel() failed to de-register VAD callback"
1287 " (Audio coding module)");
1288 }
1289#ifdef WEBRTC_DTMF_DETECTION
1290 if (_audioCodingModule.RegisterIncomingMessagesCallback(NULL) == -1)
1291 {
1292 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1293 VoEId(_instanceId,_channelId),
1294 "~Channel() failed to de-register incoming messages "
1295 "callback (Audio coding module)");
1296 }
1297#endif
1298 // De-register modules in process thread
1299#ifndef WEBRTC_EXTERNAL_TRANSPORT
1300 if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule)
1301 == -1)
1302 {
1303 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1304 VoEId(_instanceId,_channelId),
1305 "~Channel() failed to deregister socket module");
1306 }
1307#endif
1308 if (_moduleProcessThreadPtr->DeRegisterModule(&_rtpRtcpModule) == -1)
1309 {
1310 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1311 VoEId(_instanceId,_channelId),
1312 "~Channel() failed to deregister RTP/RTCP module");
1313 }
1314
1315 // Destroy modules
1316#ifndef WEBRTC_EXTERNAL_TRANSPORT
1317 UdpTransport::Destroy(
1318 &_socketTransportModule);
1319#endif
1320 RtpRtcp::DestroyRtpRtcp(&_rtpRtcpModule);
1321 AudioCodingModule::Destroy(&_audioCodingModule);
1322#ifdef WEBRTC_SRTP
1323 SrtpModule::DestroySrtpModule(&_srtpModule);
1324#endif
1325 if (_rxAudioProcessingModulePtr != NULL)
1326 {
1327 AudioProcessing::Destroy(_rxAudioProcessingModulePtr); // far end APM
1328 _rxAudioProcessingModulePtr = NULL;
1329 }
1330
1331 // End of modules shutdown
1332
1333 // Delete other objects
1334 RtpDump::DestroyRtpDump(&_rtpDumpIn);
1335 RtpDump::DestroyRtpDump(&_rtpDumpOut);
1336 delete [] _encryptionRTPBufferPtr;
1337 delete [] _decryptionRTPBufferPtr;
1338 delete [] _encryptionRTCPBufferPtr;
1339 delete [] _decryptionRTCPBufferPtr;
1340 delete &_callbackCritSect;
niklase@google.com470e71d2011-07-07 08:21:25 +00001341 delete &_fileCritSect;
1342}
1343
1344WebRtc_Word32
1345Channel::Init()
1346{
1347 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1348 "Channel::Init()");
1349
1350 // --- Initial sanity
1351
1352 if ((_engineStatisticsPtr == NULL) ||
1353 (_moduleProcessThreadPtr == NULL))
1354 {
1355 WEBRTC_TRACE(kTraceError, kTraceVoice,
1356 VoEId(_instanceId,_channelId),
1357 "Channel::Init() must call SetEngineInformation() first");
1358 return -1;
1359 }
1360
1361 // --- Add modules to process thread (for periodic schedulation)
1362
1363 const bool processThreadFail =
1364 ((_moduleProcessThreadPtr->RegisterModule(&_rtpRtcpModule) != 0) ||
1365#ifndef WEBRTC_EXTERNAL_TRANSPORT
1366 (_moduleProcessThreadPtr->RegisterModule(
1367 &_socketTransportModule) != 0));
1368#else
1369 false);
1370#endif
1371 if (processThreadFail)
1372 {
1373 _engineStatisticsPtr->SetLastError(
1374 VE_CANNOT_INIT_CHANNEL, kTraceError,
1375 "Channel::Init() modules not registered");
1376 return -1;
1377 }
pwestin@webrtc.orgc450a192012-01-04 15:00:12 +00001378 // --- ACM initialization
niklase@google.com470e71d2011-07-07 08:21:25 +00001379
1380 if ((_audioCodingModule.InitializeReceiver() == -1) ||
1381#ifdef WEBRTC_CODEC_AVT
1382 // out-of-band Dtmf tones are played out by default
1383 (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1384#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001385 (_audioCodingModule.InitializeSender() == -1))
1386 {
1387 _engineStatisticsPtr->SetLastError(
1388 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1389 "Channel::Init() unable to initialize the ACM - 1");
1390 return -1;
1391 }
1392
1393 // --- RTP/RTCP module initialization
1394
1395 // Ensure that RTCP is enabled by default for the created channel.
1396 // Note that, the module will keep generating RTCP until it is explicitly
1397 // disabled by the user.
1398 // After StopListen (when no sockets exists), RTCP packets will no longer
1399 // be transmitted since the Transport object will then be invalid.
1400
1401 const bool rtpRtcpFail =
1402 ((_rtpRtcpModule.InitReceiver() == -1) ||
1403 (_rtpRtcpModule.InitSender() == -1) ||
1404 (_rtpRtcpModule.SetTelephoneEventStatus(false, true, true) == -1) ||
1405 // RTCP is enabled by default
1406 (_rtpRtcpModule.SetRTCPStatus(kRtcpCompound) == -1));
1407 if (rtpRtcpFail)
1408 {
1409 _engineStatisticsPtr->SetLastError(
1410 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1411 "Channel::Init() RTP/RTCP module not initialized");
1412 return -1;
1413 }
1414
1415 // --- Register all permanent callbacks
1416
1417 const bool fail =
1418 (_rtpRtcpModule.RegisterIncomingDataCallback(this) == -1) ||
1419 (_rtpRtcpModule.RegisterIncomingRTPCallback(this) == -1) ||
1420 (_rtpRtcpModule.RegisterIncomingRTCPCallback(this) == -1) ||
1421 (_rtpRtcpModule.RegisterSendTransport(this) == -1) ||
1422 (_rtpRtcpModule.RegisterAudioCallback(this) == -1) ||
1423 (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1424 (_audioCodingModule.RegisterVADCallback(this) == -1);
1425
1426 if (fail)
1427 {
1428 _engineStatisticsPtr->SetLastError(
1429 VE_CANNOT_INIT_CHANNEL, kTraceError,
1430 "Channel::Init() callbacks not registered");
1431 return -1;
1432 }
1433
1434 // --- Register all supported codecs to the receiving side of the
1435 // RTP/RTCP module
1436
1437 CodecInst codec;
1438 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1439
1440 for (int idx = 0; idx < nSupportedCodecs; idx++)
1441 {
1442 // Open up the RTP/RTCP receiver for all supported codecs
1443 if ((_audioCodingModule.Codec(idx, codec) == -1) ||
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001444 (_rtpRtcpModule.RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001445 {
1446 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1447 VoEId(_instanceId,_channelId),
1448 "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1449 "to RTP/RTCP receiver",
1450 codec.plname, codec.pltype, codec.plfreq,
1451 codec.channels, codec.rate);
1452 }
1453 else
1454 {
1455 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1456 VoEId(_instanceId,_channelId),
1457 "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1458 "the RTP/RTCP receiver",
1459 codec.plname, codec.pltype, codec.plfreq,
1460 codec.channels, codec.rate);
1461 }
1462
1463 // Ensure that PCMU is used as default codec on the sending side
1464 if (!STR_CASE_CMP(codec.plname, "PCMU"))
1465 {
1466 SetSendCodec(codec);
1467 }
1468
1469 // Register default PT for outband 'telephone-event'
1470 if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1471 {
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001472 if ((_rtpRtcpModule.RegisterSendPayload(codec) == -1) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001473 (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1474 {
1475 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1476 VoEId(_instanceId,_channelId),
1477 "Channel::Init() failed to register outband "
1478 "'telephone-event' (%d/%d) correctly",
1479 codec.pltype, codec.plfreq);
1480 }
1481 }
1482
1483 if (!STR_CASE_CMP(codec.plname, "CN"))
1484 {
1485 if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1486 (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00001487 (_rtpRtcpModule.RegisterSendPayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001488 {
1489 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1490 VoEId(_instanceId,_channelId),
1491 "Channel::Init() failed to register CN (%d/%d) "
1492 "correctly - 1",
1493 codec.pltype, codec.plfreq);
1494 }
1495 }
1496#ifdef WEBRTC_CODEC_RED
1497 // Register RED to the receiving side of the ACM.
1498 // We will not receive an OnInitializeDecoder() callback for RED.
1499 if (!STR_CASE_CMP(codec.plname, "RED"))
1500 {
1501 if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1502 {
1503 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1504 VoEId(_instanceId,_channelId),
1505 "Channel::Init() failed to register RED (%d/%d) "
1506 "correctly",
1507 codec.pltype, codec.plfreq);
1508 }
1509 }
1510#endif
1511 }
1512#ifndef WEBRTC_EXTERNAL_TRANSPORT
1513 // Ensure that the WebRtcSocketTransport implementation is used as
1514 // Transport on the sending side
xians@webrtc.org83661f52011-11-25 10:58:15 +00001515 {
1516 // A lock is needed here since users can call
1517 // RegisterExternalTransport() at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001518 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +00001519 _transportPtr = &_socketTransportModule;
1520 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001521#endif
1522
1523 // Initialize the far end AP module
1524 // Using 8 kHz as initial Fs, the same as in transmission. Might be
1525 // changed at the first receiving audio.
1526 if (_rxAudioProcessingModulePtr == NULL)
1527 {
1528 _engineStatisticsPtr->SetLastError(
1529 VE_NO_MEMORY, kTraceCritical,
1530 "Channel::Init() failed to create the far-end AudioProcessing"
1531 " module");
1532 return -1;
1533 }
1534
niklase@google.com470e71d2011-07-07 08:21:25 +00001535 if (_rxAudioProcessingModulePtr->set_sample_rate_hz(8000))
1536 {
1537 _engineStatisticsPtr->SetLastError(
1538 VE_APM_ERROR, kTraceWarning,
1539 "Channel::Init() failed to set the sample rate to 8K for"
1540 " far-end AP module");
1541 }
1542
1543 if (_rxAudioProcessingModulePtr->set_num_channels(1, 1) != 0)
1544 {
1545 _engineStatisticsPtr->SetLastError(
1546 VE_SOUNDCARD_ERROR, kTraceWarning,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001547 "Init() failed to set channels for the primary audio stream");
niklase@google.com470e71d2011-07-07 08:21:25 +00001548 }
1549
1550 if (_rxAudioProcessingModulePtr->high_pass_filter()->Enable(
1551 WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1552 {
1553 _engineStatisticsPtr->SetLastError(
1554 VE_APM_ERROR, kTraceWarning,
1555 "Channel::Init() failed to set the high-pass filter for"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001556 " far-end AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001557 }
1558
1559 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(
1560 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1561 {
1562 _engineStatisticsPtr->SetLastError(
1563 VE_APM_ERROR, kTraceWarning,
1564 "Init() failed to set noise reduction level for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001565 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001566 }
1567 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(
1568 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1569 {
1570 _engineStatisticsPtr->SetLastError(
1571 VE_APM_ERROR, kTraceWarning,
1572 "Init() failed to set noise reduction state for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001573 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001574 }
1575
1576 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(
1577 (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1578 {
1579 _engineStatisticsPtr->SetLastError(
1580 VE_APM_ERROR, kTraceWarning,
1581 "Init() failed to set AGC mode for far-end AP module");
1582 }
1583 if (_rxAudioProcessingModulePtr->gain_control()->Enable(
1584 WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1585 {
1586 _engineStatisticsPtr->SetLastError(
1587 VE_APM_ERROR, kTraceWarning,
1588 "Init() failed to set AGC state for far-end AP module");
1589 }
1590
1591 return 0;
1592}
1593
1594WebRtc_Word32
1595Channel::SetEngineInformation(Statistics& engineStatistics,
1596 OutputMixer& outputMixer,
1597 voe::TransmitMixer& transmitMixer,
1598 ProcessThread& moduleProcessThread,
1599 AudioDeviceModule& audioDeviceModule,
1600 VoiceEngineObserver* voiceEngineObserver,
1601 CriticalSectionWrapper* callbackCritSect)
1602{
1603 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1604 "Channel::SetEngineInformation()");
1605 _engineStatisticsPtr = &engineStatistics;
1606 _outputMixerPtr = &outputMixer;
1607 _transmitMixerPtr = &transmitMixer,
1608 _moduleProcessThreadPtr = &moduleProcessThread;
1609 _audioDeviceModulePtr = &audioDeviceModule;
1610 _voiceEngineObserverPtr = voiceEngineObserver;
1611 _callbackCritSectPtr = callbackCritSect;
1612 return 0;
1613}
1614
1615WebRtc_Word32
1616Channel::UpdateLocalTimeStamp()
1617{
1618
1619 _timeStamp += _audioFrame._payloadDataLengthInSamples;
1620 return 0;
1621}
1622
1623WebRtc_Word32
1624Channel::StartPlayout()
1625{
1626 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1627 "Channel::StartPlayout()");
1628 if (_playing)
1629 {
1630 return 0;
1631 }
1632 // Add participant as candidates for mixing.
1633 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1634 {
1635 _engineStatisticsPtr->SetLastError(
1636 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1637 "StartPlayout() failed to add participant to mixer");
1638 return -1;
1639 }
1640
1641 _playing = true;
1642 return 0;
1643}
1644
1645WebRtc_Word32
1646Channel::StopPlayout()
1647{
1648 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1649 "Channel::StopPlayout()");
1650 if (!_playing)
1651 {
1652 return 0;
1653 }
1654 // Remove participant as candidates for mixing
1655 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1656 {
1657 _engineStatisticsPtr->SetLastError(
1658 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1659 "StartPlayout() failed to remove participant from mixer");
1660 return -1;
1661 }
1662
1663 _playing = false;
1664 _outputAudioLevel.Clear();
1665
1666 return 0;
1667}
1668
1669WebRtc_Word32
1670Channel::StartSend()
1671{
1672 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1673 "Channel::StartSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001674 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001675 // A lock is needed because |_sending| can be accessed or modified by
1676 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001677 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001678
1679 if (_sending)
1680 {
1681 return 0;
1682 }
1683 _sending = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001684 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001685
niklase@google.com470e71d2011-07-07 08:21:25 +00001686 if (_rtpRtcpModule.SetSendingStatus(true) != 0)
1687 {
1688 _engineStatisticsPtr->SetLastError(
1689 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1690 "StartSend() RTP/RTCP failed to start sending");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001691 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001692 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001693 return -1;
1694 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001695
niklase@google.com470e71d2011-07-07 08:21:25 +00001696 return 0;
1697}
1698
1699WebRtc_Word32
1700Channel::StopSend()
1701{
1702 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1703 "Channel::StopSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001704 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001705 // A lock is needed because |_sending| can be accessed or modified by
1706 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001707 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001708
1709 if (!_sending)
1710 {
1711 return 0;
1712 }
1713 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001714 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001715
niklase@google.com470e71d2011-07-07 08:21:25 +00001716 // Reset sending SSRC and sequence number and triggers direct transmission
1717 // of RTCP BYE
1718 if (_rtpRtcpModule.SetSendingStatus(false) == -1 ||
1719 _rtpRtcpModule.ResetSendDataCountersRTP() == -1)
1720 {
1721 _engineStatisticsPtr->SetLastError(
1722 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1723 "StartSend() RTP/RTCP failed to stop sending");
1724 }
1725
niklase@google.com470e71d2011-07-07 08:21:25 +00001726 return 0;
1727}
1728
1729WebRtc_Word32
1730Channel::StartReceiving()
1731{
1732 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1733 "Channel::StartReceiving()");
1734 if (_receiving)
1735 {
1736 return 0;
1737 }
1738 // If external transport is used, we will only initialize/set the variables
1739 // after this section, since we are not using the WebRtc transport but
1740 // still need to keep track of e.g. if we are receiving.
1741#ifndef WEBRTC_EXTERNAL_TRANSPORT
1742 if (!_externalTransport)
1743 {
1744 if (!_socketTransportModule.ReceiveSocketsInitialized())
1745 {
1746 _engineStatisticsPtr->SetLastError(
1747 VE_SOCKETS_NOT_INITED, kTraceError,
1748 "StartReceive() must set local receiver first");
1749 return -1;
1750 }
1751 if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0)
1752 {
1753 _engineStatisticsPtr->SetLastError(
1754 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1755 "StartReceiving() failed to start receiving");
1756 return -1;
1757 }
1758 }
1759#endif
1760 _receiving = true;
1761 _numberOfDiscardedPackets = 0;
1762 return 0;
1763}
1764
1765WebRtc_Word32
1766Channel::StopReceiving()
1767{
1768 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1769 "Channel::StopReceiving()");
1770 if (!_receiving)
1771 {
1772 return 0;
1773 }
1774
1775#ifndef WEBRTC_EXTERNAL_TRANSPORT
1776 if (!_externalTransport &&
1777 _socketTransportModule.ReceiveSocketsInitialized())
1778 {
1779 if (_socketTransportModule.StopReceiving() != 0)
1780 {
1781 _engineStatisticsPtr->SetLastError(
1782 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001783 "StopReceiving() failed to stop receiving.");
niklase@google.com470e71d2011-07-07 08:21:25 +00001784 return -1;
1785 }
1786 }
1787#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001788 bool dtmfDetection = _rtpRtcpModule.TelephoneEvent();
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001789 WebRtc_Word32 ret = _rtpRtcpModule.InitReceiver();
1790 if (ret != 0) {
1791 _engineStatisticsPtr->SetLastError(
1792 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1793 "StopReceiving() failed to reinitialize the RTP receiver.");
1794 return -1;
1795 }
1796 // Recover DTMF detection status.
1797 ret = _rtpRtcpModule.SetTelephoneEventStatus(dtmfDetection, true, true);
1798 if (ret != 0) {
1799 _engineStatisticsPtr->SetLastError(
1800 VE_INVALID_OPERATION, kTraceWarning,
1801 "StopReceiving() failed to restore telephone-event status.");
1802 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001803 RegisterReceiveCodecsToRTPModule();
1804 _receiving = false;
1805 return 0;
1806}
1807
1808#ifndef WEBRTC_EXTERNAL_TRANSPORT
1809WebRtc_Word32
1810Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort,
1811 const WebRtc_UWord16 rtcpPort,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001812 const char ipAddr[64],
1813 const char multicastIpAddr[64])
niklase@google.com470e71d2011-07-07 08:21:25 +00001814{
1815 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1816 "Channel::SetLocalReceiver()");
1817
1818 if (_externalTransport)
1819 {
1820 _engineStatisticsPtr->SetLastError(
1821 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1822 "SetLocalReceiver() conflict with external transport");
1823 return -1;
1824 }
1825
1826 if (_sending)
1827 {
1828 _engineStatisticsPtr->SetLastError(
1829 VE_ALREADY_SENDING, kTraceError,
1830 "SetLocalReceiver() already sending");
1831 return -1;
1832 }
1833 if (_receiving)
1834 {
1835 _engineStatisticsPtr->SetLastError(
1836 VE_ALREADY_LISTENING, kTraceError,
1837 "SetLocalReceiver() already receiving");
1838 return -1;
1839 }
1840
1841 if (_socketTransportModule.InitializeReceiveSockets(this,
1842 rtpPort,
1843 ipAddr,
1844 multicastIpAddr,
1845 rtcpPort) != 0)
1846 {
1847 UdpTransport::ErrorCode lastSockError(
1848 _socketTransportModule.LastError());
1849 switch (lastSockError)
1850 {
1851 case UdpTransport::kIpAddressInvalid:
1852 _engineStatisticsPtr->SetLastError(
1853 VE_INVALID_IP_ADDRESS, kTraceError,
1854 "SetLocalReceiver() invalid IP address");
1855 break;
1856 case UdpTransport::kSocketInvalid:
1857 _engineStatisticsPtr->SetLastError(
1858 VE_SOCKET_ERROR, kTraceError,
1859 "SetLocalReceiver() invalid socket");
1860 break;
1861 case UdpTransport::kPortInvalid:
1862 _engineStatisticsPtr->SetLastError(
1863 VE_INVALID_PORT_NMBR, kTraceError,
1864 "SetLocalReceiver() invalid port");
1865 break;
1866 case UdpTransport::kFailedToBindPort:
1867 _engineStatisticsPtr->SetLastError(
1868 VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError,
1869 "SetLocalReceiver() binding failed");
1870 break;
1871 default:
1872 _engineStatisticsPtr->SetLastError(
1873 VE_SOCKET_ERROR, kTraceError,
1874 "SetLocalReceiver() undefined socket error");
1875 break;
1876 }
1877 return -1;
1878 }
1879 return 0;
1880}
1881#endif
1882
1883#ifndef WEBRTC_EXTERNAL_TRANSPORT
1884WebRtc_Word32
1885Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64])
1886{
1887 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1888 "Channel::GetLocalReceiver()");
1889
1890 if (_externalTransport)
1891 {
1892 _engineStatisticsPtr->SetLastError(
1893 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1894 "SetLocalReceiver() conflict with external transport");
1895 return -1;
1896 }
1897
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001898 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00001899 WebRtc_UWord16 rtpPort(0);
1900 WebRtc_UWord16 rtcpPort(0);
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001901 char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00001902
1903 // Acquire socket information from the socket module
1904 if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp,
1905 rtpPort,
1906 rtcpPort,
1907 multicastIpAddr) != 0)
1908 {
1909 _engineStatisticsPtr->SetLastError(
1910 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1911 "GetLocalReceiver() unable to retrieve socket information");
1912 return -1;
1913 }
1914
1915 // Deliver valid results to the user
1916 port = static_cast<int> (rtpPort);
1917 RTCPport = static_cast<int> (rtcpPort);
1918 if (ipAddr != NULL)
1919 {
1920 strcpy(ipAddr, ipAddrTmp);
1921 }
1922 return 0;
1923}
1924#endif
1925
1926#ifndef WEBRTC_EXTERNAL_TRANSPORT
1927WebRtc_Word32
1928Channel::SetSendDestination(const WebRtc_UWord16 rtpPort,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00001929 const char ipAddr[64],
niklase@google.com470e71d2011-07-07 08:21:25 +00001930 const int sourcePort,
1931 const WebRtc_UWord16 rtcpPort)
1932{
1933 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1934 "Channel::SetSendDestination()");
1935
1936 if (_externalTransport)
1937 {
1938 _engineStatisticsPtr->SetLastError(
1939 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1940 "SetSendDestination() conflict with external transport");
1941 return -1;
1942 }
1943
1944 // Initialize ports and IP address for the remote (destination) side.
1945 // By default, the sockets used for receiving are used for transmission as
1946 // well, hence the source ports for outgoing packets are the same as the
1947 // receiving ports specified in SetLocalReceiver.
1948 // If an extra send socket has been created, it will be utilized until a
1949 // new source port is specified or until the channel has been deleted and
1950 // recreated. If no socket exists, sockets will be created when the first
1951 // RTP and RTCP packets shall be transmitted (see e.g.
1952 // UdpTransportImpl::SendPacket()).
1953 //
1954 // NOTE: this function does not require that sockets exists; all it does is
1955 // to build send structures to be used with the sockets when they exist.
1956 // It is therefore possible to call this method before SetLocalReceiver.
1957 // However, sockets must exist if a multi-cast address is given as input.
1958
1959 // Build send structures and enable QoS (if enabled and supported)
1960 if (_socketTransportModule.InitializeSendSockets(
1961 ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError)
1962 {
1963 UdpTransport::ErrorCode lastSockError(
1964 _socketTransportModule.LastError());
1965 switch (lastSockError)
1966 {
1967 case UdpTransport::kIpAddressInvalid:
1968 _engineStatisticsPtr->SetLastError(
1969 VE_INVALID_IP_ADDRESS, kTraceError,
1970 "SetSendDestination() invalid IP address 1");
1971 break;
1972 case UdpTransport::kSocketInvalid:
1973 _engineStatisticsPtr->SetLastError(
1974 VE_SOCKET_ERROR, kTraceError,
1975 "SetSendDestination() invalid socket 1");
1976 break;
1977 case UdpTransport::kQosError:
1978 _engineStatisticsPtr->SetLastError(
1979 VE_GQOS_ERROR, kTraceError,
1980 "SetSendDestination() failed to set QoS");
1981 break;
1982 case UdpTransport::kMulticastAddressInvalid:
1983 _engineStatisticsPtr->SetLastError(
1984 VE_INVALID_MULTICAST_ADDRESS, kTraceError,
1985 "SetSendDestination() invalid multicast address");
1986 break;
1987 default:
1988 _engineStatisticsPtr->SetLastError(
1989 VE_SOCKET_ERROR, kTraceError,
1990 "SetSendDestination() undefined socket error 1");
1991 break;
1992 }
1993 return -1;
1994 }
1995
1996 // Check if the user has specified a non-default source port different from
1997 // the local receive port.
1998 // If so, an extra local socket will be created unless the source port is
1999 // not unique.
2000 if (sourcePort != kVoEDefault)
2001 {
2002 WebRtc_UWord16 receiverRtpPort(0);
2003 WebRtc_UWord16 rtcpNA(0);
2004 if (_socketTransportModule.ReceiveSocketInformation(NULL,
2005 receiverRtpPort,
2006 rtcpNA,
2007 NULL) != 0)
2008 {
2009 _engineStatisticsPtr->SetLastError(
2010 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
2011 "SetSendDestination() failed to retrieve socket information");
2012 return -1;
2013 }
2014
2015 WebRtc_UWord16 sourcePortUW16 =
2016 static_cast<WebRtc_UWord16> (sourcePort);
2017
2018 // An extra socket will only be created if the specified source port
2019 // differs from the local receive port.
2020 if (sourcePortUW16 != receiverRtpPort)
2021 {
2022 // Initialize extra local socket to get a different source port
2023 // than the local
2024 // receiver port. Always use default source for RTCP.
2025 // Note that, this calls UdpTransport::CloseSendSockets().
2026 if (_socketTransportModule.InitializeSourcePorts(
2027 sourcePortUW16,
2028 sourcePortUW16+1) != 0)
2029 {
2030 UdpTransport::ErrorCode lastSockError(
2031 _socketTransportModule.LastError());
2032 switch (lastSockError)
2033 {
2034 case UdpTransport::kIpAddressInvalid:
2035 _engineStatisticsPtr->SetLastError(
2036 VE_INVALID_IP_ADDRESS, kTraceError,
2037 "SetSendDestination() invalid IP address 2");
2038 break;
2039 case UdpTransport::kSocketInvalid:
2040 _engineStatisticsPtr->SetLastError(
2041 VE_SOCKET_ERROR, kTraceError,
2042 "SetSendDestination() invalid socket 2");
2043 break;
2044 default:
2045 _engineStatisticsPtr->SetLastError(
2046 VE_SOCKET_ERROR, kTraceError,
2047 "SetSendDestination() undefined socket error 2");
2048 break;
2049 }
2050 return -1;
2051 }
2052 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2053 VoEId(_instanceId,_channelId),
2054 "SetSendDestination() extra local socket is created"
2055 " to facilitate unique source port");
2056 }
2057 else
2058 {
2059 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
2060 VoEId(_instanceId,_channelId),
2061 "SetSendDestination() sourcePort equals the local"
2062 " receive port => no extra socket is created");
2063 }
2064 }
2065
2066 return 0;
2067}
2068#endif
2069
2070#ifndef WEBRTC_EXTERNAL_TRANSPORT
2071WebRtc_Word32
2072Channel::GetSendDestination(int& port,
2073 char ipAddr[64],
2074 int& sourcePort,
2075 int& RTCPport)
2076{
2077 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2078 "Channel::GetSendDestination()");
2079
2080 if (_externalTransport)
2081 {
2082 _engineStatisticsPtr->SetLastError(
2083 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
2084 "GetSendDestination() conflict with external transport");
2085 return -1;
2086 }
2087
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002088 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002089 WebRtc_UWord16 rtpPort(0);
2090 WebRtc_UWord16 rtcpPort(0);
2091 WebRtc_UWord16 rtpSourcePort(0);
2092 WebRtc_UWord16 rtcpSourcePort(0);
2093
2094 // Acquire sending socket information from the socket module
2095 _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort);
2096 _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort);
2097
2098 // Deliver valid results to the user
2099 port = static_cast<int> (rtpPort);
2100 RTCPport = static_cast<int> (rtcpPort);
2101 sourcePort = static_cast<int> (rtpSourcePort);
2102 if (ipAddr != NULL)
2103 {
2104 strcpy(ipAddr, ipAddrTmp);
2105 }
2106
2107 return 0;
2108}
2109#endif
2110
2111
2112WebRtc_Word32
2113Channel::SetNetEQPlayoutMode(NetEqModes mode)
2114{
2115 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2116 "Channel::SetNetEQPlayoutMode()");
2117 AudioPlayoutMode playoutMode(voice);
2118 switch (mode)
2119 {
2120 case kNetEqDefault:
2121 playoutMode = voice;
2122 break;
2123 case kNetEqStreaming:
2124 playoutMode = streaming;
2125 break;
2126 case kNetEqFax:
2127 playoutMode = fax;
2128 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002129 }
2130 if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
2131 {
2132 _engineStatisticsPtr->SetLastError(
2133 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2134 "SetNetEQPlayoutMode() failed to set playout mode");
2135 return -1;
2136 }
2137 return 0;
2138}
2139
2140WebRtc_Word32
2141Channel::GetNetEQPlayoutMode(NetEqModes& mode)
2142{
2143 const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
2144 switch (playoutMode)
2145 {
2146 case voice:
2147 mode = kNetEqDefault;
2148 break;
2149 case streaming:
2150 mode = kNetEqStreaming;
2151 break;
2152 case fax:
2153 mode = kNetEqFax;
2154 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002155 }
2156 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2157 VoEId(_instanceId,_channelId),
2158 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
2159 return 0;
2160}
2161
2162WebRtc_Word32
2163Channel::SetNetEQBGNMode(NetEqBgnModes mode)
2164{
2165 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2166 "Channel::SetNetEQPlayoutMode()");
2167 ACMBackgroundNoiseMode noiseMode(On);
2168 switch (mode)
2169 {
2170 case kBgnOn:
2171 noiseMode = On;
2172 break;
2173 case kBgnFade:
2174 noiseMode = Fade;
2175 break;
2176 case kBgnOff:
2177 noiseMode = Off;
2178 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002179 }
2180 if (_audioCodingModule.SetBackgroundNoiseMode(noiseMode) != 0)
2181 {
2182 _engineStatisticsPtr->SetLastError(
2183 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2184 "SetBackgroundNoiseMode() failed to set noise mode");
2185 return -1;
2186 }
2187 return 0;
2188}
2189
2190WebRtc_Word32
2191Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
2192{
2193 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2194 "Channel::SetOnHoldStatus()");
2195 if (mode == kHoldSendAndPlay)
2196 {
2197 _outputIsOnHold = enable;
2198 _inputIsOnHold = enable;
2199 }
2200 else if (mode == kHoldPlayOnly)
2201 {
2202 _outputIsOnHold = enable;
2203 }
2204 if (mode == kHoldSendOnly)
2205 {
2206 _inputIsOnHold = enable;
2207 }
2208 return 0;
2209}
2210
2211WebRtc_Word32
2212Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
2213{
2214 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2215 "Channel::GetOnHoldStatus()");
2216 enabled = (_outputIsOnHold || _inputIsOnHold);
2217 if (_outputIsOnHold && _inputIsOnHold)
2218 {
2219 mode = kHoldSendAndPlay;
2220 }
2221 else if (_outputIsOnHold && !_inputIsOnHold)
2222 {
2223 mode = kHoldPlayOnly;
2224 }
2225 else if (!_outputIsOnHold && _inputIsOnHold)
2226 {
2227 mode = kHoldSendOnly;
2228 }
2229 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2230 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
2231 enabled, mode);
2232 return 0;
2233}
2234
2235WebRtc_Word32
2236Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
2237{
2238 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2239 "Channel::RegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002240 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002241
2242 if (_voiceEngineObserverPtr)
2243 {
2244 _engineStatisticsPtr->SetLastError(
2245 VE_INVALID_OPERATION, kTraceError,
2246 "RegisterVoiceEngineObserver() observer already enabled");
2247 return -1;
2248 }
2249 _voiceEngineObserverPtr = &observer;
2250 return 0;
2251}
2252
2253WebRtc_Word32
2254Channel::DeRegisterVoiceEngineObserver()
2255{
2256 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2257 "Channel::DeRegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002258 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002259
2260 if (!_voiceEngineObserverPtr)
2261 {
2262 _engineStatisticsPtr->SetLastError(
2263 VE_INVALID_OPERATION, kTraceWarning,
2264 "DeRegisterVoiceEngineObserver() observer already disabled");
2265 return 0;
2266 }
2267 _voiceEngineObserverPtr = NULL;
2268 return 0;
2269}
2270
2271WebRtc_Word32
2272Channel::GetNetEQBGNMode(NetEqBgnModes& mode)
2273{
2274 ACMBackgroundNoiseMode noiseMode(On);
2275 _audioCodingModule.BackgroundNoiseMode(noiseMode);
2276 switch (noiseMode)
2277 {
2278 case On:
2279 mode = kBgnOn;
2280 break;
2281 case Fade:
2282 mode = kBgnFade;
2283 break;
2284 case Off:
2285 mode = kBgnOff;
2286 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002287 }
2288 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2289 "Channel::GetNetEQBGNMode() => mode=%u", mode);
2290 return 0;
2291}
2292
2293WebRtc_Word32
2294Channel::GetSendCodec(CodecInst& codec)
2295{
2296 return (_audioCodingModule.SendCodec(codec));
2297}
2298
2299WebRtc_Word32
2300Channel::GetRecCodec(CodecInst& codec)
2301{
2302 return (_audioCodingModule.ReceiveCodec(codec));
2303}
2304
2305WebRtc_Word32
2306Channel::SetSendCodec(const CodecInst& codec)
2307{
2308 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2309 "Channel::SetSendCodec()");
2310
2311 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2312 {
2313 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2314 "SetSendCodec() failed to register codec to ACM");
2315 return -1;
2316 }
2317
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002318 if (_rtpRtcpModule.RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002319 {
2320 _rtpRtcpModule.DeRegisterSendPayload(codec.pltype);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002321 if (_rtpRtcpModule.RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002322 {
2323 WEBRTC_TRACE(
2324 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2325 "SetSendCodec() failed to register codec to"
2326 " RTP/RTCP module");
2327 return -1;
2328 }
2329 }
2330
2331 if (_rtpRtcpModule.SetAudioPacketSize(codec.pacsize) != 0)
2332 {
2333 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2334 "SetSendCodec() failed to set audio packet size");
2335 return -1;
2336 }
2337
2338 return 0;
2339}
2340
2341WebRtc_Word32
2342Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
2343{
2344 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2345 "Channel::SetVADStatus(mode=%d)", mode);
2346 // To disable VAD, DTX must be disabled too
2347 disableDTX = ((enableVAD == false) ? true : disableDTX);
2348 if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
2349 {
2350 _engineStatisticsPtr->SetLastError(
2351 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2352 "SetVADStatus() failed to set VAD");
2353 return -1;
2354 }
2355 return 0;
2356}
2357
2358WebRtc_Word32
2359Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
2360{
2361 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2362 "Channel::GetVADStatus");
2363 if (_audioCodingModule.VAD(disabledDTX, enabledVAD, mode) != 0)
2364 {
2365 _engineStatisticsPtr->SetLastError(
2366 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2367 "GetVADStatus() failed to get VAD status");
2368 return -1;
2369 }
2370 disabledDTX = !disabledDTX;
2371 return 0;
2372}
2373
2374WebRtc_Word32
2375Channel::SetRecPayloadType(const CodecInst& codec)
2376{
2377 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2378 "Channel::SetRecPayloadType()");
2379
2380 if (_playing)
2381 {
2382 _engineStatisticsPtr->SetLastError(
2383 VE_ALREADY_PLAYING, kTraceError,
2384 "SetRecPayloadType() unable to set PT while playing");
2385 return -1;
2386 }
2387 if (_receiving)
2388 {
2389 _engineStatisticsPtr->SetLastError(
2390 VE_ALREADY_LISTENING, kTraceError,
2391 "SetRecPayloadType() unable to set PT while listening");
2392 return -1;
2393 }
2394
2395 if (codec.pltype == -1)
2396 {
2397 // De-register the selected codec (RTP/RTCP module and ACM)
2398
2399 WebRtc_Word8 pltype(-1);
2400 CodecInst rxCodec = codec;
2401
2402 // Get payload type for the given codec
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002403 _rtpRtcpModule.ReceivePayloadType(rxCodec, &pltype);
niklase@google.com470e71d2011-07-07 08:21:25 +00002404 rxCodec.pltype = pltype;
2405
2406 if (_rtpRtcpModule.DeRegisterReceivePayload(pltype) != 0)
2407 {
2408 _engineStatisticsPtr->SetLastError(
2409 VE_RTP_RTCP_MODULE_ERROR,
2410 kTraceError,
2411 "SetRecPayloadType() RTP/RTCP-module deregistration "
2412 "failed");
2413 return -1;
2414 }
2415 if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
2416 {
2417 _engineStatisticsPtr->SetLastError(
2418 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2419 "SetRecPayloadType() ACM deregistration failed - 1");
2420 return -1;
2421 }
2422 return 0;
2423 }
2424
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002425 if (_rtpRtcpModule.RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002426 {
2427 // First attempt to register failed => de-register and try again
2428 _rtpRtcpModule.DeRegisterReceivePayload(codec.pltype);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002429 if (_rtpRtcpModule.RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002430 {
2431 _engineStatisticsPtr->SetLastError(
2432 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2433 "SetRecPayloadType() RTP/RTCP-module registration failed");
2434 return -1;
2435 }
2436 }
2437 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2438 {
2439 _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
2440 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2441 {
2442 _engineStatisticsPtr->SetLastError(
2443 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2444 "SetRecPayloadType() ACM registration failed - 1");
2445 return -1;
2446 }
2447 }
2448 return 0;
2449}
2450
2451WebRtc_Word32
2452Channel::GetRecPayloadType(CodecInst& codec)
2453{
2454 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2455 "Channel::GetRecPayloadType()");
2456 WebRtc_Word8 payloadType(-1);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002457 if (_rtpRtcpModule.ReceivePayloadType(codec, &payloadType) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002458 {
2459 _engineStatisticsPtr->SetLastError(
2460 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2461 "GetRecPayloadType() failed to retrieve RX payload type");
2462 return -1;
2463 }
2464 codec.pltype = payloadType;
2465 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2466 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
2467 return 0;
2468}
2469
2470WebRtc_Word32
2471Channel::SetAMREncFormat(AmrMode mode)
2472{
2473 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2474 "Channel::SetAMREncFormat()");
2475
2476 // ACM doesn't support AMR
2477 return -1;
2478}
2479
2480WebRtc_Word32
2481Channel::SetAMRDecFormat(AmrMode mode)
2482{
2483 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2484 "Channel::SetAMRDecFormat()");
2485
2486 // ACM doesn't support AMR
2487 return -1;
2488}
2489
2490WebRtc_Word32
2491Channel::SetAMRWbEncFormat(AmrMode mode)
2492{
2493 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2494 "Channel::SetAMRWbEncFormat()");
2495
2496 // ACM doesn't support AMR
2497 return -1;
2498
2499}
2500
2501WebRtc_Word32
2502Channel::SetAMRWbDecFormat(AmrMode mode)
2503{
2504 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2505 "Channel::SetAMRWbDecFormat()");
2506
2507 // ACM doesn't support AMR
2508 return -1;
2509}
2510
2511WebRtc_Word32
2512Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
2513{
2514 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2515 "Channel::SetSendCNPayloadType()");
2516
2517 CodecInst codec;
2518 WebRtc_Word32 samplingFreqHz(-1);
2519 if (frequency == kFreq32000Hz)
2520 samplingFreqHz = 32000;
2521 else if (frequency == kFreq16000Hz)
2522 samplingFreqHz = 16000;
2523
2524 if (_audioCodingModule.Codec("CN", codec, samplingFreqHz) == -1)
2525 {
2526 _engineStatisticsPtr->SetLastError(
2527 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2528 "SetSendCNPayloadType() failed to retrieve default CN codec "
2529 "settings");
2530 return -1;
2531 }
2532
2533 // Modify the payload type (must be set to dynamic range)
2534 codec.pltype = type;
2535
2536 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2537 {
2538 _engineStatisticsPtr->SetLastError(
2539 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2540 "SetSendCNPayloadType() failed to register CN to ACM");
2541 return -1;
2542 }
2543
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002544 if (_rtpRtcpModule.RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002545 {
2546 _rtpRtcpModule.DeRegisterSendPayload(codec.pltype);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00002547 if (_rtpRtcpModule.RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002548 {
2549 _engineStatisticsPtr->SetLastError(
2550 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2551 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
2552 "module");
2553 return -1;
2554 }
2555 }
2556 return 0;
2557}
2558
2559WebRtc_Word32
2560Channel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
2561{
2562 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2563 "Channel::SetISACInitTargetRate()");
2564
2565 CodecInst sendCodec;
2566 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2567 {
2568 _engineStatisticsPtr->SetLastError(
2569 VE_CODEC_ERROR, kTraceError,
2570 "SetISACInitTargetRate() failed to retrieve send codec");
2571 return -1;
2572 }
2573 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2574 {
2575 // This API is only valid if iSAC is setup to run in channel-adaptive
2576 // mode.
2577 // We do not validate the adaptive mode here. It is done later in the
2578 // ConfigISACBandwidthEstimator() API.
2579 _engineStatisticsPtr->SetLastError(
2580 VE_CODEC_ERROR, kTraceError,
2581 "SetISACInitTargetRate() send codec is not iSAC");
2582 return -1;
2583 }
2584
2585 WebRtc_UWord8 initFrameSizeMsec(0);
2586 if (16000 == sendCodec.plfreq)
2587 {
2588 // Note that 0 is a valid and corresponds to "use default
2589 if ((rateBps != 0 &&
2590 rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
2591 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
2592 {
2593 _engineStatisticsPtr->SetLastError(
2594 VE_INVALID_ARGUMENT, kTraceError,
2595 "SetISACInitTargetRate() invalid target rate - 1");
2596 return -1;
2597 }
2598 // 30 or 60ms
2599 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 16);
2600 }
2601 else if (32000 == sendCodec.plfreq)
2602 {
2603 if ((rateBps != 0 &&
2604 rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
2605 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
2606 {
2607 _engineStatisticsPtr->SetLastError(
2608 VE_INVALID_ARGUMENT, kTraceError,
2609 "SetISACInitTargetRate() invalid target rate - 2");
2610 return -1;
2611 }
2612 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 32); // 30ms
2613 }
2614
2615 if (_audioCodingModule.ConfigISACBandwidthEstimator(
2616 initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2617 {
2618 _engineStatisticsPtr->SetLastError(
2619 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2620 "SetISACInitTargetRate() iSAC BWE config failed");
2621 return -1;
2622 }
2623
2624 return 0;
2625}
2626
2627WebRtc_Word32
2628Channel::SetISACMaxRate(int rateBps)
2629{
2630 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2631 "Channel::SetISACMaxRate()");
2632
2633 CodecInst sendCodec;
2634 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2635 {
2636 _engineStatisticsPtr->SetLastError(
2637 VE_CODEC_ERROR, kTraceError,
2638 "SetISACMaxRate() failed to retrieve send codec");
2639 return -1;
2640 }
2641 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2642 {
2643 // This API is only valid if iSAC is selected as sending codec.
2644 _engineStatisticsPtr->SetLastError(
2645 VE_CODEC_ERROR, kTraceError,
2646 "SetISACMaxRate() send codec is not iSAC");
2647 return -1;
2648 }
2649 if (16000 == sendCodec.plfreq)
2650 {
2651 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2652 (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2653 {
2654 _engineStatisticsPtr->SetLastError(
2655 VE_INVALID_ARGUMENT, kTraceError,
2656 "SetISACMaxRate() invalid max rate - 1");
2657 return -1;
2658 }
2659 }
2660 else if (32000 == sendCodec.plfreq)
2661 {
2662 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2663 (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2664 {
2665 _engineStatisticsPtr->SetLastError(
2666 VE_INVALID_ARGUMENT, kTraceError,
2667 "SetISACMaxRate() invalid max rate - 2");
2668 return -1;
2669 }
2670 }
2671 if (_sending)
2672 {
2673 _engineStatisticsPtr->SetLastError(
2674 VE_SENDING, kTraceError,
2675 "SetISACMaxRate() unable to set max rate while sending");
2676 return -1;
2677 }
2678
2679 // Set the maximum instantaneous rate of iSAC (works for both adaptive
2680 // and non-adaptive mode)
2681 if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2682 {
2683 _engineStatisticsPtr->SetLastError(
2684 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2685 "SetISACMaxRate() failed to set max rate");
2686 return -1;
2687 }
2688
2689 return 0;
2690}
2691
2692WebRtc_Word32
2693Channel::SetISACMaxPayloadSize(int sizeBytes)
2694{
2695 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2696 "Channel::SetISACMaxPayloadSize()");
2697 CodecInst sendCodec;
2698 if (_audioCodingModule.SendCodec(sendCodec) == -1)
2699 {
2700 _engineStatisticsPtr->SetLastError(
2701 VE_CODEC_ERROR, kTraceError,
2702 "SetISACMaxPayloadSize() failed to retrieve send codec");
2703 return -1;
2704 }
2705 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2706 {
2707 _engineStatisticsPtr->SetLastError(
2708 VE_CODEC_ERROR, kTraceError,
2709 "SetISACMaxPayloadSize() send codec is not iSAC");
2710 return -1;
2711 }
2712 if (16000 == sendCodec.plfreq)
2713 {
2714 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2715 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2716 {
2717 _engineStatisticsPtr->SetLastError(
2718 VE_INVALID_ARGUMENT, kTraceError,
2719 "SetISACMaxPayloadSize() invalid max payload - 1");
2720 return -1;
2721 }
2722 }
2723 else if (32000 == sendCodec.plfreq)
2724 {
2725 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2726 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2727 {
2728 _engineStatisticsPtr->SetLastError(
2729 VE_INVALID_ARGUMENT, kTraceError,
2730 "SetISACMaxPayloadSize() invalid max payload - 2");
2731 return -1;
2732 }
2733 }
2734 if (_sending)
2735 {
2736 _engineStatisticsPtr->SetLastError(
2737 VE_SENDING, kTraceError,
2738 "SetISACMaxPayloadSize() unable to set max rate while sending");
2739 return -1;
2740 }
2741
2742 if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2743 {
2744 _engineStatisticsPtr->SetLastError(
2745 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2746 "SetISACMaxPayloadSize() failed to set max payload size");
2747 return -1;
2748 }
2749 return 0;
2750}
2751
2752WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport)
2753{
2754 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2755 "Channel::RegisterExternalTransport()");
2756
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002757 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002758
2759#ifndef WEBRTC_EXTERNAL_TRANSPORT
2760 // Sanity checks for default (non external transport) to avoid conflict with
2761 // WebRtc sockets.
2762 if (_socketTransportModule.SendSocketsInitialized())
2763 {
2764 _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT,
2765 kTraceError,
2766 "RegisterExternalTransport() send sockets already initialized");
2767 return -1;
2768 }
2769 if (_socketTransportModule.ReceiveSocketsInitialized())
2770 {
2771 _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT,
2772 kTraceError,
2773 "RegisterExternalTransport() receive sockets already initialized");
2774 return -1;
2775 }
2776#endif
2777 if (_externalTransport)
2778 {
2779 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2780 kTraceError,
2781 "RegisterExternalTransport() external transport already enabled");
2782 return -1;
2783 }
2784 _externalTransport = true;
2785 _transportPtr = &transport;
2786 return 0;
2787}
2788
2789WebRtc_Word32
2790Channel::DeRegisterExternalTransport()
2791{
2792 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2793 "Channel::DeRegisterExternalTransport()");
2794
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002795 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +00002796
niklase@google.com470e71d2011-07-07 08:21:25 +00002797 if (!_transportPtr)
2798 {
2799 _engineStatisticsPtr->SetLastError(
2800 VE_INVALID_OPERATION, kTraceWarning,
2801 "DeRegisterExternalTransport() external transport already "
2802 "disabled");
2803 return 0;
2804 }
2805 _externalTransport = false;
2806#ifdef WEBRTC_EXTERNAL_TRANSPORT
2807 _transportPtr = NULL;
2808 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2809 "DeRegisterExternalTransport() all transport is disabled");
2810#else
2811 _transportPtr = &_socketTransportModule;
2812 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2813 "DeRegisterExternalTransport() internal Transport is enabled");
2814#endif
2815 return 0;
2816}
2817
2818WebRtc_Word32
2819Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2820{
2821 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2822 "Channel::ReceivedRTPPacket()");
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002823 const char dummyIP[] = "127.0.0.1";
niklase@google.com470e71d2011-07-07 08:21:25 +00002824 IncomingRTPPacket(data, length, dummyIP, 0);
2825 return 0;
2826}
2827
2828WebRtc_Word32
2829Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2830{
2831 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2832 "Channel::ReceivedRTCPPacket()");
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002833 const char dummyIP[] = "127.0.0.1";
niklase@google.com470e71d2011-07-07 08:21:25 +00002834 IncomingRTCPPacket(data, length, dummyIP, 0);
2835 return 0;
2836}
2837
2838#ifndef WEBRTC_EXTERNAL_TRANSPORT
2839WebRtc_Word32
2840Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64])
2841{
2842 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2843 "Channel::GetSourceInfo()");
2844
2845 WebRtc_UWord16 rtpPortModule;
2846 WebRtc_UWord16 rtcpPortModule;
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002847 char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002848
2849 if (_socketTransportModule.RemoteSocketInformation(ipaddr,
2850 rtpPortModule,
2851 rtcpPortModule) != 0)
2852 {
2853 _engineStatisticsPtr->SetLastError(
2854 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2855 "GetSourceInfo() failed to retrieve remote socket information");
2856 return -1;
2857 }
2858 strcpy(ipAddr, ipaddr);
2859 rtpPort = rtpPortModule;
2860 rtcpPort = rtcpPortModule;
2861
2862 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2863 "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2864 rtpPort, rtcpPort, ipAddr);
2865 return 0;
2866}
2867
2868WebRtc_Word32
2869Channel::EnableIPv6()
2870{
2871 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2872 "Channel::EnableIPv6()");
2873 if (_socketTransportModule.ReceiveSocketsInitialized() ||
2874 _socketTransportModule.SendSocketsInitialized())
2875 {
2876 _engineStatisticsPtr->SetLastError(
2877 VE_INVALID_OPERATION, kTraceError,
2878 "EnableIPv6() socket layer is already initialized");
2879 return -1;
2880 }
2881 if (_socketTransportModule.EnableIpV6() != 0)
2882 {
2883 _engineStatisticsPtr->SetLastError(
2884 VE_SOCKET_ERROR, kTraceError,
2885 "EnableIPv6() failed to enable IPv6");
2886 const UdpTransport::ErrorCode lastError =
2887 _socketTransportModule.LastError();
2888 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2889 "UdpTransport::LastError() => %d", lastError);
2890 return -1;
2891 }
2892 return 0;
2893}
2894
2895bool
2896Channel::IPv6IsEnabled() const
2897{
2898 bool isEnabled = _socketTransportModule.IpV6Enabled();
2899 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2900 "IPv6IsEnabled() => %d", isEnabled);
2901 return isEnabled;
2902}
2903
2904WebRtc_Word32
2905Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64])
2906{
2907 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2908 "Channel::SetSourceFilter()");
2909 if (_socketTransportModule.SetFilterPorts(
2910 static_cast<WebRtc_UWord16>(rtpPort),
2911 static_cast<WebRtc_UWord16>(rtcpPort)) != 0)
2912 {
2913 _engineStatisticsPtr->SetLastError(
2914 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2915 "SetSourceFilter() failed to set filter ports");
2916 const UdpTransport::ErrorCode lastError =
2917 _socketTransportModule.LastError();
2918 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2919 "UdpTransport::LastError() => %d",
2920 lastError);
2921 return -1;
2922 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002923 const char* filterIpAddress = ipAddr;
niklase@google.com470e71d2011-07-07 08:21:25 +00002924 if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0)
2925 {
2926 _engineStatisticsPtr->SetLastError(
2927 VE_INVALID_IP_ADDRESS, kTraceError,
2928 "SetSourceFilter() failed to set filter IP address");
2929 const UdpTransport::ErrorCode lastError =
2930 _socketTransportModule.LastError();
2931 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2932 "UdpTransport::LastError() => %d", lastError);
2933 return -1;
2934 }
2935 return 0;
2936}
2937
2938WebRtc_Word32
2939Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64])
2940{
2941 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2942 "Channel::GetSourceFilter()");
2943 WebRtc_UWord16 rtpFilterPort(0);
2944 WebRtc_UWord16 rtcpFilterPort(0);
2945 if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0)
2946 {
2947 _engineStatisticsPtr->SetLastError(
2948 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2949 "GetSourceFilter() failed to retrieve filter ports");
2950 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002951 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +00002952 if (_socketTransportModule.FilterIP(ipAddrTmp) != 0)
2953 {
2954 // no filter has been configured (not seen as an error)
2955 memset(ipAddrTmp,
2956 0, UdpTransport::kIpAddressVersion6Length);
2957 }
2958 rtpPort = static_cast<int> (rtpFilterPort);
2959 rtcpPort = static_cast<int> (rtcpFilterPort);
2960 strcpy(ipAddr, ipAddrTmp);
2961 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2962 "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2963 rtpPort, rtcpPort, ipAddr);
2964 return 0;
2965}
2966
2967WebRtc_Word32
2968Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt)
2969{
2970 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2971 "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)",
2972 DSCP, (int)useSetSockopt);
2973
2974 // Set TOS value and possibly try to force usage of setsockopt()
2975 if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0)
2976 {
2977 UdpTransport::ErrorCode lastSockError(
2978 _socketTransportModule.LastError());
2979 switch (lastSockError)
2980 {
2981 case UdpTransport::kTosError:
2982 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2983 "SetSendTOS() TOS error");
2984 break;
2985 case UdpTransport::kQosError:
2986 _engineStatisticsPtr->SetLastError(
2987 VE_TOS_GQOS_CONFLICT, kTraceError,
2988 "SetSendTOS() GQOS error");
2989 break;
2990 case UdpTransport::kTosInvalid:
2991 // can't switch SetSockOpt method without disabling TOS first, or
2992 // SetSockopt() call failed
2993 _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError,
2994 "SetSendTOS() invalid TOS");
2995 break;
2996 case UdpTransport::kSocketInvalid:
2997 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
2998 "SetSendTOS() invalid Socket");
2999 break;
3000 default:
3001 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3002 "SetSendTOS() TOS error");
3003 break;
3004 }
3005 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3006 "UdpTransport => lastError = %d",
3007 lastSockError);
3008 return -1;
3009 }
3010
3011 // Set priority (PCP) value, -1 means don't change
3012 if (-1 != priority)
3013 {
3014 if (_socketTransportModule.SetPCP(priority) != 0)
3015 {
3016 UdpTransport::ErrorCode lastSockError(
3017 _socketTransportModule.LastError());
3018 switch (lastSockError)
3019 {
3020 case UdpTransport::kPcpError:
3021 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3022 "SetSendTOS() PCP error");
3023 break;
3024 case UdpTransport::kQosError:
3025 _engineStatisticsPtr->SetLastError(
3026 VE_TOS_GQOS_CONFLICT, kTraceError,
3027 "SetSendTOS() GQOS conflict");
3028 break;
3029 case UdpTransport::kSocketInvalid:
3030 _engineStatisticsPtr->SetLastError(
3031 VE_SOCKET_ERROR, kTraceError,
3032 "SetSendTOS() invalid Socket");
3033 break;
3034 default:
3035 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
3036 "SetSendTOS() PCP error");
3037 break;
3038 }
3039 WEBRTC_TRACE(kTraceError, kTraceVoice,
3040 VoEId(_instanceId,_channelId),
3041 "UdpTransport => lastError = %d",
3042 lastSockError);
3043 return -1;
3044 }
3045 }
3046
3047 return 0;
3048}
3049
3050WebRtc_Word32
3051Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt)
3052{
3053 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3054 "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)");
3055 WebRtc_Word32 dscp(0), prio(0);
3056 bool setSockopt(false);
3057 if (_socketTransportModule.ToS(dscp, setSockopt) != 0)
3058 {
3059 _engineStatisticsPtr->SetLastError(
3060 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3061 "GetSendTOS() failed to get TOS info");
3062 return -1;
3063 }
3064 if (_socketTransportModule.PCP(prio) != 0)
3065 {
3066 _engineStatisticsPtr->SetLastError(
3067 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3068 "GetSendTOS() failed to get PCP info");
3069 return -1;
3070 }
3071 DSCP = static_cast<int> (dscp);
3072 priority = static_cast<int> (prio);
3073 useSetSockopt = setSockopt;
3074 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3075 "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d",
3076 DSCP, priority, (int)useSetSockopt);
3077 return 0;
3078}
3079
3080#if defined(_WIN32)
3081WebRtc_Word32
3082Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP)
3083{
3084 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3085 "Channel::SetSendGQoS(enable=%d, serviceType=%d, "
3086 "overrideDSCP=%d)",
3087 (int)enable, serviceType, overrideDSCP);
3088 if(!_socketTransportModule.ReceiveSocketsInitialized())
3089 {
3090 _engineStatisticsPtr->SetLastError(
3091 VE_SOCKETS_NOT_INITED, kTraceError,
3092 "SetSendGQoS() GQoS state must be set after sockets are created");
3093 return -1;
3094 }
3095 if(!_socketTransportModule.SendSocketsInitialized())
3096 {
3097 _engineStatisticsPtr->SetLastError(
3098 VE_DESTINATION_NOT_INITED, kTraceError,
3099 "SetSendGQoS() GQoS state must be set after sending side is "
3100 "initialized");
3101 return -1;
3102 }
3103 if (enable &&
3104 (serviceType != SERVICETYPE_BESTEFFORT) &&
3105 (serviceType != SERVICETYPE_CONTROLLEDLOAD) &&
3106 (serviceType != SERVICETYPE_GUARANTEED) &&
3107 (serviceType != SERVICETYPE_QUALITATIVE))
3108 {
3109 _engineStatisticsPtr->SetLastError(
3110 VE_INVALID_ARGUMENT, kTraceError,
3111 "SetSendGQoS() Invalid service type");
3112 return -1;
3113 }
3114 if (enable && ((overrideDSCP < 0) || (overrideDSCP > 63)))
3115 {
3116 _engineStatisticsPtr->SetLastError(
3117 VE_INVALID_ARGUMENT, kTraceError,
3118 "SetSendGQoS() Invalid overrideDSCP value");
3119 return -1;
3120 }
3121
3122 // Avoid GQoS/ToS conflict when user wants to override the default DSCP
3123 // mapping
3124 bool QoS(false);
3125 WebRtc_Word32 sType(0);
3126 WebRtc_Word32 ovrDSCP(0);
3127 if (_socketTransportModule.QoS(QoS, sType, ovrDSCP))
3128 {
3129 _engineStatisticsPtr->SetLastError(
3130 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3131 "SetSendGQoS() failed to get QOS info");
3132 return -1;
3133 }
3134 if (QoS && ovrDSCP == 0 && overrideDSCP != 0)
3135 {
3136 _engineStatisticsPtr->SetLastError(
3137 VE_TOS_GQOS_CONFLICT, kTraceError,
3138 "SetSendGQoS() QOS is already enabled and overrideDSCP differs,"
3139 " not allowed");
3140 return -1;
3141 }
3142 const WebRtc_Word32 maxBitrate(0);
3143 if (_socketTransportModule.SetQoS(enable,
3144 static_cast<WebRtc_Word32>(serviceType),
3145 maxBitrate,
3146 static_cast<WebRtc_Word32>(overrideDSCP),
3147 true))
3148 {
3149 UdpTransport::ErrorCode lastSockError(
3150 _socketTransportModule.LastError());
3151 switch (lastSockError)
3152 {
3153 case UdpTransport::kQosError:
3154 _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError,
3155 "SetSendGQoS() QOS error");
3156 break;
3157 default:
3158 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
3159 "SetSendGQoS() Socket error");
3160 break;
3161 }
3162 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3163 "UdpTransport() => lastError = %d",
3164 lastSockError);
3165 return -1;
3166 }
3167 return 0;
3168}
3169#endif
3170
3171#if defined(_WIN32)
3172WebRtc_Word32
3173Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP)
3174{
3175 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3176 "Channel::GetSendGQoS(enable=?, serviceType=?, "
3177 "overrideDSCP=?)");
3178
3179 bool QoS(false);
3180 WebRtc_Word32 serviceTypeModule(0);
3181 WebRtc_Word32 overrideDSCPModule(0);
3182 _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule);
3183
3184 enabled = QoS;
3185 serviceType = static_cast<int> (serviceTypeModule);
3186 overrideDSCP = static_cast<int> (overrideDSCPModule);
3187
3188 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3189 "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d",
3190 (int)enabled, serviceType, overrideDSCP);
3191 return 0;
3192}
3193#endif
3194#endif
3195
3196WebRtc_Word32
3197Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds)
3198{
3199 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3200 "Channel::SetPacketTimeoutNotification()");
3201 if (enable)
3202 {
3203 const WebRtc_UWord32 RTPtimeoutMS = 1000*timeoutSeconds;
3204 const WebRtc_UWord32 RTCPtimeoutMS = 0;
3205 _rtpRtcpModule.SetPacketTimeout(RTPtimeoutMS, RTCPtimeoutMS);
3206 _rtpPacketTimeOutIsEnabled = true;
3207 _rtpTimeOutSeconds = timeoutSeconds;
3208 }
3209 else
3210 {
3211 _rtpRtcpModule.SetPacketTimeout(0, 0);
3212 _rtpPacketTimeOutIsEnabled = false;
3213 _rtpTimeOutSeconds = 0;
3214 }
3215 return 0;
3216}
3217
3218WebRtc_Word32
3219Channel::GetPacketTimeoutNotification(bool& enabled, int& timeoutSeconds)
3220{
3221 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3222 "Channel::GetPacketTimeoutNotification()");
3223 enabled = _rtpPacketTimeOutIsEnabled;
3224 if (enabled)
3225 {
3226 timeoutSeconds = _rtpTimeOutSeconds;
3227 }
3228 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3229 "GetPacketTimeoutNotification() => enabled=%d,"
3230 " timeoutSeconds=%d",
3231 enabled, timeoutSeconds);
3232 return 0;
3233}
3234
3235WebRtc_Word32
3236Channel::RegisterDeadOrAliveObserver(VoEConnectionObserver& observer)
3237{
3238 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3239 "Channel::RegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003240 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003241
3242 if (_connectionObserverPtr)
3243 {
3244 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, kTraceError,
3245 "RegisterDeadOrAliveObserver() observer already enabled");
3246 return -1;
3247 }
3248
3249 _connectionObserverPtr = &observer;
3250 _connectionObserver = true;
3251
3252 return 0;
3253}
3254
3255WebRtc_Word32
3256Channel::DeRegisterDeadOrAliveObserver()
3257{
3258 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3259 "Channel::DeRegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003260 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003261
3262 if (!_connectionObserverPtr)
3263 {
3264 _engineStatisticsPtr->SetLastError(
3265 VE_INVALID_OPERATION, kTraceWarning,
3266 "DeRegisterDeadOrAliveObserver() observer already disabled");
3267 return 0;
3268 }
3269
3270 _connectionObserver = false;
3271 _connectionObserverPtr = NULL;
3272
3273 return 0;
3274}
3275
3276WebRtc_Word32
3277Channel::SetPeriodicDeadOrAliveStatus(bool enable, int sampleTimeSeconds)
3278{
3279 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3280 "Channel::SetPeriodicDeadOrAliveStatus()");
3281 if (!_connectionObserverPtr)
3282 {
3283 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3284 "SetPeriodicDeadOrAliveStatus() connection observer has"
3285 " not been registered");
3286 }
3287 if (enable)
3288 {
3289 ResetDeadOrAliveCounters();
3290 }
3291 bool enabled(false);
3292 WebRtc_UWord8 currentSampleTimeSec(0);
3293 // Store last state (will be used later if dead-or-alive is disabled).
3294 _rtpRtcpModule.PeriodicDeadOrAliveStatus(enabled, currentSampleTimeSec);
3295 // Update the dead-or-alive state.
3296 if (_rtpRtcpModule.SetPeriodicDeadOrAliveStatus(
3297 enable, (WebRtc_UWord8)sampleTimeSeconds) != 0)
3298 {
3299 _engineStatisticsPtr->SetLastError(
3300 VE_RTP_RTCP_MODULE_ERROR,
3301 kTraceError,
3302 "SetPeriodicDeadOrAliveStatus() failed to set dead-or-alive "
3303 "status");
3304 return -1;
3305 }
3306 if (!enable)
3307 {
3308 // Restore last utilized sample time.
3309 // Without this, the sample time would always be reset to default
3310 // (2 sec), each time dead-or-alived was disabled without sample-time
3311 // parameter.
3312 _rtpRtcpModule.SetPeriodicDeadOrAliveStatus(enable,
3313 currentSampleTimeSec);
3314 }
3315 return 0;
3316}
3317
3318WebRtc_Word32
3319Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds)
3320{
3321 _rtpRtcpModule.PeriodicDeadOrAliveStatus(
3322 enabled,
3323 (WebRtc_UWord8&)sampleTimeSeconds);
3324 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3325 "GetPeriodicDeadOrAliveStatus() => enabled=%d,"
3326 " sampleTimeSeconds=%d",
3327 enabled, sampleTimeSeconds);
3328 return 0;
3329}
3330
3331WebRtc_Word32
3332Channel::SendUDPPacket(const void* data,
3333 unsigned int length,
3334 int& transmittedBytes,
3335 bool useRtcpSocket)
3336{
3337 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3338 "Channel::SendUDPPacket()");
3339 if (_externalTransport)
3340 {
3341 _engineStatisticsPtr->SetLastError(
3342 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
3343 "SendUDPPacket() external transport is enabled");
3344 return -1;
3345 }
3346 if (useRtcpSocket && !_rtpRtcpModule.RTCP())
3347 {
3348 _engineStatisticsPtr->SetLastError(
3349 VE_RTCP_ERROR, kTraceError,
3350 "SendUDPPacket() RTCP is disabled");
3351 return -1;
3352 }
3353 if (!_sending)
3354 {
3355 _engineStatisticsPtr->SetLastError(
3356 VE_NOT_SENDING, kTraceError,
3357 "SendUDPPacket() not sending");
3358 return -1;
3359 }
3360
3361 char* dataC = new char[length];
3362 if (NULL == dataC)
3363 {
3364 _engineStatisticsPtr->SetLastError(
3365 VE_NO_MEMORY, kTraceError,
3366 "SendUDPPacket() memory allocation failed");
3367 return -1;
3368 }
3369 memcpy(dataC, data, length);
3370
3371 transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket);
3372
3373 delete [] dataC;
3374 dataC = NULL;
3375
3376 if (transmittedBytes <= 0)
3377 {
3378 _engineStatisticsPtr->SetLastError(
3379 VE_SEND_ERROR, kTraceError,
3380 "SendUDPPacket() transmission failed");
3381 transmittedBytes = 0;
3382 return -1;
3383 }
3384 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3385 "SendUDPPacket() => transmittedBytes=%d", transmittedBytes);
3386 return 0;
3387}
3388
3389
3390int Channel::StartPlayingFileLocally(const char* fileName,
3391 const bool loop,
3392 const FileFormats format,
3393 const int startPosition,
3394 const float volumeScaling,
3395 const int stopPosition,
3396 const CodecInst* codecInst)
3397{
3398 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3399 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
3400 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
3401 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3402 startPosition, stopPosition);
3403
3404 if (_outputFilePlaying)
3405 {
3406 _engineStatisticsPtr->SetLastError(
3407 VE_ALREADY_PLAYING, kTraceError,
3408 "StartPlayingFileLocally() is already playing");
3409 return -1;
3410 }
3411
niklase@google.com470e71d2011-07-07 08:21:25 +00003412 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003413 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003414
3415 if (_outputFilePlayerPtr)
3416 {
3417 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3418 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3419 _outputFilePlayerPtr = NULL;
3420 }
3421
3422 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3423 _outputFilePlayerId, (const FileFormats)format);
3424
3425 if (_outputFilePlayerPtr == NULL)
3426 {
3427 _engineStatisticsPtr->SetLastError(
3428 VE_INVALID_ARGUMENT, kTraceError,
henrike@webrtc.org31d30702011-11-18 19:59:32 +00003429 "StartPlayingFileLocally() filePlayer format is not correct");
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003430 return -1;
3431 }
3432
3433 const WebRtc_UWord32 notificationTime(0);
3434
3435 if (_outputFilePlayerPtr->StartPlayingFile(
3436 fileName,
3437 loop,
3438 startPosition,
3439 volumeScaling,
3440 notificationTime,
3441 stopPosition,
3442 (const CodecInst*)codecInst) != 0)
3443 {
3444 _engineStatisticsPtr->SetLastError(
3445 VE_BAD_FILE, kTraceError,
3446 "StartPlayingFile() failed to start file playout");
3447 _outputFilePlayerPtr->StopPlayingFile();
3448 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3449 _outputFilePlayerPtr = NULL;
3450 return -1;
3451 }
3452 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3453 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003454 }
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003455 // _fileCritSect cannot be taken while calling
henrike@webrtc.org31d30702011-11-18 19:59:32 +00003456 // SetAnonymousMixabilityStatus() since as soon as the participant is added
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003457 // frames can be pulled by the mixer. Since the frames are generated from
3458 // the file, _fileCritSect will be taken. This would result in a deadlock.
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003459 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3460 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003461 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003462 _outputFilePlaying = false;
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003463 _engineStatisticsPtr->SetLastError(
3464 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3465 "StartPlayingFile() failed to add participant as file to mixer");
3466 _outputFilePlayerPtr->StopPlayingFile();
3467 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3468 _outputFilePlayerPtr = NULL;
3469 return -1;
3470 }
niklase@google.com470e71d2011-07-07 08:21:25 +00003471
3472 return 0;
3473}
3474
3475int Channel::StartPlayingFileLocally(InStream* stream,
3476 const FileFormats format,
3477 const int startPosition,
3478 const float volumeScaling,
3479 const int stopPosition,
3480 const CodecInst* codecInst)
3481{
3482 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3483 "Channel::StartPlayingFileLocally(format=%d,"
3484 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3485 format, volumeScaling, startPosition, stopPosition);
3486
3487 if(stream == NULL)
3488 {
3489 _engineStatisticsPtr->SetLastError(
3490 VE_BAD_FILE, kTraceError,
3491 "StartPlayingFileLocally() NULL as input stream");
3492 return -1;
3493 }
3494
3495
3496 if (_outputFilePlaying)
3497 {
3498 _engineStatisticsPtr->SetLastError(
3499 VE_ALREADY_PLAYING, kTraceError,
3500 "StartPlayingFileLocally() is already playing");
3501 return -1;
3502 }
3503
niklase@google.com470e71d2011-07-07 08:21:25 +00003504 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003505 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003506
3507 // Destroy the old instance
3508 if (_outputFilePlayerPtr)
3509 {
3510 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3511 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3512 _outputFilePlayerPtr = NULL;
3513 }
3514
3515 // Create the instance
3516 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3517 _outputFilePlayerId,
3518 (const FileFormats)format);
3519
3520 if (_outputFilePlayerPtr == NULL)
3521 {
3522 _engineStatisticsPtr->SetLastError(
3523 VE_INVALID_ARGUMENT, kTraceError,
3524 "StartPlayingFileLocally() filePlayer format isnot correct");
3525 return -1;
3526 }
3527
3528 const WebRtc_UWord32 notificationTime(0);
3529
3530 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3531 volumeScaling,
3532 notificationTime,
3533 stopPosition, codecInst) != 0)
3534 {
3535 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3536 "StartPlayingFile() failed to "
3537 "start file playout");
3538 _outputFilePlayerPtr->StopPlayingFile();
3539 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3540 _outputFilePlayerPtr = NULL;
3541 return -1;
3542 }
3543 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3544 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003545 }
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003546 // _fileCritSect cannot be taken while calling
3547 // SetAnonymousMixibilityStatus. Refer to comments in
3548 // StartPlayingFileLocally(const char* ...) for more details.
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003549 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3550 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003551 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003552 _outputFilePlaying = false;
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003553 _engineStatisticsPtr->SetLastError(
3554 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3555 "StartPlayingFile() failed to add participant as file to mixer");
3556 _outputFilePlayerPtr->StopPlayingFile();
3557 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3558 _outputFilePlayerPtr = NULL;
3559 return -1;
3560 }
niklase@google.com470e71d2011-07-07 08:21:25 +00003561
niklase@google.com470e71d2011-07-07 08:21:25 +00003562 return 0;
3563}
3564
3565int Channel::StopPlayingFileLocally()
3566{
3567 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3568 "Channel::StopPlayingFileLocally()");
3569
3570 if (!_outputFilePlaying)
3571 {
3572 _engineStatisticsPtr->SetLastError(
3573 VE_INVALID_OPERATION, kTraceWarning,
3574 "StopPlayingFileLocally() isnot playing");
3575 return 0;
3576 }
3577
niklase@google.com470e71d2011-07-07 08:21:25 +00003578 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003579 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003580
3581 if (_outputFilePlayerPtr->StopPlayingFile() != 0)
3582 {
3583 _engineStatisticsPtr->SetLastError(
3584 VE_STOP_RECORDING_FAILED, kTraceError,
3585 "StopPlayingFile() could not stop playing");
3586 return -1;
3587 }
3588 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3589 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3590 _outputFilePlayerPtr = NULL;
3591 _outputFilePlaying = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00003592 }
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003593 // _fileCritSect cannot be taken while calling
3594 // SetAnonymousMixibilityStatus. Refer to comments in
3595 // StartPlayingFileLocally(const char* ...) for more details.
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003596 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
3597 {
3598 _engineStatisticsPtr->SetLastError(
3599 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003600 "StopPlayingFile() failed to stop participant from playing as"
3601 "file in the mixer");
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003602 return -1;
3603 }
niklase@google.com470e71d2011-07-07 08:21:25 +00003604
3605 return 0;
3606}
3607
3608int Channel::IsPlayingFileLocally() const
3609{
3610 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3611 "Channel::IsPlayingFileLocally()");
3612
3613 return (WebRtc_Word32)_outputFilePlaying;
3614}
3615
3616int Channel::ScaleLocalFilePlayout(const float scale)
3617{
3618 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3619 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
3620
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003621 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003622
3623 if (!_outputFilePlaying)
3624 {
3625 _engineStatisticsPtr->SetLastError(
3626 VE_INVALID_OPERATION, kTraceError,
3627 "ScaleLocalFilePlayout() isnot playing");
3628 return -1;
3629 }
3630 if ((_outputFilePlayerPtr == NULL) ||
3631 (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
3632 {
3633 _engineStatisticsPtr->SetLastError(
3634 VE_BAD_ARGUMENT, kTraceError,
3635 "SetAudioScaling() failed to scale the playout");
3636 return -1;
3637 }
3638
3639 return 0;
3640}
3641
3642int Channel::GetLocalPlayoutPosition(int& positionMs)
3643{
3644 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3645 "Channel::GetLocalPlayoutPosition(position=?)");
3646
3647 WebRtc_UWord32 position;
3648
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003649 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003650
3651 if (_outputFilePlayerPtr == NULL)
3652 {
3653 _engineStatisticsPtr->SetLastError(
3654 VE_INVALID_OPERATION, kTraceError,
3655 "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
3656 return -1;
3657 }
3658
3659 if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
3660 {
3661 _engineStatisticsPtr->SetLastError(
3662 VE_BAD_FILE, kTraceError,
3663 "GetLocalPlayoutPosition() failed");
3664 return -1;
3665 }
3666 positionMs = position;
3667
3668 return 0;
3669}
3670
3671int Channel::StartPlayingFileAsMicrophone(const char* fileName,
3672 const bool loop,
3673 const FileFormats format,
3674 const int startPosition,
3675 const float volumeScaling,
3676 const int stopPosition,
3677 const CodecInst* codecInst)
3678{
3679 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3680 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
3681 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
3682 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3683 startPosition, stopPosition);
3684
3685 if (_inputFilePlaying)
3686 {
3687 _engineStatisticsPtr->SetLastError(
3688 VE_ALREADY_PLAYING, kTraceWarning,
3689 "StartPlayingFileAsMicrophone() filePlayer is playing");
3690 return 0;
3691 }
3692
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003693 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003694
3695 // Destroy the old instance
3696 if (_inputFilePlayerPtr)
3697 {
3698 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3699 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3700 _inputFilePlayerPtr = NULL;
3701 }
3702
3703 // Create the instance
3704 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3705 _inputFilePlayerId, (const FileFormats)format);
3706
3707 if (_inputFilePlayerPtr == NULL)
3708 {
3709 _engineStatisticsPtr->SetLastError(
3710 VE_INVALID_ARGUMENT, kTraceError,
3711 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
3712 return -1;
3713 }
3714
3715 const WebRtc_UWord32 notificationTime(0);
3716
3717 if (_inputFilePlayerPtr->StartPlayingFile(
3718 fileName,
3719 loop,
3720 startPosition,
3721 volumeScaling,
3722 notificationTime,
3723 stopPosition,
3724 (const CodecInst*)codecInst) != 0)
3725 {
3726 _engineStatisticsPtr->SetLastError(
3727 VE_BAD_FILE, kTraceError,
3728 "StartPlayingFile() failed to start file playout");
3729 _inputFilePlayerPtr->StopPlayingFile();
3730 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3731 _inputFilePlayerPtr = NULL;
3732 return -1;
3733 }
3734 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3735 _inputFilePlaying = true;
3736
3737 return 0;
3738}
3739
3740int Channel::StartPlayingFileAsMicrophone(InStream* stream,
3741 const FileFormats format,
3742 const int startPosition,
3743 const float volumeScaling,
3744 const int stopPosition,
3745 const CodecInst* codecInst)
3746{
3747 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3748 "Channel::StartPlayingFileAsMicrophone(format=%d, "
3749 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3750 format, volumeScaling, startPosition, stopPosition);
3751
3752 if(stream == NULL)
3753 {
3754 _engineStatisticsPtr->SetLastError(
3755 VE_BAD_FILE, kTraceError,
3756 "StartPlayingFileAsMicrophone NULL as input stream");
3757 return -1;
3758 }
3759
3760 if (_inputFilePlaying)
3761 {
3762 _engineStatisticsPtr->SetLastError(
3763 VE_ALREADY_PLAYING, kTraceWarning,
3764 "StartPlayingFileAsMicrophone() is playing");
3765 return 0;
3766 }
3767
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003768 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003769
3770 // Destroy the old instance
3771 if (_inputFilePlayerPtr)
3772 {
3773 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3774 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3775 _inputFilePlayerPtr = NULL;
3776 }
3777
3778 // Create the instance
3779 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3780 _inputFilePlayerId, (const FileFormats)format);
3781
3782 if (_inputFilePlayerPtr == NULL)
3783 {
3784 _engineStatisticsPtr->SetLastError(
3785 VE_INVALID_ARGUMENT, kTraceError,
3786 "StartPlayingInputFile() filePlayer format isnot correct");
3787 return -1;
3788 }
3789
3790 const WebRtc_UWord32 notificationTime(0);
3791
3792 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3793 volumeScaling, notificationTime,
3794 stopPosition, codecInst) != 0)
3795 {
3796 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3797 "StartPlayingFile() failed to start "
3798 "file playout");
3799 _inputFilePlayerPtr->StopPlayingFile();
3800 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3801 _inputFilePlayerPtr = NULL;
3802 return -1;
3803 }
3804
3805 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3806 _inputFilePlaying = true;
3807
3808 return 0;
3809}
3810
3811int Channel::StopPlayingFileAsMicrophone()
3812{
3813 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3814 "Channel::StopPlayingFileAsMicrophone()");
3815
3816 if (!_inputFilePlaying)
3817 {
3818 _engineStatisticsPtr->SetLastError(
3819 VE_INVALID_OPERATION, kTraceWarning,
3820 "StopPlayingFileAsMicrophone() isnot playing");
3821 return 0;
3822 }
3823
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003824 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003825 if (_inputFilePlayerPtr->StopPlayingFile() != 0)
3826 {
3827 _engineStatisticsPtr->SetLastError(
3828 VE_STOP_RECORDING_FAILED, kTraceError,
3829 "StopPlayingFile() could not stop playing");
3830 return -1;
3831 }
3832 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3833 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3834 _inputFilePlayerPtr = NULL;
3835 _inputFilePlaying = false;
3836
3837 return 0;
3838}
3839
3840int Channel::IsPlayingFileAsMicrophone() const
3841{
3842 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3843 "Channel::IsPlayingFileAsMicrophone()");
3844
3845 return _inputFilePlaying;
3846}
3847
3848int Channel::ScaleFileAsMicrophonePlayout(const float scale)
3849{
3850 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3851 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
3852
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003853 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003854
3855 if (!_inputFilePlaying)
3856 {
3857 _engineStatisticsPtr->SetLastError(
3858 VE_INVALID_OPERATION, kTraceError,
3859 "ScaleFileAsMicrophonePlayout() isnot playing");
3860 return -1;
3861 }
3862
3863 if ((_inputFilePlayerPtr == NULL) ||
3864 (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
3865 {
3866 _engineStatisticsPtr->SetLastError(
3867 VE_BAD_ARGUMENT, kTraceError,
3868 "SetAudioScaling() failed to scale playout");
3869 return -1;
3870 }
3871
3872 return 0;
3873}
3874
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00003875int Channel::StartRecordingPlayout(const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +00003876 const CodecInst* codecInst)
3877{
3878 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3879 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
3880
3881 if (_outputFileRecording)
3882 {
3883 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3884 "StartRecordingPlayout() is already recording");
3885 return 0;
3886 }
3887
3888 FileFormats format;
3889 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3890 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3891
niklas.enbom@webrtc.org40197d72012-03-26 08:45:47 +00003892 if ((codecInst != NULL) &&
3893 ((codecInst->channels < 1) || (codecInst->channels > 2)))
niklase@google.com470e71d2011-07-07 08:21:25 +00003894 {
3895 _engineStatisticsPtr->SetLastError(
3896 VE_BAD_ARGUMENT, kTraceError,
3897 "StartRecordingPlayout() invalid compression");
3898 return(-1);
3899 }
3900 if(codecInst == NULL)
3901 {
3902 format = kFileFormatPcm16kHzFile;
3903 codecInst=&dummyCodec;
3904 }
3905 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3906 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3907 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3908 {
3909 format = kFileFormatWavFile;
3910 }
3911 else
3912 {
3913 format = kFileFormatCompressedFile;
3914 }
3915
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003916 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003917
3918 // Destroy the old instance
3919 if (_outputFileRecorderPtr)
3920 {
3921 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3922 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3923 _outputFileRecorderPtr = NULL;
3924 }
3925
3926 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3927 _outputFileRecorderId, (const FileFormats)format);
3928 if (_outputFileRecorderPtr == NULL)
3929 {
3930 _engineStatisticsPtr->SetLastError(
3931 VE_INVALID_ARGUMENT, kTraceError,
3932 "StartRecordingPlayout() fileRecorder format isnot correct");
3933 return -1;
3934 }
3935
3936 if (_outputFileRecorderPtr->StartRecordingAudioFile(
3937 fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
3938 {
3939 _engineStatisticsPtr->SetLastError(
3940 VE_BAD_FILE, kTraceError,
3941 "StartRecordingAudioFile() failed to start file recording");
3942 _outputFileRecorderPtr->StopRecording();
3943 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3944 _outputFileRecorderPtr = NULL;
3945 return -1;
3946 }
3947 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3948 _outputFileRecording = true;
3949
3950 return 0;
3951}
3952
3953int Channel::StartRecordingPlayout(OutStream* stream,
3954 const CodecInst* codecInst)
3955{
3956 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3957 "Channel::StartRecordingPlayout()");
3958
3959 if (_outputFileRecording)
3960 {
3961 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3962 "StartRecordingPlayout() is already recording");
3963 return 0;
3964 }
3965
3966 FileFormats format;
3967 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3968 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3969
3970 if (codecInst != NULL && codecInst->channels != 1)
3971 {
3972 _engineStatisticsPtr->SetLastError(
3973 VE_BAD_ARGUMENT, kTraceError,
3974 "StartRecordingPlayout() invalid compression");
3975 return(-1);
3976 }
3977 if(codecInst == NULL)
3978 {
3979 format = kFileFormatPcm16kHzFile;
3980 codecInst=&dummyCodec;
3981 }
3982 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3983 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3984 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3985 {
3986 format = kFileFormatWavFile;
3987 }
3988 else
3989 {
3990 format = kFileFormatCompressedFile;
3991 }
3992
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003993 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003994
3995 // Destroy the old instance
3996 if (_outputFileRecorderPtr)
3997 {
3998 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3999 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4000 _outputFileRecorderPtr = NULL;
4001 }
4002
4003 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
4004 _outputFileRecorderId, (const FileFormats)format);
4005 if (_outputFileRecorderPtr == NULL)
4006 {
4007 _engineStatisticsPtr->SetLastError(
4008 VE_INVALID_ARGUMENT, kTraceError,
4009 "StartRecordingPlayout() fileRecorder format isnot correct");
4010 return -1;
4011 }
4012
4013 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
4014 notificationTime) != 0)
4015 {
4016 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
4017 "StartRecordingPlayout() failed to "
4018 "start file recording");
4019 _outputFileRecorderPtr->StopRecording();
4020 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4021 _outputFileRecorderPtr = NULL;
4022 return -1;
4023 }
4024
4025 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
4026 _outputFileRecording = true;
4027
4028 return 0;
4029}
4030
4031int Channel::StopRecordingPlayout()
4032{
4033 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
4034 "Channel::StopRecordingPlayout()");
4035
4036 if (!_outputFileRecording)
4037 {
4038 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
4039 "StopRecordingPlayout() isnot recording");
4040 return -1;
4041 }
4042
4043
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004044 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004045
4046 if (_outputFileRecorderPtr->StopRecording() != 0)
4047 {
4048 _engineStatisticsPtr->SetLastError(
4049 VE_STOP_RECORDING_FAILED, kTraceError,
4050 "StopRecording() could not stop recording");
4051 return(-1);
4052 }
4053 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
4054 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
4055 _outputFileRecorderPtr = NULL;
4056 _outputFileRecording = false;
4057
4058 return 0;
4059}
4060
4061void
4062Channel::SetMixWithMicStatus(bool mix)
4063{
4064 _mixFileWithMicrophone=mix;
4065}
4066
4067int
4068Channel::GetSpeechOutputLevel(WebRtc_UWord32& level) const
4069{
4070 WebRtc_Word8 currentLevel = _outputAudioLevel.Level();
4071 level = static_cast<WebRtc_Word32> (currentLevel);
4072 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4073 VoEId(_instanceId,_channelId),
4074 "GetSpeechOutputLevel() => level=%u", level);
4075 return 0;
4076}
4077
4078int
4079Channel::GetSpeechOutputLevelFullRange(WebRtc_UWord32& level) const
4080{
4081 WebRtc_Word16 currentLevel = _outputAudioLevel.LevelFullRange();
4082 level = static_cast<WebRtc_Word32> (currentLevel);
4083 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4084 VoEId(_instanceId,_channelId),
4085 "GetSpeechOutputLevelFullRange() => level=%u", level);
4086 return 0;
4087}
4088
4089int
4090Channel::SetMute(bool enable)
4091{
4092 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4093 "Channel::SetMute(enable=%d)", enable);
4094 _mute = enable;
4095 return 0;
4096}
4097
4098bool
4099Channel::Mute() const
4100{
4101 return _mute;
4102}
4103
4104int
4105Channel::SetOutputVolumePan(float left, float right)
4106{
4107 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4108 "Channel::SetOutputVolumePan()");
4109 _panLeft = left;
4110 _panRight = right;
4111 return 0;
4112}
4113
4114int
4115Channel::GetOutputVolumePan(float& left, float& right) const
4116{
4117 left = _panLeft;
4118 right = _panRight;
4119 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4120 VoEId(_instanceId,_channelId),
4121 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
4122 return 0;
4123}
4124
4125int
4126Channel::SetChannelOutputVolumeScaling(float scaling)
4127{
4128 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4129 "Channel::SetChannelOutputVolumeScaling()");
4130 _outputGain = scaling;
4131 return 0;
4132}
4133
4134int
4135Channel::GetChannelOutputVolumeScaling(float& scaling) const
4136{
4137 scaling = _outputGain;
4138 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4139 VoEId(_instanceId,_channelId),
4140 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
4141 return 0;
4142}
4143
4144#ifdef WEBRTC_SRTP
4145
4146int
4147Channel::EnableSRTPSend(
4148 CipherTypes cipherType,
4149 int cipherKeyLength,
4150 AuthenticationTypes authType,
4151 int authKeyLength,
4152 int authTagLength,
4153 SecurityLevels level,
4154 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4155 bool useForRTCP)
4156{
4157 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4158 "Channel::EnableSRTPSend()");
4159
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004160 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004161
4162 if (_encrypting)
4163 {
4164 _engineStatisticsPtr->SetLastError(
4165 VE_INVALID_OPERATION, kTraceWarning,
4166 "EnableSRTPSend() encryption already enabled");
4167 return -1;
4168 }
4169
4170 if (key == NULL)
4171 {
4172 _engineStatisticsPtr->SetLastError(
4173 VE_INVALID_ARGUMENT, kTraceWarning,
4174 "EnableSRTPSend() invalid key string");
4175 return -1;
4176 }
4177
4178 if (((kEncryption == level ||
4179 kEncryptionAndAuthentication == level) &&
4180 (cipherKeyLength < kVoiceEngineMinSrtpEncryptLength ||
4181 cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength)) ||
4182 ((kAuthentication == level ||
4183 kEncryptionAndAuthentication == level) &&
4184 kAuthHmacSha1 == authType &&
4185 (authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length ||
4186 authTagLength > kVoiceEngineMaxSrtpAuthSha1Length)) ||
4187 ((kAuthentication == level ||
4188 kEncryptionAndAuthentication == level) &&
4189 kAuthNull == authType &&
4190 (authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength ||
4191 authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength)))
4192 {
4193 _engineStatisticsPtr->SetLastError(
4194 VE_INVALID_ARGUMENT, kTraceError,
4195 "EnableSRTPSend() invalid key length(s)");
4196 return -1;
4197 }
4198
4199
4200 if (_srtpModule.EnableSRTPEncrypt(
4201 !useForRTCP,
4202 (SrtpModule::CipherTypes)cipherType,
4203 cipherKeyLength,
4204 (SrtpModule::AuthenticationTypes)authType,
4205 authKeyLength, authTagLength,
4206 (SrtpModule::SecurityLevels)level,
4207 key) == -1)
4208 {
4209 _engineStatisticsPtr->SetLastError(
4210 VE_SRTP_ERROR, kTraceError,
4211 "EnableSRTPSend() failed to enable SRTP encryption");
4212 return -1;
4213 }
4214
4215 if (_encryptionPtr == NULL)
4216 {
4217 _encryptionPtr = &_srtpModule;
4218 }
4219 _encrypting = true;
4220
4221 return 0;
4222}
4223
4224int
4225Channel::DisableSRTPSend()
4226{
4227 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4228 "Channel::DisableSRTPSend()");
4229
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004230 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004231
4232 if (!_encrypting)
4233 {
4234 _engineStatisticsPtr->SetLastError(
4235 VE_INVALID_OPERATION, kTraceWarning,
4236 "DisableSRTPSend() SRTP encryption already disabled");
4237 return 0;
4238 }
4239
4240 _encrypting = false;
4241
4242 if (_srtpModule.DisableSRTPEncrypt() == -1)
4243 {
4244 _engineStatisticsPtr->SetLastError(
4245 VE_SRTP_ERROR, kTraceError,
4246 "DisableSRTPSend() failed to disable SRTP encryption");
4247 return -1;
4248 }
4249
4250 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4251 {
4252 // Both directions are disabled
4253 _encryptionPtr = NULL;
4254 }
4255
4256 return 0;
4257}
4258
4259int
4260Channel::EnableSRTPReceive(
4261 CipherTypes cipherType,
4262 int cipherKeyLength,
4263 AuthenticationTypes authType,
4264 int authKeyLength,
4265 int authTagLength,
4266 SecurityLevels level,
4267 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4268 bool useForRTCP)
4269{
4270 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4271 "Channel::EnableSRTPReceive()");
4272
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004273 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004274
4275 if (_decrypting)
4276 {
4277 _engineStatisticsPtr->SetLastError(
4278 VE_INVALID_OPERATION, kTraceWarning,
4279 "EnableSRTPReceive() SRTP decryption already enabled");
4280 return -1;
4281 }
4282
4283 if (key == NULL)
4284 {
4285 _engineStatisticsPtr->SetLastError(
4286 VE_INVALID_ARGUMENT, kTraceWarning,
4287 "EnableSRTPReceive() invalid key string");
4288 return -1;
4289 }
4290
4291 if ((((kEncryption == level) ||
4292 (kEncryptionAndAuthentication == level)) &&
4293 ((cipherKeyLength < kVoiceEngineMinSrtpEncryptLength) ||
4294 (cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength))) ||
4295 (((kAuthentication == level) ||
4296 (kEncryptionAndAuthentication == level)) &&
4297 (kAuthHmacSha1 == authType) &&
4298 ((authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length) ||
4299 (authTagLength > kVoiceEngineMaxSrtpAuthSha1Length))) ||
4300 (((kAuthentication == level) ||
4301 (kEncryptionAndAuthentication == level)) &&
4302 (kAuthNull == authType) &&
4303 ((authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength) ||
4304 (authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength))))
4305 {
4306 _engineStatisticsPtr->SetLastError(
4307 VE_INVALID_ARGUMENT, kTraceError,
4308 "EnableSRTPReceive() invalid key length(s)");
4309 return -1;
4310 }
4311
4312 if (_srtpModule.EnableSRTPDecrypt(
4313 !useForRTCP,
4314 (SrtpModule::CipherTypes)cipherType,
4315 cipherKeyLength,
4316 (SrtpModule::AuthenticationTypes)authType,
4317 authKeyLength,
4318 authTagLength,
4319 (SrtpModule::SecurityLevels)level,
4320 key) == -1)
4321 {
4322 _engineStatisticsPtr->SetLastError(
4323 VE_SRTP_ERROR, kTraceError,
4324 "EnableSRTPReceive() failed to enable SRTP decryption");
4325 return -1;
4326 }
4327
4328 if (_encryptionPtr == NULL)
4329 {
4330 _encryptionPtr = &_srtpModule;
4331 }
4332
4333 _decrypting = true;
4334
4335 return 0;
4336}
4337
4338int
4339Channel::DisableSRTPReceive()
4340{
4341 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4342 "Channel::DisableSRTPReceive()");
4343
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004344 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004345
4346 if (!_decrypting)
4347 {
4348 _engineStatisticsPtr->SetLastError(
4349 VE_INVALID_OPERATION, kTraceWarning,
4350 "DisableSRTPReceive() SRTP decryption already disabled");
4351 return 0;
4352 }
4353
4354 _decrypting = false;
4355
4356 if (_srtpModule.DisableSRTPDecrypt() == -1)
4357 {
4358 _engineStatisticsPtr->SetLastError(
4359 VE_SRTP_ERROR, kTraceError,
4360 "DisableSRTPReceive() failed to disable SRTP decryption");
4361 return -1;
4362 }
4363
4364 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4365 {
4366 _encryptionPtr = NULL;
4367 }
4368
4369 return 0;
4370}
4371
4372#endif
4373
4374int
4375Channel::RegisterExternalEncryption(Encryption& encryption)
4376{
4377 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4378 "Channel::RegisterExternalEncryption()");
4379
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004380 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004381
4382 if (_encryptionPtr)
4383 {
4384 _engineStatisticsPtr->SetLastError(
4385 VE_INVALID_OPERATION, kTraceError,
4386 "RegisterExternalEncryption() encryption already enabled");
4387 return -1;
4388 }
4389
4390 _encryptionPtr = &encryption;
4391
4392 _decrypting = true;
4393 _encrypting = true;
4394
4395 return 0;
4396}
4397
4398int
4399Channel::DeRegisterExternalEncryption()
4400{
4401 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4402 "Channel::DeRegisterExternalEncryption()");
4403
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004404 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004405
4406 if (!_encryptionPtr)
4407 {
4408 _engineStatisticsPtr->SetLastError(
4409 VE_INVALID_OPERATION, kTraceWarning,
4410 "DeRegisterExternalEncryption() encryption already disabled");
4411 return 0;
4412 }
4413
4414 _decrypting = false;
4415 _encrypting = false;
4416
4417 _encryptionPtr = NULL;
4418
4419 return 0;
4420}
4421
4422int Channel::SendTelephoneEventOutband(unsigned char eventCode,
4423 int lengthMs, int attenuationDb,
4424 bool playDtmfEvent)
4425{
4426 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4427 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
4428 playDtmfEvent);
4429
4430 _playOutbandDtmfEvent = playDtmfEvent;
4431
4432 if (_rtpRtcpModule.SendTelephoneEventOutband(eventCode, lengthMs,
4433 attenuationDb) != 0)
4434 {
4435 _engineStatisticsPtr->SetLastError(
4436 VE_SEND_DTMF_FAILED,
4437 kTraceWarning,
4438 "SendTelephoneEventOutband() failed to send event");
4439 return -1;
4440 }
4441 return 0;
4442}
4443
4444int Channel::SendTelephoneEventInband(unsigned char eventCode,
4445 int lengthMs,
4446 int attenuationDb,
4447 bool playDtmfEvent)
4448{
4449 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4450 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
4451 playDtmfEvent);
4452
4453 _playInbandDtmfEvent = playDtmfEvent;
4454 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
4455
4456 return 0;
4457}
4458
4459int
4460Channel::SetDtmfPlayoutStatus(bool enable)
4461{
4462 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4463 "Channel::SetDtmfPlayoutStatus()");
4464 if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
4465 {
4466 _engineStatisticsPtr->SetLastError(
4467 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
4468 "SetDtmfPlayoutStatus() failed to set Dtmf playout");
4469 return -1;
4470 }
4471 return 0;
4472}
4473
4474bool
4475Channel::DtmfPlayoutStatus() const
4476{
4477 return _audioCodingModule.DtmfPlayoutStatus();
4478}
4479
4480int
4481Channel::SetSendTelephoneEventPayloadType(unsigned char type)
4482{
4483 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4484 "Channel::SetSendTelephoneEventPayloadType()");
andrew@webrtc.orgf81f9f82011-08-19 22:56:22 +00004485 if (type > 127)
niklase@google.com470e71d2011-07-07 08:21:25 +00004486 {
4487 _engineStatisticsPtr->SetLastError(
4488 VE_INVALID_ARGUMENT, kTraceError,
4489 "SetSendTelephoneEventPayloadType() invalid type");
4490 return -1;
4491 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00004492 CodecInst codec;
4493 codec.plfreq = 8000;
4494 codec.pltype = type;
4495 memcpy(codec.plname, "telephone-event", 16);
4496 if (_rtpRtcpModule.RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004497 {
4498 _engineStatisticsPtr->SetLastError(
4499 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4500 "SetSendTelephoneEventPayloadType() failed to register send"
4501 "payload type");
4502 return -1;
4503 }
4504 _sendTelephoneEventPayloadType = type;
4505 return 0;
4506}
4507
4508int
4509Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
4510{
4511 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4512 "Channel::GetSendTelephoneEventPayloadType()");
4513 type = _sendTelephoneEventPayloadType;
4514 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4515 VoEId(_instanceId,_channelId),
4516 "GetSendTelephoneEventPayloadType() => type=%u", type);
4517 return 0;
4518}
4519
4520#ifdef WEBRTC_DTMF_DETECTION
4521
4522WebRtc_Word32
4523Channel::RegisterTelephoneEventDetection(
4524 TelephoneEventDetectionMethods detectionMethod,
4525 VoETelephoneEventObserver& observer)
4526{
4527 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4528 "Channel::RegisterTelephoneEventDetection()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004529 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004530
4531 if (_telephoneEventDetectionPtr)
4532 {
4533 _engineStatisticsPtr->SetLastError(
4534 VE_INVALID_OPERATION, kTraceError,
4535 "RegisterTelephoneEventDetection() detection already enabled");
4536 return -1;
4537 }
4538
4539 _telephoneEventDetectionPtr = &observer;
4540
4541 switch (detectionMethod)
4542 {
4543 case kInBand:
4544 _inbandTelephoneEventDetection = true;
4545 _outOfBandTelephoneEventDetecion = false;
4546 break;
4547 case kOutOfBand:
4548 _inbandTelephoneEventDetection = false;
4549 _outOfBandTelephoneEventDetecion = true;
4550 break;
4551 case kInAndOutOfBand:
4552 _inbandTelephoneEventDetection = true;
4553 _outOfBandTelephoneEventDetecion = true;
4554 break;
4555 default:
4556 _engineStatisticsPtr->SetLastError(
4557 VE_INVALID_ARGUMENT, kTraceError,
4558 "RegisterTelephoneEventDetection() invalid detection method");
4559 return -1;
4560 }
4561
4562 if (_inbandTelephoneEventDetection)
4563 {
4564 // Enable in-band Dtmf detectin in the ACM.
4565 if (_audioCodingModule.RegisterIncomingMessagesCallback(this) != 0)
4566 {
4567 _engineStatisticsPtr->SetLastError(
4568 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4569 "RegisterTelephoneEventDetection() failed to enable Dtmf "
4570 "detection");
4571 }
4572 }
4573
4574 // Enable/disable out-of-band detection of received telephone-events.
4575 // When enabled, RtpAudioFeedback::OnReceivedTelephoneEvent() will be
4576 // called two times by the RTP/RTCP module (start & end).
4577 const bool forwardToDecoder =
4578 _rtpRtcpModule.TelephoneEventForwardToDecoder();
4579 const bool detectEndOfTone = true;
4580 _rtpRtcpModule.SetTelephoneEventStatus(_outOfBandTelephoneEventDetecion,
4581 forwardToDecoder,
4582 detectEndOfTone);
4583
4584 return 0;
4585}
4586
4587int
4588Channel::DeRegisterTelephoneEventDetection()
4589{
4590 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4591 "Channel::DeRegisterTelephoneEventDetection()");
4592
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004593 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004594
4595 if (!_telephoneEventDetectionPtr)
4596 {
4597 _engineStatisticsPtr->SetLastError(
4598 VE_INVALID_OPERATION,
4599 kTraceWarning,
4600 "DeRegisterTelephoneEventDetection() detection already disabled");
4601 return 0;
4602 }
4603
4604 // Disable out-of-band event detection
4605 const bool forwardToDecoder =
4606 _rtpRtcpModule.TelephoneEventForwardToDecoder();
4607 _rtpRtcpModule.SetTelephoneEventStatus(false, forwardToDecoder);
4608
4609 // Disable in-band Dtmf detection
4610 _audioCodingModule.RegisterIncomingMessagesCallback(NULL);
4611
4612 _inbandTelephoneEventDetection = false;
4613 _outOfBandTelephoneEventDetecion = false;
4614 _telephoneEventDetectionPtr = NULL;
4615
4616 return 0;
4617}
4618
4619int
4620Channel::GetTelephoneEventDetectionStatus(
4621 bool& enabled,
4622 TelephoneEventDetectionMethods& detectionMethod)
4623{
4624 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4625 "Channel::GetTelephoneEventDetectionStatus()");
4626
4627 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004628 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004629 enabled = (_telephoneEventDetectionPtr != NULL);
4630 }
4631
4632 if (enabled)
4633 {
4634 if (_inbandTelephoneEventDetection && !_outOfBandTelephoneEventDetecion)
4635 detectionMethod = kInBand;
4636 else if (!_inbandTelephoneEventDetection
4637 && _outOfBandTelephoneEventDetecion)
4638 detectionMethod = kOutOfBand;
4639 else if (_inbandTelephoneEventDetection
4640 && _outOfBandTelephoneEventDetecion)
4641 detectionMethod = kInAndOutOfBand;
4642 else
4643 {
4644 assert(false);
4645 return -1;
4646 }
4647 }
4648
4649 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4650 VoEId(_instanceId, _channelId),
4651 "GetTelephoneEventDetectionStatus() => enabled=%d,"
4652 "detectionMethod=%d", enabled, detectionMethod);
4653 return 0;
4654}
4655
4656#endif // #ifdef WEBRTC_DTMF_DETECTION
4657
4658int
4659Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
4660{
4661 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4662 "Channel::UpdateRxVadDetection()");
4663
4664 int vadDecision = 1;
4665
4666 vadDecision = (audioFrame._vadActivity == AudioFrame::kVadActive)? 1 : 0;
4667
4668 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
4669 {
4670 OnRxVadDetected(vadDecision);
4671 _oldVadDecision = vadDecision;
4672 }
4673
4674 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4675 "Channel::UpdateRxVadDetection() => vadDecision=%d",
4676 vadDecision);
4677 return 0;
4678}
4679
4680int
4681Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
4682{
4683 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4684 "Channel::RegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004685 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004686
4687 if (_rxVadObserverPtr)
4688 {
4689 _engineStatisticsPtr->SetLastError(
4690 VE_INVALID_OPERATION, kTraceError,
4691 "RegisterRxVadObserver() observer already enabled");
4692 return -1;
4693 }
niklase@google.com470e71d2011-07-07 08:21:25 +00004694 _rxVadObserverPtr = &observer;
4695 _RxVadDetection = true;
4696 return 0;
4697}
4698
4699int
4700Channel::DeRegisterRxVadObserver()
4701{
4702 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4703 "Channel::DeRegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004704 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004705
4706 if (!_rxVadObserverPtr)
4707 {
4708 _engineStatisticsPtr->SetLastError(
4709 VE_INVALID_OPERATION, kTraceWarning,
4710 "DeRegisterRxVadObserver() observer already disabled");
4711 return 0;
4712 }
4713 _rxVadObserverPtr = NULL;
4714 _RxVadDetection = false;
4715 return 0;
4716}
4717
4718int
4719Channel::VoiceActivityIndicator(int &activity)
4720{
4721 activity = _sendFrameType;
4722
4723 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4724 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
4725 return 0;
4726}
4727
4728#ifdef WEBRTC_VOICE_ENGINE_AGC
4729
4730int
4731Channel::SetRxAgcStatus(const bool enable, const AgcModes mode)
4732{
4733 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4734 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
4735 (int)enable, (int)mode);
4736
4737 GainControl::Mode agcMode(GainControl::kFixedDigital);
4738 switch (mode)
4739 {
4740 case kAgcDefault:
4741 agcMode = GainControl::kAdaptiveDigital;
4742 break;
4743 case kAgcUnchanged:
4744 agcMode = _rxAudioProcessingModulePtr->gain_control()->mode();
4745 break;
4746 case kAgcFixedDigital:
4747 agcMode = GainControl::kFixedDigital;
4748 break;
4749 case kAgcAdaptiveDigital:
4750 agcMode =GainControl::kAdaptiveDigital;
4751 break;
4752 default:
4753 _engineStatisticsPtr->SetLastError(
4754 VE_INVALID_ARGUMENT, kTraceError,
4755 "SetRxAgcStatus() invalid Agc mode");
4756 return -1;
4757 }
4758
4759 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(agcMode) != 0)
4760 {
4761 _engineStatisticsPtr->SetLastError(
4762 VE_APM_ERROR, kTraceError,
4763 "SetRxAgcStatus() failed to set Agc mode");
4764 return -1;
4765 }
4766 if (_rxAudioProcessingModulePtr->gain_control()->Enable(enable) != 0)
4767 {
4768 _engineStatisticsPtr->SetLastError(
4769 VE_APM_ERROR, kTraceError,
4770 "SetRxAgcStatus() failed to set Agc state");
4771 return -1;
4772 }
4773
4774 _rxAgcIsEnabled = enable;
4775
4776 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4777
4778 return 0;
4779}
4780
4781int
4782Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
4783{
4784 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4785 "Channel::GetRxAgcStatus(enable=?, mode=?)");
4786
4787 bool enable = _rxAudioProcessingModulePtr->gain_control()->is_enabled();
4788 GainControl::Mode agcMode =
4789 _rxAudioProcessingModulePtr->gain_control()->mode();
4790
4791 enabled = enable;
4792
4793 switch (agcMode)
4794 {
4795 case GainControl::kFixedDigital:
4796 mode = kAgcFixedDigital;
4797 break;
4798 case GainControl::kAdaptiveDigital:
4799 mode = kAgcAdaptiveDigital;
4800 break;
4801 default:
4802 _engineStatisticsPtr->SetLastError(
4803 VE_APM_ERROR, kTraceError,
4804 "GetRxAgcStatus() invalid Agc mode");
4805 return -1;
4806 }
4807
4808 return 0;
4809}
4810
4811int
4812Channel::SetRxAgcConfig(const AgcConfig config)
4813{
4814 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4815 "Channel::SetRxAgcConfig()");
4816
4817 if (_rxAudioProcessingModulePtr->gain_control()->set_target_level_dbfs(
4818 config.targetLeveldBOv) != 0)
4819 {
4820 _engineStatisticsPtr->SetLastError(
4821 VE_APM_ERROR, kTraceError,
4822 "SetRxAgcConfig() failed to set target peak |level|"
4823 "(or envelope) of the Agc");
4824 return -1;
4825 }
4826 if (_rxAudioProcessingModulePtr->gain_control()->set_compression_gain_db(
4827 config.digitalCompressionGaindB) != 0)
4828 {
4829 _engineStatisticsPtr->SetLastError(
4830 VE_APM_ERROR, kTraceError,
4831 "SetRxAgcConfig() failed to set the range in |gain| the"
4832 " digital compression stage may apply");
4833 return -1;
4834 }
4835 if (_rxAudioProcessingModulePtr->gain_control()->enable_limiter(
4836 config.limiterEnable) != 0)
4837 {
4838 _engineStatisticsPtr->SetLastError(
4839 VE_APM_ERROR, kTraceError,
4840 "SetRxAgcConfig() failed to set hard limiter to the signal");
4841 return -1;
4842 }
4843
4844 return 0;
4845}
4846
4847int
4848Channel::GetRxAgcConfig(AgcConfig& config)
4849{
4850 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4851 "Channel::GetRxAgcConfig(config=%?)");
4852
4853 config.targetLeveldBOv =
4854 _rxAudioProcessingModulePtr->gain_control()->target_level_dbfs();
4855 config.digitalCompressionGaindB =
4856 _rxAudioProcessingModulePtr->gain_control()->compression_gain_db();
4857 config.limiterEnable =
4858 _rxAudioProcessingModulePtr->gain_control()->is_limiter_enabled();
4859
4860 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4861 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
4862 "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
4863 " limiterEnable=%d",
4864 config.targetLeveldBOv,
4865 config.digitalCompressionGaindB,
4866 config.limiterEnable);
4867
4868 return 0;
4869}
4870
4871#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
4872
4873#ifdef WEBRTC_VOICE_ENGINE_NR
4874
4875int
4876Channel::SetRxNsStatus(const bool enable, const NsModes mode)
4877{
4878 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4879 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
4880 (int)enable, (int)mode);
4881
4882 NoiseSuppression::Level nsLevel(
4883 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
4884 switch (mode)
4885 {
4886
4887 case kNsDefault:
4888 nsLevel = (NoiseSuppression::Level)
4889 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
4890 break;
4891 case kNsUnchanged:
4892 nsLevel = _rxAudioProcessingModulePtr->noise_suppression()->level();
4893 break;
4894 case kNsConference:
4895 nsLevel = NoiseSuppression::kHigh;
4896 break;
4897 case kNsLowSuppression:
4898 nsLevel = NoiseSuppression::kLow;
4899 break;
4900 case kNsModerateSuppression:
4901 nsLevel = NoiseSuppression::kModerate;
4902 break;
4903 case kNsHighSuppression:
4904 nsLevel = NoiseSuppression::kHigh;
4905 break;
4906 case kNsVeryHighSuppression:
4907 nsLevel = NoiseSuppression::kVeryHigh;
4908 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004909 }
4910
4911 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(nsLevel)
4912 != 0)
4913 {
4914 _engineStatisticsPtr->SetLastError(
4915 VE_APM_ERROR, kTraceError,
4916 "SetRxAgcStatus() failed to set Ns level");
4917 return -1;
4918 }
4919 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(enable) != 0)
4920 {
4921 _engineStatisticsPtr->SetLastError(
4922 VE_APM_ERROR, kTraceError,
4923 "SetRxAgcStatus() failed to set Agc state");
4924 return -1;
4925 }
4926
4927 _rxNsIsEnabled = enable;
4928 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4929
4930 return 0;
4931}
4932
4933int
4934Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
4935{
4936 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4937 "Channel::GetRxNsStatus(enable=?, mode=?)");
4938
4939 bool enable =
4940 _rxAudioProcessingModulePtr->noise_suppression()->is_enabled();
4941 NoiseSuppression::Level ncLevel =
4942 _rxAudioProcessingModulePtr->noise_suppression()->level();
4943
4944 enabled = enable;
4945
4946 switch (ncLevel)
4947 {
4948 case NoiseSuppression::kLow:
4949 mode = kNsLowSuppression;
4950 break;
4951 case NoiseSuppression::kModerate:
4952 mode = kNsModerateSuppression;
4953 break;
4954 case NoiseSuppression::kHigh:
4955 mode = kNsHighSuppression;
4956 break;
4957 case NoiseSuppression::kVeryHigh:
4958 mode = kNsVeryHighSuppression;
4959 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004960 }
4961
4962 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4963 VoEId(_instanceId,_channelId),
4964 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
4965 return 0;
4966}
4967
4968#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
4969
4970int
4971Channel::RegisterRTPObserver(VoERTPObserver& observer)
4972{
4973 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4974 "Channel::RegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004975 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004976
4977 if (_rtpObserverPtr)
4978 {
4979 _engineStatisticsPtr->SetLastError(
4980 VE_INVALID_OPERATION, kTraceError,
4981 "RegisterRTPObserver() observer already enabled");
4982 return -1;
4983 }
4984
4985 _rtpObserverPtr = &observer;
4986 _rtpObserver = true;
4987
4988 return 0;
4989}
4990
4991int
4992Channel::DeRegisterRTPObserver()
4993{
4994 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4995 "Channel::DeRegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004996 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004997
4998 if (!_rtpObserverPtr)
4999 {
5000 _engineStatisticsPtr->SetLastError(
5001 VE_INVALID_OPERATION, kTraceWarning,
5002 "DeRegisterRTPObserver() observer already disabled");
5003 return 0;
5004 }
5005
5006 _rtpObserver = false;
5007 _rtpObserverPtr = NULL;
5008
5009 return 0;
5010}
5011
5012int
5013Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
5014{
5015 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5016 "Channel::RegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005017 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005018
5019 if (_rtcpObserverPtr)
5020 {
5021 _engineStatisticsPtr->SetLastError(
5022 VE_INVALID_OPERATION, kTraceError,
5023 "RegisterRTCPObserver() observer already enabled");
5024 return -1;
5025 }
5026
5027 _rtcpObserverPtr = &observer;
5028 _rtcpObserver = true;
5029
5030 return 0;
5031}
5032
5033int
5034Channel::DeRegisterRTCPObserver()
5035{
5036 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5037 "Channel::DeRegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005038 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005039
5040 if (!_rtcpObserverPtr)
5041 {
5042 _engineStatisticsPtr->SetLastError(
5043 VE_INVALID_OPERATION, kTraceWarning,
5044 "DeRegisterRTCPObserver() observer already disabled");
5045 return 0;
5046 }
5047
5048 _rtcpObserver = false;
5049 _rtcpObserverPtr = NULL;
5050
5051 return 0;
5052}
5053
5054int
5055Channel::SetLocalSSRC(unsigned int ssrc)
5056{
5057 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5058 "Channel::SetLocalSSRC()");
5059 if (_sending)
5060 {
5061 _engineStatisticsPtr->SetLastError(
5062 VE_ALREADY_SENDING, kTraceError,
5063 "SetLocalSSRC() already sending");
5064 return -1;
5065 }
5066 if (_rtpRtcpModule.SetSSRC(ssrc) != 0)
5067 {
5068 _engineStatisticsPtr->SetLastError(
5069 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5070 "SetLocalSSRC() failed to set SSRC");
5071 return -1;
5072 }
5073 return 0;
5074}
5075
5076int
5077Channel::GetLocalSSRC(unsigned int& ssrc)
5078{
5079 ssrc = _rtpRtcpModule.SSRC();
5080 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5081 VoEId(_instanceId,_channelId),
5082 "GetLocalSSRC() => ssrc=%lu", ssrc);
5083 return 0;
5084}
5085
5086int
5087Channel::GetRemoteSSRC(unsigned int& ssrc)
5088{
5089 ssrc = _rtpRtcpModule.RemoteSSRC();
5090 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5091 VoEId(_instanceId,_channelId),
5092 "GetRemoteSSRC() => ssrc=%lu", ssrc);
5093 return 0;
5094}
5095
5096int
5097Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
5098{
5099 if (arrCSRC == NULL)
5100 {
5101 _engineStatisticsPtr->SetLastError(
5102 VE_INVALID_ARGUMENT, kTraceError,
5103 "GetRemoteCSRCs() invalid array argument");
5104 return -1;
5105 }
5106 WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize];
5107 WebRtc_Word32 CSRCs(0);
5108 CSRCs = _rtpRtcpModule.CSRCs(arrOfCSRC);
5109 if (CSRCs > 0)
5110 {
5111 memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(WebRtc_UWord32));
5112 for (int i = 0; i < (int) CSRCs; i++)
5113 {
5114 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5115 VoEId(_instanceId, _channelId),
5116 "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
5117 }
5118 } else
5119 {
5120 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5121 VoEId(_instanceId, _channelId),
5122 "GetRemoteCSRCs() => list is empty!");
5123 }
5124 return CSRCs;
5125}
5126
5127int
5128Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
5129{
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005130 if (_rtpAudioProc.get() == NULL)
5131 {
5132 _rtpAudioProc.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
5133 _channelId)));
5134 if (_rtpAudioProc.get() == NULL)
5135 {
5136 _engineStatisticsPtr->SetLastError(VE_NO_MEMORY, kTraceCritical,
5137 "Failed to create AudioProcessing");
5138 return -1;
5139 }
5140 }
5141
5142 if (_rtpAudioProc->level_estimator()->Enable(enable) !=
5143 AudioProcessing::kNoError)
5144 {
5145 _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceWarning,
5146 "Failed to enable AudioProcessing::level_estimator()");
5147 }
5148
niklase@google.com470e71d2011-07-07 08:21:25 +00005149 _includeAudioLevelIndication = enable;
5150 return _rtpRtcpModule.SetRTPAudioLevelIndicationStatus(enable, ID);
5151}
5152int
5153Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
5154{
5155 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5156 VoEId(_instanceId,_channelId),
5157 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
5158 enabled, ID);
5159 return _rtpRtcpModule.GetRTPAudioLevelIndicationStatus(enabled, ID);
5160}
5161
5162int
5163Channel::SetRTCPStatus(bool enable)
5164{
5165 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5166 "Channel::SetRTCPStatus()");
5167 if (_rtpRtcpModule.SetRTCPStatus(enable ?
5168 kRtcpCompound : kRtcpOff) != 0)
5169 {
5170 _engineStatisticsPtr->SetLastError(
5171 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5172 "SetRTCPStatus() failed to set RTCP status");
5173 return -1;
5174 }
5175 return 0;
5176}
5177
5178int
5179Channel::GetRTCPStatus(bool& enabled)
5180{
5181 RTCPMethod method = _rtpRtcpModule.RTCP();
5182 enabled = (method != kRtcpOff);
5183 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5184 VoEId(_instanceId,_channelId),
5185 "GetRTCPStatus() => enabled=%d", enabled);
5186 return 0;
5187}
5188
5189int
5190Channel::SetRTCP_CNAME(const char cName[256])
5191{
5192 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5193 "Channel::SetRTCP_CNAME()");
5194 if (_rtpRtcpModule.SetCNAME(cName) != 0)
5195 {
5196 _engineStatisticsPtr->SetLastError(
5197 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5198 "SetRTCP_CNAME() failed to set RTCP CNAME");
5199 return -1;
5200 }
5201 return 0;
5202}
5203
5204int
5205Channel::GetRTCP_CNAME(char cName[256])
5206{
5207 if (_rtpRtcpModule.CNAME(cName) != 0)
5208 {
5209 _engineStatisticsPtr->SetLastError(
5210 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5211 "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
5212 return -1;
5213 }
5214 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5215 VoEId(_instanceId, _channelId),
5216 "GetRTCP_CNAME() => cName=%s", cName);
5217 return 0;
5218}
5219
5220int
5221Channel::GetRemoteRTCP_CNAME(char cName[256])
5222{
5223 if (cName == NULL)
5224 {
5225 _engineStatisticsPtr->SetLastError(
5226 VE_INVALID_ARGUMENT, kTraceError,
5227 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
5228 return -1;
5229 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00005230 char cname[RTCP_CNAME_SIZE];
niklase@google.com470e71d2011-07-07 08:21:25 +00005231 const WebRtc_UWord32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
5232 if (_rtpRtcpModule.RemoteCNAME(remoteSSRC, cname) != 0)
5233 {
5234 _engineStatisticsPtr->SetLastError(
5235 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
5236 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
5237 return -1;
5238 }
5239 strcpy(cName, cname);
5240 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5241 VoEId(_instanceId, _channelId),
5242 "GetRemoteRTCP_CNAME() => cName=%s", cName);
5243 return 0;
5244}
5245
5246int
5247Channel::GetRemoteRTCPData(
5248 unsigned int& NTPHigh,
5249 unsigned int& NTPLow,
5250 unsigned int& timestamp,
5251 unsigned int& playoutTimestamp,
5252 unsigned int* jitter,
5253 unsigned short* fractionLost)
5254{
5255 // --- Information from sender info in received Sender Reports
5256
5257 RTCPSenderInfo senderInfo;
5258 if (_rtpRtcpModule.RemoteRTCPStat(&senderInfo) != 0)
5259 {
5260 _engineStatisticsPtr->SetLastError(
5261 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005262 "GetRemoteRTCPData() failed to retrieve sender info for remote "
niklase@google.com470e71d2011-07-07 08:21:25 +00005263 "side");
5264 return -1;
5265 }
5266
5267 // We only utilize 12 out of 20 bytes in the sender info (ignores packet
5268 // and octet count)
5269 NTPHigh = senderInfo.NTPseconds;
5270 NTPLow = senderInfo.NTPfraction;
5271 timestamp = senderInfo.RTPtimeStamp;
5272
5273 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5274 VoEId(_instanceId, _channelId),
5275 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
5276 "timestamp=%lu",
5277 NTPHigh, NTPLow, timestamp);
5278
5279 // --- Locally derived information
5280
5281 // This value is updated on each incoming RTCP packet (0 when no packet
5282 // has been received)
5283 playoutTimestamp = _playoutTimeStampRTCP;
5284
5285 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5286 VoEId(_instanceId, _channelId),
5287 "GetRemoteRTCPData() => playoutTimestamp=%lu",
5288 _playoutTimeStampRTCP);
5289
5290 if (NULL != jitter || NULL != fractionLost)
5291 {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005292 // Get all RTCP receiver report blocks that have been received on this
5293 // channel. If we receive RTP packets from a remote source we know the
5294 // remote SSRC and use the report block from him.
5295 // Otherwise use the first report block.
5296 std::vector<RTCPReportBlock> remote_stats;
5297 if (_rtpRtcpModule.RemoteRTCPStat(&remote_stats) != 0 ||
5298 remote_stats.empty()) {
5299 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5300 VoEId(_instanceId, _channelId),
5301 "GetRemoteRTCPData() failed to measure statistics due"
5302 " to lack of received RTP and/or RTCP packets");
5303 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00005304 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005305
5306 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
5307 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
5308 for (; it != remote_stats.end(); ++it) {
5309 if (it->remoteSSRC == remoteSSRC)
5310 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00005311 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005312
5313 if (it == remote_stats.end()) {
5314 // If we have not received any RTCP packets from this SSRC it probably
5315 // means that we have not received any RTP packets.
5316 // Use the first received report block instead.
5317 it = remote_stats.begin();
5318 remoteSSRC = it->remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00005319 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005320
xians@webrtc.org79af7342012-01-31 12:22:14 +00005321 if (jitter) {
5322 *jitter = it->jitter;
5323 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5324 VoEId(_instanceId, _channelId),
5325 "GetRemoteRTCPData() => jitter = %lu", *jitter);
5326 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005327
xians@webrtc.org79af7342012-01-31 12:22:14 +00005328 if (fractionLost) {
5329 *fractionLost = it->fractionLost;
5330 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5331 VoEId(_instanceId, _channelId),
5332 "GetRemoteRTCPData() => fractionLost = %lu",
5333 *fractionLost);
5334 }
niklase@google.com470e71d2011-07-07 08:21:25 +00005335 }
5336 return 0;
5337}
5338
5339int
5340Channel::SendApplicationDefinedRTCPPacket(const unsigned char subType,
5341 unsigned int name,
5342 const char* data,
5343 unsigned short dataLengthInBytes)
5344{
5345 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5346 "Channel::SendApplicationDefinedRTCPPacket()");
5347 if (!_sending)
5348 {
5349 _engineStatisticsPtr->SetLastError(
5350 VE_NOT_SENDING, kTraceError,
5351 "SendApplicationDefinedRTCPPacket() not sending");
5352 return -1;
5353 }
5354 if (NULL == data)
5355 {
5356 _engineStatisticsPtr->SetLastError(
5357 VE_INVALID_ARGUMENT, kTraceError,
5358 "SendApplicationDefinedRTCPPacket() invalid data value");
5359 return -1;
5360 }
5361 if (dataLengthInBytes % 4 != 0)
5362 {
5363 _engineStatisticsPtr->SetLastError(
5364 VE_INVALID_ARGUMENT, kTraceError,
5365 "SendApplicationDefinedRTCPPacket() invalid length value");
5366 return -1;
5367 }
5368 RTCPMethod status = _rtpRtcpModule.RTCP();
5369 if (status == kRtcpOff)
5370 {
5371 _engineStatisticsPtr->SetLastError(
5372 VE_RTCP_ERROR, kTraceError,
5373 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
5374 return -1;
5375 }
5376
5377 // Create and schedule the RTCP APP packet for transmission
5378 if (_rtpRtcpModule.SetRTCPApplicationSpecificData(
5379 subType,
5380 name,
5381 (const unsigned char*) data,
5382 dataLengthInBytes) != 0)
5383 {
5384 _engineStatisticsPtr->SetLastError(
5385 VE_SEND_ERROR, kTraceError,
5386 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
5387 return -1;
5388 }
5389 return 0;
5390}
5391
5392int
5393Channel::GetRTPStatistics(
5394 unsigned int& averageJitterMs,
5395 unsigned int& maxJitterMs,
5396 unsigned int& discardedPackets)
5397{
5398 WebRtc_UWord8 fraction_lost(0);
5399 WebRtc_UWord32 cum_lost(0);
5400 WebRtc_UWord32 ext_max(0);
5401 WebRtc_UWord32 jitter(0);
5402 WebRtc_UWord32 max_jitter(0);
5403
5404 // The jitter statistics is updated for each received RTP packet and is
5405 // based on received packets.
5406 if (_rtpRtcpModule.StatisticsRTP(&fraction_lost,
5407 &cum_lost,
5408 &ext_max,
5409 &jitter,
5410 &max_jitter) != 0)
5411 {
5412 _engineStatisticsPtr->SetLastError(
5413 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005414 "GetRTPStatistics() failed to read RTP statistics from the "
niklase@google.com470e71d2011-07-07 08:21:25 +00005415 "RTP/RTCP module");
5416 }
5417
5418 const WebRtc_Word32 playoutFrequency =
5419 _audioCodingModule.PlayoutFrequency();
5420 if (playoutFrequency > 0)
5421 {
5422 // Scale RTP statistics given the current playout frequency
5423 maxJitterMs = max_jitter / (playoutFrequency / 1000);
5424 averageJitterMs = jitter / (playoutFrequency / 1000);
5425 }
5426
5427 discardedPackets = _numberOfDiscardedPackets;
5428
5429 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5430 VoEId(_instanceId, _channelId),
5431 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005432 " discardedPackets = %lu)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005433 averageJitterMs, maxJitterMs, discardedPackets);
5434 return 0;
5435}
5436
5437int
5438Channel::GetRTPStatistics(CallStatistics& stats)
5439{
5440 WebRtc_UWord8 fraction_lost(0);
5441 WebRtc_UWord32 cum_lost(0);
5442 WebRtc_UWord32 ext_max(0);
5443 WebRtc_UWord32 jitter(0);
5444 WebRtc_UWord32 max_jitter(0);
5445
5446 // --- Part one of the final structure (four values)
5447
5448 // The jitter statistics is updated for each received RTP packet and is
5449 // based on received packets.
5450 if (_rtpRtcpModule.StatisticsRTP(&fraction_lost,
5451 &cum_lost,
5452 &ext_max,
5453 &jitter,
5454 &max_jitter) != 0)
5455 {
5456 _engineStatisticsPtr->SetLastError(
5457 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5458 "GetRTPStatistics() failed to read RTP statistics from the "
5459 "RTP/RTCP module");
5460 }
5461
5462 stats.fractionLost = fraction_lost;
5463 stats.cumulativeLost = cum_lost;
5464 stats.extendedMax = ext_max;
5465 stats.jitterSamples = jitter;
5466
5467 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5468 VoEId(_instanceId, _channelId),
5469 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005470 " extendedMax=%lu, jitterSamples=%li)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005471 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
5472 stats.jitterSamples);
5473
5474 // --- Part two of the final structure (one value)
5475
5476 WebRtc_UWord16 RTT(0);
5477 RTCPMethod method = _rtpRtcpModule.RTCP();
5478 if (method == kRtcpOff)
5479 {
5480 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5481 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005482 "GetRTPStatistics() RTCP is disabled => valid RTT "
niklase@google.com470e71d2011-07-07 08:21:25 +00005483 "measurements cannot be retrieved");
5484 } else
5485 {
5486 // The remote SSRC will be zero if no RTP packet has been received.
5487 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
5488 if (remoteSSRC > 0)
5489 {
5490 WebRtc_UWord16 avgRTT(0);
5491 WebRtc_UWord16 maxRTT(0);
5492 WebRtc_UWord16 minRTT(0);
5493
5494 if (_rtpRtcpModule.RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
5495 != 0)
5496 {
5497 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5498 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005499 "GetRTPStatistics() failed to retrieve RTT from "
niklase@google.com470e71d2011-07-07 08:21:25 +00005500 "the RTP/RTCP module");
5501 }
5502 } else
5503 {
5504 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5505 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005506 "GetRTPStatistics() failed to measure RTT since no "
niklase@google.com470e71d2011-07-07 08:21:25 +00005507 "RTP packets have been received yet");
5508 }
5509 }
5510
5511 stats.rttMs = static_cast<int> (RTT);
5512
5513 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5514 VoEId(_instanceId, _channelId),
5515 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
5516
5517 // --- Part three of the final structure (four values)
5518
5519 WebRtc_UWord32 bytesSent(0);
5520 WebRtc_UWord32 packetsSent(0);
5521 WebRtc_UWord32 bytesReceived(0);
5522 WebRtc_UWord32 packetsReceived(0);
5523
5524 if (_rtpRtcpModule.DataCountersRTP(&bytesSent,
5525 &packetsSent,
5526 &bytesReceived,
5527 &packetsReceived) != 0)
5528 {
5529 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5530 VoEId(_instanceId, _channelId),
5531 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005532 " output will not be complete");
niklase@google.com470e71d2011-07-07 08:21:25 +00005533 }
5534
5535 stats.bytesSent = bytesSent;
5536 stats.packetsSent = packetsSent;
5537 stats.bytesReceived = bytesReceived;
5538 stats.packetsReceived = packetsReceived;
5539
5540 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5541 VoEId(_instanceId, _channelId),
5542 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005543 " bytesReceived=%d, packetsReceived=%d)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005544 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
5545 stats.packetsReceived);
5546
5547 return 0;
5548}
5549
5550int
5551Channel::SetFECStatus(bool enable, int redPayloadtype)
5552{
5553 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5554 "Channel::SetFECStatus()");
5555
5556 CodecInst codec;
5557
5558 // Get default RED settings from the ACM database
5559 bool foundRED(false);
5560 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
5561 for (int idx = 0; (!foundRED && idx < nSupportedCodecs); idx++)
5562 {
5563 _audioCodingModule.Codec(idx, codec);
5564 if (!STR_CASE_CMP(codec.plname, "RED"))
5565 {
5566 foundRED = true;
5567 }
5568 }
5569 if (!foundRED)
5570 {
5571 _engineStatisticsPtr->SetLastError(
5572 VE_CODEC_ERROR, kTraceError,
5573 "SetFECStatus() RED is not supported");
5574 return -1;
5575 }
5576
5577 if (redPayloadtype != -1)
5578 {
5579 codec.pltype = redPayloadtype;
5580 }
5581
5582 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
5583 {
5584 _engineStatisticsPtr->SetLastError(
5585 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5586 "SetFECStatus() RED registration in ACM module failed");
5587 return -1;
5588 }
5589 if (_rtpRtcpModule.SetSendREDPayloadType(codec.pltype) != 0)
5590 {
5591 _engineStatisticsPtr->SetLastError(
5592 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5593 "SetFECStatus() RED registration in RTP/RTCP module failed");
5594 return -1;
5595 }
5596 if (_audioCodingModule.SetFECStatus(enable) != 0)
5597 {
5598 _engineStatisticsPtr->SetLastError(
5599 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5600 "SetFECStatus() failed to set FEC state in the ACM");
5601 return -1;
5602 }
5603 return 0;
5604}
5605
5606int
5607Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
5608{
5609 enabled = _audioCodingModule.FECStatus();
5610 if (enabled)
5611 {
5612 WebRtc_Word8 payloadType(0);
5613 if (_rtpRtcpModule.SendREDPayloadType(payloadType) != 0)
5614 {
5615 _engineStatisticsPtr->SetLastError(
5616 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5617 "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
5618 "module");
5619 return -1;
5620 }
5621 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5622 VoEId(_instanceId, _channelId),
5623 "GetFECStatus() => enabled=%d, redPayloadtype=%d",
5624 enabled, redPayloadtype);
5625 return 0;
5626 }
5627 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5628 VoEId(_instanceId, _channelId),
5629 "GetFECStatus() => enabled=%d", enabled);
5630 return 0;
5631}
5632
5633int
niklase@google.com470e71d2011-07-07 08:21:25 +00005634Channel::StartRTPDump(const char fileNameUTF8[1024],
5635 RTPDirections direction)
5636{
5637 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5638 "Channel::StartRTPDump()");
5639 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5640 {
5641 _engineStatisticsPtr->SetLastError(
5642 VE_INVALID_ARGUMENT, kTraceError,
5643 "StartRTPDump() invalid RTP direction");
5644 return -1;
5645 }
5646 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5647 &_rtpDumpIn : &_rtpDumpOut;
5648 if (rtpDumpPtr == NULL)
5649 {
5650 assert(false);
5651 return -1;
5652 }
5653 if (rtpDumpPtr->IsActive())
5654 {
5655 rtpDumpPtr->Stop();
5656 }
5657 if (rtpDumpPtr->Start(fileNameUTF8) != 0)
5658 {
5659 _engineStatisticsPtr->SetLastError(
5660 VE_BAD_FILE, kTraceError,
5661 "StartRTPDump() failed to create file");
5662 return -1;
5663 }
5664 return 0;
5665}
5666
5667int
5668Channel::StopRTPDump(RTPDirections direction)
5669{
5670 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5671 "Channel::StopRTPDump()");
5672 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5673 {
5674 _engineStatisticsPtr->SetLastError(
5675 VE_INVALID_ARGUMENT, kTraceError,
5676 "StopRTPDump() invalid RTP direction");
5677 return -1;
5678 }
5679 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5680 &_rtpDumpIn : &_rtpDumpOut;
5681 if (rtpDumpPtr == NULL)
5682 {
5683 assert(false);
5684 return -1;
5685 }
5686 if (!rtpDumpPtr->IsActive())
5687 {
5688 return 0;
5689 }
5690 return rtpDumpPtr->Stop();
5691}
5692
5693bool
5694Channel::RTPDumpIsActive(RTPDirections direction)
5695{
5696 if ((direction != kRtpIncoming) &&
5697 (direction != kRtpOutgoing))
5698 {
5699 _engineStatisticsPtr->SetLastError(
5700 VE_INVALID_ARGUMENT, kTraceError,
5701 "RTPDumpIsActive() invalid RTP direction");
5702 return false;
5703 }
5704 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5705 &_rtpDumpIn : &_rtpDumpOut;
5706 return rtpDumpPtr->IsActive();
5707}
5708
5709int
5710Channel::InsertExtraRTPPacket(unsigned char payloadType,
5711 bool markerBit,
5712 const char* payloadData,
5713 unsigned short payloadSize)
5714{
5715 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5716 "Channel::InsertExtraRTPPacket()");
5717 if (payloadType > 127)
5718 {
5719 _engineStatisticsPtr->SetLastError(
5720 VE_INVALID_PLTYPE, kTraceError,
5721 "InsertExtraRTPPacket() invalid payload type");
5722 return -1;
5723 }
5724 if (payloadData == NULL)
5725 {
5726 _engineStatisticsPtr->SetLastError(
5727 VE_INVALID_ARGUMENT, kTraceError,
5728 "InsertExtraRTPPacket() invalid payload data");
5729 return -1;
5730 }
5731 if (payloadSize > _rtpRtcpModule.MaxDataPayloadLength())
5732 {
5733 _engineStatisticsPtr->SetLastError(
5734 VE_INVALID_ARGUMENT, kTraceError,
5735 "InsertExtraRTPPacket() invalid payload size");
5736 return -1;
5737 }
5738 if (!_sending)
5739 {
5740 _engineStatisticsPtr->SetLastError(
5741 VE_NOT_SENDING, kTraceError,
5742 "InsertExtraRTPPacket() not sending");
5743 return -1;
5744 }
5745
5746 // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
5747 // Transport::SendPacket() will be called by the module when the RTP packet
5748 // is created.
5749 // The call to SendOutgoingData() does *not* modify the timestamp and
5750 // payloadtype to ensure that the RTP module generates a valid RTP packet
5751 // (user might utilize a non-registered payload type).
5752 // The marker bit and payload type will be replaced just before the actual
5753 // transmission, i.e., the actual modification is done *after* the RTP
5754 // module has delivered its RTP packet back to the VoE.
5755 // We will use the stored values above when the packet is modified
5756 // (see Channel::SendPacket()).
5757
5758 _extraPayloadType = payloadType;
5759 _extraMarkerBit = markerBit;
5760 _insertExtraRTPPacket = true;
5761
5762 if (_rtpRtcpModule.SendOutgoingData(kAudioFrameSpeech,
5763 _lastPayloadType,
5764 _lastLocalTimeStamp,
5765 (const WebRtc_UWord8*) payloadData,
5766 payloadSize) != 0)
5767 {
5768 _engineStatisticsPtr->SetLastError(
5769 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5770 "InsertExtraRTPPacket() failed to send extra RTP packet");
5771 return -1;
5772 }
5773
5774 return 0;
5775}
5776
5777WebRtc_UWord32
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005778Channel::Demultiplex(const AudioFrame& audioFrame)
niklase@google.com470e71d2011-07-07 08:21:25 +00005779{
5780 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005781 "Channel::Demultiplex()");
niklase@google.com470e71d2011-07-07 08:21:25 +00005782 _audioFrame = audioFrame;
5783 _audioFrame._id = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00005784 return 0;
5785}
5786
5787WebRtc_UWord32
xians@google.com0b0665a2011-08-08 08:18:44 +00005788Channel::PrepareEncodeAndSend(int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00005789{
5790 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5791 "Channel::PrepareEncodeAndSend()");
5792
5793 if (_audioFrame._payloadDataLengthInSamples == 0)
5794 {
5795 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5796 "Channel::PrepareEncodeAndSend() invalid audio frame");
5797 return -1;
5798 }
5799
5800 if (_inputFilePlaying)
5801 {
5802 MixOrReplaceAudioWithFile(mixingFrequency);
5803 }
5804
5805 if (_mute)
5806 {
5807 AudioFrameOperations::Mute(_audioFrame);
5808 }
5809
5810 if (_inputExternalMedia)
5811 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005812 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005813 const bool isStereo = (_audioFrame._audioChannel == 2);
5814 if (_inputExternalMediaCallbackPtr)
5815 {
5816 _inputExternalMediaCallbackPtr->Process(
5817 _channelId,
5818 kRecordingPerChannel,
5819 (WebRtc_Word16*)_audioFrame._payloadData,
5820 _audioFrame._payloadDataLengthInSamples,
5821 _audioFrame._frequencyInHz,
5822 isStereo);
5823 }
5824 }
5825
5826 InsertInbandDtmfTone();
5827
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005828 if (_includeAudioLevelIndication)
5829 {
5830 assert(_rtpAudioProc.get() != NULL);
5831
5832 // Check if settings need to be updated.
5833 if (_rtpAudioProc->sample_rate_hz() != _audioFrame._frequencyInHz)
5834 {
5835 if (_rtpAudioProc->set_sample_rate_hz(_audioFrame._frequencyInHz) !=
5836 AudioProcessing::kNoError)
5837 {
5838 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5839 VoEId(_instanceId, _channelId),
5840 "Error setting AudioProcessing sample rate");
5841 return -1;
5842 }
5843 }
5844
5845 if (_rtpAudioProc->num_input_channels() != _audioFrame._audioChannel)
5846 {
5847 if (_rtpAudioProc->set_num_channels(_audioFrame._audioChannel,
5848 _audioFrame._audioChannel)
5849 != AudioProcessing::kNoError)
5850 {
5851 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5852 VoEId(_instanceId, _channelId),
5853 "Error setting AudioProcessing channels");
5854 return -1;
5855 }
5856 }
5857
5858 // Performs level analysis only; does not affect the signal.
5859 _rtpAudioProc->ProcessStream(&_audioFrame);
5860 }
5861
niklase@google.com470e71d2011-07-07 08:21:25 +00005862 return 0;
5863}
5864
5865WebRtc_UWord32
5866Channel::EncodeAndSend()
5867{
5868 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5869 "Channel::EncodeAndSend()");
5870
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00005871 assert(_audioFrame._audioChannel <= 2);
niklase@google.com470e71d2011-07-07 08:21:25 +00005872 if (_audioFrame._payloadDataLengthInSamples == 0)
5873 {
5874 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5875 "Channel::EncodeAndSend() invalid audio frame");
5876 return -1;
5877 }
5878
5879 _audioFrame._id = _channelId;
5880
5881 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
5882
5883 // The ACM resamples internally.
5884 _audioFrame._timeStamp = _timeStamp;
5885 if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
5886 {
5887 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
5888 "Channel::EncodeAndSend() ACM encoding failed");
5889 return -1;
5890 }
5891
5892 _timeStamp += _audioFrame._payloadDataLengthInSamples;
5893
5894 // --- Encode if complete frame is ready
5895
5896 // This call will trigger AudioPacketizationCallback::SendData if encoding
5897 // is done and payload is ready for packetization and transmission.
5898 return _audioCodingModule.Process();
5899}
5900
5901int Channel::RegisterExternalMediaProcessing(
5902 ProcessingTypes type,
5903 VoEMediaProcess& processObject)
5904{
5905 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5906 "Channel::RegisterExternalMediaProcessing()");
5907
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005908 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005909
5910 if (kPlaybackPerChannel == type)
5911 {
5912 if (_outputExternalMediaCallbackPtr)
5913 {
5914 _engineStatisticsPtr->SetLastError(
5915 VE_INVALID_OPERATION, kTraceError,
5916 "Channel::RegisterExternalMediaProcessing() "
5917 "output external media already enabled");
5918 return -1;
5919 }
5920 _outputExternalMediaCallbackPtr = &processObject;
5921 _outputExternalMedia = true;
5922 }
5923 else if (kRecordingPerChannel == type)
5924 {
5925 if (_inputExternalMediaCallbackPtr)
5926 {
5927 _engineStatisticsPtr->SetLastError(
5928 VE_INVALID_OPERATION, kTraceError,
5929 "Channel::RegisterExternalMediaProcessing() "
5930 "output external media already enabled");
5931 return -1;
5932 }
5933 _inputExternalMediaCallbackPtr = &processObject;
5934 _inputExternalMedia = true;
5935 }
5936 return 0;
5937}
5938
5939int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
5940{
5941 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5942 "Channel::DeRegisterExternalMediaProcessing()");
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, kTraceWarning,
5952 "Channel::DeRegisterExternalMediaProcessing() "
5953 "output external media already disabled");
5954 return 0;
5955 }
5956 _outputExternalMedia = false;
5957 _outputExternalMediaCallbackPtr = NULL;
5958 }
5959 else if (kRecordingPerChannel == type)
5960 {
5961 if (!_inputExternalMediaCallbackPtr)
5962 {
5963 _engineStatisticsPtr->SetLastError(
5964 VE_INVALID_OPERATION, kTraceWarning,
5965 "Channel::DeRegisterExternalMediaProcessing() "
5966 "input external media already disabled");
5967 return 0;
5968 }
5969 _inputExternalMedia = false;
5970 _inputExternalMediaCallbackPtr = NULL;
5971 }
5972
5973 return 0;
5974}
5975
5976int
5977Channel::ResetRTCPStatistics()
5978{
5979 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5980 "Channel::ResetRTCPStatistics()");
5981 WebRtc_UWord32 remoteSSRC(0);
5982 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
5983 return _rtpRtcpModule.ResetRTT(remoteSSRC);
5984}
5985
5986int
5987Channel::GetRoundTripTimeSummary(StatVal& delaysMs) const
5988{
5989 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5990 "Channel::GetRoundTripTimeSummary()");
5991 // Override default module outputs for the case when RTCP is disabled.
5992 // This is done to ensure that we are backward compatible with the
5993 // VoiceEngine where we did not use RTP/RTCP module.
5994 if (!_rtpRtcpModule.RTCP())
5995 {
5996 delaysMs.min = -1;
5997 delaysMs.max = -1;
5998 delaysMs.average = -1;
5999 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6000 "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
6001 " valid RTT measurements cannot be retrieved");
6002 return 0;
6003 }
6004
6005 WebRtc_UWord32 remoteSSRC;
6006 WebRtc_UWord16 RTT;
6007 WebRtc_UWord16 avgRTT;
6008 WebRtc_UWord16 maxRTT;
6009 WebRtc_UWord16 minRTT;
6010 // The remote SSRC will be zero if no RTP packet has been received.
6011 remoteSSRC = _rtpRtcpModule.RemoteSSRC();
6012 if (remoteSSRC == 0)
6013 {
6014 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6015 "Channel::GetRoundTripTimeSummary() unable to measure RTT"
6016 " since no RTP packet has been received yet");
6017 }
6018
6019 // Retrieve RTT statistics from the RTP/RTCP module for the specified
6020 // channel and SSRC. The SSRC is required to parse out the correct source
6021 // in conference scenarios.
6022 if (_rtpRtcpModule.RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
6023 {
6024 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6025 "GetRoundTripTimeSummary unable to retrieve RTT values"
6026 " from the RTCP layer");
6027 delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
6028 }
6029 else
6030 {
6031 delaysMs.min = minRTT;
6032 delaysMs.max = maxRTT;
6033 delaysMs.average = avgRTT;
6034 }
6035 return 0;
6036}
6037
6038int
6039Channel::GetNetworkStatistics(NetworkStatistics& stats)
6040{
6041 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6042 "Channel::GetNetworkStatistics()");
6043 return _audioCodingModule.NetworkStatistics(
6044 (ACMNetworkStatistics &)stats);
6045}
6046
6047int
niklase@google.com470e71d2011-07-07 08:21:25 +00006048Channel::GetDelayEstimate(int& delayMs) const
6049{
6050 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6051 "Channel::GetDelayEstimate()");
6052 delayMs = (_averageDelayMs + 5) / 10 + _recPacketDelayMs;
6053 return 0;
6054}
6055
6056int
6057Channel::SetMinimumPlayoutDelay(int delayMs)
6058{
6059 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6060 "Channel::SetMinimumPlayoutDelay()");
6061 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
6062 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
6063 {
6064 _engineStatisticsPtr->SetLastError(
6065 VE_INVALID_ARGUMENT, kTraceError,
6066 "SetMinimumPlayoutDelay() invalid min delay");
6067 return -1;
6068 }
6069 if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
6070 {
6071 _engineStatisticsPtr->SetLastError(
6072 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6073 "SetMinimumPlayoutDelay() failed to set min playout delay");
6074 return -1;
6075 }
6076 return 0;
6077}
6078
6079int
6080Channel::GetPlayoutTimestamp(unsigned int& timestamp)
6081{
6082 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6083 "Channel::GetPlayoutTimestamp()");
6084 WebRtc_UWord32 playoutTimestamp(0);
6085 if (GetPlayoutTimeStamp(playoutTimestamp) != 0)
6086 {
6087 _engineStatisticsPtr->SetLastError(
6088 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
6089 "GetPlayoutTimestamp() failed to retrieve timestamp");
6090 return -1;
6091 }
6092 timestamp = playoutTimestamp;
6093 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
6094 VoEId(_instanceId,_channelId),
6095 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
6096 return 0;
6097}
6098
6099int
6100Channel::SetInitTimestamp(unsigned int timestamp)
6101{
6102 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6103 "Channel::SetInitTimestamp()");
6104 if (_sending)
6105 {
6106 _engineStatisticsPtr->SetLastError(
6107 VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
6108 return -1;
6109 }
6110 if (_rtpRtcpModule.SetStartTimestamp(timestamp) != 0)
6111 {
6112 _engineStatisticsPtr->SetLastError(
6113 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6114 "SetInitTimestamp() failed to set timestamp");
6115 return -1;
6116 }
6117 return 0;
6118}
6119
6120int
6121Channel::SetInitSequenceNumber(short sequenceNumber)
6122{
6123 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6124 "Channel::SetInitSequenceNumber()");
6125 if (_sending)
6126 {
6127 _engineStatisticsPtr->SetLastError(
6128 VE_SENDING, kTraceError,
6129 "SetInitSequenceNumber() already sending");
6130 return -1;
6131 }
6132 if (_rtpRtcpModule.SetSequenceNumber(sequenceNumber) != 0)
6133 {
6134 _engineStatisticsPtr->SetLastError(
6135 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6136 "SetInitSequenceNumber() failed to set sequence number");
6137 return -1;
6138 }
6139 return 0;
6140}
6141
6142int
6143Channel::GetRtpRtcp(RtpRtcp* &rtpRtcpModule) const
6144{
6145 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6146 "Channel::GetRtpRtcp()");
6147 rtpRtcpModule = &_rtpRtcpModule;
6148 return 0;
6149}
6150
6151WebRtc_Word32
xians@google.com0b0665a2011-08-08 08:18:44 +00006152Channel::MixOrReplaceAudioWithFile(const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00006153{
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006154 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
niklase@google.com470e71d2011-07-07 08:21:25 +00006155 WebRtc_UWord32 fileSamples(0);
6156
6157 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00006158 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00006159
6160 if (_inputFilePlayerPtr == NULL)
6161 {
6162 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6163 VoEId(_instanceId, _channelId),
6164 "Channel::MixOrReplaceAudioWithFile() fileplayer"
6165 " doesnt exist");
6166 return -1;
6167 }
6168
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006169 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00006170 fileSamples,
6171 mixingFrequency) == -1)
6172 {
6173 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6174 VoEId(_instanceId, _channelId),
6175 "Channel::MixOrReplaceAudioWithFile() file mixing "
6176 "failed");
6177 return -1;
6178 }
6179 if (fileSamples == 0)
6180 {
6181 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6182 VoEId(_instanceId, _channelId),
6183 "Channel::MixOrReplaceAudioWithFile() file is ended");
6184 return 0;
6185 }
6186 }
6187
6188 assert(_audioFrame._payloadDataLengthInSamples == fileSamples);
6189
6190 if (_mixFileWithMicrophone)
6191 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006192 // Currently file stream is always mono.
6193 // TODO(xians): Change the code when FilePlayer supports real stereo.
niklase@google.com470e71d2011-07-07 08:21:25 +00006194 Utility::MixWithSat(_audioFrame._payloadData,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006195 static_cast<int>(_audioFrame._audioChannel),
6196 fileBuffer.get(),
6197 1,
6198 static_cast<int>(fileSamples));
niklase@google.com470e71d2011-07-07 08:21:25 +00006199 }
6200 else
6201 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006202 // Replace ACM audio with file.
6203 // Currently file stream is always mono.
6204 // TODO(xians): Change the code when FilePlayer supports real stereo.
niklase@google.com470e71d2011-07-07 08:21:25 +00006205 _audioFrame.UpdateFrame(_channelId,
6206 -1,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006207 fileBuffer.get(),
6208 static_cast<WebRtc_UWord16>(fileSamples),
niklase@google.com470e71d2011-07-07 08:21:25 +00006209 mixingFrequency,
6210 AudioFrame::kNormalSpeech,
6211 AudioFrame::kVadUnknown,
6212 1);
6213
6214 }
6215 return 0;
6216}
6217
6218WebRtc_Word32
6219Channel::MixAudioWithFile(AudioFrame& audioFrame,
xians@google.com0b0665a2011-08-08 08:18:44 +00006220 const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00006221{
6222 assert(mixingFrequency <= 32000);
6223
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006224 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
niklase@google.com470e71d2011-07-07 08:21:25 +00006225 WebRtc_UWord32 fileSamples(0);
6226
6227 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00006228 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00006229
6230 if (_outputFilePlayerPtr == NULL)
6231 {
6232 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6233 VoEId(_instanceId, _channelId),
6234 "Channel::MixAudioWithFile() file mixing failed");
6235 return -1;
6236 }
6237
6238 // We should get the frequency we ask for.
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006239 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00006240 fileSamples,
6241 mixingFrequency) == -1)
6242 {
6243 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6244 VoEId(_instanceId, _channelId),
6245 "Channel::MixAudioWithFile() file mixing failed");
6246 return -1;
6247 }
6248 }
6249
6250 if (audioFrame._payloadDataLengthInSamples == fileSamples)
6251 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006252 // Currently file stream is always mono.
6253 // TODO(xians): Change the code when FilePlayer supports real stereo.
niklase@google.com470e71d2011-07-07 08:21:25 +00006254 Utility::MixWithSat(audioFrame._payloadData,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006255 static_cast<int>(audioFrame._audioChannel),
6256 fileBuffer.get(),
6257 1,
6258 static_cast<int>(fileSamples));
niklase@google.com470e71d2011-07-07 08:21:25 +00006259 }
6260 else
6261 {
6262 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6263 "Channel::MixAudioWithFile() _payloadDataLengthInSamples(%d) != "
6264 "fileSamples(%d)",
6265 audioFrame._payloadDataLengthInSamples, fileSamples);
6266 return -1;
6267 }
6268
6269 return 0;
6270}
6271
6272int
6273Channel::InsertInbandDtmfTone()
6274{
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006275 // Check if we should start a new tone.
niklase@google.com470e71d2011-07-07 08:21:25 +00006276 if (_inbandDtmfQueue.PendingDtmf() &&
6277 !_inbandDtmfGenerator.IsAddingTone() &&
6278 _inbandDtmfGenerator.DelaySinceLastTone() >
6279 kMinTelephoneEventSeparationMs)
6280 {
6281 WebRtc_Word8 eventCode(0);
6282 WebRtc_UWord16 lengthMs(0);
6283 WebRtc_UWord8 attenuationDb(0);
6284
6285 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
6286 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
6287 if (_playInbandDtmfEvent)
6288 {
6289 // Add tone to output mixer using a reduced length to minimize
6290 // risk of echo.
6291 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
6292 attenuationDb);
6293 }
6294 }
6295
6296 if (_inbandDtmfGenerator.IsAddingTone())
6297 {
6298 WebRtc_UWord16 frequency(0);
6299 _inbandDtmfGenerator.GetSampleRate(frequency);
6300
6301 if (frequency != _audioFrame._frequencyInHz)
6302 {
6303 // Update sample rate of Dtmf tone since the mixing frequency
6304 // has changed.
6305 _inbandDtmfGenerator.SetSampleRate(
6306 (WebRtc_UWord16) (_audioFrame._frequencyInHz));
6307 // Reset the tone to be added taking the new sample rate into
6308 // account.
6309 _inbandDtmfGenerator.ResetTone();
6310 }
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006311
niklase@google.com470e71d2011-07-07 08:21:25 +00006312 WebRtc_Word16 toneBuffer[320];
6313 WebRtc_UWord16 toneSamples(0);
6314 // Get 10ms tone segment and set time since last tone to zero
6315 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
6316 {
6317 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6318 VoEId(_instanceId, _channelId),
6319 "Channel::EncodeAndSend() inserting Dtmf failed");
6320 return -1;
6321 }
6322
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006323 // Replace mixed audio with DTMF tone.
6324 for (int sample = 0;
6325 sample < _audioFrame._payloadDataLengthInSamples;
6326 sample++)
6327 {
6328 for (int channel = 0;
6329 channel < _audioFrame._audioChannel;
6330 channel++)
6331 {
6332 _audioFrame._payloadData[sample * _audioFrame._audioChannel + channel] =
6333 toneBuffer[sample];
6334 }
6335 }
6336
niklase@google.com470e71d2011-07-07 08:21:25 +00006337 assert(_audioFrame._payloadDataLengthInSamples == toneSamples);
6338 } else
6339 {
6340 // Add 10ms to "delay-since-last-tone" counter
6341 _inbandDtmfGenerator.UpdateDelaySinceLastTone();
6342 }
6343 return 0;
6344}
6345
6346WebRtc_Word32
6347Channel::GetPlayoutTimeStamp(WebRtc_UWord32& playoutTimestamp)
6348{
6349 WebRtc_UWord32 timestamp(0);
6350 CodecInst currRecCodec;
6351
6352 if (_audioCodingModule.PlayoutTimestamp(timestamp) == -1)
6353 {
6354 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6355 "Channel::GetPlayoutTimeStamp() failed to read playout"
6356 " timestamp from the ACM");
6357 return -1;
6358 }
6359
6360 WebRtc_UWord16 delayMS(0);
6361 if (_audioDeviceModulePtr->PlayoutDelay(&delayMS) == -1)
6362 {
6363 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6364 "Channel::GetPlayoutTimeStamp() failed to read playout"
6365 " delay from the ADM");
6366 return -1;
6367 }
6368
6369 WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
6370 if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0)
6371 {
6372 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0)
6373 {
6374 playoutFrequency = 8000;
6375 }
6376 }
6377 timestamp -= (delayMS * (playoutFrequency/1000));
6378
6379 playoutTimestamp = timestamp;
6380
6381 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6382 "Channel::GetPlayoutTimeStamp() => playoutTimestamp = %lu",
6383 playoutTimestamp);
6384 return 0;
6385}
6386
6387void
6388Channel::ResetDeadOrAliveCounters()
6389{
6390 _countDeadDetections = 0;
6391 _countAliveDetections = 0;
6392}
6393
6394void
6395Channel::UpdateDeadOrAliveCounters(bool alive)
6396{
6397 if (alive)
6398 _countAliveDetections++;
6399 else
6400 _countDeadDetections++;
6401}
6402
6403int
6404Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
6405{
6406 bool enabled;
6407 WebRtc_UWord8 timeSec;
6408
6409 _rtpRtcpModule.PeriodicDeadOrAliveStatus(enabled, timeSec);
6410 if (!enabled)
6411 return (-1);
6412
6413 countDead = static_cast<int> (_countDeadDetections);
6414 countAlive = static_cast<int> (_countAliveDetections);
6415 return 0;
6416}
6417
6418WebRtc_Word32
6419Channel::SendPacketRaw(const void *data, int len, bool RTCP)
6420{
6421 if (_transportPtr == NULL)
6422 {
6423 return -1;
6424 }
6425 if (!RTCP)
6426 {
6427 return _transportPtr->SendPacket(_channelId, data, len);
6428 }
6429 else
6430 {
6431 return _transportPtr->SendRTCPPacket(_channelId, data, len);
6432 }
6433}
6434
6435WebRtc_Word32
6436Channel::UpdatePacketDelay(const WebRtc_UWord32 timestamp,
6437 const WebRtc_UWord16 sequenceNumber)
6438{
6439 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6440 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
6441 timestamp, sequenceNumber);
6442
6443 WebRtc_Word32 rtpReceiveFrequency(0);
6444
6445 // Get frequency of last received payload
6446 rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
6447
6448 CodecInst currRecCodec;
6449 if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0)
6450 {
6451 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0)
6452 {
6453 // Even though the actual sampling rate for G.722 audio is
6454 // 16,000 Hz, the RTP clock rate for the G722 payload format is
6455 // 8,000 Hz because that value was erroneously assigned in
6456 // RFC 1890 and must remain unchanged for backward compatibility.
6457 rtpReceiveFrequency = 8000;
6458 }
6459 }
6460
6461 const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
6462 WebRtc_UWord32 timeStampDiffMs(0);
6463
6464 if (timeStampDiff > 0)
6465 {
6466 switch (rtpReceiveFrequency)
6467 {
6468 case 8000:
6469 timeStampDiffMs = timeStampDiff >> 3;
6470 break;
6471 case 16000:
6472 timeStampDiffMs = timeStampDiff >> 4;
6473 break;
6474 case 32000:
6475 timeStampDiffMs = timeStampDiff >> 5;
6476 break;
6477 default:
6478 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6479 VoEId(_instanceId, _channelId),
6480 "Channel::UpdatePacketDelay() invalid sample "
6481 "rate");
6482 timeStampDiffMs = 0;
6483 return -1;
6484 }
6485 if (timeStampDiffMs > 5000)
6486 {
6487 timeStampDiffMs = 0;
6488 }
6489
6490 if (_averageDelayMs == 0)
6491 {
6492 _averageDelayMs = timeStampDiffMs;
6493 }
6494 else
6495 {
6496 // Filter average delay value using exponential filter (alpha is
6497 // 7/8). We derive 10*_averageDelayMs here (reduces risk of
6498 // rounding error) and compensate for it in GetDelayEstimate()
6499 // later. Adding 4/8 results in correct rounding.
6500 _averageDelayMs = ((_averageDelayMs*7 + 10*timeStampDiffMs + 4)>>3);
6501 }
6502
6503 if (sequenceNumber - _previousSequenceNumber == 1)
6504 {
6505 WebRtc_UWord16 packetDelayMs = 0;
6506 switch (rtpReceiveFrequency)
6507 {
6508 case 8000:
6509 packetDelayMs = (WebRtc_UWord16)(
6510 (timestamp - _previousTimestamp) >> 3);
6511 break;
6512 case 16000:
6513 packetDelayMs = (WebRtc_UWord16)(
6514 (timestamp - _previousTimestamp) >> 4);
6515 break;
6516 case 32000:
6517 packetDelayMs = (WebRtc_UWord16)(
6518 (timestamp - _previousTimestamp) >> 5);
6519 break;
6520 }
6521
6522 if (packetDelayMs >= 10 && packetDelayMs <= 60)
6523 _recPacketDelayMs = packetDelayMs;
6524 }
6525 }
6526
6527 _previousSequenceNumber = sequenceNumber;
6528 _previousTimestamp = timestamp;
6529
6530 return 0;
6531}
6532
6533void
6534Channel::RegisterReceiveCodecsToRTPModule()
6535{
6536 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6537 "Channel::RegisterReceiveCodecsToRTPModule()");
6538
6539
6540 CodecInst codec;
6541 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
6542
6543 for (int idx = 0; idx < nSupportedCodecs; idx++)
6544 {
6545 // Open up the RTP/RTCP receiver for all supported codecs
6546 if ((_audioCodingModule.Codec(idx, codec) == -1) ||
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00006547 (_rtpRtcpModule.RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00006548 {
6549 WEBRTC_TRACE(
6550 kTraceWarning,
6551 kTraceVoice,
6552 VoEId(_instanceId, _channelId),
6553 "Channel::RegisterReceiveCodecsToRTPModule() unable"
6554 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
6555 codec.plname, codec.pltype, codec.plfreq,
6556 codec.channels, codec.rate);
6557 }
6558 else
6559 {
6560 WEBRTC_TRACE(
6561 kTraceInfo,
6562 kTraceVoice,
6563 VoEId(_instanceId, _channelId),
6564 "Channel::RegisterReceiveCodecsToRTPModule() %s "
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00006565 "(%d/%d/%d/%d) has been added to the RTP/RTCP "
niklase@google.com470e71d2011-07-07 08:21:25 +00006566 "receiver",
6567 codec.plname, codec.pltype, codec.plfreq,
6568 codec.channels, codec.rate);
6569 }
6570 }
6571}
6572
6573int
6574Channel::ApmProcessRx(AudioFrame& audioFrame)
6575{
6576 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6577 "Channel::ApmProcessRx()");
6578
6579 // Reset the APM frequency if the frequency has changed
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00006580 if (_rxAudioProcessingModulePtr->sample_rate_hz() !=
6581 audioFrame._frequencyInHz)
niklase@google.com470e71d2011-07-07 08:21:25 +00006582 {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00006583 if (_rxAudioProcessingModulePtr->set_sample_rate_hz(
6584 audioFrame._frequencyInHz) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00006585 {
6586 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00006587 "AudioProcessingModule::set_sample_rate_hz("
6588 "_frequencyInHz=%u) => error",
6589 _audioFrame._frequencyInHz);
niklase@google.com470e71d2011-07-07 08:21:25 +00006590 }
6591 }
6592
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00006593 if (_rxAudioProcessingModulePtr->ProcessStream(&audioFrame) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00006594 {
6595 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
6596 "AudioProcessingModule::ProcessStream() => error");
6597 }
6598
6599 return 0;
6600}
6601
6602} // namespace voe
6603
6604} // namespace webrtc