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