2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/voice_engine/channel.h"
13 #include "webrtc/common.h"
14 #include "webrtc/modules/audio_device/include/audio_device.h"
15 #include "webrtc/modules/audio_processing/include/audio_processing.h"
16 #include "webrtc/modules/interface/module_common_types.h"
17 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
18 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
19 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
21 #include "webrtc/modules/utility/interface/audio_frame_operations.h"
22 #include "webrtc/modules/utility/interface/process_thread.h"
23 #include "webrtc/modules/utility/interface/rtp_dump.h"
24 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
25 #include "webrtc/system_wrappers/interface/logging.h"
26 #include "webrtc/system_wrappers/interface/trace.h"
27 #include "webrtc/video_engine/include/vie_network.h"
28 #include "webrtc/voice_engine/include/voe_base.h"
29 #include "webrtc/voice_engine/include/voe_external_media.h"
30 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
31 #include "webrtc/voice_engine/output_mixer.h"
32 #include "webrtc/voice_engine/statistics.h"
33 #include "webrtc/voice_engine/transmit_mixer.h"
34 #include "webrtc/voice_engine/utility.h"
43 // Extend the default RTCP statistics struct with max_jitter, defined as the
44 // maximum jitter value seen in an RTCP report block.
45 struct ChannelStatistics : public RtcpStatistics {
46 ChannelStatistics() : rtcp(), max_jitter(0) {}
52 // Statistics callback, called at each generation of a new RTCP report block.
53 class StatisticsProxy : public RtcpStatisticsCallback {
55 StatisticsProxy(uint32_t ssrc)
56 : stats_lock_(CriticalSectionWrapper::CreateCriticalSection()),
58 virtual ~StatisticsProxy() {}
60 virtual void StatisticsUpdated(const RtcpStatistics& statistics,
61 uint32_t ssrc) OVERRIDE {
65 CriticalSectionScoped cs(stats_lock_.get());
66 stats_.rtcp = statistics;
67 if (statistics.jitter > stats_.max_jitter) {
68 stats_.max_jitter = statistics.jitter;
72 void ResetStatistics() {
73 CriticalSectionScoped cs(stats_lock_.get());
74 stats_ = ChannelStatistics();
77 ChannelStatistics GetStats() {
78 CriticalSectionScoped cs(stats_lock_.get());
83 // StatisticsUpdated calls are triggered from threads in the RTP module,
84 // while GetStats calls can be triggered from the public voice engine API,
85 // hence synchronization is needed.
86 scoped_ptr<CriticalSectionWrapper> stats_lock_;
88 ChannelStatistics stats_;
92 Channel::SendData(FrameType frameType,
95 const uint8_t* payloadData,
97 const RTPFragmentationHeader* fragmentation)
99 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
100 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
101 " payloadSize=%u, fragmentation=0x%x)",
102 frameType, payloadType, timeStamp, payloadSize, fragmentation);
104 if (_includeAudioLevelIndication)
106 // Store current audio level in the RTP/RTCP module.
107 // The level will be used in combination with voice-activity state
108 // (frameType) to add an RTP header extension
109 _rtpRtcpModule->SetAudioLevel(rms_level_.RMS());
112 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
114 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
115 if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType,
118 // Leaving the time when this frame was
119 // received from the capture device as
120 // undefined for voice for now.
124 fragmentation) == -1)
126 _engineStatisticsPtr->SetLastError(
127 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
128 "Channel::SendData() failed to send data to RTP/RTCP module");
132 _lastLocalTimeStamp = timeStamp;
133 _lastPayloadType = payloadType;
139 Channel::InFrameType(int16_t frameType)
141 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
142 "Channel::InFrameType(frameType=%d)", frameType);
144 CriticalSectionScoped cs(&_callbackCritSect);
145 // 1 indicates speech
146 _sendFrameType = (frameType == 1) ? 1 : 0;
151 Channel::OnRxVadDetected(int vadDecision)
153 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
154 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision);
156 CriticalSectionScoped cs(&_callbackCritSect);
157 if (_rxVadObserverPtr)
159 _rxVadObserverPtr->OnRxVad(_channelId, vadDecision);
166 Channel::SendPacket(int channel, const void *data, int len)
168 channel = VoEChannelId(channel);
169 assert(channel == _channelId);
171 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
172 "Channel::SendPacket(channel=%d, len=%d)", channel, len);
174 CriticalSectionScoped cs(&_callbackCritSect);
176 if (_transportPtr == NULL)
178 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
179 "Channel::SendPacket() failed to send RTP packet due to"
180 " invalid transport object");
184 uint8_t* bufferToSendPtr = (uint8_t*)data;
185 int32_t bufferLength = len;
187 // Dump the RTP packet to a file (if RTP dump is enabled).
188 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
190 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
191 VoEId(_instanceId,_channelId),
192 "Channel::SendPacket() RTP dump to output file failed");
195 int n = _transportPtr->SendPacket(channel, bufferToSendPtr,
198 std::string transport_name =
199 _externalTransport ? "external transport" : "WebRtc sockets";
200 WEBRTC_TRACE(kTraceError, kTraceVoice,
201 VoEId(_instanceId,_channelId),
202 "Channel::SendPacket() RTP transmission using %s failed",
203 transport_name.c_str());
210 Channel::SendRTCPPacket(int channel, const void *data, int len)
212 channel = VoEChannelId(channel);
213 assert(channel == _channelId);
215 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
216 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len);
218 CriticalSectionScoped cs(&_callbackCritSect);
219 if (_transportPtr == NULL)
221 WEBRTC_TRACE(kTraceError, kTraceVoice,
222 VoEId(_instanceId,_channelId),
223 "Channel::SendRTCPPacket() failed to send RTCP packet"
224 " due to invalid transport object");
228 uint8_t* bufferToSendPtr = (uint8_t*)data;
229 int32_t bufferLength = len;
231 // Dump the RTCP packet to a file (if RTP dump is enabled).
232 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1)
234 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
235 VoEId(_instanceId,_channelId),
236 "Channel::SendPacket() RTCP dump to output file failed");
239 int n = _transportPtr->SendRTCPPacket(channel,
243 std::string transport_name =
244 _externalTransport ? "external transport" : "WebRtc sockets";
245 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
246 VoEId(_instanceId,_channelId),
247 "Channel::SendRTCPPacket() transmission using %s failed",
248 transport_name.c_str());
255 Channel::OnPlayTelephoneEvent(int32_t id,
260 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
261 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u,"
262 " volume=%u)", id, event, lengthMs, volume);
264 if (!_playOutbandDtmfEvent || (event > 15))
266 // Ignore callback since feedback is disabled or event is not a
271 assert(_outputMixerPtr != NULL);
273 // Start playing out the Dtmf tone (if playout is enabled).
274 // Reduce length of tone with 80ms to the reduce risk of echo.
275 _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume);
279 Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc)
281 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
282 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)",
285 int32_t channel = VoEChannelId(id);
286 assert(channel == _channelId);
288 // Update ssrc so that NTP for AV sync can be updated.
289 _rtpRtcpModule->SetRemoteSSRC(ssrc);
293 CriticalSectionScoped cs(&_callbackCritSect);
297 // Send new SSRC to registered observer using callback
298 _rtpObserverPtr->OnIncomingSSRCChanged(channel, ssrc);
303 void Channel::OnIncomingCSRCChanged(int32_t id,
307 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
308 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)",
311 int32_t channel = VoEChannelId(id);
312 assert(channel == _channelId);
316 CriticalSectionScoped cs(&_callbackCritSect);
320 _rtpObserverPtr->OnIncomingCSRCChanged(channel, CSRC, added);
325 void Channel::ResetStatistics(uint32_t ssrc) {
326 StreamStatistician* statistician =
327 rtp_receive_statistics_->GetStatistician(ssrc);
329 statistician->ResetStatistics();
331 statistics_proxy_->ResetStatistics();
335 Channel::OnApplicationDataReceived(int32_t id,
341 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
342 "Channel::OnApplicationDataReceived(id=%d, subType=%u,"
343 " name=%u, length=%u)",
344 id, subType, name, length);
346 int32_t channel = VoEChannelId(id);
347 assert(channel == _channelId);
351 CriticalSectionScoped cs(&_callbackCritSect);
353 if (_rtcpObserverPtr)
355 _rtcpObserverPtr->OnApplicationDataReceived(channel,
365 Channel::OnInitializeDecoder(
368 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
373 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
374 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, "
375 "payloadName=%s, frequency=%u, channels=%u, rate=%u)",
376 id, payloadType, payloadName, frequency, channels, rate);
378 assert(VoEChannelId(id) == _channelId);
380 CodecInst receiveCodec = {0};
381 CodecInst dummyCodec = {0};
383 receiveCodec.pltype = payloadType;
384 receiveCodec.plfreq = frequency;
385 receiveCodec.channels = channels;
386 receiveCodec.rate = rate;
387 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
389 audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
390 receiveCodec.pacsize = dummyCodec.pacsize;
392 // Register the new codec to the ACM
393 if (audio_coding_->RegisterReceiveCodec(receiveCodec) == -1)
395 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
396 VoEId(_instanceId, _channelId),
397 "Channel::OnInitializeDecoder() invalid codec ("
398 "pt=%d, name=%s) received - 1", payloadType, payloadName);
399 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
407 Channel::OnPacketTimeout(int32_t id)
409 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
410 "Channel::OnPacketTimeout(id=%d)", id);
412 CriticalSectionScoped cs(_callbackCritSectPtr);
413 if (_voiceEngineObserverPtr)
415 if (channel_state_.Get().receiving || _externalTransport)
417 int32_t channel = VoEChannelId(id);
418 assert(channel == _channelId);
419 // Ensure that next OnReceivedPacket() callback will trigger
420 // a VE_PACKET_RECEIPT_RESTARTED callback.
421 _rtpPacketTimedOut = true;
422 // Deliver callback to the observer
423 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
424 VoEId(_instanceId,_channelId),
425 "Channel::OnPacketTimeout() => "
426 "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)");
427 _voiceEngineObserverPtr->CallbackOnError(channel,
428 VE_RECEIVE_PACKET_TIMEOUT);
434 Channel::OnReceivedPacket(int32_t id,
435 RtpRtcpPacketType packetType)
437 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
438 "Channel::OnReceivedPacket(id=%d, packetType=%d)",
441 assert(VoEChannelId(id) == _channelId);
443 // Notify only for the case when we have restarted an RTP session.
444 if (_rtpPacketTimedOut && (kPacketRtp == packetType))
446 CriticalSectionScoped cs(_callbackCritSectPtr);
447 if (_voiceEngineObserverPtr)
449 int32_t channel = VoEChannelId(id);
450 assert(channel == _channelId);
451 // Reset timeout mechanism
452 _rtpPacketTimedOut = false;
453 // Deliver callback to the observer
454 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
455 VoEId(_instanceId,_channelId),
456 "Channel::OnPacketTimeout() =>"
457 " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)");
458 _voiceEngineObserverPtr->CallbackOnError(
460 VE_PACKET_RECEIPT_RESTARTED);
466 Channel::OnPeriodicDeadOrAlive(int32_t id,
469 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
470 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive);
473 CriticalSectionScoped cs(&_callbackCritSect);
474 if (!_connectionObserver)
478 int32_t channel = VoEChannelId(id);
479 assert(channel == _channelId);
481 // Use Alive as default to limit risk of false Dead detections
484 // Always mark the connection as Dead when the module reports kRtpDead
485 if (kRtpDead == alive)
490 // It is possible that the connection is alive even if no RTP packet has
491 // been received for a long time since the other side might use VAD/DTX
492 // and a low SID-packet update rate.
493 if ((kRtpNoRtp == alive) && channel_state_.Get().playing)
495 // Detect Alive for all NetEQ states except for the case when we are
497 // PLC_CNG <=> background noise only due to long expand or error.
498 // Note that, the case where the other side stops sending during CNG
499 // state will be detected as Alive. Dead is is not set until after
500 // missing RTCP packets for at least twelve seconds (handled
501 // internally by the RTP/RTCP module).
502 isAlive = (_outputSpeechType != AudioFrame::kPLCCNG);
505 // Send callback to the registered observer
506 if (_connectionObserver)
508 CriticalSectionScoped cs(&_callbackCritSect);
509 if (_connectionObserverPtr)
511 _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive);
517 Channel::OnReceivedPayloadData(const uint8_t* payloadData,
518 uint16_t payloadSize,
519 const WebRtcRTPHeader* rtpHeader)
521 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
522 "Channel::OnReceivedPayloadData(payloadSize=%d,"
523 " payloadType=%u, audioChannel=%u)",
525 rtpHeader->header.payloadType,
526 rtpHeader->type.Audio.channel);
528 _lastRemoteTimeStamp = rtpHeader->header.timestamp;
530 if (!channel_state_.Get().playing)
532 // Avoid inserting into NetEQ when we are not playing. Count the
533 // packet as discarded.
534 WEBRTC_TRACE(kTraceStream, kTraceVoice,
535 VoEId(_instanceId, _channelId),
536 "received packet is discarded since playing is not"
538 _numberOfDiscardedPackets++;
542 // Push the incoming payload (parsed and ready for decoding) into the ACM
543 if (audio_coding_->IncomingPacket(payloadData,
547 _engineStatisticsPtr->SetLastError(
548 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
549 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
553 // Update the packet delay.
554 UpdatePacketDelay(rtpHeader->header.timestamp,
555 rtpHeader->header.sequenceNumber);
557 uint16_t round_trip_time = 0;
558 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time,
561 std::vector<uint16_t> nack_list = audio_coding_->GetNackList(
563 if (!nack_list.empty()) {
564 // Can't use nack_list.data() since it's not supported by all
566 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
571 bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
572 int rtp_packet_length) {
574 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
575 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
576 "IncomingPacket invalid RTP header");
579 header.payload_type_frequency =
580 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
581 if (header.payload_type_frequency < 0)
583 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
586 int32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame)
588 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
589 "Channel::GetAudioFrame(id=%d)", id);
591 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
592 if (audio_coding_->PlayoutData10Ms(audioFrame.sample_rate_hz_,
595 WEBRTC_TRACE(kTraceError, kTraceVoice,
596 VoEId(_instanceId,_channelId),
597 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
598 // In all likelihood, the audio in this frame is garbage. We return an
599 // error so that the audio mixer module doesn't add it to the mix. As
600 // a result, it won't be played out and the actions skipped here are
607 UpdateRxVadDetection(audioFrame);
610 // Convert module ID to internal VoE channel ID
611 audioFrame.id_ = VoEChannelId(audioFrame.id_);
612 // Store speech type for dead-or-alive detection
613 _outputSpeechType = audioFrame.speech_type_;
615 ChannelState::State state = channel_state_.Get();
617 if (state.rx_apm_is_enabled) {
618 int err = rx_audioproc_->ProcessStream(&audioFrame);
620 LOG(LS_ERROR) << "ProcessStream() error: " << err;
625 float output_gain = 1.0f;
626 float left_pan = 1.0f;
627 float right_pan = 1.0f;
629 CriticalSectionScoped cs(&volume_settings_critsect_);
630 output_gain = _outputGain;
632 right_pan= _panRight;
635 // Output volume scaling
636 if (output_gain < 0.99f || output_gain > 1.01f)
638 AudioFrameOperations::ScaleWithSat(output_gain, audioFrame);
641 // Scale left and/or right channel(s) if stereo and master balance is
644 if (left_pan != 1.0f || right_pan != 1.0f)
646 if (audioFrame.num_channels_ == 1)
648 // Emulate stereo mode since panning is active.
649 // The mono signal is copied to both left and right channels here.
650 AudioFrameOperations::MonoToStereo(&audioFrame);
652 // For true stereo mode (when we are receiving a stereo signal), no
655 // Do the panning operation (the audio frame contains stereo at this
657 AudioFrameOperations::Scale(left_pan, right_pan, audioFrame);
660 // Mix decoded PCM output with file if file mixing is enabled
661 if (state.output_file_playing)
663 MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
667 if (_outputExternalMedia)
669 CriticalSectionScoped cs(&_callbackCritSect);
670 const bool isStereo = (audioFrame.num_channels_ == 2);
671 if (_outputExternalMediaCallbackPtr)
673 _outputExternalMediaCallbackPtr->Process(
676 (int16_t*)audioFrame.data_,
677 audioFrame.samples_per_channel_,
678 audioFrame.sample_rate_hz_,
683 // Record playout if enabled
685 CriticalSectionScoped cs(&_fileCritSect);
687 if (_outputFileRecording && _outputFileRecorderPtr)
689 _outputFileRecorderPtr->RecordAudioToFile(audioFrame);
693 // Measure audio level (0-9)
694 _outputAudioLevel.ComputeLevel(audioFrame);
700 Channel::NeededFrequency(int32_t id)
702 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
703 "Channel::NeededFrequency(id=%d)", id);
705 int highestNeeded = 0;
707 // Determine highest needed receive frequency
708 int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
710 // Return the bigger of playout and receive frequency in the ACM.
711 if (audio_coding_->PlayoutFrequency() > receiveFrequency)
713 highestNeeded = audio_coding_->PlayoutFrequency();
717 highestNeeded = receiveFrequency;
720 // Special case, if we're playing a file on the playout side
721 // we take that frequency into consideration as well
722 // This is not needed on sending side, since the codec will
723 // limit the spectrum anyway.
724 if (channel_state_.Get().output_file_playing)
726 CriticalSectionScoped cs(&_fileCritSect);
727 if (_outputFilePlayerPtr)
729 if(_outputFilePlayerPtr->Frequency()>highestNeeded)
731 highestNeeded=_outputFilePlayerPtr->Frequency();
736 return(highestNeeded);
740 Channel::CreateChannel(Channel*& channel,
743 const Config& config)
745 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId),
746 "Channel::CreateChannel(channelId=%d, instanceId=%d)",
747 channelId, instanceId);
749 channel = new Channel(channelId, instanceId, config);
752 WEBRTC_TRACE(kTraceMemory, kTraceVoice,
753 VoEId(instanceId,channelId),
754 "Channel::CreateChannel() unable to allocate memory for"
762 Channel::PlayNotification(int32_t id, uint32_t durationMs)
764 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
765 "Channel::PlayNotification(id=%d, durationMs=%d)",
772 Channel::RecordNotification(int32_t id, uint32_t durationMs)
774 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
775 "Channel::RecordNotification(id=%d, durationMs=%d)",
782 Channel::PlayFileEnded(int32_t id)
784 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
785 "Channel::PlayFileEnded(id=%d)", id);
787 if (id == _inputFilePlayerId)
789 channel_state_.SetInputFilePlaying(false);
790 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
791 VoEId(_instanceId,_channelId),
792 "Channel::PlayFileEnded() => input file player module is"
795 else if (id == _outputFilePlayerId)
797 channel_state_.SetOutputFilePlaying(false);
798 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
799 VoEId(_instanceId,_channelId),
800 "Channel::PlayFileEnded() => output file player module is"
806 Channel::RecordFileEnded(int32_t id)
808 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
809 "Channel::RecordFileEnded(id=%d)", id);
811 assert(id == _outputFileRecorderId);
813 CriticalSectionScoped cs(&_fileCritSect);
815 _outputFileRecording = false;
816 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
817 VoEId(_instanceId,_channelId),
818 "Channel::RecordFileEnded() => output file recorder module is"
822 Channel::Channel(int32_t channelId,
824 const Config& config) :
825 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
826 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
827 volume_settings_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
828 _instanceId(instanceId),
829 _channelId(channelId),
830 rtp_header_parser_(RtpHeaderParser::Create()),
831 rtp_payload_registry_(
832 new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))),
833 rtp_receive_statistics_(ReceiveStatistics::Create(
834 Clock::GetRealTimeClock())),
835 rtp_receiver_(RtpReceiver::CreateAudioReceiver(
836 VoEModuleId(instanceId, channelId), Clock::GetRealTimeClock(), this,
837 this, this, rtp_payload_registry_.get())),
838 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
839 audio_coding_(AudioCodingModule::Create(
840 VoEModuleId(instanceId, channelId))),
841 _rtpDumpIn(*RtpDump::CreateRtpDump()),
842 _rtpDumpOut(*RtpDump::CreateRtpDump()),
844 _externalTransport(false),
846 _inputFilePlayerPtr(NULL),
847 _outputFilePlayerPtr(NULL),
848 _outputFileRecorderPtr(NULL),
849 // Avoid conflict with other channels by adding 1024 - 1026,
850 // won't use as much as 1024 channels.
851 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
852 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
853 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
854 _outputFileRecording(false),
855 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
856 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
857 _outputExternalMedia(false),
858 _inputExternalMediaCallbackPtr(NULL),
859 _outputExternalMediaCallbackPtr(NULL),
860 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset
861 _sendTelephoneEventPayloadType(106),
862 jitter_buffer_playout_timestamp_(0),
863 playout_timestamp_rtp_(0),
864 playout_timestamp_rtcp_(0),
865 playout_delay_ms_(0),
866 _numberOfDiscardedPackets(0),
867 send_sequence_number_(0),
868 _engineStatisticsPtr(NULL),
869 _outputMixerPtr(NULL),
870 _transmitMixerPtr(NULL),
871 _moduleProcessThreadPtr(NULL),
872 _audioDeviceModulePtr(NULL),
873 _voiceEngineObserverPtr(NULL),
874 _callbackCritSectPtr(NULL),
876 _rxVadObserverPtr(NULL),
879 _rtpObserverPtr(NULL),
880 _rtcpObserverPtr(NULL),
881 _externalPlayout(false),
882 _externalMixing(false),
883 _mixFileWithMicrophone(false),
885 _rtcpObserver(false),
890 _playOutbandDtmfEvent(false),
891 _playInbandDtmfEvent(false),
892 _lastLocalTimeStamp(0),
893 _lastRemoteTimeStamp(0),
895 _includeAudioLevelIndication(false),
896 _rtpPacketTimedOut(false),
897 _rtpPacketTimeOutIsEnabled(false),
898 _rtpTimeOutSeconds(0),
899 _connectionObserver(false),
900 _connectionObserverPtr(NULL),
901 _outputSpeechType(AudioFrame::kNormalSpeech),
904 _average_jitter_buffer_delay_us(0),
905 least_required_delay_ms_(0),
906 _previousTimestamp(0),
907 _recPacketDelayMs(20),
908 _RxVadDetection(false),
909 _rxAgcIsEnabled(false),
910 _rxNsIsEnabled(false),
911 restored_packet_in_use_(false)
913 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
914 "Channel::Channel() - ctor");
915 _inbandDtmfQueue.ResetDtmf();
916 _inbandDtmfGenerator.Init();
917 _outputAudioLevel.Clear();
919 RtpRtcp::Configuration configuration;
920 configuration.id = VoEModuleId(instanceId, channelId);
921 configuration.audio = true;
922 configuration.outgoing_transport = this;
923 configuration.rtcp_feedback = this;
924 configuration.audio_messages = this;
925 configuration.receive_statistics = rtp_receive_statistics_.get();
927 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
929 statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC()));
930 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(
931 statistics_proxy_.get());
933 Config audioproc_config;
934 audioproc_config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
935 rx_audioproc_.reset(AudioProcessing::Create(audioproc_config));
940 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
941 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId),
942 "Channel::~Channel() - dtor");
944 if (_outputExternalMedia)
946 DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
948 if (channel_state_.Get().input_external_media)
950 DeRegisterExternalMediaProcessing(kRecordingPerChannel);
956 CriticalSectionScoped cs(&_fileCritSect);
957 if (_inputFilePlayerPtr)
959 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
960 _inputFilePlayerPtr->StopPlayingFile();
961 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
962 _inputFilePlayerPtr = NULL;
964 if (_outputFilePlayerPtr)
966 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
967 _outputFilePlayerPtr->StopPlayingFile();
968 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
969 _outputFilePlayerPtr = NULL;
971 if (_outputFileRecorderPtr)
973 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
974 _outputFileRecorderPtr->StopRecording();
975 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
976 _outputFileRecorderPtr = NULL;
980 // The order to safely shutdown modules in a channel is:
981 // 1. De-register callbacks in modules
982 // 2. De-register modules in process thread
983 // 3. Destroy modules
984 if (audio_coding_->RegisterTransportCallback(NULL) == -1)
986 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
987 VoEId(_instanceId,_channelId),
988 "~Channel() failed to de-register transport callback"
989 " (Audio coding module)");
991 if (audio_coding_->RegisterVADCallback(NULL) == -1)
993 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
994 VoEId(_instanceId,_channelId),
995 "~Channel() failed to de-register VAD callback"
996 " (Audio coding module)");
998 // De-register modules in process thread
999 if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
1001 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1002 VoEId(_instanceId,_channelId),
1003 "~Channel() failed to deregister RTP/RTCP module");
1005 // End of modules shutdown
1007 // Delete other objects
1009 vie_network_->Release();
1010 vie_network_ = NULL;
1012 RtpDump::DestroyRtpDump(&_rtpDumpIn);
1013 RtpDump::DestroyRtpDump(&_rtpDumpOut);
1014 delete &_callbackCritSect;
1015 delete &_fileCritSect;
1016 delete &volume_settings_critsect_;
1022 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1025 channel_state_.Reset();
1027 // --- Initial sanity
1029 if ((_engineStatisticsPtr == NULL) ||
1030 (_moduleProcessThreadPtr == NULL))
1032 WEBRTC_TRACE(kTraceError, kTraceVoice,
1033 VoEId(_instanceId,_channelId),
1034 "Channel::Init() must call SetEngineInformation() first");
1038 // --- Add modules to process thread (for periodic schedulation)
1040 const bool processThreadFail =
1041 ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
1043 if (processThreadFail)
1045 _engineStatisticsPtr->SetLastError(
1046 VE_CANNOT_INIT_CHANNEL, kTraceError,
1047 "Channel::Init() modules not registered");
1050 // --- ACM initialization
1052 if ((audio_coding_->InitializeReceiver() == -1) ||
1053 #ifdef WEBRTC_CODEC_AVT
1054 // out-of-band Dtmf tones are played out by default
1055 (audio_coding_->SetDtmfPlayoutStatus(true) == -1) ||
1057 (audio_coding_->InitializeSender() == -1))
1059 _engineStatisticsPtr->SetLastError(
1060 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1061 "Channel::Init() unable to initialize the ACM - 1");
1065 // --- RTP/RTCP module initialization
1067 // Ensure that RTCP is enabled by default for the created channel.
1068 // Note that, the module will keep generating RTCP until it is explicitly
1069 // disabled by the user.
1070 // After StopListen (when no sockets exists), RTCP packets will no longer
1071 // be transmitted since the Transport object will then be invalid.
1072 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
1073 // RTCP is enabled by default.
1074 if (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1)
1076 _engineStatisticsPtr->SetLastError(
1077 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1078 "Channel::Init() RTP/RTCP module not initialized");
1082 // --- Register all permanent callbacks
1084 (audio_coding_->RegisterTransportCallback(this) == -1) ||
1085 (audio_coding_->RegisterVADCallback(this) == -1);
1089 _engineStatisticsPtr->SetLastError(
1090 VE_CANNOT_INIT_CHANNEL, kTraceError,
1091 "Channel::Init() callbacks not registered");
1095 // --- Register all supported codecs to the receiving side of the
1099 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1101 for (int idx = 0; idx < nSupportedCodecs; idx++)
1103 // Open up the RTP/RTCP receiver for all supported codecs
1104 if ((audio_coding_->Codec(idx, &codec) == -1) ||
1105 (rtp_receiver_->RegisterReceivePayload(
1110 (codec.rate < 0) ? 0 : codec.rate) == -1))
1112 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1113 VoEId(_instanceId,_channelId),
1114 "Channel::Init() unable to register %s (%d/%d/%d/%d) "
1115 "to RTP/RTCP receiver",
1116 codec.plname, codec.pltype, codec.plfreq,
1117 codec.channels, codec.rate);
1121 WEBRTC_TRACE(kTraceInfo, kTraceVoice,
1122 VoEId(_instanceId,_channelId),
1123 "Channel::Init() %s (%d/%d/%d/%d) has been added to "
1124 "the RTP/RTCP receiver",
1125 codec.plname, codec.pltype, codec.plfreq,
1126 codec.channels, codec.rate);
1129 // Ensure that PCMU is used as default codec on the sending side
1130 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1))
1132 SetSendCodec(codec);
1135 // Register default PT for outband 'telephone-event'
1136 if (!STR_CASE_CMP(codec.plname, "telephone-event"))
1138 if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) ||
1139 (audio_coding_->RegisterReceiveCodec(codec) == -1))
1141 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1142 VoEId(_instanceId,_channelId),
1143 "Channel::Init() failed to register outband "
1144 "'telephone-event' (%d/%d) correctly",
1145 codec.pltype, codec.plfreq);
1149 if (!STR_CASE_CMP(codec.plname, "CN"))
1151 if ((audio_coding_->RegisterSendCodec(codec) == -1) ||
1152 (audio_coding_->RegisterReceiveCodec(codec) == -1) ||
1153 (_rtpRtcpModule->RegisterSendPayload(codec) == -1))
1155 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1156 VoEId(_instanceId,_channelId),
1157 "Channel::Init() failed to register CN (%d/%d) "
1159 codec.pltype, codec.plfreq);
1162 #ifdef WEBRTC_CODEC_RED
1163 // Register RED to the receiving side of the ACM.
1164 // We will not receive an OnInitializeDecoder() callback for RED.
1165 if (!STR_CASE_CMP(codec.plname, "RED"))
1167 if (audio_coding_->RegisterReceiveCodec(codec) == -1)
1169 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1170 VoEId(_instanceId,_channelId),
1171 "Channel::Init() failed to register RED (%d/%d) "
1173 codec.pltype, codec.plfreq);
1179 if (rx_audioproc_->noise_suppression()->set_level(kDefaultNsMode) != 0) {
1180 LOG_FERR1(LS_ERROR, noise_suppression()->set_level, kDefaultNsMode);
1183 if (rx_audioproc_->gain_control()->set_mode(kDefaultRxAgcMode) != 0) {
1184 LOG_FERR1(LS_ERROR, gain_control()->set_mode, kDefaultRxAgcMode);
1192 Channel::SetEngineInformation(Statistics& engineStatistics,
1193 OutputMixer& outputMixer,
1194 voe::TransmitMixer& transmitMixer,
1195 ProcessThread& moduleProcessThread,
1196 AudioDeviceModule& audioDeviceModule,
1197 VoiceEngineObserver* voiceEngineObserver,
1198 CriticalSectionWrapper* callbackCritSect)
1200 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1201 "Channel::SetEngineInformation()");
1202 _engineStatisticsPtr = &engineStatistics;
1203 _outputMixerPtr = &outputMixer;
1204 _transmitMixerPtr = &transmitMixer,
1205 _moduleProcessThreadPtr = &moduleProcessThread;
1206 _audioDeviceModulePtr = &audioDeviceModule;
1207 _voiceEngineObserverPtr = voiceEngineObserver;
1208 _callbackCritSectPtr = callbackCritSect;
1213 Channel::UpdateLocalTimeStamp()
1216 _timeStamp += _audioFrame.samples_per_channel_;
1221 Channel::StartPlayout()
1223 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1224 "Channel::StartPlayout()");
1225 if (channel_state_.Get().playing)
1230 if (!_externalMixing) {
1231 // Add participant as candidates for mixing.
1232 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0)
1234 _engineStatisticsPtr->SetLastError(
1235 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1236 "StartPlayout() failed to add participant to mixer");
1241 channel_state_.SetPlaying(true);
1242 if (RegisterFilePlayingToMixer() != 0)
1249 Channel::StopPlayout()
1251 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1252 "Channel::StopPlayout()");
1253 if (!channel_state_.Get().playing)
1258 if (!_externalMixing) {
1259 // Remove participant as candidates for mixing
1260 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0)
1262 _engineStatisticsPtr->SetLastError(
1263 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1264 "StopPlayout() failed to remove participant from mixer");
1269 channel_state_.SetPlaying(false);
1270 _outputAudioLevel.Clear();
1276 Channel::StartSend()
1278 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1279 "Channel::StartSend()");
1280 // Resume the previous sequence number which was reset by StopSend().
1281 // This needs to be done before |sending| is set to true.
1282 if (send_sequence_number_)
1283 SetInitSequenceNumber(send_sequence_number_);
1285 if (channel_state_.Get().sending)
1289 channel_state_.SetSending(true);
1291 if (_rtpRtcpModule->SetSendingStatus(true) != 0)
1293 _engineStatisticsPtr->SetLastError(
1294 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1295 "StartSend() RTP/RTCP failed to start sending");
1296 CriticalSectionScoped cs(&_callbackCritSect);
1297 channel_state_.SetSending(false);
1307 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1308 "Channel::StopSend()");
1309 if (!channel_state_.Get().sending)
1313 channel_state_.SetSending(false);
1315 // Store the sequence number to be able to pick up the same sequence for
1316 // the next StartSend(). This is needed for restarting device, otherwise
1317 // it might cause libSRTP to complain about packets being replayed.
1318 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1319 // CL is landed. See issue
1320 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1321 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1323 // Reset sending SSRC and sequence number and triggers direct transmission
1325 if (_rtpRtcpModule->SetSendingStatus(false) == -1 ||
1326 _rtpRtcpModule->ResetSendDataCountersRTP() == -1)
1328 _engineStatisticsPtr->SetLastError(
1329 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1330 "StartSend() RTP/RTCP failed to stop sending");
1337 Channel::StartReceiving()
1339 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1340 "Channel::StartReceiving()");
1341 if (channel_state_.Get().receiving)
1345 channel_state_.SetReceiving(true);
1346 _numberOfDiscardedPackets = 0;
1351 Channel::StopReceiving()
1353 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1354 "Channel::StopReceiving()");
1355 if (!channel_state_.Get().receiving)
1360 channel_state_.SetReceiving(false);
1365 Channel::SetNetEQPlayoutMode(NetEqModes mode)
1367 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1368 "Channel::SetNetEQPlayoutMode()");
1369 AudioPlayoutMode playoutMode(voice);
1373 playoutMode = voice;
1375 case kNetEqStreaming:
1376 playoutMode = streaming;
1385 if (audio_coding_->SetPlayoutMode(playoutMode) != 0)
1387 _engineStatisticsPtr->SetLastError(
1388 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1389 "SetNetEQPlayoutMode() failed to set playout mode");
1396 Channel::GetNetEQPlayoutMode(NetEqModes& mode)
1398 const AudioPlayoutMode playoutMode = audio_coding_->PlayoutMode();
1399 switch (playoutMode)
1402 mode = kNetEqDefault;
1405 mode = kNetEqStreaming;
1413 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
1414 VoEId(_instanceId,_channelId),
1415 "Channel::GetNetEQPlayoutMode() => mode=%u", mode);
1420 Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer)
1422 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1423 "Channel::RegisterVoiceEngineObserver()");
1424 CriticalSectionScoped cs(&_callbackCritSect);
1426 if (_voiceEngineObserverPtr)
1428 _engineStatisticsPtr->SetLastError(
1429 VE_INVALID_OPERATION, kTraceError,
1430 "RegisterVoiceEngineObserver() observer already enabled");
1433 _voiceEngineObserverPtr = &observer;
1438 Channel::DeRegisterVoiceEngineObserver()
1440 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1441 "Channel::DeRegisterVoiceEngineObserver()");
1442 CriticalSectionScoped cs(&_callbackCritSect);
1444 if (!_voiceEngineObserverPtr)
1446 _engineStatisticsPtr->SetLastError(
1447 VE_INVALID_OPERATION, kTraceWarning,
1448 "DeRegisterVoiceEngineObserver() observer already disabled");
1451 _voiceEngineObserverPtr = NULL;
1456 Channel::GetSendCodec(CodecInst& codec)
1458 return (audio_coding_->SendCodec(&codec));
1462 Channel::GetRecCodec(CodecInst& codec)
1464 return (audio_coding_->ReceiveCodec(&codec));
1468 Channel::SetSendCodec(const CodecInst& codec)
1470 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1471 "Channel::SetSendCodec()");
1473 if (audio_coding_->RegisterSendCodec(codec) != 0)
1475 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1476 "SetSendCodec() failed to register codec to ACM");
1480 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1482 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1483 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1486 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1487 "SetSendCodec() failed to register codec to"
1488 " RTP/RTCP module");
1493 if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0)
1495 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
1496 "SetSendCodec() failed to set audio packet size");
1504 Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX)
1506 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1507 "Channel::SetVADStatus(mode=%d)", mode);
1508 // To disable VAD, DTX must be disabled too
1509 disableDTX = ((enableVAD == false) ? true : disableDTX);
1510 if (audio_coding_->SetVAD(!disableDTX, enableVAD, mode) != 0)
1512 _engineStatisticsPtr->SetLastError(
1513 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1514 "SetVADStatus() failed to set VAD");
1521 Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX)
1523 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1524 "Channel::GetVADStatus");
1525 if (audio_coding_->VAD(&disabledDTX, &enabledVAD, &mode) != 0)
1527 _engineStatisticsPtr->SetLastError(
1528 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1529 "GetVADStatus() failed to get VAD status");
1532 disabledDTX = !disabledDTX;
1537 Channel::SetRecPayloadType(const CodecInst& codec)
1539 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1540 "Channel::SetRecPayloadType()");
1542 if (channel_state_.Get().playing)
1544 _engineStatisticsPtr->SetLastError(
1545 VE_ALREADY_PLAYING, kTraceError,
1546 "SetRecPayloadType() unable to set PT while playing");
1549 if (channel_state_.Get().receiving)
1551 _engineStatisticsPtr->SetLastError(
1552 VE_ALREADY_LISTENING, kTraceError,
1553 "SetRecPayloadType() unable to set PT while listening");
1557 if (codec.pltype == -1)
1559 // De-register the selected codec (RTP/RTCP module and ACM)
1562 CodecInst rxCodec = codec;
1564 // Get payload type for the given codec
1565 rtp_payload_registry_->ReceivePayloadType(
1569 (rxCodec.rate < 0) ? 0 : rxCodec.rate,
1571 rxCodec.pltype = pltype;
1573 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0)
1575 _engineStatisticsPtr->SetLastError(
1576 VE_RTP_RTCP_MODULE_ERROR,
1578 "SetRecPayloadType() RTP/RTCP-module deregistration "
1582 if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0)
1584 _engineStatisticsPtr->SetLastError(
1585 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1586 "SetRecPayloadType() ACM deregistration failed - 1");
1592 if (rtp_receiver_->RegisterReceivePayload(
1597 (codec.rate < 0) ? 0 : codec.rate) != 0)
1599 // First attempt to register failed => de-register and try again
1600 rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
1601 if (rtp_receiver_->RegisterReceivePayload(
1606 (codec.rate < 0) ? 0 : codec.rate) != 0)
1608 _engineStatisticsPtr->SetLastError(
1609 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1610 "SetRecPayloadType() RTP/RTCP-module registration failed");
1614 if (audio_coding_->RegisterReceiveCodec(codec) != 0)
1616 audio_coding_->UnregisterReceiveCodec(codec.pltype);
1617 if (audio_coding_->RegisterReceiveCodec(codec) != 0)
1619 _engineStatisticsPtr->SetLastError(
1620 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1621 "SetRecPayloadType() ACM registration failed - 1");
1629 Channel::GetRecPayloadType(CodecInst& codec)
1631 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1632 "Channel::GetRecPayloadType()");
1633 int8_t payloadType(-1);
1634 if (rtp_payload_registry_->ReceivePayloadType(
1638 (codec.rate < 0) ? 0 : codec.rate,
1641 _engineStatisticsPtr->SetLastError(
1642 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1643 "GetRecPayloadType() failed to retrieve RX payload type");
1646 codec.pltype = payloadType;
1647 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1648 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype);
1653 Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency)
1655 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1656 "Channel::SetSendCNPayloadType()");
1659 int32_t samplingFreqHz(-1);
1660 const int kMono = 1;
1661 if (frequency == kFreq32000Hz)
1662 samplingFreqHz = 32000;
1663 else if (frequency == kFreq16000Hz)
1664 samplingFreqHz = 16000;
1666 if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1)
1668 _engineStatisticsPtr->SetLastError(
1669 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1670 "SetSendCNPayloadType() failed to retrieve default CN codec "
1675 // Modify the payload type (must be set to dynamic range)
1676 codec.pltype = type;
1678 if (audio_coding_->RegisterSendCodec(codec) != 0)
1680 _engineStatisticsPtr->SetLastError(
1681 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1682 "SetSendCNPayloadType() failed to register CN to ACM");
1686 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1688 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1689 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
1691 _engineStatisticsPtr->SetLastError(
1692 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1693 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1701 int32_t Channel::RegisterExternalTransport(Transport& transport)
1703 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1704 "Channel::RegisterExternalTransport()");
1706 CriticalSectionScoped cs(&_callbackCritSect);
1708 if (_externalTransport)
1710 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION,
1712 "RegisterExternalTransport() external transport already enabled");
1715 _externalTransport = true;
1716 _transportPtr = &transport;
1721 Channel::DeRegisterExternalTransport()
1723 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1724 "Channel::DeRegisterExternalTransport()");
1726 CriticalSectionScoped cs(&_callbackCritSect);
1730 _engineStatisticsPtr->SetLastError(
1731 VE_INVALID_OPERATION, kTraceWarning,
1732 "DeRegisterExternalTransport() external transport already "
1736 _externalTransport = false;
1737 _transportPtr = NULL;
1738 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1739 "DeRegisterExternalTransport() all transport is disabled");
1743 int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length,
1744 const PacketTime& packet_time) {
1745 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1746 "Channel::ReceivedRTPPacket()");
1748 // Store playout timestamp for the received RTP packet
1749 UpdatePlayoutTimestamp(false);
1751 // Dump the RTP packet to a file (if RTP dump is enabled).
1752 if (_rtpDumpIn.DumpPacket((const uint8_t*)data,
1753 (uint16_t)length) == -1) {
1754 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1755 VoEId(_instanceId,_channelId),
1756 "Channel::SendPacket() RTP dump to input file failed");
1758 const uint8_t* received_packet = reinterpret_cast<const uint8_t*>(data);
1760 if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
1761 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1762 "Incoming packet: invalid RTP header");
1765 header.payload_type_frequency =
1766 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
1767 if (header.payload_type_frequency < 0)
1769 bool in_order = IsPacketInOrder(header);
1770 rtp_receive_statistics_->IncomingPacket(header, length,
1771 IsPacketRetransmitted(header, in_order));
1772 rtp_payload_registry_->SetIncomingPayloadType(header);
1774 // Forward any packets to ViE bandwidth estimator, if enabled.
1776 CriticalSectionScoped cs(&_callbackCritSect);
1778 int64_t arrival_time_ms;
1779 if (packet_time.timestamp != -1) {
1780 arrival_time_ms = (packet_time.timestamp + 500) / 1000;
1782 arrival_time_ms = TickTime::MillisecondTimestamp();
1784 int payload_length = length - header.headerLength;
1785 vie_network_->ReceivedBWEPacket(video_channel_, arrival_time_ms,
1786 payload_length, header);
1790 return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1;
1793 bool Channel::ReceivePacket(const uint8_t* packet,
1795 const RTPHeader& header,
1797 if (rtp_payload_registry_->IsEncapsulated(header)) {
1798 return HandleEncapsulation(packet, packet_length, header);
1800 const uint8_t* payload = packet + header.headerLength;
1801 int payload_length = packet_length - header.headerLength;
1802 assert(payload_length >= 0);
1803 PayloadUnion payload_specific;
1804 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
1805 &payload_specific)) {
1808 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
1809 payload_specific, in_order);
1812 bool Channel::HandleEncapsulation(const uint8_t* packet,
1814 const RTPHeader& header) {
1815 if (!rtp_payload_registry_->IsRtx(header))
1818 // Remove the RTX header and parse the original RTP header.
1819 if (packet_length < header.headerLength)
1821 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
1823 if (restored_packet_in_use_) {
1824 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1825 "Multiple RTX headers detected, dropping packet");
1828 uint8_t* restored_packet_ptr = restored_packet_;
1829 if (!rtp_payload_registry_->RestoreOriginalPacket(
1830 &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(),
1832 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1833 "Incoming RTX packet: invalid RTP header");
1836 restored_packet_in_use_ = true;
1837 bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length);
1838 restored_packet_in_use_ = false;
1842 bool Channel::IsPacketInOrder(const RTPHeader& header) const {
1843 StreamStatistician* statistician =
1844 rtp_receive_statistics_->GetStatistician(header.ssrc);
1847 return statistician->IsPacketInOrder(header.sequenceNumber);
1850 bool Channel::IsPacketRetransmitted(const RTPHeader& header,
1851 bool in_order) const {
1852 // Retransmissions are handled separately if RTX is enabled.
1853 if (rtp_payload_registry_->RtxEnabled())
1855 StreamStatistician* statistician =
1856 rtp_receive_statistics_->GetStatistician(header.ssrc);
1859 // Check if this is a retransmission.
1860 uint16_t min_rtt = 0;
1861 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
1863 statistician->IsRetransmitOfOldPacket(header, min_rtt);
1866 int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) {
1867 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
1868 "Channel::ReceivedRTCPPacket()");
1869 // Store playout timestamp for the received RTCP packet
1870 UpdatePlayoutTimestamp(true);
1872 // Dump the RTCP packet to a file (if RTP dump is enabled).
1873 if (_rtpDumpIn.DumpPacket((const uint8_t*)data,
1874 (uint16_t)length) == -1) {
1875 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
1876 VoEId(_instanceId,_channelId),
1877 "Channel::SendPacket() RTCP dump to input file failed");
1880 // Deliver RTCP packet to RTP/RTCP module for parsing
1881 if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data,
1882 (uint16_t)length) == -1) {
1883 _engineStatisticsPtr->SetLastError(
1884 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
1885 "Channel::IncomingRTPPacket() RTCP packet is invalid");
1890 int Channel::StartPlayingFileLocally(const char* fileName,
1894 float volumeScaling,
1896 const CodecInst* codecInst)
1898 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1899 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1900 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1901 "stopPosition=%d)", fileName, loop, format, volumeScaling,
1902 startPosition, stopPosition);
1904 if (channel_state_.Get().output_file_playing)
1906 _engineStatisticsPtr->SetLastError(
1907 VE_ALREADY_PLAYING, kTraceError,
1908 "StartPlayingFileLocally() is already playing");
1913 CriticalSectionScoped cs(&_fileCritSect);
1915 if (_outputFilePlayerPtr)
1917 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1918 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1919 _outputFilePlayerPtr = NULL;
1922 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
1923 _outputFilePlayerId, (const FileFormats)format);
1925 if (_outputFilePlayerPtr == NULL)
1927 _engineStatisticsPtr->SetLastError(
1928 VE_INVALID_ARGUMENT, kTraceError,
1929 "StartPlayingFileLocally() filePlayer format is not correct");
1933 const uint32_t notificationTime(0);
1935 if (_outputFilePlayerPtr->StartPlayingFile(
1942 (const CodecInst*)codecInst) != 0)
1944 _engineStatisticsPtr->SetLastError(
1945 VE_BAD_FILE, kTraceError,
1946 "StartPlayingFile() failed to start file playout");
1947 _outputFilePlayerPtr->StopPlayingFile();
1948 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1949 _outputFilePlayerPtr = NULL;
1952 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
1953 channel_state_.SetOutputFilePlaying(true);
1956 if (RegisterFilePlayingToMixer() != 0)
1962 int Channel::StartPlayingFileLocally(InStream* stream,
1965 float volumeScaling,
1967 const CodecInst* codecInst)
1969 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
1970 "Channel::StartPlayingFileLocally(format=%d,"
1971 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1972 format, volumeScaling, startPosition, stopPosition);
1976 _engineStatisticsPtr->SetLastError(
1977 VE_BAD_FILE, kTraceError,
1978 "StartPlayingFileLocally() NULL as input stream");
1983 if (channel_state_.Get().output_file_playing)
1985 _engineStatisticsPtr->SetLastError(
1986 VE_ALREADY_PLAYING, kTraceError,
1987 "StartPlayingFileLocally() is already playing");
1992 CriticalSectionScoped cs(&_fileCritSect);
1994 // Destroy the old instance
1995 if (_outputFilePlayerPtr)
1997 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
1998 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
1999 _outputFilePlayerPtr = NULL;
2002 // Create the instance
2003 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2004 _outputFilePlayerId,
2005 (const FileFormats)format);
2007 if (_outputFilePlayerPtr == NULL)
2009 _engineStatisticsPtr->SetLastError(
2010 VE_INVALID_ARGUMENT, kTraceError,
2011 "StartPlayingFileLocally() filePlayer format isnot correct");
2015 const uint32_t notificationTime(0);
2017 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
2020 stopPosition, codecInst) != 0)
2022 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2023 "StartPlayingFile() failed to "
2024 "start file playout");
2025 _outputFilePlayerPtr->StopPlayingFile();
2026 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2027 _outputFilePlayerPtr = NULL;
2030 _outputFilePlayerPtr->RegisterModuleFileCallback(this);
2031 channel_state_.SetOutputFilePlaying(true);
2034 if (RegisterFilePlayingToMixer() != 0)
2040 int Channel::StopPlayingFileLocally()
2042 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2043 "Channel::StopPlayingFileLocally()");
2045 if (!channel_state_.Get().output_file_playing)
2047 _engineStatisticsPtr->SetLastError(
2048 VE_INVALID_OPERATION, kTraceWarning,
2049 "StopPlayingFileLocally() isnot playing");
2054 CriticalSectionScoped cs(&_fileCritSect);
2056 if (_outputFilePlayerPtr->StopPlayingFile() != 0)
2058 _engineStatisticsPtr->SetLastError(
2059 VE_STOP_RECORDING_FAILED, kTraceError,
2060 "StopPlayingFile() could not stop playing");
2063 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2064 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2065 _outputFilePlayerPtr = NULL;
2066 channel_state_.SetOutputFilePlaying(false);
2068 // _fileCritSect cannot be taken while calling
2069 // SetAnonymousMixibilityStatus. Refer to comments in
2070 // StartPlayingFileLocally(const char* ...) for more details.
2071 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
2073 _engineStatisticsPtr->SetLastError(
2074 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
2075 "StopPlayingFile() failed to stop participant from playing as"
2076 "file in the mixer");
2083 int Channel::IsPlayingFileLocally() const
2085 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2086 "Channel::IsPlayingFileLocally()");
2088 return channel_state_.Get().output_file_playing;
2091 int Channel::RegisterFilePlayingToMixer()
2093 // Return success for not registering for file playing to mixer if:
2094 // 1. playing file before playout is started on that channel.
2095 // 2. starting playout without file playing on that channel.
2096 if (!channel_state_.Get().playing ||
2097 !channel_state_.Get().output_file_playing)
2102 // |_fileCritSect| cannot be taken while calling
2103 // SetAnonymousMixabilityStatus() since as soon as the participant is added
2104 // frames can be pulled by the mixer. Since the frames are generated from
2105 // the file, _fileCritSect will be taken. This would result in a deadlock.
2106 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
2108 channel_state_.SetOutputFilePlaying(false);
2109 CriticalSectionScoped cs(&_fileCritSect);
2110 _engineStatisticsPtr->SetLastError(
2111 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
2112 "StartPlayingFile() failed to add participant as file to mixer");
2113 _outputFilePlayerPtr->StopPlayingFile();
2114 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
2115 _outputFilePlayerPtr = NULL;
2122 int Channel::ScaleLocalFilePlayout(float scale)
2124 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2125 "Channel::ScaleLocalFilePlayout(scale=%5.3f)", scale);
2127 CriticalSectionScoped cs(&_fileCritSect);
2129 if (!channel_state_.Get().output_file_playing)
2131 _engineStatisticsPtr->SetLastError(
2132 VE_INVALID_OPERATION, kTraceError,
2133 "ScaleLocalFilePlayout() isnot playing");
2136 if ((_outputFilePlayerPtr == NULL) ||
2137 (_outputFilePlayerPtr->SetAudioScaling(scale) != 0))
2139 _engineStatisticsPtr->SetLastError(
2140 VE_BAD_ARGUMENT, kTraceError,
2141 "SetAudioScaling() failed to scale the playout");
2148 int Channel::GetLocalPlayoutPosition(int& positionMs)
2150 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2151 "Channel::GetLocalPlayoutPosition(position=?)");
2155 CriticalSectionScoped cs(&_fileCritSect);
2157 if (_outputFilePlayerPtr == NULL)
2159 _engineStatisticsPtr->SetLastError(
2160 VE_INVALID_OPERATION, kTraceError,
2161 "GetLocalPlayoutPosition() filePlayer instance doesnot exist");
2165 if (_outputFilePlayerPtr->GetPlayoutPosition(position) != 0)
2167 _engineStatisticsPtr->SetLastError(
2168 VE_BAD_FILE, kTraceError,
2169 "GetLocalPlayoutPosition() failed");
2172 positionMs = position;
2177 int Channel::StartPlayingFileAsMicrophone(const char* fileName,
2181 float volumeScaling,
2183 const CodecInst* codecInst)
2185 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2186 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
2187 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
2188 "stopPosition=%d)", fileName, loop, format, volumeScaling,
2189 startPosition, stopPosition);
2191 CriticalSectionScoped cs(&_fileCritSect);
2193 if (channel_state_.Get().input_file_playing)
2195 _engineStatisticsPtr->SetLastError(
2196 VE_ALREADY_PLAYING, kTraceWarning,
2197 "StartPlayingFileAsMicrophone() filePlayer is playing");
2201 // Destroy the old instance
2202 if (_inputFilePlayerPtr)
2204 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2205 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2206 _inputFilePlayerPtr = NULL;
2209 // Create the instance
2210 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2211 _inputFilePlayerId, (const FileFormats)format);
2213 if (_inputFilePlayerPtr == NULL)
2215 _engineStatisticsPtr->SetLastError(
2216 VE_INVALID_ARGUMENT, kTraceError,
2217 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
2221 const uint32_t notificationTime(0);
2223 if (_inputFilePlayerPtr->StartPlayingFile(
2230 (const CodecInst*)codecInst) != 0)
2232 _engineStatisticsPtr->SetLastError(
2233 VE_BAD_FILE, kTraceError,
2234 "StartPlayingFile() failed to start file playout");
2235 _inputFilePlayerPtr->StopPlayingFile();
2236 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2237 _inputFilePlayerPtr = NULL;
2240 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2241 channel_state_.SetInputFilePlaying(true);
2246 int Channel::StartPlayingFileAsMicrophone(InStream* stream,
2249 float volumeScaling,
2251 const CodecInst* codecInst)
2253 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2254 "Channel::StartPlayingFileAsMicrophone(format=%d, "
2255 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
2256 format, volumeScaling, startPosition, stopPosition);
2260 _engineStatisticsPtr->SetLastError(
2261 VE_BAD_FILE, kTraceError,
2262 "StartPlayingFileAsMicrophone NULL as input stream");
2266 CriticalSectionScoped cs(&_fileCritSect);
2268 if (channel_state_.Get().input_file_playing)
2270 _engineStatisticsPtr->SetLastError(
2271 VE_ALREADY_PLAYING, kTraceWarning,
2272 "StartPlayingFileAsMicrophone() is playing");
2276 // Destroy the old instance
2277 if (_inputFilePlayerPtr)
2279 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2280 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2281 _inputFilePlayerPtr = NULL;
2284 // Create the instance
2285 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer(
2286 _inputFilePlayerId, (const FileFormats)format);
2288 if (_inputFilePlayerPtr == NULL)
2290 _engineStatisticsPtr->SetLastError(
2291 VE_INVALID_ARGUMENT, kTraceError,
2292 "StartPlayingInputFile() filePlayer format isnot correct");
2296 const uint32_t notificationTime(0);
2298 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition,
2299 volumeScaling, notificationTime,
2300 stopPosition, codecInst) != 0)
2302 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2303 "StartPlayingFile() failed to start "
2305 _inputFilePlayerPtr->StopPlayingFile();
2306 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2307 _inputFilePlayerPtr = NULL;
2311 _inputFilePlayerPtr->RegisterModuleFileCallback(this);
2312 channel_state_.SetInputFilePlaying(true);
2317 int Channel::StopPlayingFileAsMicrophone()
2319 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2320 "Channel::StopPlayingFileAsMicrophone()");
2322 CriticalSectionScoped cs(&_fileCritSect);
2324 if (!channel_state_.Get().input_file_playing)
2326 _engineStatisticsPtr->SetLastError(
2327 VE_INVALID_OPERATION, kTraceWarning,
2328 "StopPlayingFileAsMicrophone() isnot playing");
2332 if (_inputFilePlayerPtr->StopPlayingFile() != 0)
2334 _engineStatisticsPtr->SetLastError(
2335 VE_STOP_RECORDING_FAILED, kTraceError,
2336 "StopPlayingFile() could not stop playing");
2339 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
2340 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
2341 _inputFilePlayerPtr = NULL;
2342 channel_state_.SetInputFilePlaying(false);
2347 int Channel::IsPlayingFileAsMicrophone() const
2349 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2350 "Channel::IsPlayingFileAsMicrophone()");
2351 return channel_state_.Get().input_file_playing;
2354 int Channel::ScaleFileAsMicrophonePlayout(float scale)
2356 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2357 "Channel::ScaleFileAsMicrophonePlayout(scale=%5.3f)", scale);
2359 CriticalSectionScoped cs(&_fileCritSect);
2361 if (!channel_state_.Get().input_file_playing)
2363 _engineStatisticsPtr->SetLastError(
2364 VE_INVALID_OPERATION, kTraceError,
2365 "ScaleFileAsMicrophonePlayout() isnot playing");
2369 if ((_inputFilePlayerPtr == NULL) ||
2370 (_inputFilePlayerPtr->SetAudioScaling(scale) != 0))
2372 _engineStatisticsPtr->SetLastError(
2373 VE_BAD_ARGUMENT, kTraceError,
2374 "SetAudioScaling() failed to scale playout");
2381 int Channel::StartRecordingPlayout(const char* fileName,
2382 const CodecInst* codecInst)
2384 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2385 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
2387 if (_outputFileRecording)
2389 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2390 "StartRecordingPlayout() is already recording");
2395 const uint32_t notificationTime(0); // Not supported in VoE
2396 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2398 if ((codecInst != NULL) &&
2399 ((codecInst->channels < 1) || (codecInst->channels > 2)))
2401 _engineStatisticsPtr->SetLastError(
2402 VE_BAD_ARGUMENT, kTraceError,
2403 "StartRecordingPlayout() invalid compression");
2406 if(codecInst == NULL)
2408 format = kFileFormatPcm16kHzFile;
2409 codecInst=&dummyCodec;
2411 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2412 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2413 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2415 format = kFileFormatWavFile;
2419 format = kFileFormatCompressedFile;
2422 CriticalSectionScoped cs(&_fileCritSect);
2424 // Destroy the old instance
2425 if (_outputFileRecorderPtr)
2427 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2428 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2429 _outputFileRecorderPtr = NULL;
2432 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2433 _outputFileRecorderId, (const FileFormats)format);
2434 if (_outputFileRecorderPtr == NULL)
2436 _engineStatisticsPtr->SetLastError(
2437 VE_INVALID_ARGUMENT, kTraceError,
2438 "StartRecordingPlayout() fileRecorder format isnot correct");
2442 if (_outputFileRecorderPtr->StartRecordingAudioFile(
2443 fileName, (const CodecInst&)*codecInst, notificationTime) != 0)
2445 _engineStatisticsPtr->SetLastError(
2446 VE_BAD_FILE, kTraceError,
2447 "StartRecordingAudioFile() failed to start file recording");
2448 _outputFileRecorderPtr->StopRecording();
2449 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2450 _outputFileRecorderPtr = NULL;
2453 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2454 _outputFileRecording = true;
2459 int Channel::StartRecordingPlayout(OutStream* stream,
2460 const CodecInst* codecInst)
2462 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2463 "Channel::StartRecordingPlayout()");
2465 if (_outputFileRecording)
2467 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1),
2468 "StartRecordingPlayout() is already recording");
2473 const uint32_t notificationTime(0); // Not supported in VoE
2474 CodecInst dummyCodec={100,"L16",16000,320,1,320000};
2476 if (codecInst != NULL && codecInst->channels != 1)
2478 _engineStatisticsPtr->SetLastError(
2479 VE_BAD_ARGUMENT, kTraceError,
2480 "StartRecordingPlayout() invalid compression");
2483 if(codecInst == NULL)
2485 format = kFileFormatPcm16kHzFile;
2486 codecInst=&dummyCodec;
2488 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) ||
2489 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) ||
2490 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0))
2492 format = kFileFormatWavFile;
2496 format = kFileFormatCompressedFile;
2499 CriticalSectionScoped cs(&_fileCritSect);
2501 // Destroy the old instance
2502 if (_outputFileRecorderPtr)
2504 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2505 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2506 _outputFileRecorderPtr = NULL;
2509 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder(
2510 _outputFileRecorderId, (const FileFormats)format);
2511 if (_outputFileRecorderPtr == NULL)
2513 _engineStatisticsPtr->SetLastError(
2514 VE_INVALID_ARGUMENT, kTraceError,
2515 "StartRecordingPlayout() fileRecorder format isnot correct");
2519 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst,
2520 notificationTime) != 0)
2522 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2523 "StartRecordingPlayout() failed to "
2524 "start file recording");
2525 _outputFileRecorderPtr->StopRecording();
2526 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2527 _outputFileRecorderPtr = NULL;
2531 _outputFileRecorderPtr->RegisterModuleFileCallback(this);
2532 _outputFileRecording = true;
2537 int Channel::StopRecordingPlayout()
2539 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1),
2540 "Channel::StopRecordingPlayout()");
2542 if (!_outputFileRecording)
2544 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1),
2545 "StopRecordingPlayout() isnot recording");
2550 CriticalSectionScoped cs(&_fileCritSect);
2552 if (_outputFileRecorderPtr->StopRecording() != 0)
2554 _engineStatisticsPtr->SetLastError(
2555 VE_STOP_RECORDING_FAILED, kTraceError,
2556 "StopRecording() could not stop recording");
2559 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL);
2560 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr);
2561 _outputFileRecorderPtr = NULL;
2562 _outputFileRecording = false;
2568 Channel::SetMixWithMicStatus(bool mix)
2570 CriticalSectionScoped cs(&_fileCritSect);
2571 _mixFileWithMicrophone=mix;
2575 Channel::GetSpeechOutputLevel(uint32_t& level) const
2577 int8_t currentLevel = _outputAudioLevel.Level();
2578 level = static_cast<int32_t> (currentLevel);
2579 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2580 VoEId(_instanceId,_channelId),
2581 "GetSpeechOutputLevel() => level=%u", level);
2586 Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const
2588 int16_t currentLevel = _outputAudioLevel.LevelFullRange();
2589 level = static_cast<int32_t> (currentLevel);
2590 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2591 VoEId(_instanceId,_channelId),
2592 "GetSpeechOutputLevelFullRange() => level=%u", level);
2597 Channel::SetMute(bool enable)
2599 CriticalSectionScoped cs(&volume_settings_critsect_);
2600 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2601 "Channel::SetMute(enable=%d)", enable);
2607 Channel::Mute() const
2609 CriticalSectionScoped cs(&volume_settings_critsect_);
2614 Channel::SetOutputVolumePan(float left, float right)
2616 CriticalSectionScoped cs(&volume_settings_critsect_);
2617 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2618 "Channel::SetOutputVolumePan()");
2625 Channel::GetOutputVolumePan(float& left, float& right) const
2627 CriticalSectionScoped cs(&volume_settings_critsect_);
2630 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2631 VoEId(_instanceId,_channelId),
2632 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right);
2637 Channel::SetChannelOutputVolumeScaling(float scaling)
2639 CriticalSectionScoped cs(&volume_settings_critsect_);
2640 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2641 "Channel::SetChannelOutputVolumeScaling()");
2642 _outputGain = scaling;
2647 Channel::GetChannelOutputVolumeScaling(float& scaling) const
2649 CriticalSectionScoped cs(&volume_settings_critsect_);
2650 scaling = _outputGain;
2651 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2652 VoEId(_instanceId,_channelId),
2653 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling);
2657 int Channel::SendTelephoneEventOutband(unsigned char eventCode,
2658 int lengthMs, int attenuationDb,
2661 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2662 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)",
2665 _playOutbandDtmfEvent = playDtmfEvent;
2667 if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs,
2668 attenuationDb) != 0)
2670 _engineStatisticsPtr->SetLastError(
2671 VE_SEND_DTMF_FAILED,
2673 "SendTelephoneEventOutband() failed to send event");
2679 int Channel::SendTelephoneEventInband(unsigned char eventCode,
2684 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2685 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)",
2688 _playInbandDtmfEvent = playDtmfEvent;
2689 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb);
2695 Channel::SetDtmfPlayoutStatus(bool enable)
2697 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2698 "Channel::SetDtmfPlayoutStatus()");
2699 if (audio_coding_->SetDtmfPlayoutStatus(enable) != 0)
2701 _engineStatisticsPtr->SetLastError(
2702 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
2703 "SetDtmfPlayoutStatus() failed to set Dtmf playout");
2710 Channel::DtmfPlayoutStatus() const
2712 return audio_coding_->DtmfPlayoutStatus();
2716 Channel::SetSendTelephoneEventPayloadType(unsigned char type)
2718 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2719 "Channel::SetSendTelephoneEventPayloadType()");
2722 _engineStatisticsPtr->SetLastError(
2723 VE_INVALID_ARGUMENT, kTraceError,
2724 "SetSendTelephoneEventPayloadType() invalid type");
2727 CodecInst codec = {};
2728 codec.plfreq = 8000;
2729 codec.pltype = type;
2730 memcpy(codec.plname, "telephone-event", 16);
2731 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0)
2733 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2734 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2735 _engineStatisticsPtr->SetLastError(
2736 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2737 "SetSendTelephoneEventPayloadType() failed to register send"
2742 _sendTelephoneEventPayloadType = type;
2747 Channel::GetSendTelephoneEventPayloadType(unsigned char& type)
2749 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2750 "Channel::GetSendTelephoneEventPayloadType()");
2751 type = _sendTelephoneEventPayloadType;
2752 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2753 VoEId(_instanceId,_channelId),
2754 "GetSendTelephoneEventPayloadType() => type=%u", type);
2759 Channel::UpdateRxVadDetection(AudioFrame& audioFrame)
2761 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2762 "Channel::UpdateRxVadDetection()");
2764 int vadDecision = 1;
2766 vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0;
2768 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr)
2770 OnRxVadDetected(vadDecision);
2771 _oldVadDecision = vadDecision;
2774 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
2775 "Channel::UpdateRxVadDetection() => vadDecision=%d",
2781 Channel::RegisterRxVadObserver(VoERxVadCallback &observer)
2783 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2784 "Channel::RegisterRxVadObserver()");
2785 CriticalSectionScoped cs(&_callbackCritSect);
2787 if (_rxVadObserverPtr)
2789 _engineStatisticsPtr->SetLastError(
2790 VE_INVALID_OPERATION, kTraceError,
2791 "RegisterRxVadObserver() observer already enabled");
2794 _rxVadObserverPtr = &observer;
2795 _RxVadDetection = true;
2800 Channel::DeRegisterRxVadObserver()
2802 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2803 "Channel::DeRegisterRxVadObserver()");
2804 CriticalSectionScoped cs(&_callbackCritSect);
2806 if (!_rxVadObserverPtr)
2808 _engineStatisticsPtr->SetLastError(
2809 VE_INVALID_OPERATION, kTraceWarning,
2810 "DeRegisterRxVadObserver() observer already disabled");
2813 _rxVadObserverPtr = NULL;
2814 _RxVadDetection = false;
2819 Channel::VoiceActivityIndicator(int &activity)
2821 activity = _sendFrameType;
2823 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2824 "Channel::VoiceActivityIndicator(indicator=%d)", activity);
2828 #ifdef WEBRTC_VOICE_ENGINE_AGC
2831 Channel::SetRxAgcStatus(bool enable, AgcModes mode)
2833 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2834 "Channel::SetRxAgcStatus(enable=%d, mode=%d)",
2835 (int)enable, (int)mode);
2837 GainControl::Mode agcMode = kDefaultRxAgcMode;
2843 agcMode = rx_audioproc_->gain_control()->mode();
2845 case kAgcFixedDigital:
2846 agcMode = GainControl::kFixedDigital;
2848 case kAgcAdaptiveDigital:
2849 agcMode =GainControl::kAdaptiveDigital;
2852 _engineStatisticsPtr->SetLastError(
2853 VE_INVALID_ARGUMENT, kTraceError,
2854 "SetRxAgcStatus() invalid Agc mode");
2858 if (rx_audioproc_->gain_control()->set_mode(agcMode) != 0)
2860 _engineStatisticsPtr->SetLastError(
2861 VE_APM_ERROR, kTraceError,
2862 "SetRxAgcStatus() failed to set Agc mode");
2865 if (rx_audioproc_->gain_control()->Enable(enable) != 0)
2867 _engineStatisticsPtr->SetLastError(
2868 VE_APM_ERROR, kTraceError,
2869 "SetRxAgcStatus() failed to set Agc state");
2873 _rxAgcIsEnabled = enable;
2874 channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
2880 Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode)
2882 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2883 "Channel::GetRxAgcStatus(enable=?, mode=?)");
2885 bool enable = rx_audioproc_->gain_control()->is_enabled();
2886 GainControl::Mode agcMode =
2887 rx_audioproc_->gain_control()->mode();
2893 case GainControl::kFixedDigital:
2894 mode = kAgcFixedDigital;
2896 case GainControl::kAdaptiveDigital:
2897 mode = kAgcAdaptiveDigital;
2900 _engineStatisticsPtr->SetLastError(
2901 VE_APM_ERROR, kTraceError,
2902 "GetRxAgcStatus() invalid Agc mode");
2910 Channel::SetRxAgcConfig(AgcConfig config)
2912 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2913 "Channel::SetRxAgcConfig()");
2915 if (rx_audioproc_->gain_control()->set_target_level_dbfs(
2916 config.targetLeveldBOv) != 0)
2918 _engineStatisticsPtr->SetLastError(
2919 VE_APM_ERROR, kTraceError,
2920 "SetRxAgcConfig() failed to set target peak |level|"
2921 "(or envelope) of the Agc");
2924 if (rx_audioproc_->gain_control()->set_compression_gain_db(
2925 config.digitalCompressionGaindB) != 0)
2927 _engineStatisticsPtr->SetLastError(
2928 VE_APM_ERROR, kTraceError,
2929 "SetRxAgcConfig() failed to set the range in |gain| the"
2930 " digital compression stage may apply");
2933 if (rx_audioproc_->gain_control()->enable_limiter(
2934 config.limiterEnable) != 0)
2936 _engineStatisticsPtr->SetLastError(
2937 VE_APM_ERROR, kTraceError,
2938 "SetRxAgcConfig() failed to set hard limiter to the signal");
2946 Channel::GetRxAgcConfig(AgcConfig& config)
2948 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2949 "Channel::GetRxAgcConfig(config=%?)");
2951 config.targetLeveldBOv =
2952 rx_audioproc_->gain_control()->target_level_dbfs();
2953 config.digitalCompressionGaindB =
2954 rx_audioproc_->gain_control()->compression_gain_db();
2955 config.limiterEnable =
2956 rx_audioproc_->gain_control()->is_limiter_enabled();
2958 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
2959 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => "
2960 "targetLeveldBOv=%u, digitalCompressionGaindB=%u,"
2961 " limiterEnable=%d",
2962 config.targetLeveldBOv,
2963 config.digitalCompressionGaindB,
2964 config.limiterEnable);
2969 #endif // #ifdef WEBRTC_VOICE_ENGINE_AGC
2971 #ifdef WEBRTC_VOICE_ENGINE_NR
2974 Channel::SetRxNsStatus(bool enable, NsModes mode)
2976 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
2977 "Channel::SetRxNsStatus(enable=%d, mode=%d)",
2978 (int)enable, (int)mode);
2980 NoiseSuppression::Level nsLevel = kDefaultNsMode;
2987 nsLevel = rx_audioproc_->noise_suppression()->level();
2990 nsLevel = NoiseSuppression::kHigh;
2992 case kNsLowSuppression:
2993 nsLevel = NoiseSuppression::kLow;
2995 case kNsModerateSuppression:
2996 nsLevel = NoiseSuppression::kModerate;
2998 case kNsHighSuppression:
2999 nsLevel = NoiseSuppression::kHigh;
3001 case kNsVeryHighSuppression:
3002 nsLevel = NoiseSuppression::kVeryHigh;
3006 if (rx_audioproc_->noise_suppression()->set_level(nsLevel)
3009 _engineStatisticsPtr->SetLastError(
3010 VE_APM_ERROR, kTraceError,
3011 "SetRxNsStatus() failed to set NS level");
3014 if (rx_audioproc_->noise_suppression()->Enable(enable) != 0)
3016 _engineStatisticsPtr->SetLastError(
3017 VE_APM_ERROR, kTraceError,
3018 "SetRxNsStatus() failed to set NS state");
3022 _rxNsIsEnabled = enable;
3023 channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
3029 Channel::GetRxNsStatus(bool& enabled, NsModes& mode)
3031 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3032 "Channel::GetRxNsStatus(enable=?, mode=?)");
3035 rx_audioproc_->noise_suppression()->is_enabled();
3036 NoiseSuppression::Level ncLevel =
3037 rx_audioproc_->noise_suppression()->level();
3043 case NoiseSuppression::kLow:
3044 mode = kNsLowSuppression;
3046 case NoiseSuppression::kModerate:
3047 mode = kNsModerateSuppression;
3049 case NoiseSuppression::kHigh:
3050 mode = kNsHighSuppression;
3052 case NoiseSuppression::kVeryHigh:
3053 mode = kNsVeryHighSuppression;
3057 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3058 VoEId(_instanceId,_channelId),
3059 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode);
3063 #endif // #ifdef WEBRTC_VOICE_ENGINE_NR
3066 Channel::RegisterRTPObserver(VoERTPObserver& observer)
3068 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3069 "Channel::RegisterRTPObserver()");
3070 CriticalSectionScoped cs(&_callbackCritSect);
3072 if (_rtpObserverPtr)
3074 _engineStatisticsPtr->SetLastError(
3075 VE_INVALID_OPERATION, kTraceError,
3076 "RegisterRTPObserver() observer already enabled");
3080 _rtpObserverPtr = &observer;
3081 _rtpObserver = true;
3087 Channel::DeRegisterRTPObserver()
3089 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3090 "Channel::DeRegisterRTPObserver()");
3091 CriticalSectionScoped cs(&_callbackCritSect);
3093 if (!_rtpObserverPtr)
3095 _engineStatisticsPtr->SetLastError(
3096 VE_INVALID_OPERATION, kTraceWarning,
3097 "DeRegisterRTPObserver() observer already disabled");
3101 _rtpObserver = false;
3102 _rtpObserverPtr = NULL;
3108 Channel::RegisterRTCPObserver(VoERTCPObserver& observer)
3110 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3111 "Channel::RegisterRTCPObserver()");
3112 CriticalSectionScoped cs(&_callbackCritSect);
3114 if (_rtcpObserverPtr)
3116 _engineStatisticsPtr->SetLastError(
3117 VE_INVALID_OPERATION, kTraceError,
3118 "RegisterRTCPObserver() observer already enabled");
3122 _rtcpObserverPtr = &observer;
3123 _rtcpObserver = true;
3129 Channel::DeRegisterRTCPObserver()
3131 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3132 "Channel::DeRegisterRTCPObserver()");
3133 CriticalSectionScoped cs(&_callbackCritSect);
3135 if (!_rtcpObserverPtr)
3137 _engineStatisticsPtr->SetLastError(
3138 VE_INVALID_OPERATION, kTraceWarning,
3139 "DeRegisterRTCPObserver() observer already disabled");
3143 _rtcpObserver = false;
3144 _rtcpObserverPtr = NULL;
3150 Channel::SetLocalSSRC(unsigned int ssrc)
3152 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3153 "Channel::SetLocalSSRC()");
3154 if (channel_state_.Get().sending)
3156 _engineStatisticsPtr->SetLastError(
3157 VE_ALREADY_SENDING, kTraceError,
3158 "SetLocalSSRC() already sending");
3161 if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
3163 _engineStatisticsPtr->SetLastError(
3164 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3165 "SetLocalSSRC() failed to set SSRC");
3172 Channel::GetLocalSSRC(unsigned int& ssrc)
3174 ssrc = _rtpRtcpModule->SSRC();
3175 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3176 VoEId(_instanceId,_channelId),
3177 "GetLocalSSRC() => ssrc=%lu", ssrc);
3182 Channel::GetRemoteSSRC(unsigned int& ssrc)
3184 ssrc = rtp_receiver_->SSRC();
3185 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3186 VoEId(_instanceId,_channelId),
3187 "GetRemoteSSRC() => ssrc=%lu", ssrc);
3192 Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
3194 if (arrCSRC == NULL)
3196 _engineStatisticsPtr->SetLastError(
3197 VE_INVALID_ARGUMENT, kTraceError,
3198 "GetRemoteCSRCs() invalid array argument");
3201 uint32_t arrOfCSRC[kRtpCsrcSize];
3203 CSRCs = rtp_receiver_->CSRCs(arrOfCSRC);
3206 memcpy(arrCSRC, arrOfCSRC, CSRCs * sizeof(uint32_t));
3207 for (int i = 0; i < (int) CSRCs; i++)
3209 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3210 VoEId(_instanceId, _channelId),
3211 "GetRemoteCSRCs() => arrCSRC[%d]=%lu", i, arrCSRC[i]);
3215 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3216 VoEId(_instanceId, _channelId),
3217 "GetRemoteCSRCs() => list is empty!");
3222 int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
3223 _includeAudioLevelIndication = enable;
3224 return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
3227 int Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
3229 rtp_header_parser_->DeregisterRtpHeaderExtension(
3230 kRtpExtensionAudioLevel);
3231 if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension(
3232 kRtpExtensionAudioLevel, id)) {
3238 int Channel::SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
3239 return SetSendRtpHeaderExtension(enable, kRtpExtensionAbsoluteSendTime, id);
3242 int Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
3243 rtp_header_parser_->DeregisterRtpHeaderExtension(
3244 kRtpExtensionAbsoluteSendTime);
3245 if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension(
3246 kRtpExtensionAbsoluteSendTime, id)) {
3253 Channel::SetRTCPStatus(bool enable)
3255 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3256 "Channel::SetRTCPStatus()");
3257 if (_rtpRtcpModule->SetRTCPStatus(enable ?
3258 kRtcpCompound : kRtcpOff) != 0)
3260 _engineStatisticsPtr->SetLastError(
3261 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3262 "SetRTCPStatus() failed to set RTCP status");
3269 Channel::GetRTCPStatus(bool& enabled)
3271 RTCPMethod method = _rtpRtcpModule->RTCP();
3272 enabled = (method != kRtcpOff);
3273 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3274 VoEId(_instanceId,_channelId),
3275 "GetRTCPStatus() => enabled=%d", enabled);
3280 Channel::SetRTCP_CNAME(const char cName[256])
3282 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3283 "Channel::SetRTCP_CNAME()");
3284 if (_rtpRtcpModule->SetCNAME(cName) != 0)
3286 _engineStatisticsPtr->SetLastError(
3287 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3288 "SetRTCP_CNAME() failed to set RTCP CNAME");
3295 Channel::GetRTCP_CNAME(char cName[256])
3297 if (_rtpRtcpModule->CNAME(cName) != 0)
3299 _engineStatisticsPtr->SetLastError(
3300 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3301 "GetRTCP_CNAME() failed to retrieve RTCP CNAME");
3304 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3305 VoEId(_instanceId, _channelId),
3306 "GetRTCP_CNAME() => cName=%s", cName);
3311 Channel::GetRemoteRTCP_CNAME(char cName[256])
3315 _engineStatisticsPtr->SetLastError(
3316 VE_INVALID_ARGUMENT, kTraceError,
3317 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
3320 char cname[RTCP_CNAME_SIZE];
3321 const uint32_t remoteSSRC = rtp_receiver_->SSRC();
3322 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0)
3324 _engineStatisticsPtr->SetLastError(
3325 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
3326 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
3329 strcpy(cName, cname);
3330 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3331 VoEId(_instanceId, _channelId),
3332 "GetRemoteRTCP_CNAME() => cName=%s", cName);
3337 Channel::GetRemoteRTCPData(
3338 unsigned int& NTPHigh,
3339 unsigned int& NTPLow,
3340 unsigned int& timestamp,
3341 unsigned int& playoutTimestamp,
3342 unsigned int* jitter,
3343 unsigned short* fractionLost)
3345 // --- Information from sender info in received Sender Reports
3347 RTCPSenderInfo senderInfo;
3348 if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0)
3350 _engineStatisticsPtr->SetLastError(
3351 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3352 "GetRemoteRTCPData() failed to retrieve sender info for remote "
3357 // We only utilize 12 out of 20 bytes in the sender info (ignores packet
3359 NTPHigh = senderInfo.NTPseconds;
3360 NTPLow = senderInfo.NTPfraction;
3361 timestamp = senderInfo.RTPtimeStamp;
3363 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3364 VoEId(_instanceId, _channelId),
3365 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, "
3367 NTPHigh, NTPLow, timestamp);
3369 // --- Locally derived information
3371 // This value is updated on each incoming RTCP packet (0 when no packet
3372 // has been received)
3373 playoutTimestamp = playout_timestamp_rtcp_;
3375 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3376 VoEId(_instanceId, _channelId),
3377 "GetRemoteRTCPData() => playoutTimestamp=%lu",
3378 playout_timestamp_rtcp_);
3380 if (NULL != jitter || NULL != fractionLost)
3382 // Get all RTCP receiver report blocks that have been received on this
3383 // channel. If we receive RTP packets from a remote source we know the
3384 // remote SSRC and use the report block from him.
3385 // Otherwise use the first report block.
3386 std::vector<RTCPReportBlock> remote_stats;
3387 if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 ||
3388 remote_stats.empty()) {
3389 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3390 VoEId(_instanceId, _channelId),
3391 "GetRemoteRTCPData() failed to measure statistics due"
3392 " to lack of received RTP and/or RTCP packets");
3396 uint32_t remoteSSRC = rtp_receiver_->SSRC();
3397 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin();
3398 for (; it != remote_stats.end(); ++it) {
3399 if (it->remoteSSRC == remoteSSRC)
3403 if (it == remote_stats.end()) {
3404 // If we have not received any RTCP packets from this SSRC it probably
3405 // means that we have not received any RTP packets.
3406 // Use the first received report block instead.
3407 it = remote_stats.begin();
3408 remoteSSRC = it->remoteSSRC;
3412 *jitter = it->jitter;
3413 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3414 VoEId(_instanceId, _channelId),
3415 "GetRemoteRTCPData() => jitter = %lu", *jitter);
3419 *fractionLost = it->fractionLost;
3420 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3421 VoEId(_instanceId, _channelId),
3422 "GetRemoteRTCPData() => fractionLost = %lu",
3430 Channel::SendApplicationDefinedRTCPPacket(unsigned char subType,
3433 unsigned short dataLengthInBytes)
3435 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3436 "Channel::SendApplicationDefinedRTCPPacket()");
3437 if (!channel_state_.Get().sending)
3439 _engineStatisticsPtr->SetLastError(
3440 VE_NOT_SENDING, kTraceError,
3441 "SendApplicationDefinedRTCPPacket() not sending");
3446 _engineStatisticsPtr->SetLastError(
3447 VE_INVALID_ARGUMENT, kTraceError,
3448 "SendApplicationDefinedRTCPPacket() invalid data value");
3451 if (dataLengthInBytes % 4 != 0)
3453 _engineStatisticsPtr->SetLastError(
3454 VE_INVALID_ARGUMENT, kTraceError,
3455 "SendApplicationDefinedRTCPPacket() invalid length value");
3458 RTCPMethod status = _rtpRtcpModule->RTCP();
3459 if (status == kRtcpOff)
3461 _engineStatisticsPtr->SetLastError(
3462 VE_RTCP_ERROR, kTraceError,
3463 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
3467 // Create and schedule the RTCP APP packet for transmission
3468 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
3471 (const unsigned char*) data,
3472 dataLengthInBytes) != 0)
3474 _engineStatisticsPtr->SetLastError(
3475 VE_SEND_ERROR, kTraceError,
3476 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
3483 Channel::GetRTPStatistics(
3484 unsigned int& averageJitterMs,
3485 unsigned int& maxJitterMs,
3486 unsigned int& discardedPackets)
3488 // The jitter statistics is updated for each received RTP packet and is
3489 // based on received packets.
3490 if (_rtpRtcpModule->RTCP() == kRtcpOff) {
3491 // If RTCP is off, there is no timed thread in the RTCP module regularly
3492 // generating new stats, trigger the update manually here instead.
3493 StreamStatistician* statistician =
3494 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
3496 // Don't use returned statistics, use data from proxy instead so that
3497 // max jitter can be fetched atomically.
3499 statistician->GetStatistics(&s, true);
3503 ChannelStatistics stats = statistics_proxy_->GetStats();
3504 const int32_t playoutFrequency = audio_coding_->PlayoutFrequency();
3505 if (playoutFrequency > 0) {
3506 // Scale RTP statistics given the current playout frequency
3507 maxJitterMs = stats.max_jitter / (playoutFrequency / 1000);
3508 averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000);
3511 discardedPackets = _numberOfDiscardedPackets;
3513 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3514 VoEId(_instanceId, _channelId),
3515 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu,"
3516 " discardedPackets = %lu)",
3517 averageJitterMs, maxJitterMs, discardedPackets);
3521 int Channel::GetRemoteRTCPSenderInfo(SenderInfo* sender_info) {
3522 if (sender_info == NULL) {
3523 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
3524 "GetRemoteRTCPSenderInfo() invalid sender_info.");
3528 // Get the sender info from the latest received RTCP Sender Report.
3529 RTCPSenderInfo rtcp_sender_info;
3530 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_sender_info) != 0) {
3531 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3532 "GetRemoteRTCPSenderInfo() failed to read RTCP SR sender info.");
3536 sender_info->NTP_timestamp_high = rtcp_sender_info.NTPseconds;
3537 sender_info->NTP_timestamp_low = rtcp_sender_info.NTPfraction;
3538 sender_info->RTP_timestamp = rtcp_sender_info.RTPtimeStamp;
3539 sender_info->sender_packet_count = rtcp_sender_info.sendPacketCount;
3540 sender_info->sender_octet_count = rtcp_sender_info.sendOctetCount;
3544 int Channel::GetRemoteRTCPReportBlocks(
3545 std::vector<ReportBlock>* report_blocks) {
3546 if (report_blocks == NULL) {
3547 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
3548 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
3552 // Get the report blocks from the latest received RTCP Sender or Receiver
3553 // Report. Each element in the vector contains the sender's SSRC and a
3554 // report block according to RFC 3550.
3555 std::vector<RTCPReportBlock> rtcp_report_blocks;
3556 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
3557 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3558 "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block.");
3562 if (rtcp_report_blocks.empty())
3565 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
3566 for (; it != rtcp_report_blocks.end(); ++it) {
3567 ReportBlock report_block;
3568 report_block.sender_SSRC = it->remoteSSRC;
3569 report_block.source_SSRC = it->sourceSSRC;
3570 report_block.fraction_lost = it->fractionLost;
3571 report_block.cumulative_num_packets_lost = it->cumulativeLost;
3572 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
3573 report_block.interarrival_jitter = it->jitter;
3574 report_block.last_SR_timestamp = it->lastSR;
3575 report_block.delay_since_last_SR = it->delaySinceLastSR;
3576 report_blocks->push_back(report_block);
3582 Channel::GetRTPStatistics(CallStatistics& stats)
3584 // --- Part one of the final structure (four values)
3586 // The jitter statistics is updated for each received RTP packet and is
3587 // based on received packets.
3588 RtcpStatistics statistics;
3589 StreamStatistician* statistician =
3590 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
3591 if (!statistician || !statistician->GetStatistics(
3592 &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) {
3593 _engineStatisticsPtr->SetLastError(
3594 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning,
3595 "GetRTPStatistics() failed to read RTP statistics from the "
3599 stats.fractionLost = statistics.fraction_lost;
3600 stats.cumulativeLost = statistics.cumulative_lost;
3601 stats.extendedMax = statistics.extended_max_sequence_number;
3602 stats.jitterSamples = statistics.jitter;
3604 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3605 VoEId(_instanceId, _channelId),
3606 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu,"
3607 " extendedMax=%lu, jitterSamples=%li)",
3608 stats.fractionLost, stats.cumulativeLost, stats.extendedMax,
3609 stats.jitterSamples);
3611 // --- Part two of the final structure (one value)
3614 RTCPMethod method = _rtpRtcpModule->RTCP();
3615 if (method == kRtcpOff)
3617 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3618 VoEId(_instanceId, _channelId),
3619 "GetRTPStatistics() RTCP is disabled => valid RTT "
3620 "measurements cannot be retrieved");
3623 // The remote SSRC will be zero if no RTP packet has been received.
3624 uint32_t remoteSSRC = rtp_receiver_->SSRC();
3631 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT)
3634 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3635 VoEId(_instanceId, _channelId),
3636 "GetRTPStatistics() failed to retrieve RTT from "
3637 "the RTP/RTCP module");
3641 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3642 VoEId(_instanceId, _channelId),
3643 "GetRTPStatistics() failed to measure RTT since no "
3644 "RTP packets have been received yet");
3648 stats.rttMs = static_cast<int> (RTT);
3650 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3651 VoEId(_instanceId, _channelId),
3652 "GetRTPStatistics() => rttMs=%d", stats.rttMs);
3654 // --- Part three of the final structure (four values)
3656 uint32_t bytesSent(0);
3657 uint32_t packetsSent(0);
3658 uint32_t bytesReceived(0);
3659 uint32_t packetsReceived(0);
3662 statistician->GetDataCounters(&bytesReceived, &packetsReceived);
3665 if (_rtpRtcpModule->DataCountersRTP(&bytesSent,
3668 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
3669 VoEId(_instanceId, _channelId),
3670 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
3671 " output will not be complete");
3674 stats.bytesSent = bytesSent;
3675 stats.packetsSent = packetsSent;
3676 stats.bytesReceived = bytesReceived;
3677 stats.packetsReceived = packetsReceived;
3679 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3680 VoEId(_instanceId, _channelId),
3681 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d,"
3682 " bytesReceived=%d, packetsReceived=%d)",
3683 stats.bytesSent, stats.packetsSent, stats.bytesReceived,
3684 stats.packetsReceived);
3689 int Channel::SetFECStatus(bool enable, int redPayloadtype) {
3690 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3691 "Channel::SetFECStatus()");
3694 if (redPayloadtype < 0 || redPayloadtype > 127) {
3695 _engineStatisticsPtr->SetLastError(
3696 VE_PLTYPE_ERROR, kTraceError,
3697 "SetFECStatus() invalid RED payload type");
3701 if (SetRedPayloadType(redPayloadtype) < 0) {
3702 _engineStatisticsPtr->SetLastError(
3703 VE_CODEC_ERROR, kTraceError,
3704 "SetSecondarySendCodec() Failed to register RED ACM");
3709 if (audio_coding_->SetFECStatus(enable) != 0) {
3710 _engineStatisticsPtr->SetLastError(
3711 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
3712 "SetFECStatus() failed to set FEC state in the ACM");
3719 Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
3721 enabled = audio_coding_->FECStatus();
3724 int8_t payloadType(0);
3725 if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0)
3727 _engineStatisticsPtr->SetLastError(
3728 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
3729 "GetFECStatus() failed to retrieve RED PT from RTP/RTCP "
3733 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3734 VoEId(_instanceId, _channelId),
3735 "GetFECStatus() => enabled=%d, redPayloadtype=%d",
3736 enabled, redPayloadtype);
3739 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
3740 VoEId(_instanceId, _channelId),
3741 "GetFECStatus() => enabled=%d", enabled);
3745 void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
3746 // None of these functions can fail.
3747 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
3748 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
3749 rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
3751 audio_coding_->EnableNack(maxNumberOfPackets);
3753 audio_coding_->DisableNack();
3756 // Called when we are missing one or more packets.
3757 int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
3758 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
3762 Channel::StartRTPDump(const char fileNameUTF8[1024],
3763 RTPDirections direction)
3765 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3766 "Channel::StartRTPDump()");
3767 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
3769 _engineStatisticsPtr->SetLastError(
3770 VE_INVALID_ARGUMENT, kTraceError,
3771 "StartRTPDump() invalid RTP direction");
3774 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3775 &_rtpDumpIn : &_rtpDumpOut;
3776 if (rtpDumpPtr == NULL)
3781 if (rtpDumpPtr->IsActive())
3785 if (rtpDumpPtr->Start(fileNameUTF8) != 0)
3787 _engineStatisticsPtr->SetLastError(
3788 VE_BAD_FILE, kTraceError,
3789 "StartRTPDump() failed to create file");
3796 Channel::StopRTPDump(RTPDirections direction)
3798 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
3799 "Channel::StopRTPDump()");
3800 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing))
3802 _engineStatisticsPtr->SetLastError(
3803 VE_INVALID_ARGUMENT, kTraceError,
3804 "StopRTPDump() invalid RTP direction");
3807 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3808 &_rtpDumpIn : &_rtpDumpOut;
3809 if (rtpDumpPtr == NULL)
3814 if (!rtpDumpPtr->IsActive())
3818 return rtpDumpPtr->Stop();
3822 Channel::RTPDumpIsActive(RTPDirections direction)
3824 if ((direction != kRtpIncoming) &&
3825 (direction != kRtpOutgoing))
3827 _engineStatisticsPtr->SetLastError(
3828 VE_INVALID_ARGUMENT, kTraceError,
3829 "RTPDumpIsActive() invalid RTP direction");
3832 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ?
3833 &_rtpDumpIn : &_rtpDumpOut;
3834 return rtpDumpPtr->IsActive();
3837 void Channel::SetVideoEngineBWETarget(ViENetwork* vie_network,
3838 int video_channel) {
3839 CriticalSectionScoped cs(&_callbackCritSect);
3841 vie_network_->Release();
3842 vie_network_ = NULL;
3844 video_channel_ = -1;
3846 if (vie_network != NULL && video_channel != -1) {
3847 vie_network_ = vie_network;
3848 video_channel_ = video_channel;
3853 Channel::Demultiplex(const AudioFrame& audioFrame)
3855 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3856 "Channel::Demultiplex()");
3857 _audioFrame.CopyFrom(audioFrame);
3858 _audioFrame.id_ = _channelId;
3862 void Channel::Demultiplex(const int16_t* audio_data,
3864 int number_of_frames,
3865 int number_of_channels) {
3867 GetSendCodec(codec);
3869 if (!mono_recording_audio_.get()) {
3870 // Temporary space for DownConvertToCodecFormat.
3871 mono_recording_audio_.reset(new int16_t[kMaxMonoDataSizeSamples]);
3873 DownConvertToCodecFormat(audio_data,
3879 mono_recording_audio_.get(),
3885 Channel::PrepareEncodeAndSend(int mixingFrequency)
3887 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3888 "Channel::PrepareEncodeAndSend()");
3890 if (_audioFrame.samples_per_channel_ == 0)
3892 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3893 "Channel::PrepareEncodeAndSend() invalid audio frame");
3897 if (channel_state_.Get().input_file_playing)
3899 MixOrReplaceAudioWithFile(mixingFrequency);
3904 AudioFrameOperations::Mute(_audioFrame);
3907 if (channel_state_.Get().input_external_media)
3909 CriticalSectionScoped cs(&_callbackCritSect);
3910 const bool isStereo = (_audioFrame.num_channels_ == 2);
3911 if (_inputExternalMediaCallbackPtr)
3913 _inputExternalMediaCallbackPtr->Process(
3915 kRecordingPerChannel,
3916 (int16_t*)_audioFrame.data_,
3917 _audioFrame.samples_per_channel_,
3918 _audioFrame.sample_rate_hz_,
3923 InsertInbandDtmfTone();
3925 if (_includeAudioLevelIndication) {
3926 int length = _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
3927 rms_level_.Process(_audioFrame.data_, length);
3934 Channel::EncodeAndSend()
3936 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
3937 "Channel::EncodeAndSend()");
3939 assert(_audioFrame.num_channels_ <= 2);
3940 if (_audioFrame.samples_per_channel_ == 0)
3942 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
3943 "Channel::EncodeAndSend() invalid audio frame");
3947 _audioFrame.id_ = _channelId;
3949 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
3951 // The ACM resamples internally.
3952 _audioFrame.timestamp_ = _timeStamp;
3953 if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) != 0)
3955 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId),
3956 "Channel::EncodeAndSend() ACM encoding failed");
3960 _timeStamp += _audioFrame.samples_per_channel_;
3962 // --- Encode if complete frame is ready
3964 // This call will trigger AudioPacketizationCallback::SendData if encoding
3965 // is done and payload is ready for packetization and transmission.
3966 return audio_coding_->Process();
3969 int Channel::RegisterExternalMediaProcessing(
3970 ProcessingTypes type,
3971 VoEMediaProcess& processObject)
3973 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
3974 "Channel::RegisterExternalMediaProcessing()");
3976 CriticalSectionScoped cs(&_callbackCritSect);
3978 if (kPlaybackPerChannel == type)
3980 if (_outputExternalMediaCallbackPtr)
3982 _engineStatisticsPtr->SetLastError(
3983 VE_INVALID_OPERATION, kTraceError,
3984 "Channel::RegisterExternalMediaProcessing() "
3985 "output external media already enabled");
3988 _outputExternalMediaCallbackPtr = &processObject;
3989 _outputExternalMedia = true;
3991 else if (kRecordingPerChannel == type)
3993 if (_inputExternalMediaCallbackPtr)
3995 _engineStatisticsPtr->SetLastError(
3996 VE_INVALID_OPERATION, kTraceError,
3997 "Channel::RegisterExternalMediaProcessing() "
3998 "output external media already enabled");
4001 _inputExternalMediaCallbackPtr = &processObject;
4002 channel_state_.SetInputExternalMedia(true);
4007 int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
4009 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4010 "Channel::DeRegisterExternalMediaProcessing()");
4012 CriticalSectionScoped cs(&_callbackCritSect);
4014 if (kPlaybackPerChannel == type)
4016 if (!_outputExternalMediaCallbackPtr)
4018 _engineStatisticsPtr->SetLastError(
4019 VE_INVALID_OPERATION, kTraceWarning,
4020 "Channel::DeRegisterExternalMediaProcessing() "
4021 "output external media already disabled");
4024 _outputExternalMedia = false;
4025 _outputExternalMediaCallbackPtr = NULL;
4027 else if (kRecordingPerChannel == type)
4029 if (!_inputExternalMediaCallbackPtr)
4031 _engineStatisticsPtr->SetLastError(
4032 VE_INVALID_OPERATION, kTraceWarning,
4033 "Channel::DeRegisterExternalMediaProcessing() "
4034 "input external media already disabled");
4037 channel_state_.SetInputExternalMedia(false);
4038 _inputExternalMediaCallbackPtr = NULL;
4044 int Channel::SetExternalMixing(bool enabled) {
4045 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4046 "Channel::SetExternalMixing(enabled=%d)", enabled);
4048 if (channel_state_.Get().playing)
4050 _engineStatisticsPtr->SetLastError(
4051 VE_INVALID_OPERATION, kTraceError,
4052 "Channel::SetExternalMixing() "
4053 "external mixing cannot be changed while playing.");
4057 _externalMixing = enabled;
4063 Channel::GetNetworkStatistics(NetworkStatistics& stats)
4065 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4066 "Channel::GetNetworkStatistics()");
4067 ACMNetworkStatistics acm_stats;
4068 int return_value = audio_coding_->NetworkStatistics(&acm_stats);
4069 if (return_value >= 0) {
4070 memcpy(&stats, &acm_stats, sizeof(NetworkStatistics));
4072 return return_value;
4075 void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
4076 audio_coding_->GetDecodingCallStatistics(stats);
4079 bool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms,
4080 int* playout_buffer_delay_ms) const {
4081 if (_average_jitter_buffer_delay_us == 0) {
4082 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4083 "Channel::GetDelayEstimate() no valid estimate.");
4086 *jitter_buffer_delay_ms = (_average_jitter_buffer_delay_us + 500) / 1000 +
4088 *playout_buffer_delay_ms = playout_delay_ms_;
4089 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4090 "Channel::GetDelayEstimate()");
4094 int Channel::SetInitialPlayoutDelay(int delay_ms)
4096 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4097 "Channel::SetInitialPlayoutDelay()");
4098 if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
4099 (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs))
4101 _engineStatisticsPtr->SetLastError(
4102 VE_INVALID_ARGUMENT, kTraceError,
4103 "SetInitialPlayoutDelay() invalid min delay");
4106 if (audio_coding_->SetInitialPlayoutDelay(delay_ms) != 0)
4108 _engineStatisticsPtr->SetLastError(
4109 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4110 "SetInitialPlayoutDelay() failed to set min playout delay");
4118 Channel::SetMinimumPlayoutDelay(int delayMs)
4120 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4121 "Channel::SetMinimumPlayoutDelay()");
4122 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
4123 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs))
4125 _engineStatisticsPtr->SetLastError(
4126 VE_INVALID_ARGUMENT, kTraceError,
4127 "SetMinimumPlayoutDelay() invalid min delay");
4130 if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0)
4132 _engineStatisticsPtr->SetLastError(
4133 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4134 "SetMinimumPlayoutDelay() failed to set min playout delay");
4140 void Channel::UpdatePlayoutTimestamp(bool rtcp) {
4141 uint32_t playout_timestamp = 0;
4143 if (audio_coding_->PlayoutTimestamp(&playout_timestamp) == -1) {
4144 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4145 "Channel::UpdatePlayoutTimestamp() failed to read playout"
4146 " timestamp from the ACM");
4147 _engineStatisticsPtr->SetLastError(
4148 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4149 "UpdatePlayoutTimestamp() failed to retrieve timestamp");
4153 uint16_t delay_ms = 0;
4154 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
4155 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4156 "Channel::UpdatePlayoutTimestamp() failed to read playout"
4157 " delay from the ADM");
4158 _engineStatisticsPtr->SetLastError(
4159 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4160 "UpdatePlayoutTimestamp() failed to retrieve playout delay");
4164 int32_t playout_frequency = audio_coding_->PlayoutFrequency();
4165 CodecInst current_recive_codec;
4166 if (audio_coding_->ReceiveCodec(¤t_recive_codec) == 0) {
4167 if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) {
4168 playout_frequency = 8000;
4169 } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) {
4170 playout_frequency = 48000;
4174 jitter_buffer_playout_timestamp_ = playout_timestamp;
4176 // Remove the playout delay.
4177 playout_timestamp -= (delay_ms * (playout_frequency / 1000));
4179 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4180 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
4184 playout_timestamp_rtcp_ = playout_timestamp;
4186 playout_timestamp_rtp_ = playout_timestamp;
4188 playout_delay_ms_ = delay_ms;
4191 int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
4192 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4193 "Channel::GetPlayoutTimestamp()");
4194 if (playout_timestamp_rtp_ == 0) {
4195 _engineStatisticsPtr->SetLastError(
4196 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
4197 "GetPlayoutTimestamp() failed to retrieve timestamp");
4200 timestamp = playout_timestamp_rtp_;
4201 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
4202 VoEId(_instanceId,_channelId),
4203 "GetPlayoutTimestamp() => timestamp=%u", timestamp);
4208 Channel::SetInitTimestamp(unsigned int timestamp)
4210 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4211 "Channel::SetInitTimestamp()");
4212 if (channel_state_.Get().sending)
4214 _engineStatisticsPtr->SetLastError(
4215 VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
4218 if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0)
4220 _engineStatisticsPtr->SetLastError(
4221 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4222 "SetInitTimestamp() failed to set timestamp");
4229 Channel::SetInitSequenceNumber(short sequenceNumber)
4231 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4232 "Channel::SetInitSequenceNumber()");
4233 if (channel_state_.Get().sending)
4235 _engineStatisticsPtr->SetLastError(
4236 VE_SENDING, kTraceError,
4237 "SetInitSequenceNumber() already sending");
4240 if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0)
4242 _engineStatisticsPtr->SetLastError(
4243 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4244 "SetInitSequenceNumber() failed to set sequence number");
4251 Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const
4253 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4254 "Channel::GetRtpRtcp()");
4255 *rtpRtcpModule = _rtpRtcpModule.get();
4256 *rtp_receiver = rtp_receiver_.get();
4260 // TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
4263 Channel::MixOrReplaceAudioWithFile(int mixingFrequency)
4265 scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]);
4269 CriticalSectionScoped cs(&_fileCritSect);
4271 if (_inputFilePlayerPtr == NULL)
4273 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4274 VoEId(_instanceId, _channelId),
4275 "Channel::MixOrReplaceAudioWithFile() fileplayer"
4280 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
4282 mixingFrequency) == -1)
4284 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4285 VoEId(_instanceId, _channelId),
4286 "Channel::MixOrReplaceAudioWithFile() file mixing "
4290 if (fileSamples == 0)
4292 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4293 VoEId(_instanceId, _channelId),
4294 "Channel::MixOrReplaceAudioWithFile() file is ended");
4299 assert(_audioFrame.samples_per_channel_ == fileSamples);
4301 if (_mixFileWithMicrophone)
4303 // Currently file stream is always mono.
4304 // TODO(xians): Change the code when FilePlayer supports real stereo.
4305 MixWithSat(_audioFrame.data_,
4306 _audioFrame.num_channels_,
4313 // Replace ACM audio with file.
4314 // Currently file stream is always mono.
4315 // TODO(xians): Change the code when FilePlayer supports real stereo.
4316 _audioFrame.UpdateFrame(_channelId,
4321 AudioFrame::kNormalSpeech,
4322 AudioFrame::kVadUnknown,
4330 Channel::MixAudioWithFile(AudioFrame& audioFrame,
4331 int mixingFrequency)
4333 assert(mixingFrequency <= 32000);
4335 scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]);
4339 CriticalSectionScoped cs(&_fileCritSect);
4341 if (_outputFilePlayerPtr == NULL)
4343 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4344 VoEId(_instanceId, _channelId),
4345 "Channel::MixAudioWithFile() file mixing failed");
4349 // We should get the frequency we ask for.
4350 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(),
4352 mixingFrequency) == -1)
4354 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4355 VoEId(_instanceId, _channelId),
4356 "Channel::MixAudioWithFile() file mixing failed");
4361 if (audioFrame.samples_per_channel_ == fileSamples)
4363 // Currently file stream is always mono.
4364 // TODO(xians): Change the code when FilePlayer supports real stereo.
4365 MixWithSat(audioFrame.data_,
4366 audioFrame.num_channels_,
4373 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId),
4374 "Channel::MixAudioWithFile() samples_per_channel_(%d) != "
4376 audioFrame.samples_per_channel_, fileSamples);
4384 Channel::InsertInbandDtmfTone()
4386 // Check if we should start a new tone.
4387 if (_inbandDtmfQueue.PendingDtmf() &&
4388 !_inbandDtmfGenerator.IsAddingTone() &&
4389 _inbandDtmfGenerator.DelaySinceLastTone() >
4390 kMinTelephoneEventSeparationMs)
4392 int8_t eventCode(0);
4393 uint16_t lengthMs(0);
4394 uint8_t attenuationDb(0);
4396 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb);
4397 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb);
4398 if (_playInbandDtmfEvent)
4400 // Add tone to output mixer using a reduced length to minimize
4402 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80,
4407 if (_inbandDtmfGenerator.IsAddingTone())
4409 uint16_t frequency(0);
4410 _inbandDtmfGenerator.GetSampleRate(frequency);
4412 if (frequency != _audioFrame.sample_rate_hz_)
4414 // Update sample rate of Dtmf tone since the mixing frequency
4416 _inbandDtmfGenerator.SetSampleRate(
4417 (uint16_t) (_audioFrame.sample_rate_hz_));
4418 // Reset the tone to be added taking the new sample rate into
4420 _inbandDtmfGenerator.ResetTone();
4423 int16_t toneBuffer[320];
4424 uint16_t toneSamples(0);
4425 // Get 10ms tone segment and set time since last tone to zero
4426 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1)
4428 WEBRTC_TRACE(kTraceWarning, kTraceVoice,
4429 VoEId(_instanceId, _channelId),
4430 "Channel::EncodeAndSend() inserting Dtmf failed");
4434 // Replace mixed audio with DTMF tone.
4435 for (int sample = 0;
4436 sample < _audioFrame.samples_per_channel_;
4439 for (int channel = 0;
4440 channel < _audioFrame.num_channels_;
4443 const int index = sample * _audioFrame.num_channels_ + channel;
4444 _audioFrame.data_[index] = toneBuffer[sample];
4448 assert(_audioFrame.samples_per_channel_ == toneSamples);
4451 // Add 10ms to "delay-since-last-tone" counter
4452 _inbandDtmfGenerator.UpdateDelaySinceLastTone();
4458 Channel::SendPacketRaw(const void *data, int len, bool RTCP)
4460 CriticalSectionScoped cs(&_callbackCritSect);
4461 if (_transportPtr == NULL)
4467 return _transportPtr->SendPacket(_channelId, data, len);
4471 return _transportPtr->SendRTCPPacket(_channelId, data, len);
4475 // Called for incoming RTP packets after successful RTP header parsing.
4476 void Channel::UpdatePacketDelay(uint32_t rtp_timestamp,
4477 uint16_t sequence_number) {
4478 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId),
4479 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)",
4480 rtp_timestamp, sequence_number);
4482 // Get frequency of last received payload
4483 int rtp_receive_frequency = audio_coding_->ReceiveFrequency();
4485 CodecInst current_receive_codec;
4486 if (audio_coding_->ReceiveCodec(¤t_receive_codec) != 0) {
4490 // Update the least required delay.
4491 least_required_delay_ms_ = audio_coding_->LeastRequiredDelayMs();
4493 if (STR_CASE_CMP("G722", current_receive_codec.plname) == 0) {
4494 // Even though the actual sampling rate for G.722 audio is
4495 // 16,000 Hz, the RTP clock rate for the G722 payload format is
4496 // 8,000 Hz because that value was erroneously assigned in
4497 // RFC 1890 and must remain unchanged for backward compatibility.
4498 rtp_receive_frequency = 8000;
4499 } else if (STR_CASE_CMP("opus", current_receive_codec.plname) == 0) {
4500 // We are resampling Opus internally to 32,000 Hz until all our
4501 // DSP routines can operate at 48,000 Hz, but the RTP clock
4502 // rate for the Opus payload format is standardized to 48,000 Hz,
4503 // because that is the maximum supported decoding sampling rate.
4504 rtp_receive_frequency = 48000;
4507 // |jitter_buffer_playout_timestamp_| updated in UpdatePlayoutTimestamp for
4508 // every incoming packet.
4509 uint32_t timestamp_diff_ms = (rtp_timestamp -
4510 jitter_buffer_playout_timestamp_) / (rtp_receive_frequency / 1000);
4511 if (!IsNewerTimestamp(rtp_timestamp, jitter_buffer_playout_timestamp_) ||
4512 timestamp_diff_ms > (2 * kVoiceEngineMaxMinPlayoutDelayMs)) {
4513 // If |jitter_buffer_playout_timestamp_| is newer than the incoming RTP
4514 // timestamp, the resulting difference is negative, but is set to zero.
4515 // This can happen when a network glitch causes a packet to arrive late,
4516 // and during long comfort noise periods with clock drift.
4517 timestamp_diff_ms = 0;
4520 uint16_t packet_delay_ms = (rtp_timestamp - _previousTimestamp) /
4521 (rtp_receive_frequency / 1000);
4523 _previousTimestamp = rtp_timestamp;
4525 if (timestamp_diff_ms == 0) return;
4527 if (packet_delay_ms >= 10 && packet_delay_ms <= 60) {
4528 _recPacketDelayMs = packet_delay_ms;
4531 if (_average_jitter_buffer_delay_us == 0) {
4532 _average_jitter_buffer_delay_us = timestamp_diff_ms * 1000;
4536 // Filter average delay value using exponential filter (alpha is
4537 // 7/8). We derive 1000 *_average_jitter_buffer_delay_us here (reduces
4538 // risk of rounding error) and compensate for it in GetDelayEstimate()
4540 _average_jitter_buffer_delay_us = (_average_jitter_buffer_delay_us * 7 +
4541 1000 * timestamp_diff_ms + 500) / 8;
4545 Channel::RegisterReceiveCodecsToRTPModule()
4547 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
4548 "Channel::RegisterReceiveCodecsToRTPModule()");
4552 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
4554 for (int idx = 0; idx < nSupportedCodecs; idx++)
4556 // Open up the RTP/RTCP receiver for all supported codecs
4557 if ((audio_coding_->Codec(idx, &codec) == -1) ||
4558 (rtp_receiver_->RegisterReceivePayload(
4563 (codec.rate < 0) ? 0 : codec.rate) == -1))
4568 VoEId(_instanceId, _channelId),
4569 "Channel::RegisterReceiveCodecsToRTPModule() unable"
4570 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver",
4571 codec.plname, codec.pltype, codec.plfreq,
4572 codec.channels, codec.rate);
4579 VoEId(_instanceId, _channelId),
4580 "Channel::RegisterReceiveCodecsToRTPModule() %s "
4581 "(%d/%d/%d/%d) has been added to the RTP/RTCP "
4583 codec.plname, codec.pltype, codec.plfreq,
4584 codec.channels, codec.rate);
4589 int Channel::SetSecondarySendCodec(const CodecInst& codec,
4590 int red_payload_type) {
4591 // Sanity check for payload type.
4592 if (red_payload_type < 0 || red_payload_type > 127) {
4593 _engineStatisticsPtr->SetLastError(
4594 VE_PLTYPE_ERROR, kTraceError,
4595 "SetRedPayloadType() invalid RED payload type");
4599 if (SetRedPayloadType(red_payload_type) < 0) {
4600 _engineStatisticsPtr->SetLastError(
4601 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4602 "SetSecondarySendCodec() Failed to register RED ACM");
4605 if (audio_coding_->RegisterSecondarySendCodec(codec) < 0) {
4606 _engineStatisticsPtr->SetLastError(
4607 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4608 "SetSecondarySendCodec() Failed to register secondary send codec in "
4616 void Channel::RemoveSecondarySendCodec() {
4617 audio_coding_->UnregisterSecondarySendCodec();
4620 int Channel::GetSecondarySendCodec(CodecInst* codec) {
4621 if (audio_coding_->SecondarySendCodec(codec) < 0) {
4622 _engineStatisticsPtr->SetLastError(
4623 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4624 "GetSecondarySendCodec() Failed to get secondary sent codec from ACM");
4630 // Assuming this method is called with valid payload type.
4631 int Channel::SetRedPayloadType(int red_payload_type) {
4633 bool found_red = false;
4635 // Get default RED settings from the ACM database
4636 const int num_codecs = AudioCodingModule::NumberOfCodecs();
4637 for (int idx = 0; idx < num_codecs; idx++) {
4638 audio_coding_->Codec(idx, &codec);
4639 if (!STR_CASE_CMP(codec.plname, "RED")) {
4646 _engineStatisticsPtr->SetLastError(
4647 VE_CODEC_ERROR, kTraceError,
4648 "SetRedPayloadType() RED is not supported");
4652 codec.pltype = red_payload_type;
4653 if (audio_coding_->RegisterSendCodec(codec) < 0) {
4654 _engineStatisticsPtr->SetLastError(
4655 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
4656 "SetRedPayloadType() RED registration in ACM module failed");
4660 if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) {
4661 _engineStatisticsPtr->SetLastError(
4662 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
4663 "SetRedPayloadType() RED registration in RTP/RTCP module failed");
4669 int Channel::SetSendRtpHeaderExtension(bool enable, RTPExtensionType type,
4672 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
4674 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
4679 } // namespace webrtc