blob: 1eabee8401dd5442d068fd5f4910b08411b1066d [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
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000011#include "webrtc/voice_engine/channel.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000013#include "webrtc/modules/audio_device/include/audio_device.h"
14#include "webrtc/modules/audio_processing/include/audio_processing.h"
15#include "webrtc/modules/utility/interface/audio_frame_operations.h"
16#include "webrtc/modules/utility/interface/process_thread.h"
17#include "webrtc/modules/utility/interface/rtp_dump.h"
18#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/interface/logging.h"
20#include "webrtc/system_wrappers/interface/trace.h"
21#include "webrtc/voice_engine/include/voe_base.h"
22#include "webrtc/voice_engine/include/voe_external_media.h"
23#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
24#include "webrtc/voice_engine/output_mixer.h"
25#include "webrtc/voice_engine/statistics.h"
26#include "webrtc/voice_engine/transmit_mixer.h"
27#include "webrtc/voice_engine/utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000028
29#if defined(_WIN32)
30#include <Qos.h>
31#endif
32
andrew@webrtc.org50419b02012-11-14 19:07:54 +000033namespace webrtc {
34namespace voe {
niklase@google.com470e71d2011-07-07 08:21:25 +000035
36WebRtc_Word32
37Channel::SendData(FrameType frameType,
38 WebRtc_UWord8 payloadType,
39 WebRtc_UWord32 timeStamp,
40 const WebRtc_UWord8* payloadData,
41 WebRtc_UWord16 payloadSize,
42 const RTPFragmentationHeader* fragmentation)
43{
44 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
45 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
46 " payloadSize=%u, fragmentation=0x%x)",
47 frameType, payloadType, timeStamp, payloadSize, fragmentation);
48
49 if (_includeAudioLevelIndication)
50 {
andrew@webrtc.org755b04a2011-11-15 16:57:56 +000051 assert(_rtpAudioProc.get() != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +000052 // Store current audio level in the RTP/RTCP module.
53 // The level will be used in combination with voice-activity state
54 // (frameType) to add an RTP header extension
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000055 _rtpRtcpModule->SetAudioLevel(_rtpAudioProc->level_estimator()->RMS());
niklase@google.com470e71d2011-07-07 08:21:25 +000056 }
57
58 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
59 // packetization.
60 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000061 if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
niklase@google.com470e71d2011-07-07 08:21:25 +000062 payloadType,
63 timeStamp,
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +000064 // Leaving the time when this frame was
65 // received from the capture device as
66 // undefined for voice for now.
67 -1,
niklase@google.com470e71d2011-07-07 08:21:25 +000068 payloadData,
69 payloadSize,
70 fragmentation) == -1)
71 {
72 _engineStatisticsPtr->SetLastError(
73 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
74 "Channel::SendData() failed to send data to RTP/RTCP module");
75 return -1;
76 }
77
78 _lastLocalTimeStamp = timeStamp;
79 _lastPayloadType = payloadType;
80
81 return 0;
82}
83
84WebRtc_Word32
85Channel::InFrameType(WebRtc_Word16 frameType)
86{
87 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
88 "Channel::InFrameType(frameType=%d)", frameType);
89
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +000090 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +000091 // 1 indicates speech
92 _sendFrameType = (frameType == 1) ? 1 : 0;
93 return 0;
94}
95
niklase@google.com470e71d2011-07-07 08:21:25 +000096WebRtc_Word32
97Channel::OnRxVadDetected(const int vadDecision)
98{
99 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
100 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
101
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000102 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000103 if (_rxVadObserverPtr)
104 {
105 _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
106 }
107
108 return 0;
109}
110
111int
112Channel::SendPacket(int channel, const void *data, int len)
113{
114 channel = VoEChannelId(channel);
115 assert(channel == _channelId);
116
117 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
118 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
119
120 if (_transportPtr == NULL)
121 {
122 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
123 "Channel::SendPacket() failed to send RTP packet due to"
124 " invalid transport object");
125 return -1;
126 }
127
128 // Insert extra RTP packet using if user has called the InsertExtraRTPPacket
129 // API
130 if (_insertExtraRTPPacket)
131 {
132 WebRtc_UWord8* rtpHdr = (WebRtc_UWord8*)data;
133 WebRtc_UWord8 M_PT(0);
134 if (_extraMarkerBit)
135 {
136 M_PT = 0x80; // set the M-bit
137 }
138 M_PT += _extraPayloadType; // set the payload type
139 *(++rtpHdr) = M_PT; // modify the M|PT-byte within the RTP header
140 _insertExtraRTPPacket = false; // insert one packet only
141 }
142
143 WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
144 WebRtc_Word32 bufferLength = len;
145
146 // Dump the RTP packet to a file (if RTP dump is enabled).
147 if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
148 {
149 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
150 VoEId(_instanceId,_channelId),
151 "Channel::SendPacket() RTP dump to output file failed");
152 }
153
154 // SRTP or External encryption
155 if (_encrypting)
156 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000157 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
159 if (_encryptionPtr)
160 {
161 if (!_encryptionRTPBufferPtr)
162 {
163 // Allocate memory for encryption buffer one time only
164 _encryptionRTPBufferPtr =
165 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
xians@webrtc.org51253502012-10-25 13:58:02 +0000166 memset(_encryptionRTPBufferPtr, 0,
167 kVoiceEngineMaxIpPacketSizeBytes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 }
169
170 // Perform encryption (SRTP or external)
171 WebRtc_Word32 encryptedBufferLength = 0;
172 _encryptionPtr->encrypt(_channelId,
173 bufferToSendPtr,
174 _encryptionRTPBufferPtr,
175 bufferLength,
176 (int*)&encryptedBufferLength);
177 if (encryptedBufferLength <= 0)
178 {
179 _engineStatisticsPtr->SetLastError(
180 VE_ENCRYPTION_FAILED,
181 kTraceError, "Channel::SendPacket() encryption failed");
182 return -1;
183 }
184
185 // Replace default data buffer with encrypted buffer
186 bufferToSendPtr = _encryptionRTPBufferPtr;
187 bufferLength = encryptedBufferLength;
188 }
189 }
190
191 // Packet transmission using WebRtc socket transport
192 if (!_externalTransport)
193 {
194 int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
195 bufferLength);
196 if (n < 0)
197 {
198 WEBRTC_TRACE(kTraceError, kTraceVoice,
199 VoEId(_instanceId,_channelId),
200 "Channel::SendPacket() RTP transmission using WebRtc"
201 " sockets failed");
202 return -1;
203 }
204 return n;
205 }
206
207 // Packet transmission using external transport transport
208 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000209 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000210
211 int n = _transportPtr->SendPacket(channel,
212 bufferToSendPtr,
213 bufferLength);
214 if (n < 0)
215 {
216 WEBRTC_TRACE(kTraceError, kTraceVoice,
217 VoEId(_instanceId,_channelId),
218 "Channel::SendPacket() RTP transmission using external"
219 " transport failed");
220 return -1;
221 }
222 return n;
223 }
224}
225
226int
227Channel::SendRTCPPacket(int channel, const void *data, int len)
228{
229 channel = VoEChannelId(channel);
230 assert(channel == _channelId);
231
232 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
233 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
234
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000236 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +0000237 if (_transportPtr == NULL)
238 {
239 WEBRTC_TRACE(kTraceError, kTraceVoice,
240 VoEId(_instanceId,_channelId),
241 "Channel::SendRTCPPacket() failed to send RTCP packet"
242 " due to invalid transport object");
243 return -1;
244 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 }
246
247 WebRtc_UWord8* bufferToSendPtr = (WebRtc_UWord8*)data;
248 WebRtc_Word32 bufferLength = len;
249
250 // Dump the RTCP packet to a file (if RTP dump is enabled).
251 if (_rtpDumpOut.DumpPacket((const WebRtc_UWord8*)data, len) == -1)
252 {
253 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
254 VoEId(_instanceId,_channelId),
255 "Channel::SendPacket() RTCP dump to output file failed");
256 }
257
258 // SRTP or External encryption
259 if (_encrypting)
260 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000261 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000262
263 if (_encryptionPtr)
264 {
265 if (!_encryptionRTCPBufferPtr)
266 {
267 // Allocate memory for encryption buffer one time only
268 _encryptionRTCPBufferPtr =
269 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
270 }
271
272 // Perform encryption (SRTP or external).
273 WebRtc_Word32 encryptedBufferLength = 0;
274 _encryptionPtr->encrypt_rtcp(_channelId,
275 bufferToSendPtr,
276 _encryptionRTCPBufferPtr,
277 bufferLength,
278 (int*)&encryptedBufferLength);
279 if (encryptedBufferLength <= 0)
280 {
281 _engineStatisticsPtr->SetLastError(
282 VE_ENCRYPTION_FAILED, kTraceError,
283 "Channel::SendRTCPPacket() encryption failed");
284 return -1;
285 }
286
287 // Replace default data buffer with encrypted buffer
288 bufferToSendPtr = _encryptionRTCPBufferPtr;
289 bufferLength = encryptedBufferLength;
290 }
291 }
292
293 // Packet transmission using WebRtc socket transport
294 if (!_externalTransport)
295 {
296 int n = _transportPtr->SendRTCPPacket(channel,
297 bufferToSendPtr,
298 bufferLength);
299 if (n < 0)
300 {
301 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
302 VoEId(_instanceId,_channelId),
303 "Channel::SendRTCPPacket() transmission using WebRtc"
304 " sockets failed");
305 return -1;
306 }
307 return n;
308 }
309
310 // Packet transmission using external transport transport
311 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000312 CriticalSectionScoped cs(&_callbackCritSect);
henrike@webrtc.orgde727ab2012-11-18 18:49:13 +0000313 if (_transportPtr == NULL)
314 {
315 return -1;
316 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000317 int n = _transportPtr->SendRTCPPacket(channel,
318 bufferToSendPtr,
319 bufferLength);
320 if (n < 0)
321 {
322 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
323 VoEId(_instanceId,_channelId),
324 "Channel::SendRTCPPacket() transmission using external"
325 " transport failed");
326 return -1;
327 }
328 return n;
329 }
330
331 return len;
332}
333
334void
pwestin@webrtc.org684f0572013-03-13 23:20:57 +0000335Channel::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket,
336 const WebRtc_Word32 rtpPacketLength,
337 const char* fromIP,
338 const WebRtc_UWord16 fromPort)
339{
340 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
341 "Channel::IncomingRTPPacket(rtpPacketLength=%d,"
342 " fromIP=%s, fromPort=%u)",
343 rtpPacketLength, fromIP, fromPort);
344
345 // Store playout timestamp for the received RTP packet
346 // to be used for upcoming delay estimations
347 WebRtc_UWord32 playoutTimestamp(0);
348 if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
349 {
350 _playoutTimeStampRTP = playoutTimestamp;
351 }
352
353 WebRtc_UWord8* rtpBufferPtr = (WebRtc_UWord8*)incomingRtpPacket;
354 WebRtc_Word32 rtpBufferLength = rtpPacketLength;
355
356 // SRTP or External decryption
357 if (_decrypting)
358 {
359 CriticalSectionScoped cs(&_callbackCritSect);
360
361 if (_encryptionPtr)
362 {
363 if (!_decryptionRTPBufferPtr)
364 {
365 // Allocate memory for decryption buffer one time only
366 _decryptionRTPBufferPtr =
367 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
368 }
369
370 // Perform decryption (SRTP or external)
371 WebRtc_Word32 decryptedBufferLength = 0;
372 _encryptionPtr->decrypt(_channelId,
373 rtpBufferPtr,
374 _decryptionRTPBufferPtr,
375 rtpBufferLength,
376 (int*)&decryptedBufferLength);
377 if (decryptedBufferLength <= 0)
378 {
379 _engineStatisticsPtr->SetLastError(
380 VE_DECRYPTION_FAILED, kTraceError,
381 "Channel::IncomingRTPPacket() decryption failed");
382 return;
383 }
384
385 // Replace default data buffer with decrypted buffer
386 rtpBufferPtr = _decryptionRTPBufferPtr;
387 rtpBufferLength = decryptedBufferLength;
388 }
389 }
390
391 // Dump the RTP packet to a file (if RTP dump is enabled).
392 if (_rtpDumpIn.DumpPacket(rtpBufferPtr,
393 (WebRtc_UWord16)rtpBufferLength) == -1)
394 {
395 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
396 VoEId(_instanceId,_channelId),
397 "Channel::SendPacket() RTP dump to input file failed");
398 }
399
400 // Deliver RTP packet to RTP/RTCP module for parsing
401 // The packet will be pushed back to the channel thru the
402 // OnReceivedPayloadData callback so we don't push it to the ACM here
403 if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtpBufferPtr,
404 (WebRtc_UWord16)rtpBufferLength) == -1)
405 {
406 _engineStatisticsPtr->SetLastError(
407 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
408 "Channel::IncomingRTPPacket() RTP packet is invalid");
409 return;
410 }
411}
412
413void
414Channel::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket,
415 const WebRtc_Word32 rtcpPacketLength,
416 const char* fromIP,
417 const WebRtc_UWord16 fromPort)
418{
419 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
420 "Channel::IncomingRTCPPacket(rtcpPacketLength=%d, fromIP=%s,"
421 " fromPort=%u)",
422 rtcpPacketLength, fromIP, fromPort);
423
424 // Temporary buffer pointer and size for decryption
425 WebRtc_UWord8* rtcpBufferPtr = (WebRtc_UWord8*)incomingRtcpPacket;
426 WebRtc_Word32 rtcpBufferLength = rtcpPacketLength;
427
428 // Store playout timestamp for the received RTCP packet
429 // which will be read by the GetRemoteRTCPData API
430 WebRtc_UWord32 playoutTimestamp(0);
431 if (GetPlayoutTimeStamp(playoutTimestamp) == 0)
432 {
433 _playoutTimeStampRTCP = playoutTimestamp;
434 }
435
436 // SRTP or External decryption
437 if (_decrypting)
438 {
439 CriticalSectionScoped cs(&_callbackCritSect);
440
441 if (_encryptionPtr)
442 {
443 if (!_decryptionRTCPBufferPtr)
444 {
445 // Allocate memory for decryption buffer one time only
446 _decryptionRTCPBufferPtr =
447 new WebRtc_UWord8[kVoiceEngineMaxIpPacketSizeBytes];
448 }
449
450 // Perform decryption (SRTP or external).
451 WebRtc_Word32 decryptedBufferLength = 0;
452 _encryptionPtr->decrypt_rtcp(_channelId,
453 rtcpBufferPtr,
454 _decryptionRTCPBufferPtr,
455 rtcpBufferLength,
456 (int*)&decryptedBufferLength);
457 if (decryptedBufferLength <= 0)
458 {
459 _engineStatisticsPtr->SetLastError(
460 VE_DECRYPTION_FAILED, kTraceError,
461 "Channel::IncomingRTCPPacket() decryption failed");
462 return;
463 }
464
465 // Replace default data buffer with decrypted buffer
466 rtcpBufferPtr = _decryptionRTCPBufferPtr;
467 rtcpBufferLength = decryptedBufferLength;
468 }
469 }
470
471 // Dump the RTCP packet to a file (if RTP dump is enabled).
472 if (_rtpDumpIn.DumpPacket(rtcpBufferPtr,
473 (WebRtc_UWord16)rtcpBufferLength) == -1)
474 {
475 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
476 VoEId(_instanceId,_channelId),
477 "Channel::SendPacket() RTCP dump to input file failed");
478 }
479
480 // Deliver RTCP packet to RTP/RTCP module for parsing
481 if (_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)rtcpBufferPtr,
482 (WebRtc_UWord16)rtcpBufferLength) == -1)
483 {
484 _engineStatisticsPtr->SetLastError(
485 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
486 "Channel::IncomingRTPPacket() RTCP packet is invalid");
487 return;
488 }
489}
490
491void
niklase@google.com470e71d2011-07-07 08:21:25 +0000492Channel::OnPlayTelephoneEvent(const WebRtc_Word32 id,
493 const WebRtc_UWord8 event,
494 const WebRtc_UWord16 lengthMs,
495 const WebRtc_UWord8 volume)
496{
497 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
498 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +0000499 " volume=%u)", id, event, lengthMs, volume);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
501 if (!_playOutbandDtmfEvent || (event > 15))
502 {
503 // Ignore callback since feedback is disabled or event is not a
504 // Dtmf tone event.
505 return;
506 }
507
508 assert(_outputMixerPtr != NULL);
509
510 // Start playing out the Dtmf tone (if playout is enabled).
511 // Reduce length of tone with 80ms to the reduce risk of echo.
512 _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
513}
514
515void
516Channel::OnIncomingSSRCChanged(const WebRtc_Word32 id,
517 const WebRtc_UWord32 SSRC)
518{
519 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
520 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
521 id, SSRC);
522
523 WebRtc_Word32 channel = VoEChannelId(id);
524 assert(channel == _channelId);
525
526 // Reset RTP-module counters since a new incoming RTP stream is detected
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000527 _rtpRtcpModule->ResetReceiveDataCountersRTP();
528 _rtpRtcpModule->ResetStatisticsRTP();
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
530 if (_rtpObserver)
531 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000532 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
534 if (_rtpObserverPtr)
535 {
536 // Send new SSRC to registered observer using callback
537 _rtpObserverPtr->OnIncomingSSRCChanged(channel, SSRC);
538 }
539 }
540}
541
542void Channel::OnIncomingCSRCChanged(const WebRtc_Word32 id,
543 const WebRtc_UWord32 CSRC,
544 const bool added)
545{
546 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
547 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
548 id, CSRC, added);
549
550 WebRtc_Word32 channel = VoEChannelId(id);
551 assert(channel == _channelId);
552
553 if (_rtpObserver)
554 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000555 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000556
557 if (_rtpObserverPtr)
558 {
559 _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
560 }
561 }
562}
563
564void
565Channel::OnApplicationDataReceived(const WebRtc_Word32 id,
566 const WebRtc_UWord8 subType,
567 const WebRtc_UWord32 name,
568 const WebRtc_UWord16 length,
569 const WebRtc_UWord8* data)
570{
571 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
572 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
573 " name=%u, length=%u)",
574 id, subType, name, length);
575
576 WebRtc_Word32 channel = VoEChannelId(id);
577 assert(channel == _channelId);
578
579 if (_rtcpObserver)
580 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000581 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000582
583 if (_rtcpObserverPtr)
584 {
585 _rtcpObserverPtr->OnApplicationDataReceived(channel,
586 subType,
587 name,
588 data,
589 length);
590 }
591 }
592}
593
594WebRtc_Word32
595Channel::OnInitializeDecoder(
596 const WebRtc_Word32 id,
597 const WebRtc_Word8 payloadType,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000598 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
xians@google.com0b0665a2011-08-08 08:18:44 +0000599 const int frequency,
niklase@google.com470e71d2011-07-07 08:21:25 +0000600 const WebRtc_UWord8 channels,
601 const WebRtc_UWord32 rate)
602{
603 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
604 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
605 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
606 id, payloadType, payloadName, frequency, channels, rate);
607
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000608 assert(VoEChannelId(id) == _channelId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
henrika@webrtc.orgf75901f2012-01-16 08:45:42 +0000610 CodecInst receiveCodec = {0};
611 CodecInst dummyCodec = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
613 receiveCodec.pltype = payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614 receiveCodec.plfreq = frequency;
615 receiveCodec.channels = channels;
616 receiveCodec.rate = rate;
henrika@webrtc.orgf75901f2012-01-16 08:45:42 +0000617 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +0000618
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000619 _audioCodingModule.Codec(payloadName, &dummyCodec, frequency, channels);
niklase@google.com470e71d2011-07-07 08:21:25 +0000620 receiveCodec.pacsize = dummyCodec.pacsize;
621
622 // Register the new codec to the ACM
623 if (_audioCodingModule.RegisterReceiveCodec(receiveCodec) == -1)
624 {
625 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000626 VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +0000627 "Channel::OnInitializeDecoder() invalid codec ("
628 "pt=%d, name=%s) received - 1", payloadType, payloadName);
629 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
630 return -1;
631 }
632
633 return 0;
634}
635
636void
637Channel::OnPacketTimeout(const WebRtc_Word32 id)
638{
639 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
640 "Channel::OnPacketTimeout(id=%d)", id);
641
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000642 CriticalSectionScoped cs(_callbackCritSectPtr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643 if (_voiceEngineObserverPtr)
644 {
645 if (_receiving || _externalTransport)
646 {
647 WebRtc_Word32 channel = VoEChannelId(id);
648 assert(channel == _channelId);
649 // Ensure that next OnReceivedPacket() callback will trigger
650 // a VE_PACKET_RECEIPT_RESTARTED callback.
651 _rtpPacketTimedOut = true;
652 // Deliver callback to the observer
653 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
654 VoEId(_instanceId,_channelId),
655 "Channel::OnPacketTimeout() => "
656 "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
657 _voiceEngineObserverPtr->CallbackOnError(channel,
658 VE_RECEIVE_PACKET_TIMEOUT);
659 }
660 }
661}
662
663void
664Channel::OnReceivedPacket(const WebRtc_Word32 id,
665 const RtpRtcpPacketType packetType)
666{
667 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
668 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
669 id, packetType);
670
andrew@webrtc.orgceb148c2011-08-23 17:53:54 +0000671 assert(VoEChannelId(id) == _channelId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000672
673 // Notify only for the case when we have restarted an RTP session.
674 if (_rtpPacketTimedOut && (kPacketRtp == packetType))
675 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000676 CriticalSectionScoped cs(_callbackCritSectPtr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677 if (_voiceEngineObserverPtr)
678 {
679 WebRtc_Word32 channel = VoEChannelId(id);
680 assert(channel == _channelId);
681 // Reset timeout mechanism
682 _rtpPacketTimedOut = false;
683 // Deliver callback to the observer
684 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
685 VoEId(_instanceId,_channelId),
686 "Channel::OnPacketTimeout() =>"
687 " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
688 _voiceEngineObserverPtr->CallbackOnError(
689 channel,
690 VE_PACKET_RECEIPT_RESTARTED);
691 }
692 }
693}
694
695void
696Channel::OnPeriodicDeadOrAlive(const WebRtc_Word32 id,
697 const RTPAliveType alive)
698{
699 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
700 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
701
702 if (!_connectionObserver)
703 return;
704
705 WebRtc_Word32 channel = VoEChannelId(id);
706 assert(channel == _channelId);
707
708 // Use Alive as default to limit risk of false Dead detections
709 bool isAlive(true);
710
711 // Always mark the connection as Dead when the module reports kRtpDead
712 if (kRtpDead == alive)
713 {
714 isAlive = false;
715 }
716
717 // It is possible that the connection is alive even if no RTP packet has
718 // been received for a long time since the other side might use VAD/DTX
719 // and a low SID-packet update rate.
720 if ((kRtpNoRtp == alive) && _playing)
721 {
722 // Detect Alive for all NetEQ states except for the case when we are
723 // in PLC_CNG state.
724 // PLC_CNG <=> background noise only due to long expand or error.
725 // Note that, the case where the other side stops sending during CNG
726 // state will be detected as Alive. Dead is is not set until after
727 // missing RTCP packets for at least twelve seconds (handled
728 // internally by the RTP/RTCP module).
729 isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
730 }
731
732 UpdateDeadOrAliveCounters(isAlive);
733
734 // Send callback to the registered observer
735 if (_connectionObserver)
736 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000737 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000738 if (_connectionObserverPtr)
739 {
740 _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
741 }
742 }
743}
744
745WebRtc_Word32
746Channel::OnReceivedPayloadData(const WebRtc_UWord8* payloadData,
747 const WebRtc_UWord16 payloadSize,
748 const WebRtcRTPHeader* rtpHeader)
749{
750 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
751 "Channel::OnReceivedPayloadData(payloadSize=%d,"
752 " payloadType=%u, audioChannel=%u)",
753 payloadSize,
754 rtpHeader->header.payloadType,
755 rtpHeader->type.Audio.channel);
756
roosa@google.com0870f022012-12-12 21:31:41 +0000757 _lastRemoteTimeStamp = rtpHeader->header.timestamp;
758
niklase@google.com470e71d2011-07-07 08:21:25 +0000759 if (!_playing)
760 {
761 // Avoid inserting into NetEQ when we are not playing. Count the
762 // packet as discarded.
763 WEBRTC_TRACE(kTraceStream, kTraceVoice,
764 VoEId(_instanceId, _channelId),
765 "received packet is discarded since playing is not"
766 " activated");
767 _numberOfDiscardedPackets++;
768 return 0;
769 }
770
771 // Push the incoming payload (parsed and ready for decoding) into the ACM
tina.legrand@webrtc.org16b6b902012-04-12 11:02:38 +0000772 if (_audioCodingModule.IncomingPacket(payloadData,
niklase@google.com470e71d2011-07-07 08:21:25 +0000773 payloadSize,
774 *rtpHeader) != 0)
775 {
776 _engineStatisticsPtr->SetLastError(
777 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
778 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
779 return -1;
780 }
781
782 // Update the packet delay
783 UpdatePacketDelay(rtpHeader->header.timestamp,
784 rtpHeader->header.sequenceNumber);
785
786 return 0;
787}
788
789WebRtc_Word32 Channel::GetAudioFrame(const WebRtc_Word32 id,
790 AudioFrame& audioFrame)
791{
792 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
793 "Channel::GetAudioFrame(id=%d)", id);
794
795 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000796 if (_audioCodingModule.PlayoutData10Ms(audioFrame.sample_rate_hz_,
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +0000797 &audioFrame) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000798 {
799 WEBRTC_TRACE(kTraceError, kTraceVoice,
800 VoEId(_instanceId,_channelId),
801 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
andrew@webrtc.org7859e102012-01-13 00:30:11 +0000802 // In all likelihood, the audio in this frame is garbage. We return an
803 // error so that the audio mixer module doesn't add it to the mix. As
804 // a result, it won't be played out and the actions skipped here are
805 // irrelevant.
806 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000807 }
808
809 if (_RxVadDetection)
810 {
811 UpdateRxVadDetection(audioFrame);
812 }
813
814 // Convert module ID to internal VoE channel ID
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000815 audioFrame.id_ = VoEChannelId(audioFrame.id_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 // Store speech type for dead-or-alive detection
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000817 _outputSpeechType = audioFrame.speech_type_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000818
819 // Perform far-end AudioProcessing module processing on the received signal
820 if (_rxApmIsEnabled)
821 {
822 ApmProcessRx(audioFrame);
823 }
824
825 // Output volume scaling
826 if (_outputGain < 0.99f || _outputGain > 1.01f)
827 {
828 AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
829 }
830
831 // Scale left and/or right channel(s) if stereo and master balance is
832 // active
833
834 if (_panLeft != 1.0f || _panRight != 1.0f)
835 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000836 if (audioFrame.num_channels_ == 1)
niklase@google.com470e71d2011-07-07 08:21:25 +0000837 {
838 // Emulate stereo mode since panning is active.
839 // The mono signal is copied to both left and right channels here.
andrew@webrtc.org4ecea3e2012-06-27 03:25:31 +0000840 AudioFrameOperations::MonoToStereo(&audioFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000841 }
842 // For true stereo mode (when we are receiving a stereo signal), no
843 // action is needed.
844
845 // Do the panning operation (the audio frame contains stereo at this
846 // stage)
847 AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
848 }
849
850 // Mix decoded PCM output with file if file mixing is enabled
851 if (_outputFilePlaying)
852 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000853 MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000854 }
855
856 // Place channel in on-hold state (~muted) if on-hold is activated
857 if (_outputIsOnHold)
858 {
859 AudioFrameOperations::Mute(audioFrame);
860 }
861
862 // External media
863 if (_outputExternalMedia)
864 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000865 CriticalSectionScoped cs(&_callbackCritSect);
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000866 const bool isStereo = (audioFrame.num_channels_ == 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000867 if (_outputExternalMediaCallbackPtr)
868 {
869 _outputExternalMediaCallbackPtr->Process(
870 _channelId,
871 kPlaybackPerChannel,
andrew@webrtc.org63a50982012-05-02 23:56:37 +0000872 (WebRtc_Word16*)audioFrame.data_,
873 audioFrame.samples_per_channel_,
874 audioFrame.sample_rate_hz_,
niklase@google.com470e71d2011-07-07 08:21:25 +0000875 isStereo);
876 }
877 }
878
879 // Record playout if enabled
880 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000881 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000882
883 if (_outputFileRecording && _outputFileRecorderPtr)
884 {
niklas.enbom@webrtc.org5398d952012-03-26 08:11:25 +0000885 _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886 }
887 }
888
889 // Measure audio level (0-9)
890 _outputAudioLevel.ComputeLevel(audioFrame);
891
892 return 0;
893}
894
895WebRtc_Word32
896Channel::NeededFrequency(const WebRtc_Word32 id)
897{
898 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
899 "Channel::NeededFrequency(id=%d)", id);
900
901 int highestNeeded = 0;
902
903 // Determine highest needed receive frequency
904 WebRtc_Word32 receiveFrequency = _audioCodingModule.ReceiveFrequency();
905
906 // Return the bigger of playout and receive frequency in the ACM.
907 if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
908 {
909 highestNeeded = _audioCodingModule.PlayoutFrequency();
910 }
911 else
912 {
913 highestNeeded = receiveFrequency;
914 }
915
916 // Special case, if we're playing a file on the playout side
917 // we take that frequency into consideration as well
918 // This is not needed on sending side, since the codec will
919 // limit the spectrum anyway.
920 if (_outputFilePlaying)
921 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000922 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000923 if (_outputFilePlayerPtr && _outputFilePlaying)
924 {
925 if(_outputFilePlayerPtr->Frequency()>highestNeeded)
926 {
927 highestNeeded=_outputFilePlayerPtr->Frequency();
928 }
929 }
930 }
931
932 return(highestNeeded);
933}
934
niklase@google.com470e71d2011-07-07 08:21:25 +0000935WebRtc_Word32
936Channel::CreateChannel(Channel*& channel,
937 const WebRtc_Word32 channelId,
938 const WebRtc_UWord32 instanceId)
939{
940 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
941 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
942 channelId, instanceId);
943
944 channel = new Channel(channelId, instanceId);
945 if (channel == NULL)
946 {
947 WEBRTC_TRACE(kTraceMemory, kTraceVoice,
948 VoEId(instanceId,channelId),
949 "Channel::CreateChannel() unable to allocate memory for"
950 " channel");
951 return -1;
952 }
953 return 0;
954}
955
956void
957Channel::PlayNotification(const WebRtc_Word32 id,
958 const WebRtc_UWord32 durationMs)
959{
960 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
961 "Channel::PlayNotification(id=%d, durationMs=%d)",
962 id, durationMs);
963
964 // Not implement yet
965}
966
967void
968Channel::RecordNotification(const WebRtc_Word32 id,
969 const WebRtc_UWord32 durationMs)
970{
971 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
972 "Channel::RecordNotification(id=%d, durationMs=%d)",
973 id, durationMs);
974
975 // Not implement yet
976}
977
978void
979Channel::PlayFileEnded(const WebRtc_Word32 id)
980{
981 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
982 "Channel::PlayFileEnded(id=%d)", id);
983
984 if (id == _inputFilePlayerId)
985 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000986 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000987
988 _inputFilePlaying = false;
989 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
990 VoEId(_instanceId,_channelId),
991 "Channel::PlayFileEnded() => input file player module is"
992 " shutdown");
993 }
994 else if (id == _outputFilePlayerId)
995 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +0000996 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000997
998 _outputFilePlaying = false;
999 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1000 VoEId(_instanceId,_channelId),
1001 "Channel::PlayFileEnded() => output file player module is"
1002 " shutdown");
1003 }
1004}
1005
1006void
1007Channel::RecordFileEnded(const WebRtc_Word32 id)
1008{
1009 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1010 "Channel::RecordFileEnded(id=%d)", id);
1011
1012 assert(id == _outputFileRecorderId);
1013
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001014 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001015
1016 _outputFileRecording = false;
1017 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1018 VoEId(_instanceId,_channelId),
1019 "Channel::RecordFileEnded() => output file recorder module is"
1020 " shutdown");
1021}
1022
1023Channel::Channel(const WebRtc_Word32 channelId,
1024 const WebRtc_UWord32 instanceId) :
1025 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
1026 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001027 _instanceId(instanceId),
xians@google.com22963ab2011-08-03 12:40:23 +00001028 _channelId(channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001029 _audioCodingModule(*AudioCodingModule::Create(
xians@google.com22963ab2011-08-03 12:40:23 +00001030 VoEModuleId(instanceId, channelId))),
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001031#ifndef WEBRTC_EXTERNAL_TRANSPORT
1032 _numSocketThreads(KNumSocketThreads),
1033 _socketTransportModule(*UdpTransport::Create(
1034 VoEModuleId(instanceId, channelId), _numSocketThreads)),
1035#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001036#ifdef WEBRTC_SRTP
1037 _srtpModule(*SrtpModule::CreateSrtpModule(VoEModuleId(instanceId,
1038 channelId))),
1039#endif
1040 _rtpDumpIn(*RtpDump::CreateRtpDump()),
1041 _rtpDumpOut(*RtpDump::CreateRtpDump()),
niklase@google.com470e71d2011-07-07 08:21:25 +00001042 _outputAudioLevel(),
niklase@google.com470e71d2011-07-07 08:21:25 +00001043 _externalTransport(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001044 _inputFilePlayerPtr(NULL),
1045 _outputFilePlayerPtr(NULL),
1046 _outputFileRecorderPtr(NULL),
1047 // Avoid conflict with other channels by adding 1024 - 1026,
1048 // won't use as much as 1024 channels.
1049 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
1050 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
1051 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
1052 _inputFilePlaying(false),
1053 _outputFilePlaying(false),
1054 _outputFileRecording(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001055 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
1056 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
niklase@google.com470e71d2011-07-07 08:21:25 +00001057 _inputExternalMedia(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001058 _outputExternalMedia(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001059 _inputExternalMediaCallbackPtr(NULL),
1060 _outputExternalMediaCallbackPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001061 _encryptionRTPBufferPtr(NULL),
1062 _decryptionRTPBufferPtr(NULL),
1063 _encryptionRTCPBufferPtr(NULL),
1064 _decryptionRTCPBufferPtr(NULL),
1065 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
1066 _sendTelephoneEventPayloadType(106),
1067 _playoutTimeStampRTP(0),
1068 _playoutTimeStampRTCP(0),
1069 _numberOfDiscardedPackets(0),
1070 _engineStatisticsPtr(NULL),
henrika@webrtc.org2919e952012-01-31 08:45:03 +00001071 _outputMixerPtr(NULL),
1072 _transmitMixerPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001073 _moduleProcessThreadPtr(NULL),
1074 _audioDeviceModulePtr(NULL),
1075 _voiceEngineObserverPtr(NULL),
1076 _callbackCritSectPtr(NULL),
1077 _transportPtr(NULL),
1078 _encryptionPtr(NULL),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001079 _rtpAudioProc(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001080 _rxAudioProcessingModulePtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001081 _rxVadObserverPtr(NULL),
1082 _oldVadDecision(-1),
1083 _sendFrameType(0),
niklase@google.com470e71d2011-07-07 08:21:25 +00001084 _rtpObserverPtr(NULL),
1085 _rtcpObserverPtr(NULL),
xians@google.com22963ab2011-08-03 12:40:23 +00001086 _outputIsOnHold(false),
1087 _externalPlayout(false),
roosa@google.com1b60ceb2012-12-12 23:00:29 +00001088 _externalMixing(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001089 _inputIsOnHold(false),
1090 _playing(false),
1091 _sending(false),
1092 _receiving(false),
1093 _mixFileWithMicrophone(false),
1094 _rtpObserver(false),
1095 _rtcpObserver(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001096 _mute(false),
1097 _panLeft(1.0f),
1098 _panRight(1.0f),
1099 _outputGain(1.0f),
xians@google.com22963ab2011-08-03 12:40:23 +00001100 _encrypting(false),
1101 _decrypting(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001102 _playOutbandDtmfEvent(false),
1103 _playInbandDtmfEvent(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001104 _extraPayloadType(0),
1105 _insertExtraRTPPacket(false),
1106 _extraMarkerBit(false),
1107 _lastLocalTimeStamp(0),
roosa@google.com0870f022012-12-12 21:31:41 +00001108 _lastRemoteTimeStamp(0),
niklase@google.com470e71d2011-07-07 08:21:25 +00001109 _lastPayloadType(0),
xians@google.com22963ab2011-08-03 12:40:23 +00001110 _includeAudioLevelIndication(false),
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 _rtpPacketTimedOut(false),
1112 _rtpPacketTimeOutIsEnabled(false),
1113 _rtpTimeOutSeconds(0),
1114 _connectionObserver(false),
1115 _connectionObserverPtr(NULL),
1116 _countAliveDetections(0),
1117 _countDeadDetections(0),
1118 _outputSpeechType(AudioFrame::kNormalSpeech),
1119 _averageDelayMs(0),
1120 _previousSequenceNumber(0),
1121 _previousTimestamp(0),
1122 _recPacketDelayMs(20),
1123 _RxVadDetection(false),
1124 _rxApmIsEnabled(false),
1125 _rxAgcIsEnabled(false),
xians@google.com22963ab2011-08-03 12:40:23 +00001126 _rxNsIsEnabled(false)
niklase@google.com470e71d2011-07-07 08:21:25 +00001127{
1128 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1129 "Channel::Channel() - ctor");
1130 _inbandDtmfQueue.ResetDtmf();
1131 _inbandDtmfGenerator.Init();
1132 _outputAudioLevel.Clear();
1133
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001134 RtpRtcp::Configuration configuration;
1135 configuration.id = VoEModuleId(instanceId, channelId);
1136 configuration.audio = true;
1137 configuration.incoming_data = this;
1138 configuration.incoming_messages = this;
1139 configuration.outgoing_transport = this;
1140 configuration.rtcp_feedback = this;
1141 configuration.audio_messages = this;
1142
1143 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
1144
niklase@google.com470e71d2011-07-07 08:21:25 +00001145 // Create far end AudioProcessing Module
1146 _rxAudioProcessingModulePtr = AudioProcessing::Create(
1147 VoEModuleId(instanceId, channelId));
1148}
1149
1150Channel::~Channel()
1151{
1152 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1153 "Channel::~Channel() - dtor");
1154
1155 if (_outputExternalMedia)
1156 {
1157 DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1158 }
1159 if (_inputExternalMedia)
1160 {
1161 DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1162 }
1163 StopSend();
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001164#ifndef WEBRTC_EXTERNAL_TRANSPORT
1165 StopReceiving();
1166 // De-register packet callback to ensure we're not in a callback when
1167 // deleting channel state, avoids race condition and deadlock.
1168 if (_socketTransportModule.InitializeReceiveSockets(NULL, 0, NULL, NULL, 0)
1169 != 0)
1170 {
1171 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1172 VoEId(_instanceId, _channelId),
1173 "~Channel() failed to de-register receive callback");
1174 }
1175#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001176 StopPlayout();
1177
1178 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001179 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001180 if (_inputFilePlayerPtr)
1181 {
1182 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1183 _inputFilePlayerPtr->StopPlayingFile();
1184 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1185 _inputFilePlayerPtr = NULL;
1186 }
1187 if (_outputFilePlayerPtr)
1188 {
1189 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1190 _outputFilePlayerPtr->StopPlayingFile();
1191 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1192 _outputFilePlayerPtr = NULL;
1193 }
1194 if (_outputFileRecorderPtr)
1195 {
1196 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1197 _outputFileRecorderPtr->StopRecording();
1198 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1199 _outputFileRecorderPtr = NULL;
1200 }
1201 }
1202
1203 // The order to safely shutdown modules in a channel is:
1204 // 1. De-register callbacks in modules
1205 // 2. De-register modules in process thread
1206 // 3. Destroy modules
niklase@google.com470e71d2011-07-07 08:21:25 +00001207 if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1208 {
1209 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1210 VoEId(_instanceId,_channelId),
1211 "~Channel() failed to de-register transport callback"
1212 " (Audio coding module)");
1213 }
1214 if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1215 {
1216 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1217 VoEId(_instanceId,_channelId),
1218 "~Channel() failed to de-register VAD callback"
1219 " (Audio coding module)");
1220 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001221 // De-register modules in process thread
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001222#ifndef WEBRTC_EXTERNAL_TRANSPORT
1223 if (_moduleProcessThreadPtr->DeRegisterModule(&_socketTransportModule)
1224 == -1)
1225 {
1226 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1227 VoEId(_instanceId,_channelId),
1228 "~Channel() failed to deregister socket module");
1229 }
1230#endif
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001231 if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00001232 {
1233 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1234 VoEId(_instanceId,_channelId),
1235 "~Channel() failed to deregister RTP/RTCP module");
1236 }
1237
1238 // Destroy modules
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001239#ifndef WEBRTC_EXTERNAL_TRANSPORT
1240 UdpTransport::Destroy(
1241 &_socketTransportModule);
1242#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001243 AudioCodingModule::Destroy(&_audioCodingModule);
1244#ifdef WEBRTC_SRTP
1245 SrtpModule::DestroySrtpModule(&_srtpModule);
1246#endif
1247 if (_rxAudioProcessingModulePtr != NULL)
1248 {
1249 AudioProcessing::Destroy(_rxAudioProcessingModulePtr); // far end APM
1250 _rxAudioProcessingModulePtr = NULL;
1251 }
1252
1253 // End of modules shutdown
1254
1255 // Delete other objects
1256 RtpDump::DestroyRtpDump(&_rtpDumpIn);
1257 RtpDump::DestroyRtpDump(&_rtpDumpOut);
1258 delete [] _encryptionRTPBufferPtr;
1259 delete [] _decryptionRTPBufferPtr;
1260 delete [] _encryptionRTCPBufferPtr;
1261 delete [] _decryptionRTCPBufferPtr;
1262 delete &_callbackCritSect;
niklase@google.com470e71d2011-07-07 08:21:25 +00001263 delete &_fileCritSect;
1264}
1265
1266WebRtc_Word32
1267Channel::Init()
1268{
1269 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1270 "Channel::Init()");
1271
1272 // --- Initial sanity
1273
1274 if ((_engineStatisticsPtr == NULL) ||
1275 (_moduleProcessThreadPtr == NULL))
1276 {
1277 WEBRTC_TRACE(kTraceError, kTraceVoice,
1278 VoEId(_instanceId,_channelId),
1279 "Channel::Init() must call SetEngineInformation() first");
1280 return -1;
1281 }
1282
1283 // --- Add modules to process thread (for periodic schedulation)
1284
1285 const bool processThreadFail =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001286 ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001287#ifndef WEBRTC_EXTERNAL_TRANSPORT
1288 (_moduleProcessThreadPtr->RegisterModule(
1289 &_socketTransportModule) != 0));
1290#else
niklase@google.com470e71d2011-07-07 08:21:25 +00001291 false);
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001292#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001293 if (processThreadFail)
1294 {
1295 _engineStatisticsPtr->SetLastError(
1296 VE_CANNOT_INIT_CHANNEL, kTraceError,
1297 "Channel::Init() modules not registered");
1298 return -1;
1299 }
pwestin@webrtc.orgc450a192012-01-04 15:00:12 +00001300 // --- ACM initialization
niklase@google.com470e71d2011-07-07 08:21:25 +00001301
1302 if ((_audioCodingModule.InitializeReceiver() == -1) ||
1303#ifdef WEBRTC_CODEC_AVT
1304 // out-of-band Dtmf tones are played out by default
1305 (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1306#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001307 (_audioCodingModule.InitializeSender() == -1))
1308 {
1309 _engineStatisticsPtr->SetLastError(
1310 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1311 "Channel::Init() unable to initialize the ACM - 1");
1312 return -1;
1313 }
1314
1315 // --- RTP/RTCP module initialization
1316
1317 // Ensure that RTCP is enabled by default for the created channel.
1318 // Note that, the module will keep generating RTCP until it is explicitly
1319 // disabled by the user.
1320 // After StopListen (when no sockets exists), RTCP packets will no longer
1321 // be transmitted since the Transport object will then be invalid.
1322
1323 const bool rtpRtcpFail =
turaj@webrtc.orgb7edd062013-03-12 22:27:27 +00001324 ((_rtpRtcpModule->SetTelephoneEventForwardToDecoder(true) == -1) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001325 // RTCP is enabled by default
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001326 (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1));
niklase@google.com470e71d2011-07-07 08:21:25 +00001327 if (rtpRtcpFail)
1328 {
1329 _engineStatisticsPtr->SetLastError(
1330 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1331 "Channel::Init() RTP/RTCP module not initialized");
1332 return -1;
1333 }
1334
1335 // --- Register all permanent callbacks
niklase@google.com470e71d2011-07-07 08:21:25 +00001336 const bool fail =
niklase@google.com470e71d2011-07-07 08:21:25 +00001337 (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1338 (_audioCodingModule.RegisterVADCallback(this) == -1);
1339
1340 if (fail)
1341 {
1342 _engineStatisticsPtr->SetLastError(
1343 VE_CANNOT_INIT_CHANNEL, kTraceError,
1344 "Channel::Init() callbacks not registered");
1345 return -1;
1346 }
1347
1348 // --- Register all supported codecs to the receiving side of the
1349 // RTP/RTCP module
1350
1351 CodecInst codec;
1352 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1353
1354 for (int idx = 0; idx < nSupportedCodecs; idx++)
1355 {
1356 // Open up the RTP/RTCP receiver for all supported codecs
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00001357 if ((_audioCodingModule.Codec(idx, &codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001358 (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001359 {
1360 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1361 VoEId(_instanceId,_channelId),
1362 "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1363 "to RTP/RTCP receiver",
1364 codec.plname, codec.pltype, codec.plfreq,
1365 codec.channels, codec.rate);
1366 }
1367 else
1368 {
1369 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1370 VoEId(_instanceId,_channelId),
1371 "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1372 "the RTP/RTCP receiver",
1373 codec.plname, codec.pltype, codec.plfreq,
1374 codec.channels, codec.rate);
1375 }
1376
1377 // Ensure that PCMU is used as default codec on the sending side
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +00001378 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001379 {
1380 SetSendCodec(codec);
1381 }
1382
1383 // Register default PT for outband 'telephone-event'
1384 if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1385 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001386 if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
niklase@google.com470e71d2011-07-07 08:21:25 +00001387 (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1388 {
1389 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1390 VoEId(_instanceId,_channelId),
1391 "Channel::Init() failed to register outband "
1392 "'telephone-event' (%d/%d) correctly",
1393 codec.pltype, codec.plfreq);
1394 }
1395 }
1396
1397 if (!STR_CASE_CMP(codec.plname, "CN"))
1398 {
1399 if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1400 (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001401 (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00001402 {
1403 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1404 VoEId(_instanceId,_channelId),
1405 "Channel::Init() failed to register CN (%d/%d) "
1406 "correctly - 1",
1407 codec.pltype, codec.plfreq);
1408 }
1409 }
1410#ifdef WEBRTC_CODEC_RED
1411 // Register RED to the receiving side of the ACM.
1412 // We will not receive an OnInitializeDecoder() callback for RED.
1413 if (!STR_CASE_CMP(codec.plname, "RED"))
1414 {
1415 if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1416 {
1417 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1418 VoEId(_instanceId,_channelId),
1419 "Channel::Init() failed to register RED (%d/%d) "
1420 "correctly",
1421 codec.pltype, codec.plfreq);
1422 }
1423 }
1424#endif
1425 }
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001426#ifndef WEBRTC_EXTERNAL_TRANSPORT
1427 // Ensure that the WebRtcSocketTransport implementation is used as
1428 // Transport on the sending side
1429 {
1430 // A lock is needed here since users can call
1431 // RegisterExternalTransport() at the same time.
1432 CriticalSectionScoped cs(&_callbackCritSect);
1433 _transportPtr = &_socketTransportModule;
1434 }
1435#endif
1436
niklase@google.com470e71d2011-07-07 08:21:25 +00001437 // Initialize the far end AP module
1438 // Using 8 kHz as initial Fs, the same as in transmission. Might be
1439 // changed at the first receiving audio.
1440 if (_rxAudioProcessingModulePtr == NULL)
1441 {
1442 _engineStatisticsPtr->SetLastError(
1443 VE_NO_MEMORY, kTraceCritical,
1444 "Channel::Init() failed to create the far-end AudioProcessing"
1445 " module");
1446 return -1;
1447 }
1448
niklase@google.com470e71d2011-07-07 08:21:25 +00001449 if (_rxAudioProcessingModulePtr->set_sample_rate_hz(8000))
1450 {
1451 _engineStatisticsPtr->SetLastError(
1452 VE_APM_ERROR, kTraceWarning,
1453 "Channel::Init() failed to set the sample rate to 8K for"
1454 " far-end AP module");
1455 }
1456
1457 if (_rxAudioProcessingModulePtr->set_num_channels(1, 1) != 0)
1458 {
1459 _engineStatisticsPtr->SetLastError(
1460 VE_SOUNDCARD_ERROR, kTraceWarning,
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00001461 "Init() failed to set channels for the primary audio stream");
niklase@google.com470e71d2011-07-07 08:21:25 +00001462 }
1463
1464 if (_rxAudioProcessingModulePtr->high_pass_filter()->Enable(
1465 WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1466 {
1467 _engineStatisticsPtr->SetLastError(
1468 VE_APM_ERROR, kTraceWarning,
1469 "Channel::Init() failed to set the high-pass filter for"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001470 " far-end AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001471 }
1472
1473 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(
1474 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1475 {
1476 _engineStatisticsPtr->SetLastError(
1477 VE_APM_ERROR, kTraceWarning,
1478 "Init() failed to set noise reduction level for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001479 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001480 }
1481 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(
1482 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1483 {
1484 _engineStatisticsPtr->SetLastError(
1485 VE_APM_ERROR, kTraceWarning,
1486 "Init() failed to set noise reduction state for far-end"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00001487 " AP module");
niklase@google.com470e71d2011-07-07 08:21:25 +00001488 }
1489
1490 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(
1491 (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1492 {
1493 _engineStatisticsPtr->SetLastError(
1494 VE_APM_ERROR, kTraceWarning,
1495 "Init() failed to set AGC mode for far-end AP module");
1496 }
1497 if (_rxAudioProcessingModulePtr->gain_control()->Enable(
1498 WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1499 {
1500 _engineStatisticsPtr->SetLastError(
1501 VE_APM_ERROR, kTraceWarning,
1502 "Init() failed to set AGC state for far-end AP module");
1503 }
1504
1505 return 0;
1506}
1507
1508WebRtc_Word32
1509Channel::SetEngineInformation(Statistics& engineStatistics,
1510 OutputMixer& outputMixer,
1511 voe::TransmitMixer& transmitMixer,
1512 ProcessThread& moduleProcessThread,
1513 AudioDeviceModule& audioDeviceModule,
1514 VoiceEngineObserver* voiceEngineObserver,
1515 CriticalSectionWrapper* callbackCritSect)
1516{
1517 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1518 "Channel::SetEngineInformation()");
1519 _engineStatisticsPtr = &engineStatistics;
1520 _outputMixerPtr = &outputMixer;
1521 _transmitMixerPtr = &transmitMixer,
1522 _moduleProcessThreadPtr = &moduleProcessThread;
1523 _audioDeviceModulePtr = &audioDeviceModule;
1524 _voiceEngineObserverPtr = voiceEngineObserver;
1525 _callbackCritSectPtr = callbackCritSect;
1526 return 0;
1527}
1528
1529WebRtc_Word32
1530Channel::UpdateLocalTimeStamp()
1531{
1532
andrew@webrtc.org63a50982012-05-02 23:56:37 +00001533 _timeStamp += _audioFrame.samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +00001534 return 0;
1535}
1536
1537WebRtc_Word32
1538Channel::StartPlayout()
1539{
1540 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1541 "Channel::StartPlayout()");
1542 if (_playing)
1543 {
1544 return 0;
1545 }
roosa@google.com1b60ceb2012-12-12 23:00:29 +00001546
1547 if (!_externalMixing) {
1548 // Add participant as candidates for mixing.
1549 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1550 {
1551 _engineStatisticsPtr->SetLastError(
1552 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1553 "StartPlayout() failed to add participant to mixer");
1554 return -1;
1555 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001556 }
1557
1558 _playing = true;
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001559
1560 if (RegisterFilePlayingToMixer() != 0)
1561 return -1;
1562
niklase@google.com470e71d2011-07-07 08:21:25 +00001563 return 0;
1564}
1565
1566WebRtc_Word32
1567Channel::StopPlayout()
1568{
1569 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1570 "Channel::StopPlayout()");
1571 if (!_playing)
1572 {
1573 return 0;
1574 }
roosa@google.com1b60ceb2012-12-12 23:00:29 +00001575
1576 if (!_externalMixing) {
1577 // Remove participant as candidates for mixing
1578 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1579 {
1580 _engineStatisticsPtr->SetLastError(
1581 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1582 "StopPlayout() failed to remove participant from mixer");
1583 return -1;
1584 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001585 }
1586
1587 _playing = false;
1588 _outputAudioLevel.Clear();
1589
1590 return 0;
1591}
1592
1593WebRtc_Word32
1594Channel::StartSend()
1595{
1596 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1597 "Channel::StartSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001598 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001599 // A lock is needed because |_sending| can be accessed or modified by
1600 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001601 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001602
1603 if (_sending)
1604 {
1605 return 0;
1606 }
1607 _sending = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001608 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001609
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001610 if (_rtpRtcpModule->SetSendingStatus(true) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001611 {
1612 _engineStatisticsPtr->SetLastError(
1613 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1614 "StartSend() RTP/RTCP failed to start sending");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001615 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001616 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001617 return -1;
1618 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001619
niklase@google.com470e71d2011-07-07 08:21:25 +00001620 return 0;
1621}
1622
1623WebRtc_Word32
1624Channel::StopSend()
1625{
1626 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1627 "Channel::StopSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001628 {
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001629 // A lock is needed because |_sending| can be accessed or modified by
1630 // another thread at the same time.
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00001631 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001632
1633 if (!_sending)
1634 {
1635 return 0;
1636 }
1637 _sending = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00001638 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001639
niklase@google.com470e71d2011-07-07 08:21:25 +00001640 // Reset sending SSRC and sequence number and triggers direct transmission
1641 // of RTCP BYE
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00001642 if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
1643 _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00001644 {
1645 _engineStatisticsPtr->SetLastError(
1646 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1647 "StartSend() RTP/RTCP failed to stop sending");
1648 }
1649
niklase@google.com470e71d2011-07-07 08:21:25 +00001650 return 0;
1651}
1652
1653WebRtc_Word32
1654Channel::StartReceiving()
1655{
1656 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1657 "Channel::StartReceiving()");
1658 if (_receiving)
1659 {
1660 return 0;
1661 }
1662 // If external transport is used, we will only initialize/set the variables
1663 // after this section, since we are not using the WebRtc transport but
1664 // still need to keep track of e.g. if we are receiving.
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001665#ifndef WEBRTC_EXTERNAL_TRANSPORT
1666 if (!_externalTransport)
1667 {
1668 if (!_socketTransportModule.ReceiveSocketsInitialized())
1669 {
1670 _engineStatisticsPtr->SetLastError(
1671 VE_SOCKETS_NOT_INITED, kTraceError,
1672 "StartReceive() must set local receiver first");
1673 return -1;
1674 }
1675 if (_socketTransportModule.StartReceiving(KNumberOfSocketBuffers) != 0)
1676 {
1677 _engineStatisticsPtr->SetLastError(
1678 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1679 "StartReceiving() failed to start receiving");
1680 return -1;
1681 }
1682 }
1683#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00001684 _receiving = true;
1685 _numberOfDiscardedPackets = 0;
1686 return 0;
1687}
1688
1689WebRtc_Word32
1690Channel::StopReceiving()
1691{
1692 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1693 "Channel::StopReceiving()");
1694 if (!_receiving)
1695 {
1696 return 0;
1697 }
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001698
1699#ifndef WEBRTC_EXTERNAL_TRANSPORT
1700 if (!_externalTransport &&
1701 _socketTransportModule.ReceiveSocketsInitialized())
1702 {
1703 if (_socketTransportModule.StopReceiving() != 0)
1704 {
1705 _engineStatisticsPtr->SetLastError(
1706 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
1707 "StopReceiving() failed to stop receiving.");
1708 return -1;
1709 }
1710 }
1711#endif
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001712 // Recover DTMF detection status.
turaj@webrtc.orgb7edd062013-03-12 22:27:27 +00001713 WebRtc_Word32 ret = _rtpRtcpModule->SetTelephoneEventForwardToDecoder(true);
henrika@webrtc.orgaf71f0e2011-12-05 07:02:22 +00001714 if (ret != 0) {
1715 _engineStatisticsPtr->SetLastError(
1716 VE_INVALID_OPERATION, kTraceWarning,
1717 "StopReceiving() failed to restore telephone-event status.");
1718 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001719 RegisterReceiveCodecsToRTPModule();
1720 _receiving = false;
1721 return 0;
1722}
1723
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001724#ifndef WEBRTC_EXTERNAL_TRANSPORT
1725WebRtc_Word32
1726Channel::SetLocalReceiver(const WebRtc_UWord16 rtpPort,
1727 const WebRtc_UWord16 rtcpPort,
1728 const char ipAddr[64],
1729 const char multicastIpAddr[64])
1730{
1731 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1732 "Channel::SetLocalReceiver()");
1733
1734 if (_externalTransport)
1735 {
1736 _engineStatisticsPtr->SetLastError(
1737 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1738 "SetLocalReceiver() conflict with external transport");
1739 return -1;
1740 }
1741
1742 if (_sending)
1743 {
1744 _engineStatisticsPtr->SetLastError(
1745 VE_ALREADY_SENDING, kTraceError,
1746 "SetLocalReceiver() already sending");
1747 return -1;
1748 }
1749 if (_receiving)
1750 {
1751 _engineStatisticsPtr->SetLastError(
1752 VE_ALREADY_LISTENING, kTraceError,
1753 "SetLocalReceiver() already receiving");
1754 return -1;
1755 }
1756
1757 if (_socketTransportModule.InitializeReceiveSockets(this,
1758 rtpPort,
1759 ipAddr,
1760 multicastIpAddr,
1761 rtcpPort) != 0)
1762 {
1763 UdpTransport::ErrorCode lastSockError(
1764 _socketTransportModule.LastError());
1765 switch (lastSockError)
1766 {
1767 case UdpTransport::kIpAddressInvalid:
1768 _engineStatisticsPtr->SetLastError(
1769 VE_INVALID_IP_ADDRESS, kTraceError,
1770 "SetLocalReceiver() invalid IP address");
1771 break;
1772 case UdpTransport::kSocketInvalid:
1773 _engineStatisticsPtr->SetLastError(
1774 VE_SOCKET_ERROR, kTraceError,
1775 "SetLocalReceiver() invalid socket");
1776 break;
1777 case UdpTransport::kPortInvalid:
1778 _engineStatisticsPtr->SetLastError(
1779 VE_INVALID_PORT_NMBR, kTraceError,
1780 "SetLocalReceiver() invalid port");
1781 break;
1782 case UdpTransport::kFailedToBindPort:
1783 _engineStatisticsPtr->SetLastError(
1784 VE_BINDING_SOCKET_TO_LOCAL_ADDRESS_FAILED, kTraceError,
1785 "SetLocalReceiver() binding failed");
1786 break;
1787 default:
1788 _engineStatisticsPtr->SetLastError(
1789 VE_SOCKET_ERROR, kTraceError,
1790 "SetLocalReceiver() undefined socket error");
1791 break;
1792 }
1793 return -1;
1794 }
1795 return 0;
1796}
1797#endif
1798
1799#ifndef WEBRTC_EXTERNAL_TRANSPORT
1800WebRtc_Word32
1801Channel::GetLocalReceiver(int& port, int& RTCPport, char ipAddr[64])
1802{
1803 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1804 "Channel::GetLocalReceiver()");
1805
1806 if (_externalTransport)
1807 {
1808 _engineStatisticsPtr->SetLastError(
1809 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1810 "SetLocalReceiver() conflict with external transport");
1811 return -1;
1812 }
1813
1814 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
1815 WebRtc_UWord16 rtpPort(0);
1816 WebRtc_UWord16 rtcpPort(0);
1817 char multicastIpAddr[UdpTransport::kIpAddressVersion6Length] = {0};
1818
1819 // Acquire socket information from the socket module
1820 if (_socketTransportModule.ReceiveSocketInformation(ipAddrTmp,
1821 rtpPort,
1822 rtcpPort,
1823 multicastIpAddr) != 0)
1824 {
1825 _engineStatisticsPtr->SetLastError(
1826 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1827 "GetLocalReceiver() unable to retrieve socket information");
1828 return -1;
1829 }
1830
1831 // Deliver valid results to the user
1832 port = static_cast<int> (rtpPort);
1833 RTCPport = static_cast<int> (rtcpPort);
1834 if (ipAddr != NULL)
1835 {
1836 strcpy(ipAddr, ipAddrTmp);
1837 }
1838 return 0;
1839}
1840#endif
1841
1842#ifndef WEBRTC_EXTERNAL_TRANSPORT
1843WebRtc_Word32
1844Channel::SetSendDestination(const WebRtc_UWord16 rtpPort,
1845 const char ipAddr[64],
1846 const int sourcePort,
1847 const WebRtc_UWord16 rtcpPort)
1848{
1849 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1850 "Channel::SetSendDestination()");
1851
1852 if (_externalTransport)
1853 {
1854 _engineStatisticsPtr->SetLastError(
1855 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
1856 "SetSendDestination() conflict with external transport");
1857 return -1;
1858 }
1859
1860 // Initialize ports and IP address for the remote (destination) side.
1861 // By default, the sockets used for receiving are used for transmission as
1862 // well, hence the source ports for outgoing packets are the same as the
1863 // receiving ports specified in SetLocalReceiver.
1864 // If an extra send socket has been created, it will be utilized until a
1865 // new source port is specified or until the channel has been deleted and
1866 // recreated. If no socket exists, sockets will be created when the first
1867 // RTP and RTCP packets shall be transmitted (see e.g.
1868 // UdpTransportImpl::SendPacket()).
1869 //
1870 // NOTE: this function does not require that sockets exists; all it does is
1871 // to build send structures to be used with the sockets when they exist.
1872 // It is therefore possible to call this method before SetLocalReceiver.
1873 // However, sockets must exist if a multi-cast address is given as input.
1874
1875 // Build send structures and enable QoS (if enabled and supported)
1876 if (_socketTransportModule.InitializeSendSockets(
1877 ipAddr, rtpPort, rtcpPort) != UdpTransport::kNoSocketError)
1878 {
1879 UdpTransport::ErrorCode lastSockError(
1880 _socketTransportModule.LastError());
1881 switch (lastSockError)
1882 {
1883 case UdpTransport::kIpAddressInvalid:
1884 _engineStatisticsPtr->SetLastError(
1885 VE_INVALID_IP_ADDRESS, kTraceError,
1886 "SetSendDestination() invalid IP address 1");
1887 break;
1888 case UdpTransport::kSocketInvalid:
1889 _engineStatisticsPtr->SetLastError(
1890 VE_SOCKET_ERROR, kTraceError,
1891 "SetSendDestination() invalid socket 1");
1892 break;
1893 case UdpTransport::kQosError:
1894 _engineStatisticsPtr->SetLastError(
1895 VE_GQOS_ERROR, kTraceError,
1896 "SetSendDestination() failed to set QoS");
1897 break;
1898 case UdpTransport::kMulticastAddressInvalid:
1899 _engineStatisticsPtr->SetLastError(
1900 VE_INVALID_MULTICAST_ADDRESS, kTraceError,
1901 "SetSendDestination() invalid multicast address");
1902 break;
1903 default:
1904 _engineStatisticsPtr->SetLastError(
1905 VE_SOCKET_ERROR, kTraceError,
1906 "SetSendDestination() undefined socket error 1");
1907 break;
1908 }
1909 return -1;
1910 }
1911
1912 // Check if the user has specified a non-default source port different from
1913 // the local receive port.
1914 // If so, an extra local socket will be created unless the source port is
1915 // not unique.
1916 if (sourcePort != kVoEDefault)
1917 {
1918 WebRtc_UWord16 receiverRtpPort(0);
1919 WebRtc_UWord16 rtcpNA(0);
1920 if (_socketTransportModule.ReceiveSocketInformation(NULL,
1921 receiverRtpPort,
1922 rtcpNA,
1923 NULL) != 0)
1924 {
1925 _engineStatisticsPtr->SetLastError(
1926 VE_CANNOT_GET_SOCKET_INFO, kTraceError,
1927 "SetSendDestination() failed to retrieve socket information");
1928 return -1;
1929 }
1930
1931 WebRtc_UWord16 sourcePortUW16 =
1932 static_cast<WebRtc_UWord16> (sourcePort);
1933
1934 // An extra socket will only be created if the specified source port
1935 // differs from the local receive port.
1936 if (sourcePortUW16 != receiverRtpPort)
1937 {
1938 // Initialize extra local socket to get a different source port
1939 // than the local
1940 // receiver port. Always use default source for RTCP.
1941 // Note that, this calls UdpTransport::CloseSendSockets().
1942 if (_socketTransportModule.InitializeSourcePorts(
1943 sourcePortUW16,
1944 sourcePortUW16+1) != 0)
1945 {
1946 UdpTransport::ErrorCode lastSockError(
1947 _socketTransportModule.LastError());
1948 switch (lastSockError)
1949 {
1950 case UdpTransport::kIpAddressInvalid:
1951 _engineStatisticsPtr->SetLastError(
1952 VE_INVALID_IP_ADDRESS, kTraceError,
1953 "SetSendDestination() invalid IP address 2");
1954 break;
1955 case UdpTransport::kSocketInvalid:
1956 _engineStatisticsPtr->SetLastError(
1957 VE_SOCKET_ERROR, kTraceError,
1958 "SetSendDestination() invalid socket 2");
1959 break;
1960 default:
1961 _engineStatisticsPtr->SetLastError(
1962 VE_SOCKET_ERROR, kTraceError,
1963 "SetSendDestination() undefined socket error 2");
1964 break;
1965 }
1966 return -1;
1967 }
1968 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1969 VoEId(_instanceId,_channelId),
1970 "SetSendDestination() extra local socket is created"
1971 " to facilitate unique source port");
1972 }
1973 else
1974 {
1975 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1976 VoEId(_instanceId,_channelId),
1977 "SetSendDestination() sourcePort equals the local"
1978 " receive port => no extra socket is created");
1979 }
1980 }
1981
1982 return 0;
1983}
1984#endif
1985
1986#ifndef WEBRTC_EXTERNAL_TRANSPORT
1987WebRtc_Word32
1988Channel::GetSendDestination(int& port,
1989 char ipAddr[64],
1990 int& sourcePort,
1991 int& RTCPport)
1992{
1993 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1994 "Channel::GetSendDestination()");
1995
1996 if (_externalTransport)
1997 {
1998 _engineStatisticsPtr->SetLastError(
1999 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
2000 "GetSendDestination() conflict with external transport");
2001 return -1;
2002 }
2003
2004 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2005 WebRtc_UWord16 rtpPort(0);
2006 WebRtc_UWord16 rtcpPort(0);
2007 WebRtc_UWord16 rtpSourcePort(0);
2008 WebRtc_UWord16 rtcpSourcePort(0);
2009
2010 // Acquire sending socket information from the socket module
2011 _socketTransportModule.SendSocketInformation(ipAddrTmp, rtpPort, rtcpPort);
2012 _socketTransportModule.SourcePorts(rtpSourcePort, rtcpSourcePort);
2013
2014 // Deliver valid results to the user
2015 port = static_cast<int> (rtpPort);
2016 RTCPport = static_cast<int> (rtcpPort);
2017 sourcePort = static_cast<int> (rtpSourcePort);
2018 if (ipAddr != NULL)
2019 {
2020 strcpy(ipAddr, ipAddrTmp);
2021 }
2022
2023 return 0;
2024}
2025#endif
2026
2027
niklase@google.com470e71d2011-07-07 08:21:25 +00002028WebRtc_Word32
2029Channel::SetNetEQPlayoutMode(NetEqModes mode)
2030{
2031 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2032 "Channel::SetNetEQPlayoutMode()");
2033 AudioPlayoutMode playoutMode(voice);
2034 switch (mode)
2035 {
2036 case kNetEqDefault:
2037 playoutMode = voice;
2038 break;
2039 case kNetEqStreaming:
2040 playoutMode = streaming;
2041 break;
2042 case kNetEqFax:
2043 playoutMode = fax;
2044 break;
roosa@google.comb7186192012-12-12 21:59:14 +00002045 case kNetEqOff:
2046 playoutMode = off;
2047 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00002048 }
2049 if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
2050 {
2051 _engineStatisticsPtr->SetLastError(
2052 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2053 "SetNetEQPlayoutMode() failed to set playout mode");
2054 return -1;
2055 }
2056 return 0;
2057}
2058
2059WebRtc_Word32
2060Channel::GetNetEQPlayoutMode(NetEqModes& mode)
2061{
2062 const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
2063 switch (playoutMode)
2064 {
2065 case voice:
2066 mode = kNetEqDefault;
2067 break;
2068 case streaming:
2069 mode = kNetEqStreaming;
2070 break;
2071 case fax:
2072 mode = kNetEqFax;
2073 break;
roosa@google.comb7186192012-12-12 21:59:14 +00002074 case off:
2075 mode = kNetEqOff;
niklase@google.com470e71d2011-07-07 08:21:25 +00002076 }
2077 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2078 VoEId(_instanceId,_channelId),
2079 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
2080 return 0;
2081}
2082
2083WebRtc_Word32
niklase@google.com470e71d2011-07-07 08:21:25 +00002084Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
2085{
2086 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2087 "Channel::SetOnHoldStatus()");
2088 if (mode == kHoldSendAndPlay)
2089 {
2090 _outputIsOnHold = enable;
2091 _inputIsOnHold = enable;
2092 }
2093 else if (mode == kHoldPlayOnly)
2094 {
2095 _outputIsOnHold = enable;
2096 }
2097 if (mode == kHoldSendOnly)
2098 {
2099 _inputIsOnHold = enable;
2100 }
2101 return 0;
2102}
2103
2104WebRtc_Word32
2105Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
2106{
2107 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2108 "Channel::GetOnHoldStatus()");
2109 enabled = (_outputIsOnHold || _inputIsOnHold);
2110 if (_outputIsOnHold && _inputIsOnHold)
2111 {
2112 mode = kHoldSendAndPlay;
2113 }
2114 else if (_outputIsOnHold && !_inputIsOnHold)
2115 {
2116 mode = kHoldPlayOnly;
2117 }
2118 else if (!_outputIsOnHold && _inputIsOnHold)
2119 {
2120 mode = kHoldSendOnly;
2121 }
2122 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2123 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
2124 enabled, mode);
2125 return 0;
2126}
2127
2128WebRtc_Word32
2129Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
2130{
2131 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2132 "Channel::RegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002133 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002134
2135 if (_voiceEngineObserverPtr)
2136 {
2137 _engineStatisticsPtr->SetLastError(
2138 VE_INVALID_OPERATION, kTraceError,
2139 "RegisterVoiceEngineObserver() observer already enabled");
2140 return -1;
2141 }
2142 _voiceEngineObserverPtr = &observer;
2143 return 0;
2144}
2145
2146WebRtc_Word32
2147Channel::DeRegisterVoiceEngineObserver()
2148{
2149 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2150 "Channel::DeRegisterVoiceEngineObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002151 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002152
2153 if (!_voiceEngineObserverPtr)
2154 {
2155 _engineStatisticsPtr->SetLastError(
2156 VE_INVALID_OPERATION, kTraceWarning,
2157 "DeRegisterVoiceEngineObserver() observer already disabled");
2158 return 0;
2159 }
2160 _voiceEngineObserverPtr = NULL;
2161 return 0;
2162}
2163
2164WebRtc_Word32
niklase@google.com470e71d2011-07-07 08:21:25 +00002165Channel::GetSendCodec(CodecInst& codec)
2166{
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002167 return (_audioCodingModule.SendCodec(&codec));
niklase@google.com470e71d2011-07-07 08:21:25 +00002168}
2169
2170WebRtc_Word32
2171Channel::GetRecCodec(CodecInst& codec)
2172{
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002173 return (_audioCodingModule.ReceiveCodec(&codec));
niklase@google.com470e71d2011-07-07 08:21:25 +00002174}
2175
2176WebRtc_Word32
2177Channel::SetSendCodec(const CodecInst& codec)
2178{
2179 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2180 "Channel::SetSendCodec()");
2181
2182 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2183 {
2184 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2185 "SetSendCodec() failed to register codec to ACM");
2186 return -1;
2187 }
2188
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002189 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002190 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002191 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2192 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002193 {
2194 WEBRTC_TRACE(
2195 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2196 "SetSendCodec() failed to register codec to"
2197 " RTP/RTCP module");
2198 return -1;
2199 }
2200 }
2201
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002202 if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002203 {
2204 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2205 "SetSendCodec() failed to set audio packet size");
2206 return -1;
2207 }
2208
2209 return 0;
2210}
2211
2212WebRtc_Word32
2213Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
2214{
2215 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2216 "Channel::SetVADStatus(mode=%d)", mode);
2217 // To disable VAD, DTX must be disabled too
2218 disableDTX = ((enableVAD == false) ? true : disableDTX);
2219 if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
2220 {
2221 _engineStatisticsPtr->SetLastError(
2222 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2223 "SetVADStatus() failed to set VAD");
2224 return -1;
2225 }
2226 return 0;
2227}
2228
2229WebRtc_Word32
2230Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
2231{
2232 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2233 "Channel::GetVADStatus");
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002234 if (_audioCodingModule.VAD(&disabledDTX, &enabledVAD, &mode) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002235 {
2236 _engineStatisticsPtr->SetLastError(
2237 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2238 "GetVADStatus() failed to get VAD status");
2239 return -1;
2240 }
2241 disabledDTX = !disabledDTX;
2242 return 0;
2243}
2244
2245WebRtc_Word32
2246Channel::SetRecPayloadType(const CodecInst& codec)
2247{
2248 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2249 "Channel::SetRecPayloadType()");
2250
2251 if (_playing)
2252 {
2253 _engineStatisticsPtr->SetLastError(
2254 VE_ALREADY_PLAYING, kTraceError,
2255 "SetRecPayloadType() unable to set PT while playing");
2256 return -1;
2257 }
2258 if (_receiving)
2259 {
2260 _engineStatisticsPtr->SetLastError(
2261 VE_ALREADY_LISTENING, kTraceError,
2262 "SetRecPayloadType() unable to set PT while listening");
2263 return -1;
2264 }
2265
2266 if (codec.pltype == -1)
2267 {
2268 // De-register the selected codec (RTP/RTCP module and ACM)
2269
2270 WebRtc_Word8 pltype(-1);
2271 CodecInst rxCodec = codec;
2272
2273 // Get payload type for the given codec
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002274 _rtpRtcpModule->ReceivePayloadType(rxCodec, &pltype);
niklase@google.com470e71d2011-07-07 08:21:25 +00002275 rxCodec.pltype = pltype;
2276
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002277 if (_rtpRtcpModule->DeRegisterReceivePayload(pltype) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002278 {
2279 _engineStatisticsPtr->SetLastError(
2280 VE_RTP_RTCP_MODULE_ERROR,
2281 kTraceError,
2282 "SetRecPayloadType() RTP/RTCP-module deregistration "
2283 "failed");
2284 return -1;
2285 }
2286 if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
2287 {
2288 _engineStatisticsPtr->SetLastError(
2289 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2290 "SetRecPayloadType() ACM deregistration failed - 1");
2291 return -1;
2292 }
2293 return 0;
2294 }
2295
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002296 if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002297 {
2298 // First attempt to register failed => de-register and try again
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002299 _rtpRtcpModule->DeRegisterReceivePayload(codec.pltype);
2300 if (_rtpRtcpModule->RegisterReceivePayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002301 {
2302 _engineStatisticsPtr->SetLastError(
2303 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2304 "SetRecPayloadType() RTP/RTCP-module registration failed");
2305 return -1;
2306 }
2307 }
2308 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2309 {
2310 _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
2311 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
2312 {
2313 _engineStatisticsPtr->SetLastError(
2314 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2315 "SetRecPayloadType() ACM registration failed - 1");
2316 return -1;
2317 }
2318 }
2319 return 0;
2320}
2321
2322WebRtc_Word32
2323Channel::GetRecPayloadType(CodecInst& codec)
2324{
2325 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2326 "Channel::GetRecPayloadType()");
2327 WebRtc_Word8 payloadType(-1);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002328 if (_rtpRtcpModule->ReceivePayloadType(codec, &payloadType) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002329 {
2330 _engineStatisticsPtr->SetLastError(
henrika@webrtc.org37198002012-06-18 11:00:12 +00002331 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
niklase@google.com470e71d2011-07-07 08:21:25 +00002332 "GetRecPayloadType() failed to retrieve RX payload type");
2333 return -1;
2334 }
2335 codec.pltype = payloadType;
2336 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2337 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
2338 return 0;
2339}
2340
2341WebRtc_Word32
2342Channel::SetAMREncFormat(AmrMode mode)
2343{
2344 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2345 "Channel::SetAMREncFormat()");
2346
2347 // ACM doesn't support AMR
2348 return -1;
2349}
2350
2351WebRtc_Word32
2352Channel::SetAMRDecFormat(AmrMode mode)
2353{
2354 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2355 "Channel::SetAMRDecFormat()");
2356
2357 // ACM doesn't support AMR
2358 return -1;
2359}
2360
2361WebRtc_Word32
2362Channel::SetAMRWbEncFormat(AmrMode mode)
2363{
2364 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2365 "Channel::SetAMRWbEncFormat()");
2366
2367 // ACM doesn't support AMR
2368 return -1;
2369
2370}
2371
2372WebRtc_Word32
2373Channel::SetAMRWbDecFormat(AmrMode mode)
2374{
2375 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2376 "Channel::SetAMRWbDecFormat()");
2377
2378 // ACM doesn't support AMR
2379 return -1;
2380}
2381
2382WebRtc_Word32
2383Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
2384{
2385 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2386 "Channel::SetSendCNPayloadType()");
2387
2388 CodecInst codec;
2389 WebRtc_Word32 samplingFreqHz(-1);
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +00002390 const int kMono = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002391 if (frequency == kFreq32000Hz)
2392 samplingFreqHz = 32000;
2393 else if (frequency == kFreq16000Hz)
2394 samplingFreqHz = 16000;
2395
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002396 if (_audioCodingModule.Codec("CN", &codec, samplingFreqHz, kMono) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00002397 {
2398 _engineStatisticsPtr->SetLastError(
2399 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2400 "SetSendCNPayloadType() failed to retrieve default CN codec "
2401 "settings");
2402 return -1;
2403 }
2404
2405 // Modify the payload type (must be set to dynamic range)
2406 codec.pltype = type;
2407
2408 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
2409 {
2410 _engineStatisticsPtr->SetLastError(
2411 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2412 "SetSendCNPayloadType() failed to register CN to ACM");
2413 return -1;
2414 }
2415
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002416 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002417 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00002418 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2419 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00002420 {
2421 _engineStatisticsPtr->SetLastError(
2422 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2423 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
2424 "module");
2425 return -1;
2426 }
2427 }
2428 return 0;
2429}
2430
2431WebRtc_Word32
2432Channel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
2433{
2434 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2435 "Channel::SetISACInitTargetRate()");
2436
2437 CodecInst sendCodec;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002438 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00002439 {
2440 _engineStatisticsPtr->SetLastError(
2441 VE_CODEC_ERROR, kTraceError,
2442 "SetISACInitTargetRate() failed to retrieve send codec");
2443 return -1;
2444 }
2445 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2446 {
2447 // This API is only valid if iSAC is setup to run in channel-adaptive
2448 // mode.
2449 // We do not validate the adaptive mode here. It is done later in the
2450 // ConfigISACBandwidthEstimator() API.
2451 _engineStatisticsPtr->SetLastError(
2452 VE_CODEC_ERROR, kTraceError,
2453 "SetISACInitTargetRate() send codec is not iSAC");
2454 return -1;
2455 }
2456
2457 WebRtc_UWord8 initFrameSizeMsec(0);
2458 if (16000 == sendCodec.plfreq)
2459 {
2460 // Note that 0 is a valid and corresponds to "use default
2461 if ((rateBps != 0 &&
2462 rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
2463 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
2464 {
2465 _engineStatisticsPtr->SetLastError(
2466 VE_INVALID_ARGUMENT, kTraceError,
2467 "SetISACInitTargetRate() invalid target rate - 1");
2468 return -1;
2469 }
2470 // 30 or 60ms
2471 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 16);
2472 }
2473 else if (32000 == sendCodec.plfreq)
2474 {
2475 if ((rateBps != 0 &&
2476 rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
2477 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
2478 {
2479 _engineStatisticsPtr->SetLastError(
2480 VE_INVALID_ARGUMENT, kTraceError,
2481 "SetISACInitTargetRate() invalid target rate - 2");
2482 return -1;
2483 }
2484 initFrameSizeMsec = (WebRtc_UWord8)(sendCodec.pacsize / 32); // 30ms
2485 }
2486
2487 if (_audioCodingModule.ConfigISACBandwidthEstimator(
2488 initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2489 {
2490 _engineStatisticsPtr->SetLastError(
2491 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2492 "SetISACInitTargetRate() iSAC BWE config failed");
2493 return -1;
2494 }
2495
2496 return 0;
2497}
2498
2499WebRtc_Word32
2500Channel::SetISACMaxRate(int rateBps)
2501{
2502 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2503 "Channel::SetISACMaxRate()");
2504
2505 CodecInst sendCodec;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002506 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00002507 {
2508 _engineStatisticsPtr->SetLastError(
2509 VE_CODEC_ERROR, kTraceError,
2510 "SetISACMaxRate() failed to retrieve send codec");
2511 return -1;
2512 }
2513 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2514 {
2515 // This API is only valid if iSAC is selected as sending codec.
2516 _engineStatisticsPtr->SetLastError(
2517 VE_CODEC_ERROR, kTraceError,
2518 "SetISACMaxRate() send codec is not iSAC");
2519 return -1;
2520 }
2521 if (16000 == sendCodec.plfreq)
2522 {
2523 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2524 (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2525 {
2526 _engineStatisticsPtr->SetLastError(
2527 VE_INVALID_ARGUMENT, kTraceError,
2528 "SetISACMaxRate() invalid max rate - 1");
2529 return -1;
2530 }
2531 }
2532 else if (32000 == sendCodec.plfreq)
2533 {
2534 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2535 (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2536 {
2537 _engineStatisticsPtr->SetLastError(
2538 VE_INVALID_ARGUMENT, kTraceError,
2539 "SetISACMaxRate() invalid max rate - 2");
2540 return -1;
2541 }
2542 }
2543 if (_sending)
2544 {
2545 _engineStatisticsPtr->SetLastError(
2546 VE_SENDING, kTraceError,
2547 "SetISACMaxRate() unable to set max rate while sending");
2548 return -1;
2549 }
2550
2551 // Set the maximum instantaneous rate of iSAC (works for both adaptive
2552 // and non-adaptive mode)
2553 if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2554 {
2555 _engineStatisticsPtr->SetLastError(
2556 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2557 "SetISACMaxRate() failed to set max rate");
2558 return -1;
2559 }
2560
2561 return 0;
2562}
2563
2564WebRtc_Word32
2565Channel::SetISACMaxPayloadSize(int sizeBytes)
2566{
2567 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2568 "Channel::SetISACMaxPayloadSize()");
2569 CodecInst sendCodec;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00002570 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00002571 {
2572 _engineStatisticsPtr->SetLastError(
2573 VE_CODEC_ERROR, kTraceError,
2574 "SetISACMaxPayloadSize() failed to retrieve send codec");
2575 return -1;
2576 }
2577 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2578 {
2579 _engineStatisticsPtr->SetLastError(
2580 VE_CODEC_ERROR, kTraceError,
2581 "SetISACMaxPayloadSize() send codec is not iSAC");
2582 return -1;
2583 }
2584 if (16000 == sendCodec.plfreq)
2585 {
2586 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2587 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2588 {
2589 _engineStatisticsPtr->SetLastError(
2590 VE_INVALID_ARGUMENT, kTraceError,
2591 "SetISACMaxPayloadSize() invalid max payload - 1");
2592 return -1;
2593 }
2594 }
2595 else if (32000 == sendCodec.plfreq)
2596 {
2597 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2598 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2599 {
2600 _engineStatisticsPtr->SetLastError(
2601 VE_INVALID_ARGUMENT, kTraceError,
2602 "SetISACMaxPayloadSize() invalid max payload - 2");
2603 return -1;
2604 }
2605 }
2606 if (_sending)
2607 {
2608 _engineStatisticsPtr->SetLastError(
2609 VE_SENDING, kTraceError,
2610 "SetISACMaxPayloadSize() unable to set max rate while sending");
2611 return -1;
2612 }
2613
2614 if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2615 {
2616 _engineStatisticsPtr->SetLastError(
2617 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2618 "SetISACMaxPayloadSize() failed to set max payload size");
2619 return -1;
2620 }
2621 return 0;
2622}
2623
2624WebRtc_Word32 Channel::RegisterExternalTransport(Transport& transport)
2625{
2626 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2627 "Channel::RegisterExternalTransport()");
2628
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002629 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002630
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002631#ifndef WEBRTC_EXTERNAL_TRANSPORT
2632 // Sanity checks for default (non external transport) to avoid conflict with
2633 // WebRtc sockets.
2634 if (_socketTransportModule.SendSocketsInitialized())
2635 {
2636 _engineStatisticsPtr->SetLastError(VE_SEND_SOCKETS_CONFLICT,
2637 kTraceError,
2638 "RegisterExternalTransport() send sockets already initialized");
2639 return -1;
2640 }
2641 if (_socketTransportModule.ReceiveSocketsInitialized())
2642 {
2643 _engineStatisticsPtr->SetLastError(VE_RECEIVE_SOCKETS_CONFLICT,
2644 kTraceError,
2645 "RegisterExternalTransport() receive sockets already initialized");
2646 return -1;
2647 }
2648#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00002649 if (_externalTransport)
2650 {
2651 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2652 kTraceError,
2653 "RegisterExternalTransport() external transport already enabled");
2654 return -1;
2655 }
2656 _externalTransport = true;
2657 _transportPtr = &transport;
2658 return 0;
2659}
2660
2661WebRtc_Word32
2662Channel::DeRegisterExternalTransport()
2663{
2664 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2665 "Channel::DeRegisterExternalTransport()");
2666
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00002667 CriticalSectionScoped cs(&_callbackCritSect);
xians@webrtc.org83661f52011-11-25 10:58:15 +00002668
niklase@google.com470e71d2011-07-07 08:21:25 +00002669 if (!_transportPtr)
2670 {
2671 _engineStatisticsPtr->SetLastError(
2672 VE_INVALID_OPERATION, kTraceWarning,
2673 "DeRegisterExternalTransport() external transport already "
2674 "disabled");
2675 return 0;
2676 }
2677 _externalTransport = false;
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002678#ifdef WEBRTC_EXTERNAL_TRANSPORT
niklase@google.com470e71d2011-07-07 08:21:25 +00002679 _transportPtr = NULL;
2680 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2681 "DeRegisterExternalTransport() all transport is disabled");
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002682#else
2683 _transportPtr = &_socketTransportModule;
2684 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2685 "DeRegisterExternalTransport() internal Transport is enabled");
2686#endif
niklase@google.com470e71d2011-07-07 08:21:25 +00002687 return 0;
2688}
2689
2690WebRtc_Word32
2691Channel::ReceivedRTPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2692{
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002693 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2694 "Channel::ReceivedRTPPacket()");
2695 const char dummyIP[] = "127.0.0.1";
2696 IncomingRTPPacket(data, length, dummyIP, 0);
2697 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002698}
2699
2700WebRtc_Word32
2701Channel::ReceivedRTCPPacket(const WebRtc_Word8* data, WebRtc_Word32 length)
2702{
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002703 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2704 "Channel::ReceivedRTCPPacket()");
2705 const char dummyIP[] = "127.0.0.1";
2706 IncomingRTCPPacket(data, length, dummyIP, 0);
2707 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002708}
2709
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00002710#ifndef WEBRTC_EXTERNAL_TRANSPORT
2711WebRtc_Word32
2712Channel::GetSourceInfo(int& rtpPort, int& rtcpPort, char ipAddr[64])
2713{
2714 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2715 "Channel::GetSourceInfo()");
2716
2717 WebRtc_UWord16 rtpPortModule;
2718 WebRtc_UWord16 rtcpPortModule;
2719 char ipaddr[UdpTransport::kIpAddressVersion6Length] = {0};
2720
2721 if (_socketTransportModule.RemoteSocketInformation(ipaddr,
2722 rtpPortModule,
2723 rtcpPortModule) != 0)
2724 {
2725 _engineStatisticsPtr->SetLastError(
2726 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2727 "GetSourceInfo() failed to retrieve remote socket information");
2728 return -1;
2729 }
2730 strcpy(ipAddr, ipaddr);
2731 rtpPort = rtpPortModule;
2732 rtcpPort = rtcpPortModule;
2733
2734 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2735 "GetSourceInfo() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2736 rtpPort, rtcpPort, ipAddr);
2737 return 0;
2738}
2739
2740WebRtc_Word32
2741Channel::EnableIPv6()
2742{
2743 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2744 "Channel::EnableIPv6()");
2745 if (_socketTransportModule.ReceiveSocketsInitialized() ||
2746 _socketTransportModule.SendSocketsInitialized())
2747 {
2748 _engineStatisticsPtr->SetLastError(
2749 VE_INVALID_OPERATION, kTraceError,
2750 "EnableIPv6() socket layer is already initialized");
2751 return -1;
2752 }
2753 if (_socketTransportModule.EnableIpV6() != 0)
2754 {
2755 _engineStatisticsPtr->SetLastError(
2756 VE_SOCKET_ERROR, kTraceError,
2757 "EnableIPv6() failed to enable IPv6");
2758 const UdpTransport::ErrorCode lastError =
2759 _socketTransportModule.LastError();
2760 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2761 "UdpTransport::LastError() => %d", lastError);
2762 return -1;
2763 }
2764 return 0;
2765}
2766
2767bool
2768Channel::IPv6IsEnabled() const
2769{
2770 bool isEnabled = _socketTransportModule.IpV6Enabled();
2771 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2772 "IPv6IsEnabled() => %d", isEnabled);
2773 return isEnabled;
2774}
2775
2776WebRtc_Word32
2777Channel::SetSourceFilter(int rtpPort, int rtcpPort, const char ipAddr[64])
2778{
2779 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2780 "Channel::SetSourceFilter()");
2781 if (_socketTransportModule.SetFilterPorts(
2782 static_cast<WebRtc_UWord16>(rtpPort),
2783 static_cast<WebRtc_UWord16>(rtcpPort)) != 0)
2784 {
2785 _engineStatisticsPtr->SetLastError(
2786 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2787 "SetSourceFilter() failed to set filter ports");
2788 const UdpTransport::ErrorCode lastError =
2789 _socketTransportModule.LastError();
2790 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2791 "UdpTransport::LastError() => %d",
2792 lastError);
2793 return -1;
2794 }
2795 const char* filterIpAddress = ipAddr;
2796 if (_socketTransportModule.SetFilterIP(filterIpAddress) != 0)
2797 {
2798 _engineStatisticsPtr->SetLastError(
2799 VE_INVALID_IP_ADDRESS, kTraceError,
2800 "SetSourceFilter() failed to set filter IP address");
2801 const UdpTransport::ErrorCode lastError =
2802 _socketTransportModule.LastError();
2803 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2804 "UdpTransport::LastError() => %d", lastError);
2805 return -1;
2806 }
2807 return 0;
2808}
2809
2810WebRtc_Word32
2811Channel::GetSourceFilter(int& rtpPort, int& rtcpPort, char ipAddr[64])
2812{
2813 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2814 "Channel::GetSourceFilter()");
2815 WebRtc_UWord16 rtpFilterPort(0);
2816 WebRtc_UWord16 rtcpFilterPort(0);
2817 if (_socketTransportModule.FilterPorts(rtpFilterPort, rtcpFilterPort) != 0)
2818 {
2819 _engineStatisticsPtr->SetLastError(
2820 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2821 "GetSourceFilter() failed to retrieve filter ports");
2822 }
2823 char ipAddrTmp[UdpTransport::kIpAddressVersion6Length] = {0};
2824 if (_socketTransportModule.FilterIP(ipAddrTmp) != 0)
2825 {
2826 // no filter has been configured (not seen as an error)
2827 memset(ipAddrTmp,
2828 0, UdpTransport::kIpAddressVersion6Length);
2829 }
2830 rtpPort = static_cast<int> (rtpFilterPort);
2831 rtcpPort = static_cast<int> (rtcpFilterPort);
2832 strcpy(ipAddr, ipAddrTmp);
2833 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2834 "GetSourceFilter() => rtpPort=%d, rtcpPort=%d, ipAddr=%s",
2835 rtpPort, rtcpPort, ipAddr);
2836 return 0;
2837}
2838
2839WebRtc_Word32
2840Channel::SetSendTOS(int DSCP, int priority, bool useSetSockopt)
2841{
2842 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2843 "Channel::SetSendTOS(DSCP=%d, useSetSockopt=%d)",
2844 DSCP, (int)useSetSockopt);
2845
2846 // Set TOS value and possibly try to force usage of setsockopt()
2847 if (_socketTransportModule.SetToS(DSCP, useSetSockopt) != 0)
2848 {
2849 UdpTransport::ErrorCode lastSockError(
2850 _socketTransportModule.LastError());
2851 switch (lastSockError)
2852 {
2853 case UdpTransport::kTosError:
2854 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2855 "SetSendTOS() TOS error");
2856 break;
2857 case UdpTransport::kQosError:
2858 _engineStatisticsPtr->SetLastError(
2859 VE_TOS_GQOS_CONFLICT, kTraceError,
2860 "SetSendTOS() GQOS error");
2861 break;
2862 case UdpTransport::kTosInvalid:
2863 // can't switch SetSockOpt method without disabling TOS first, or
2864 // SetSockopt() call failed
2865 _engineStatisticsPtr->SetLastError(VE_TOS_INVALID, kTraceError,
2866 "SetSendTOS() invalid TOS");
2867 break;
2868 case UdpTransport::kSocketInvalid:
2869 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
2870 "SetSendTOS() invalid Socket");
2871 break;
2872 default:
2873 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2874 "SetSendTOS() TOS error");
2875 break;
2876 }
2877 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
2878 "UdpTransport => lastError = %d",
2879 lastSockError);
2880 return -1;
2881 }
2882
2883 // Set priority (PCP) value, -1 means don't change
2884 if (-1 != priority)
2885 {
2886 if (_socketTransportModule.SetPCP(priority) != 0)
2887 {
2888 UdpTransport::ErrorCode lastSockError(
2889 _socketTransportModule.LastError());
2890 switch (lastSockError)
2891 {
2892 case UdpTransport::kPcpError:
2893 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2894 "SetSendTOS() PCP error");
2895 break;
2896 case UdpTransport::kQosError:
2897 _engineStatisticsPtr->SetLastError(
2898 VE_TOS_GQOS_CONFLICT, kTraceError,
2899 "SetSendTOS() GQOS conflict");
2900 break;
2901 case UdpTransport::kSocketInvalid:
2902 _engineStatisticsPtr->SetLastError(
2903 VE_SOCKET_ERROR, kTraceError,
2904 "SetSendTOS() invalid Socket");
2905 break;
2906 default:
2907 _engineStatisticsPtr->SetLastError(VE_TOS_ERROR, kTraceError,
2908 "SetSendTOS() PCP error");
2909 break;
2910 }
2911 WEBRTC_TRACE(kTraceError, kTraceVoice,
2912 VoEId(_instanceId,_channelId),
2913 "UdpTransport => lastError = %d",
2914 lastSockError);
2915 return -1;
2916 }
2917 }
2918
2919 return 0;
2920}
2921
2922WebRtc_Word32
2923Channel::GetSendTOS(int &DSCP, int& priority, bool &useSetSockopt)
2924{
2925 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2926 "Channel::GetSendTOS(DSCP=?, useSetSockopt=?)");
2927 WebRtc_Word32 dscp(0), prio(0);
2928 bool setSockopt(false);
2929 if (_socketTransportModule.ToS(dscp, setSockopt) != 0)
2930 {
2931 _engineStatisticsPtr->SetLastError(
2932 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2933 "GetSendTOS() failed to get TOS info");
2934 return -1;
2935 }
2936 if (_socketTransportModule.PCP(prio) != 0)
2937 {
2938 _engineStatisticsPtr->SetLastError(
2939 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
2940 "GetSendTOS() failed to get PCP info");
2941 return -1;
2942 }
2943 DSCP = static_cast<int> (dscp);
2944 priority = static_cast<int> (prio);
2945 useSetSockopt = setSockopt;
2946 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
2947 "GetSendTOS() => DSCP=%d, priority=%d, useSetSockopt=%d",
2948 DSCP, priority, (int)useSetSockopt);
2949 return 0;
2950}
2951
2952#if defined(_WIN32)
2953WebRtc_Word32
2954Channel::SetSendGQoS(bool enable, int serviceType, int overrideDSCP)
2955{
2956 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2957 "Channel::SetSendGQoS(enable=%d, serviceType=%d, "
2958 "overrideDSCP=%d)",
2959 (int)enable, serviceType, overrideDSCP);
2960 if(!_socketTransportModule.ReceiveSocketsInitialized())
2961 {
2962 _engineStatisticsPtr->SetLastError(
2963 VE_SOCKETS_NOT_INITED, kTraceError,
2964 "SetSendGQoS() GQoS state must be set after sockets are created");
2965 return -1;
2966 }
2967 if(!_socketTransportModule.SendSocketsInitialized())
2968 {
2969 _engineStatisticsPtr->SetLastError(
2970 VE_DESTINATION_NOT_INITED, kTraceError,
2971 "SetSendGQoS() GQoS state must be set after sending side is "
2972 "initialized");
2973 return -1;
2974 }
2975 if (enable &&
2976 (serviceType != SERVICETYPE_BESTEFFORT) &&
2977 (serviceType != SERVICETYPE_CONTROLLEDLOAD) &&
2978 (serviceType != SERVICETYPE_GUARANTEED) &&
2979 (serviceType != SERVICETYPE_QUALITATIVE))
2980 {
2981 _engineStatisticsPtr->SetLastError(
2982 VE_INVALID_ARGUMENT, kTraceError,
2983 "SetSendGQoS() Invalid service type");
2984 return -1;
2985 }
2986 if (enable && ((overrideDSCP < 0) || (overrideDSCP > 63)))
2987 {
2988 _engineStatisticsPtr->SetLastError(
2989 VE_INVALID_ARGUMENT, kTraceError,
2990 "SetSendGQoS() Invalid overrideDSCP value");
2991 return -1;
2992 }
2993
2994 // Avoid GQoS/ToS conflict when user wants to override the default DSCP
2995 // mapping
2996 bool QoS(false);
2997 WebRtc_Word32 sType(0);
2998 WebRtc_Word32 ovrDSCP(0);
2999 if (_socketTransportModule.QoS(QoS, sType, ovrDSCP))
3000 {
3001 _engineStatisticsPtr->SetLastError(
3002 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceError,
3003 "SetSendGQoS() failed to get QOS info");
3004 return -1;
3005 }
3006 if (QoS && ovrDSCP == 0 && overrideDSCP != 0)
3007 {
3008 _engineStatisticsPtr->SetLastError(
3009 VE_TOS_GQOS_CONFLICT, kTraceError,
3010 "SetSendGQoS() QOS is already enabled and overrideDSCP differs,"
3011 " not allowed");
3012 return -1;
3013 }
3014 const WebRtc_Word32 maxBitrate(0);
3015 if (_socketTransportModule.SetQoS(enable,
3016 static_cast<WebRtc_Word32>(serviceType),
3017 maxBitrate,
3018 static_cast<WebRtc_Word32>(overrideDSCP),
3019 true))
3020 {
3021 UdpTransport::ErrorCode lastSockError(
3022 _socketTransportModule.LastError());
3023 switch (lastSockError)
3024 {
3025 case UdpTransport::kQosError:
3026 _engineStatisticsPtr->SetLastError(VE_GQOS_ERROR, kTraceError,
3027 "SetSendGQoS() QOS error");
3028 break;
3029 default:
3030 _engineStatisticsPtr->SetLastError(VE_SOCKET_ERROR, kTraceError,
3031 "SetSendGQoS() Socket error");
3032 break;
3033 }
3034 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3035 "UdpTransport() => lastError = %d",
3036 lastSockError);
3037 return -1;
3038 }
3039 return 0;
3040}
3041#endif
3042
3043#if defined(_WIN32)
3044WebRtc_Word32
3045Channel::GetSendGQoS(bool &enabled, int &serviceType, int &overrideDSCP)
3046{
3047 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3048 "Channel::GetSendGQoS(enable=?, serviceType=?, "
3049 "overrideDSCP=?)");
3050
3051 bool QoS(false);
3052 WebRtc_Word32 serviceTypeModule(0);
3053 WebRtc_Word32 overrideDSCPModule(0);
3054 _socketTransportModule.QoS(QoS, serviceTypeModule, overrideDSCPModule);
3055
3056 enabled = QoS;
3057 serviceType = static_cast<int> (serviceTypeModule);
3058 overrideDSCP = static_cast<int> (overrideDSCPModule);
3059
3060 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3061 "GetSendGQoS() => enabled=%d, serviceType=%d, overrideDSCP=%d",
3062 (int)enabled, serviceType, overrideDSCP);
3063 return 0;
3064}
3065#endif
3066#endif
3067
niklase@google.com470e71d2011-07-07 08:21:25 +00003068WebRtc_Word32
3069Channel::SetPacketTimeoutNotification(bool enable, int timeoutSeconds)
3070{
3071 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3072 "Channel::SetPacketTimeoutNotification()");
3073 if (enable)
3074 {
3075 const WebRtc_UWord32 RTPtimeoutMS = 1000*timeoutSeconds;
3076 const WebRtc_UWord32 RTCPtimeoutMS = 0;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003077 _rtpRtcpModule->SetPacketTimeout(RTPtimeoutMS, RTCPtimeoutMS);
niklase@google.com470e71d2011-07-07 08:21:25 +00003078 _rtpPacketTimeOutIsEnabled = true;
3079 _rtpTimeOutSeconds = timeoutSeconds;
3080 }
3081 else
3082 {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003083 _rtpRtcpModule->SetPacketTimeout(0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +00003084 _rtpPacketTimeOutIsEnabled = false;
3085 _rtpTimeOutSeconds = 0;
3086 }
3087 return 0;
3088}
3089
3090WebRtc_Word32
3091Channel::GetPacketTimeoutNotification(bool& enabled, int& timeoutSeconds)
3092{
3093 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3094 "Channel::GetPacketTimeoutNotification()");
3095 enabled = _rtpPacketTimeOutIsEnabled;
3096 if (enabled)
3097 {
3098 timeoutSeconds = _rtpTimeOutSeconds;
3099 }
3100 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3101 "GetPacketTimeoutNotification() => enabled=%d,"
3102 " timeoutSeconds=%d",
3103 enabled, timeoutSeconds);
3104 return 0;
3105}
3106
3107WebRtc_Word32
3108Channel::RegisterDeadOrAliveObserver(VoEConnectionObserver& observer)
3109{
3110 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3111 "Channel::RegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003112 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003113
3114 if (_connectionObserverPtr)
3115 {
3116 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, kTraceError,
3117 "RegisterDeadOrAliveObserver() observer already enabled");
3118 return -1;
3119 }
3120
3121 _connectionObserverPtr = &observer;
3122 _connectionObserver = true;
3123
3124 return 0;
3125}
3126
3127WebRtc_Word32
3128Channel::DeRegisterDeadOrAliveObserver()
3129{
3130 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3131 "Channel::DeRegisterDeadOrAliveObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003132 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003133
3134 if (!_connectionObserverPtr)
3135 {
3136 _engineStatisticsPtr->SetLastError(
3137 VE_INVALID_OPERATION, kTraceWarning,
3138 "DeRegisterDeadOrAliveObserver() observer already disabled");
3139 return 0;
3140 }
3141
3142 _connectionObserver = false;
3143 _connectionObserverPtr = NULL;
3144
3145 return 0;
3146}
3147
3148WebRtc_Word32
3149Channel::SetPeriodicDeadOrAliveStatus(bool enable, int sampleTimeSeconds)
3150{
3151 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3152 "Channel::SetPeriodicDeadOrAliveStatus()");
3153 if (!_connectionObserverPtr)
3154 {
3155 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3156 "SetPeriodicDeadOrAliveStatus() connection observer has"
3157 " not been registered");
3158 }
3159 if (enable)
3160 {
3161 ResetDeadOrAliveCounters();
3162 }
3163 bool enabled(false);
3164 WebRtc_UWord8 currentSampleTimeSec(0);
3165 // Store last state (will be used later if dead-or-alive is disabled).
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003166 _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, currentSampleTimeSec);
niklase@google.com470e71d2011-07-07 08:21:25 +00003167 // Update the dead-or-alive state.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003168 if (_rtpRtcpModule->SetPeriodicDeadOrAliveStatus(
niklase@google.com470e71d2011-07-07 08:21:25 +00003169 enable, (WebRtc_UWord8)sampleTimeSeconds) != 0)
3170 {
3171 _engineStatisticsPtr->SetLastError(
3172 VE_RTP_RTCP_MODULE_ERROR,
3173 kTraceError,
3174 "SetPeriodicDeadOrAliveStatus() failed to set dead-or-alive "
3175 "status");
3176 return -1;
3177 }
3178 if (!enable)
3179 {
3180 // Restore last utilized sample time.
3181 // Without this, the sample time would always be reset to default
3182 // (2 sec), each time dead-or-alived was disabled without sample-time
3183 // parameter.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003184 _rtpRtcpModule->SetPeriodicDeadOrAliveStatus(enable,
niklase@google.com470e71d2011-07-07 08:21:25 +00003185 currentSampleTimeSec);
3186 }
3187 return 0;
3188}
3189
3190WebRtc_Word32
3191Channel::GetPeriodicDeadOrAliveStatus(bool& enabled, int& sampleTimeSeconds)
3192{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00003193 _rtpRtcpModule->PeriodicDeadOrAliveStatus(
niklase@google.com470e71d2011-07-07 08:21:25 +00003194 enabled,
3195 (WebRtc_UWord8&)sampleTimeSeconds);
3196 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,-1),
3197 "GetPeriodicDeadOrAliveStatus() => enabled=%d,"
3198 " sampleTimeSeconds=%d",
3199 enabled, sampleTimeSeconds);
3200 return 0;
3201}
3202
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00003203WebRtc_Word32
3204Channel::SendUDPPacket(const void* data,
3205 unsigned int length,
3206 int& transmittedBytes,
3207 bool useRtcpSocket)
3208{
3209 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3210 "Channel::SendUDPPacket()");
3211 if (_externalTransport)
3212 {
3213 _engineStatisticsPtr->SetLastError(
3214 VE_EXTERNAL_TRANSPORT_ENABLED, kTraceError,
3215 "SendUDPPacket() external transport is enabled");
3216 return -1;
3217 }
3218 if (useRtcpSocket && !_rtpRtcpModule->RTCP())
3219 {
3220 _engineStatisticsPtr->SetLastError(
3221 VE_RTCP_ERROR, kTraceError,
3222 "SendUDPPacket() RTCP is disabled");
3223 return -1;
3224 }
3225 if (!_sending)
3226 {
3227 _engineStatisticsPtr->SetLastError(
3228 VE_NOT_SENDING, kTraceError,
3229 "SendUDPPacket() not sending");
3230 return -1;
3231 }
3232
3233 char* dataC = new char[length];
3234 if (NULL == dataC)
3235 {
3236 _engineStatisticsPtr->SetLastError(
3237 VE_NO_MEMORY, kTraceError,
3238 "SendUDPPacket() memory allocation failed");
3239 return -1;
3240 }
3241 memcpy(dataC, data, length);
3242
3243 transmittedBytes = SendPacketRaw(dataC, length, useRtcpSocket);
3244
3245 delete [] dataC;
3246 dataC = NULL;
3247
3248 if (transmittedBytes <= 0)
3249 {
3250 _engineStatisticsPtr->SetLastError(
3251 VE_SEND_ERROR, kTraceError,
3252 "SendUDPPacket() transmission failed");
3253 transmittedBytes = 0;
3254 return -1;
3255 }
3256 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3257 "SendUDPPacket() => transmittedBytes=%d", transmittedBytes);
3258 return 0;
3259}
3260
3261
niklase@google.com470e71d2011-07-07 08:21:25 +00003262int Channel::StartPlayingFileLocally(const char* fileName,
3263 const bool loop,
3264 const FileFormats format,
3265 const int startPosition,
3266 const float volumeScaling,
3267 const int stopPosition,
3268 const CodecInst* codecInst)
3269{
3270 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3271 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
3272 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
3273 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3274 startPosition, stopPosition);
3275
3276 if (_outputFilePlaying)
3277 {
3278 _engineStatisticsPtr->SetLastError(
3279 VE_ALREADY_PLAYING, kTraceError,
3280 "StartPlayingFileLocally() is already playing");
3281 return -1;
3282 }
3283
niklase@google.com470e71d2011-07-07 08:21:25 +00003284 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003285 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003286
3287 if (_outputFilePlayerPtr)
3288 {
3289 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3290 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3291 _outputFilePlayerPtr = NULL;
3292 }
3293
3294 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3295 _outputFilePlayerId, (const FileFormats)format);
3296
3297 if (_outputFilePlayerPtr == NULL)
3298 {
3299 _engineStatisticsPtr->SetLastError(
3300 VE_INVALID_ARGUMENT, kTraceError,
henrike@webrtc.org31d30702011-11-18 19:59:32 +00003301 "StartPlayingFileLocally() filePlayer format is not correct");
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003302 return -1;
3303 }
3304
3305 const WebRtc_UWord32 notificationTime(0);
3306
3307 if (_outputFilePlayerPtr->StartPlayingFile(
3308 fileName,
3309 loop,
3310 startPosition,
3311 volumeScaling,
3312 notificationTime,
3313 stopPosition,
3314 (const CodecInst*)codecInst) != 0)
3315 {
3316 _engineStatisticsPtr->SetLastError(
3317 VE_BAD_FILE, kTraceError,
3318 "StartPlayingFile() failed to start file playout");
3319 _outputFilePlayerPtr->StopPlayingFile();
3320 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3321 _outputFilePlayerPtr = NULL;
3322 return -1;
3323 }
3324 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3325 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003326 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003327
3328 if (RegisterFilePlayingToMixer() != 0)
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003329 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00003330
3331 return 0;
3332}
3333
3334int Channel::StartPlayingFileLocally(InStream* stream,
3335 const FileFormats format,
3336 const int startPosition,
3337 const float volumeScaling,
3338 const int stopPosition,
3339 const CodecInst* codecInst)
3340{
3341 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3342 "Channel::StartPlayingFileLocally(format=%d,"
3343 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3344 format, volumeScaling, startPosition, stopPosition);
3345
3346 if(stream == NULL)
3347 {
3348 _engineStatisticsPtr->SetLastError(
3349 VE_BAD_FILE, kTraceError,
3350 "StartPlayingFileLocally() NULL as input stream");
3351 return -1;
3352 }
3353
3354
3355 if (_outputFilePlaying)
3356 {
3357 _engineStatisticsPtr->SetLastError(
3358 VE_ALREADY_PLAYING, kTraceError,
3359 "StartPlayingFileLocally() is already playing");
3360 return -1;
3361 }
3362
niklase@google.com470e71d2011-07-07 08:21:25 +00003363 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003364 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003365
3366 // Destroy the old instance
3367 if (_outputFilePlayerPtr)
3368 {
3369 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3370 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3371 _outputFilePlayerPtr = NULL;
3372 }
3373
3374 // Create the instance
3375 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3376 _outputFilePlayerId,
3377 (const FileFormats)format);
3378
3379 if (_outputFilePlayerPtr == NULL)
3380 {
3381 _engineStatisticsPtr->SetLastError(
3382 VE_INVALID_ARGUMENT, kTraceError,
3383 "StartPlayingFileLocally() filePlayer format isnot correct");
3384 return -1;
3385 }
3386
3387 const WebRtc_UWord32 notificationTime(0);
3388
3389 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3390 volumeScaling,
3391 notificationTime,
3392 stopPosition, codecInst) != 0)
3393 {
3394 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3395 "StartPlayingFile() failed to "
3396 "start file playout");
3397 _outputFilePlayerPtr->StopPlayingFile();
3398 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3399 _outputFilePlayerPtr = NULL;
3400 return -1;
3401 }
3402 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
3403 _outputFilePlaying = true;
niklase@google.com470e71d2011-07-07 08:21:25 +00003404 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003405
3406 if (RegisterFilePlayingToMixer() != 0)
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003407 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00003408
niklase@google.com470e71d2011-07-07 08:21:25 +00003409 return 0;
3410}
3411
3412int Channel::StopPlayingFileLocally()
3413{
3414 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3415 "Channel::StopPlayingFileLocally()");
3416
3417 if (!_outputFilePlaying)
3418 {
3419 _engineStatisticsPtr->SetLastError(
3420 VE_INVALID_OPERATION, kTraceWarning,
3421 "StopPlayingFileLocally() isnot playing");
3422 return 0;
3423 }
3424
niklase@google.com470e71d2011-07-07 08:21:25 +00003425 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003426 CriticalSectionScoped cs(&_fileCritSect);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003427
3428 if (_outputFilePlayerPtr->StopPlayingFile() != 0)
3429 {
3430 _engineStatisticsPtr->SetLastError(
3431 VE_STOP_RECORDING_FAILED, kTraceError,
3432 "StopPlayingFile() could not stop playing");
3433 return -1;
3434 }
3435 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3436 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3437 _outputFilePlayerPtr = NULL;
3438 _outputFilePlaying = false;
niklase@google.com470e71d2011-07-07 08:21:25 +00003439 }
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003440 // _fileCritSect cannot be taken while calling
3441 // SetAnonymousMixibilityStatus. Refer to comments in
3442 // StartPlayingFileLocally(const char* ...) for more details.
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003443 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
3444 {
3445 _engineStatisticsPtr->SetLastError(
3446 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00003447 "StopPlayingFile() failed to stop participant from playing as"
3448 "file in the mixer");
henrike@webrtc.org066f9e52011-10-28 23:15:47 +00003449 return -1;
3450 }
niklase@google.com470e71d2011-07-07 08:21:25 +00003451
3452 return 0;
3453}
3454
3455int Channel::IsPlayingFileLocally() const
3456{
3457 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3458 "Channel::IsPlayingFileLocally()");
3459
3460 return (WebRtc_Word32)_outputFilePlaying;
3461}
3462
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00003463int Channel::RegisterFilePlayingToMixer()
3464{
3465 // Return success for not registering for file playing to mixer if:
3466 // 1. playing file before playout is started on that channel.
3467 // 2. starting playout without file playing on that channel.
3468 if (!_playing || !_outputFilePlaying)
3469 {
3470 return 0;
3471 }
3472
3473 // |_fileCritSect| cannot be taken while calling
3474 // SetAnonymousMixabilityStatus() since as soon as the participant is added
3475 // frames can be pulled by the mixer. Since the frames are generated from
3476 // the file, _fileCritSect will be taken. This would result in a deadlock.
3477 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
3478 {
3479 CriticalSectionScoped cs(&_fileCritSect);
3480 _outputFilePlaying = false;
3481 _engineStatisticsPtr->SetLastError(
3482 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
3483 "StartPlayingFile() failed to add participant as file to mixer");
3484 _outputFilePlayerPtr->StopPlayingFile();
3485 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
3486 _outputFilePlayerPtr = NULL;
3487 return -1;
3488 }
3489
3490 return 0;
3491}
3492
niklase@google.com470e71d2011-07-07 08:21:25 +00003493int Channel::ScaleLocalFilePlayout(const float scale)
3494{
3495 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3496 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
3497
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003498 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003499
3500 if (!_outputFilePlaying)
3501 {
3502 _engineStatisticsPtr->SetLastError(
3503 VE_INVALID_OPERATION, kTraceError,
3504 "ScaleLocalFilePlayout() isnot playing");
3505 return -1;
3506 }
3507 if ((_outputFilePlayerPtr == NULL) ||
3508 (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
3509 {
3510 _engineStatisticsPtr->SetLastError(
3511 VE_BAD_ARGUMENT, kTraceError,
3512 "SetAudioScaling() failed to scale the playout");
3513 return -1;
3514 }
3515
3516 return 0;
3517}
3518
3519int Channel::GetLocalPlayoutPosition(int& positionMs)
3520{
3521 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3522 "Channel::GetLocalPlayoutPosition(position=?)");
3523
3524 WebRtc_UWord32 position;
3525
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003526 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003527
3528 if (_outputFilePlayerPtr == NULL)
3529 {
3530 _engineStatisticsPtr->SetLastError(
3531 VE_INVALID_OPERATION, kTraceError,
3532 "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
3533 return -1;
3534 }
3535
3536 if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
3537 {
3538 _engineStatisticsPtr->SetLastError(
3539 VE_BAD_FILE, kTraceError,
3540 "GetLocalPlayoutPosition() failed");
3541 return -1;
3542 }
3543 positionMs = position;
3544
3545 return 0;
3546}
3547
3548int Channel::StartPlayingFileAsMicrophone(const char* fileName,
3549 const bool loop,
3550 const FileFormats format,
3551 const int startPosition,
3552 const float volumeScaling,
3553 const int stopPosition,
3554 const CodecInst* codecInst)
3555{
3556 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3557 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
3558 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
3559 "stopPosition=%d)", fileName, loop, format, volumeScaling,
3560 startPosition, stopPosition);
3561
3562 if (_inputFilePlaying)
3563 {
3564 _engineStatisticsPtr->SetLastError(
3565 VE_ALREADY_PLAYING, kTraceWarning,
3566 "StartPlayingFileAsMicrophone() filePlayer is playing");
3567 return 0;
3568 }
3569
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003570 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003571
3572 // Destroy the old instance
3573 if (_inputFilePlayerPtr)
3574 {
3575 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3576 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3577 _inputFilePlayerPtr = NULL;
3578 }
3579
3580 // Create the instance
3581 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3582 _inputFilePlayerId, (const FileFormats)format);
3583
3584 if (_inputFilePlayerPtr == NULL)
3585 {
3586 _engineStatisticsPtr->SetLastError(
3587 VE_INVALID_ARGUMENT, kTraceError,
3588 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
3589 return -1;
3590 }
3591
3592 const WebRtc_UWord32 notificationTime(0);
3593
3594 if (_inputFilePlayerPtr->StartPlayingFile(
3595 fileName,
3596 loop,
3597 startPosition,
3598 volumeScaling,
3599 notificationTime,
3600 stopPosition,
3601 (const CodecInst*)codecInst) != 0)
3602 {
3603 _engineStatisticsPtr->SetLastError(
3604 VE_BAD_FILE, kTraceError,
3605 "StartPlayingFile() failed to start file playout");
3606 _inputFilePlayerPtr->StopPlayingFile();
3607 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3608 _inputFilePlayerPtr = NULL;
3609 return -1;
3610 }
3611 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3612 _inputFilePlaying = true;
3613
3614 return 0;
3615}
3616
3617int Channel::StartPlayingFileAsMicrophone(InStream* stream,
3618 const FileFormats format,
3619 const int startPosition,
3620 const float volumeScaling,
3621 const int stopPosition,
3622 const CodecInst* codecInst)
3623{
3624 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3625 "Channel::StartPlayingFileAsMicrophone(format=%d, "
3626 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
3627 format, volumeScaling, startPosition, stopPosition);
3628
3629 if(stream == NULL)
3630 {
3631 _engineStatisticsPtr->SetLastError(
3632 VE_BAD_FILE, kTraceError,
3633 "StartPlayingFileAsMicrophone NULL as input stream");
3634 return -1;
3635 }
3636
3637 if (_inputFilePlaying)
3638 {
3639 _engineStatisticsPtr->SetLastError(
3640 VE_ALREADY_PLAYING, kTraceWarning,
3641 "StartPlayingFileAsMicrophone() is playing");
3642 return 0;
3643 }
3644
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003645 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003646
3647 // Destroy the old instance
3648 if (_inputFilePlayerPtr)
3649 {
3650 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3651 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3652 _inputFilePlayerPtr = NULL;
3653 }
3654
3655 // Create the instance
3656 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
3657 _inputFilePlayerId, (const FileFormats)format);
3658
3659 if (_inputFilePlayerPtr == NULL)
3660 {
3661 _engineStatisticsPtr->SetLastError(
3662 VE_INVALID_ARGUMENT, kTraceError,
3663 "StartPlayingInputFile() filePlayer format isnot correct");
3664 return -1;
3665 }
3666
3667 const WebRtc_UWord32 notificationTime(0);
3668
3669 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
3670 volumeScaling, notificationTime,
3671 stopPosition, codecInst) != 0)
3672 {
3673 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3674 "StartPlayingFile() failed to start "
3675 "file playout");
3676 _inputFilePlayerPtr->StopPlayingFile();
3677 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3678 _inputFilePlayerPtr = NULL;
3679 return -1;
3680 }
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00003681
niklase@google.com470e71d2011-07-07 08:21:25 +00003682 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
3683 _inputFilePlaying = true;
3684
3685 return 0;
3686}
3687
3688int Channel::StopPlayingFileAsMicrophone()
3689{
3690 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3691 "Channel::StopPlayingFileAsMicrophone()");
3692
3693 if (!_inputFilePlaying)
3694 {
3695 _engineStatisticsPtr->SetLastError(
3696 VE_INVALID_OPERATION, kTraceWarning,
3697 "StopPlayingFileAsMicrophone() isnot playing");
3698 return 0;
3699 }
3700
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003701 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003702 if (_inputFilePlayerPtr->StopPlayingFile() != 0)
3703 {
3704 _engineStatisticsPtr->SetLastError(
3705 VE_STOP_RECORDING_FAILED, kTraceError,
3706 "StopPlayingFile() could not stop playing");
3707 return -1;
3708 }
3709 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
3710 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
3711 _inputFilePlayerPtr = NULL;
3712 _inputFilePlaying = false;
3713
3714 return 0;
3715}
3716
3717int Channel::IsPlayingFileAsMicrophone() const
3718{
3719 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3720 "Channel::IsPlayingFileAsMicrophone()");
3721
3722 return _inputFilePlaying;
3723}
3724
3725int Channel::ScaleFileAsMicrophonePlayout(const float scale)
3726{
3727 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3728 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
3729
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003730 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003731
3732 if (!_inputFilePlaying)
3733 {
3734 _engineStatisticsPtr->SetLastError(
3735 VE_INVALID_OPERATION, kTraceError,
3736 "ScaleFileAsMicrophonePlayout() isnot playing");
3737 return -1;
3738 }
3739
3740 if ((_inputFilePlayerPtr == NULL) ||
3741 (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
3742 {
3743 _engineStatisticsPtr->SetLastError(
3744 VE_BAD_ARGUMENT, kTraceError,
3745 "SetAudioScaling() failed to scale playout");
3746 return -1;
3747 }
3748
3749 return 0;
3750}
3751
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00003752int Channel::StartRecordingPlayout(const char* fileName,
niklase@google.com470e71d2011-07-07 08:21:25 +00003753 const CodecInst* codecInst)
3754{
3755 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3756 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
3757
3758 if (_outputFileRecording)
3759 {
3760 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3761 "StartRecordingPlayout() is already recording");
3762 return 0;
3763 }
3764
3765 FileFormats format;
3766 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3767 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3768
niklas.enbom@webrtc.org40197d72012-03-26 08:45:47 +00003769 if ((codecInst != NULL) &&
3770 ((codecInst->channels < 1) || (codecInst->channels > 2)))
niklase@google.com470e71d2011-07-07 08:21:25 +00003771 {
3772 _engineStatisticsPtr->SetLastError(
3773 VE_BAD_ARGUMENT, kTraceError,
3774 "StartRecordingPlayout() invalid compression");
3775 return(-1);
3776 }
3777 if(codecInst == NULL)
3778 {
3779 format = kFileFormatPcm16kHzFile;
3780 codecInst=&dummyCodec;
3781 }
3782 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3783 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3784 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3785 {
3786 format = kFileFormatWavFile;
3787 }
3788 else
3789 {
3790 format = kFileFormatCompressedFile;
3791 }
3792
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003793 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003794
3795 // Destroy the old instance
3796 if (_outputFileRecorderPtr)
3797 {
3798 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3799 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3800 _outputFileRecorderPtr = NULL;
3801 }
3802
3803 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3804 _outputFileRecorderId, (const FileFormats)format);
3805 if (_outputFileRecorderPtr == NULL)
3806 {
3807 _engineStatisticsPtr->SetLastError(
3808 VE_INVALID_ARGUMENT, kTraceError,
3809 "StartRecordingPlayout() fileRecorder format isnot correct");
3810 return -1;
3811 }
3812
3813 if (_outputFileRecorderPtr->StartRecordingAudioFile(
3814 fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
3815 {
3816 _engineStatisticsPtr->SetLastError(
3817 VE_BAD_FILE, kTraceError,
3818 "StartRecordingAudioFile() failed to start file recording");
3819 _outputFileRecorderPtr->StopRecording();
3820 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3821 _outputFileRecorderPtr = NULL;
3822 return -1;
3823 }
3824 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3825 _outputFileRecording = true;
3826
3827 return 0;
3828}
3829
3830int Channel::StartRecordingPlayout(OutStream* stream,
3831 const CodecInst* codecInst)
3832{
3833 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3834 "Channel::StartRecordingPlayout()");
3835
3836 if (_outputFileRecording)
3837 {
3838 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
3839 "StartRecordingPlayout() is already recording");
3840 return 0;
3841 }
3842
3843 FileFormats format;
3844 const WebRtc_UWord32 notificationTime(0); // Not supported in VoE
3845 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
3846
3847 if (codecInst != NULL && codecInst->channels != 1)
3848 {
3849 _engineStatisticsPtr->SetLastError(
3850 VE_BAD_ARGUMENT, kTraceError,
3851 "StartRecordingPlayout() invalid compression");
3852 return(-1);
3853 }
3854 if(codecInst == NULL)
3855 {
3856 format = kFileFormatPcm16kHzFile;
3857 codecInst=&dummyCodec;
3858 }
3859 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
3860 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
3861 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
3862 {
3863 format = kFileFormatWavFile;
3864 }
3865 else
3866 {
3867 format = kFileFormatCompressedFile;
3868 }
3869
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003870 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003871
3872 // Destroy the old instance
3873 if (_outputFileRecorderPtr)
3874 {
3875 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3876 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3877 _outputFileRecorderPtr = NULL;
3878 }
3879
3880 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
3881 _outputFileRecorderId, (const FileFormats)format);
3882 if (_outputFileRecorderPtr == NULL)
3883 {
3884 _engineStatisticsPtr->SetLastError(
3885 VE_INVALID_ARGUMENT, kTraceError,
3886 "StartRecordingPlayout() fileRecorder format isnot correct");
3887 return -1;
3888 }
3889
3890 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
3891 notificationTime) != 0)
3892 {
3893 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
3894 "StartRecordingPlayout() failed to "
3895 "start file recording");
3896 _outputFileRecorderPtr->StopRecording();
3897 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3898 _outputFileRecorderPtr = NULL;
3899 return -1;
3900 }
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00003901
niklase@google.com470e71d2011-07-07 08:21:25 +00003902 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
3903 _outputFileRecording = true;
3904
3905 return 0;
3906}
3907
3908int Channel::StopRecordingPlayout()
3909{
3910 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
3911 "Channel::StopRecordingPlayout()");
3912
3913 if (!_outputFileRecording)
3914 {
3915 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
3916 "StopRecordingPlayout() isnot recording");
3917 return -1;
3918 }
3919
3920
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00003921 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00003922
3923 if (_outputFileRecorderPtr->StopRecording() != 0)
3924 {
3925 _engineStatisticsPtr->SetLastError(
3926 VE_STOP_RECORDING_FAILED, kTraceError,
3927 "StopRecording() could not stop recording");
3928 return(-1);
3929 }
3930 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
3931 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
3932 _outputFileRecorderPtr = NULL;
3933 _outputFileRecording = false;
3934
3935 return 0;
3936}
3937
3938void
3939Channel::SetMixWithMicStatus(bool mix)
3940{
3941 _mixFileWithMicrophone=mix;
3942}
3943
3944int
3945Channel::GetSpeechOutputLevel(WebRtc_UWord32& level) const
3946{
3947 WebRtc_Word8 currentLevel = _outputAudioLevel.Level();
3948 level = static_cast<WebRtc_Word32> (currentLevel);
3949 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3950 VoEId(_instanceId,_channelId),
3951 "GetSpeechOutputLevel() => level=%u", level);
3952 return 0;
3953}
3954
3955int
3956Channel::GetSpeechOutputLevelFullRange(WebRtc_UWord32& level) const
3957{
3958 WebRtc_Word16 currentLevel = _outputAudioLevel.LevelFullRange();
3959 level = static_cast<WebRtc_Word32> (currentLevel);
3960 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3961 VoEId(_instanceId,_channelId),
3962 "GetSpeechOutputLevelFullRange() => level=%u", level);
3963 return 0;
3964}
3965
3966int
3967Channel::SetMute(bool enable)
3968{
3969 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3970 "Channel::SetMute(enable=%d)", enable);
3971 _mute = enable;
3972 return 0;
3973}
3974
3975bool
3976Channel::Mute() const
3977{
3978 return _mute;
3979}
3980
3981int
3982Channel::SetOutputVolumePan(float left, float right)
3983{
3984 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3985 "Channel::SetOutputVolumePan()");
3986 _panLeft = left;
3987 _panRight = right;
3988 return 0;
3989}
3990
3991int
3992Channel::GetOutputVolumePan(float& left, float& right) const
3993{
3994 left = _panLeft;
3995 right = _panRight;
3996 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3997 VoEId(_instanceId,_channelId),
3998 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
3999 return 0;
4000}
4001
4002int
4003Channel::SetChannelOutputVolumeScaling(float scaling)
4004{
4005 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4006 "Channel::SetChannelOutputVolumeScaling()");
4007 _outputGain = scaling;
4008 return 0;
4009}
4010
4011int
4012Channel::GetChannelOutputVolumeScaling(float& scaling) const
4013{
4014 scaling = _outputGain;
4015 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4016 VoEId(_instanceId,_channelId),
4017 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
4018 return 0;
4019}
4020
4021#ifdef WEBRTC_SRTP
4022
4023int
4024Channel::EnableSRTPSend(
4025 CipherTypes cipherType,
4026 int cipherKeyLength,
4027 AuthenticationTypes authType,
4028 int authKeyLength,
4029 int authTagLength,
4030 SecurityLevels level,
4031 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4032 bool useForRTCP)
4033{
4034 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4035 "Channel::EnableSRTPSend()");
4036
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004037 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004038
4039 if (_encrypting)
4040 {
4041 _engineStatisticsPtr->SetLastError(
4042 VE_INVALID_OPERATION, kTraceWarning,
4043 "EnableSRTPSend() encryption already enabled");
4044 return -1;
4045 }
4046
4047 if (key == NULL)
4048 {
4049 _engineStatisticsPtr->SetLastError(
4050 VE_INVALID_ARGUMENT, kTraceWarning,
4051 "EnableSRTPSend() invalid key string");
4052 return -1;
4053 }
4054
4055 if (((kEncryption == level ||
4056 kEncryptionAndAuthentication == level) &&
4057 (cipherKeyLength < kVoiceEngineMinSrtpEncryptLength ||
4058 cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength)) ||
4059 ((kAuthentication == level ||
4060 kEncryptionAndAuthentication == level) &&
4061 kAuthHmacSha1 == authType &&
4062 (authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length ||
4063 authTagLength > kVoiceEngineMaxSrtpAuthSha1Length)) ||
4064 ((kAuthentication == level ||
4065 kEncryptionAndAuthentication == level) &&
4066 kAuthNull == authType &&
4067 (authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength ||
4068 authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength)))
4069 {
4070 _engineStatisticsPtr->SetLastError(
4071 VE_INVALID_ARGUMENT, kTraceError,
4072 "EnableSRTPSend() invalid key length(s)");
4073 return -1;
4074 }
4075
4076
4077 if (_srtpModule.EnableSRTPEncrypt(
4078 !useForRTCP,
4079 (SrtpModule::CipherTypes)cipherType,
4080 cipherKeyLength,
4081 (SrtpModule::AuthenticationTypes)authType,
4082 authKeyLength, authTagLength,
4083 (SrtpModule::SecurityLevels)level,
4084 key) == -1)
4085 {
4086 _engineStatisticsPtr->SetLastError(
4087 VE_SRTP_ERROR, kTraceError,
4088 "EnableSRTPSend() failed to enable SRTP encryption");
4089 return -1;
4090 }
4091
4092 if (_encryptionPtr == NULL)
4093 {
4094 _encryptionPtr = &_srtpModule;
4095 }
4096 _encrypting = true;
4097
4098 return 0;
4099}
4100
4101int
4102Channel::DisableSRTPSend()
4103{
4104 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4105 "Channel::DisableSRTPSend()");
4106
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004107 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004108
4109 if (!_encrypting)
4110 {
4111 _engineStatisticsPtr->SetLastError(
4112 VE_INVALID_OPERATION, kTraceWarning,
4113 "DisableSRTPSend() SRTP encryption already disabled");
4114 return 0;
4115 }
4116
4117 _encrypting = false;
4118
4119 if (_srtpModule.DisableSRTPEncrypt() == -1)
4120 {
4121 _engineStatisticsPtr->SetLastError(
4122 VE_SRTP_ERROR, kTraceError,
4123 "DisableSRTPSend() failed to disable SRTP encryption");
4124 return -1;
4125 }
4126
4127 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4128 {
4129 // Both directions are disabled
4130 _encryptionPtr = NULL;
4131 }
4132
4133 return 0;
4134}
4135
4136int
4137Channel::EnableSRTPReceive(
4138 CipherTypes cipherType,
4139 int cipherKeyLength,
4140 AuthenticationTypes authType,
4141 int authKeyLength,
4142 int authTagLength,
4143 SecurityLevels level,
4144 const unsigned char key[kVoiceEngineMaxSrtpKeyLength],
4145 bool useForRTCP)
4146{
4147 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4148 "Channel::EnableSRTPReceive()");
4149
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004150 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004151
4152 if (_decrypting)
4153 {
4154 _engineStatisticsPtr->SetLastError(
4155 VE_INVALID_OPERATION, kTraceWarning,
4156 "EnableSRTPReceive() SRTP decryption already enabled");
4157 return -1;
4158 }
4159
4160 if (key == NULL)
4161 {
4162 _engineStatisticsPtr->SetLastError(
4163 VE_INVALID_ARGUMENT, kTraceWarning,
4164 "EnableSRTPReceive() invalid key string");
4165 return -1;
4166 }
4167
4168 if ((((kEncryption == level) ||
4169 (kEncryptionAndAuthentication == level)) &&
4170 ((cipherKeyLength < kVoiceEngineMinSrtpEncryptLength) ||
4171 (cipherKeyLength > kVoiceEngineMaxSrtpEncryptLength))) ||
4172 (((kAuthentication == level) ||
4173 (kEncryptionAndAuthentication == level)) &&
4174 (kAuthHmacSha1 == authType) &&
4175 ((authKeyLength > kVoiceEngineMaxSrtpAuthSha1Length) ||
4176 (authTagLength > kVoiceEngineMaxSrtpAuthSha1Length))) ||
4177 (((kAuthentication == level) ||
4178 (kEncryptionAndAuthentication == level)) &&
4179 (kAuthNull == authType) &&
4180 ((authKeyLength > kVoiceEngineMaxSrtpKeyAuthNullLength) ||
4181 (authTagLength > kVoiceEngineMaxSrtpTagAuthNullLength))))
4182 {
4183 _engineStatisticsPtr->SetLastError(
4184 VE_INVALID_ARGUMENT, kTraceError,
4185 "EnableSRTPReceive() invalid key length(s)");
4186 return -1;
4187 }
4188
4189 if (_srtpModule.EnableSRTPDecrypt(
4190 !useForRTCP,
4191 (SrtpModule::CipherTypes)cipherType,
4192 cipherKeyLength,
4193 (SrtpModule::AuthenticationTypes)authType,
4194 authKeyLength,
4195 authTagLength,
4196 (SrtpModule::SecurityLevels)level,
4197 key) == -1)
4198 {
4199 _engineStatisticsPtr->SetLastError(
4200 VE_SRTP_ERROR, kTraceError,
4201 "EnableSRTPReceive() failed to enable SRTP decryption");
4202 return -1;
4203 }
4204
4205 if (_encryptionPtr == NULL)
4206 {
4207 _encryptionPtr = &_srtpModule;
4208 }
4209
4210 _decrypting = true;
4211
4212 return 0;
4213}
4214
4215int
4216Channel::DisableSRTPReceive()
4217{
4218 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4219 "Channel::DisableSRTPReceive()");
4220
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004221 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004222
4223 if (!_decrypting)
4224 {
4225 _engineStatisticsPtr->SetLastError(
4226 VE_INVALID_OPERATION, kTraceWarning,
4227 "DisableSRTPReceive() SRTP decryption already disabled");
4228 return 0;
4229 }
4230
4231 _decrypting = false;
4232
4233 if (_srtpModule.DisableSRTPDecrypt() == -1)
4234 {
4235 _engineStatisticsPtr->SetLastError(
4236 VE_SRTP_ERROR, kTraceError,
4237 "DisableSRTPReceive() failed to disable SRTP decryption");
4238 return -1;
4239 }
4240
4241 if (!_srtpModule.SRTPDecrypt() && !_srtpModule.SRTPEncrypt())
4242 {
4243 _encryptionPtr = NULL;
4244 }
4245
4246 return 0;
4247}
4248
4249#endif
4250
4251int
4252Channel::RegisterExternalEncryption(Encryption& encryption)
4253{
4254 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4255 "Channel::RegisterExternalEncryption()");
4256
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004257 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004258
4259 if (_encryptionPtr)
4260 {
4261 _engineStatisticsPtr->SetLastError(
4262 VE_INVALID_OPERATION, kTraceError,
4263 "RegisterExternalEncryption() encryption already enabled");
4264 return -1;
4265 }
4266
4267 _encryptionPtr = &encryption;
4268
4269 _decrypting = true;
4270 _encrypting = true;
4271
4272 return 0;
4273}
4274
4275int
4276Channel::DeRegisterExternalEncryption()
4277{
4278 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4279 "Channel::DeRegisterExternalEncryption()");
4280
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004281 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004282
4283 if (!_encryptionPtr)
4284 {
4285 _engineStatisticsPtr->SetLastError(
4286 VE_INVALID_OPERATION, kTraceWarning,
4287 "DeRegisterExternalEncryption() encryption already disabled");
4288 return 0;
4289 }
4290
4291 _decrypting = false;
4292 _encrypting = false;
4293
4294 _encryptionPtr = NULL;
4295
4296 return 0;
4297}
4298
4299int Channel::SendTelephoneEventOutband(unsigned char eventCode,
4300 int lengthMs, int attenuationDb,
4301 bool playDtmfEvent)
4302{
4303 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4304 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
4305 playDtmfEvent);
4306
4307 _playOutbandDtmfEvent = playDtmfEvent;
4308
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004309 if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
niklase@google.com470e71d2011-07-07 08:21:25 +00004310 attenuationDb) != 0)
4311 {
4312 _engineStatisticsPtr->SetLastError(
4313 VE_SEND_DTMF_FAILED,
4314 kTraceWarning,
4315 "SendTelephoneEventOutband() failed to send event");
4316 return -1;
4317 }
4318 return 0;
4319}
4320
4321int Channel::SendTelephoneEventInband(unsigned char eventCode,
4322 int lengthMs,
4323 int attenuationDb,
4324 bool playDtmfEvent)
4325{
4326 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4327 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
4328 playDtmfEvent);
4329
4330 _playInbandDtmfEvent = playDtmfEvent;
4331 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
4332
4333 return 0;
4334}
4335
4336int
4337Channel::SetDtmfPlayoutStatus(bool enable)
4338{
4339 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4340 "Channel::SetDtmfPlayoutStatus()");
4341 if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
4342 {
4343 _engineStatisticsPtr->SetLastError(
4344 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
4345 "SetDtmfPlayoutStatus() failed to set Dtmf playout");
4346 return -1;
4347 }
4348 return 0;
4349}
4350
4351bool
4352Channel::DtmfPlayoutStatus() const
4353{
4354 return _audioCodingModule.DtmfPlayoutStatus();
4355}
4356
4357int
4358Channel::SetSendTelephoneEventPayloadType(unsigned char type)
4359{
4360 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4361 "Channel::SetSendTelephoneEventPayloadType()");
andrew@webrtc.orgf81f9f82011-08-19 22:56:22 +00004362 if (type > 127)
niklase@google.com470e71d2011-07-07 08:21:25 +00004363 {
4364 _engineStatisticsPtr->SetLastError(
4365 VE_INVALID_ARGUMENT, kTraceError,
4366 "SetSendTelephoneEventPayloadType() invalid type");
4367 return -1;
4368 }
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +00004369 CodecInst codec;
4370 codec.plfreq = 8000;
4371 codec.pltype = type;
4372 memcpy(codec.plname, "telephone-event", 16);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004373 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004374 {
4375 _engineStatisticsPtr->SetLastError(
4376 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4377 "SetSendTelephoneEventPayloadType() failed to register send"
4378 "payload type");
4379 return -1;
4380 }
4381 _sendTelephoneEventPayloadType = type;
4382 return 0;
4383}
4384
4385int
4386Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
4387{
4388 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4389 "Channel::GetSendTelephoneEventPayloadType()");
4390 type = _sendTelephoneEventPayloadType;
4391 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4392 VoEId(_instanceId,_channelId),
4393 "GetSendTelephoneEventPayloadType() => type=%u", type);
4394 return 0;
4395}
4396
niklase@google.com470e71d2011-07-07 08:21:25 +00004397int
4398Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
4399{
4400 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4401 "Channel::UpdateRxVadDetection()");
4402
4403 int vadDecision = 1;
4404
andrew@webrtc.org63a50982012-05-02 23:56:37 +00004405 vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00004406
4407 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
4408 {
4409 OnRxVadDetected(vadDecision);
4410 _oldVadDecision = vadDecision;
4411 }
4412
4413 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4414 "Channel::UpdateRxVadDetection() => vadDecision=%d",
4415 vadDecision);
4416 return 0;
4417}
4418
4419int
4420Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
4421{
4422 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4423 "Channel::RegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004424 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004425
4426 if (_rxVadObserverPtr)
4427 {
4428 _engineStatisticsPtr->SetLastError(
4429 VE_INVALID_OPERATION, kTraceError,
4430 "RegisterRxVadObserver() observer already enabled");
4431 return -1;
4432 }
niklase@google.com470e71d2011-07-07 08:21:25 +00004433 _rxVadObserverPtr = &observer;
4434 _RxVadDetection = true;
4435 return 0;
4436}
4437
4438int
4439Channel::DeRegisterRxVadObserver()
4440{
4441 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4442 "Channel::DeRegisterRxVadObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004443 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004444
4445 if (!_rxVadObserverPtr)
4446 {
4447 _engineStatisticsPtr->SetLastError(
4448 VE_INVALID_OPERATION, kTraceWarning,
4449 "DeRegisterRxVadObserver() observer already disabled");
4450 return 0;
4451 }
4452 _rxVadObserverPtr = NULL;
4453 _RxVadDetection = false;
4454 return 0;
4455}
4456
4457int
4458Channel::VoiceActivityIndicator(int &activity)
4459{
4460 activity = _sendFrameType;
4461
4462 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4463 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
4464 return 0;
4465}
4466
4467#ifdef WEBRTC_VOICE_ENGINE_AGC
4468
4469int
4470Channel::SetRxAgcStatus(const bool enable, const AgcModes mode)
4471{
4472 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4473 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
4474 (int)enable, (int)mode);
4475
4476 GainControl::Mode agcMode(GainControl::kFixedDigital);
4477 switch (mode)
4478 {
4479 case kAgcDefault:
4480 agcMode = GainControl::kAdaptiveDigital;
4481 break;
4482 case kAgcUnchanged:
4483 agcMode = _rxAudioProcessingModulePtr->gain_control()->mode();
4484 break;
4485 case kAgcFixedDigital:
4486 agcMode = GainControl::kFixedDigital;
4487 break;
4488 case kAgcAdaptiveDigital:
4489 agcMode =GainControl::kAdaptiveDigital;
4490 break;
4491 default:
4492 _engineStatisticsPtr->SetLastError(
4493 VE_INVALID_ARGUMENT, kTraceError,
4494 "SetRxAgcStatus() invalid Agc mode");
4495 return -1;
4496 }
4497
4498 if (_rxAudioProcessingModulePtr->gain_control()->set_mode(agcMode) != 0)
4499 {
4500 _engineStatisticsPtr->SetLastError(
4501 VE_APM_ERROR, kTraceError,
4502 "SetRxAgcStatus() failed to set Agc mode");
4503 return -1;
4504 }
4505 if (_rxAudioProcessingModulePtr->gain_control()->Enable(enable) != 0)
4506 {
4507 _engineStatisticsPtr->SetLastError(
4508 VE_APM_ERROR, kTraceError,
4509 "SetRxAgcStatus() failed to set Agc state");
4510 return -1;
4511 }
4512
4513 _rxAgcIsEnabled = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +00004514 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4515
4516 return 0;
4517}
4518
4519int
4520Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
4521{
4522 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4523 "Channel::GetRxAgcStatus(enable=?, mode=?)");
4524
4525 bool enable = _rxAudioProcessingModulePtr->gain_control()->is_enabled();
4526 GainControl::Mode agcMode =
4527 _rxAudioProcessingModulePtr->gain_control()->mode();
4528
4529 enabled = enable;
4530
4531 switch (agcMode)
4532 {
4533 case GainControl::kFixedDigital:
4534 mode = kAgcFixedDigital;
4535 break;
4536 case GainControl::kAdaptiveDigital:
4537 mode = kAgcAdaptiveDigital;
4538 break;
4539 default:
4540 _engineStatisticsPtr->SetLastError(
4541 VE_APM_ERROR, kTraceError,
4542 "GetRxAgcStatus() invalid Agc mode");
4543 return -1;
4544 }
4545
4546 return 0;
4547}
4548
4549int
4550Channel::SetRxAgcConfig(const AgcConfig config)
4551{
4552 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4553 "Channel::SetRxAgcConfig()");
4554
4555 if (_rxAudioProcessingModulePtr->gain_control()->set_target_level_dbfs(
4556 config.targetLeveldBOv) != 0)
4557 {
4558 _engineStatisticsPtr->SetLastError(
4559 VE_APM_ERROR, kTraceError,
4560 "SetRxAgcConfig() failed to set target peak |level|"
4561 "(or envelope) of the Agc");
4562 return -1;
4563 }
4564 if (_rxAudioProcessingModulePtr->gain_control()->set_compression_gain_db(
4565 config.digitalCompressionGaindB) != 0)
4566 {
4567 _engineStatisticsPtr->SetLastError(
4568 VE_APM_ERROR, kTraceError,
4569 "SetRxAgcConfig() failed to set the range in |gain| the"
4570 " digital compression stage may apply");
4571 return -1;
4572 }
4573 if (_rxAudioProcessingModulePtr->gain_control()->enable_limiter(
4574 config.limiterEnable) != 0)
4575 {
4576 _engineStatisticsPtr->SetLastError(
4577 VE_APM_ERROR, kTraceError,
4578 "SetRxAgcConfig() failed to set hard limiter to the signal");
4579 return -1;
4580 }
4581
4582 return 0;
4583}
4584
4585int
4586Channel::GetRxAgcConfig(AgcConfig& config)
4587{
4588 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4589 "Channel::GetRxAgcConfig(config=%?)");
4590
4591 config.targetLeveldBOv =
4592 _rxAudioProcessingModulePtr->gain_control()->target_level_dbfs();
4593 config.digitalCompressionGaindB =
4594 _rxAudioProcessingModulePtr->gain_control()->compression_gain_db();
4595 config.limiterEnable =
4596 _rxAudioProcessingModulePtr->gain_control()->is_limiter_enabled();
4597
4598 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4599 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
4600 "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
4601 " limiterEnable=%d",
4602 config.targetLeveldBOv,
4603 config.digitalCompressionGaindB,
4604 config.limiterEnable);
4605
4606 return 0;
4607}
4608
4609#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
4610
4611#ifdef WEBRTC_VOICE_ENGINE_NR
4612
4613int
4614Channel::SetRxNsStatus(const bool enable, const NsModes mode)
4615{
4616 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4617 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
4618 (int)enable, (int)mode);
4619
4620 NoiseSuppression::Level nsLevel(
4621 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
4622 switch (mode)
4623 {
4624
4625 case kNsDefault:
4626 nsLevel = (NoiseSuppression::Level)
4627 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
4628 break;
4629 case kNsUnchanged:
4630 nsLevel = _rxAudioProcessingModulePtr->noise_suppression()->level();
4631 break;
4632 case kNsConference:
4633 nsLevel = NoiseSuppression::kHigh;
4634 break;
4635 case kNsLowSuppression:
4636 nsLevel = NoiseSuppression::kLow;
4637 break;
4638 case kNsModerateSuppression:
4639 nsLevel = NoiseSuppression::kModerate;
4640 break;
4641 case kNsHighSuppression:
4642 nsLevel = NoiseSuppression::kHigh;
4643 break;
4644 case kNsVeryHighSuppression:
4645 nsLevel = NoiseSuppression::kVeryHigh;
4646 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004647 }
4648
4649 if (_rxAudioProcessingModulePtr->noise_suppression()->set_level(nsLevel)
4650 != 0)
4651 {
4652 _engineStatisticsPtr->SetLastError(
4653 VE_APM_ERROR, kTraceError,
4654 "SetRxAgcStatus() failed to set Ns level");
4655 return -1;
4656 }
4657 if (_rxAudioProcessingModulePtr->noise_suppression()->Enable(enable) != 0)
4658 {
4659 _engineStatisticsPtr->SetLastError(
4660 VE_APM_ERROR, kTraceError,
4661 "SetRxAgcStatus() failed to set Agc state");
4662 return -1;
4663 }
4664
4665 _rxNsIsEnabled = enable;
4666 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
4667
4668 return 0;
4669}
4670
4671int
4672Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
4673{
4674 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4675 "Channel::GetRxNsStatus(enable=?, mode=?)");
4676
4677 bool enable =
4678 _rxAudioProcessingModulePtr->noise_suppression()->is_enabled();
4679 NoiseSuppression::Level ncLevel =
4680 _rxAudioProcessingModulePtr->noise_suppression()->level();
4681
4682 enabled = enable;
4683
4684 switch (ncLevel)
4685 {
4686 case NoiseSuppression::kLow:
4687 mode = kNsLowSuppression;
4688 break;
4689 case NoiseSuppression::kModerate:
4690 mode = kNsModerateSuppression;
4691 break;
4692 case NoiseSuppression::kHigh:
4693 mode = kNsHighSuppression;
4694 break;
4695 case NoiseSuppression::kVeryHigh:
4696 mode = kNsVeryHighSuppression;
4697 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00004698 }
4699
4700 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4701 VoEId(_instanceId,_channelId),
4702 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
4703 return 0;
4704}
4705
4706#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
4707
4708int
4709Channel::RegisterRTPObserver(VoERTPObserver& observer)
4710{
4711 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4712 "Channel::RegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004713 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004714
4715 if (_rtpObserverPtr)
4716 {
4717 _engineStatisticsPtr->SetLastError(
4718 VE_INVALID_OPERATION, kTraceError,
4719 "RegisterRTPObserver() observer already enabled");
4720 return -1;
4721 }
4722
4723 _rtpObserverPtr = &observer;
4724 _rtpObserver = true;
4725
4726 return 0;
4727}
4728
4729int
4730Channel::DeRegisterRTPObserver()
4731{
4732 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4733 "Channel::DeRegisterRTPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004734 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004735
4736 if (!_rtpObserverPtr)
4737 {
4738 _engineStatisticsPtr->SetLastError(
4739 VE_INVALID_OPERATION, kTraceWarning,
4740 "DeRegisterRTPObserver() observer already disabled");
4741 return 0;
4742 }
4743
4744 _rtpObserver = false;
4745 _rtpObserverPtr = NULL;
4746
4747 return 0;
4748}
4749
4750int
4751Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
4752{
4753 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4754 "Channel::RegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004755 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004756
4757 if (_rtcpObserverPtr)
4758 {
4759 _engineStatisticsPtr->SetLastError(
4760 VE_INVALID_OPERATION, kTraceError,
4761 "RegisterRTCPObserver() observer already enabled");
4762 return -1;
4763 }
4764
4765 _rtcpObserverPtr = &observer;
4766 _rtcpObserver = true;
4767
4768 return 0;
4769}
4770
4771int
4772Channel::DeRegisterRTCPObserver()
4773{
4774 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4775 "Channel::DeRegisterRTCPObserver()");
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00004776 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00004777
4778 if (!_rtcpObserverPtr)
4779 {
4780 _engineStatisticsPtr->SetLastError(
4781 VE_INVALID_OPERATION, kTraceWarning,
4782 "DeRegisterRTCPObserver() observer already disabled");
4783 return 0;
4784 }
4785
4786 _rtcpObserver = false;
4787 _rtcpObserverPtr = NULL;
4788
4789 return 0;
4790}
4791
4792int
4793Channel::SetLocalSSRC(unsigned int ssrc)
4794{
4795 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4796 "Channel::SetLocalSSRC()");
4797 if (_sending)
4798 {
4799 _engineStatisticsPtr->SetLastError(
4800 VE_ALREADY_SENDING, kTraceError,
4801 "SetLocalSSRC() already sending");
4802 return -1;
4803 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004804 if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004805 {
4806 _engineStatisticsPtr->SetLastError(
4807 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4808 "SetLocalSSRC() failed to set SSRC");
4809 return -1;
4810 }
4811 return 0;
4812}
4813
4814int
4815Channel::GetLocalSSRC(unsigned int& ssrc)
4816{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004817 ssrc = _rtpRtcpModule->SSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00004818 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4819 VoEId(_instanceId,_channelId),
4820 "GetLocalSSRC() => ssrc=%lu", ssrc);
4821 return 0;
4822}
4823
4824int
4825Channel::GetRemoteSSRC(unsigned int& ssrc)
4826{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004827 ssrc = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00004828 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4829 VoEId(_instanceId,_channelId),
4830 "GetRemoteSSRC() => ssrc=%lu", ssrc);
4831 return 0;
4832}
4833
4834int
4835Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
4836{
4837 if (arrCSRC == NULL)
4838 {
4839 _engineStatisticsPtr->SetLastError(
4840 VE_INVALID_ARGUMENT, kTraceError,
4841 "GetRemoteCSRCs() invalid array argument");
4842 return -1;
4843 }
4844 WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize];
4845 WebRtc_Word32 CSRCs(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004846 CSRCs = _rtpRtcpModule->CSRCs(arrOfCSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00004847 if (CSRCs > 0)
4848 {
4849 memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(WebRtc_UWord32));
4850 for (int i = 0; i < (int) CSRCs; i++)
4851 {
4852 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4853 VoEId(_instanceId, _channelId),
4854 "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
4855 }
4856 } else
4857 {
4858 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4859 VoEId(_instanceId, _channelId),
4860 "GetRemoteCSRCs() => list is empty!");
4861 }
4862 return CSRCs;
4863}
4864
4865int
4866Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
4867{
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00004868 if (_rtpAudioProc.get() == NULL)
4869 {
4870 _rtpAudioProc.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
4871 _channelId)));
4872 if (_rtpAudioProc.get() == NULL)
4873 {
4874 _engineStatisticsPtr->SetLastError(VE_NO_MEMORY, kTraceCritical,
4875 "Failed to create AudioProcessing");
4876 return -1;
4877 }
4878 }
4879
4880 if (_rtpAudioProc->level_estimator()->Enable(enable) !=
4881 AudioProcessing::kNoError)
4882 {
4883 _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceWarning,
4884 "Failed to enable AudioProcessing::level_estimator()");
4885 }
4886
niklase@google.com470e71d2011-07-07 08:21:25 +00004887 _includeAudioLevelIndication = enable;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004888 return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
niklase@google.com470e71d2011-07-07 08:21:25 +00004889}
4890int
4891Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
4892{
4893 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4894 VoEId(_instanceId,_channelId),
4895 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
4896 enabled, ID);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004897 return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
niklase@google.com470e71d2011-07-07 08:21:25 +00004898}
4899
4900int
4901Channel::SetRTCPStatus(bool enable)
4902{
4903 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4904 "Channel::SetRTCPStatus()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004905 if (_rtpRtcpModule->SetRTCPStatus(enable ?
niklase@google.com470e71d2011-07-07 08:21:25 +00004906 kRtcpCompound : kRtcpOff) != 0)
4907 {
4908 _engineStatisticsPtr->SetLastError(
4909 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4910 "SetRTCPStatus() failed to set RTCP status");
4911 return -1;
4912 }
4913 return 0;
4914}
4915
4916int
4917Channel::GetRTCPStatus(bool& enabled)
4918{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004919 RTCPMethod method = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00004920 enabled = (method != kRtcpOff);
4921 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4922 VoEId(_instanceId,_channelId),
4923 "GetRTCPStatus() => enabled=%d", enabled);
4924 return 0;
4925}
4926
4927int
4928Channel::SetRTCP_CNAME(const char cName[256])
4929{
4930 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4931 "Channel::SetRTCP_CNAME()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004932 if (_rtpRtcpModule->SetCNAME(cName) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004933 {
4934 _engineStatisticsPtr->SetLastError(
4935 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4936 "SetRTCP_CNAME() failed to set RTCP CNAME");
4937 return -1;
4938 }
4939 return 0;
4940}
4941
4942int
4943Channel::GetRTCP_CNAME(char cName[256])
4944{
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004945 if (_rtpRtcpModule->CNAME(cName) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004946 {
4947 _engineStatisticsPtr->SetLastError(
4948 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4949 "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
4950 return -1;
4951 }
4952 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4953 VoEId(_instanceId, _channelId),
4954 "GetRTCP_CNAME() => cName=%s", cName);
4955 return 0;
4956}
4957
4958int
4959Channel::GetRemoteRTCP_CNAME(char cName[256])
4960{
4961 if (cName == NULL)
4962 {
4963 _engineStatisticsPtr->SetLastError(
4964 VE_INVALID_ARGUMENT, kTraceError,
4965 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
4966 return -1;
4967 }
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00004968 char cname[RTCP_CNAME_SIZE];
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004969 const WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
4970 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004971 {
4972 _engineStatisticsPtr->SetLastError(
4973 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
4974 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
4975 return -1;
4976 }
4977 strcpy(cName, cname);
4978 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4979 VoEId(_instanceId, _channelId),
4980 "GetRemoteRTCP_CNAME() => cName=%s", cName);
4981 return 0;
4982}
4983
4984int
4985Channel::GetRemoteRTCPData(
4986 unsigned int& NTPHigh,
4987 unsigned int& NTPLow,
4988 unsigned int& timestamp,
4989 unsigned int& playoutTimestamp,
4990 unsigned int* jitter,
4991 unsigned short* fractionLost)
4992{
4993 // --- Information from sender info in received Sender Reports
4994
4995 RTCPSenderInfo senderInfo;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00004996 if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00004997 {
4998 _engineStatisticsPtr->SetLastError(
4999 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005000 "GetRemoteRTCPData() failed to retrieve sender info for remote "
niklase@google.com470e71d2011-07-07 08:21:25 +00005001 "side");
5002 return -1;
5003 }
5004
5005 // We only utilize 12 out of 20 bytes in the sender info (ignores packet
5006 // and octet count)
5007 NTPHigh = senderInfo.NTPseconds;
5008 NTPLow = senderInfo.NTPfraction;
5009 timestamp = senderInfo.RTPtimeStamp;
5010
5011 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5012 VoEId(_instanceId, _channelId),
5013 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
5014 "timestamp=%lu",
5015 NTPHigh, NTPLow, timestamp);
5016
5017 // --- Locally derived information
5018
5019 // This value is updated on each incoming RTCP packet (0 when no packet
5020 // has been received)
5021 playoutTimestamp = _playoutTimeStampRTCP;
5022
5023 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5024 VoEId(_instanceId, _channelId),
5025 "GetRemoteRTCPData() => playoutTimestamp=%lu",
5026 _playoutTimeStampRTCP);
5027
5028 if (NULL != jitter || NULL != fractionLost)
5029 {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005030 // Get all RTCP receiver report blocks that have been received on this
5031 // channel. If we receive RTP packets from a remote source we know the
5032 // remote SSRC and use the report block from him.
5033 // Otherwise use the first report block.
5034 std::vector<RTCPReportBlock> remote_stats;
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005035 if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005036 remote_stats.empty()) {
5037 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5038 VoEId(_instanceId, _channelId),
5039 "GetRemoteRTCPData() failed to measure statistics due"
5040 " to lack of received RTP and/or RTCP packets");
5041 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00005042 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005043
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005044 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005045 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
5046 for (; it != remote_stats.end(); ++it) {
5047 if (it->remoteSSRC == remoteSSRC)
5048 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00005049 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005050
5051 if (it == remote_stats.end()) {
5052 // If we have not received any RTCP packets from this SSRC it probably
5053 // means that we have not received any RTP packets.
5054 // Use the first received report block instead.
5055 it = remote_stats.begin();
5056 remoteSSRC = it->remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00005057 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005058
xians@webrtc.org79af7342012-01-31 12:22:14 +00005059 if (jitter) {
5060 *jitter = it->jitter;
5061 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5062 VoEId(_instanceId, _channelId),
5063 "GetRemoteRTCPData() => jitter = %lu", *jitter);
5064 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +00005065
xians@webrtc.org79af7342012-01-31 12:22:14 +00005066 if (fractionLost) {
5067 *fractionLost = it->fractionLost;
5068 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5069 VoEId(_instanceId, _channelId),
5070 "GetRemoteRTCPData() => fractionLost = %lu",
5071 *fractionLost);
5072 }
niklase@google.com470e71d2011-07-07 08:21:25 +00005073 }
5074 return 0;
5075}
5076
5077int
5078Channel::SendApplicationDefinedRTCPPacket(const unsigned char subType,
5079 unsigned int name,
5080 const char* data,
5081 unsigned short dataLengthInBytes)
5082{
5083 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5084 "Channel::SendApplicationDefinedRTCPPacket()");
5085 if (!_sending)
5086 {
5087 _engineStatisticsPtr->SetLastError(
5088 VE_NOT_SENDING, kTraceError,
5089 "SendApplicationDefinedRTCPPacket() not sending");
5090 return -1;
5091 }
5092 if (NULL == data)
5093 {
5094 _engineStatisticsPtr->SetLastError(
5095 VE_INVALID_ARGUMENT, kTraceError,
5096 "SendApplicationDefinedRTCPPacket() invalid data value");
5097 return -1;
5098 }
5099 if (dataLengthInBytes % 4 != 0)
5100 {
5101 _engineStatisticsPtr->SetLastError(
5102 VE_INVALID_ARGUMENT, kTraceError,
5103 "SendApplicationDefinedRTCPPacket() invalid length value");
5104 return -1;
5105 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005106 RTCPMethod status = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00005107 if (status == kRtcpOff)
5108 {
5109 _engineStatisticsPtr->SetLastError(
5110 VE_RTCP_ERROR, kTraceError,
5111 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
5112 return -1;
5113 }
5114
5115 // Create and schedule the RTCP APP packet for transmission
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005116 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
niklase@google.com470e71d2011-07-07 08:21:25 +00005117 subType,
5118 name,
5119 (const unsigned char*) data,
5120 dataLengthInBytes) != 0)
5121 {
5122 _engineStatisticsPtr->SetLastError(
5123 VE_SEND_ERROR, kTraceError,
5124 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
5125 return -1;
5126 }
5127 return 0;
5128}
5129
5130int
5131Channel::GetRTPStatistics(
5132 unsigned int& averageJitterMs,
5133 unsigned int& maxJitterMs,
5134 unsigned int& discardedPackets)
5135{
5136 WebRtc_UWord8 fraction_lost(0);
5137 WebRtc_UWord32 cum_lost(0);
5138 WebRtc_UWord32 ext_max(0);
5139 WebRtc_UWord32 jitter(0);
5140 WebRtc_UWord32 max_jitter(0);
5141
5142 // The jitter statistics is updated for each received RTP packet and is
5143 // based on received packets.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005144 if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
niklase@google.com470e71d2011-07-07 08:21:25 +00005145 &cum_lost,
5146 &ext_max,
5147 &jitter,
5148 &max_jitter) != 0)
5149 {
5150 _engineStatisticsPtr->SetLastError(
5151 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005152 "GetRTPStatistics() failed to read RTP statistics from the "
niklase@google.com470e71d2011-07-07 08:21:25 +00005153 "RTP/RTCP module");
5154 }
5155
5156 const WebRtc_Word32 playoutFrequency =
5157 _audioCodingModule.PlayoutFrequency();
5158 if (playoutFrequency > 0)
5159 {
5160 // Scale RTP statistics given the current playout frequency
5161 maxJitterMs = max_jitter / (playoutFrequency / 1000);
5162 averageJitterMs = jitter / (playoutFrequency / 1000);
5163 }
5164
5165 discardedPackets = _numberOfDiscardedPackets;
5166
5167 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5168 VoEId(_instanceId, _channelId),
5169 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005170 " discardedPackets = %lu)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005171 averageJitterMs, maxJitterMs, discardedPackets);
5172 return 0;
5173}
5174
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00005175int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
5176 if (sender_info == NULL) {
5177 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5178 "GetRemoteRTCPSenderInfo() invalid sender_info.");
5179 return -1;
5180 }
5181
5182 // Get the sender info from the latest received RTCP Sender Report.
5183 RTCPSenderInfo rtcp_sender_info;
5184 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
5185 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5186 "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
5187 return -1;
5188 }
5189
5190 sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
5191 sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
5192 sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
5193 sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
5194 sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
5195 return 0;
5196}
5197
5198int Channel::GetRemoteRTCPReportBlocks(
5199 std::vector<ReportBlock>* report_blocks) {
5200 if (report_blocks == NULL) {
5201 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
5202 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
5203 return -1;
5204 }
5205
5206 // Get the report blocks from the latest received RTCP Sender or Receiver
5207 // Report. Each element in the vector contains the sender's SSRC and a
5208 // report block according to RFC 3550.
5209 std::vector<RTCPReportBlock> rtcp_report_blocks;
5210 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
5211 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5212 "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
5213 return -1;
5214 }
5215
5216 if (rtcp_report_blocks.empty())
5217 return 0;
5218
5219 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
5220 for (; it != rtcp_report_blocks.end(); ++it) {
5221 ReportBlock report_block;
5222 report_block.sender_SSRC = it->remoteSSRC;
5223 report_block.source_SSRC = it->sourceSSRC;
5224 report_block.fraction_lost = it->fractionLost;
5225 report_block.cumulative_num_packets_lost = it->cumulativeLost;
5226 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
5227 report_block.interarrival_jitter = it->jitter;
5228 report_block.last_SR_timestamp = it->lastSR;
5229 report_block.delay_since_last_SR = it->delaySinceLastSR;
5230 report_blocks->push_back(report_block);
5231 }
5232 return 0;
5233}
5234
niklase@google.com470e71d2011-07-07 08:21:25 +00005235int
5236Channel::GetRTPStatistics(CallStatistics& stats)
5237{
5238 WebRtc_UWord8 fraction_lost(0);
5239 WebRtc_UWord32 cum_lost(0);
5240 WebRtc_UWord32 ext_max(0);
5241 WebRtc_UWord32 jitter(0);
5242 WebRtc_UWord32 max_jitter(0);
5243
5244 // --- Part one of the final structure (four values)
5245
5246 // The jitter statistics is updated for each received RTP packet and is
5247 // based on received packets.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005248 if (_rtpRtcpModule->StatisticsRTP(&fraction_lost,
niklase@google.com470e71d2011-07-07 08:21:25 +00005249 &cum_lost,
5250 &ext_max,
5251 &jitter,
5252 &max_jitter) != 0)
5253 {
5254 _engineStatisticsPtr->SetLastError(
5255 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
5256 "GetRTPStatistics() failed to read RTP statistics from the "
5257 "RTP/RTCP module");
5258 }
5259
5260 stats.fractionLost = fraction_lost;
5261 stats.cumulativeLost = cum_lost;
5262 stats.extendedMax = ext_max;
5263 stats.jitterSamples = jitter;
5264
5265 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5266 VoEId(_instanceId, _channelId),
5267 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005268 " extendedMax=%lu, jitterSamples=%li)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005269 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
5270 stats.jitterSamples);
5271
5272 // --- Part two of the final structure (one value)
5273
5274 WebRtc_UWord16 RTT(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005275 RTCPMethod method = _rtpRtcpModule->RTCP();
niklase@google.com470e71d2011-07-07 08:21:25 +00005276 if (method == kRtcpOff)
5277 {
5278 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5279 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005280 "GetRTPStatistics() RTCP is disabled => valid RTT "
niklase@google.com470e71d2011-07-07 08:21:25 +00005281 "measurements cannot be retrieved");
5282 } else
5283 {
5284 // The remote SSRC will be zero if no RTP packet has been received.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005285 WebRtc_UWord32 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00005286 if (remoteSSRC > 0)
5287 {
5288 WebRtc_UWord16 avgRTT(0);
5289 WebRtc_UWord16 maxRTT(0);
5290 WebRtc_UWord16 minRTT(0);
5291
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005292 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
niklase@google.com470e71d2011-07-07 08:21:25 +00005293 != 0)
5294 {
5295 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5296 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005297 "GetRTPStatistics() failed to retrieve RTT from "
niklase@google.com470e71d2011-07-07 08:21:25 +00005298 "the RTP/RTCP module");
5299 }
5300 } else
5301 {
5302 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5303 VoEId(_instanceId, _channelId),
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005304 "GetRTPStatistics() failed to measure RTT since no "
niklase@google.com470e71d2011-07-07 08:21:25 +00005305 "RTP packets have been received yet");
5306 }
5307 }
5308
5309 stats.rttMs = static_cast<int> (RTT);
5310
5311 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5312 VoEId(_instanceId, _channelId),
5313 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
5314
5315 // --- Part three of the final structure (four values)
5316
5317 WebRtc_UWord32 bytesSent(0);
5318 WebRtc_UWord32 packetsSent(0);
5319 WebRtc_UWord32 bytesReceived(0);
5320 WebRtc_UWord32 packetsReceived(0);
5321
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005322 if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
niklase@google.com470e71d2011-07-07 08:21:25 +00005323 &packetsSent,
5324 &bytesReceived,
5325 &packetsReceived) != 0)
5326 {
5327 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5328 VoEId(_instanceId, _channelId),
5329 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005330 " output will not be complete");
niklase@google.com470e71d2011-07-07 08:21:25 +00005331 }
5332
5333 stats.bytesSent = bytesSent;
5334 stats.packetsSent = packetsSent;
5335 stats.bytesReceived = bytesReceived;
5336 stats.packetsReceived = packetsReceived;
5337
5338 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5339 VoEId(_instanceId, _channelId),
5340 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00005341 " bytesReceived=%d, packetsReceived=%d)",
niklase@google.com470e71d2011-07-07 08:21:25 +00005342 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
5343 stats.packetsReceived);
5344
5345 return 0;
5346}
5347
turaj@webrtc.org42259e72012-12-11 02:15:12 +00005348int Channel::SetFECStatus(bool enable, int redPayloadtype) {
5349 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5350 "Channel::SetFECStatus()");
niklase@google.com470e71d2011-07-07 08:21:25 +00005351
turaj@webrtc.org8c8ad852013-01-31 18:20:17 +00005352 if (enable) {
5353 if (redPayloadtype < 0 || redPayloadtype > 127) {
5354 _engineStatisticsPtr->SetLastError(
5355 VE_PLTYPE_ERROR, kTraceError,
5356 "SetFECStatus() invalid RED payload type");
5357 return -1;
5358 }
5359
5360 if (SetRedPayloadType(redPayloadtype) < 0) {
5361 _engineStatisticsPtr->SetLastError(
5362 VE_CODEC_ERROR, kTraceError,
5363 "SetSecondarySendCodec() Failed to register RED ACM");
5364 return -1;
5365 }
turaj@webrtc.org42259e72012-12-11 02:15:12 +00005366 }
niklase@google.com470e71d2011-07-07 08:21:25 +00005367
turaj@webrtc.org42259e72012-12-11 02:15:12 +00005368 if (_audioCodingModule.SetFECStatus(enable) != 0) {
5369 _engineStatisticsPtr->SetLastError(
5370 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5371 "SetFECStatus() failed to set FEC state in the ACM");
5372 return -1;
5373 }
5374 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00005375}
5376
5377int
5378Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
5379{
5380 enabled = _audioCodingModule.FECStatus();
5381 if (enabled)
5382 {
5383 WebRtc_Word8 payloadType(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005384 if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005385 {
5386 _engineStatisticsPtr->SetLastError(
5387 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5388 "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
5389 "module");
5390 return -1;
5391 }
5392 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5393 VoEId(_instanceId, _channelId),
5394 "GetFECStatus() => enabled=%d, redPayloadtype=%d",
5395 enabled, redPayloadtype);
5396 return 0;
5397 }
5398 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5399 VoEId(_instanceId, _channelId),
5400 "GetFECStatus() => enabled=%d", enabled);
5401 return 0;
5402}
5403
5404int
niklase@google.com470e71d2011-07-07 08:21:25 +00005405Channel::StartRTPDump(const char fileNameUTF8[1024],
5406 RTPDirections direction)
5407{
5408 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5409 "Channel::StartRTPDump()");
5410 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5411 {
5412 _engineStatisticsPtr->SetLastError(
5413 VE_INVALID_ARGUMENT, kTraceError,
5414 "StartRTPDump() invalid RTP direction");
5415 return -1;
5416 }
5417 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5418 &_rtpDumpIn : &_rtpDumpOut;
5419 if (rtpDumpPtr == NULL)
5420 {
5421 assert(false);
5422 return -1;
5423 }
5424 if (rtpDumpPtr->IsActive())
5425 {
5426 rtpDumpPtr->Stop();
5427 }
5428 if (rtpDumpPtr->Start(fileNameUTF8) != 0)
5429 {
5430 _engineStatisticsPtr->SetLastError(
5431 VE_BAD_FILE, kTraceError,
5432 "StartRTPDump() failed to create file");
5433 return -1;
5434 }
5435 return 0;
5436}
5437
5438int
5439Channel::StopRTPDump(RTPDirections direction)
5440{
5441 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5442 "Channel::StopRTPDump()");
5443 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
5444 {
5445 _engineStatisticsPtr->SetLastError(
5446 VE_INVALID_ARGUMENT, kTraceError,
5447 "StopRTPDump() invalid RTP direction");
5448 return -1;
5449 }
5450 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5451 &_rtpDumpIn : &_rtpDumpOut;
5452 if (rtpDumpPtr == NULL)
5453 {
5454 assert(false);
5455 return -1;
5456 }
5457 if (!rtpDumpPtr->IsActive())
5458 {
5459 return 0;
5460 }
5461 return rtpDumpPtr->Stop();
5462}
5463
5464bool
5465Channel::RTPDumpIsActive(RTPDirections direction)
5466{
5467 if ((direction != kRtpIncoming) &&
5468 (direction != kRtpOutgoing))
5469 {
5470 _engineStatisticsPtr->SetLastError(
5471 VE_INVALID_ARGUMENT, kTraceError,
5472 "RTPDumpIsActive() invalid RTP direction");
5473 return false;
5474 }
5475 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
5476 &_rtpDumpIn : &_rtpDumpOut;
5477 return rtpDumpPtr->IsActive();
5478}
5479
5480int
5481Channel::InsertExtraRTPPacket(unsigned char payloadType,
5482 bool markerBit,
5483 const char* payloadData,
5484 unsigned short payloadSize)
5485{
5486 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
5487 "Channel::InsertExtraRTPPacket()");
5488 if (payloadType > 127)
5489 {
5490 _engineStatisticsPtr->SetLastError(
5491 VE_INVALID_PLTYPE, kTraceError,
5492 "InsertExtraRTPPacket() invalid payload type");
5493 return -1;
5494 }
5495 if (payloadData == NULL)
5496 {
5497 _engineStatisticsPtr->SetLastError(
5498 VE_INVALID_ARGUMENT, kTraceError,
5499 "InsertExtraRTPPacket() invalid payload data");
5500 return -1;
5501 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005502 if (payloadSize > _rtpRtcpModule->MaxDataPayloadLength())
niklase@google.com470e71d2011-07-07 08:21:25 +00005503 {
5504 _engineStatisticsPtr->SetLastError(
5505 VE_INVALID_ARGUMENT, kTraceError,
5506 "InsertExtraRTPPacket() invalid payload size");
5507 return -1;
5508 }
5509 if (!_sending)
5510 {
5511 _engineStatisticsPtr->SetLastError(
5512 VE_NOT_SENDING, kTraceError,
5513 "InsertExtraRTPPacket() not sending");
5514 return -1;
5515 }
5516
5517 // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
5518 // Transport::SendPacket() will be called by the module when the RTP packet
5519 // is created.
5520 // The call to SendOutgoingData() does *not* modify the timestamp and
5521 // payloadtype to ensure that the RTP module generates a valid RTP packet
5522 // (user might utilize a non-registered payload type).
5523 // The marker bit and payload type will be replaced just before the actual
5524 // transmission, i.e., the actual modification is done *after* the RTP
5525 // module has delivered its RTP packet back to the VoE.
5526 // We will use the stored values above when the packet is modified
5527 // (see Channel::SendPacket()).
5528
5529 _extraPayloadType = payloadType;
5530 _extraMarkerBit = markerBit;
5531 _insertExtraRTPPacket = true;
5532
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005533 if (_rtpRtcpModule->SendOutgoingData(kAudioFrameSpeech,
niklase@google.com470e71d2011-07-07 08:21:25 +00005534 _lastPayloadType,
5535 _lastLocalTimeStamp,
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +00005536 // Leaving the time when this frame was
5537 // received from the capture device as
5538 // undefined for voice for now.
5539 -1,
niklase@google.com470e71d2011-07-07 08:21:25 +00005540 (const WebRtc_UWord8*) payloadData,
5541 payloadSize) != 0)
5542 {
5543 _engineStatisticsPtr->SetLastError(
5544 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5545 "InsertExtraRTPPacket() failed to send extra RTP packet");
5546 return -1;
5547 }
5548
5549 return 0;
5550}
5551
5552WebRtc_UWord32
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005553Channel::Demultiplex(const AudioFrame& audioFrame)
niklase@google.com470e71d2011-07-07 08:21:25 +00005554{
5555 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005556 "Channel::Demultiplex()");
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00005557 _audioFrame.CopyFrom(audioFrame);
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005558 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00005559 return 0;
5560}
5561
5562WebRtc_UWord32
xians@google.com0b0665a2011-08-08 08:18:44 +00005563Channel::PrepareEncodeAndSend(int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00005564{
5565 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5566 "Channel::PrepareEncodeAndSend()");
5567
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005568 if (_audioFrame.samples_per_channel_ == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005569 {
5570 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5571 "Channel::PrepareEncodeAndSend() invalid audio frame");
5572 return -1;
5573 }
5574
5575 if (_inputFilePlaying)
5576 {
5577 MixOrReplaceAudioWithFile(mixingFrequency);
5578 }
5579
5580 if (_mute)
5581 {
5582 AudioFrameOperations::Mute(_audioFrame);
5583 }
5584
5585 if (_inputExternalMedia)
5586 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005587 CriticalSectionScoped cs(&_callbackCritSect);
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005588 const bool isStereo = (_audioFrame.num_channels_ == 2);
niklase@google.com470e71d2011-07-07 08:21:25 +00005589 if (_inputExternalMediaCallbackPtr)
5590 {
5591 _inputExternalMediaCallbackPtr->Process(
5592 _channelId,
5593 kRecordingPerChannel,
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005594 (WebRtc_Word16*)_audioFrame.data_,
5595 _audioFrame.samples_per_channel_,
5596 _audioFrame.sample_rate_hz_,
niklase@google.com470e71d2011-07-07 08:21:25 +00005597 isStereo);
5598 }
5599 }
5600
5601 InsertInbandDtmfTone();
5602
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005603 if (_includeAudioLevelIndication)
5604 {
5605 assert(_rtpAudioProc.get() != NULL);
5606
5607 // Check if settings need to be updated.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005608 if (_rtpAudioProc->sample_rate_hz() != _audioFrame.sample_rate_hz_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005609 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005610 if (_rtpAudioProc->set_sample_rate_hz(_audioFrame.sample_rate_hz_) !=
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005611 AudioProcessing::kNoError)
5612 {
5613 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5614 VoEId(_instanceId, _channelId),
5615 "Error setting AudioProcessing sample rate");
5616 return -1;
5617 }
5618 }
5619
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005620 if (_rtpAudioProc->num_input_channels() != _audioFrame.num_channels_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005621 {
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005622 if (_rtpAudioProc->set_num_channels(_audioFrame.num_channels_,
5623 _audioFrame.num_channels_)
andrew@webrtc.org755b04a2011-11-15 16:57:56 +00005624 != AudioProcessing::kNoError)
5625 {
5626 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5627 VoEId(_instanceId, _channelId),
5628 "Error setting AudioProcessing channels");
5629 return -1;
5630 }
5631 }
5632
5633 // Performs level analysis only; does not affect the signal.
5634 _rtpAudioProc->ProcessStream(&_audioFrame);
5635 }
5636
niklase@google.com470e71d2011-07-07 08:21:25 +00005637 return 0;
5638}
5639
5640WebRtc_UWord32
5641Channel::EncodeAndSend()
5642{
5643 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5644 "Channel::EncodeAndSend()");
5645
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005646 assert(_audioFrame.num_channels_ <= 2);
5647 if (_audioFrame.samples_per_channel_ == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005648 {
5649 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5650 "Channel::EncodeAndSend() invalid audio frame");
5651 return -1;
5652 }
5653
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005654 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00005655
5656 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
5657
5658 // The ACM resamples internally.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005659 _audioFrame.timestamp_ = _timeStamp;
niklase@google.com470e71d2011-07-07 08:21:25 +00005660 if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
5661 {
5662 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
5663 "Channel::EncodeAndSend() ACM encoding failed");
5664 return -1;
5665 }
5666
andrew@webrtc.org63a50982012-05-02 23:56:37 +00005667 _timeStamp += _audioFrame.samples_per_channel_;
niklase@google.com470e71d2011-07-07 08:21:25 +00005668
5669 // --- Encode if complete frame is ready
5670
5671 // This call will trigger AudioPacketizationCallback::SendData if encoding
5672 // is done and payload is ready for packetization and transmission.
5673 return _audioCodingModule.Process();
5674}
5675
5676int Channel::RegisterExternalMediaProcessing(
5677 ProcessingTypes type,
5678 VoEMediaProcess& processObject)
5679{
5680 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5681 "Channel::RegisterExternalMediaProcessing()");
5682
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005683 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005684
5685 if (kPlaybackPerChannel == type)
5686 {
5687 if (_outputExternalMediaCallbackPtr)
5688 {
5689 _engineStatisticsPtr->SetLastError(
5690 VE_INVALID_OPERATION, kTraceError,
5691 "Channel::RegisterExternalMediaProcessing() "
5692 "output external media already enabled");
5693 return -1;
5694 }
5695 _outputExternalMediaCallbackPtr = &processObject;
5696 _outputExternalMedia = true;
5697 }
5698 else if (kRecordingPerChannel == type)
5699 {
5700 if (_inputExternalMediaCallbackPtr)
5701 {
5702 _engineStatisticsPtr->SetLastError(
5703 VE_INVALID_OPERATION, kTraceError,
5704 "Channel::RegisterExternalMediaProcessing() "
5705 "output external media already enabled");
5706 return -1;
5707 }
5708 _inputExternalMediaCallbackPtr = &processObject;
5709 _inputExternalMedia = true;
5710 }
5711 return 0;
5712}
5713
5714int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
5715{
5716 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5717 "Channel::DeRegisterExternalMediaProcessing()");
5718
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005719 CriticalSectionScoped cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005720
5721 if (kPlaybackPerChannel == type)
5722 {
5723 if (!_outputExternalMediaCallbackPtr)
5724 {
5725 _engineStatisticsPtr->SetLastError(
5726 VE_INVALID_OPERATION, kTraceWarning,
5727 "Channel::DeRegisterExternalMediaProcessing() "
5728 "output external media already disabled");
5729 return 0;
5730 }
5731 _outputExternalMedia = false;
5732 _outputExternalMediaCallbackPtr = NULL;
5733 }
5734 else if (kRecordingPerChannel == type)
5735 {
5736 if (!_inputExternalMediaCallbackPtr)
5737 {
5738 _engineStatisticsPtr->SetLastError(
5739 VE_INVALID_OPERATION, kTraceWarning,
5740 "Channel::DeRegisterExternalMediaProcessing() "
5741 "input external media already disabled");
5742 return 0;
5743 }
5744 _inputExternalMedia = false;
5745 _inputExternalMediaCallbackPtr = NULL;
5746 }
5747
5748 return 0;
5749}
5750
roosa@google.com1b60ceb2012-12-12 23:00:29 +00005751int Channel::SetExternalMixing(bool enabled) {
5752 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5753 "Channel::SetExternalMixing(enabled=%d)", enabled);
5754
5755 if (_playing)
5756 {
5757 _engineStatisticsPtr->SetLastError(
5758 VE_INVALID_OPERATION, kTraceError,
5759 "Channel::SetExternalMixing() "
5760 "external mixing cannot be changed while playing.");
5761 return -1;
5762 }
5763
5764 _externalMixing = enabled;
5765
5766 return 0;
5767}
5768
niklase@google.com470e71d2011-07-07 08:21:25 +00005769int
5770Channel::ResetRTCPStatistics()
5771{
5772 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5773 "Channel::ResetRTCPStatistics()");
5774 WebRtc_UWord32 remoteSSRC(0);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005775 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
5776 return _rtpRtcpModule->ResetRTT(remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00005777}
5778
5779int
5780Channel::GetRoundTripTimeSummary(StatVal& delaysMs) const
5781{
5782 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5783 "Channel::GetRoundTripTimeSummary()");
5784 // Override default module outputs for the case when RTCP is disabled.
5785 // This is done to ensure that we are backward compatible with the
5786 // VoiceEngine where we did not use RTP/RTCP module.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005787 if (!_rtpRtcpModule->RTCP())
niklase@google.com470e71d2011-07-07 08:21:25 +00005788 {
5789 delaysMs.min = -1;
5790 delaysMs.max = -1;
5791 delaysMs.average = -1;
5792 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5793 "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
5794 " valid RTT measurements cannot be retrieved");
5795 return 0;
5796 }
5797
5798 WebRtc_UWord32 remoteSSRC;
5799 WebRtc_UWord16 RTT;
5800 WebRtc_UWord16 avgRTT;
5801 WebRtc_UWord16 maxRTT;
5802 WebRtc_UWord16 minRTT;
5803 // The remote SSRC will be zero if no RTP packet has been received.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005804 remoteSSRC = _rtpRtcpModule->RemoteSSRC();
niklase@google.com470e71d2011-07-07 08:21:25 +00005805 if (remoteSSRC == 0)
5806 {
5807 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5808 "Channel::GetRoundTripTimeSummary() unable to measure RTT"
5809 " since no RTP packet has been received yet");
5810 }
5811
5812 // Retrieve RTT statistics from the RTP/RTCP module for the specified
5813 // channel and SSRC. The SSRC is required to parse out the correct source
5814 // in conference scenarios.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005815 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005816 {
5817 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5818 "GetRoundTripTimeSummary unable to retrieve RTT values"
5819 " from the RTCP layer");
5820 delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
5821 }
5822 else
5823 {
5824 delaysMs.min = minRTT;
5825 delaysMs.max = maxRTT;
5826 delaysMs.average = avgRTT;
5827 }
5828 return 0;
5829}
5830
5831int
5832Channel::GetNetworkStatistics(NetworkStatistics& stats)
5833{
5834 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5835 "Channel::GetNetworkStatistics()");
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00005836 ACMNetworkStatistics acm_stats;
5837 int return_value = _audioCodingModule.NetworkStatistics(&acm_stats);
5838 if (return_value >= 0) {
5839 memcpy(&stats, &acm_stats, sizeof(NetworkStatistics));
5840 }
5841 return return_value;
niklase@google.com470e71d2011-07-07 08:21:25 +00005842}
5843
5844int
niklase@google.com470e71d2011-07-07 08:21:25 +00005845Channel::GetDelayEstimate(int& delayMs) const
5846{
5847 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5848 "Channel::GetDelayEstimate()");
5849 delayMs = (_averageDelayMs + 5) / 10 + _recPacketDelayMs;
5850 return 0;
5851}
5852
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +00005853int Channel::SetInitialPlayoutDelay(int delay_ms)
5854{
5855 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5856 "Channel::SetInitialPlayoutDelay()");
5857 if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
5858 (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs))
5859 {
5860 _engineStatisticsPtr->SetLastError(
5861 VE_INVALID_ARGUMENT, kTraceError,
5862 "SetInitialPlayoutDelay() invalid min delay");
5863 return -1;
5864 }
5865 if (_audioCodingModule.SetInitialPlayoutDelay(delay_ms) != 0)
5866 {
5867 _engineStatisticsPtr->SetLastError(
5868 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5869 "SetInitialPlayoutDelay() failed to set min playout delay");
5870 return -1;
5871 }
5872 return 0;
5873}
5874
5875
niklase@google.com470e71d2011-07-07 08:21:25 +00005876int
5877Channel::SetMinimumPlayoutDelay(int delayMs)
5878{
5879 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5880 "Channel::SetMinimumPlayoutDelay()");
5881 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
5882 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
5883 {
5884 _engineStatisticsPtr->SetLastError(
5885 VE_INVALID_ARGUMENT, kTraceError,
5886 "SetMinimumPlayoutDelay() invalid min delay");
5887 return -1;
5888 }
5889 if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
5890 {
5891 _engineStatisticsPtr->SetLastError(
5892 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5893 "SetMinimumPlayoutDelay() failed to set min playout delay");
5894 return -1;
5895 }
5896 return 0;
5897}
5898
5899int
5900Channel::GetPlayoutTimestamp(unsigned int& timestamp)
5901{
5902 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5903 "Channel::GetPlayoutTimestamp()");
5904 WebRtc_UWord32 playoutTimestamp(0);
5905 if (GetPlayoutTimeStamp(playoutTimestamp) != 0)
5906 {
5907 _engineStatisticsPtr->SetLastError(
5908 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
5909 "GetPlayoutTimestamp() failed to retrieve timestamp");
5910 return -1;
5911 }
5912 timestamp = playoutTimestamp;
5913 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
5914 VoEId(_instanceId,_channelId),
5915 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
5916 return 0;
5917}
5918
5919int
5920Channel::SetInitTimestamp(unsigned int timestamp)
5921{
5922 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5923 "Channel::SetInitTimestamp()");
5924 if (_sending)
5925 {
5926 _engineStatisticsPtr->SetLastError(
5927 VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
5928 return -1;
5929 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005930 if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005931 {
5932 _engineStatisticsPtr->SetLastError(
5933 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5934 "SetInitTimestamp() failed to set timestamp");
5935 return -1;
5936 }
5937 return 0;
5938}
5939
5940int
5941Channel::SetInitSequenceNumber(short sequenceNumber)
5942{
5943 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5944 "Channel::SetInitSequenceNumber()");
5945 if (_sending)
5946 {
5947 _engineStatisticsPtr->SetLastError(
5948 VE_SENDING, kTraceError,
5949 "SetInitSequenceNumber() already sending");
5950 return -1;
5951 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005952 if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00005953 {
5954 _engineStatisticsPtr->SetLastError(
5955 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5956 "SetInitSequenceNumber() failed to set sequence number");
5957 return -1;
5958 }
5959 return 0;
5960}
5961
5962int
5963Channel::GetRtpRtcp(RtpRtcp* &rtpRtcpModule) const
5964{
5965 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5966 "Channel::GetRtpRtcp()");
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00005967 rtpRtcpModule = _rtpRtcpModule.get();
niklase@google.com470e71d2011-07-07 08:21:25 +00005968 return 0;
5969}
5970
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00005971// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
5972// a shared helper.
niklase@google.com470e71d2011-07-07 08:21:25 +00005973WebRtc_Word32
xians@google.com0b0665a2011-08-08 08:18:44 +00005974Channel::MixOrReplaceAudioWithFile(const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00005975{
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00005976 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00005977 int fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00005978
5979 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00005980 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00005981
5982 if (_inputFilePlayerPtr == NULL)
5983 {
5984 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5985 VoEId(_instanceId, _channelId),
5986 "Channel::MixOrReplaceAudioWithFile() fileplayer"
5987 " doesnt exist");
5988 return -1;
5989 }
5990
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00005991 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00005992 fileSamples,
5993 mixingFrequency) == -1)
5994 {
5995 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5996 VoEId(_instanceId, _channelId),
5997 "Channel::MixOrReplaceAudioWithFile() file mixing "
5998 "failed");
5999 return -1;
6000 }
6001 if (fileSamples == 0)
6002 {
6003 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6004 VoEId(_instanceId, _channelId),
6005 "Channel::MixOrReplaceAudioWithFile() file is ended");
6006 return 0;
6007 }
6008 }
6009
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006010 assert(_audioFrame.samples_per_channel_ == fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006011
6012 if (_mixFileWithMicrophone)
6013 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006014 // Currently file stream is always mono.
6015 // TODO(xians): Change the code when FilePlayer supports real stereo.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006016 Utility::MixWithSat(_audioFrame.data_,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006017 _audioFrame.num_channels_,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006018 fileBuffer.get(),
6019 1,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006020 fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006021 }
6022 else
6023 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006024 // Replace ACM audio with file.
6025 // Currently file stream is always mono.
6026 // TODO(xians): Change the code when FilePlayer supports real stereo.
niklase@google.com470e71d2011-07-07 08:21:25 +00006027 _audioFrame.UpdateFrame(_channelId,
6028 -1,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006029 fileBuffer.get(),
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006030 fileSamples,
niklase@google.com470e71d2011-07-07 08:21:25 +00006031 mixingFrequency,
6032 AudioFrame::kNormalSpeech,
6033 AudioFrame::kVadUnknown,
6034 1);
6035
6036 }
6037 return 0;
6038}
6039
6040WebRtc_Word32
6041Channel::MixAudioWithFile(AudioFrame& audioFrame,
xians@google.com0b0665a2011-08-08 08:18:44 +00006042 const int mixingFrequency)
niklase@google.com470e71d2011-07-07 08:21:25 +00006043{
6044 assert(mixingFrequency <= 32000);
6045
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006046 scoped_array<WebRtc_Word16> fileBuffer(new WebRtc_Word16[640]);
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006047 int fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00006048
6049 {
mflodman@webrtc.org9a065d12012-03-07 08:12:21 +00006050 CriticalSectionScoped cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00006051
6052 if (_outputFilePlayerPtr == NULL)
6053 {
6054 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6055 VoEId(_instanceId, _channelId),
6056 "Channel::MixAudioWithFile() file mixing failed");
6057 return -1;
6058 }
6059
6060 // We should get the frequency we ask for.
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006061 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
niklase@google.com470e71d2011-07-07 08:21:25 +00006062 fileSamples,
6063 mixingFrequency) == -1)
6064 {
6065 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6066 VoEId(_instanceId, _channelId),
6067 "Channel::MixAudioWithFile() file mixing failed");
6068 return -1;
6069 }
6070 }
6071
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006072 if (audioFrame.samples_per_channel_ == fileSamples)
niklase@google.com470e71d2011-07-07 08:21:25 +00006073 {
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006074 // Currently file stream is always mono.
6075 // TODO(xians): Change the code when FilePlayer supports real stereo.
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006076 Utility::MixWithSat(audioFrame.data_,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006077 audioFrame.num_channels_,
braveyao@webrtc.orgd7131432012-03-29 10:39:44 +00006078 fileBuffer.get(),
6079 1,
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00006080 fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006081 }
6082 else
6083 {
6084 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006085 "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
niklase@google.com470e71d2011-07-07 08:21:25 +00006086 "fileSamples(%d)",
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006087 audioFrame.samples_per_channel_, fileSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006088 return -1;
6089 }
6090
6091 return 0;
6092}
6093
6094int
6095Channel::InsertInbandDtmfTone()
6096{
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006097 // Check if we should start a new tone.
niklase@google.com470e71d2011-07-07 08:21:25 +00006098 if (_inbandDtmfQueue.PendingDtmf() &&
6099 !_inbandDtmfGenerator.IsAddingTone() &&
6100 _inbandDtmfGenerator.DelaySinceLastTone() >
6101 kMinTelephoneEventSeparationMs)
6102 {
6103 WebRtc_Word8 eventCode(0);
6104 WebRtc_UWord16 lengthMs(0);
6105 WebRtc_UWord8 attenuationDb(0);
6106
6107 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
6108 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
6109 if (_playInbandDtmfEvent)
6110 {
6111 // Add tone to output mixer using a reduced length to minimize
6112 // risk of echo.
6113 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
6114 attenuationDb);
6115 }
6116 }
6117
6118 if (_inbandDtmfGenerator.IsAddingTone())
6119 {
6120 WebRtc_UWord16 frequency(0);
6121 _inbandDtmfGenerator.GetSampleRate(frequency);
6122
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006123 if (frequency != _audioFrame.sample_rate_hz_)
niklase@google.com470e71d2011-07-07 08:21:25 +00006124 {
6125 // Update sample rate of Dtmf tone since the mixing frequency
6126 // has changed.
6127 _inbandDtmfGenerator.SetSampleRate(
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006128 (WebRtc_UWord16) (_audioFrame.sample_rate_hz_));
niklase@google.com470e71d2011-07-07 08:21:25 +00006129 // Reset the tone to be added taking the new sample rate into
6130 // account.
6131 _inbandDtmfGenerator.ResetTone();
6132 }
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00006133
niklase@google.com470e71d2011-07-07 08:21:25 +00006134 WebRtc_Word16 toneBuffer[320];
6135 WebRtc_UWord16 toneSamples(0);
6136 // Get 10ms tone segment and set time since last tone to zero
6137 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
6138 {
6139 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6140 VoEId(_instanceId, _channelId),
6141 "Channel::EncodeAndSend() inserting Dtmf failed");
6142 return -1;
6143 }
6144
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006145 // Replace mixed audio with DTMF tone.
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00006146 for (int sample = 0;
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006147 sample < _audioFrame.samples_per_channel_;
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006148 sample++)
6149 {
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00006150 for (int channel = 0;
6151 channel < _audioFrame.num_channels_;
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006152 channel++)
6153 {
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00006154 const int index = sample * _audioFrame.num_channels_ + channel;
6155 _audioFrame.data_[index] = toneBuffer[sample];
niklas.enbom@webrtc.orgaf26f642011-11-16 12:41:36 +00006156 }
6157 }
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +00006158
andrew@webrtc.org63a50982012-05-02 23:56:37 +00006159 assert(_audioFrame.samples_per_channel_ == toneSamples);
niklase@google.com470e71d2011-07-07 08:21:25 +00006160 } else
6161 {
6162 // Add 10ms to "delay-since-last-tone" counter
6163 _inbandDtmfGenerator.UpdateDelaySinceLastTone();
6164 }
6165 return 0;
6166}
6167
6168WebRtc_Word32
6169Channel::GetPlayoutTimeStamp(WebRtc_UWord32& playoutTimestamp)
6170{
6171 WebRtc_UWord32 timestamp(0);
6172 CodecInst currRecCodec;
6173
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00006174 if (_audioCodingModule.PlayoutTimestamp(&timestamp) == -1)
niklase@google.com470e71d2011-07-07 08:21:25 +00006175 {
6176 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6177 "Channel::GetPlayoutTimeStamp() failed to read playout"
6178 " timestamp from the ACM");
6179 return -1;
6180 }
6181
6182 WebRtc_UWord16 delayMS(0);
6183 if (_audioDeviceModulePtr->PlayoutDelay(&delayMS) == -1)
6184 {
6185 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
6186 "Channel::GetPlayoutTimeStamp() failed to read playout"
6187 " delay from the ADM");
6188 return -1;
6189 }
6190
6191 WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00006192 if (_audioCodingModule.ReceiveCodec(&currRecCodec) == 0) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006193 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6194 playoutFrequency = 8000;
6195 } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6196 playoutFrequency = 48000;
6197 }
niklase@google.com470e71d2011-07-07 08:21:25 +00006198 }
6199 timestamp -= (delayMS * (playoutFrequency/1000));
6200
6201 playoutTimestamp = timestamp;
6202
6203 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6204 "Channel::GetPlayoutTimeStamp() => playoutTimestamp = %lu",
6205 playoutTimestamp);
6206 return 0;
6207}
6208
6209void
6210Channel::ResetDeadOrAliveCounters()
6211{
6212 _countDeadDetections = 0;
6213 _countAliveDetections = 0;
6214}
6215
6216void
6217Channel::UpdateDeadOrAliveCounters(bool alive)
6218{
6219 if (alive)
6220 _countAliveDetections++;
6221 else
6222 _countDeadDetections++;
6223}
6224
6225int
6226Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
6227{
6228 bool enabled;
6229 WebRtc_UWord8 timeSec;
6230
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006231 _rtpRtcpModule->PeriodicDeadOrAliveStatus(enabled, timeSec);
niklase@google.com470e71d2011-07-07 08:21:25 +00006232 if (!enabled)
6233 return (-1);
6234
6235 countDead = static_cast<int> (_countDeadDetections);
6236 countAlive = static_cast<int> (_countAliveDetections);
6237 return 0;
6238}
6239
6240WebRtc_Word32
6241Channel::SendPacketRaw(const void *data, int len, bool RTCP)
6242{
6243 if (_transportPtr == NULL)
6244 {
6245 return -1;
6246 }
6247 if (!RTCP)
6248 {
6249 return _transportPtr->SendPacket(_channelId, data, len);
6250 }
6251 else
6252 {
6253 return _transportPtr->SendRTCPPacket(_channelId, data, len);
6254 }
6255}
6256
6257WebRtc_Word32
6258Channel::UpdatePacketDelay(const WebRtc_UWord32 timestamp,
6259 const WebRtc_UWord16 sequenceNumber)
6260{
6261 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
6262 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
6263 timestamp, sequenceNumber);
6264
6265 WebRtc_Word32 rtpReceiveFrequency(0);
6266
6267 // Get frequency of last received payload
6268 rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
6269
6270 CodecInst currRecCodec;
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00006271 if (_audioCodingModule.ReceiveCodec(&currRecCodec) == 0) {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006272 if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
6273 // Even though the actual sampling rate for G.722 audio is
6274 // 16,000 Hz, the RTP clock rate for the G722 payload format is
6275 // 8,000 Hz because that value was erroneously assigned in
6276 // RFC 1890 and must remain unchanged for backward compatibility.
6277 rtpReceiveFrequency = 8000;
6278 } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
6279 // We are resampling Opus internally to 32,000 Hz until all our
6280 // DSP routines can operate at 48,000 Hz, but the RTP clock
6281 // rate for the Opus payload format is standardized to 48,000 Hz,
6282 // because that is the maximum supported decoding sampling rate.
6283 rtpReceiveFrequency = 48000;
6284 }
niklase@google.com470e71d2011-07-07 08:21:25 +00006285 }
6286
6287 const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
6288 WebRtc_UWord32 timeStampDiffMs(0);
6289
6290 if (timeStampDiff > 0)
6291 {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006292 switch (rtpReceiveFrequency) {
6293 case 8000:
6294 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 3);
6295 break;
6296 case 16000:
6297 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 4);
6298 break;
6299 case 32000:
6300 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 5);
6301 break;
6302 case 48000:
6303 timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff / 48);
6304 break;
6305 default:
6306 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
6307 VoEId(_instanceId, _channelId),
6308 "Channel::UpdatePacketDelay() invalid sample rate");
6309 timeStampDiffMs = 0;
6310 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00006311 }
niklas.enbom@webrtc.org218c5422013-01-17 22:25:49 +00006312 if (timeStampDiffMs > (2 * kVoiceEngineMaxMinPlayoutDelayMs))
niklase@google.com470e71d2011-07-07 08:21:25 +00006313 {
6314 timeStampDiffMs = 0;
6315 }
6316
6317 if (_averageDelayMs == 0)
6318 {
niklas.enbom@webrtc.org218c5422013-01-17 22:25:49 +00006319 _averageDelayMs = timeStampDiffMs * 10;
niklase@google.com470e71d2011-07-07 08:21:25 +00006320 }
6321 else
6322 {
6323 // Filter average delay value using exponential filter (alpha is
6324 // 7/8). We derive 10*_averageDelayMs here (reduces risk of
6325 // rounding error) and compensate for it in GetDelayEstimate()
6326 // later. Adding 4/8 results in correct rounding.
6327 _averageDelayMs = ((_averageDelayMs*7 + 10*timeStampDiffMs + 4)>>3);
6328 }
6329
6330 if (sequenceNumber - _previousSequenceNumber == 1)
6331 {
6332 WebRtc_UWord16 packetDelayMs = 0;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006333 switch (rtpReceiveFrequency) {
6334 case 8000:
6335 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006336 (timestamp - _previousTimestamp) >> 3);
6337 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006338 case 16000:
6339 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006340 (timestamp - _previousTimestamp) >> 4);
6341 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006342 case 32000:
6343 packetDelayMs = static_cast<WebRtc_UWord16>(
niklase@google.com470e71d2011-07-07 08:21:25 +00006344 (timestamp - _previousTimestamp) >> 5);
6345 break;
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +00006346 case 48000:
6347 packetDelayMs = static_cast<WebRtc_UWord16>(
6348 (timestamp - _previousTimestamp) / 48);
6349 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00006350 }
6351
6352 if (packetDelayMs >= 10 && packetDelayMs <= 60)
6353 _recPacketDelayMs = packetDelayMs;
6354 }
6355 }
6356
6357 _previousSequenceNumber = sequenceNumber;
6358 _previousTimestamp = timestamp;
6359
6360 return 0;
6361}
6362
6363void
6364Channel::RegisterReceiveCodecsToRTPModule()
6365{
6366 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
6367 "Channel::RegisterReceiveCodecsToRTPModule()");
6368
6369
6370 CodecInst codec;
6371 const WebRtc_UWord8 nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
6372
6373 for (int idx = 0; idx < nSupportedCodecs; idx++)
6374 {
6375 // Open up the RTP/RTCP receiver for all supported codecs
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00006376 if ((_audioCodingModule.Codec(idx, &codec) == -1) ||
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +00006377 (_rtpRtcpModule->RegisterReceivePayload(codec) == -1))
niklase@google.com470e71d2011-07-07 08:21:25 +00006378 {
6379 WEBRTC_TRACE(
6380 kTraceWarning,
6381 kTraceVoice,
6382 VoEId(_instanceId, _channelId),
6383 "Channel::RegisterReceiveCodecsToRTPModule() unable"
6384 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
6385 codec.plname, codec.pltype, codec.plfreq,
6386 codec.channels, codec.rate);
6387 }
6388 else
6389 {
6390 WEBRTC_TRACE(
6391 kTraceInfo,
6392 kTraceVoice,
6393 VoEId(_instanceId, _channelId),
6394 "Channel::RegisterReceiveCodecsToRTPModule() %s "
wu@webrtc.orgfcd12b32011-09-15 20:49:50 +00006395 "(%d/%d/%d/%d) has been added to the RTP/RTCP "
niklase@google.com470e71d2011-07-07 08:21:25 +00006396 "receiver",
6397 codec.plname, codec.pltype, codec.plfreq,
6398 codec.channels, codec.rate);
6399 }
6400 }
6401}
6402
andrew@webrtc.org50419b02012-11-14 19:07:54 +00006403int Channel::ApmProcessRx(AudioFrame& frame) {
6404 AudioProcessing* audioproc = _rxAudioProcessingModulePtr;
6405 // Register the (possibly new) frame parameters.
6406 if (audioproc->set_sample_rate_hz(frame.sample_rate_hz_) != 0) {
andrew@webrtc.org655d8f52012-11-20 07:34:45 +00006407 LOG_FERR1(LS_WARNING, set_sample_rate_hz, frame.sample_rate_hz_);
andrew@webrtc.org50419b02012-11-14 19:07:54 +00006408 }
6409 if (audioproc->set_num_channels(frame.num_channels_,
6410 frame.num_channels_) != 0) {
andrew@webrtc.org655d8f52012-11-20 07:34:45 +00006411 LOG_FERR1(LS_WARNING, set_num_channels, frame.num_channels_);
andrew@webrtc.org50419b02012-11-14 19:07:54 +00006412 }
6413 if (audioproc->ProcessStream(&frame) != 0) {
andrew@webrtc.org655d8f52012-11-20 07:34:45 +00006414 LOG_FERR0(LS_WARNING, ProcessStream);
andrew@webrtc.org50419b02012-11-14 19:07:54 +00006415 }
6416 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00006417}
6418
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006419int Channel::SetSecondarySendCodec(const CodecInst& codec,
6420 int red_payload_type) {
turaj@webrtc.org8c8ad852013-01-31 18:20:17 +00006421 // Sanity check for payload type.
6422 if (red_payload_type < 0 || red_payload_type > 127) {
6423 _engineStatisticsPtr->SetLastError(
6424 VE_PLTYPE_ERROR, kTraceError,
6425 "SetRedPayloadType() invalid RED payload type");
6426 return -1;
6427 }
6428
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006429 if (SetRedPayloadType(red_payload_type) < 0) {
6430 _engineStatisticsPtr->SetLastError(
6431 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6432 "SetSecondarySendCodec() Failed to register RED ACM");
6433 return -1;
6434 }
6435 if (_audioCodingModule.RegisterSecondarySendCodec(codec) < 0) {
6436 _engineStatisticsPtr->SetLastError(
6437 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6438 "SetSecondarySendCodec() Failed to register secondary send codec in "
6439 "ACM");
6440 return -1;
6441 }
6442
6443 return 0;
6444}
6445
6446void Channel::RemoveSecondarySendCodec() {
6447 _audioCodingModule.UnregisterSecondarySendCodec();
6448}
6449
6450int Channel::GetSecondarySendCodec(CodecInst* codec) {
6451 if (_audioCodingModule.SecondarySendCodec(codec) < 0) {
6452 _engineStatisticsPtr->SetLastError(
6453 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6454 "GetSecondarySendCodec() Failed to get secondary sent codec from ACM");
6455 return -1;
6456 }
6457 return 0;
6458}
6459
turaj@webrtc.org8c8ad852013-01-31 18:20:17 +00006460// Assuming this method is called with valid payload type.
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006461int Channel::SetRedPayloadType(int red_payload_type) {
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006462 CodecInst codec;
6463 bool found_red = false;
6464
6465 // Get default RED settings from the ACM database
6466 const int num_codecs = AudioCodingModule::NumberOfCodecs();
6467 for (int idx = 0; idx < num_codecs; idx++) {
tina.legrand@webrtc.org7a7a0082013-02-21 10:27:48 +00006468 _audioCodingModule.Codec(idx, &codec);
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006469 if (!STR_CASE_CMP(codec.plname, "RED")) {
6470 found_red = true;
6471 break;
6472 }
6473 }
6474
6475 if (!found_red) {
6476 _engineStatisticsPtr->SetLastError(
6477 VE_CODEC_ERROR, kTraceError,
6478 "SetRedPayloadType() RED is not supported");
6479 return -1;
6480 }
6481
turaj@webrtc.org9d532fd2013-01-31 18:34:19 +00006482 codec.pltype = red_payload_type;
turaj@webrtc.org42259e72012-12-11 02:15:12 +00006483 if (_audioCodingModule.RegisterSendCodec(codec) < 0) {
6484 _engineStatisticsPtr->SetLastError(
6485 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
6486 "SetRedPayloadType() RED registration in ACM module failed");
6487 return -1;
6488 }
6489
6490 if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
6491 _engineStatisticsPtr->SetLastError(
6492 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
6493 "SetRedPayloadType() RED registration in RTP/RTCP module failed");
6494 return -1;
6495 }
6496 return 0;
6497}
6498
niklase@google.com470e71d2011-07-07 08:21:25 +00006499} // namespace voe
niklase@google.com470e71d2011-07-07 08:21:25 +00006500} // namespace webrtc