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