blob: eda0ddcf491adb3100d07208441ec8c0b363e99e [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
turaj@webrtc.orgead8a5b2013-02-12 21:42:18 +000011#include "webrtc/voice_engine/channel.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
minyue@webrtc.org4489c512013-09-12 17:03:00 +000013#include "webrtc/common.h"
turaj@webrtc.orgead8a5b2013-02-12 21:42:18 +000014#include "webrtc/modules/audio_device/include/audio_device.h"
15#include "webrtc/modules/audio_processing/include/audio_processing.h"
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +000016#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
17#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
18#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
19#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
turaj@webrtc.orgead8a5b2013-02-12 21:42:18 +000020#include "webrtc/modules/utility/interface/audio_frame_operations.h"
21#include "webrtc/modules/utility/interface/process_thread.h"
22#include "webrtc/modules/utility/interface/rtp_dump.h"
23#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24#include "webrtc/system_wrappers/interface/logging.h"
25#include "webrtc/system_wrappers/interface/trace.h"
26#include "webrtc/voice_engine/include/voe_base.h"
27#include "webrtc/voice_engine/include/voe_external_media.h"
28#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
29#include "webrtc/voice_engine/output_mixer.h"
30#include "webrtc/voice_engine/statistics.h"
31#include "webrtc/voice_engine/transmit_mixer.h"
32#include "webrtc/voice_engine/utility.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000033
34#if defined(_WIN32)
35#include <Qos.h>
36#endif
37
andrew@webrtc.orgd898c012012-11-14 19:07:54 +000038namespace webrtc {
39namespace voe {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000040
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +000041int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000042Channel::SendData(FrameType frameType,
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +000043 uint8_t payloadType,
44 uint32_t timeStamp,
45 const uint8_t* payloadData,
46 uint16_t payloadSize,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000047 const RTPFragmentationHeader* fragmentation)
48{
49 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
50 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
51 " payloadSize=%u, fragmentation=0x%x)",
52 frameType, payloadType, timeStamp, payloadSize, fragmentation);
53
54 if (_includeAudioLevelIndication)
55 {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000056 // Store current audio level in the RTP/RTCP module.
57 // The level will be used in combination with voice-activity state
58 // (frameType) to add an RTP header extension
andrew@webrtc.org80142aa2013-09-18 22:37:32 +000059 _rtpRtcpModule->SetAudioLevel(rtp_audioproc_->level_estimator()->RMS());
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000060 }
61
62 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
63 // packetization.
64 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
65 if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
66 payloadType,
67 timeStamp,
68 // Leaving the time when this frame was
69 // received from the capture device as
70 // undefined for voice for now.
71 -1,
72 payloadData,
73 payloadSize,
74 fragmentation) == -1)
75 {
76 _engineStatisticsPtr->SetLastError(
77 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
78 "Channel::SendData() failed to send data to RTP/RTCP module");
79 return -1;
80 }
81
82 _lastLocalTimeStamp = timeStamp;
83 _lastPayloadType = payloadType;
84
85 return 0;
86}
87
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +000088int32_t
89Channel::InFrameType(int16_t frameType)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000090{
91 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
92 "Channel::InFrameType(frameType=%d)", frameType);
93
94 CriticalSectionScoped cs(&_callbackCritSect);
95 // 1 indicates speech
96 _sendFrameType = (frameType == 1) ? 1 : 0;
97 return 0;
98}
99
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000100int32_t
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000101Channel::OnRxVadDetected(int vadDecision)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000102{
103 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
104 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
105
106 CriticalSectionScoped cs(&_callbackCritSect);
107 if (_rxVadObserverPtr)
108 {
109 _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
110 }
111
112 return 0;
113}
114
115int
116Channel::SendPacket(int channel, const void *data, int len)
117{
118 channel = VoEChannelId(channel);
119 assert(channel == _channelId);
120
121 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
122 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
123
124 if (_transportPtr == NULL)
125 {
126 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
127 "Channel::SendPacket() failed to send RTP packet due to"
128 " invalid transport object");
129 return -1;
130 }
131
132 // Insert extra RTP packet using if user has called the InsertExtraRTPPacket
133 // API
134 if (_insertExtraRTPPacket)
135 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000136 uint8_t* rtpHdr = (uint8_t*)data;
137 uint8_t M_PT(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000138 if (_extraMarkerBit)
139 {
140 M_PT = 0x80; // set the M-bit
141 }
142 M_PT += _extraPayloadType; // set the payload type
143 *(++rtpHdr) = M_PT; // modify the M|PT-byte within the RTP header
144 _insertExtraRTPPacket = false; // insert one packet only
145 }
146
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000147 uint8_t* bufferToSendPtr = (uint8_t*)data;
148 int32_t bufferLength = len;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000149
150 // Dump the RTP packet to a file (if RTP dump is enabled).
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000151 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000152 {
153 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
154 VoEId(_instanceId,_channelId),
155 "Channel::SendPacket() RTP dump to output file failed");
156 }
157
158 // SRTP or External encryption
159 if (_encrypting)
160 {
161 CriticalSectionScoped cs(&_callbackCritSect);
162
163 if (_encryptionPtr)
164 {
165 if (!_encryptionRTPBufferPtr)
166 {
167 // Allocate memory for encryption buffer one time only
168 _encryptionRTPBufferPtr =
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000169 new uint8_t[kVoiceEngineMaxIpPacketSizeBytes];
xians@webrtc.orgbc53c402012-10-25 13:58:02 +0000170 memset(_encryptionRTPBufferPtr, 0,
171 kVoiceEngineMaxIpPacketSizeBytes);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000172 }
173
174 // Perform encryption (SRTP or external)
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000175 int32_t encryptedBufferLength = 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000176 _encryptionPtr->encrypt(_channelId,
177 bufferToSendPtr,
178 _encryptionRTPBufferPtr,
179 bufferLength,
180 (int*)&encryptedBufferLength);
181 if (encryptedBufferLength <= 0)
182 {
183 _engineStatisticsPtr->SetLastError(
184 VE_ENCRYPTION_FAILED,
185 kTraceError, "Channel::SendPacket() encryption failed");
186 return -1;
187 }
188
189 // Replace default data buffer with encrypted buffer
190 bufferToSendPtr = _encryptionRTPBufferPtr;
191 bufferLength = encryptedBufferLength;
192 }
193 }
194
195 // Packet transmission using WebRtc socket transport
196 if (!_externalTransport)
197 {
198 int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
199 bufferLength);
200 if (n < 0)
201 {
202 WEBRTC_TRACE(kTraceError, kTraceVoice,
203 VoEId(_instanceId,_channelId),
204 "Channel::SendPacket() RTP transmission using WebRtc"
205 " sockets failed");
206 return -1;
207 }
208 return n;
209 }
210
211 // Packet transmission using external transport transport
212 {
213 CriticalSectionScoped cs(&_callbackCritSect);
214
215 int n = _transportPtr->SendPacket(channel,
216 bufferToSendPtr,
217 bufferLength);
218 if (n < 0)
219 {
220 WEBRTC_TRACE(kTraceError, kTraceVoice,
221 VoEId(_instanceId,_channelId),
222 "Channel::SendPacket() RTP transmission using external"
223 " transport failed");
224 return -1;
225 }
226 return n;
227 }
228}
229
230int
231Channel::SendRTCPPacket(int channel, const void *data, int len)
232{
233 channel = VoEChannelId(channel);
234 assert(channel == _channelId);
235
236 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
237 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
238
239 {
240 CriticalSectionScoped cs(&_callbackCritSect);
241 if (_transportPtr == NULL)
242 {
243 WEBRTC_TRACE(kTraceError, kTraceVoice,
244 VoEId(_instanceId,_channelId),
245 "Channel::SendRTCPPacket() failed to send RTCP packet"
246 " due to invalid transport object");
247 return -1;
248 }
249 }
250
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000251 uint8_t* bufferToSendPtr = (uint8_t*)data;
252 int32_t bufferLength = len;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000253
254 // Dump the RTCP packet to a file (if RTP dump is enabled).
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000255 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000256 {
257 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
258 VoEId(_instanceId,_channelId),
259 "Channel::SendPacket() RTCP dump to output file failed");
260 }
261
262 // SRTP or External encryption
263 if (_encrypting)
264 {
265 CriticalSectionScoped cs(&_callbackCritSect);
266
267 if (_encryptionPtr)
268 {
269 if (!_encryptionRTCPBufferPtr)
270 {
271 // Allocate memory for encryption buffer one time only
272 _encryptionRTCPBufferPtr =
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000273 new uint8_t[kVoiceEngineMaxIpPacketSizeBytes];
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000274 }
275
276 // Perform encryption (SRTP or external).
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000277 int32_t encryptedBufferLength = 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000278 _encryptionPtr->encrypt_rtcp(_channelId,
279 bufferToSendPtr,
280 _encryptionRTCPBufferPtr,
281 bufferLength,
282 (int*)&encryptedBufferLength);
283 if (encryptedBufferLength <= 0)
284 {
285 _engineStatisticsPtr->SetLastError(
286 VE_ENCRYPTION_FAILED, kTraceError,
287 "Channel::SendRTCPPacket() encryption failed");
288 return -1;
289 }
290
291 // Replace default data buffer with encrypted buffer
292 bufferToSendPtr = _encryptionRTCPBufferPtr;
293 bufferLength = encryptedBufferLength;
294 }
295 }
296
297 // Packet transmission using WebRtc socket transport
298 if (!_externalTransport)
299 {
300 int n = _transportPtr->SendRTCPPacket(channel,
301 bufferToSendPtr,
302 bufferLength);
303 if (n < 0)
304 {
305 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
306 VoEId(_instanceId,_channelId),
307 "Channel::SendRTCPPacket() transmission using WebRtc"
308 " sockets failed");
309 return -1;
310 }
311 return n;
312 }
313
314 // Packet transmission using external transport transport
315 {
316 CriticalSectionScoped cs(&_callbackCritSect);
henrike@webrtc.org03a161e2012-11-18 18:49:13 +0000317 if (_transportPtr == NULL)
318 {
319 return -1;
320 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000321 int n = _transportPtr->SendRTCPPacket(channel,
322 bufferToSendPtr,
323 bufferLength);
324 if (n < 0)
325 {
326 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
327 VoEId(_instanceId,_channelId),
328 "Channel::SendRTCPPacket() transmission using external"
329 " transport failed");
330 return -1;
331 }
332 return n;
333 }
334
335 return len;
336}
337
338void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000339Channel::OnPlayTelephoneEvent(int32_t id,
340 uint8_t event,
341 uint16_t lengthMs,
342 uint8_t volume)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000343{
344 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
345 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
346 " volume=%u)", id, event, lengthMs, volume);
347
348 if (!_playOutbandDtmfEvent || (event > 15))
349 {
350 // Ignore callback since feedback is disabled or event is not a
351 // Dtmf tone event.
352 return;
353 }
354
355 assert(_outputMixerPtr != NULL);
356
357 // Start playing out the Dtmf tone (if playout is enabled).
358 // Reduce length of tone with 80ms to the reduce risk of echo.
359 _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
360}
361
362void
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +0000363Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000364{
365 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
366 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +0000367 id, ssrc);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000368
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000369 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000370 assert(channel == _channelId);
371
dwkang@webrtc.orgc766a742013-08-29 07:34:12 +0000372 // Update ssrc so that NTP for AV sync can be updated.
373 _rtpRtcpModule->SetRemoteSSRC(ssrc);
374
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000375 if (_rtpObserver)
376 {
377 CriticalSectionScoped cs(&_callbackCritSect);
378
379 if (_rtpObserverPtr)
380 {
381 // Send new SSRC to registered observer using callback
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +0000382 _rtpObserverPtr->OnIncomingSSRCChanged(channel, ssrc);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000383 }
384 }
385}
386
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000387void Channel::OnIncomingCSRCChanged(int32_t id,
388 uint32_t CSRC,
389 bool added)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000390{
391 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
392 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
393 id, CSRC, added);
394
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000395 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000396 assert(channel == _channelId);
397
398 if (_rtpObserver)
399 {
400 CriticalSectionScoped cs(&_callbackCritSect);
401
402 if (_rtpObserverPtr)
403 {
404 _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
405 }
406 }
407}
408
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +0000409void Channel::ResetStatistics(uint32_t ssrc) {
410 StreamStatistician* statistician =
411 rtp_receive_statistics_->GetStatistician(ssrc);
412 if (statistician) {
413 statistician->ResetStatistics();
414 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000415}
416
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000417void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000418Channel::OnApplicationDataReceived(int32_t id,
419 uint8_t subType,
420 uint32_t name,
421 uint16_t length,
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000422 const uint8_t* data)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000423{
424 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
425 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
426 " name=%u, length=%u)",
427 id, subType, name, length);
428
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000429 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000430 assert(channel == _channelId);
431
432 if (_rtcpObserver)
433 {
434 CriticalSectionScoped cs(&_callbackCritSect);
435
436 if (_rtcpObserverPtr)
437 {
438 _rtcpObserverPtr->OnApplicationDataReceived(channel,
439 subType,
440 name,
441 data,
442 length);
443 }
444 }
445}
446
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000447int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000448Channel::OnInitializeDecoder(
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000449 int32_t id,
450 int8_t payloadType,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000451 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000452 int frequency,
453 uint8_t channels,
454 uint32_t rate)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000455{
456 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
457 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
458 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
459 id, payloadType, payloadName, frequency, channels, rate);
460
461 assert(VoEChannelId(id) == _channelId);
462
463 CodecInst receiveCodec = {0};
464 CodecInst dummyCodec = {0};
465
466 receiveCodec.pltype = payloadType;
467 receiveCodec.plfreq = frequency;
468 receiveCodec.channels = channels;
469 receiveCodec.rate = rate;
470 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
andrew@webrtc.orgd4682362013-01-22 04:44:30 +0000471
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +0000472 _audioCodingModule.Codec(payloadName, &dummyCodec, frequency, channels);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000473 receiveCodec.pacsize = dummyCodec.pacsize;
474
475 // Register the new codec to the ACM
476 if (_audioCodingModule.RegisterReceiveCodec(receiveCodec) == -1)
477 {
478 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
479 VoEId(_instanceId, _channelId),
480 "Channel::OnInitializeDecoder() invalid codec ("
481 "pt=%d, name=%s) received - 1", payloadType, payloadName);
482 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
483 return -1;
484 }
485
486 return 0;
487}
488
489void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000490Channel::OnPacketTimeout(int32_t id)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000491{
492 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
493 "Channel::OnPacketTimeout(id=%d)", id);
494
495 CriticalSectionScoped cs(_callbackCritSectPtr);
496 if (_voiceEngineObserverPtr)
497 {
498 if (_receiving || _externalTransport)
499 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000500 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000501 assert(channel == _channelId);
502 // Ensure that next OnReceivedPacket() callback will trigger
503 // a VE_PACKET_RECEIPT_RESTARTED callback.
504 _rtpPacketTimedOut = true;
505 // Deliver callback to the observer
506 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
507 VoEId(_instanceId,_channelId),
508 "Channel::OnPacketTimeout() => "
509 "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
510 _voiceEngineObserverPtr->CallbackOnError(channel,
511 VE_RECEIVE_PACKET_TIMEOUT);
512 }
513 }
514}
515
516void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000517Channel::OnReceivedPacket(int32_t id,
518 RtpRtcpPacketType packetType)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000519{
520 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
521 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
522 id, packetType);
523
524 assert(VoEChannelId(id) == _channelId);
525
526 // Notify only for the case when we have restarted an RTP session.
527 if (_rtpPacketTimedOut && (kPacketRtp == packetType))
528 {
529 CriticalSectionScoped cs(_callbackCritSectPtr);
530 if (_voiceEngineObserverPtr)
531 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000532 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000533 assert(channel == _channelId);
534 // Reset timeout mechanism
535 _rtpPacketTimedOut = false;
536 // Deliver callback to the observer
537 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
538 VoEId(_instanceId,_channelId),
539 "Channel::OnPacketTimeout() =>"
540 " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
541 _voiceEngineObserverPtr->CallbackOnError(
542 channel,
543 VE_PACKET_RECEIPT_RESTARTED);
544 }
545 }
546}
547
548void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000549Channel::OnPeriodicDeadOrAlive(int32_t id,
550 RTPAliveType alive)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000551{
552 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
553 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
554
henrika@webrtc.org1d25eac2013-04-05 14:34:57 +0000555 {
556 CriticalSectionScoped cs(&_callbackCritSect);
557 if (!_connectionObserver)
558 return;
559 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000560
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000561 int32_t channel = VoEChannelId(id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000562 assert(channel == _channelId);
563
564 // Use Alive as default to limit risk of false Dead detections
565 bool isAlive(true);
566
567 // Always mark the connection as Dead when the module reports kRtpDead
568 if (kRtpDead == alive)
569 {
570 isAlive = false;
571 }
572
573 // It is possible that the connection is alive even if no RTP packet has
574 // been received for a long time since the other side might use VAD/DTX
575 // and a low SID-packet update rate.
576 if ((kRtpNoRtp == alive) && _playing)
577 {
578 // Detect Alive for all NetEQ states except for the case when we are
579 // in PLC_CNG state.
580 // PLC_CNG <=> background noise only due to long expand or error.
581 // Note that, the case where the other side stops sending during CNG
582 // state will be detected as Alive. Dead is is not set until after
583 // missing RTCP packets for at least twelve seconds (handled
584 // internally by the RTP/RTCP module).
585 isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
586 }
587
588 UpdateDeadOrAliveCounters(isAlive);
589
590 // Send callback to the registered observer
591 if (_connectionObserver)
592 {
593 CriticalSectionScoped cs(&_callbackCritSect);
594 if (_connectionObserverPtr)
595 {
596 _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
597 }
598 }
599}
600
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000601int32_t
602Channel::OnReceivedPayloadData(const uint8_t* payloadData,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000603 uint16_t payloadSize,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000604 const WebRtcRTPHeader* rtpHeader)
605{
606 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
607 "Channel::OnReceivedPayloadData(payloadSize=%d,"
608 " payloadType=%u, audioChannel=%u)",
609 payloadSize,
610 rtpHeader->header.payloadType,
611 rtpHeader->type.Audio.channel);
612
roosa@google.comca771492012-12-12 21:31:41 +0000613 _lastRemoteTimeStamp = rtpHeader->header.timestamp;
614
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000615 if (!_playing)
616 {
617 // Avoid inserting into NetEQ when we are not playing. Count the
618 // packet as discarded.
619 WEBRTC_TRACE(kTraceStream, kTraceVoice,
620 VoEId(_instanceId, _channelId),
621 "received packet is discarded since playing is not"
622 " activated");
623 _numberOfDiscardedPackets++;
624 return 0;
625 }
626
627 // Push the incoming payload (parsed and ready for decoding) into the ACM
628 if (_audioCodingModule.IncomingPacket(payloadData,
629 payloadSize,
630 *rtpHeader) != 0)
631 {
632 _engineStatisticsPtr->SetLastError(
633 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
634 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
635 return -1;
636 }
637
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +0000638 // Update the packet delay.
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000639 UpdatePacketDelay(rtpHeader->header.timestamp,
640 rtpHeader->header.sequenceNumber);
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +0000641
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000642 uint16_t round_trip_time = 0;
643 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time,
644 NULL, NULL, NULL);
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +0000645
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000646 std::vector<uint16_t> nack_list = _audioCodingModule.GetNackList(
647 round_trip_time);
648 if (!nack_list.empty()) {
649 // Can't use nack_list.data() since it's not supported by all
650 // compilers.
651 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +0000652 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000653 return 0;
654}
655
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +0000656bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
657 int rtp_packet_length) {
658 RTPHeader header;
659 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
660 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
661 "IncomingPacket invalid RTP header");
662 return false;
663 }
664 header.payload_type_frequency =
665 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
666 if (header.payload_type_frequency < 0)
667 return false;
668 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
669}
670
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000671int32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000672{
673 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
674 "Channel::GetAudioFrame(id=%d)", id);
675
676 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
677 if (_audioCodingModule.PlayoutData10Ms(audioFrame.sample_rate_hz_,
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +0000678 &audioFrame) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000679 {
680 WEBRTC_TRACE(kTraceError, kTraceVoice,
681 VoEId(_instanceId,_channelId),
682 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
683 // In all likelihood, the audio in this frame is garbage. We return an
684 // error so that the audio mixer module doesn't add it to the mix. As
685 // a result, it won't be played out and the actions skipped here are
686 // irrelevant.
687 return -1;
688 }
689
690 if (_RxVadDetection)
691 {
692 UpdateRxVadDetection(audioFrame);
693 }
694
695 // Convert module ID to internal VoE channel ID
696 audioFrame.id_ = VoEChannelId(audioFrame.id_);
697 // Store speech type for dead-or-alive detection
698 _outputSpeechType = audioFrame.speech_type_;
699
700 // Perform far-end AudioProcessing module processing on the received signal
701 if (_rxApmIsEnabled)
702 {
703 ApmProcessRx(audioFrame);
704 }
705
706 // Output volume scaling
707 if (_outputGain < 0.99f || _outputGain > 1.01f)
708 {
709 AudioFrameOperations::ScaleWithSat(_outputGain, audioFrame);
710 }
711
712 // Scale left and/or right channel(s) if stereo and master balance is
713 // active
714
715 if (_panLeft != 1.0f || _panRight != 1.0f)
716 {
717 if (audioFrame.num_channels_ == 1)
718 {
719 // Emulate stereo mode since panning is active.
720 // The mono signal is copied to both left and right channels here.
721 AudioFrameOperations::MonoToStereo(&audioFrame);
722 }
723 // For true stereo mode (when we are receiving a stereo signal), no
724 // action is needed.
725
726 // Do the panning operation (the audio frame contains stereo at this
727 // stage)
728 AudioFrameOperations::Scale(_panLeft, _panRight, audioFrame);
729 }
730
731 // Mix decoded PCM output with file if file mixing is enabled
732 if (_outputFilePlaying)
733 {
734 MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
735 }
736
737 // Place channel in on-hold state (~muted) if on-hold is activated
738 if (_outputIsOnHold)
739 {
740 AudioFrameOperations::Mute(audioFrame);
741 }
742
743 // External media
744 if (_outputExternalMedia)
745 {
746 CriticalSectionScoped cs(&_callbackCritSect);
747 const bool isStereo = (audioFrame.num_channels_ == 2);
748 if (_outputExternalMediaCallbackPtr)
749 {
750 _outputExternalMediaCallbackPtr->Process(
751 _channelId,
752 kPlaybackPerChannel,
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000753 (int16_t*)audioFrame.data_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000754 audioFrame.samples_per_channel_,
755 audioFrame.sample_rate_hz_,
756 isStereo);
757 }
758 }
759
760 // Record playout if enabled
761 {
762 CriticalSectionScoped cs(&_fileCritSect);
763
764 if (_outputFileRecording && _outputFileRecorderPtr)
765 {
766 _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
767 }
768 }
769
770 // Measure audio level (0-9)
771 _outputAudioLevel.ComputeLevel(audioFrame);
772
773 return 0;
774}
775
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000776int32_t
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000777Channel::NeededFrequency(int32_t id)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000778{
779 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
780 "Channel::NeededFrequency(id=%d)", id);
781
782 int highestNeeded = 0;
783
784 // Determine highest needed receive frequency
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000785 int32_t receiveFrequency = _audioCodingModule.ReceiveFrequency();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000786
787 // Return the bigger of playout and receive frequency in the ACM.
788 if (_audioCodingModule.PlayoutFrequency() > receiveFrequency)
789 {
790 highestNeeded = _audioCodingModule.PlayoutFrequency();
791 }
792 else
793 {
794 highestNeeded = receiveFrequency;
795 }
796
797 // Special case, if we're playing a file on the playout side
798 // we take that frequency into consideration as well
799 // This is not needed on sending side, since the codec will
800 // limit the spectrum anyway.
801 if (_outputFilePlaying)
802 {
803 CriticalSectionScoped cs(&_fileCritSect);
804 if (_outputFilePlayerPtr && _outputFilePlaying)
805 {
806 if(_outputFilePlayerPtr->Frequency()>highestNeeded)
807 {
808 highestNeeded=_outputFilePlayerPtr->Frequency();
809 }
810 }
811 }
812
813 return(highestNeeded);
814}
815
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +0000816int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000817Channel::CreateChannel(Channel*& channel,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000818 int32_t channelId,
minyue@webrtc.org4489c512013-09-12 17:03:00 +0000819 uint32_t instanceId,
820 const Config& config)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000821{
822 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
823 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
824 channelId, instanceId);
825
minyue@webrtc.org4489c512013-09-12 17:03:00 +0000826 channel = new Channel(channelId, instanceId, config);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000827 if (channel == NULL)
828 {
829 WEBRTC_TRACE(kTraceMemory, kTraceVoice,
830 VoEId(instanceId,channelId),
831 "Channel::CreateChannel() unable to allocate memory for"
832 " channel");
833 return -1;
834 }
835 return 0;
836}
837
838void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000839Channel::PlayNotification(int32_t id, uint32_t durationMs)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000840{
841 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
842 "Channel::PlayNotification(id=%d, durationMs=%d)",
843 id, durationMs);
844
845 // Not implement yet
846}
847
848void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000849Channel::RecordNotification(int32_t id, uint32_t durationMs)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000850{
851 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
852 "Channel::RecordNotification(id=%d, durationMs=%d)",
853 id, durationMs);
854
855 // Not implement yet
856}
857
858void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000859Channel::PlayFileEnded(int32_t id)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000860{
861 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
862 "Channel::PlayFileEnded(id=%d)", id);
863
864 if (id == _inputFilePlayerId)
865 {
866 CriticalSectionScoped cs(&_fileCritSect);
867
868 _inputFilePlaying = false;
869 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
870 VoEId(_instanceId,_channelId),
871 "Channel::PlayFileEnded() => input file player module is"
872 " shutdown");
873 }
874 else if (id == _outputFilePlayerId)
875 {
876 CriticalSectionScoped cs(&_fileCritSect);
877
878 _outputFilePlaying = false;
879 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
880 VoEId(_instanceId,_channelId),
881 "Channel::PlayFileEnded() => output file player module is"
882 " shutdown");
883 }
884}
885
886void
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000887Channel::RecordFileEnded(int32_t id)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000888{
889 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
890 "Channel::RecordFileEnded(id=%d)", id);
891
892 assert(id == _outputFileRecorderId);
893
894 CriticalSectionScoped cs(&_fileCritSect);
895
896 _outputFileRecording = false;
897 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
898 VoEId(_instanceId,_channelId),
899 "Channel::RecordFileEnded() => output file recorder module is"
900 " shutdown");
901}
902
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +0000903Channel::Channel(int32_t channelId,
minyue@webrtc.org4489c512013-09-12 17:03:00 +0000904 uint32_t instanceId,
905 const Config& config) :
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000906 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
907 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
908 _instanceId(instanceId),
909 _channelId(channelId),
stefan@webrtc.org6696fba2013-05-29 12:12:51 +0000910 rtp_header_parser_(RtpHeaderParser::Create()),
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +0000911 rtp_payload_registry_(
912 new RTPPayloadRegistry(channelId,
913 RTPPayloadStrategy::CreateStrategy(true))),
914 rtp_receive_statistics_(ReceiveStatistics::Create(
915 Clock::GetRealTimeClock())),
916 rtp_receiver_(RtpReceiver::CreateAudioReceiver(
917 VoEModuleId(instanceId, channelId), Clock::GetRealTimeClock(), this,
918 this, this, rtp_payload_registry_.get())),
919 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
minyue@webrtc.org4489c512013-09-12 17:03:00 +0000920 _audioCodingModule(*config.Get<AudioCodingModuleFactory>().Create(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000921 VoEModuleId(instanceId, channelId))),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000922 _rtpDumpIn(*RtpDump::CreateRtpDump()),
923 _rtpDumpOut(*RtpDump::CreateRtpDump()),
924 _outputAudioLevel(),
925 _externalTransport(false),
926 _inputFilePlayerPtr(NULL),
927 _outputFilePlayerPtr(NULL),
928 _outputFileRecorderPtr(NULL),
929 // Avoid conflict with other channels by adding 1024 - 1026,
930 // won't use as much as 1024 channels.
931 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
932 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
933 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
934 _inputFilePlaying(false),
935 _outputFilePlaying(false),
936 _outputFileRecording(false),
937 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
938 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
939 _inputExternalMedia(false),
940 _outputExternalMedia(false),
941 _inputExternalMediaCallbackPtr(NULL),
942 _outputExternalMediaCallbackPtr(NULL),
943 _encryptionRTPBufferPtr(NULL),
944 _decryptionRTPBufferPtr(NULL),
945 _encryptionRTCPBufferPtr(NULL),
946 _decryptionRTCPBufferPtr(NULL),
947 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
948 _sendTelephoneEventPayloadType(106),
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +0000949 playout_timestamp_rtp_(0),
950 playout_timestamp_rtcp_(0),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000951 _numberOfDiscardedPackets(0),
xians@webrtc.org5ce87232013-07-31 16:30:19 +0000952 send_sequence_number_(0),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000953 _engineStatisticsPtr(NULL),
954 _outputMixerPtr(NULL),
955 _transmitMixerPtr(NULL),
956 _moduleProcessThreadPtr(NULL),
957 _audioDeviceModulePtr(NULL),
958 _voiceEngineObserverPtr(NULL),
959 _callbackCritSectPtr(NULL),
960 _transportPtr(NULL),
961 _encryptionPtr(NULL),
andrew@webrtc.org80142aa2013-09-18 22:37:32 +0000962 rtp_audioproc_(NULL),
963 rx_audioproc_(AudioProcessing::Create(VoEModuleId(instanceId, channelId))),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000964 _rxVadObserverPtr(NULL),
965 _oldVadDecision(-1),
966 _sendFrameType(0),
967 _rtpObserverPtr(NULL),
968 _rtcpObserverPtr(NULL),
969 _outputIsOnHold(false),
970 _externalPlayout(false),
roosa@google.comb9e3afc2012-12-12 23:00:29 +0000971 _externalMixing(false),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000972 _inputIsOnHold(false),
973 _playing(false),
974 _sending(false),
975 _receiving(false),
976 _mixFileWithMicrophone(false),
977 _rtpObserver(false),
978 _rtcpObserver(false),
979 _mute(false),
980 _panLeft(1.0f),
981 _panRight(1.0f),
982 _outputGain(1.0f),
983 _encrypting(false),
984 _decrypting(false),
985 _playOutbandDtmfEvent(false),
986 _playInbandDtmfEvent(false),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000987 _extraPayloadType(0),
988 _insertExtraRTPPacket(false),
989 _extraMarkerBit(false),
990 _lastLocalTimeStamp(0),
roosa@google.comca771492012-12-12 21:31:41 +0000991 _lastRemoteTimeStamp(0),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000992 _lastPayloadType(0),
993 _includeAudioLevelIndication(false),
994 _rtpPacketTimedOut(false),
995 _rtpPacketTimeOutIsEnabled(false),
996 _rtpTimeOutSeconds(0),
997 _connectionObserver(false),
998 _connectionObserverPtr(NULL),
999 _countAliveDetections(0),
1000 _countDeadDetections(0),
1001 _outputSpeechType(AudioFrame::kNormalSpeech),
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00001002 _average_jitter_buffer_delay_us(0),
turaj@webrtc.orgd5577342013-05-22 20:39:43 +00001003 least_required_delay_ms_(0),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001004 _previousTimestamp(0),
1005 _recPacketDelayMs(20),
1006 _RxVadDetection(false),
1007 _rxApmIsEnabled(false),
1008 _rxAgcIsEnabled(false),
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00001009 _rxNsIsEnabled(false),
1010 restored_packet_in_use_(false)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001011{
1012 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1013 "Channel::Channel() - ctor");
1014 _inbandDtmfQueue.ResetDtmf();
1015 _inbandDtmfGenerator.Init();
1016 _outputAudioLevel.Clear();
1017
1018 RtpRtcp::Configuration configuration;
1019 configuration.id = VoEModuleId(instanceId, channelId);
1020 configuration.audio = true;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001021 configuration.outgoing_transport = this;
1022 configuration.rtcp_feedback = this;
1023 configuration.audio_messages = this;
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001024 configuration.receive_statistics = rtp_receive_statistics_.get();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001025
1026 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001027}
1028
1029Channel::~Channel()
1030{
1031 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
1032 "Channel::~Channel() - dtor");
1033
1034 if (_outputExternalMedia)
1035 {
1036 DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
1037 }
1038 if (_inputExternalMedia)
1039 {
1040 DeRegisterExternalMediaProcessing(kRecordingPerChannel);
1041 }
1042 StopSend();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001043 StopPlayout();
1044
1045 {
1046 CriticalSectionScoped cs(&_fileCritSect);
1047 if (_inputFilePlayerPtr)
1048 {
1049 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1050 _inputFilePlayerPtr->StopPlayingFile();
1051 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
1052 _inputFilePlayerPtr = NULL;
1053 }
1054 if (_outputFilePlayerPtr)
1055 {
1056 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1057 _outputFilePlayerPtr->StopPlayingFile();
1058 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1059 _outputFilePlayerPtr = NULL;
1060 }
1061 if (_outputFileRecorderPtr)
1062 {
1063 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
1064 _outputFileRecorderPtr->StopRecording();
1065 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
1066 _outputFileRecorderPtr = NULL;
1067 }
1068 }
1069
1070 // The order to safely shutdown modules in a channel is:
1071 // 1. De-register callbacks in modules
1072 // 2. De-register modules in process thread
1073 // 3. Destroy modules
1074 if (_audioCodingModule.RegisterTransportCallback(NULL) == -1)
1075 {
1076 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1077 VoEId(_instanceId,_channelId),
1078 "~Channel() failed to de-register transport callback"
1079 " (Audio coding module)");
1080 }
1081 if (_audioCodingModule.RegisterVADCallback(NULL) == -1)
1082 {
1083 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1084 VoEId(_instanceId,_channelId),
1085 "~Channel() failed to de-register VAD callback"
1086 " (Audio coding module)");
1087 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001088 // De-register modules in process thread
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001089 if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
1090 {
1091 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1092 VoEId(_instanceId,_channelId),
1093 "~Channel() failed to deregister RTP/RTCP module");
1094 }
1095
1096 // Destroy modules
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001097 AudioCodingModule::Destroy(&_audioCodingModule);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001098
1099 // End of modules shutdown
1100
1101 // Delete other objects
1102 RtpDump::DestroyRtpDump(&_rtpDumpIn);
1103 RtpDump::DestroyRtpDump(&_rtpDumpOut);
1104 delete [] _encryptionRTPBufferPtr;
1105 delete [] _decryptionRTPBufferPtr;
1106 delete [] _encryptionRTCPBufferPtr;
1107 delete [] _decryptionRTCPBufferPtr;
1108 delete &_callbackCritSect;
1109 delete &_fileCritSect;
1110}
1111
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001112int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001113Channel::Init()
1114{
1115 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1116 "Channel::Init()");
1117
1118 // --- Initial sanity
1119
1120 if ((_engineStatisticsPtr == NULL) ||
1121 (_moduleProcessThreadPtr == NULL))
1122 {
1123 WEBRTC_TRACE(kTraceError, kTraceVoice,
1124 VoEId(_instanceId,_channelId),
1125 "Channel::Init() must call SetEngineInformation() first");
1126 return -1;
1127 }
1128
1129 // --- Add modules to process thread (for periodic schedulation)
1130
1131 const bool processThreadFail =
1132 ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001133 false);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001134 if (processThreadFail)
1135 {
1136 _engineStatisticsPtr->SetLastError(
1137 VE_CANNOT_INIT_CHANNEL, kTraceError,
1138 "Channel::Init() modules not registered");
1139 return -1;
1140 }
1141 // --- ACM initialization
1142
1143 if ((_audioCodingModule.InitializeReceiver() == -1) ||
1144#ifdef WEBRTC_CODEC_AVT
1145 // out-of-band Dtmf tones are played out by default
1146 (_audioCodingModule.SetDtmfPlayoutStatus(true) == -1) ||
1147#endif
1148 (_audioCodingModule.InitializeSender() == -1))
1149 {
1150 _engineStatisticsPtr->SetLastError(
1151 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1152 "Channel::Init() unable to initialize the ACM - 1");
1153 return -1;
1154 }
1155
1156 // --- RTP/RTCP module initialization
1157
1158 // Ensure that RTCP is enabled by default for the created channel.
1159 // Note that, the module will keep generating RTCP until it is explicitly
1160 // disabled by the user.
1161 // After StopListen (when no sockets exists), RTCP packets will no longer
1162 // be transmitted since the Transport object will then be invalid.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001163 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
1164 // RTCP is enabled by default.
1165 if (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001166 {
1167 _engineStatisticsPtr->SetLastError(
1168 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1169 "Channel::Init() RTP/RTCP module not initialized");
1170 return -1;
1171 }
1172
1173 // --- Register all permanent callbacks
1174 const bool fail =
1175 (_audioCodingModule.RegisterTransportCallback(this) == -1) ||
1176 (_audioCodingModule.RegisterVADCallback(this) == -1);
1177
1178 if (fail)
1179 {
1180 _engineStatisticsPtr->SetLastError(
1181 VE_CANNOT_INIT_CHANNEL, kTraceError,
1182 "Channel::Init() callbacks not registered");
1183 return -1;
1184 }
1185
1186 // --- Register all supported codecs to the receiving side of the
1187 // RTP/RTCP module
1188
1189 CodecInst codec;
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001190 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001191
1192 for (int idx = 0; idx < nSupportedCodecs; idx++)
1193 {
1194 // Open up the RTP/RTCP receiver for all supported codecs
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001195 if ((_audioCodingModule.Codec(idx, &codec) == -1) ||
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001196 (rtp_receiver_->RegisterReceivePayload(
1197 codec.plname,
1198 codec.pltype,
1199 codec.plfreq,
1200 codec.channels,
1201 (codec.rate < 0) ? 0 : codec.rate) == -1))
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001202 {
1203 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1204 VoEId(_instanceId,_channelId),
1205 "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1206 "to RTP/RTCP receiver",
1207 codec.plname, codec.pltype, codec.plfreq,
1208 codec.channels, codec.rate);
1209 }
1210 else
1211 {
1212 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1213 VoEId(_instanceId,_channelId),
1214 "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1215 "the RTP/RTCP receiver",
1216 codec.plname, codec.pltype, codec.plfreq,
1217 codec.channels, codec.rate);
1218 }
1219
1220 // Ensure that PCMU is used as default codec on the sending side
1221 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
1222 {
1223 SetSendCodec(codec);
1224 }
1225
1226 // Register default PT for outband 'telephone-event'
1227 if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1228 {
1229 if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
1230 (_audioCodingModule.RegisterReceiveCodec(codec) == -1))
1231 {
1232 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1233 VoEId(_instanceId,_channelId),
1234 "Channel::Init() failed to register outband "
1235 "'telephone-event' (%d/%d) correctly",
1236 codec.pltype, codec.plfreq);
1237 }
1238 }
1239
1240 if (!STR_CASE_CMP(codec.plname, "CN"))
1241 {
1242 if ((_audioCodingModule.RegisterSendCodec(codec) == -1) ||
1243 (_audioCodingModule.RegisterReceiveCodec(codec) == -1) ||
1244 (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
1245 {
1246 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1247 VoEId(_instanceId,_channelId),
1248 "Channel::Init() failed to register CN (%d/%d) "
1249 "correctly - 1",
1250 codec.pltype, codec.plfreq);
1251 }
1252 }
1253#ifdef WEBRTC_CODEC_RED
1254 // Register RED to the receiving side of the ACM.
1255 // We will not receive an OnInitializeDecoder() callback for RED.
1256 if (!STR_CASE_CMP(codec.plname, "RED"))
1257 {
1258 if (_audioCodingModule.RegisterReceiveCodec(codec) == -1)
1259 {
1260 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1261 VoEId(_instanceId,_channelId),
1262 "Channel::Init() failed to register RED (%d/%d) "
1263 "correctly",
1264 codec.pltype, codec.plfreq);
1265 }
1266 }
1267#endif
1268 }
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001269
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001270
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001271 if (rx_audioproc_->set_sample_rate_hz(8000))
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001272 {
1273 _engineStatisticsPtr->SetLastError(
1274 VE_APM_ERROR, kTraceWarning,
1275 "Channel::Init() failed to set the sample rate to 8K for"
1276 " far-end AP module");
1277 }
1278
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001279 if (rx_audioproc_->set_num_channels(1, 1) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001280 {
1281 _engineStatisticsPtr->SetLastError(
1282 VE_SOUNDCARD_ERROR, kTraceWarning,
1283 "Init() failed to set channels for the primary audio stream");
1284 }
1285
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001286 if (rx_audioproc_->high_pass_filter()->Enable(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001287 WEBRTC_VOICE_ENGINE_RX_HP_DEFAULT_STATE) != 0)
1288 {
1289 _engineStatisticsPtr->SetLastError(
1290 VE_APM_ERROR, kTraceWarning,
1291 "Channel::Init() failed to set the high-pass filter for"
1292 " far-end AP module");
1293 }
1294
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001295 if (rx_audioproc_->noise_suppression()->set_level(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001296 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE) != 0)
1297 {
1298 _engineStatisticsPtr->SetLastError(
1299 VE_APM_ERROR, kTraceWarning,
1300 "Init() failed to set noise reduction level for far-end"
1301 " AP module");
1302 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001303 if (rx_audioproc_->noise_suppression()->Enable(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001304 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_STATE) != 0)
1305 {
1306 _engineStatisticsPtr->SetLastError(
1307 VE_APM_ERROR, kTraceWarning,
1308 "Init() failed to set noise reduction state for far-end"
1309 " AP module");
1310 }
1311
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001312 if (rx_audioproc_->gain_control()->set_mode(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001313 (GainControl::Mode)WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_MODE) != 0)
1314 {
1315 _engineStatisticsPtr->SetLastError(
1316 VE_APM_ERROR, kTraceWarning,
1317 "Init() failed to set AGC mode for far-end AP module");
1318 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00001319 if (rx_audioproc_->gain_control()->Enable(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001320 WEBRTC_VOICE_ENGINE_RX_AGC_DEFAULT_STATE) != 0)
1321 {
1322 _engineStatisticsPtr->SetLastError(
1323 VE_APM_ERROR, kTraceWarning,
1324 "Init() failed to set AGC state for far-end AP module");
1325 }
1326
1327 return 0;
1328}
1329
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001330int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001331Channel::SetEngineInformation(Statistics& engineStatistics,
1332 OutputMixer& outputMixer,
1333 voe::TransmitMixer& transmitMixer,
1334 ProcessThread& moduleProcessThread,
1335 AudioDeviceModule& audioDeviceModule,
1336 VoiceEngineObserver* voiceEngineObserver,
1337 CriticalSectionWrapper* callbackCritSect)
1338{
1339 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1340 "Channel::SetEngineInformation()");
1341 _engineStatisticsPtr = &engineStatistics;
1342 _outputMixerPtr = &outputMixer;
1343 _transmitMixerPtr = &transmitMixer,
1344 _moduleProcessThreadPtr = &moduleProcessThread;
1345 _audioDeviceModulePtr = &audioDeviceModule;
1346 _voiceEngineObserverPtr = voiceEngineObserver;
1347 _callbackCritSectPtr = callbackCritSect;
1348 return 0;
1349}
1350
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001351int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001352Channel::UpdateLocalTimeStamp()
1353{
1354
1355 _timeStamp += _audioFrame.samples_per_channel_;
1356 return 0;
1357}
1358
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001359int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001360Channel::StartPlayout()
1361{
1362 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1363 "Channel::StartPlayout()");
1364 if (_playing)
1365 {
1366 return 0;
1367 }
roosa@google.comb9e3afc2012-12-12 23:00:29 +00001368
1369 if (!_externalMixing) {
1370 // Add participant as candidates for mixing.
1371 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1372 {
1373 _engineStatisticsPtr->SetLastError(
1374 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1375 "StartPlayout() failed to add participant to mixer");
1376 return -1;
1377 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001378 }
1379
1380 _playing = true;
1381
1382 if (RegisterFilePlayingToMixer() != 0)
1383 return -1;
1384
1385 return 0;
1386}
1387
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001388int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001389Channel::StopPlayout()
1390{
1391 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1392 "Channel::StopPlayout()");
1393 if (!_playing)
1394 {
1395 return 0;
1396 }
roosa@google.comb9e3afc2012-12-12 23:00:29 +00001397
1398 if (!_externalMixing) {
1399 // Remove participant as candidates for mixing
1400 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1401 {
1402 _engineStatisticsPtr->SetLastError(
1403 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1404 "StopPlayout() failed to remove participant from mixer");
1405 return -1;
1406 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001407 }
1408
1409 _playing = false;
1410 _outputAudioLevel.Clear();
1411
1412 return 0;
1413}
1414
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001415int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001416Channel::StartSend()
1417{
1418 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1419 "Channel::StartSend()");
xians@webrtc.org5ce87232013-07-31 16:30:19 +00001420 // Resume the previous sequence number which was reset by StopSend().
1421 // This needs to be done before |_sending| is set to true.
1422 if (send_sequence_number_)
1423 SetInitSequenceNumber(send_sequence_number_);
1424
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001425 {
1426 // A lock is needed because |_sending| can be accessed or modified by
1427 // another thread at the same time.
1428 CriticalSectionScoped cs(&_callbackCritSect);
1429
1430 if (_sending)
1431 {
1432 return 0;
1433 }
1434 _sending = true;
1435 }
1436
1437 if (_rtpRtcpModule->SetSendingStatus(true) != 0)
1438 {
1439 _engineStatisticsPtr->SetLastError(
1440 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1441 "StartSend() RTP/RTCP failed to start sending");
1442 CriticalSectionScoped cs(&_callbackCritSect);
1443 _sending = false;
1444 return -1;
1445 }
1446
1447 return 0;
1448}
1449
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001450int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001451Channel::StopSend()
1452{
1453 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1454 "Channel::StopSend()");
1455 {
1456 // A lock is needed because |_sending| can be accessed or modified by
1457 // another thread at the same time.
1458 CriticalSectionScoped cs(&_callbackCritSect);
1459
1460 if (!_sending)
1461 {
1462 return 0;
1463 }
1464 _sending = false;
1465 }
1466
xians@webrtc.org5ce87232013-07-31 16:30:19 +00001467 // Store the sequence number to be able to pick up the same sequence for
1468 // the next StartSend(). This is needed for restarting device, otherwise
1469 // it might cause libSRTP to complain about packets being replayed.
1470 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1471 // CL is landed. See issue
1472 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1473 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1474
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001475 // Reset sending SSRC and sequence number and triggers direct transmission
1476 // of RTCP BYE
1477 if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
1478 _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
1479 {
1480 _engineStatisticsPtr->SetLastError(
1481 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1482 "StartSend() RTP/RTCP failed to stop sending");
1483 }
1484
1485 return 0;
1486}
1487
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001488int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001489Channel::StartReceiving()
1490{
1491 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1492 "Channel::StartReceiving()");
1493 if (_receiving)
1494 {
1495 return 0;
1496 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001497 _receiving = true;
1498 _numberOfDiscardedPackets = 0;
1499 return 0;
1500}
1501
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001502int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001503Channel::StopReceiving()
1504{
1505 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1506 "Channel::StopReceiving()");
1507 if (!_receiving)
1508 {
1509 return 0;
1510 }
pwestin@webrtc.org912b7f72013-03-13 23:20:57 +00001511
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001512 // Recover DTMF detection status.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001513 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001514 RegisterReceiveCodecsToRTPModule();
1515 _receiving = false;
1516 return 0;
1517}
1518
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001519int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001520Channel::SetNetEQPlayoutMode(NetEqModes mode)
1521{
1522 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1523 "Channel::SetNetEQPlayoutMode()");
1524 AudioPlayoutMode playoutMode(voice);
1525 switch (mode)
1526 {
1527 case kNetEqDefault:
1528 playoutMode = voice;
1529 break;
1530 case kNetEqStreaming:
1531 playoutMode = streaming;
1532 break;
1533 case kNetEqFax:
1534 playoutMode = fax;
1535 break;
roosa@google.com90d333e2012-12-12 21:59:14 +00001536 case kNetEqOff:
1537 playoutMode = off;
1538 break;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001539 }
1540 if (_audioCodingModule.SetPlayoutMode(playoutMode) != 0)
1541 {
1542 _engineStatisticsPtr->SetLastError(
1543 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1544 "SetNetEQPlayoutMode() failed to set playout mode");
1545 return -1;
1546 }
1547 return 0;
1548}
1549
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001550int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001551Channel::GetNetEQPlayoutMode(NetEqModes& mode)
1552{
1553 const AudioPlayoutMode playoutMode = _audioCodingModule.PlayoutMode();
1554 switch (playoutMode)
1555 {
1556 case voice:
1557 mode = kNetEqDefault;
1558 break;
1559 case streaming:
1560 mode = kNetEqStreaming;
1561 break;
1562 case fax:
1563 mode = kNetEqFax;
1564 break;
roosa@google.com90d333e2012-12-12 21:59:14 +00001565 case off:
1566 mode = kNetEqOff;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001567 }
1568 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1569 VoEId(_instanceId,_channelId),
1570 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
1571 return 0;
1572}
1573
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001574int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001575Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
1576{
1577 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1578 "Channel::SetOnHoldStatus()");
1579 if (mode == kHoldSendAndPlay)
1580 {
1581 _outputIsOnHold = enable;
1582 _inputIsOnHold = enable;
1583 }
1584 else if (mode == kHoldPlayOnly)
1585 {
1586 _outputIsOnHold = enable;
1587 }
1588 if (mode == kHoldSendOnly)
1589 {
1590 _inputIsOnHold = enable;
1591 }
1592 return 0;
1593}
1594
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001595int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001596Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
1597{
1598 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1599 "Channel::GetOnHoldStatus()");
1600 enabled = (_outputIsOnHold || _inputIsOnHold);
1601 if (_outputIsOnHold && _inputIsOnHold)
1602 {
1603 mode = kHoldSendAndPlay;
1604 }
1605 else if (_outputIsOnHold && !_inputIsOnHold)
1606 {
1607 mode = kHoldPlayOnly;
1608 }
1609 else if (!_outputIsOnHold && _inputIsOnHold)
1610 {
1611 mode = kHoldSendOnly;
1612 }
1613 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1614 "Channel::GetOnHoldStatus() => enabled=%d, mode=%d",
1615 enabled, mode);
1616 return 0;
1617}
1618
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001619int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001620Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
1621{
1622 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1623 "Channel::RegisterVoiceEngineObserver()");
1624 CriticalSectionScoped cs(&_callbackCritSect);
1625
1626 if (_voiceEngineObserverPtr)
1627 {
1628 _engineStatisticsPtr->SetLastError(
1629 VE_INVALID_OPERATION, kTraceError,
1630 "RegisterVoiceEngineObserver() observer already enabled");
1631 return -1;
1632 }
1633 _voiceEngineObserverPtr = &observer;
1634 return 0;
1635}
1636
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001637int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001638Channel::DeRegisterVoiceEngineObserver()
1639{
1640 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1641 "Channel::DeRegisterVoiceEngineObserver()");
1642 CriticalSectionScoped cs(&_callbackCritSect);
1643
1644 if (!_voiceEngineObserverPtr)
1645 {
1646 _engineStatisticsPtr->SetLastError(
1647 VE_INVALID_OPERATION, kTraceWarning,
1648 "DeRegisterVoiceEngineObserver() observer already disabled");
1649 return 0;
1650 }
1651 _voiceEngineObserverPtr = NULL;
1652 return 0;
1653}
1654
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001655int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001656Channel::GetSendCodec(CodecInst& codec)
1657{
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001658 return (_audioCodingModule.SendCodec(&codec));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001659}
1660
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001661int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001662Channel::GetRecCodec(CodecInst& codec)
1663{
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001664 return (_audioCodingModule.ReceiveCodec(&codec));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001665}
1666
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001667int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001668Channel::SetSendCodec(const CodecInst& codec)
1669{
1670 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1671 "Channel::SetSendCodec()");
1672
1673 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
1674 {
1675 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1676 "SetSendCodec() failed to register codec to ACM");
1677 return -1;
1678 }
1679
1680 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1681 {
1682 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1683 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1684 {
1685 WEBRTC_TRACE(
1686 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1687 "SetSendCodec() failed to register codec to"
1688 " RTP/RTCP module");
1689 return -1;
1690 }
1691 }
1692
1693 if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
1694 {
1695 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1696 "SetSendCodec() failed to set audio packet size");
1697 return -1;
1698 }
1699
1700 return 0;
1701}
1702
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001703int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001704Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
1705{
1706 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1707 "Channel::SetVADStatus(mode=%d)", mode);
1708 // To disable VAD, DTX must be disabled too
1709 disableDTX = ((enableVAD == false) ? true : disableDTX);
1710 if (_audioCodingModule.SetVAD(!disableDTX, enableVAD, mode) != 0)
1711 {
1712 _engineStatisticsPtr->SetLastError(
1713 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1714 "SetVADStatus() failed to set VAD");
1715 return -1;
1716 }
1717 return 0;
1718}
1719
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001720int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001721Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
1722{
1723 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1724 "Channel::GetVADStatus");
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001725 if (_audioCodingModule.VAD(&disabledDTX, &enabledVAD, &mode) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001726 {
1727 _engineStatisticsPtr->SetLastError(
1728 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1729 "GetVADStatus() failed to get VAD status");
1730 return -1;
1731 }
1732 disabledDTX = !disabledDTX;
1733 return 0;
1734}
1735
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001736int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001737Channel::SetRecPayloadType(const CodecInst& codec)
1738{
1739 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1740 "Channel::SetRecPayloadType()");
1741
1742 if (_playing)
1743 {
1744 _engineStatisticsPtr->SetLastError(
1745 VE_ALREADY_PLAYING, kTraceError,
1746 "SetRecPayloadType() unable to set PT while playing");
1747 return -1;
1748 }
1749 if (_receiving)
1750 {
1751 _engineStatisticsPtr->SetLastError(
1752 VE_ALREADY_LISTENING, kTraceError,
1753 "SetRecPayloadType() unable to set PT while listening");
1754 return -1;
1755 }
1756
1757 if (codec.pltype == -1)
1758 {
1759 // De-register the selected codec (RTP/RTCP module and ACM)
1760
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001761 int8_t pltype(-1);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001762 CodecInst rxCodec = codec;
1763
1764 // Get payload type for the given codec
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001765 rtp_payload_registry_->ReceivePayloadType(
1766 rxCodec.plname,
1767 rxCodec.plfreq,
1768 rxCodec.channels,
1769 (rxCodec.rate < 0) ? 0 : rxCodec.rate,
1770 &pltype);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001771 rxCodec.pltype = pltype;
1772
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001773 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001774 {
1775 _engineStatisticsPtr->SetLastError(
1776 VE_RTP_RTCP_MODULE_ERROR,
1777 kTraceError,
1778 "SetRecPayloadType() RTP/RTCP-module deregistration "
1779 "failed");
1780 return -1;
1781 }
1782 if (_audioCodingModule.UnregisterReceiveCodec(rxCodec.pltype) != 0)
1783 {
1784 _engineStatisticsPtr->SetLastError(
1785 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1786 "SetRecPayloadType() ACM deregistration failed - 1");
1787 return -1;
1788 }
1789 return 0;
1790 }
1791
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001792 if (rtp_receiver_->RegisterReceivePayload(
1793 codec.plname,
1794 codec.pltype,
1795 codec.plfreq,
1796 codec.channels,
1797 (codec.rate < 0) ? 0 : codec.rate) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001798 {
1799 // First attempt to register failed => de-register and try again
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001800 rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
1801 if (rtp_receiver_->RegisterReceivePayload(
1802 codec.plname,
1803 codec.pltype,
1804 codec.plfreq,
1805 codec.channels,
1806 (codec.rate < 0) ? 0 : codec.rate) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001807 {
1808 _engineStatisticsPtr->SetLastError(
1809 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1810 "SetRecPayloadType() RTP/RTCP-module registration failed");
1811 return -1;
1812 }
1813 }
1814 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
1815 {
1816 _audioCodingModule.UnregisterReceiveCodec(codec.pltype);
1817 if (_audioCodingModule.RegisterReceiveCodec(codec) != 0)
1818 {
1819 _engineStatisticsPtr->SetLastError(
1820 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1821 "SetRecPayloadType() ACM registration failed - 1");
1822 return -1;
1823 }
1824 }
1825 return 0;
1826}
1827
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001828int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001829Channel::GetRecPayloadType(CodecInst& codec)
1830{
1831 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1832 "Channel::GetRecPayloadType()");
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001833 int8_t payloadType(-1);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00001834 if (rtp_payload_registry_->ReceivePayloadType(
1835 codec.plname,
1836 codec.plfreq,
1837 codec.channels,
1838 (codec.rate < 0) ? 0 : codec.rate,
1839 &payloadType) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001840 {
1841 _engineStatisticsPtr->SetLastError(
1842 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1843 "GetRecPayloadType() failed to retrieve RX payload type");
1844 return -1;
1845 }
1846 codec.pltype = payloadType;
1847 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1848 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
1849 return 0;
1850}
1851
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001852int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001853Channel::SetAMREncFormat(AmrMode mode)
1854{
1855 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1856 "Channel::SetAMREncFormat()");
1857
1858 // ACM doesn't support AMR
1859 return -1;
1860}
1861
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001862int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001863Channel::SetAMRDecFormat(AmrMode mode)
1864{
1865 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1866 "Channel::SetAMRDecFormat()");
1867
1868 // ACM doesn't support AMR
1869 return -1;
1870}
1871
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001872int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001873Channel::SetAMRWbEncFormat(AmrMode mode)
1874{
1875 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1876 "Channel::SetAMRWbEncFormat()");
1877
1878 // ACM doesn't support AMR
1879 return -1;
1880
1881}
1882
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001883int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001884Channel::SetAMRWbDecFormat(AmrMode mode)
1885{
1886 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1887 "Channel::SetAMRWbDecFormat()");
1888
1889 // ACM doesn't support AMR
1890 return -1;
1891}
1892
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001893int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001894Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
1895{
1896 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1897 "Channel::SetSendCNPayloadType()");
1898
1899 CodecInst codec;
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001900 int32_t samplingFreqHz(-1);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001901 const int kMono = 1;
1902 if (frequency == kFreq32000Hz)
1903 samplingFreqHz = 32000;
1904 else if (frequency == kFreq16000Hz)
1905 samplingFreqHz = 16000;
1906
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001907 if (_audioCodingModule.Codec("CN", &codec, samplingFreqHz, kMono) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001908 {
1909 _engineStatisticsPtr->SetLastError(
1910 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1911 "SetSendCNPayloadType() failed to retrieve default CN codec "
1912 "settings");
1913 return -1;
1914 }
1915
1916 // Modify the payload type (must be set to dynamic range)
1917 codec.pltype = type;
1918
1919 if (_audioCodingModule.RegisterSendCodec(codec) != 0)
1920 {
1921 _engineStatisticsPtr->SetLastError(
1922 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1923 "SetSendCNPayloadType() failed to register CN to ACM");
1924 return -1;
1925 }
1926
1927 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1928 {
1929 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1930 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1931 {
1932 _engineStatisticsPtr->SetLastError(
1933 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1934 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1935 "module");
1936 return -1;
1937 }
1938 }
1939 return 0;
1940}
1941
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001942int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001943Channel::SetISACInitTargetRate(int rateBps, bool useFixedFrameSize)
1944{
1945 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1946 "Channel::SetISACInitTargetRate()");
1947
1948 CodecInst sendCodec;
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00001949 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001950 {
1951 _engineStatisticsPtr->SetLastError(
1952 VE_CODEC_ERROR, kTraceError,
1953 "SetISACInitTargetRate() failed to retrieve send codec");
1954 return -1;
1955 }
1956 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
1957 {
1958 // This API is only valid if iSAC is setup to run in channel-adaptive
1959 // mode.
1960 // We do not validate the adaptive mode here. It is done later in the
1961 // ConfigISACBandwidthEstimator() API.
1962 _engineStatisticsPtr->SetLastError(
1963 VE_CODEC_ERROR, kTraceError,
1964 "SetISACInitTargetRate() send codec is not iSAC");
1965 return -1;
1966 }
1967
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001968 uint8_t initFrameSizeMsec(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001969 if (16000 == sendCodec.plfreq)
1970 {
1971 // Note that 0 is a valid and corresponds to "use default
1972 if ((rateBps != 0 &&
1973 rateBps < kVoiceEngineMinIsacInitTargetRateBpsWb) ||
1974 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsWb))
1975 {
1976 _engineStatisticsPtr->SetLastError(
1977 VE_INVALID_ARGUMENT, kTraceError,
1978 "SetISACInitTargetRate() invalid target rate - 1");
1979 return -1;
1980 }
1981 // 30 or 60ms
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001982 initFrameSizeMsec = (uint8_t)(sendCodec.pacsize / 16);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001983 }
1984 else if (32000 == sendCodec.plfreq)
1985 {
1986 if ((rateBps != 0 &&
1987 rateBps < kVoiceEngineMinIsacInitTargetRateBpsSwb) ||
1988 (rateBps > kVoiceEngineMaxIsacInitTargetRateBpsSwb))
1989 {
1990 _engineStatisticsPtr->SetLastError(
1991 VE_INVALID_ARGUMENT, kTraceError,
1992 "SetISACInitTargetRate() invalid target rate - 2");
1993 return -1;
1994 }
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00001995 initFrameSizeMsec = (uint8_t)(sendCodec.pacsize / 32); // 30ms
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001996 }
1997
1998 if (_audioCodingModule.ConfigISACBandwidthEstimator(
1999 initFrameSizeMsec, rateBps, useFixedFrameSize) == -1)
2000 {
2001 _engineStatisticsPtr->SetLastError(
2002 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2003 "SetISACInitTargetRate() iSAC BWE config failed");
2004 return -1;
2005 }
2006
2007 return 0;
2008}
2009
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002010int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002011Channel::SetISACMaxRate(int rateBps)
2012{
2013 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2014 "Channel::SetISACMaxRate()");
2015
2016 CodecInst sendCodec;
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00002017 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002018 {
2019 _engineStatisticsPtr->SetLastError(
2020 VE_CODEC_ERROR, kTraceError,
2021 "SetISACMaxRate() failed to retrieve send codec");
2022 return -1;
2023 }
2024 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2025 {
2026 // This API is only valid if iSAC is selected as sending codec.
2027 _engineStatisticsPtr->SetLastError(
2028 VE_CODEC_ERROR, kTraceError,
2029 "SetISACMaxRate() send codec is not iSAC");
2030 return -1;
2031 }
2032 if (16000 == sendCodec.plfreq)
2033 {
2034 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsWb) ||
2035 (rateBps > kVoiceEngineMaxIsacMaxRateBpsWb))
2036 {
2037 _engineStatisticsPtr->SetLastError(
2038 VE_INVALID_ARGUMENT, kTraceError,
2039 "SetISACMaxRate() invalid max rate - 1");
2040 return -1;
2041 }
2042 }
2043 else if (32000 == sendCodec.plfreq)
2044 {
2045 if ((rateBps < kVoiceEngineMinIsacMaxRateBpsSwb) ||
2046 (rateBps > kVoiceEngineMaxIsacMaxRateBpsSwb))
2047 {
2048 _engineStatisticsPtr->SetLastError(
2049 VE_INVALID_ARGUMENT, kTraceError,
2050 "SetISACMaxRate() invalid max rate - 2");
2051 return -1;
2052 }
2053 }
2054 if (_sending)
2055 {
2056 _engineStatisticsPtr->SetLastError(
2057 VE_SENDING, kTraceError,
2058 "SetISACMaxRate() unable to set max rate while sending");
2059 return -1;
2060 }
2061
2062 // Set the maximum instantaneous rate of iSAC (works for both adaptive
2063 // and non-adaptive mode)
2064 if (_audioCodingModule.SetISACMaxRate(rateBps) == -1)
2065 {
2066 _engineStatisticsPtr->SetLastError(
2067 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2068 "SetISACMaxRate() failed to set max rate");
2069 return -1;
2070 }
2071
2072 return 0;
2073}
2074
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002075int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002076Channel::SetISACMaxPayloadSize(int sizeBytes)
2077{
2078 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2079 "Channel::SetISACMaxPayloadSize()");
2080 CodecInst sendCodec;
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00002081 if (_audioCodingModule.SendCodec(&sendCodec) == -1)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002082 {
2083 _engineStatisticsPtr->SetLastError(
2084 VE_CODEC_ERROR, kTraceError,
2085 "SetISACMaxPayloadSize() failed to retrieve send codec");
2086 return -1;
2087 }
2088 if (STR_CASE_CMP(sendCodec.plname, "ISAC") != 0)
2089 {
2090 _engineStatisticsPtr->SetLastError(
2091 VE_CODEC_ERROR, kTraceError,
2092 "SetISACMaxPayloadSize() send codec is not iSAC");
2093 return -1;
2094 }
2095 if (16000 == sendCodec.plfreq)
2096 {
2097 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesWb) ||
2098 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesWb))
2099 {
2100 _engineStatisticsPtr->SetLastError(
2101 VE_INVALID_ARGUMENT, kTraceError,
2102 "SetISACMaxPayloadSize() invalid max payload - 1");
2103 return -1;
2104 }
2105 }
2106 else if (32000 == sendCodec.plfreq)
2107 {
2108 if ((sizeBytes < kVoiceEngineMinIsacMaxPayloadSizeBytesSwb) ||
2109 (sizeBytes > kVoiceEngineMaxIsacMaxPayloadSizeBytesSwb))
2110 {
2111 _engineStatisticsPtr->SetLastError(
2112 VE_INVALID_ARGUMENT, kTraceError,
2113 "SetISACMaxPayloadSize() invalid max payload - 2");
2114 return -1;
2115 }
2116 }
2117 if (_sending)
2118 {
2119 _engineStatisticsPtr->SetLastError(
2120 VE_SENDING, kTraceError,
2121 "SetISACMaxPayloadSize() unable to set max rate while sending");
2122 return -1;
2123 }
2124
2125 if (_audioCodingModule.SetISACMaxPayloadSize(sizeBytes) == -1)
2126 {
2127 _engineStatisticsPtr->SetLastError(
2128 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2129 "SetISACMaxPayloadSize() failed to set max payload size");
2130 return -1;
2131 }
2132 return 0;
2133}
2134
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002135int32_t Channel::RegisterExternalTransport(Transport& transport)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002136{
2137 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2138 "Channel::RegisterExternalTransport()");
2139
2140 CriticalSectionScoped cs(&_callbackCritSect);
2141
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002142 if (_externalTransport)
2143 {
2144 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
2145 kTraceError,
2146 "RegisterExternalTransport() external transport already enabled");
2147 return -1;
2148 }
2149 _externalTransport = true;
2150 _transportPtr = &transport;
2151 return 0;
2152}
2153
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002154int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002155Channel::DeRegisterExternalTransport()
2156{
2157 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2158 "Channel::DeRegisterExternalTransport()");
2159
2160 CriticalSectionScoped cs(&_callbackCritSect);
2161
2162 if (!_transportPtr)
2163 {
2164 _engineStatisticsPtr->SetLastError(
2165 VE_INVALID_OPERATION, kTraceWarning,
2166 "DeRegisterExternalTransport() external transport already "
2167 "disabled");
2168 return 0;
2169 }
2170 _externalTransport = false;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002171 _transportPtr = NULL;
2172 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2173 "DeRegisterExternalTransport() all transport is disabled");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002174 return 0;
2175}
2176
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002177int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length) {
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002178 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2179 "Channel::ReceivedRTPPacket()");
2180
2181 // Store playout timestamp for the received RTP packet
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00002182 UpdatePlayoutTimestamp(false);
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002183
2184 // Dump the RTP packet to a file (if RTP dump is enabled).
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002185 if (_rtpDumpIn.DumpPacket((const uint8_t*)data,
2186 (uint16_t)length) == -1) {
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002187 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
2188 VoEId(_instanceId,_channelId),
2189 "Channel::SendPacket() RTP dump to input file failed");
2190 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002191 const uint8_t* received_packet = reinterpret_cast<const uint8_t*>(data);
stefan@webrtc.org6696fba2013-05-29 12:12:51 +00002192 RTPHeader header;
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002193 if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
2194 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
2195 "Incoming packet: invalid RTP header");
stefan@webrtc.org6696fba2013-05-29 12:12:51 +00002196 return -1;
2197 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002198 header.payload_type_frequency =
2199 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002200 if (header.payload_type_frequency < 0)
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002201 return -1;
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002202 rtp_receive_statistics_->IncomingPacket(header, length,
2203 IsPacketRetransmitted(header));
2204 rtp_payload_registry_->SetIncomingPayloadType(header);
2205 return ReceivePacket(received_packet, length, header,
2206 IsPacketInOrder(header)) ? 0 : -1;
2207}
2208
2209bool Channel::ReceivePacket(const uint8_t* packet,
2210 int packet_length,
2211 const RTPHeader& header,
2212 bool in_order) {
2213 if (rtp_payload_registry_->IsEncapsulated(header)) {
2214 return HandleEncapsulation(packet, packet_length, header);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002215 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002216 const uint8_t* payload = packet + header.headerLength;
2217 int payload_length = packet_length - header.headerLength;
2218 assert(payload_length >= 0);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002219 PayloadUnion payload_specific;
2220 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002221 &payload_specific)) {
2222 return false;
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002223 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002224 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
2225 payload_specific, in_order);
2226}
2227
2228bool Channel::HandleEncapsulation(const uint8_t* packet,
2229 int packet_length,
2230 const RTPHeader& header) {
2231 if (!rtp_payload_registry_->IsRtx(header))
2232 return false;
2233
2234 // Remove the RTX header and parse the original RTP header.
2235 if (packet_length < header.headerLength)
2236 return false;
2237 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
2238 return false;
2239 if (restored_packet_in_use_) {
2240 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
2241 "Multiple RTX headers detected, dropping packet");
2242 return false;
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002243 }
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002244 uint8_t* restored_packet_ptr = restored_packet_;
2245 if (!rtp_payload_registry_->RestoreOriginalPacket(
2246 &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
2247 header)) {
2248 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
2249 "Incoming RTX packet: invalid RTP header");
2250 return false;
2251 }
2252 restored_packet_in_use_ = true;
2253 bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
2254 restored_packet_in_use_ = false;
2255 return ret;
2256}
2257
2258bool Channel::IsPacketInOrder(const RTPHeader& header) const {
2259 StreamStatistician* statistician =
2260 rtp_receive_statistics_->GetStatistician(header.ssrc);
2261 if (!statistician)
2262 return false;
2263 return statistician->IsPacketInOrder(header.sequenceNumber);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002264}
2265
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002266bool Channel::IsPacketRetransmitted(const RTPHeader& header) const {
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00002267 // Retransmissions are handled separately if RTX is enabled.
2268 if (rtp_payload_registry_->RtxEnabled())
2269 return false;
2270 StreamStatistician* statistician =
2271 rtp_receive_statistics_->GetStatistician(header.ssrc);
2272 if (!statistician)
2273 return false;
2274 // Check if this is a retransmission.
2275 uint16_t min_rtt = 0;
2276 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
2277 return !IsPacketInOrder(header) &&
2278 statistician->IsRetransmitOfOldPacket(header, min_rtt);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00002279}
2280
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002281int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) {
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002282 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2283 "Channel::ReceivedRTCPPacket()");
2284 // Store playout timestamp for the received RTCP packet
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00002285 UpdatePlayoutTimestamp(true);
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002286
2287 // Dump the RTCP packet to a file (if RTP dump is enabled).
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002288 if (_rtpDumpIn.DumpPacket((const uint8_t*)data,
2289 (uint16_t)length) == -1) {
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002290 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
2291 VoEId(_instanceId,_channelId),
2292 "Channel::SendPacket() RTCP dump to input file failed");
2293 }
2294
2295 // Deliver RTCP packet to RTP/RTCP module for parsing
stefan@webrtc.org6696fba2013-05-29 12:12:51 +00002296 if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data,
2297 (uint16_t)length) == -1) {
pwestin@webrtc.orge4932182013-04-03 15:43:57 +00002298 _engineStatisticsPtr->SetLastError(
2299 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
2300 "Channel::IncomingRTPPacket() RTCP packet is invalid");
2301 }
2302 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002303}
2304
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002305int Channel::StartPlayingFileLocally(const char* fileName,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002306 bool loop,
2307 FileFormats format,
2308 int startPosition,
2309 float volumeScaling,
2310 int stopPosition,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002311 const CodecInst* codecInst)
2312{
2313 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2314 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
2315 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
2316 "stopPosition=%d)", fileName, loop, format, volumeScaling,
2317 startPosition, stopPosition);
2318
2319 if (_outputFilePlaying)
2320 {
2321 _engineStatisticsPtr->SetLastError(
2322 VE_ALREADY_PLAYING, kTraceError,
2323 "StartPlayingFileLocally() is already playing");
2324 return -1;
2325 }
2326
2327 {
2328 CriticalSectionScoped cs(&_fileCritSect);
2329
2330 if (_outputFilePlayerPtr)
2331 {
2332 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2333 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2334 _outputFilePlayerPtr = NULL;
2335 }
2336
2337 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2338 _outputFilePlayerId, (const FileFormats)format);
2339
2340 if (_outputFilePlayerPtr == NULL)
2341 {
2342 _engineStatisticsPtr->SetLastError(
2343 VE_INVALID_ARGUMENT, kTraceError,
2344 "StartPlayingFileLocally() filePlayer format is not correct");
2345 return -1;
2346 }
2347
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002348 const uint32_t notificationTime(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002349
2350 if (_outputFilePlayerPtr->StartPlayingFile(
2351 fileName,
2352 loop,
2353 startPosition,
2354 volumeScaling,
2355 notificationTime,
2356 stopPosition,
2357 (const CodecInst*)codecInst) != 0)
2358 {
2359 _engineStatisticsPtr->SetLastError(
2360 VE_BAD_FILE, kTraceError,
2361 "StartPlayingFile() failed to start file playout");
2362 _outputFilePlayerPtr->StopPlayingFile();
2363 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2364 _outputFilePlayerPtr = NULL;
2365 return -1;
2366 }
2367 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
2368 _outputFilePlaying = true;
2369 }
2370
2371 if (RegisterFilePlayingToMixer() != 0)
2372 return -1;
2373
2374 return 0;
2375}
2376
2377int Channel::StartPlayingFileLocally(InStream* stream,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002378 FileFormats format,
2379 int startPosition,
2380 float volumeScaling,
2381 int stopPosition,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002382 const CodecInst* codecInst)
2383{
2384 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2385 "Channel::StartPlayingFileLocally(format=%d,"
2386 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2387 format, volumeScaling, startPosition, stopPosition);
2388
2389 if(stream == NULL)
2390 {
2391 _engineStatisticsPtr->SetLastError(
2392 VE_BAD_FILE, kTraceError,
2393 "StartPlayingFileLocally() NULL as input stream");
2394 return -1;
2395 }
2396
2397
2398 if (_outputFilePlaying)
2399 {
2400 _engineStatisticsPtr->SetLastError(
2401 VE_ALREADY_PLAYING, kTraceError,
2402 "StartPlayingFileLocally() is already playing");
2403 return -1;
2404 }
2405
2406 {
2407 CriticalSectionScoped cs(&_fileCritSect);
2408
2409 // Destroy the old instance
2410 if (_outputFilePlayerPtr)
2411 {
2412 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2413 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2414 _outputFilePlayerPtr = NULL;
2415 }
2416
2417 // Create the instance
2418 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2419 _outputFilePlayerId,
2420 (const FileFormats)format);
2421
2422 if (_outputFilePlayerPtr == NULL)
2423 {
2424 _engineStatisticsPtr->SetLastError(
2425 VE_INVALID_ARGUMENT, kTraceError,
2426 "StartPlayingFileLocally() filePlayer format isnot correct");
2427 return -1;
2428 }
2429
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002430 const uint32_t notificationTime(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002431
2432 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
2433 volumeScaling,
2434 notificationTime,
2435 stopPosition, codecInst) != 0)
2436 {
2437 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2438 "StartPlayingFile() failed to "
2439 "start file playout");
2440 _outputFilePlayerPtr->StopPlayingFile();
2441 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2442 _outputFilePlayerPtr = NULL;
2443 return -1;
2444 }
2445 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
2446 _outputFilePlaying = true;
2447 }
2448
2449 if (RegisterFilePlayingToMixer() != 0)
2450 return -1;
2451
2452 return 0;
2453}
2454
2455int Channel::StopPlayingFileLocally()
2456{
2457 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2458 "Channel::StopPlayingFileLocally()");
2459
2460 if (!_outputFilePlaying)
2461 {
2462 _engineStatisticsPtr->SetLastError(
2463 VE_INVALID_OPERATION, kTraceWarning,
2464 "StopPlayingFileLocally() isnot playing");
2465 return 0;
2466 }
2467
2468 {
2469 CriticalSectionScoped cs(&_fileCritSect);
2470
2471 if (_outputFilePlayerPtr->StopPlayingFile() != 0)
2472 {
2473 _engineStatisticsPtr->SetLastError(
2474 VE_STOP_RECORDING_FAILED, kTraceError,
2475 "StopPlayingFile() could not stop playing");
2476 return -1;
2477 }
2478 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2479 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2480 _outputFilePlayerPtr = NULL;
2481 _outputFilePlaying = false;
2482 }
2483 // _fileCritSect cannot be taken while calling
2484 // SetAnonymousMixibilityStatus. Refer to comments in
2485 // StartPlayingFileLocally(const char* ...) for more details.
2486 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
2487 {
2488 _engineStatisticsPtr->SetLastError(
2489 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
2490 "StopPlayingFile() failed to stop participant from playing as"
2491 "file in the mixer");
2492 return -1;
2493 }
2494
2495 return 0;
2496}
2497
2498int Channel::IsPlayingFileLocally() const
2499{
2500 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2501 "Channel::IsPlayingFileLocally()");
2502
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002503 return (int32_t)_outputFilePlaying;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002504}
2505
2506int Channel::RegisterFilePlayingToMixer()
2507{
2508 // Return success for not registering for file playing to mixer if:
2509 // 1. playing file before playout is started on that channel.
2510 // 2. starting playout without file playing on that channel.
2511 if (!_playing || !_outputFilePlaying)
2512 {
2513 return 0;
2514 }
2515
2516 // |_fileCritSect| cannot be taken while calling
2517 // SetAnonymousMixabilityStatus() since as soon as the participant is added
2518 // frames can be pulled by the mixer. Since the frames are generated from
2519 // the file, _fileCritSect will be taken. This would result in a deadlock.
2520 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
2521 {
2522 CriticalSectionScoped cs(&_fileCritSect);
2523 _outputFilePlaying = false;
2524 _engineStatisticsPtr->SetLastError(
2525 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
2526 "StartPlayingFile() failed to add participant as file to mixer");
2527 _outputFilePlayerPtr->StopPlayingFile();
2528 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2529 _outputFilePlayerPtr = NULL;
2530 return -1;
2531 }
2532
2533 return 0;
2534}
2535
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002536int Channel::ScaleLocalFilePlayout(float scale)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002537{
2538 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2539 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
2540
2541 CriticalSectionScoped cs(&_fileCritSect);
2542
2543 if (!_outputFilePlaying)
2544 {
2545 _engineStatisticsPtr->SetLastError(
2546 VE_INVALID_OPERATION, kTraceError,
2547 "ScaleLocalFilePlayout() isnot playing");
2548 return -1;
2549 }
2550 if ((_outputFilePlayerPtr == NULL) ||
2551 (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
2552 {
2553 _engineStatisticsPtr->SetLastError(
2554 VE_BAD_ARGUMENT, kTraceError,
2555 "SetAudioScaling() failed to scale the playout");
2556 return -1;
2557 }
2558
2559 return 0;
2560}
2561
2562int Channel::GetLocalPlayoutPosition(int& positionMs)
2563{
2564 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2565 "Channel::GetLocalPlayoutPosition(position=?)");
2566
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002567 uint32_t position;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002568
2569 CriticalSectionScoped cs(&_fileCritSect);
2570
2571 if (_outputFilePlayerPtr == NULL)
2572 {
2573 _engineStatisticsPtr->SetLastError(
2574 VE_INVALID_OPERATION, kTraceError,
2575 "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
2576 return -1;
2577 }
2578
2579 if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
2580 {
2581 _engineStatisticsPtr->SetLastError(
2582 VE_BAD_FILE, kTraceError,
2583 "GetLocalPlayoutPosition() failed");
2584 return -1;
2585 }
2586 positionMs = position;
2587
2588 return 0;
2589}
2590
2591int Channel::StartPlayingFileAsMicrophone(const char* fileName,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002592 bool loop,
2593 FileFormats format,
2594 int startPosition,
2595 float volumeScaling,
2596 int stopPosition,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002597 const CodecInst* codecInst)
2598{
2599 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2600 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
2601 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
2602 "stopPosition=%d)", fileName, loop, format, volumeScaling,
2603 startPosition, stopPosition);
2604
2605 if (_inputFilePlaying)
2606 {
2607 _engineStatisticsPtr->SetLastError(
2608 VE_ALREADY_PLAYING, kTraceWarning,
2609 "StartPlayingFileAsMicrophone() filePlayer is playing");
2610 return 0;
2611 }
2612
2613 CriticalSectionScoped cs(&_fileCritSect);
2614
2615 // Destroy the old instance
2616 if (_inputFilePlayerPtr)
2617 {
2618 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2619 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2620 _inputFilePlayerPtr = NULL;
2621 }
2622
2623 // Create the instance
2624 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2625 _inputFilePlayerId, (const FileFormats)format);
2626
2627 if (_inputFilePlayerPtr == NULL)
2628 {
2629 _engineStatisticsPtr->SetLastError(
2630 VE_INVALID_ARGUMENT, kTraceError,
2631 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
2632 return -1;
2633 }
2634
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002635 const uint32_t notificationTime(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002636
2637 if (_inputFilePlayerPtr->StartPlayingFile(
2638 fileName,
2639 loop,
2640 startPosition,
2641 volumeScaling,
2642 notificationTime,
2643 stopPosition,
2644 (const CodecInst*)codecInst) != 0)
2645 {
2646 _engineStatisticsPtr->SetLastError(
2647 VE_BAD_FILE, kTraceError,
2648 "StartPlayingFile() failed to start file playout");
2649 _inputFilePlayerPtr->StopPlayingFile();
2650 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2651 _inputFilePlayerPtr = NULL;
2652 return -1;
2653 }
2654 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2655 _inputFilePlaying = true;
2656
2657 return 0;
2658}
2659
2660int Channel::StartPlayingFileAsMicrophone(InStream* stream,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002661 FileFormats format,
2662 int startPosition,
2663 float volumeScaling,
2664 int stopPosition,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002665 const CodecInst* codecInst)
2666{
2667 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2668 "Channel::StartPlayingFileAsMicrophone(format=%d, "
2669 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2670 format, volumeScaling, startPosition, stopPosition);
2671
2672 if(stream == NULL)
2673 {
2674 _engineStatisticsPtr->SetLastError(
2675 VE_BAD_FILE, kTraceError,
2676 "StartPlayingFileAsMicrophone NULL as input stream");
2677 return -1;
2678 }
2679
2680 if (_inputFilePlaying)
2681 {
2682 _engineStatisticsPtr->SetLastError(
2683 VE_ALREADY_PLAYING, kTraceWarning,
2684 "StartPlayingFileAsMicrophone() is playing");
2685 return 0;
2686 }
2687
2688 CriticalSectionScoped cs(&_fileCritSect);
2689
2690 // Destroy the old instance
2691 if (_inputFilePlayerPtr)
2692 {
2693 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2694 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2695 _inputFilePlayerPtr = NULL;
2696 }
2697
2698 // Create the instance
2699 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2700 _inputFilePlayerId, (const FileFormats)format);
2701
2702 if (_inputFilePlayerPtr == NULL)
2703 {
2704 _engineStatisticsPtr->SetLastError(
2705 VE_INVALID_ARGUMENT, kTraceError,
2706 "StartPlayingInputFile() filePlayer format isnot correct");
2707 return -1;
2708 }
2709
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002710 const uint32_t notificationTime(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002711
2712 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
2713 volumeScaling, notificationTime,
2714 stopPosition, codecInst) != 0)
2715 {
2716 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2717 "StartPlayingFile() failed to start "
2718 "file playout");
2719 _inputFilePlayerPtr->StopPlayingFile();
2720 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2721 _inputFilePlayerPtr = NULL;
2722 return -1;
2723 }
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00002724
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002725 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2726 _inputFilePlaying = true;
2727
2728 return 0;
2729}
2730
2731int Channel::StopPlayingFileAsMicrophone()
2732{
2733 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2734 "Channel::StopPlayingFileAsMicrophone()");
2735
2736 if (!_inputFilePlaying)
2737 {
2738 _engineStatisticsPtr->SetLastError(
2739 VE_INVALID_OPERATION, kTraceWarning,
2740 "StopPlayingFileAsMicrophone() isnot playing");
2741 return 0;
2742 }
2743
2744 CriticalSectionScoped cs(&_fileCritSect);
2745 if (_inputFilePlayerPtr->StopPlayingFile() != 0)
2746 {
2747 _engineStatisticsPtr->SetLastError(
2748 VE_STOP_RECORDING_FAILED, kTraceError,
2749 "StopPlayingFile() could not stop playing");
2750 return -1;
2751 }
2752 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2753 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2754 _inputFilePlayerPtr = NULL;
2755 _inputFilePlaying = false;
2756
2757 return 0;
2758}
2759
2760int Channel::IsPlayingFileAsMicrophone() const
2761{
2762 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2763 "Channel::IsPlayingFileAsMicrophone()");
2764
2765 return _inputFilePlaying;
2766}
2767
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00002768int Channel::ScaleFileAsMicrophonePlayout(float scale)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002769{
2770 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2771 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
2772
2773 CriticalSectionScoped cs(&_fileCritSect);
2774
2775 if (!_inputFilePlaying)
2776 {
2777 _engineStatisticsPtr->SetLastError(
2778 VE_INVALID_OPERATION, kTraceError,
2779 "ScaleFileAsMicrophonePlayout() isnot playing");
2780 return -1;
2781 }
2782
2783 if ((_inputFilePlayerPtr == NULL) ||
2784 (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
2785 {
2786 _engineStatisticsPtr->SetLastError(
2787 VE_BAD_ARGUMENT, kTraceError,
2788 "SetAudioScaling() failed to scale playout");
2789 return -1;
2790 }
2791
2792 return 0;
2793}
2794
2795int Channel::StartRecordingPlayout(const char* fileName,
2796 const CodecInst* codecInst)
2797{
2798 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2799 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
2800
2801 if (_outputFileRecording)
2802 {
2803 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2804 "StartRecordingPlayout() is already recording");
2805 return 0;
2806 }
2807
2808 FileFormats format;
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002809 const uint32_t notificationTime(0); // Not supported in VoE
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002810 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2811
2812 if ((codecInst != NULL) &&
2813 ((codecInst->channels < 1) || (codecInst->channels > 2)))
2814 {
2815 _engineStatisticsPtr->SetLastError(
2816 VE_BAD_ARGUMENT, kTraceError,
2817 "StartRecordingPlayout() invalid compression");
2818 return(-1);
2819 }
2820 if(codecInst == NULL)
2821 {
2822 format = kFileFormatPcm16kHzFile;
2823 codecInst=&dummyCodec;
2824 }
2825 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2826 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2827 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2828 {
2829 format = kFileFormatWavFile;
2830 }
2831 else
2832 {
2833 format = kFileFormatCompressedFile;
2834 }
2835
2836 CriticalSectionScoped cs(&_fileCritSect);
2837
2838 // Destroy the old instance
2839 if (_outputFileRecorderPtr)
2840 {
2841 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2842 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2843 _outputFileRecorderPtr = NULL;
2844 }
2845
2846 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2847 _outputFileRecorderId, (const FileFormats)format);
2848 if (_outputFileRecorderPtr == NULL)
2849 {
2850 _engineStatisticsPtr->SetLastError(
2851 VE_INVALID_ARGUMENT, kTraceError,
2852 "StartRecordingPlayout() fileRecorder format isnot correct");
2853 return -1;
2854 }
2855
2856 if (_outputFileRecorderPtr->StartRecordingAudioFile(
2857 fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
2858 {
2859 _engineStatisticsPtr->SetLastError(
2860 VE_BAD_FILE, kTraceError,
2861 "StartRecordingAudioFile() failed to start file recording");
2862 _outputFileRecorderPtr->StopRecording();
2863 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2864 _outputFileRecorderPtr = NULL;
2865 return -1;
2866 }
2867 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2868 _outputFileRecording = true;
2869
2870 return 0;
2871}
2872
2873int Channel::StartRecordingPlayout(OutStream* stream,
2874 const CodecInst* codecInst)
2875{
2876 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2877 "Channel::StartRecordingPlayout()");
2878
2879 if (_outputFileRecording)
2880 {
2881 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2882 "StartRecordingPlayout() is already recording");
2883 return 0;
2884 }
2885
2886 FileFormats format;
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002887 const uint32_t notificationTime(0); // Not supported in VoE
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002888 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2889
2890 if (codecInst != NULL && codecInst->channels != 1)
2891 {
2892 _engineStatisticsPtr->SetLastError(
2893 VE_BAD_ARGUMENT, kTraceError,
2894 "StartRecordingPlayout() invalid compression");
2895 return(-1);
2896 }
2897 if(codecInst == NULL)
2898 {
2899 format = kFileFormatPcm16kHzFile;
2900 codecInst=&dummyCodec;
2901 }
2902 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2903 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2904 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2905 {
2906 format = kFileFormatWavFile;
2907 }
2908 else
2909 {
2910 format = kFileFormatCompressedFile;
2911 }
2912
2913 CriticalSectionScoped cs(&_fileCritSect);
2914
2915 // Destroy the old instance
2916 if (_outputFileRecorderPtr)
2917 {
2918 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2919 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2920 _outputFileRecorderPtr = NULL;
2921 }
2922
2923 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2924 _outputFileRecorderId, (const FileFormats)format);
2925 if (_outputFileRecorderPtr == NULL)
2926 {
2927 _engineStatisticsPtr->SetLastError(
2928 VE_INVALID_ARGUMENT, kTraceError,
2929 "StartRecordingPlayout() fileRecorder format isnot correct");
2930 return -1;
2931 }
2932
2933 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
2934 notificationTime) != 0)
2935 {
2936 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2937 "StartRecordingPlayout() failed to "
2938 "start file recording");
2939 _outputFileRecorderPtr->StopRecording();
2940 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2941 _outputFileRecorderPtr = NULL;
2942 return -1;
2943 }
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00002944
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002945 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2946 _outputFileRecording = true;
2947
2948 return 0;
2949}
2950
2951int Channel::StopRecordingPlayout()
2952{
2953 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
2954 "Channel::StopRecordingPlayout()");
2955
2956 if (!_outputFileRecording)
2957 {
2958 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
2959 "StopRecordingPlayout() isnot recording");
2960 return -1;
2961 }
2962
2963
2964 CriticalSectionScoped cs(&_fileCritSect);
2965
2966 if (_outputFileRecorderPtr->StopRecording() != 0)
2967 {
2968 _engineStatisticsPtr->SetLastError(
2969 VE_STOP_RECORDING_FAILED, kTraceError,
2970 "StopRecording() could not stop recording");
2971 return(-1);
2972 }
2973 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2974 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2975 _outputFileRecorderPtr = NULL;
2976 _outputFileRecording = false;
2977
2978 return 0;
2979}
2980
2981void
2982Channel::SetMixWithMicStatus(bool mix)
2983{
2984 _mixFileWithMicrophone=mix;
2985}
2986
2987int
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002988Channel::GetSpeechOutputLevel(uint32_t& level) const
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002989{
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002990 int8_t currentLevel = _outputAudioLevel.Level();
2991 level = static_cast<int32_t> (currentLevel);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00002992 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2993 VoEId(_instanceId,_channelId),
2994 "GetSpeechOutputLevel() => level=%u", level);
2995 return 0;
2996}
2997
2998int
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00002999Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003000{
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00003001 int16_t currentLevel = _outputAudioLevel.LevelFullRange();
3002 level = static_cast<int32_t> (currentLevel);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003003 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3004 VoEId(_instanceId,_channelId),
3005 "GetSpeechOutputLevelFullRange() => level=%u", level);
3006 return 0;
3007}
3008
3009int
3010Channel::SetMute(bool enable)
3011{
3012 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3013 "Channel::SetMute(enable=%d)", enable);
3014 _mute = enable;
3015 return 0;
3016}
3017
3018bool
3019Channel::Mute() const
3020{
3021 return _mute;
3022}
3023
3024int
3025Channel::SetOutputVolumePan(float left, float right)
3026{
3027 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3028 "Channel::SetOutputVolumePan()");
3029 _panLeft = left;
3030 _panRight = right;
3031 return 0;
3032}
3033
3034int
3035Channel::GetOutputVolumePan(float& left, float& right) const
3036{
3037 left = _panLeft;
3038 right = _panRight;
3039 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3040 VoEId(_instanceId,_channelId),
3041 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
3042 return 0;
3043}
3044
3045int
3046Channel::SetChannelOutputVolumeScaling(float scaling)
3047{
3048 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3049 "Channel::SetChannelOutputVolumeScaling()");
3050 _outputGain = scaling;
3051 return 0;
3052}
3053
3054int
3055Channel::GetChannelOutputVolumeScaling(float& scaling) const
3056{
3057 scaling = _outputGain;
3058 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3059 VoEId(_instanceId,_channelId),
3060 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
3061 return 0;
3062}
3063
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003064int
3065Channel::RegisterExternalEncryption(Encryption& encryption)
3066{
3067 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3068 "Channel::RegisterExternalEncryption()");
3069
3070 CriticalSectionScoped cs(&_callbackCritSect);
3071
3072 if (_encryptionPtr)
3073 {
3074 _engineStatisticsPtr->SetLastError(
3075 VE_INVALID_OPERATION, kTraceError,
3076 "RegisterExternalEncryption() encryption already enabled");
3077 return -1;
3078 }
3079
3080 _encryptionPtr = &encryption;
3081
3082 _decrypting = true;
3083 _encrypting = true;
3084
3085 return 0;
3086}
3087
3088int
3089Channel::DeRegisterExternalEncryption()
3090{
3091 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3092 "Channel::DeRegisterExternalEncryption()");
3093
3094 CriticalSectionScoped cs(&_callbackCritSect);
3095
3096 if (!_encryptionPtr)
3097 {
3098 _engineStatisticsPtr->SetLastError(
3099 VE_INVALID_OPERATION, kTraceWarning,
3100 "DeRegisterExternalEncryption() encryption already disabled");
3101 return 0;
3102 }
3103
3104 _decrypting = false;
3105 _encrypting = false;
3106
3107 _encryptionPtr = NULL;
3108
3109 return 0;
3110}
3111
3112int Channel::SendTelephoneEventOutband(unsigned char eventCode,
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003113 int lengthMs, int attenuationDb,
3114 bool playDtmfEvent)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003115{
3116 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3117 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
3118 playDtmfEvent);
3119
3120 _playOutbandDtmfEvent = playDtmfEvent;
3121
3122 if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
3123 attenuationDb) != 0)
3124 {
3125 _engineStatisticsPtr->SetLastError(
3126 VE_SEND_DTMF_FAILED,
3127 kTraceWarning,
3128 "SendTelephoneEventOutband() failed to send event");
3129 return -1;
3130 }
3131 return 0;
3132}
3133
3134int Channel::SendTelephoneEventInband(unsigned char eventCode,
3135 int lengthMs,
3136 int attenuationDb,
3137 bool playDtmfEvent)
3138{
3139 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3140 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
3141 playDtmfEvent);
3142
3143 _playInbandDtmfEvent = playDtmfEvent;
3144 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
3145
3146 return 0;
3147}
3148
3149int
3150Channel::SetDtmfPlayoutStatus(bool enable)
3151{
3152 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3153 "Channel::SetDtmfPlayoutStatus()");
3154 if (_audioCodingModule.SetDtmfPlayoutStatus(enable) != 0)
3155 {
3156 _engineStatisticsPtr->SetLastError(
3157 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
3158 "SetDtmfPlayoutStatus() failed to set Dtmf playout");
3159 return -1;
3160 }
3161 return 0;
3162}
3163
3164bool
3165Channel::DtmfPlayoutStatus() const
3166{
3167 return _audioCodingModule.DtmfPlayoutStatus();
3168}
3169
3170int
3171Channel::SetSendTelephoneEventPayloadType(unsigned char type)
3172{
3173 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3174 "Channel::SetSendTelephoneEventPayloadType()");
3175 if (type > 127)
3176 {
3177 _engineStatisticsPtr->SetLastError(
3178 VE_INVALID_ARGUMENT, kTraceError,
3179 "SetSendTelephoneEventPayloadType() invalid type");
3180 return -1;
3181 }
pbos@webrtc.org6a4acb92013-07-11 15:50:07 +00003182 CodecInst codec = {};
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003183 codec.plfreq = 8000;
3184 codec.pltype = type;
3185 memcpy(codec.plname, "telephone-event", 16);
3186 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
3187 {
henrika@webrtc.org570c4a52013-04-17 07:34:25 +00003188 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
3189 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
3190 _engineStatisticsPtr->SetLastError(
3191 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3192 "SetSendTelephoneEventPayloadType() failed to register send"
3193 "payload type");
3194 return -1;
3195 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003196 }
3197 _sendTelephoneEventPayloadType = type;
3198 return 0;
3199}
3200
3201int
3202Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
3203{
3204 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3205 "Channel::GetSendTelephoneEventPayloadType()");
3206 type = _sendTelephoneEventPayloadType;
3207 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3208 VoEId(_instanceId,_channelId),
3209 "GetSendTelephoneEventPayloadType() => type=%u", type);
3210 return 0;
3211}
3212
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003213int
3214Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
3215{
3216 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3217 "Channel::UpdateRxVadDetection()");
3218
3219 int vadDecision = 1;
3220
3221 vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
3222
3223 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
3224 {
3225 OnRxVadDetected(vadDecision);
3226 _oldVadDecision = vadDecision;
3227 }
3228
3229 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3230 "Channel::UpdateRxVadDetection() => vadDecision=%d",
3231 vadDecision);
3232 return 0;
3233}
3234
3235int
3236Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
3237{
3238 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3239 "Channel::RegisterRxVadObserver()");
3240 CriticalSectionScoped cs(&_callbackCritSect);
3241
3242 if (_rxVadObserverPtr)
3243 {
3244 _engineStatisticsPtr->SetLastError(
3245 VE_INVALID_OPERATION, kTraceError,
3246 "RegisterRxVadObserver() observer already enabled");
3247 return -1;
3248 }
3249 _rxVadObserverPtr = &observer;
3250 _RxVadDetection = true;
3251 return 0;
3252}
3253
3254int
3255Channel::DeRegisterRxVadObserver()
3256{
3257 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3258 "Channel::DeRegisterRxVadObserver()");
3259 CriticalSectionScoped cs(&_callbackCritSect);
3260
3261 if (!_rxVadObserverPtr)
3262 {
3263 _engineStatisticsPtr->SetLastError(
3264 VE_INVALID_OPERATION, kTraceWarning,
3265 "DeRegisterRxVadObserver() observer already disabled");
3266 return 0;
3267 }
3268 _rxVadObserverPtr = NULL;
3269 _RxVadDetection = false;
3270 return 0;
3271}
3272
3273int
3274Channel::VoiceActivityIndicator(int &activity)
3275{
3276 activity = _sendFrameType;
3277
3278 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3279 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
3280 return 0;
3281}
3282
3283#ifdef WEBRTC_VOICE_ENGINE_AGC
3284
3285int
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00003286Channel::SetRxAgcStatus(bool enable, AgcModes mode)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003287{
3288 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3289 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
3290 (int)enable, (int)mode);
3291
3292 GainControl::Mode agcMode(GainControl::kFixedDigital);
3293 switch (mode)
3294 {
3295 case kAgcDefault:
3296 agcMode = GainControl::kAdaptiveDigital;
3297 break;
3298 case kAgcUnchanged:
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003299 agcMode = rx_audioproc_->gain_control()->mode();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003300 break;
3301 case kAgcFixedDigital:
3302 agcMode = GainControl::kFixedDigital;
3303 break;
3304 case kAgcAdaptiveDigital:
3305 agcMode =GainControl::kAdaptiveDigital;
3306 break;
3307 default:
3308 _engineStatisticsPtr->SetLastError(
3309 VE_INVALID_ARGUMENT, kTraceError,
3310 "SetRxAgcStatus() invalid Agc mode");
3311 return -1;
3312 }
3313
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003314 if (rx_audioproc_->gain_control()->set_mode(agcMode) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003315 {
3316 _engineStatisticsPtr->SetLastError(
3317 VE_APM_ERROR, kTraceError,
3318 "SetRxAgcStatus() failed to set Agc mode");
3319 return -1;
3320 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003321 if (rx_audioproc_->gain_control()->Enable(enable) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003322 {
3323 _engineStatisticsPtr->SetLastError(
3324 VE_APM_ERROR, kTraceError,
3325 "SetRxAgcStatus() failed to set Agc state");
3326 return -1;
3327 }
3328
3329 _rxAgcIsEnabled = enable;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003330 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
3331
3332 return 0;
3333}
3334
3335int
3336Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
3337{
3338 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3339 "Channel::GetRxAgcStatus(enable=?, mode=?)");
3340
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003341 bool enable = rx_audioproc_->gain_control()->is_enabled();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003342 GainControl::Mode agcMode =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003343 rx_audioproc_->gain_control()->mode();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003344
3345 enabled = enable;
3346
3347 switch (agcMode)
3348 {
3349 case GainControl::kFixedDigital:
3350 mode = kAgcFixedDigital;
3351 break;
3352 case GainControl::kAdaptiveDigital:
3353 mode = kAgcAdaptiveDigital;
3354 break;
3355 default:
3356 _engineStatisticsPtr->SetLastError(
3357 VE_APM_ERROR, kTraceError,
3358 "GetRxAgcStatus() invalid Agc mode");
3359 return -1;
3360 }
3361
3362 return 0;
3363}
3364
3365int
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00003366Channel::SetRxAgcConfig(AgcConfig config)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003367{
3368 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3369 "Channel::SetRxAgcConfig()");
3370
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003371 if (rx_audioproc_->gain_control()->set_target_level_dbfs(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003372 config.targetLeveldBOv) != 0)
3373 {
3374 _engineStatisticsPtr->SetLastError(
3375 VE_APM_ERROR, kTraceError,
3376 "SetRxAgcConfig() failed to set target peak |level|"
3377 "(or envelope) of the Agc");
3378 return -1;
3379 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003380 if (rx_audioproc_->gain_control()->set_compression_gain_db(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003381 config.digitalCompressionGaindB) != 0)
3382 {
3383 _engineStatisticsPtr->SetLastError(
3384 VE_APM_ERROR, kTraceError,
3385 "SetRxAgcConfig() failed to set the range in |gain| the"
3386 " digital compression stage may apply");
3387 return -1;
3388 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003389 if (rx_audioproc_->gain_control()->enable_limiter(
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003390 config.limiterEnable) != 0)
3391 {
3392 _engineStatisticsPtr->SetLastError(
3393 VE_APM_ERROR, kTraceError,
3394 "SetRxAgcConfig() failed to set hard limiter to the signal");
3395 return -1;
3396 }
3397
3398 return 0;
3399}
3400
3401int
3402Channel::GetRxAgcConfig(AgcConfig& config)
3403{
3404 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3405 "Channel::GetRxAgcConfig(config=%?)");
3406
3407 config.targetLeveldBOv =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003408 rx_audioproc_->gain_control()->target_level_dbfs();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003409 config.digitalCompressionGaindB =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003410 rx_audioproc_->gain_control()->compression_gain_db();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003411 config.limiterEnable =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003412 rx_audioproc_->gain_control()->is_limiter_enabled();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003413
3414 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3415 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
3416 "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
3417 " limiterEnable=%d",
3418 config.targetLeveldBOv,
3419 config.digitalCompressionGaindB,
3420 config.limiterEnable);
3421
3422 return 0;
3423}
3424
3425#endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
3426
3427#ifdef WEBRTC_VOICE_ENGINE_NR
3428
3429int
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00003430Channel::SetRxNsStatus(bool enable, NsModes mode)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003431{
3432 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3433 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
3434 (int)enable, (int)mode);
3435
3436 NoiseSuppression::Level nsLevel(
3437 (NoiseSuppression::Level)WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE);
3438 switch (mode)
3439 {
3440
3441 case kNsDefault:
3442 nsLevel = (NoiseSuppression::Level)
3443 WEBRTC_VOICE_ENGINE_RX_NS_DEFAULT_MODE;
3444 break;
3445 case kNsUnchanged:
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003446 nsLevel = rx_audioproc_->noise_suppression()->level();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003447 break;
3448 case kNsConference:
3449 nsLevel = NoiseSuppression::kHigh;
3450 break;
3451 case kNsLowSuppression:
3452 nsLevel = NoiseSuppression::kLow;
3453 break;
3454 case kNsModerateSuppression:
3455 nsLevel = NoiseSuppression::kModerate;
3456 break;
3457 case kNsHighSuppression:
3458 nsLevel = NoiseSuppression::kHigh;
3459 break;
3460 case kNsVeryHighSuppression:
3461 nsLevel = NoiseSuppression::kVeryHigh;
3462 break;
3463 }
3464
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003465 if (rx_audioproc_->noise_suppression()->set_level(nsLevel)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003466 != 0)
3467 {
3468 _engineStatisticsPtr->SetLastError(
3469 VE_APM_ERROR, kTraceError,
3470 "SetRxAgcStatus() failed to set Ns level");
3471 return -1;
3472 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003473 if (rx_audioproc_->noise_suppression()->Enable(enable) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003474 {
3475 _engineStatisticsPtr->SetLastError(
3476 VE_APM_ERROR, kTraceError,
3477 "SetRxAgcStatus() failed to set Agc state");
3478 return -1;
3479 }
3480
3481 _rxNsIsEnabled = enable;
3482 _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
3483
3484 return 0;
3485}
3486
3487int
3488Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
3489{
3490 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3491 "Channel::GetRxNsStatus(enable=?, mode=?)");
3492
3493 bool enable =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003494 rx_audioproc_->noise_suppression()->is_enabled();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003495 NoiseSuppression::Level ncLevel =
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003496 rx_audioproc_->noise_suppression()->level();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003497
3498 enabled = enable;
3499
3500 switch (ncLevel)
3501 {
3502 case NoiseSuppression::kLow:
3503 mode = kNsLowSuppression;
3504 break;
3505 case NoiseSuppression::kModerate:
3506 mode = kNsModerateSuppression;
3507 break;
3508 case NoiseSuppression::kHigh:
3509 mode = kNsHighSuppression;
3510 break;
3511 case NoiseSuppression::kVeryHigh:
3512 mode = kNsVeryHighSuppression;
3513 break;
3514 }
3515
3516 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3517 VoEId(_instanceId,_channelId),
3518 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
3519 return 0;
3520}
3521
3522#endif // #ifdef WEBRTC_VOICE_ENGINE_NR
3523
3524int
3525Channel::RegisterRTPObserver(VoERTPObserver& observer)
3526{
3527 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3528 "Channel::RegisterRTPObserver()");
3529 CriticalSectionScoped cs(&_callbackCritSect);
3530
3531 if (_rtpObserverPtr)
3532 {
3533 _engineStatisticsPtr->SetLastError(
3534 VE_INVALID_OPERATION, kTraceError,
3535 "RegisterRTPObserver() observer already enabled");
3536 return -1;
3537 }
3538
3539 _rtpObserverPtr = &observer;
3540 _rtpObserver = true;
3541
3542 return 0;
3543}
3544
3545int
3546Channel::DeRegisterRTPObserver()
3547{
3548 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3549 "Channel::DeRegisterRTPObserver()");
3550 CriticalSectionScoped cs(&_callbackCritSect);
3551
3552 if (!_rtpObserverPtr)
3553 {
3554 _engineStatisticsPtr->SetLastError(
3555 VE_INVALID_OPERATION, kTraceWarning,
3556 "DeRegisterRTPObserver() observer already disabled");
3557 return 0;
3558 }
3559
3560 _rtpObserver = false;
3561 _rtpObserverPtr = NULL;
3562
3563 return 0;
3564}
3565
3566int
3567Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
3568{
3569 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3570 "Channel::RegisterRTCPObserver()");
3571 CriticalSectionScoped cs(&_callbackCritSect);
3572
3573 if (_rtcpObserverPtr)
3574 {
3575 _engineStatisticsPtr->SetLastError(
3576 VE_INVALID_OPERATION, kTraceError,
3577 "RegisterRTCPObserver() observer already enabled");
3578 return -1;
3579 }
3580
3581 _rtcpObserverPtr = &observer;
3582 _rtcpObserver = true;
3583
3584 return 0;
3585}
3586
3587int
3588Channel::DeRegisterRTCPObserver()
3589{
3590 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3591 "Channel::DeRegisterRTCPObserver()");
3592 CriticalSectionScoped cs(&_callbackCritSect);
3593
3594 if (!_rtcpObserverPtr)
3595 {
3596 _engineStatisticsPtr->SetLastError(
3597 VE_INVALID_OPERATION, kTraceWarning,
3598 "DeRegisterRTCPObserver() observer already disabled");
3599 return 0;
3600 }
3601
3602 _rtcpObserver = false;
3603 _rtcpObserverPtr = NULL;
3604
3605 return 0;
3606}
3607
3608int
3609Channel::SetLocalSSRC(unsigned int ssrc)
3610{
3611 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3612 "Channel::SetLocalSSRC()");
3613 if (_sending)
3614 {
3615 _engineStatisticsPtr->SetLastError(
3616 VE_ALREADY_SENDING, kTraceError,
3617 "SetLocalSSRC() already sending");
3618 return -1;
3619 }
3620 if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
3621 {
3622 _engineStatisticsPtr->SetLastError(
3623 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3624 "SetLocalSSRC() failed to set SSRC");
3625 return -1;
3626 }
3627 return 0;
3628}
3629
3630int
3631Channel::GetLocalSSRC(unsigned int& ssrc)
3632{
3633 ssrc = _rtpRtcpModule->SSRC();
3634 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3635 VoEId(_instanceId,_channelId),
3636 "GetLocalSSRC() => ssrc=%lu", ssrc);
3637 return 0;
3638}
3639
3640int
3641Channel::GetRemoteSSRC(unsigned int& ssrc)
3642{
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003643 ssrc = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003644 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3645 VoEId(_instanceId,_channelId),
3646 "GetRemoteSSRC() => ssrc=%lu", ssrc);
3647 return 0;
3648}
3649
3650int
3651Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
3652{
3653 if (arrCSRC == NULL)
3654 {
3655 _engineStatisticsPtr->SetLastError(
3656 VE_INVALID_ARGUMENT, kTraceError,
3657 "GetRemoteCSRCs() invalid array argument");
3658 return -1;
3659 }
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00003660 uint32_t arrOfCSRC[kRtpCsrcSize];
3661 int32_t CSRCs(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003662 CSRCs = _rtpRtcpModule->CSRCs(arrOfCSRC);
3663 if (CSRCs > 0)
3664 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00003665 memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(uint32_t));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003666 for (int i = 0; i < (int) CSRCs; i++)
3667 {
3668 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3669 VoEId(_instanceId, _channelId),
3670 "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
3671 }
3672 } else
3673 {
3674 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3675 VoEId(_instanceId, _channelId),
3676 "GetRemoteCSRCs() => list is empty!");
3677 }
3678 return CSRCs;
3679}
3680
3681int
3682Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
3683{
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003684 if (rtp_audioproc_.get() == NULL) {
3685 rtp_audioproc_.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
3686 _channelId)));
3687 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003688
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003689 if (rtp_audioproc_->level_estimator()->Enable(enable) !=
3690 AudioProcessing::kNoError) {
3691 _engineStatisticsPtr->SetLastError(VE_APM_ERROR, kTraceError,
3692 "Failed to enable AudioProcessing::level_estimator()");
3693 return -1;
3694 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003695
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003696 _includeAudioLevelIndication = enable;
3697 if (enable) {
3698 rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
3699 ID);
3700 } else {
3701 rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
3702 }
3703 return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003704}
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00003705
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003706int
3707Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
3708{
3709 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3710 VoEId(_instanceId,_channelId),
3711 "GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
3712 enabled, ID);
3713 return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
3714}
3715
3716int
3717Channel::SetRTCPStatus(bool enable)
3718{
3719 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3720 "Channel::SetRTCPStatus()");
3721 if (_rtpRtcpModule->SetRTCPStatus(enable ?
3722 kRtcpCompound : kRtcpOff) != 0)
3723 {
3724 _engineStatisticsPtr->SetLastError(
3725 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3726 "SetRTCPStatus() failed to set RTCP status");
3727 return -1;
3728 }
3729 return 0;
3730}
3731
3732int
3733Channel::GetRTCPStatus(bool& enabled)
3734{
3735 RTCPMethod method = _rtpRtcpModule->RTCP();
3736 enabled = (method != kRtcpOff);
3737 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3738 VoEId(_instanceId,_channelId),
3739 "GetRTCPStatus() => enabled=%d", enabled);
3740 return 0;
3741}
3742
3743int
3744Channel::SetRTCP_CNAME(const char cName[256])
3745{
3746 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3747 "Channel::SetRTCP_CNAME()");
3748 if (_rtpRtcpModule->SetCNAME(cName) != 0)
3749 {
3750 _engineStatisticsPtr->SetLastError(
3751 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3752 "SetRTCP_CNAME() failed to set RTCP CNAME");
3753 return -1;
3754 }
3755 return 0;
3756}
3757
3758int
3759Channel::GetRTCP_CNAME(char cName[256])
3760{
3761 if (_rtpRtcpModule->CNAME(cName) != 0)
3762 {
3763 _engineStatisticsPtr->SetLastError(
3764 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3765 "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
3766 return -1;
3767 }
3768 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3769 VoEId(_instanceId, _channelId),
3770 "GetRTCP_CNAME() => cName=%s", cName);
3771 return 0;
3772}
3773
3774int
3775Channel::GetRemoteRTCP_CNAME(char cName[256])
3776{
3777 if (cName == NULL)
3778 {
3779 _engineStatisticsPtr->SetLastError(
3780 VE_INVALID_ARGUMENT, kTraceError,
3781 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
3782 return -1;
3783 }
3784 char cname[RTCP_CNAME_SIZE];
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003785 const uint32_t remoteSSRC = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003786 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
3787 {
3788 _engineStatisticsPtr->SetLastError(
3789 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
3790 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
3791 return -1;
3792 }
3793 strcpy(cName, cname);
3794 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3795 VoEId(_instanceId, _channelId),
3796 "GetRemoteRTCP_CNAME() => cName=%s", cName);
3797 return 0;
3798}
3799
3800int
3801Channel::GetRemoteRTCPData(
3802 unsigned int& NTPHigh,
3803 unsigned int& NTPLow,
3804 unsigned int& timestamp,
3805 unsigned int& playoutTimestamp,
3806 unsigned int* jitter,
3807 unsigned short* fractionLost)
3808{
3809 // --- Information from sender info in received Sender Reports
3810
3811 RTCPSenderInfo senderInfo;
3812 if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
3813 {
3814 _engineStatisticsPtr->SetLastError(
3815 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3816 "GetRemoteRTCPData() failed to retrieve sender info for remote "
3817 "side");
3818 return -1;
3819 }
3820
3821 // We only utilize 12 out of 20 bytes in the sender info (ignores packet
3822 // and octet count)
3823 NTPHigh = senderInfo.NTPseconds;
3824 NTPLow = senderInfo.NTPfraction;
3825 timestamp = senderInfo.RTPtimeStamp;
3826
3827 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3828 VoEId(_instanceId, _channelId),
3829 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
3830 "timestamp=%lu",
3831 NTPHigh, NTPLow, timestamp);
3832
3833 // --- Locally derived information
3834
3835 // This value is updated on each incoming RTCP packet (0 when no packet
3836 // has been received)
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00003837 playoutTimestamp = playout_timestamp_rtcp_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003838
3839 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3840 VoEId(_instanceId, _channelId),
3841 "GetRemoteRTCPData() => playoutTimestamp=%lu",
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00003842 playout_timestamp_rtcp_);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003843
3844 if (NULL != jitter || NULL != fractionLost)
3845 {
3846 // Get all RTCP receiver report blocks that have been received on this
3847 // channel. If we receive RTP packets from a remote source we know the
3848 // remote SSRC and use the report block from him.
3849 // Otherwise use the first report block.
3850 std::vector<RTCPReportBlock> remote_stats;
3851 if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
3852 remote_stats.empty()) {
3853 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3854 VoEId(_instanceId, _channelId),
3855 "GetRemoteRTCPData() failed to measure statistics due"
3856 " to lack of received RTP and/or RTCP packets");
3857 return -1;
3858 }
3859
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003860 uint32_t remoteSSRC = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003861 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
3862 for (; it != remote_stats.end(); ++it) {
3863 if (it->remoteSSRC == remoteSSRC)
3864 break;
3865 }
3866
3867 if (it == remote_stats.end()) {
3868 // If we have not received any RTCP packets from this SSRC it probably
3869 // means that we have not received any RTP packets.
3870 // Use the first received report block instead.
3871 it = remote_stats.begin();
3872 remoteSSRC = it->remoteSSRC;
3873 }
3874
3875 if (jitter) {
3876 *jitter = it->jitter;
3877 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3878 VoEId(_instanceId, _channelId),
3879 "GetRemoteRTCPData() => jitter = %lu", *jitter);
3880 }
3881
3882 if (fractionLost) {
3883 *fractionLost = it->fractionLost;
3884 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3885 VoEId(_instanceId, _channelId),
3886 "GetRemoteRTCPData() => fractionLost = %lu",
3887 *fractionLost);
3888 }
3889 }
3890 return 0;
3891}
3892
3893int
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00003894Channel::SendApplicationDefinedRTCPPacket(unsigned char subType,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003895 unsigned int name,
3896 const char* data,
3897 unsigned short dataLengthInBytes)
3898{
3899 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3900 "Channel::SendApplicationDefinedRTCPPacket()");
3901 if (!_sending)
3902 {
3903 _engineStatisticsPtr->SetLastError(
3904 VE_NOT_SENDING, kTraceError,
3905 "SendApplicationDefinedRTCPPacket() not sending");
3906 return -1;
3907 }
3908 if (NULL == data)
3909 {
3910 _engineStatisticsPtr->SetLastError(
3911 VE_INVALID_ARGUMENT, kTraceError,
3912 "SendApplicationDefinedRTCPPacket() invalid data value");
3913 return -1;
3914 }
3915 if (dataLengthInBytes % 4 != 0)
3916 {
3917 _engineStatisticsPtr->SetLastError(
3918 VE_INVALID_ARGUMENT, kTraceError,
3919 "SendApplicationDefinedRTCPPacket() invalid length value");
3920 return -1;
3921 }
3922 RTCPMethod status = _rtpRtcpModule->RTCP();
3923 if (status == kRtcpOff)
3924 {
3925 _engineStatisticsPtr->SetLastError(
3926 VE_RTCP_ERROR, kTraceError,
3927 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
3928 return -1;
3929 }
3930
3931 // Create and schedule the RTCP APP packet for transmission
3932 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
3933 subType,
3934 name,
3935 (const unsigned char*) data,
3936 dataLengthInBytes) != 0)
3937 {
3938 _engineStatisticsPtr->SetLastError(
3939 VE_SEND_ERROR, kTraceError,
3940 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
3941 return -1;
3942 }
3943 return 0;
3944}
3945
3946int
3947Channel::GetRTPStatistics(
3948 unsigned int& averageJitterMs,
3949 unsigned int& maxJitterMs,
3950 unsigned int& discardedPackets)
3951{
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003952 // The jitter statistics is updated for each received RTP packet and is
3953 // based on received packets.
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00003954 StreamStatistician::Statistics statistics;
3955 StreamStatistician* statistician =
3956 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
3957 if (!statistician || !statistician->GetStatistics(
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003958 &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
3959 _engineStatisticsPtr->SetLastError(
3960 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
3961 "GetRTPStatistics() failed to read RTP statistics from the "
3962 "RTP/RTCP module");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003963 }
3964
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00003965 const int32_t playoutFrequency =
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003966 _audioCodingModule.PlayoutFrequency();
3967 if (playoutFrequency > 0)
3968 {
3969 // Scale RTP statistics given the current playout frequency
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00003970 maxJitterMs = statistics.max_jitter / (playoutFrequency / 1000);
3971 averageJitterMs = statistics.jitter / (playoutFrequency / 1000);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00003972 }
3973
3974 discardedPackets = _numberOfDiscardedPackets;
3975
3976 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3977 VoEId(_instanceId, _channelId),
3978 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
3979 " discardedPackets = %lu)",
3980 averageJitterMs, maxJitterMs, discardedPackets);
3981 return 0;
3982}
3983
3984int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
3985 if (sender_info == NULL) {
3986 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
3987 "GetRemoteRTCPSenderInfo() invalid sender_info.");
3988 return -1;
3989 }
3990
3991 // Get the sender info from the latest received RTCP Sender Report.
3992 RTCPSenderInfo rtcp_sender_info;
3993 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
3994 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3995 "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
3996 return -1;
3997 }
3998
3999 sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
4000 sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
4001 sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
4002 sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
4003 sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
4004 return 0;
4005}
4006
4007int Channel::GetRemoteRTCPReportBlocks(
4008 std::vector<ReportBlock>* report_blocks) {
4009 if (report_blocks == NULL) {
4010 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
4011 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
4012 return -1;
4013 }
4014
4015 // Get the report blocks from the latest received RTCP Sender or Receiver
4016 // Report. Each element in the vector contains the sender's SSRC and a
4017 // report block according to RFC 3550.
4018 std::vector<RTCPReportBlock> rtcp_report_blocks;
4019 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
4020 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4021 "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
4022 return -1;
4023 }
4024
4025 if (rtcp_report_blocks.empty())
4026 return 0;
4027
4028 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
4029 for (; it != rtcp_report_blocks.end(); ++it) {
4030 ReportBlock report_block;
4031 report_block.sender_SSRC = it->remoteSSRC;
4032 report_block.source_SSRC = it->sourceSSRC;
4033 report_block.fraction_lost = it->fractionLost;
4034 report_block.cumulative_num_packets_lost = it->cumulativeLost;
4035 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
4036 report_block.interarrival_jitter = it->jitter;
4037 report_block.last_SR_timestamp = it->lastSR;
4038 report_block.delay_since_last_SR = it->delaySinceLastSR;
4039 report_blocks->push_back(report_block);
4040 }
4041 return 0;
4042}
4043
4044int
4045Channel::GetRTPStatistics(CallStatistics& stats)
4046{
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004047 // --- Part one of the final structure (four values)
4048
4049 // The jitter statistics is updated for each received RTP packet and is
4050 // based on received packets.
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00004051 StreamStatistician::Statistics statistics;
4052 StreamStatistician* statistician =
4053 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
4054 if (!statistician || !statistician->GetStatistics(
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004055 &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
4056 _engineStatisticsPtr->SetLastError(
4057 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
4058 "GetRTPStatistics() failed to read RTP statistics from the "
4059 "RTP/RTCP module");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004060 }
4061
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004062 stats.fractionLost = statistics.fraction_lost;
4063 stats.cumulativeLost = statistics.cumulative_lost;
4064 stats.extendedMax = statistics.extended_max_sequence_number;
4065 stats.jitterSamples = statistics.jitter;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004066
4067 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4068 VoEId(_instanceId, _channelId),
4069 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
4070 " extendedMax=%lu, jitterSamples=%li)",
4071 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
4072 stats.jitterSamples);
4073
4074 // --- Part two of the final structure (one value)
4075
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004076 uint16_t RTT(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004077 RTCPMethod method = _rtpRtcpModule->RTCP();
4078 if (method == kRtcpOff)
4079 {
4080 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4081 VoEId(_instanceId, _channelId),
4082 "GetRTPStatistics() RTCP is disabled => valid RTT "
4083 "measurements cannot be retrieved");
4084 } else
4085 {
4086 // The remote SSRC will be zero if no RTP packet has been received.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004087 uint32_t remoteSSRC = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004088 if (remoteSSRC > 0)
4089 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004090 uint16_t avgRTT(0);
4091 uint16_t maxRTT(0);
4092 uint16_t minRTT(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004093
4094 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
4095 != 0)
4096 {
4097 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4098 VoEId(_instanceId, _channelId),
4099 "GetRTPStatistics() failed to retrieve RTT from "
4100 "the RTP/RTCP module");
4101 }
4102 } else
4103 {
4104 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4105 VoEId(_instanceId, _channelId),
4106 "GetRTPStatistics() failed to measure RTT since no "
4107 "RTP packets have been received yet");
4108 }
4109 }
4110
4111 stats.rttMs = static_cast<int> (RTT);
4112
4113 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4114 VoEId(_instanceId, _channelId),
4115 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
4116
4117 // --- Part three of the final structure (four values)
4118
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004119 uint32_t bytesSent(0);
4120 uint32_t packetsSent(0);
4121 uint32_t bytesReceived(0);
4122 uint32_t packetsReceived(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004123
stefan@webrtc.orga20e2d42013-08-21 20:58:21 +00004124 if (statistician) {
4125 statistician->GetDataCounters(&bytesReceived, &packetsReceived);
4126 }
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004127
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004128 if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004129 &packetsSent) != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004130 {
4131 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4132 VoEId(_instanceId, _channelId),
4133 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
4134 " output will not be complete");
4135 }
4136
4137 stats.bytesSent = bytesSent;
4138 stats.packetsSent = packetsSent;
4139 stats.bytesReceived = bytesReceived;
4140 stats.packetsReceived = packetsReceived;
4141
4142 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4143 VoEId(_instanceId, _channelId),
4144 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
4145 " bytesReceived=%d, packetsReceived=%d)",
4146 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
4147 stats.packetsReceived);
4148
4149 return 0;
4150}
4151
turaj@webrtc.org7db52902012-12-11 02:15:12 +00004152int Channel::SetFECStatus(bool enable, int redPayloadtype) {
4153 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4154 "Channel::SetFECStatus()");
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004155
turaj@webrtc.org040f8002013-01-31 18:20:17 +00004156 if (enable) {
4157 if (redPayloadtype < 0 || redPayloadtype > 127) {
4158 _engineStatisticsPtr->SetLastError(
4159 VE_PLTYPE_ERROR, kTraceError,
4160 "SetFECStatus() invalid RED payload type");
4161 return -1;
4162 }
4163
4164 if (SetRedPayloadType(redPayloadtype) < 0) {
4165 _engineStatisticsPtr->SetLastError(
4166 VE_CODEC_ERROR, kTraceError,
4167 "SetSecondarySendCodec() Failed to register RED ACM");
4168 return -1;
4169 }
turaj@webrtc.org7db52902012-12-11 02:15:12 +00004170 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004171
turaj@webrtc.org7db52902012-12-11 02:15:12 +00004172 if (_audioCodingModule.SetFECStatus(enable) != 0) {
4173 _engineStatisticsPtr->SetLastError(
4174 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4175 "SetFECStatus() failed to set FEC state in the ACM");
4176 return -1;
4177 }
4178 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004179}
4180
4181int
4182Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
4183{
4184 enabled = _audioCodingModule.FECStatus();
4185 if (enabled)
4186 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004187 int8_t payloadType(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004188 if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
4189 {
4190 _engineStatisticsPtr->SetLastError(
4191 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4192 "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
4193 "module");
4194 return -1;
4195 }
4196 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4197 VoEId(_instanceId, _channelId),
4198 "GetFECStatus() => enabled=%d, redPayloadtype=%d",
4199 enabled, redPayloadtype);
4200 return 0;
4201 }
4202 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4203 VoEId(_instanceId, _channelId),
4204 "GetFECStatus() => enabled=%d", enabled);
4205 return 0;
4206}
4207
pwestin@webrtc.orgb8171ff2013-06-05 15:33:20 +00004208void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
4209 // None of these functions can fail.
4210 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
stefan@webrtc.orgdb74c612013-09-06 13:40:11 +00004211 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
4212 rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +00004213 if (enable)
4214 _audioCodingModule.EnableNack(maxNumberOfPackets);
4215 else
4216 _audioCodingModule.DisableNack();
pwestin@webrtc.orgb8171ff2013-06-05 15:33:20 +00004217}
4218
pwestin@webrtc.org4aa9f1a2013-06-06 21:09:01 +00004219// Called when we are missing one or more packets.
4220int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
pwestin@webrtc.orgb8171ff2013-06-05 15:33:20 +00004221 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
4222}
4223
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004224int
4225Channel::StartRTPDump(const char fileNameUTF8[1024],
4226 RTPDirections direction)
4227{
4228 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4229 "Channel::StartRTPDump()");
4230 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
4231 {
4232 _engineStatisticsPtr->SetLastError(
4233 VE_INVALID_ARGUMENT, kTraceError,
4234 "StartRTPDump() invalid RTP direction");
4235 return -1;
4236 }
4237 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
4238 &_rtpDumpIn : &_rtpDumpOut;
4239 if (rtpDumpPtr == NULL)
4240 {
4241 assert(false);
4242 return -1;
4243 }
4244 if (rtpDumpPtr->IsActive())
4245 {
4246 rtpDumpPtr->Stop();
4247 }
4248 if (rtpDumpPtr->Start(fileNameUTF8) != 0)
4249 {
4250 _engineStatisticsPtr->SetLastError(
4251 VE_BAD_FILE, kTraceError,
4252 "StartRTPDump() failed to create file");
4253 return -1;
4254 }
4255 return 0;
4256}
4257
4258int
4259Channel::StopRTPDump(RTPDirections direction)
4260{
4261 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4262 "Channel::StopRTPDump()");
4263 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
4264 {
4265 _engineStatisticsPtr->SetLastError(
4266 VE_INVALID_ARGUMENT, kTraceError,
4267 "StopRTPDump() invalid RTP direction");
4268 return -1;
4269 }
4270 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
4271 &_rtpDumpIn : &_rtpDumpOut;
4272 if (rtpDumpPtr == NULL)
4273 {
4274 assert(false);
4275 return -1;
4276 }
4277 if (!rtpDumpPtr->IsActive())
4278 {
4279 return 0;
4280 }
4281 return rtpDumpPtr->Stop();
4282}
4283
4284bool
4285Channel::RTPDumpIsActive(RTPDirections direction)
4286{
4287 if ((direction != kRtpIncoming) &&
4288 (direction != kRtpOutgoing))
4289 {
4290 _engineStatisticsPtr->SetLastError(
4291 VE_INVALID_ARGUMENT, kTraceError,
4292 "RTPDumpIsActive() invalid RTP direction");
4293 return false;
4294 }
4295 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
4296 &_rtpDumpIn : &_rtpDumpOut;
4297 return rtpDumpPtr->IsActive();
4298}
4299
4300int
4301Channel::InsertExtraRTPPacket(unsigned char payloadType,
4302 bool markerBit,
4303 const char* payloadData,
4304 unsigned short payloadSize)
4305{
4306 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
4307 "Channel::InsertExtraRTPPacket()");
4308 if (payloadType > 127)
4309 {
4310 _engineStatisticsPtr->SetLastError(
4311 VE_INVALID_PLTYPE, kTraceError,
4312 "InsertExtraRTPPacket() invalid payload type");
4313 return -1;
4314 }
4315 if (payloadData == NULL)
4316 {
4317 _engineStatisticsPtr->SetLastError(
4318 VE_INVALID_ARGUMENT, kTraceError,
4319 "InsertExtraRTPPacket() invalid payload data");
4320 return -1;
4321 }
4322 if (payloadSize > _rtpRtcpModule->MaxDataPayloadLength())
4323 {
4324 _engineStatisticsPtr->SetLastError(
4325 VE_INVALID_ARGUMENT, kTraceError,
4326 "InsertExtraRTPPacket() invalid payload size");
4327 return -1;
4328 }
4329 if (!_sending)
4330 {
4331 _engineStatisticsPtr->SetLastError(
4332 VE_NOT_SENDING, kTraceError,
4333 "InsertExtraRTPPacket() not sending");
4334 return -1;
4335 }
4336
4337 // Create extra RTP packet by calling RtpRtcp::SendOutgoingData().
4338 // Transport::SendPacket() will be called by the module when the RTP packet
4339 // is created.
4340 // The call to SendOutgoingData() does *not* modify the timestamp and
4341 // payloadtype to ensure that the RTP module generates a valid RTP packet
4342 // (user might utilize a non-registered payload type).
4343 // The marker bit and payload type will be replaced just before the actual
4344 // transmission, i.e., the actual modification is done *after* the RTP
4345 // module has delivered its RTP packet back to the VoE.
4346 // We will use the stored values above when the packet is modified
4347 // (see Channel::SendPacket()).
4348
4349 _extraPayloadType = payloadType;
4350 _extraMarkerBit = markerBit;
4351 _insertExtraRTPPacket = true;
4352
4353 if (_rtpRtcpModule->SendOutgoingData(kAudioFrameSpeech,
4354 _lastPayloadType,
4355 _lastLocalTimeStamp,
4356 // Leaving the time when this frame was
4357 // received from the capture device as
4358 // undefined for voice for now.
4359 -1,
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004360 (const uint8_t*) payloadData,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004361 payloadSize) != 0)
4362 {
4363 _engineStatisticsPtr->SetLastError(
4364 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4365 "InsertExtraRTPPacket() failed to send extra RTP packet");
4366 return -1;
4367 }
4368
4369 return 0;
4370}
4371
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004372uint32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004373Channel::Demultiplex(const AudioFrame& audioFrame)
4374{
4375 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4376 "Channel::Demultiplex()");
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00004377 _audioFrame.CopyFrom(audioFrame);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004378 _audioFrame.id_ = _channelId;
4379 return 0;
4380}
4381
xians@webrtc.org44f12392013-07-31 16:23:37 +00004382// TODO(xians): This method borrows quite some code from
4383// TransmitMixer::GenerateAudioFrame(), refactor these two methods and reduce
4384// code duplication.
4385void Channel::Demultiplex(const int16_t* audio_data,
xians@webrtc.org0e6fa8c2013-07-31 16:27:42 +00004386 int sample_rate,
xians@webrtc.org44f12392013-07-31 16:23:37 +00004387 int number_of_frames,
xians@webrtc.org0e6fa8c2013-07-31 16:27:42 +00004388 int number_of_channels) {
xians@webrtc.org44f12392013-07-31 16:23:37 +00004389 // The highest sample rate that WebRTC supports for mono audio is 96kHz.
4390 static const int kMaxNumberOfFrames = 960;
4391 assert(number_of_frames <= kMaxNumberOfFrames);
4392
4393 // Get the send codec information for doing resampling or downmixing later on.
4394 CodecInst codec;
4395 GetSendCodec(codec);
4396 assert(codec.channels == 1 || codec.channels == 2);
4397 int support_sample_rate = std::min(32000,
4398 std::min(sample_rate, codec.plfreq));
4399
4400 // Downmix the data to mono if needed.
4401 const int16_t* audio_ptr = audio_data;
4402 if (number_of_channels == 2 && codec.channels == 1) {
4403 if (!mono_recording_audio_.get())
4404 mono_recording_audio_.reset(new int16_t[kMaxNumberOfFrames]);
4405
4406 AudioFrameOperations::StereoToMono(audio_data, number_of_frames,
4407 mono_recording_audio_.get());
4408 audio_ptr = mono_recording_audio_.get();
4409 }
4410
4411 // Resample the data to the sample rate that the codec is using.
4412 if (input_resampler_.InitializeIfNeeded(sample_rate,
4413 support_sample_rate,
4414 codec.channels)) {
4415 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
4416 "Channel::Demultiplex() unable to resample");
4417 return;
4418 }
4419
4420 int out_length = input_resampler_.Resample(audio_ptr,
4421 number_of_frames * codec.channels,
4422 _audioFrame.data_,
4423 AudioFrame::kMaxDataSizeSamples);
4424 if (out_length == -1) {
4425 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
4426 "Channel::Demultiplex() resampling failed");
4427 return;
4428 }
4429
4430 _audioFrame.samples_per_channel_ = out_length / codec.channels;
4431 _audioFrame.timestamp_ = -1;
4432 _audioFrame.sample_rate_hz_ = support_sample_rate;
4433 _audioFrame.speech_type_ = AudioFrame::kNormalSpeech;
4434 _audioFrame.vad_activity_ = AudioFrame::kVadUnknown;
4435 _audioFrame.num_channels_ = codec.channels;
4436 _audioFrame.id_ = _channelId;
4437}
4438
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004439uint32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004440Channel::PrepareEncodeAndSend(int mixingFrequency)
4441{
4442 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4443 "Channel::PrepareEncodeAndSend()");
4444
4445 if (_audioFrame.samples_per_channel_ == 0)
4446 {
4447 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4448 "Channel::PrepareEncodeAndSend() invalid audio frame");
4449 return -1;
4450 }
4451
4452 if (_inputFilePlaying)
4453 {
4454 MixOrReplaceAudioWithFile(mixingFrequency);
4455 }
4456
4457 if (_mute)
4458 {
4459 AudioFrameOperations::Mute(_audioFrame);
4460 }
4461
4462 if (_inputExternalMedia)
4463 {
4464 CriticalSectionScoped cs(&_callbackCritSect);
4465 const bool isStereo = (_audioFrame.num_channels_ == 2);
4466 if (_inputExternalMediaCallbackPtr)
4467 {
4468 _inputExternalMediaCallbackPtr->Process(
4469 _channelId,
4470 kRecordingPerChannel,
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004471 (int16_t*)_audioFrame.data_,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004472 _audioFrame.samples_per_channel_,
4473 _audioFrame.sample_rate_hz_,
4474 isStereo);
4475 }
4476 }
4477
4478 InsertInbandDtmfTone();
4479
4480 if (_includeAudioLevelIndication)
4481 {
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00004482 if (rtp_audioproc_->set_sample_rate_hz(_audioFrame.sample_rate_hz_) !=
4483 AudioProcessing::kNoError)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004484 {
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00004485 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4486 VoEId(_instanceId, _channelId),
4487 "Error setting AudioProcessing sample rate");
4488 return -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004489 }
4490
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00004491 if (rtp_audioproc_->set_num_channels(_audioFrame.num_channels_,
4492 _audioFrame.num_channels_) !=
4493 AudioProcessing::kNoError)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004494 {
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00004495 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4496 VoEId(_instanceId, _channelId),
4497 "Error setting AudioProcessing channels");
4498 return -1;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004499 }
4500
4501 // Performs level analysis only; does not affect the signal.
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00004502 rtp_audioproc_->ProcessStream(&_audioFrame);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004503 }
4504
4505 return 0;
4506}
4507
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004508uint32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004509Channel::EncodeAndSend()
4510{
4511 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4512 "Channel::EncodeAndSend()");
4513
4514 assert(_audioFrame.num_channels_ <= 2);
4515 if (_audioFrame.samples_per_channel_ == 0)
4516 {
4517 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4518 "Channel::EncodeAndSend() invalid audio frame");
4519 return -1;
4520 }
4521
4522 _audioFrame.id_ = _channelId;
4523
4524 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
4525
4526 // The ACM resamples internally.
4527 _audioFrame.timestamp_ = _timeStamp;
4528 if (_audioCodingModule.Add10MsData((AudioFrame&)_audioFrame) != 0)
4529 {
4530 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
4531 "Channel::EncodeAndSend() ACM encoding failed");
4532 return -1;
4533 }
4534
4535 _timeStamp += _audioFrame.samples_per_channel_;
4536
4537 // --- Encode if complete frame is ready
4538
4539 // This call will trigger AudioPacketizationCallback::SendData if encoding
4540 // is done and payload is ready for packetization and transmission.
4541 return _audioCodingModule.Process();
4542}
4543
4544int Channel::RegisterExternalMediaProcessing(
4545 ProcessingTypes type,
4546 VoEMediaProcess& processObject)
4547{
4548 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4549 "Channel::RegisterExternalMediaProcessing()");
4550
4551 CriticalSectionScoped cs(&_callbackCritSect);
4552
4553 if (kPlaybackPerChannel == type)
4554 {
4555 if (_outputExternalMediaCallbackPtr)
4556 {
4557 _engineStatisticsPtr->SetLastError(
4558 VE_INVALID_OPERATION, kTraceError,
4559 "Channel::RegisterExternalMediaProcessing() "
4560 "output external media already enabled");
4561 return -1;
4562 }
4563 _outputExternalMediaCallbackPtr = &processObject;
4564 _outputExternalMedia = true;
4565 }
4566 else if (kRecordingPerChannel == type)
4567 {
4568 if (_inputExternalMediaCallbackPtr)
4569 {
4570 _engineStatisticsPtr->SetLastError(
4571 VE_INVALID_OPERATION, kTraceError,
4572 "Channel::RegisterExternalMediaProcessing() "
4573 "output external media already enabled");
4574 return -1;
4575 }
4576 _inputExternalMediaCallbackPtr = &processObject;
4577 _inputExternalMedia = true;
4578 }
4579 return 0;
4580}
4581
4582int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
4583{
4584 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4585 "Channel::DeRegisterExternalMediaProcessing()");
4586
4587 CriticalSectionScoped cs(&_callbackCritSect);
4588
4589 if (kPlaybackPerChannel == type)
4590 {
4591 if (!_outputExternalMediaCallbackPtr)
4592 {
4593 _engineStatisticsPtr->SetLastError(
4594 VE_INVALID_OPERATION, kTraceWarning,
4595 "Channel::DeRegisterExternalMediaProcessing() "
4596 "output external media already disabled");
4597 return 0;
4598 }
4599 _outputExternalMedia = false;
4600 _outputExternalMediaCallbackPtr = NULL;
4601 }
4602 else if (kRecordingPerChannel == type)
4603 {
4604 if (!_inputExternalMediaCallbackPtr)
4605 {
4606 _engineStatisticsPtr->SetLastError(
4607 VE_INVALID_OPERATION, kTraceWarning,
4608 "Channel::DeRegisterExternalMediaProcessing() "
4609 "input external media already disabled");
4610 return 0;
4611 }
4612 _inputExternalMedia = false;
4613 _inputExternalMediaCallbackPtr = NULL;
4614 }
4615
4616 return 0;
4617}
4618
roosa@google.comb9e3afc2012-12-12 23:00:29 +00004619int Channel::SetExternalMixing(bool enabled) {
4620 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4621 "Channel::SetExternalMixing(enabled=%d)", enabled);
4622
4623 if (_playing)
4624 {
4625 _engineStatisticsPtr->SetLastError(
4626 VE_INVALID_OPERATION, kTraceError,
4627 "Channel::SetExternalMixing() "
4628 "external mixing cannot be changed while playing.");
4629 return -1;
4630 }
4631
4632 _externalMixing = enabled;
4633
4634 return 0;
4635}
4636
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004637int
4638Channel::ResetRTCPStatistics()
4639{
4640 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4641 "Channel::ResetRTCPStatistics()");
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004642 uint32_t remoteSSRC(0);
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004643 remoteSSRC = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004644 return _rtpRtcpModule->ResetRTT(remoteSSRC);
4645}
4646
4647int
4648Channel::GetRoundTripTimeSummary(StatVal& delaysMs) const
4649{
4650 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4651 "Channel::GetRoundTripTimeSummary()");
4652 // Override default module outputs for the case when RTCP is disabled.
4653 // This is done to ensure that we are backward compatible with the
4654 // VoiceEngine where we did not use RTP/RTCP module.
4655 if (!_rtpRtcpModule->RTCP())
4656 {
4657 delaysMs.min = -1;
4658 delaysMs.max = -1;
4659 delaysMs.average = -1;
4660 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4661 "Channel::GetRoundTripTimeSummary() RTCP is disabled =>"
4662 " valid RTT measurements cannot be retrieved");
4663 return 0;
4664 }
4665
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004666 uint32_t remoteSSRC;
4667 uint16_t RTT;
4668 uint16_t avgRTT;
4669 uint16_t maxRTT;
4670 uint16_t minRTT;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004671 // The remote SSRC will be zero if no RTP packet has been received.
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004672 remoteSSRC = rtp_receiver_->SSRC();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004673 if (remoteSSRC == 0)
4674 {
4675 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4676 "Channel::GetRoundTripTimeSummary() unable to measure RTT"
4677 " since no RTP packet has been received yet");
4678 }
4679
4680 // Retrieve RTT statistics from the RTP/RTCP module for the specified
4681 // channel and SSRC. The SSRC is required to parse out the correct source
4682 // in conference scenarios.
4683 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT,&maxRTT) != 0)
4684 {
4685 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4686 "GetRoundTripTimeSummary unable to retrieve RTT values"
4687 " from the RTCP layer");
4688 delaysMs.min = -1; delaysMs.max = -1; delaysMs.average = -1;
4689 }
4690 else
4691 {
4692 delaysMs.min = minRTT;
4693 delaysMs.max = maxRTT;
4694 delaysMs.average = avgRTT;
4695 }
4696 return 0;
4697}
4698
4699int
4700Channel::GetNetworkStatistics(NetworkStatistics& stats)
4701{
4702 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4703 "Channel::GetNetworkStatistics()");
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00004704 ACMNetworkStatistics acm_stats;
4705 int return_value = _audioCodingModule.NetworkStatistics(&acm_stats);
4706 if (return_value >= 0) {
4707 memcpy(&stats, &acm_stats, sizeof(NetworkStatistics));
4708 }
4709 return return_value;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004710}
4711
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00004712bool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms,
4713 int* playout_buffer_delay_ms) const {
4714 if (_average_jitter_buffer_delay_us == 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004715 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00004716 "Channel::GetDelayEstimate() no valid estimate.");
4717 return false;
4718 }
4719 *jitter_buffer_delay_ms = (_average_jitter_buffer_delay_us + 500) / 1000 +
4720 _recPacketDelayMs;
4721 *playout_buffer_delay_ms = playout_delay_ms_;
4722 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4723 "Channel::GetDelayEstimate()");
4724 return true;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004725}
4726
turaj@webrtc.orgead8a5b2013-02-12 21:42:18 +00004727int Channel::SetInitialPlayoutDelay(int delay_ms)
4728{
4729 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4730 "Channel::SetInitialPlayoutDelay()");
4731 if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
4732 (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs))
4733 {
4734 _engineStatisticsPtr->SetLastError(
4735 VE_INVALID_ARGUMENT, kTraceError,
4736 "SetInitialPlayoutDelay() invalid min delay");
4737 return -1;
4738 }
4739 if (_audioCodingModule.SetInitialPlayoutDelay(delay_ms) != 0)
4740 {
4741 _engineStatisticsPtr->SetLastError(
4742 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4743 "SetInitialPlayoutDelay() failed to set min playout delay");
4744 return -1;
4745 }
4746 return 0;
4747}
4748
4749
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004750int
4751Channel::SetMinimumPlayoutDelay(int delayMs)
4752{
4753 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4754 "Channel::SetMinimumPlayoutDelay()");
4755 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
4756 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
4757 {
4758 _engineStatisticsPtr->SetLastError(
4759 VE_INVALID_ARGUMENT, kTraceError,
4760 "SetMinimumPlayoutDelay() invalid min delay");
4761 return -1;
4762 }
4763 if (_audioCodingModule.SetMinimumPlayoutDelay(delayMs) != 0)
4764 {
4765 _engineStatisticsPtr->SetLastError(
4766 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4767 "SetMinimumPlayoutDelay() failed to set min playout delay");
4768 return -1;
4769 }
4770 return 0;
4771}
4772
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00004773void Channel::UpdatePlayoutTimestamp(bool rtcp) {
4774 uint32_t playout_timestamp = 0;
4775
4776 if (_audioCodingModule.PlayoutTimestamp(&playout_timestamp) == -1) {
4777 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4778 "Channel::UpdatePlayoutTimestamp() failed to read playout"
4779 " timestamp from the ACM");
4780 _engineStatisticsPtr->SetLastError(
4781 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4782 "UpdatePlayoutTimestamp() failed to retrieve timestamp");
4783 return;
4784 }
4785
4786 uint16_t delay_ms = 0;
4787 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
4788 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4789 "Channel::UpdatePlayoutTimestamp() failed to read playout"
4790 " delay from the ADM");
4791 _engineStatisticsPtr->SetLastError(
4792 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4793 "UpdatePlayoutTimestamp() failed to retrieve playout delay");
4794 return;
4795 }
4796
4797 int32_t playout_frequency = _audioCodingModule.PlayoutFrequency();
4798 CodecInst current_recive_codec;
4799 if (_audioCodingModule.ReceiveCodec(&current_recive_codec) == 0) {
4800 if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) {
4801 playout_frequency = 8000;
4802 } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) {
4803 playout_frequency = 48000;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004804 }
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00004805 }
4806
4807 // Remove the playout delay.
4808 playout_timestamp -= (delay_ms * (playout_frequency / 1000));
4809
4810 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4811 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
4812 playout_timestamp);
4813
4814 if (rtcp) {
4815 playout_timestamp_rtcp_ = playout_timestamp;
4816 } else {
4817 playout_timestamp_rtp_ = playout_timestamp;
4818 }
4819 playout_delay_ms_ = delay_ms;
4820}
4821
4822int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
4823 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4824 "Channel::GetPlayoutTimestamp()");
4825 if (playout_timestamp_rtp_ == 0) {
4826 _engineStatisticsPtr->SetLastError(
4827 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4828 "GetPlayoutTimestamp() failed to retrieve timestamp");
4829 return -1;
4830 }
4831 timestamp = playout_timestamp_rtp_;
4832 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4833 VoEId(_instanceId,_channelId),
4834 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
4835 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004836}
4837
4838int
4839Channel::SetInitTimestamp(unsigned int timestamp)
4840{
4841 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4842 "Channel::SetInitTimestamp()");
4843 if (_sending)
4844 {
4845 _engineStatisticsPtr->SetLastError(
4846 VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
4847 return -1;
4848 }
4849 if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
4850 {
4851 _engineStatisticsPtr->SetLastError(
4852 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4853 "SetInitTimestamp() failed to set timestamp");
4854 return -1;
4855 }
4856 return 0;
4857}
4858
4859int
4860Channel::SetInitSequenceNumber(short sequenceNumber)
4861{
4862 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4863 "Channel::SetInitSequenceNumber()");
4864 if (_sending)
4865 {
4866 _engineStatisticsPtr->SetLastError(
4867 VE_SENDING, kTraceError,
4868 "SetInitSequenceNumber() already sending");
4869 return -1;
4870 }
4871 if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
4872 {
4873 _engineStatisticsPtr->SetLastError(
4874 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4875 "SetInitSequenceNumber() failed to set sequence number");
4876 return -1;
4877 }
4878 return 0;
4879}
4880
4881int
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004882Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004883{
4884 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4885 "Channel::GetRtpRtcp()");
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00004886 *rtpRtcpModule = _rtpRtcpModule.get();
4887 *rtp_receiver = rtp_receiver_.get();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004888 return 0;
4889}
4890
4891// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
4892// a shared helper.
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004893int32_t
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00004894Channel::MixOrReplaceAudioWithFile(int mixingFrequency)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004895{
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004896 scoped_array<int16_t> fileBuffer(new int16_t[640]);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004897 int fileSamples(0);
4898
4899 {
4900 CriticalSectionScoped cs(&_fileCritSect);
4901
4902 if (_inputFilePlayerPtr == NULL)
4903 {
4904 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4905 VoEId(_instanceId, _channelId),
4906 "Channel::MixOrReplaceAudioWithFile() fileplayer"
4907 " doesnt exist");
4908 return -1;
4909 }
4910
4911 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
4912 fileSamples,
4913 mixingFrequency) == -1)
4914 {
4915 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4916 VoEId(_instanceId, _channelId),
4917 "Channel::MixOrReplaceAudioWithFile() file mixing "
4918 "failed");
4919 return -1;
4920 }
4921 if (fileSamples == 0)
4922 {
4923 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4924 VoEId(_instanceId, _channelId),
4925 "Channel::MixOrReplaceAudioWithFile() file is ended");
4926 return 0;
4927 }
4928 }
4929
4930 assert(_audioFrame.samples_per_channel_ == fileSamples);
4931
4932 if (_mixFileWithMicrophone)
4933 {
4934 // Currently file stream is always mono.
4935 // TODO(xians): Change the code when FilePlayer supports real stereo.
4936 Utility::MixWithSat(_audioFrame.data_,
4937 _audioFrame.num_channels_,
4938 fileBuffer.get(),
4939 1,
4940 fileSamples);
4941 }
4942 else
4943 {
4944 // Replace ACM audio with file.
4945 // Currently file stream is always mono.
4946 // TODO(xians): Change the code when FilePlayer supports real stereo.
4947 _audioFrame.UpdateFrame(_channelId,
4948 -1,
4949 fileBuffer.get(),
4950 fileSamples,
4951 mixingFrequency,
4952 AudioFrame::kNormalSpeech,
4953 AudioFrame::kVadUnknown,
4954 1);
4955
4956 }
4957 return 0;
4958}
4959
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004960int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004961Channel::MixAudioWithFile(AudioFrame& audioFrame,
pbos@webrtc.orgca7a9a22013-05-14 08:31:39 +00004962 int mixingFrequency)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004963{
4964 assert(mixingFrequency <= 32000);
4965
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00004966 scoped_array<int16_t> fileBuffer(new int16_t[640]);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00004967 int fileSamples(0);
4968
4969 {
4970 CriticalSectionScoped cs(&_fileCritSect);
4971
4972 if (_outputFilePlayerPtr == NULL)
4973 {
4974 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4975 VoEId(_instanceId, _channelId),
4976 "Channel::MixAudioWithFile() file mixing failed");
4977 return -1;
4978 }
4979
4980 // We should get the frequency we ask for.
4981 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
4982 fileSamples,
4983 mixingFrequency) == -1)
4984 {
4985 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4986 VoEId(_instanceId, _channelId),
4987 "Channel::MixAudioWithFile() file mixing failed");
4988 return -1;
4989 }
4990 }
4991
4992 if (audioFrame.samples_per_channel_ == fileSamples)
4993 {
4994 // Currently file stream is always mono.
4995 // TODO(xians): Change the code when FilePlayer supports real stereo.
4996 Utility::MixWithSat(audioFrame.data_,
4997 audioFrame.num_channels_,
4998 fileBuffer.get(),
4999 1,
5000 fileSamples);
5001 }
5002 else
5003 {
5004 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
5005 "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
5006 "fileSamples(%d)",
5007 audioFrame.samples_per_channel_, fileSamples);
5008 return -1;
5009 }
5010
5011 return 0;
5012}
5013
5014int
5015Channel::InsertInbandDtmfTone()
5016{
5017 // Check if we should start a new tone.
5018 if (_inbandDtmfQueue.PendingDtmf() &&
5019 !_inbandDtmfGenerator.IsAddingTone() &&
5020 _inbandDtmfGenerator.DelaySinceLastTone() >
5021 kMinTelephoneEventSeparationMs)
5022 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005023 int8_t eventCode(0);
5024 uint16_t lengthMs(0);
5025 uint8_t attenuationDb(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005026
5027 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
5028 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
5029 if (_playInbandDtmfEvent)
5030 {
5031 // Add tone to output mixer using a reduced length to minimize
5032 // risk of echo.
5033 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
5034 attenuationDb);
5035 }
5036 }
5037
5038 if (_inbandDtmfGenerator.IsAddingTone())
5039 {
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005040 uint16_t frequency(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005041 _inbandDtmfGenerator.GetSampleRate(frequency);
5042
5043 if (frequency != _audioFrame.sample_rate_hz_)
5044 {
5045 // Update sample rate of Dtmf tone since the mixing frequency
5046 // has changed.
5047 _inbandDtmfGenerator.SetSampleRate(
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005048 (uint16_t) (_audioFrame.sample_rate_hz_));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005049 // Reset the tone to be added taking the new sample rate into
5050 // account.
5051 _inbandDtmfGenerator.ResetTone();
5052 }
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00005053
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005054 int16_t toneBuffer[320];
5055 uint16_t toneSamples(0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005056 // Get 10ms tone segment and set time since last tone to zero
5057 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
5058 {
5059 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
5060 VoEId(_instanceId, _channelId),
5061 "Channel::EncodeAndSend() inserting Dtmf failed");
5062 return -1;
5063 }
5064
5065 // Replace mixed audio with DTMF tone.
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00005066 for (int sample = 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005067 sample < _audioFrame.samples_per_channel_;
5068 sample++)
5069 {
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00005070 for (int channel = 0;
5071 channel < _audioFrame.num_channels_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005072 channel++)
5073 {
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00005074 const int index = sample * _audioFrame.num_channels_ + channel;
5075 _audioFrame.data_[index] = toneBuffer[sample];
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005076 }
5077 }
andrew@webrtc.orgd4682362013-01-22 04:44:30 +00005078
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005079 assert(_audioFrame.samples_per_channel_ == toneSamples);
5080 } else
5081 {
5082 // Add 10ms to "delay-since-last-tone" counter
5083 _inbandDtmfGenerator.UpdateDelaySinceLastTone();
5084 }
5085 return 0;
5086}
5087
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005088void
5089Channel::ResetDeadOrAliveCounters()
5090{
5091 _countDeadDetections = 0;
5092 _countAliveDetections = 0;
5093}
5094
5095void
5096Channel::UpdateDeadOrAliveCounters(bool alive)
5097{
5098 if (alive)
5099 _countAliveDetections++;
5100 else
5101 _countDeadDetections++;
5102}
5103
5104int
5105Channel::GetDeadOrAliveCounters(int& countDead, int& countAlive) const
5106{
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005107 return 0;
5108}
5109
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005110int32_t
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005111Channel::SendPacketRaw(const void *data, int len, bool RTCP)
5112{
5113 if (_transportPtr == NULL)
5114 {
5115 return -1;
5116 }
5117 if (!RTCP)
5118 {
5119 return _transportPtr->SendPacket(_channelId, data, len);
5120 }
5121 else
5122 {
5123 return _transportPtr->SendRTCPPacket(_channelId, data, len);
5124 }
5125}
5126
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005127// Called for incoming RTP packets after successful RTP header parsing.
5128void Channel::UpdatePacketDelay(uint32_t rtp_timestamp,
5129 uint16_t sequence_number) {
5130 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
5131 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
5132 rtp_timestamp, sequence_number);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005133
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005134 // Get frequency of last received payload
5135 int rtp_receive_frequency = _audioCodingModule.ReceiveFrequency();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005136
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005137 CodecInst current_receive_codec;
5138 if (_audioCodingModule.ReceiveCodec(&current_receive_codec) != 0) {
5139 return;
5140 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005141
turaj@webrtc.orgd5577342013-05-22 20:39:43 +00005142 // Update the least required delay.
5143 least_required_delay_ms_ = _audioCodingModule.LeastRequiredDelayMs();
5144
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005145 if (STR_CASE_CMP("G722", current_receive_codec.plname) == 0) {
5146 // Even though the actual sampling rate for G.722 audio is
5147 // 16,000 Hz, the RTP clock rate for the G722 payload format is
5148 // 8,000 Hz because that value was erroneously assigned in
5149 // RFC 1890 and must remain unchanged for backward compatibility.
5150 rtp_receive_frequency = 8000;
5151 } else if (STR_CASE_CMP("opus", current_receive_codec.plname) == 0) {
5152 // We are resampling Opus internally to 32,000 Hz until all our
5153 // DSP routines can operate at 48,000 Hz, but the RTP clock
5154 // rate for the Opus payload format is standardized to 48,000 Hz,
5155 // because that is the maximum supported decoding sampling rate.
5156 rtp_receive_frequency = 48000;
5157 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005158
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005159 // playout_timestamp_rtp_ updated in UpdatePlayoutTimestamp for every incoming
5160 // packet.
5161 uint32_t timestamp_diff_ms = (rtp_timestamp - playout_timestamp_rtp_) /
5162 (rtp_receive_frequency / 1000);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005163
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005164 uint16_t packet_delay_ms = (rtp_timestamp - _previousTimestamp) /
5165 (rtp_receive_frequency / 1000);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005166
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005167 _previousTimestamp = rtp_timestamp;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005168
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005169 if (timestamp_diff_ms > (2 * kVoiceEngineMaxMinPlayoutDelayMs)) {
5170 timestamp_diff_ms = 0;
5171 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005172
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005173 if (timestamp_diff_ms == 0) return;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005174
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005175 if (packet_delay_ms >= 10 && packet_delay_ms <= 60) {
5176 _recPacketDelayMs = packet_delay_ms;
5177 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005178
pwestin@webrtc.orgf2724972013-04-11 20:23:35 +00005179 if (_average_jitter_buffer_delay_us == 0) {
5180 _average_jitter_buffer_delay_us = timestamp_diff_ms * 1000;
5181 return;
5182 }
5183
5184 // Filter average delay value using exponential filter (alpha is
5185 // 7/8). We derive 1000 *_average_jitter_buffer_delay_us here (reduces
5186 // risk of rounding error) and compensate for it in GetDelayEstimate()
5187 // later.
5188 _average_jitter_buffer_delay_us = (_average_jitter_buffer_delay_us * 7 +
5189 1000 * timestamp_diff_ms + 500) / 8;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005190}
5191
5192void
5193Channel::RegisterReceiveCodecsToRTPModule()
5194{
5195 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
5196 "Channel::RegisterReceiveCodecsToRTPModule()");
5197
5198
5199 CodecInst codec;
pbos@webrtc.org54f03bc2013-04-09 10:09:10 +00005200 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005201
5202 for (int idx = 0; idx < nSupportedCodecs; idx++)
5203 {
5204 // Open up the RTP/RTCP receiver for all supported codecs
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00005205 if ((_audioCodingModule.Codec(idx, &codec) == -1) ||
wu@webrtc.org7fc75bb2013-08-15 23:38:54 +00005206 (rtp_receiver_->RegisterReceivePayload(
5207 codec.plname,
5208 codec.pltype,
5209 codec.plfreq,
5210 codec.channels,
5211 (codec.rate < 0) ? 0 : codec.rate) == -1))
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005212 {
5213 WEBRTC_TRACE(
5214 kTraceWarning,
5215 kTraceVoice,
5216 VoEId(_instanceId, _channelId),
5217 "Channel::RegisterReceiveCodecsToRTPModule() unable"
5218 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
5219 codec.plname, codec.pltype, codec.plfreq,
5220 codec.channels, codec.rate);
5221 }
5222 else
5223 {
5224 WEBRTC_TRACE(
5225 kTraceInfo,
5226 kTraceVoice,
5227 VoEId(_instanceId, _channelId),
5228 "Channel::RegisterReceiveCodecsToRTPModule() %s "
5229 "(%d/%d/%d/%d) has been added to the RTP/RTCP "
5230 "receiver",
5231 codec.plname, codec.pltype, codec.plfreq,
5232 codec.channels, codec.rate);
5233 }
5234 }
5235}
5236
andrew@webrtc.orgd898c012012-11-14 19:07:54 +00005237int Channel::ApmProcessRx(AudioFrame& frame) {
andrew@webrtc.orgd898c012012-11-14 19:07:54 +00005238 // Register the (possibly new) frame parameters.
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00005239 if (rx_audioproc_->set_sample_rate_hz(frame.sample_rate_hz_) != 0) {
andrew@webrtc.orgbc687c52012-11-20 07:34:45 +00005240 LOG_FERR1(LS_WARNING, set_sample_rate_hz, frame.sample_rate_hz_);
andrew@webrtc.orgd898c012012-11-14 19:07:54 +00005241 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00005242 if (rx_audioproc_->set_num_channels(frame.num_channels_,
5243 frame.num_channels_) != 0) {
andrew@webrtc.orgbc687c52012-11-20 07:34:45 +00005244 LOG_FERR1(LS_WARNING, set_num_channels, frame.num_channels_);
andrew@webrtc.orgd898c012012-11-14 19:07:54 +00005245 }
andrew@webrtc.org80142aa2013-09-18 22:37:32 +00005246 if (rx_audioproc_->ProcessStream(&frame) != 0) {
andrew@webrtc.orgbc687c52012-11-20 07:34:45 +00005247 LOG_FERR0(LS_WARNING, ProcessStream);
andrew@webrtc.orgd898c012012-11-14 19:07:54 +00005248 }
5249 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00005250}
5251
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005252int Channel::SetSecondarySendCodec(const CodecInst& codec,
5253 int red_payload_type) {
turaj@webrtc.org040f8002013-01-31 18:20:17 +00005254 // Sanity check for payload type.
5255 if (red_payload_type < 0 || red_payload_type > 127) {
5256 _engineStatisticsPtr->SetLastError(
5257 VE_PLTYPE_ERROR, kTraceError,
5258 "SetRedPayloadType() invalid RED payload type");
5259 return -1;
5260 }
5261
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005262 if (SetRedPayloadType(red_payload_type) < 0) {
5263 _engineStatisticsPtr->SetLastError(
5264 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5265 "SetSecondarySendCodec() Failed to register RED ACM");
5266 return -1;
5267 }
5268 if (_audioCodingModule.RegisterSecondarySendCodec(codec) < 0) {
5269 _engineStatisticsPtr->SetLastError(
5270 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5271 "SetSecondarySendCodec() Failed to register secondary send codec in "
5272 "ACM");
5273 return -1;
5274 }
5275
5276 return 0;
5277}
5278
5279void Channel::RemoveSecondarySendCodec() {
5280 _audioCodingModule.UnregisterSecondarySendCodec();
5281}
5282
5283int Channel::GetSecondarySendCodec(CodecInst* codec) {
5284 if (_audioCodingModule.SecondarySendCodec(codec) < 0) {
5285 _engineStatisticsPtr->SetLastError(
5286 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5287 "GetSecondarySendCodec() Failed to get secondary sent codec from ACM");
5288 return -1;
5289 }
5290 return 0;
5291}
5292
turaj@webrtc.org040f8002013-01-31 18:20:17 +00005293// Assuming this method is called with valid payload type.
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005294int Channel::SetRedPayloadType(int red_payload_type) {
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005295 CodecInst codec;
5296 bool found_red = false;
5297
5298 // Get default RED settings from the ACM database
5299 const int num_codecs = AudioCodingModule::NumberOfCodecs();
5300 for (int idx = 0; idx < num_codecs; idx++) {
tina.legrand@webrtc.orge9bb4e52013-02-21 10:27:48 +00005301 _audioCodingModule.Codec(idx, &codec);
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005302 if (!STR_CASE_CMP(codec.plname, "RED")) {
5303 found_red = true;
5304 break;
5305 }
5306 }
5307
5308 if (!found_red) {
5309 _engineStatisticsPtr->SetLastError(
5310 VE_CODEC_ERROR, kTraceError,
5311 "SetRedPayloadType() RED is not supported");
5312 return -1;
5313 }
5314
turaj@webrtc.org2344ebe2013-01-31 18:34:19 +00005315 codec.pltype = red_payload_type;
turaj@webrtc.org7db52902012-12-11 02:15:12 +00005316 if (_audioCodingModule.RegisterSendCodec(codec) < 0) {
5317 _engineStatisticsPtr->SetLastError(
5318 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
5319 "SetRedPayloadType() RED registration in ACM module failed");
5320 return -1;
5321 }
5322
5323 if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
5324 _engineStatisticsPtr->SetLastError(
5325 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
5326 "SetRedPayloadType() RED registration in RTP/RTCP module failed");
5327 return -1;
5328 }
5329 return 0;
5330}
5331
pbos@webrtc.org3b89e102013-07-03 15:12:26 +00005332} // namespace voe
5333} // namespace webrtc