1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/voice_engine/channel.h" 12 13 #include "webrtc/base/timeutils.h" 14 #include "webrtc/common.h" 15 #include "webrtc/modules/audio_device/include/audio_device.h" 16 #include "webrtc/modules/audio_processing/include/audio_processing.h" 17 #include "webrtc/modules/interface/module_common_types.h" 18 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" 19 #include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h" 20 #include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" 21 #include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" 22 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" 23 #include "webrtc/modules/utility/interface/audio_frame_operations.h" 24 #include "webrtc/modules/utility/interface/process_thread.h" 25 #include "webrtc/modules/utility/interface/rtp_dump.h" 26 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 27 #include "webrtc/system_wrappers/interface/logging.h" 28 #include "webrtc/system_wrappers/interface/trace.h" 29 #include "webrtc/video_engine/include/vie_network.h" 30 #include "webrtc/voice_engine/include/voe_base.h" 31 #include "webrtc/voice_engine/include/voe_external_media.h" 32 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" 33 #include "webrtc/voice_engine/output_mixer.h" 34 #include "webrtc/voice_engine/statistics.h" 35 #include "webrtc/voice_engine/transmit_mixer.h" 36 #include "webrtc/voice_engine/utility.h" 37 38 #if defined(_WIN32) 39 #include <Qos.h> 40 #endif 41 42 namespace webrtc { 43 namespace voe { 44 45 // Extend the default RTCP statistics struct with max_jitter, defined as the 46 // maximum jitter value seen in an RTCP report block. 47 struct ChannelStatistics : public RtcpStatistics { 48 ChannelStatistics() : rtcp(), max_jitter(0) {} 49 50 RtcpStatistics rtcp; 51 uint32_t max_jitter; 52 }; 53 54 // Statistics callback, called at each generation of a new RTCP report block. 55 class StatisticsProxy : public RtcpStatisticsCallback { 56 public: 57 StatisticsProxy(uint32_t ssrc) 58 : stats_lock_(CriticalSectionWrapper::CreateCriticalSection()), 59 ssrc_(ssrc) {} 60 virtual ~StatisticsProxy() {} 61 62 virtual void StatisticsUpdated(const RtcpStatistics& statistics, 63 uint32_t ssrc) OVERRIDE { 64 if (ssrc != ssrc_) 65 return; 66 67 CriticalSectionScoped cs(stats_lock_.get()); 68 stats_.rtcp = statistics; 69 if (statistics.jitter > stats_.max_jitter) { 70 stats_.max_jitter = statistics.jitter; 71 } 72 } 73 74 void ResetStatistics() { 75 CriticalSectionScoped cs(stats_lock_.get()); 76 stats_ = ChannelStatistics(); 77 } 78 79 ChannelStatistics GetStats() { 80 CriticalSectionScoped cs(stats_lock_.get()); 81 return stats_; 82 } 83 84 private: 85 // StatisticsUpdated calls are triggered from threads in the RTP module, 86 // while GetStats calls can be triggered from the public voice engine API, 87 // hence synchronization is needed. 88 scoped_ptr<CriticalSectionWrapper> stats_lock_; 89 const uint32_t ssrc_; 90 ChannelStatistics stats_; 91 }; 92 93 class VoEBitrateObserver : public BitrateObserver { 94 public: 95 explicit VoEBitrateObserver(Channel* owner) 96 : owner_(owner) {} 97 virtual ~VoEBitrateObserver() {} 98 99 // Implements BitrateObserver. 100 virtual void OnNetworkChanged(const uint32_t bitrate_bps, 101 const uint8_t fraction_lost, 102 const uint32_t rtt) OVERRIDE { 103 // |fraction_lost| has a scale of 0 - 255. 104 owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt); 105 } 106 107 private: 108 Channel* owner_; 109 }; 110 111 int32_t 112 Channel::SendData(FrameType frameType, 113 uint8_t payloadType, 114 uint32_t timeStamp, 115 const uint8_t* payloadData, 116 uint16_t payloadSize, 117 const RTPFragmentationHeader* fragmentation) 118 { 119 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 120 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u," 121 " payloadSize=%u, fragmentation=0x%x)", 122 frameType, payloadType, timeStamp, payloadSize, fragmentation); 123 124 if (_includeAudioLevelIndication) 125 { 126 // Store current audio level in the RTP/RTCP module. 127 // The level will be used in combination with voice-activity state 128 // (frameType) to add an RTP header extension 129 _rtpRtcpModule->SetAudioLevel(rms_level_.RMS()); 130 } 131 132 // Push data from ACM to RTP/RTCP-module to deliver audio frame for 133 // packetization. 134 // This call will trigger Transport::SendPacket() from the RTP/RTCP module. 135 if (_rtpRtcpModule->SendOutgoingData((FrameType&)frameType, 136 payloadType, 137 timeStamp, 138 // Leaving the time when this frame was 139 // received from the capture device as 140 // undefined for voice for now. 141 -1, 142 payloadData, 143 payloadSize, 144 fragmentation) == -1) 145 { 146 _engineStatisticsPtr->SetLastError( 147 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 148 "Channel::SendData() failed to send data to RTP/RTCP module"); 149 return -1; 150 } 151 152 _lastLocalTimeStamp = timeStamp; 153 _lastPayloadType = payloadType; 154 155 return 0; 156 } 157 158 int32_t 159 Channel::InFrameType(int16_t frameType) 160 { 161 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 162 "Channel::InFrameType(frameType=%d)", frameType); 163 164 CriticalSectionScoped cs(&_callbackCritSect); 165 // 1 indicates speech 166 _sendFrameType = (frameType == 1) ? 1 : 0; 167 return 0; 168 } 169 170 int32_t 171 Channel::OnRxVadDetected(int vadDecision) 172 { 173 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 174 "Channel::OnRxVadDetected(vadDecision=%d)", vadDecision); 175 176 CriticalSectionScoped cs(&_callbackCritSect); 177 if (_rxVadObserverPtr) 178 { 179 _rxVadObserverPtr->OnRxVad(_channelId, vadDecision); 180 } 181 182 return 0; 183 } 184 185 int 186 Channel::SendPacket(int channel, const void *data, int len) 187 { 188 channel = VoEChannelId(channel); 189 assert(channel == _channelId); 190 191 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 192 "Channel::SendPacket(channel=%d, len=%d)", channel, len); 193 194 CriticalSectionScoped cs(&_callbackCritSect); 195 196 if (_transportPtr == NULL) 197 { 198 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 199 "Channel::SendPacket() failed to send RTP packet due to" 200 " invalid transport object"); 201 return -1; 202 } 203 204 uint8_t* bufferToSendPtr = (uint8_t*)data; 205 int32_t bufferLength = len; 206 207 // Dump the RTP packet to a file (if RTP dump is enabled). 208 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1) 209 { 210 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 211 VoEId(_instanceId,_channelId), 212 "Channel::SendPacket() RTP dump to output file failed"); 213 } 214 215 int n = _transportPtr->SendPacket(channel, bufferToSendPtr, 216 bufferLength); 217 if (n < 0) { 218 std::string transport_name = 219 _externalTransport ? "external transport" : "WebRtc sockets"; 220 WEBRTC_TRACE(kTraceError, kTraceVoice, 221 VoEId(_instanceId,_channelId), 222 "Channel::SendPacket() RTP transmission using %s failed", 223 transport_name.c_str()); 224 return -1; 225 } 226 return n; 227 } 228 229 int 230 Channel::SendRTCPPacket(int channel, const void *data, int len) 231 { 232 channel = VoEChannelId(channel); 233 assert(channel == _channelId); 234 235 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 236 "Channel::SendRTCPPacket(channel=%d, len=%d)", channel, len); 237 238 CriticalSectionScoped cs(&_callbackCritSect); 239 if (_transportPtr == NULL) 240 { 241 WEBRTC_TRACE(kTraceError, kTraceVoice, 242 VoEId(_instanceId,_channelId), 243 "Channel::SendRTCPPacket() failed to send RTCP packet" 244 " due to invalid transport object"); 245 return -1; 246 } 247 248 uint8_t* bufferToSendPtr = (uint8_t*)data; 249 int32_t bufferLength = len; 250 251 // Dump the RTCP packet to a file (if RTP dump is enabled). 252 if (_rtpDumpOut.DumpPacket((const uint8_t*)data, len) == -1) 253 { 254 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 255 VoEId(_instanceId,_channelId), 256 "Channel::SendPacket() RTCP dump to output file failed"); 257 } 258 259 int n = _transportPtr->SendRTCPPacket(channel, 260 bufferToSendPtr, 261 bufferLength); 262 if (n < 0) { 263 std::string transport_name = 264 _externalTransport ? "external transport" : "WebRtc sockets"; 265 WEBRTC_TRACE(kTraceInfo, kTraceVoice, 266 VoEId(_instanceId,_channelId), 267 "Channel::SendRTCPPacket() transmission using %s failed", 268 transport_name.c_str()); 269 return -1; 270 } 271 return n; 272 } 273 274 void 275 Channel::OnPlayTelephoneEvent(int32_t id, 276 uint8_t event, 277 uint16_t lengthMs, 278 uint8_t volume) 279 { 280 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 281 "Channel::OnPlayTelephoneEvent(id=%d, event=%u, lengthMs=%u," 282 " volume=%u)", id, event, lengthMs, volume); 283 284 if (!_playOutbandDtmfEvent || (event > 15)) 285 { 286 // Ignore callback since feedback is disabled or event is not a 287 // Dtmf tone event. 288 return; 289 } 290 291 assert(_outputMixerPtr != NULL); 292 293 // Start playing out the Dtmf tone (if playout is enabled). 294 // Reduce length of tone with 80ms to the reduce risk of echo. 295 _outputMixerPtr->PlayDtmfTone(event, lengthMs - 80, volume); 296 } 297 298 void 299 Channel::OnIncomingSSRCChanged(int32_t id, uint32_t ssrc) 300 { 301 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 302 "Channel::OnIncomingSSRCChanged(id=%d, SSRC=%d)", 303 id, ssrc); 304 305 // Update ssrc so that NTP for AV sync can be updated. 306 _rtpRtcpModule->SetRemoteSSRC(ssrc); 307 } 308 309 void Channel::OnIncomingCSRCChanged(int32_t id, 310 uint32_t CSRC, 311 bool added) 312 { 313 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 314 "Channel::OnIncomingCSRCChanged(id=%d, CSRC=%d, added=%d)", 315 id, CSRC, added); 316 } 317 318 void Channel::ResetStatistics(uint32_t ssrc) { 319 StreamStatistician* statistician = 320 rtp_receive_statistics_->GetStatistician(ssrc); 321 if (statistician) { 322 statistician->ResetStatistics(); 323 } 324 statistics_proxy_->ResetStatistics(); 325 } 326 327 void 328 Channel::OnApplicationDataReceived(int32_t id, 329 uint8_t subType, 330 uint32_t name, 331 uint16_t length, 332 const uint8_t* data) 333 { 334 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 335 "Channel::OnApplicationDataReceived(id=%d, subType=%u," 336 " name=%u, length=%u)", 337 id, subType, name, length); 338 339 int32_t channel = VoEChannelId(id); 340 assert(channel == _channelId); 341 342 if (_rtcpObserver) 343 { 344 CriticalSectionScoped cs(&_callbackCritSect); 345 346 if (_rtcpObserverPtr) 347 { 348 _rtcpObserverPtr->OnApplicationDataReceived(channel, 349 subType, 350 name, 351 data, 352 length); 353 } 354 } 355 } 356 357 int32_t 358 Channel::OnInitializeDecoder( 359 int32_t id, 360 int8_t payloadType, 361 const char payloadName[RTP_PAYLOAD_NAME_SIZE], 362 int frequency, 363 uint8_t channels, 364 uint32_t rate) 365 { 366 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 367 "Channel::OnInitializeDecoder(id=%d, payloadType=%d, " 368 "payloadName=%s, frequency=%u, channels=%u, rate=%u)", 369 id, payloadType, payloadName, frequency, channels, rate); 370 371 assert(VoEChannelId(id) == _channelId); 372 373 CodecInst receiveCodec = {0}; 374 CodecInst dummyCodec = {0}; 375 376 receiveCodec.pltype = payloadType; 377 receiveCodec.plfreq = frequency; 378 receiveCodec.channels = channels; 379 receiveCodec.rate = rate; 380 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 381 382 audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels); 383 receiveCodec.pacsize = dummyCodec.pacsize; 384 385 // Register the new codec to the ACM 386 if (audio_coding_->RegisterReceiveCodec(receiveCodec) == -1) 387 { 388 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 389 VoEId(_instanceId, _channelId), 390 "Channel::OnInitializeDecoder() invalid codec (" 391 "pt=%d, name=%s) received - 1", payloadType, payloadName); 392 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR); 393 return -1; 394 } 395 396 return 0; 397 } 398 399 void 400 Channel::OnPacketTimeout(int32_t id) 401 { 402 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 403 "Channel::OnPacketTimeout(id=%d)", id); 404 405 CriticalSectionScoped cs(_callbackCritSectPtr); 406 if (_voiceEngineObserverPtr) 407 { 408 if (channel_state_.Get().receiving || _externalTransport) 409 { 410 int32_t channel = VoEChannelId(id); 411 assert(channel == _channelId); 412 // Ensure that next OnReceivedPacket() callback will trigger 413 // a VE_PACKET_RECEIPT_RESTARTED callback. 414 _rtpPacketTimedOut = true; 415 // Deliver callback to the observer 416 WEBRTC_TRACE(kTraceInfo, kTraceVoice, 417 VoEId(_instanceId,_channelId), 418 "Channel::OnPacketTimeout() => " 419 "CallbackOnError(VE_RECEIVE_PACKET_TIMEOUT)"); 420 _voiceEngineObserverPtr->CallbackOnError(channel, 421 VE_RECEIVE_PACKET_TIMEOUT); 422 } 423 } 424 } 425 426 void 427 Channel::OnReceivedPacket(int32_t id, 428 RtpRtcpPacketType packetType) 429 { 430 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 431 "Channel::OnReceivedPacket(id=%d, packetType=%d)", 432 id, packetType); 433 434 assert(VoEChannelId(id) == _channelId); 435 436 // Notify only for the case when we have restarted an RTP session. 437 if (_rtpPacketTimedOut && (kPacketRtp == packetType)) 438 { 439 CriticalSectionScoped cs(_callbackCritSectPtr); 440 if (_voiceEngineObserverPtr) 441 { 442 int32_t channel = VoEChannelId(id); 443 assert(channel == _channelId); 444 // Reset timeout mechanism 445 _rtpPacketTimedOut = false; 446 // Deliver callback to the observer 447 WEBRTC_TRACE(kTraceInfo, kTraceVoice, 448 VoEId(_instanceId,_channelId), 449 "Channel::OnPacketTimeout() =>" 450 " CallbackOnError(VE_PACKET_RECEIPT_RESTARTED)"); 451 _voiceEngineObserverPtr->CallbackOnError( 452 channel, 453 VE_PACKET_RECEIPT_RESTARTED); 454 } 455 } 456 } 457 458 void 459 Channel::OnPeriodicDeadOrAlive(int32_t id, 460 RTPAliveType alive) 461 { 462 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 463 "Channel::OnPeriodicDeadOrAlive(id=%d, alive=%d)", id, alive); 464 465 { 466 CriticalSectionScoped cs(&_callbackCritSect); 467 if (!_connectionObserver) 468 return; 469 } 470 471 int32_t channel = VoEChannelId(id); 472 assert(channel == _channelId); 473 474 // Use Alive as default to limit risk of false Dead detections 475 bool isAlive(true); 476 477 // Always mark the connection as Dead when the module reports kRtpDead 478 if (kRtpDead == alive) 479 { 480 isAlive = false; 481 } 482 483 // It is possible that the connection is alive even if no RTP packet has 484 // been received for a long time since the other side might use VAD/DTX 485 // and a low SID-packet update rate. 486 if ((kRtpNoRtp == alive) && channel_state_.Get().playing) 487 { 488 // Detect Alive for all NetEQ states except for the case when we are 489 // in PLC_CNG state. 490 // PLC_CNG <=> background noise only due to long expand or error. 491 // Note that, the case where the other side stops sending during CNG 492 // state will be detected as Alive. Dead is is not set until after 493 // missing RTCP packets for at least twelve seconds (handled 494 // internally by the RTP/RTCP module). 495 isAlive = (_outputSpeechType != AudioFrame::kPLCCNG); 496 } 497 498 // Send callback to the registered observer 499 if (_connectionObserver) 500 { 501 CriticalSectionScoped cs(&_callbackCritSect); 502 if (_connectionObserverPtr) 503 { 504 _connectionObserverPtr->OnPeriodicDeadOrAlive(channel, isAlive); 505 } 506 } 507 } 508 509 int32_t 510 Channel::OnReceivedPayloadData(const uint8_t* payloadData, 511 uint16_t payloadSize, 512 const WebRtcRTPHeader* rtpHeader) 513 { 514 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 515 "Channel::OnReceivedPayloadData(payloadSize=%d," 516 " payloadType=%u, audioChannel=%u)", 517 payloadSize, 518 rtpHeader->header.payloadType, 519 rtpHeader->type.Audio.channel); 520 521 if (!channel_state_.Get().playing) 522 { 523 // Avoid inserting into NetEQ when we are not playing. Count the 524 // packet as discarded. 525 WEBRTC_TRACE(kTraceStream, kTraceVoice, 526 VoEId(_instanceId, _channelId), 527 "received packet is discarded since playing is not" 528 " activated"); 529 _numberOfDiscardedPackets++; 530 return 0; 531 } 532 533 // Push the incoming payload (parsed and ready for decoding) into the ACM 534 if (audio_coding_->IncomingPacket(payloadData, 535 payloadSize, 536 *rtpHeader) != 0) 537 { 538 _engineStatisticsPtr->SetLastError( 539 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning, 540 "Channel::OnReceivedPayloadData() unable to push data to the ACM"); 541 return -1; 542 } 543 544 // Update the packet delay. 545 UpdatePacketDelay(rtpHeader->header.timestamp, 546 rtpHeader->header.sequenceNumber); 547 548 uint16_t round_trip_time = 0; 549 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, 550 NULL, NULL, NULL); 551 552 std::vector<uint16_t> nack_list = audio_coding_->GetNackList( 553 round_trip_time); 554 if (!nack_list.empty()) { 555 // Can't use nack_list.data() since it's not supported by all 556 // compilers. 557 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size())); 558 } 559 return 0; 560 } 561 562 bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet, 563 int rtp_packet_length) { 564 RTPHeader header; 565 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) { 566 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId, 567 "IncomingPacket invalid RTP header"); 568 return false; 569 } 570 header.payload_type_frequency = 571 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType); 572 if (header.payload_type_frequency < 0) 573 return false; 574 return ReceivePacket(rtp_packet, rtp_packet_length, header, false); 575 } 576 577 int32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame) 578 { 579 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 580 "Channel::GetAudioFrame(id=%d)", id); 581 582 // Get 10ms raw PCM data from the ACM (mixer limits output frequency) 583 if (audio_coding_->PlayoutData10Ms(audioFrame.sample_rate_hz_, 584 &audioFrame) == -1) 585 { 586 WEBRTC_TRACE(kTraceError, kTraceVoice, 587 VoEId(_instanceId,_channelId), 588 "Channel::GetAudioFrame() PlayoutData10Ms() failed!"); 589 // In all likelihood, the audio in this frame is garbage. We return an 590 // error so that the audio mixer module doesn't add it to the mix. As 591 // a result, it won't be played out and the actions skipped here are 592 // irrelevant. 593 return -1; 594 } 595 596 if (_RxVadDetection) 597 { 598 UpdateRxVadDetection(audioFrame); 599 } 600 601 // Convert module ID to internal VoE channel ID 602 audioFrame.id_ = VoEChannelId(audioFrame.id_); 603 // Store speech type for dead-or-alive detection 604 _outputSpeechType = audioFrame.speech_type_; 605 606 ChannelState::State state = channel_state_.Get(); 607 608 if (state.rx_apm_is_enabled) { 609 int err = rx_audioproc_->ProcessStream(&audioFrame); 610 if (err) { 611 LOG(LS_ERROR) << "ProcessStream() error: " << err; 612 assert(false); 613 } 614 } 615 616 float output_gain = 1.0f; 617 float left_pan = 1.0f; 618 float right_pan = 1.0f; 619 { 620 CriticalSectionScoped cs(&volume_settings_critsect_); 621 output_gain = _outputGain; 622 left_pan = _panLeft; 623 right_pan= _panRight; 624 } 625 626 // Output volume scaling 627 if (output_gain < 0.99f || output_gain > 1.01f) 628 { 629 AudioFrameOperations::ScaleWithSat(output_gain, audioFrame); 630 } 631 632 // Scale left and/or right channel(s) if stereo and master balance is 633 // active 634 635 if (left_pan != 1.0f || right_pan != 1.0f) 636 { 637 if (audioFrame.num_channels_ == 1) 638 { 639 // Emulate stereo mode since panning is active. 640 // The mono signal is copied to both left and right channels here. 641 AudioFrameOperations::MonoToStereo(&audioFrame); 642 } 643 // For true stereo mode (when we are receiving a stereo signal), no 644 // action is needed. 645 646 // Do the panning operation (the audio frame contains stereo at this 647 // stage) 648 AudioFrameOperations::Scale(left_pan, right_pan, audioFrame); 649 } 650 651 // Mix decoded PCM output with file if file mixing is enabled 652 if (state.output_file_playing) 653 { 654 MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_); 655 } 656 657 // External media 658 if (_outputExternalMedia) 659 { 660 CriticalSectionScoped cs(&_callbackCritSect); 661 const bool isStereo = (audioFrame.num_channels_ == 2); 662 if (_outputExternalMediaCallbackPtr) 663 { 664 _outputExternalMediaCallbackPtr->Process( 665 _channelId, 666 kPlaybackPerChannel, 667 (int16_t*)audioFrame.data_, 668 audioFrame.samples_per_channel_, 669 audioFrame.sample_rate_hz_, 670 isStereo); 671 } 672 } 673 674 // Record playout if enabled 675 { 676 CriticalSectionScoped cs(&_fileCritSect); 677 678 if (_outputFileRecording && _outputFileRecorderPtr) 679 { 680 _outputFileRecorderPtr->RecordAudioToFile(audioFrame); 681 } 682 } 683 684 // Measure audio level (0-9) 685 _outputAudioLevel.ComputeLevel(audioFrame); 686 687 if (capture_start_rtp_time_stamp_ < 0 && audioFrame.timestamp_ != 0) { 688 // The first frame with a valid rtp timestamp. 689 capture_start_rtp_time_stamp_ = audioFrame.timestamp_; 690 } 691 692 if (capture_start_rtp_time_stamp_ >= 0) { 693 // audioFrame.timestamp_ should be valid from now on. 694 695 // Compute elapsed time. 696 int64_t unwrap_timestamp = 697 rtp_ts_wraparound_handler_->Unwrap(audioFrame.timestamp_); 698 audioFrame.elapsed_time_ms_ = 699 (unwrap_timestamp - capture_start_rtp_time_stamp_) / 700 (GetPlayoutFrequency() / 1000); 701 702 // Compute ntp time. 703 audioFrame.ntp_time_ms_ = ntp_estimator_->Estimate(audioFrame.timestamp_); 704 // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received. 705 if (audioFrame.ntp_time_ms_ > 0) { 706 // Compute |capture_start_ntp_time_ms_| so that 707 // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_| 708 CriticalSectionScoped lock(ts_stats_lock_.get()); 709 capture_start_ntp_time_ms_ = 710 audioFrame.ntp_time_ms_ - audioFrame.elapsed_time_ms_; 711 } 712 } 713 714 return 0; 715 } 716 717 int32_t 718 Channel::NeededFrequency(int32_t id) 719 { 720 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 721 "Channel::NeededFrequency(id=%d)", id); 722 723 int highestNeeded = 0; 724 725 // Determine highest needed receive frequency 726 int32_t receiveFrequency = audio_coding_->ReceiveFrequency(); 727 728 // Return the bigger of playout and receive frequency in the ACM. 729 if (audio_coding_->PlayoutFrequency() > receiveFrequency) 730 { 731 highestNeeded = audio_coding_->PlayoutFrequency(); 732 } 733 else 734 { 735 highestNeeded = receiveFrequency; 736 } 737 738 // Special case, if we're playing a file on the playout side 739 // we take that frequency into consideration as well 740 // This is not needed on sending side, since the codec will 741 // limit the spectrum anyway. 742 if (channel_state_.Get().output_file_playing) 743 { 744 CriticalSectionScoped cs(&_fileCritSect); 745 if (_outputFilePlayerPtr) 746 { 747 if(_outputFilePlayerPtr->Frequency()>highestNeeded) 748 { 749 highestNeeded=_outputFilePlayerPtr->Frequency(); 750 } 751 } 752 } 753 754 return(highestNeeded); 755 } 756 757 int32_t 758 Channel::CreateChannel(Channel*& channel, 759 int32_t channelId, 760 uint32_t instanceId, 761 const Config& config) 762 { 763 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId,channelId), 764 "Channel::CreateChannel(channelId=%d, instanceId=%d)", 765 channelId, instanceId); 766 767 channel = new Channel(channelId, instanceId, config); 768 if (channel == NULL) 769 { 770 WEBRTC_TRACE(kTraceMemory, kTraceVoice, 771 VoEId(instanceId,channelId), 772 "Channel::CreateChannel() unable to allocate memory for" 773 " channel"); 774 return -1; 775 } 776 return 0; 777 } 778 779 void 780 Channel::PlayNotification(int32_t id, uint32_t durationMs) 781 { 782 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 783 "Channel::PlayNotification(id=%d, durationMs=%d)", 784 id, durationMs); 785 786 // Not implement yet 787 } 788 789 void 790 Channel::RecordNotification(int32_t id, uint32_t durationMs) 791 { 792 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 793 "Channel::RecordNotification(id=%d, durationMs=%d)", 794 id, durationMs); 795 796 // Not implement yet 797 } 798 799 void 800 Channel::PlayFileEnded(int32_t id) 801 { 802 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 803 "Channel::PlayFileEnded(id=%d)", id); 804 805 if (id == _inputFilePlayerId) 806 { 807 channel_state_.SetInputFilePlaying(false); 808 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 809 VoEId(_instanceId,_channelId), 810 "Channel::PlayFileEnded() => input file player module is" 811 " shutdown"); 812 } 813 else if (id == _outputFilePlayerId) 814 { 815 channel_state_.SetOutputFilePlaying(false); 816 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 817 VoEId(_instanceId,_channelId), 818 "Channel::PlayFileEnded() => output file player module is" 819 " shutdown"); 820 } 821 } 822 823 void 824 Channel::RecordFileEnded(int32_t id) 825 { 826 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 827 "Channel::RecordFileEnded(id=%d)", id); 828 829 assert(id == _outputFileRecorderId); 830 831 CriticalSectionScoped cs(&_fileCritSect); 832 833 _outputFileRecording = false; 834 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 835 VoEId(_instanceId,_channelId), 836 "Channel::RecordFileEnded() => output file recorder module is" 837 " shutdown"); 838 } 839 840 Channel::Channel(int32_t channelId, 841 uint32_t instanceId, 842 const Config& config) : 843 _fileCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 844 _callbackCritSect(*CriticalSectionWrapper::CreateCriticalSection()), 845 volume_settings_critsect_(*CriticalSectionWrapper::CreateCriticalSection()), 846 _instanceId(instanceId), 847 _channelId(channelId), 848 rtp_header_parser_(RtpHeaderParser::Create()), 849 rtp_payload_registry_( 850 new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))), 851 rtp_receive_statistics_(ReceiveStatistics::Create( 852 Clock::GetRealTimeClock())), 853 rtp_receiver_(RtpReceiver::CreateAudioReceiver( 854 VoEModuleId(instanceId, channelId), Clock::GetRealTimeClock(), this, 855 this, this, rtp_payload_registry_.get())), 856 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()), 857 audio_coding_(AudioCodingModule::Create( 858 VoEModuleId(instanceId, channelId))), 859 _rtpDumpIn(*RtpDump::CreateRtpDump()), 860 _rtpDumpOut(*RtpDump::CreateRtpDump()), 861 _outputAudioLevel(), 862 _externalTransport(false), 863 _audioLevel_dBov(0), 864 _inputFilePlayerPtr(NULL), 865 _outputFilePlayerPtr(NULL), 866 _outputFileRecorderPtr(NULL), 867 // Avoid conflict with other channels by adding 1024 - 1026, 868 // won't use as much as 1024 channels. 869 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024), 870 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025), 871 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026), 872 _outputFileRecording(false), 873 _inbandDtmfQueue(VoEModuleId(instanceId, channelId)), 874 _inbandDtmfGenerator(VoEModuleId(instanceId, channelId)), 875 _outputExternalMedia(false), 876 _inputExternalMediaCallbackPtr(NULL), 877 _outputExternalMediaCallbackPtr(NULL), 878 _timeStamp(0), // This is just an offset, RTP module will add it's own random offset 879 _sendTelephoneEventPayloadType(106), 880 ntp_estimator_(new RemoteNtpTimeEstimator(Clock::GetRealTimeClock())), 881 jitter_buffer_playout_timestamp_(0), 882 playout_timestamp_rtp_(0), 883 playout_timestamp_rtcp_(0), 884 playout_delay_ms_(0), 885 _numberOfDiscardedPackets(0), 886 send_sequence_number_(0), 887 ts_stats_lock_(CriticalSectionWrapper::CreateCriticalSection()), 888 rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()), 889 capture_start_rtp_time_stamp_(-1), 890 capture_start_ntp_time_ms_(-1), 891 _engineStatisticsPtr(NULL), 892 _outputMixerPtr(NULL), 893 _transmitMixerPtr(NULL), 894 _moduleProcessThreadPtr(NULL), 895 _audioDeviceModulePtr(NULL), 896 _voiceEngineObserverPtr(NULL), 897 _callbackCritSectPtr(NULL), 898 _transportPtr(NULL), 899 _rxVadObserverPtr(NULL), 900 _oldVadDecision(-1), 901 _sendFrameType(0), 902 _rtcpObserverPtr(NULL), 903 _externalPlayout(false), 904 _externalMixing(false), 905 _mixFileWithMicrophone(false), 906 _rtcpObserver(false), 907 _mute(false), 908 _panLeft(1.0f), 909 _panRight(1.0f), 910 _outputGain(1.0f), 911 _playOutbandDtmfEvent(false), 912 _playInbandDtmfEvent(false), 913 _lastLocalTimeStamp(0), 914 _lastPayloadType(0), 915 _includeAudioLevelIndication(false), 916 _rtpPacketTimedOut(false), 917 _rtpPacketTimeOutIsEnabled(false), 918 _rtpTimeOutSeconds(0), 919 _connectionObserver(false), 920 _connectionObserverPtr(NULL), 921 _outputSpeechType(AudioFrame::kNormalSpeech), 922 vie_network_(NULL), 923 video_channel_(-1), 924 _average_jitter_buffer_delay_us(0), 925 least_required_delay_ms_(0), 926 _previousTimestamp(0), 927 _recPacketDelayMs(20), 928 _RxVadDetection(false), 929 _rxAgcIsEnabled(false), 930 _rxNsIsEnabled(false), 931 restored_packet_in_use_(false), 932 bitrate_controller_( 933 BitrateController::CreateBitrateController(Clock::GetRealTimeClock(), 934 true)), 935 rtcp_bandwidth_observer_( 936 bitrate_controller_->CreateRtcpBandwidthObserver()), 937 send_bitrate_observer_(new VoEBitrateObserver(this)) 938 { 939 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), 940 "Channel::Channel() - ctor"); 941 _inbandDtmfQueue.ResetDtmf(); 942 _inbandDtmfGenerator.Init(); 943 _outputAudioLevel.Clear(); 944 945 RtpRtcp::Configuration configuration; 946 configuration.id = VoEModuleId(instanceId, channelId); 947 configuration.audio = true; 948 configuration.outgoing_transport = this; 949 configuration.rtcp_feedback = this; 950 configuration.audio_messages = this; 951 configuration.receive_statistics = rtp_receive_statistics_.get(); 952 configuration.bandwidth_callback = rtcp_bandwidth_observer_.get(); 953 954 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration)); 955 956 statistics_proxy_.reset(new StatisticsProxy(_rtpRtcpModule->SSRC())); 957 rtp_receive_statistics_->RegisterRtcpStatisticsCallback( 958 statistics_proxy_.get()); 959 960 Config audioproc_config; 961 audioproc_config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 962 rx_audioproc_.reset(AudioProcessing::Create(audioproc_config)); 963 } 964 965 Channel::~Channel() 966 { 967 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL); 968 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId,_channelId), 969 "Channel::~Channel() - dtor"); 970 971 if (_outputExternalMedia) 972 { 973 DeRegisterExternalMediaProcessing(kPlaybackPerChannel); 974 } 975 if (channel_state_.Get().input_external_media) 976 { 977 DeRegisterExternalMediaProcessing(kRecordingPerChannel); 978 } 979 StopSend(); 980 StopPlayout(); 981 982 { 983 CriticalSectionScoped cs(&_fileCritSect); 984 if (_inputFilePlayerPtr) 985 { 986 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 987 _inputFilePlayerPtr->StopPlayingFile(); 988 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 989 _inputFilePlayerPtr = NULL; 990 } 991 if (_outputFilePlayerPtr) 992 { 993 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 994 _outputFilePlayerPtr->StopPlayingFile(); 995 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 996 _outputFilePlayerPtr = NULL; 997 } 998 if (_outputFileRecorderPtr) 999 { 1000 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 1001 _outputFileRecorderPtr->StopRecording(); 1002 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 1003 _outputFileRecorderPtr = NULL; 1004 } 1005 } 1006 1007 // The order to safely shutdown modules in a channel is: 1008 // 1. De-register callbacks in modules 1009 // 2. De-register modules in process thread 1010 // 3. Destroy modules 1011 if (audio_coding_->RegisterTransportCallback(NULL) == -1) 1012 { 1013 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1014 VoEId(_instanceId,_channelId), 1015 "~Channel() failed to de-register transport callback" 1016 " (Audio coding module)"); 1017 } 1018 if (audio_coding_->RegisterVADCallback(NULL) == -1) 1019 { 1020 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1021 VoEId(_instanceId,_channelId), 1022 "~Channel() failed to de-register VAD callback" 1023 " (Audio coding module)"); 1024 } 1025 // De-register modules in process thread 1026 if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1) 1027 { 1028 WEBRTC_TRACE(kTraceInfo, kTraceVoice, 1029 VoEId(_instanceId,_channelId), 1030 "~Channel() failed to deregister RTP/RTCP module"); 1031 } 1032 // End of modules shutdown 1033 1034 // Delete other objects 1035 if (vie_network_) { 1036 vie_network_->Release(); 1037 vie_network_ = NULL; 1038 } 1039 RtpDump::DestroyRtpDump(&_rtpDumpIn); 1040 RtpDump::DestroyRtpDump(&_rtpDumpOut); 1041 delete &_callbackCritSect; 1042 delete &_fileCritSect; 1043 delete &volume_settings_critsect_; 1044 } 1045 1046 int32_t 1047 Channel::Init() 1048 { 1049 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1050 "Channel::Init()"); 1051 1052 channel_state_.Reset(); 1053 1054 // --- Initial sanity 1055 1056 if ((_engineStatisticsPtr == NULL) || 1057 (_moduleProcessThreadPtr == NULL)) 1058 { 1059 WEBRTC_TRACE(kTraceError, kTraceVoice, 1060 VoEId(_instanceId,_channelId), 1061 "Channel::Init() must call SetEngineInformation() first"); 1062 return -1; 1063 } 1064 1065 // --- Add modules to process thread (for periodic schedulation) 1066 1067 const bool processThreadFail = 1068 ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) || 1069 false); 1070 if (processThreadFail) 1071 { 1072 _engineStatisticsPtr->SetLastError( 1073 VE_CANNOT_INIT_CHANNEL, kTraceError, 1074 "Channel::Init() modules not registered"); 1075 return -1; 1076 } 1077 // --- ACM initialization 1078 1079 if ((audio_coding_->InitializeReceiver() == -1) || 1080 #ifdef WEBRTC_CODEC_AVT 1081 // out-of-band Dtmf tones are played out by default 1082 (audio_coding_->SetDtmfPlayoutStatus(true) == -1) || 1083 #endif 1084 (audio_coding_->InitializeSender() == -1)) 1085 { 1086 _engineStatisticsPtr->SetLastError( 1087 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1088 "Channel::Init() unable to initialize the ACM - 1"); 1089 return -1; 1090 } 1091 1092 // --- RTP/RTCP module initialization 1093 1094 // Ensure that RTCP is enabled by default for the created channel. 1095 // Note that, the module will keep generating RTCP until it is explicitly 1096 // disabled by the user. 1097 // After StopListen (when no sockets exists), RTCP packets will no longer 1098 // be transmitted since the Transport object will then be invalid. 1099 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true); 1100 // RTCP is enabled by default. 1101 if (_rtpRtcpModule->SetRTCPStatus(kRtcpCompound) == -1) 1102 { 1103 _engineStatisticsPtr->SetLastError( 1104 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1105 "Channel::Init() RTP/RTCP module not initialized"); 1106 return -1; 1107 } 1108 1109 // --- Register all permanent callbacks 1110 const bool fail = 1111 (audio_coding_->RegisterTransportCallback(this) == -1) || 1112 (audio_coding_->RegisterVADCallback(this) == -1); 1113 1114 if (fail) 1115 { 1116 _engineStatisticsPtr->SetLastError( 1117 VE_CANNOT_INIT_CHANNEL, kTraceError, 1118 "Channel::Init() callbacks not registered"); 1119 return -1; 1120 } 1121 1122 // --- Register all supported codecs to the receiving side of the 1123 // RTP/RTCP module 1124 1125 CodecInst codec; 1126 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs(); 1127 1128 for (int idx = 0; idx < nSupportedCodecs; idx++) 1129 { 1130 // Open up the RTP/RTCP receiver for all supported codecs 1131 if ((audio_coding_->Codec(idx, &codec) == -1) || 1132 (rtp_receiver_->RegisterReceivePayload( 1133 codec.plname, 1134 codec.pltype, 1135 codec.plfreq, 1136 codec.channels, 1137 (codec.rate < 0) ? 0 : codec.rate) == -1)) 1138 { 1139 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1140 VoEId(_instanceId,_channelId), 1141 "Channel::Init() unable to register %s (%d/%d/%d/%d) " 1142 "to RTP/RTCP receiver", 1143 codec.plname, codec.pltype, codec.plfreq, 1144 codec.channels, codec.rate); 1145 } 1146 else 1147 { 1148 WEBRTC_TRACE(kTraceInfo, kTraceVoice, 1149 VoEId(_instanceId,_channelId), 1150 "Channel::Init() %s (%d/%d/%d/%d) has been added to " 1151 "the RTP/RTCP receiver", 1152 codec.plname, codec.pltype, codec.plfreq, 1153 codec.channels, codec.rate); 1154 } 1155 1156 // Ensure that PCMU is used as default codec on the sending side 1157 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) 1158 { 1159 SetSendCodec(codec); 1160 } 1161 1162 // Register default PT for outband 'telephone-event' 1163 if (!STR_CASE_CMP(codec.plname, "telephone-event")) 1164 { 1165 if ((_rtpRtcpModule->RegisterSendPayload(codec) == -1) || 1166 (audio_coding_->RegisterReceiveCodec(codec) == -1)) 1167 { 1168 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1169 VoEId(_instanceId,_channelId), 1170 "Channel::Init() failed to register outband " 1171 "'telephone-event' (%d/%d) correctly", 1172 codec.pltype, codec.plfreq); 1173 } 1174 } 1175 1176 if (!STR_CASE_CMP(codec.plname, "CN")) 1177 { 1178 if ((audio_coding_->RegisterSendCodec(codec) == -1) || 1179 (audio_coding_->RegisterReceiveCodec(codec) == -1) || 1180 (_rtpRtcpModule->RegisterSendPayload(codec) == -1)) 1181 { 1182 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1183 VoEId(_instanceId,_channelId), 1184 "Channel::Init() failed to register CN (%d/%d) " 1185 "correctly - 1", 1186 codec.pltype, codec.plfreq); 1187 } 1188 } 1189 #ifdef WEBRTC_CODEC_RED 1190 // Register RED to the receiving side of the ACM. 1191 // We will not receive an OnInitializeDecoder() callback for RED. 1192 if (!STR_CASE_CMP(codec.plname, "RED")) 1193 { 1194 if (audio_coding_->RegisterReceiveCodec(codec) == -1) 1195 { 1196 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1197 VoEId(_instanceId,_channelId), 1198 "Channel::Init() failed to register RED (%d/%d) " 1199 "correctly", 1200 codec.pltype, codec.plfreq); 1201 } 1202 } 1203 #endif 1204 } 1205 1206 if (rx_audioproc_->noise_suppression()->set_level(kDefaultNsMode) != 0) { 1207 LOG_FERR1(LS_ERROR, noise_suppression()->set_level, kDefaultNsMode); 1208 return -1; 1209 } 1210 if (rx_audioproc_->gain_control()->set_mode(kDefaultRxAgcMode) != 0) { 1211 LOG_FERR1(LS_ERROR, gain_control()->set_mode, kDefaultRxAgcMode); 1212 return -1; 1213 } 1214 1215 return 0; 1216 } 1217 1218 int32_t 1219 Channel::SetEngineInformation(Statistics& engineStatistics, 1220 OutputMixer& outputMixer, 1221 voe::TransmitMixer& transmitMixer, 1222 ProcessThread& moduleProcessThread, 1223 AudioDeviceModule& audioDeviceModule, 1224 VoiceEngineObserver* voiceEngineObserver, 1225 CriticalSectionWrapper* callbackCritSect) 1226 { 1227 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1228 "Channel::SetEngineInformation()"); 1229 _engineStatisticsPtr = &engineStatistics; 1230 _outputMixerPtr = &outputMixer; 1231 _transmitMixerPtr = &transmitMixer, 1232 _moduleProcessThreadPtr = &moduleProcessThread; 1233 _audioDeviceModulePtr = &audioDeviceModule; 1234 _voiceEngineObserverPtr = voiceEngineObserver; 1235 _callbackCritSectPtr = callbackCritSect; 1236 return 0; 1237 } 1238 1239 int32_t 1240 Channel::UpdateLocalTimeStamp() 1241 { 1242 1243 _timeStamp += _audioFrame.samples_per_channel_; 1244 return 0; 1245 } 1246 1247 int32_t 1248 Channel::StartPlayout() 1249 { 1250 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1251 "Channel::StartPlayout()"); 1252 if (channel_state_.Get().playing) 1253 { 1254 return 0; 1255 } 1256 1257 if (!_externalMixing) { 1258 // Add participant as candidates for mixing. 1259 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) 1260 { 1261 _engineStatisticsPtr->SetLastError( 1262 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 1263 "StartPlayout() failed to add participant to mixer"); 1264 return -1; 1265 } 1266 } 1267 1268 channel_state_.SetPlaying(true); 1269 if (RegisterFilePlayingToMixer() != 0) 1270 return -1; 1271 1272 return 0; 1273 } 1274 1275 int32_t 1276 Channel::StopPlayout() 1277 { 1278 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1279 "Channel::StopPlayout()"); 1280 if (!channel_state_.Get().playing) 1281 { 1282 return 0; 1283 } 1284 1285 if (!_externalMixing) { 1286 // Remove participant as candidates for mixing 1287 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) 1288 { 1289 _engineStatisticsPtr->SetLastError( 1290 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 1291 "StopPlayout() failed to remove participant from mixer"); 1292 return -1; 1293 } 1294 } 1295 1296 channel_state_.SetPlaying(false); 1297 _outputAudioLevel.Clear(); 1298 1299 return 0; 1300 } 1301 1302 int32_t 1303 Channel::StartSend() 1304 { 1305 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1306 "Channel::StartSend()"); 1307 // Resume the previous sequence number which was reset by StopSend(). 1308 // This needs to be done before |sending| is set to true. 1309 if (send_sequence_number_) 1310 SetInitSequenceNumber(send_sequence_number_); 1311 1312 if (channel_state_.Get().sending) 1313 { 1314 return 0; 1315 } 1316 channel_state_.SetSending(true); 1317 1318 if (_rtpRtcpModule->SetSendingStatus(true) != 0) 1319 { 1320 _engineStatisticsPtr->SetLastError( 1321 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1322 "StartSend() RTP/RTCP failed to start sending"); 1323 CriticalSectionScoped cs(&_callbackCritSect); 1324 channel_state_.SetSending(false); 1325 return -1; 1326 } 1327 1328 return 0; 1329 } 1330 1331 int32_t 1332 Channel::StopSend() 1333 { 1334 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1335 "Channel::StopSend()"); 1336 if (!channel_state_.Get().sending) 1337 { 1338 return 0; 1339 } 1340 channel_state_.SetSending(false); 1341 1342 // Store the sequence number to be able to pick up the same sequence for 1343 // the next StartSend(). This is needed for restarting device, otherwise 1344 // it might cause libSRTP to complain about packets being replayed. 1345 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring 1346 // CL is landed. See issue 1347 // https://code.google.com/p/webrtc/issues/detail?id=2111 . 1348 send_sequence_number_ = _rtpRtcpModule->SequenceNumber(); 1349 1350 // Reset sending SSRC and sequence number and triggers direct transmission 1351 // of RTCP BYE 1352 if (_rtpRtcpModule->SetSendingStatus(false) == -1 || 1353 _rtpRtcpModule->ResetSendDataCountersRTP() == -1) 1354 { 1355 _engineStatisticsPtr->SetLastError( 1356 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 1357 "StartSend() RTP/RTCP failed to stop sending"); 1358 } 1359 1360 return 0; 1361 } 1362 1363 int32_t 1364 Channel::StartReceiving() 1365 { 1366 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1367 "Channel::StartReceiving()"); 1368 if (channel_state_.Get().receiving) 1369 { 1370 return 0; 1371 } 1372 channel_state_.SetReceiving(true); 1373 _numberOfDiscardedPackets = 0; 1374 return 0; 1375 } 1376 1377 int32_t 1378 Channel::StopReceiving() 1379 { 1380 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1381 "Channel::StopReceiving()"); 1382 if (!channel_state_.Get().receiving) 1383 { 1384 return 0; 1385 } 1386 1387 channel_state_.SetReceiving(false); 1388 return 0; 1389 } 1390 1391 int32_t 1392 Channel::SetNetEQPlayoutMode(NetEqModes mode) 1393 { 1394 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1395 "Channel::SetNetEQPlayoutMode()"); 1396 AudioPlayoutMode playoutMode(voice); 1397 switch (mode) 1398 { 1399 case kNetEqDefault: 1400 playoutMode = voice; 1401 break; 1402 case kNetEqStreaming: 1403 playoutMode = streaming; 1404 break; 1405 case kNetEqFax: 1406 playoutMode = fax; 1407 break; 1408 case kNetEqOff: 1409 playoutMode = off; 1410 break; 1411 } 1412 if (audio_coding_->SetPlayoutMode(playoutMode) != 0) 1413 { 1414 _engineStatisticsPtr->SetLastError( 1415 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1416 "SetNetEQPlayoutMode() failed to set playout mode"); 1417 return -1; 1418 } 1419 return 0; 1420 } 1421 1422 int32_t 1423 Channel::GetNetEQPlayoutMode(NetEqModes& mode) 1424 { 1425 const AudioPlayoutMode playoutMode = audio_coding_->PlayoutMode(); 1426 switch (playoutMode) 1427 { 1428 case voice: 1429 mode = kNetEqDefault; 1430 break; 1431 case streaming: 1432 mode = kNetEqStreaming; 1433 break; 1434 case fax: 1435 mode = kNetEqFax; 1436 break; 1437 case off: 1438 mode = kNetEqOff; 1439 } 1440 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 1441 VoEId(_instanceId,_channelId), 1442 "Channel::GetNetEQPlayoutMode() => mode=%u", mode); 1443 return 0; 1444 } 1445 1446 int32_t 1447 Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) 1448 { 1449 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1450 "Channel::RegisterVoiceEngineObserver()"); 1451 CriticalSectionScoped cs(&_callbackCritSect); 1452 1453 if (_voiceEngineObserverPtr) 1454 { 1455 _engineStatisticsPtr->SetLastError( 1456 VE_INVALID_OPERATION, kTraceError, 1457 "RegisterVoiceEngineObserver() observer already enabled"); 1458 return -1; 1459 } 1460 _voiceEngineObserverPtr = &observer; 1461 return 0; 1462 } 1463 1464 int32_t 1465 Channel::DeRegisterVoiceEngineObserver() 1466 { 1467 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1468 "Channel::DeRegisterVoiceEngineObserver()"); 1469 CriticalSectionScoped cs(&_callbackCritSect); 1470 1471 if (!_voiceEngineObserverPtr) 1472 { 1473 _engineStatisticsPtr->SetLastError( 1474 VE_INVALID_OPERATION, kTraceWarning, 1475 "DeRegisterVoiceEngineObserver() observer already disabled"); 1476 return 0; 1477 } 1478 _voiceEngineObserverPtr = NULL; 1479 return 0; 1480 } 1481 1482 int32_t 1483 Channel::GetSendCodec(CodecInst& codec) 1484 { 1485 return (audio_coding_->SendCodec(&codec)); 1486 } 1487 1488 int32_t 1489 Channel::GetRecCodec(CodecInst& codec) 1490 { 1491 return (audio_coding_->ReceiveCodec(&codec)); 1492 } 1493 1494 int32_t 1495 Channel::SetSendCodec(const CodecInst& codec) 1496 { 1497 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1498 "Channel::SetSendCodec()"); 1499 1500 if (audio_coding_->RegisterSendCodec(codec) != 0) 1501 { 1502 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1503 "SetSendCodec() failed to register codec to ACM"); 1504 return -1; 1505 } 1506 1507 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1508 { 1509 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 1510 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1511 { 1512 WEBRTC_TRACE( 1513 kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1514 "SetSendCodec() failed to register codec to" 1515 " RTP/RTCP module"); 1516 return -1; 1517 } 1518 } 1519 1520 if (_rtpRtcpModule->SetAudioPacketSize(codec.pacsize) != 0) 1521 { 1522 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 1523 "SetSendCodec() failed to set audio packet size"); 1524 return -1; 1525 } 1526 1527 bitrate_controller_->SetBitrateObserver(send_bitrate_observer_.get(), 1528 codec.rate, 0, 0); 1529 1530 return 0; 1531 } 1532 1533 void 1534 Channel::OnNetworkChanged(const uint32_t bitrate_bps, 1535 const uint8_t fraction_lost, // 0 - 255. 1536 const uint32_t rtt) { 1537 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1538 "Channel::OnNetworkChanged(bitrate_bps=%d, fration_lost=%d, rtt=%d)", 1539 bitrate_bps, fraction_lost, rtt); 1540 // Normalizes rate to 0 - 100. 1541 if (audio_coding_->SetPacketLossRate(100 * fraction_lost / 255) != 0) { 1542 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR, 1543 kTraceError, "OnNetworkChanged() failed to set packet loss rate"); 1544 assert(false); // This should not happen. 1545 } 1546 } 1547 1548 int32_t 1549 Channel::SetVADStatus(bool enableVAD, ACMVADMode mode, bool disableDTX) 1550 { 1551 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1552 "Channel::SetVADStatus(mode=%d)", mode); 1553 // To disable VAD, DTX must be disabled too 1554 disableDTX = ((enableVAD == false) ? true : disableDTX); 1555 if (audio_coding_->SetVAD(!disableDTX, enableVAD, mode) != 0) 1556 { 1557 _engineStatisticsPtr->SetLastError( 1558 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1559 "SetVADStatus() failed to set VAD"); 1560 return -1; 1561 } 1562 return 0; 1563 } 1564 1565 int32_t 1566 Channel::GetVADStatus(bool& enabledVAD, ACMVADMode& mode, bool& disabledDTX) 1567 { 1568 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1569 "Channel::GetVADStatus"); 1570 if (audio_coding_->VAD(&disabledDTX, &enabledVAD, &mode) != 0) 1571 { 1572 _engineStatisticsPtr->SetLastError( 1573 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1574 "GetVADStatus() failed to get VAD status"); 1575 return -1; 1576 } 1577 disabledDTX = !disabledDTX; 1578 return 0; 1579 } 1580 1581 int32_t 1582 Channel::SetRecPayloadType(const CodecInst& codec) 1583 { 1584 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1585 "Channel::SetRecPayloadType()"); 1586 1587 if (channel_state_.Get().playing) 1588 { 1589 _engineStatisticsPtr->SetLastError( 1590 VE_ALREADY_PLAYING, kTraceError, 1591 "SetRecPayloadType() unable to set PT while playing"); 1592 return -1; 1593 } 1594 if (channel_state_.Get().receiving) 1595 { 1596 _engineStatisticsPtr->SetLastError( 1597 VE_ALREADY_LISTENING, kTraceError, 1598 "SetRecPayloadType() unable to set PT while listening"); 1599 return -1; 1600 } 1601 1602 if (codec.pltype == -1) 1603 { 1604 // De-register the selected codec (RTP/RTCP module and ACM) 1605 1606 int8_t pltype(-1); 1607 CodecInst rxCodec = codec; 1608 1609 // Get payload type for the given codec 1610 rtp_payload_registry_->ReceivePayloadType( 1611 rxCodec.plname, 1612 rxCodec.plfreq, 1613 rxCodec.channels, 1614 (rxCodec.rate < 0) ? 0 : rxCodec.rate, 1615 &pltype); 1616 rxCodec.pltype = pltype; 1617 1618 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) 1619 { 1620 _engineStatisticsPtr->SetLastError( 1621 VE_RTP_RTCP_MODULE_ERROR, 1622 kTraceError, 1623 "SetRecPayloadType() RTP/RTCP-module deregistration " 1624 "failed"); 1625 return -1; 1626 } 1627 if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) 1628 { 1629 _engineStatisticsPtr->SetLastError( 1630 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1631 "SetRecPayloadType() ACM deregistration failed - 1"); 1632 return -1; 1633 } 1634 return 0; 1635 } 1636 1637 if (rtp_receiver_->RegisterReceivePayload( 1638 codec.plname, 1639 codec.pltype, 1640 codec.plfreq, 1641 codec.channels, 1642 (codec.rate < 0) ? 0 : codec.rate) != 0) 1643 { 1644 // First attempt to register failed => de-register and try again 1645 rtp_receiver_->DeRegisterReceivePayload(codec.pltype); 1646 if (rtp_receiver_->RegisterReceivePayload( 1647 codec.plname, 1648 codec.pltype, 1649 codec.plfreq, 1650 codec.channels, 1651 (codec.rate < 0) ? 0 : codec.rate) != 0) 1652 { 1653 _engineStatisticsPtr->SetLastError( 1654 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1655 "SetRecPayloadType() RTP/RTCP-module registration failed"); 1656 return -1; 1657 } 1658 } 1659 if (audio_coding_->RegisterReceiveCodec(codec) != 0) 1660 { 1661 audio_coding_->UnregisterReceiveCodec(codec.pltype); 1662 if (audio_coding_->RegisterReceiveCodec(codec) != 0) 1663 { 1664 _engineStatisticsPtr->SetLastError( 1665 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1666 "SetRecPayloadType() ACM registration failed - 1"); 1667 return -1; 1668 } 1669 } 1670 return 0; 1671 } 1672 1673 int32_t 1674 Channel::GetRecPayloadType(CodecInst& codec) 1675 { 1676 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1677 "Channel::GetRecPayloadType()"); 1678 int8_t payloadType(-1); 1679 if (rtp_payload_registry_->ReceivePayloadType( 1680 codec.plname, 1681 codec.plfreq, 1682 codec.channels, 1683 (codec.rate < 0) ? 0 : codec.rate, 1684 &payloadType) != 0) 1685 { 1686 _engineStatisticsPtr->SetLastError( 1687 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning, 1688 "GetRecPayloadType() failed to retrieve RX payload type"); 1689 return -1; 1690 } 1691 codec.pltype = payloadType; 1692 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1693 "Channel::GetRecPayloadType() => pltype=%u", codec.pltype); 1694 return 0; 1695 } 1696 1697 int32_t 1698 Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) 1699 { 1700 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1701 "Channel::SetSendCNPayloadType()"); 1702 1703 CodecInst codec; 1704 int32_t samplingFreqHz(-1); 1705 const int kMono = 1; 1706 if (frequency == kFreq32000Hz) 1707 samplingFreqHz = 32000; 1708 else if (frequency == kFreq16000Hz) 1709 samplingFreqHz = 16000; 1710 1711 if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) 1712 { 1713 _engineStatisticsPtr->SetLastError( 1714 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1715 "SetSendCNPayloadType() failed to retrieve default CN codec " 1716 "settings"); 1717 return -1; 1718 } 1719 1720 // Modify the payload type (must be set to dynamic range) 1721 codec.pltype = type; 1722 1723 if (audio_coding_->RegisterSendCodec(codec) != 0) 1724 { 1725 _engineStatisticsPtr->SetLastError( 1726 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 1727 "SetSendCNPayloadType() failed to register CN to ACM"); 1728 return -1; 1729 } 1730 1731 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1732 { 1733 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 1734 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 1735 { 1736 _engineStatisticsPtr->SetLastError( 1737 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 1738 "SetSendCNPayloadType() failed to register CN to RTP/RTCP " 1739 "module"); 1740 return -1; 1741 } 1742 } 1743 return 0; 1744 } 1745 1746 int32_t Channel::RegisterExternalTransport(Transport& transport) 1747 { 1748 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 1749 "Channel::RegisterExternalTransport()"); 1750 1751 CriticalSectionScoped cs(&_callbackCritSect); 1752 1753 if (_externalTransport) 1754 { 1755 _engineStatisticsPtr->SetLastError(VE_INVALID_OPERATION, 1756 kTraceError, 1757 "RegisterExternalTransport() external transport already enabled"); 1758 return -1; 1759 } 1760 _externalTransport = true; 1761 _transportPtr = &transport; 1762 return 0; 1763 } 1764 1765 int32_t 1766 Channel::DeRegisterExternalTransport() 1767 { 1768 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1769 "Channel::DeRegisterExternalTransport()"); 1770 1771 CriticalSectionScoped cs(&_callbackCritSect); 1772 1773 if (!_transportPtr) 1774 { 1775 _engineStatisticsPtr->SetLastError( 1776 VE_INVALID_OPERATION, kTraceWarning, 1777 "DeRegisterExternalTransport() external transport already " 1778 "disabled"); 1779 return 0; 1780 } 1781 _externalTransport = false; 1782 _transportPtr = NULL; 1783 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1784 "DeRegisterExternalTransport() all transport is disabled"); 1785 return 0; 1786 } 1787 1788 int32_t Channel::ReceivedRTPPacket(const int8_t* data, int32_t length, 1789 const PacketTime& packet_time) { 1790 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 1791 "Channel::ReceivedRTPPacket()"); 1792 1793 // Store playout timestamp for the received RTP packet 1794 UpdatePlayoutTimestamp(false); 1795 1796 // Dump the RTP packet to a file (if RTP dump is enabled). 1797 if (_rtpDumpIn.DumpPacket((const uint8_t*)data, 1798 (uint16_t)length) == -1) { 1799 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1800 VoEId(_instanceId,_channelId), 1801 "Channel::SendPacket() RTP dump to input file failed"); 1802 } 1803 const uint8_t* received_packet = reinterpret_cast<const uint8_t*>(data); 1804 RTPHeader header; 1805 if (!rtp_header_parser_->Parse(received_packet, length, &header)) { 1806 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 1807 "Incoming packet: invalid RTP header"); 1808 return -1; 1809 } 1810 header.payload_type_frequency = 1811 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType); 1812 if (header.payload_type_frequency < 0) 1813 return -1; 1814 bool in_order = IsPacketInOrder(header); 1815 rtp_receive_statistics_->IncomingPacket(header, length, 1816 IsPacketRetransmitted(header, in_order)); 1817 rtp_payload_registry_->SetIncomingPayloadType(header); 1818 1819 // Forward any packets to ViE bandwidth estimator, if enabled. 1820 { 1821 CriticalSectionScoped cs(&_callbackCritSect); 1822 if (vie_network_) { 1823 int64_t arrival_time_ms; 1824 if (packet_time.timestamp != -1) { 1825 arrival_time_ms = (packet_time.timestamp + 500) / 1000; 1826 } else { 1827 arrival_time_ms = TickTime::MillisecondTimestamp(); 1828 } 1829 int payload_length = length - header.headerLength; 1830 vie_network_->ReceivedBWEPacket(video_channel_, arrival_time_ms, 1831 payload_length, header); 1832 } 1833 } 1834 1835 return ReceivePacket(received_packet, length, header, in_order) ? 0 : -1; 1836 } 1837 1838 bool Channel::ReceivePacket(const uint8_t* packet, 1839 int packet_length, 1840 const RTPHeader& header, 1841 bool in_order) { 1842 if (rtp_payload_registry_->IsEncapsulated(header)) { 1843 return HandleEncapsulation(packet, packet_length, header); 1844 } 1845 const uint8_t* payload = packet + header.headerLength; 1846 int payload_length = packet_length - header.headerLength; 1847 assert(payload_length >= 0); 1848 PayloadUnion payload_specific; 1849 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, 1850 &payload_specific)) { 1851 return false; 1852 } 1853 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length, 1854 payload_specific, in_order); 1855 } 1856 1857 bool Channel::HandleEncapsulation(const uint8_t* packet, 1858 int packet_length, 1859 const RTPHeader& header) { 1860 if (!rtp_payload_registry_->IsRtx(header)) 1861 return false; 1862 1863 // Remove the RTX header and parse the original RTP header. 1864 if (packet_length < header.headerLength) 1865 return false; 1866 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes) 1867 return false; 1868 if (restored_packet_in_use_) { 1869 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 1870 "Multiple RTX headers detected, dropping packet"); 1871 return false; 1872 } 1873 uint8_t* restored_packet_ptr = restored_packet_; 1874 if (!rtp_payload_registry_->RestoreOriginalPacket( 1875 &restored_packet_ptr, packet, &packet_length, rtp_receiver_->SSRC(), 1876 header)) { 1877 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId, 1878 "Incoming RTX packet: invalid RTP header"); 1879 return false; 1880 } 1881 restored_packet_in_use_ = true; 1882 bool ret = OnRecoveredPacket(restored_packet_ptr, packet_length); 1883 restored_packet_in_use_ = false; 1884 return ret; 1885 } 1886 1887 bool Channel::IsPacketInOrder(const RTPHeader& header) const { 1888 StreamStatistician* statistician = 1889 rtp_receive_statistics_->GetStatistician(header.ssrc); 1890 if (!statistician) 1891 return false; 1892 return statistician->IsPacketInOrder(header.sequenceNumber); 1893 } 1894 1895 bool Channel::IsPacketRetransmitted(const RTPHeader& header, 1896 bool in_order) const { 1897 // Retransmissions are handled separately if RTX is enabled. 1898 if (rtp_payload_registry_->RtxEnabled()) 1899 return false; 1900 StreamStatistician* statistician = 1901 rtp_receive_statistics_->GetStatistician(header.ssrc); 1902 if (!statistician) 1903 return false; 1904 // Check if this is a retransmission. 1905 uint16_t min_rtt = 0; 1906 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL); 1907 return !in_order && 1908 statistician->IsRetransmitOfOldPacket(header, min_rtt); 1909 } 1910 1911 int32_t Channel::ReceivedRTCPPacket(const int8_t* data, int32_t length) { 1912 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 1913 "Channel::ReceivedRTCPPacket()"); 1914 // Store playout timestamp for the received RTCP packet 1915 UpdatePlayoutTimestamp(true); 1916 1917 // Dump the RTCP packet to a file (if RTP dump is enabled). 1918 if (_rtpDumpIn.DumpPacket((const uint8_t*)data, 1919 (uint16_t)length) == -1) { 1920 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 1921 VoEId(_instanceId,_channelId), 1922 "Channel::SendPacket() RTCP dump to input file failed"); 1923 } 1924 1925 // Deliver RTCP packet to RTP/RTCP module for parsing 1926 if (_rtpRtcpModule->IncomingRtcpPacket((const uint8_t*)data, 1927 (uint16_t)length) == -1) { 1928 _engineStatisticsPtr->SetLastError( 1929 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning, 1930 "Channel::IncomingRTPPacket() RTCP packet is invalid"); 1931 } 1932 1933 ntp_estimator_->UpdateRtcpTimestamp(rtp_receiver_->SSRC(), 1934 _rtpRtcpModule.get()); 1935 return 0; 1936 } 1937 1938 int Channel::StartPlayingFileLocally(const char* fileName, 1939 bool loop, 1940 FileFormats format, 1941 int startPosition, 1942 float volumeScaling, 1943 int stopPosition, 1944 const CodecInst* codecInst) 1945 { 1946 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 1947 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d," 1948 " format=%d, volumeScaling=%5.3f, startPosition=%d, " 1949 "stopPosition=%d)", fileName, loop, format, volumeScaling, 1950 startPosition, stopPosition); 1951 1952 if (channel_state_.Get().output_file_playing) 1953 { 1954 _engineStatisticsPtr->SetLastError( 1955 VE_ALREADY_PLAYING, kTraceError, 1956 "StartPlayingFileLocally() is already playing"); 1957 return -1; 1958 } 1959 1960 { 1961 CriticalSectionScoped cs(&_fileCritSect); 1962 1963 if (_outputFilePlayerPtr) 1964 { 1965 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 1966 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1967 _outputFilePlayerPtr = NULL; 1968 } 1969 1970 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer( 1971 _outputFilePlayerId, (const FileFormats)format); 1972 1973 if (_outputFilePlayerPtr == NULL) 1974 { 1975 _engineStatisticsPtr->SetLastError( 1976 VE_INVALID_ARGUMENT, kTraceError, 1977 "StartPlayingFileLocally() filePlayer format is not correct"); 1978 return -1; 1979 } 1980 1981 const uint32_t notificationTime(0); 1982 1983 if (_outputFilePlayerPtr->StartPlayingFile( 1984 fileName, 1985 loop, 1986 startPosition, 1987 volumeScaling, 1988 notificationTime, 1989 stopPosition, 1990 (const CodecInst*)codecInst) != 0) 1991 { 1992 _engineStatisticsPtr->SetLastError( 1993 VE_BAD_FILE, kTraceError, 1994 "StartPlayingFile() failed to start file playout"); 1995 _outputFilePlayerPtr->StopPlayingFile(); 1996 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 1997 _outputFilePlayerPtr = NULL; 1998 return -1; 1999 } 2000 _outputFilePlayerPtr->RegisterModuleFileCallback(this); 2001 channel_state_.SetOutputFilePlaying(true); 2002 } 2003 2004 if (RegisterFilePlayingToMixer() != 0) 2005 return -1; 2006 2007 return 0; 2008 } 2009 2010 int Channel::StartPlayingFileLocally(InStream* stream, 2011 FileFormats format, 2012 int startPosition, 2013 float volumeScaling, 2014 int stopPosition, 2015 const CodecInst* codecInst) 2016 { 2017 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2018 "Channel::StartPlayingFileLocally(format=%d," 2019 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)", 2020 format, volumeScaling, startPosition, stopPosition); 2021 2022 if(stream == NULL) 2023 { 2024 _engineStatisticsPtr->SetLastError( 2025 VE_BAD_FILE, kTraceError, 2026 "StartPlayingFileLocally() NULL as input stream"); 2027 return -1; 2028 } 2029 2030 2031 if (channel_state_.Get().output_file_playing) 2032 { 2033 _engineStatisticsPtr->SetLastError( 2034 VE_ALREADY_PLAYING, kTraceError, 2035 "StartPlayingFileLocally() is already playing"); 2036 return -1; 2037 } 2038 2039 { 2040 CriticalSectionScoped cs(&_fileCritSect); 2041 2042 // Destroy the old instance 2043 if (_outputFilePlayerPtr) 2044 { 2045 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2046 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2047 _outputFilePlayerPtr = NULL; 2048 } 2049 2050 // Create the instance 2051 _outputFilePlayerPtr = FilePlayer::CreateFilePlayer( 2052 _outputFilePlayerId, 2053 (const FileFormats)format); 2054 2055 if (_outputFilePlayerPtr == NULL) 2056 { 2057 _engineStatisticsPtr->SetLastError( 2058 VE_INVALID_ARGUMENT, kTraceError, 2059 "StartPlayingFileLocally() filePlayer format isnot correct"); 2060 return -1; 2061 } 2062 2063 const uint32_t notificationTime(0); 2064 2065 if (_outputFilePlayerPtr->StartPlayingFile(*stream, startPosition, 2066 volumeScaling, 2067 notificationTime, 2068 stopPosition, codecInst) != 0) 2069 { 2070 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 2071 "StartPlayingFile() failed to " 2072 "start file playout"); 2073 _outputFilePlayerPtr->StopPlayingFile(); 2074 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2075 _outputFilePlayerPtr = NULL; 2076 return -1; 2077 } 2078 _outputFilePlayerPtr->RegisterModuleFileCallback(this); 2079 channel_state_.SetOutputFilePlaying(true); 2080 } 2081 2082 if (RegisterFilePlayingToMixer() != 0) 2083 return -1; 2084 2085 return 0; 2086 } 2087 2088 int Channel::StopPlayingFileLocally() 2089 { 2090 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2091 "Channel::StopPlayingFileLocally()"); 2092 2093 if (!channel_state_.Get().output_file_playing) 2094 { 2095 _engineStatisticsPtr->SetLastError( 2096 VE_INVALID_OPERATION, kTraceWarning, 2097 "StopPlayingFileLocally() isnot playing"); 2098 return 0; 2099 } 2100 2101 { 2102 CriticalSectionScoped cs(&_fileCritSect); 2103 2104 if (_outputFilePlayerPtr->StopPlayingFile() != 0) 2105 { 2106 _engineStatisticsPtr->SetLastError( 2107 VE_STOP_RECORDING_FAILED, kTraceError, 2108 "StopPlayingFile() could not stop playing"); 2109 return -1; 2110 } 2111 _outputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2112 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2113 _outputFilePlayerPtr = NULL; 2114 channel_state_.SetOutputFilePlaying(false); 2115 } 2116 // _fileCritSect cannot be taken while calling 2117 // SetAnonymousMixibilityStatus. Refer to comments in 2118 // StartPlayingFileLocally(const char* ...) for more details. 2119 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) 2120 { 2121 _engineStatisticsPtr->SetLastError( 2122 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 2123 "StopPlayingFile() failed to stop participant from playing as" 2124 "file in the mixer"); 2125 return -1; 2126 } 2127 2128 return 0; 2129 } 2130 2131 int Channel::IsPlayingFileLocally() const 2132 { 2133 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2134 "Channel::IsPlayingFileLocally()"); 2135 2136 return channel_state_.Get().output_file_playing; 2137 } 2138 2139 int Channel::RegisterFilePlayingToMixer() 2140 { 2141 // Return success for not registering for file playing to mixer if: 2142 // 1. playing file before playout is started on that channel. 2143 // 2. starting playout without file playing on that channel. 2144 if (!channel_state_.Get().playing || 2145 !channel_state_.Get().output_file_playing) 2146 { 2147 return 0; 2148 } 2149 2150 // |_fileCritSect| cannot be taken while calling 2151 // SetAnonymousMixabilityStatus() since as soon as the participant is added 2152 // frames can be pulled by the mixer. Since the frames are generated from 2153 // the file, _fileCritSect will be taken. This would result in a deadlock. 2154 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) 2155 { 2156 channel_state_.SetOutputFilePlaying(false); 2157 CriticalSectionScoped cs(&_fileCritSect); 2158 _engineStatisticsPtr->SetLastError( 2159 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError, 2160 "StartPlayingFile() failed to add participant as file to mixer"); 2161 _outputFilePlayerPtr->StopPlayingFile(); 2162 FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr); 2163 _outputFilePlayerPtr = NULL; 2164 return -1; 2165 } 2166 2167 return 0; 2168 } 2169 2170 int Channel::StartPlayingFileAsMicrophone(const char* fileName, 2171 bool loop, 2172 FileFormats format, 2173 int startPosition, 2174 float volumeScaling, 2175 int stopPosition, 2176 const CodecInst* codecInst) 2177 { 2178 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2179 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, " 2180 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, " 2181 "stopPosition=%d)", fileName, loop, format, volumeScaling, 2182 startPosition, stopPosition); 2183 2184 CriticalSectionScoped cs(&_fileCritSect); 2185 2186 if (channel_state_.Get().input_file_playing) 2187 { 2188 _engineStatisticsPtr->SetLastError( 2189 VE_ALREADY_PLAYING, kTraceWarning, 2190 "StartPlayingFileAsMicrophone() filePlayer is playing"); 2191 return 0; 2192 } 2193 2194 // Destroy the old instance 2195 if (_inputFilePlayerPtr) 2196 { 2197 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2198 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2199 _inputFilePlayerPtr = NULL; 2200 } 2201 2202 // Create the instance 2203 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer( 2204 _inputFilePlayerId, (const FileFormats)format); 2205 2206 if (_inputFilePlayerPtr == NULL) 2207 { 2208 _engineStatisticsPtr->SetLastError( 2209 VE_INVALID_ARGUMENT, kTraceError, 2210 "StartPlayingFileAsMicrophone() filePlayer format isnot correct"); 2211 return -1; 2212 } 2213 2214 const uint32_t notificationTime(0); 2215 2216 if (_inputFilePlayerPtr->StartPlayingFile( 2217 fileName, 2218 loop, 2219 startPosition, 2220 volumeScaling, 2221 notificationTime, 2222 stopPosition, 2223 (const CodecInst*)codecInst) != 0) 2224 { 2225 _engineStatisticsPtr->SetLastError( 2226 VE_BAD_FILE, kTraceError, 2227 "StartPlayingFile() failed to start file playout"); 2228 _inputFilePlayerPtr->StopPlayingFile(); 2229 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2230 _inputFilePlayerPtr = NULL; 2231 return -1; 2232 } 2233 _inputFilePlayerPtr->RegisterModuleFileCallback(this); 2234 channel_state_.SetInputFilePlaying(true); 2235 2236 return 0; 2237 } 2238 2239 int Channel::StartPlayingFileAsMicrophone(InStream* stream, 2240 FileFormats format, 2241 int startPosition, 2242 float volumeScaling, 2243 int stopPosition, 2244 const CodecInst* codecInst) 2245 { 2246 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2247 "Channel::StartPlayingFileAsMicrophone(format=%d, " 2248 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)", 2249 format, volumeScaling, startPosition, stopPosition); 2250 2251 if(stream == NULL) 2252 { 2253 _engineStatisticsPtr->SetLastError( 2254 VE_BAD_FILE, kTraceError, 2255 "StartPlayingFileAsMicrophone NULL as input stream"); 2256 return -1; 2257 } 2258 2259 CriticalSectionScoped cs(&_fileCritSect); 2260 2261 if (channel_state_.Get().input_file_playing) 2262 { 2263 _engineStatisticsPtr->SetLastError( 2264 VE_ALREADY_PLAYING, kTraceWarning, 2265 "StartPlayingFileAsMicrophone() is playing"); 2266 return 0; 2267 } 2268 2269 // Destroy the old instance 2270 if (_inputFilePlayerPtr) 2271 { 2272 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2273 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2274 _inputFilePlayerPtr = NULL; 2275 } 2276 2277 // Create the instance 2278 _inputFilePlayerPtr = FilePlayer::CreateFilePlayer( 2279 _inputFilePlayerId, (const FileFormats)format); 2280 2281 if (_inputFilePlayerPtr == NULL) 2282 { 2283 _engineStatisticsPtr->SetLastError( 2284 VE_INVALID_ARGUMENT, kTraceError, 2285 "StartPlayingInputFile() filePlayer format isnot correct"); 2286 return -1; 2287 } 2288 2289 const uint32_t notificationTime(0); 2290 2291 if (_inputFilePlayerPtr->StartPlayingFile(*stream, startPosition, 2292 volumeScaling, notificationTime, 2293 stopPosition, codecInst) != 0) 2294 { 2295 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 2296 "StartPlayingFile() failed to start " 2297 "file playout"); 2298 _inputFilePlayerPtr->StopPlayingFile(); 2299 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2300 _inputFilePlayerPtr = NULL; 2301 return -1; 2302 } 2303 2304 _inputFilePlayerPtr->RegisterModuleFileCallback(this); 2305 channel_state_.SetInputFilePlaying(true); 2306 2307 return 0; 2308 } 2309 2310 int Channel::StopPlayingFileAsMicrophone() 2311 { 2312 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2313 "Channel::StopPlayingFileAsMicrophone()"); 2314 2315 CriticalSectionScoped cs(&_fileCritSect); 2316 2317 if (!channel_state_.Get().input_file_playing) 2318 { 2319 _engineStatisticsPtr->SetLastError( 2320 VE_INVALID_OPERATION, kTraceWarning, 2321 "StopPlayingFileAsMicrophone() isnot playing"); 2322 return 0; 2323 } 2324 2325 if (_inputFilePlayerPtr->StopPlayingFile() != 0) 2326 { 2327 _engineStatisticsPtr->SetLastError( 2328 VE_STOP_RECORDING_FAILED, kTraceError, 2329 "StopPlayingFile() could not stop playing"); 2330 return -1; 2331 } 2332 _inputFilePlayerPtr->RegisterModuleFileCallback(NULL); 2333 FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr); 2334 _inputFilePlayerPtr = NULL; 2335 channel_state_.SetInputFilePlaying(false); 2336 2337 return 0; 2338 } 2339 2340 int Channel::IsPlayingFileAsMicrophone() const 2341 { 2342 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2343 "Channel::IsPlayingFileAsMicrophone()"); 2344 return channel_state_.Get().input_file_playing; 2345 } 2346 2347 int Channel::StartRecordingPlayout(const char* fileName, 2348 const CodecInst* codecInst) 2349 { 2350 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2351 "Channel::StartRecordingPlayout(fileName=%s)", fileName); 2352 2353 if (_outputFileRecording) 2354 { 2355 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 2356 "StartRecordingPlayout() is already recording"); 2357 return 0; 2358 } 2359 2360 FileFormats format; 2361 const uint32_t notificationTime(0); // Not supported in VoE 2362 CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 2363 2364 if ((codecInst != NULL) && 2365 ((codecInst->channels < 1) || (codecInst->channels > 2))) 2366 { 2367 _engineStatisticsPtr->SetLastError( 2368 VE_BAD_ARGUMENT, kTraceError, 2369 "StartRecordingPlayout() invalid compression"); 2370 return(-1); 2371 } 2372 if(codecInst == NULL) 2373 { 2374 format = kFileFormatPcm16kHzFile; 2375 codecInst=&dummyCodec; 2376 } 2377 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 2378 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 2379 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 2380 { 2381 format = kFileFormatWavFile; 2382 } 2383 else 2384 { 2385 format = kFileFormatCompressedFile; 2386 } 2387 2388 CriticalSectionScoped cs(&_fileCritSect); 2389 2390 // Destroy the old instance 2391 if (_outputFileRecorderPtr) 2392 { 2393 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2394 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2395 _outputFileRecorderPtr = NULL; 2396 } 2397 2398 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 2399 _outputFileRecorderId, (const FileFormats)format); 2400 if (_outputFileRecorderPtr == NULL) 2401 { 2402 _engineStatisticsPtr->SetLastError( 2403 VE_INVALID_ARGUMENT, kTraceError, 2404 "StartRecordingPlayout() fileRecorder format isnot correct"); 2405 return -1; 2406 } 2407 2408 if (_outputFileRecorderPtr->StartRecordingAudioFile( 2409 fileName, (const CodecInst&)*codecInst, notificationTime) != 0) 2410 { 2411 _engineStatisticsPtr->SetLastError( 2412 VE_BAD_FILE, kTraceError, 2413 "StartRecordingAudioFile() failed to start file recording"); 2414 _outputFileRecorderPtr->StopRecording(); 2415 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2416 _outputFileRecorderPtr = NULL; 2417 return -1; 2418 } 2419 _outputFileRecorderPtr->RegisterModuleFileCallback(this); 2420 _outputFileRecording = true; 2421 2422 return 0; 2423 } 2424 2425 int Channel::StartRecordingPlayout(OutStream* stream, 2426 const CodecInst* codecInst) 2427 { 2428 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2429 "Channel::StartRecordingPlayout()"); 2430 2431 if (_outputFileRecording) 2432 { 2433 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,-1), 2434 "StartRecordingPlayout() is already recording"); 2435 return 0; 2436 } 2437 2438 FileFormats format; 2439 const uint32_t notificationTime(0); // Not supported in VoE 2440 CodecInst dummyCodec={100,"L16",16000,320,1,320000}; 2441 2442 if (codecInst != NULL && codecInst->channels != 1) 2443 { 2444 _engineStatisticsPtr->SetLastError( 2445 VE_BAD_ARGUMENT, kTraceError, 2446 "StartRecordingPlayout() invalid compression"); 2447 return(-1); 2448 } 2449 if(codecInst == NULL) 2450 { 2451 format = kFileFormatPcm16kHzFile; 2452 codecInst=&dummyCodec; 2453 } 2454 else if((STR_CASE_CMP(codecInst->plname,"L16") == 0) || 2455 (STR_CASE_CMP(codecInst->plname,"PCMU") == 0) || 2456 (STR_CASE_CMP(codecInst->plname,"PCMA") == 0)) 2457 { 2458 format = kFileFormatWavFile; 2459 } 2460 else 2461 { 2462 format = kFileFormatCompressedFile; 2463 } 2464 2465 CriticalSectionScoped cs(&_fileCritSect); 2466 2467 // Destroy the old instance 2468 if (_outputFileRecorderPtr) 2469 { 2470 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2471 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2472 _outputFileRecorderPtr = NULL; 2473 } 2474 2475 _outputFileRecorderPtr = FileRecorder::CreateFileRecorder( 2476 _outputFileRecorderId, (const FileFormats)format); 2477 if (_outputFileRecorderPtr == NULL) 2478 { 2479 _engineStatisticsPtr->SetLastError( 2480 VE_INVALID_ARGUMENT, kTraceError, 2481 "StartRecordingPlayout() fileRecorder format isnot correct"); 2482 return -1; 2483 } 2484 2485 if (_outputFileRecorderPtr->StartRecordingAudioFile(*stream, *codecInst, 2486 notificationTime) != 0) 2487 { 2488 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError, 2489 "StartRecordingPlayout() failed to " 2490 "start file recording"); 2491 _outputFileRecorderPtr->StopRecording(); 2492 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2493 _outputFileRecorderPtr = NULL; 2494 return -1; 2495 } 2496 2497 _outputFileRecorderPtr->RegisterModuleFileCallback(this); 2498 _outputFileRecording = true; 2499 2500 return 0; 2501 } 2502 2503 int Channel::StopRecordingPlayout() 2504 { 2505 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,-1), 2506 "Channel::StopRecordingPlayout()"); 2507 2508 if (!_outputFileRecording) 2509 { 2510 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,-1), 2511 "StopRecordingPlayout() isnot recording"); 2512 return -1; 2513 } 2514 2515 2516 CriticalSectionScoped cs(&_fileCritSect); 2517 2518 if (_outputFileRecorderPtr->StopRecording() != 0) 2519 { 2520 _engineStatisticsPtr->SetLastError( 2521 VE_STOP_RECORDING_FAILED, kTraceError, 2522 "StopRecording() could not stop recording"); 2523 return(-1); 2524 } 2525 _outputFileRecorderPtr->RegisterModuleFileCallback(NULL); 2526 FileRecorder::DestroyFileRecorder(_outputFileRecorderPtr); 2527 _outputFileRecorderPtr = NULL; 2528 _outputFileRecording = false; 2529 2530 return 0; 2531 } 2532 2533 void 2534 Channel::SetMixWithMicStatus(bool mix) 2535 { 2536 CriticalSectionScoped cs(&_fileCritSect); 2537 _mixFileWithMicrophone=mix; 2538 } 2539 2540 int 2541 Channel::GetSpeechOutputLevel(uint32_t& level) const 2542 { 2543 int8_t currentLevel = _outputAudioLevel.Level(); 2544 level = static_cast<int32_t> (currentLevel); 2545 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2546 VoEId(_instanceId,_channelId), 2547 "GetSpeechOutputLevel() => level=%u", level); 2548 return 0; 2549 } 2550 2551 int 2552 Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const 2553 { 2554 int16_t currentLevel = _outputAudioLevel.LevelFullRange(); 2555 level = static_cast<int32_t> (currentLevel); 2556 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2557 VoEId(_instanceId,_channelId), 2558 "GetSpeechOutputLevelFullRange() => level=%u", level); 2559 return 0; 2560 } 2561 2562 int 2563 Channel::SetMute(bool enable) 2564 { 2565 CriticalSectionScoped cs(&volume_settings_critsect_); 2566 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2567 "Channel::SetMute(enable=%d)", enable); 2568 _mute = enable; 2569 return 0; 2570 } 2571 2572 bool 2573 Channel::Mute() const 2574 { 2575 CriticalSectionScoped cs(&volume_settings_critsect_); 2576 return _mute; 2577 } 2578 2579 int 2580 Channel::SetOutputVolumePan(float left, float right) 2581 { 2582 CriticalSectionScoped cs(&volume_settings_critsect_); 2583 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2584 "Channel::SetOutputVolumePan()"); 2585 _panLeft = left; 2586 _panRight = right; 2587 return 0; 2588 } 2589 2590 int 2591 Channel::GetOutputVolumePan(float& left, float& right) const 2592 { 2593 CriticalSectionScoped cs(&volume_settings_critsect_); 2594 left = _panLeft; 2595 right = _panRight; 2596 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2597 VoEId(_instanceId,_channelId), 2598 "GetOutputVolumePan() => left=%3.2f, right=%3.2f", left, right); 2599 return 0; 2600 } 2601 2602 int 2603 Channel::SetChannelOutputVolumeScaling(float scaling) 2604 { 2605 CriticalSectionScoped cs(&volume_settings_critsect_); 2606 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2607 "Channel::SetChannelOutputVolumeScaling()"); 2608 _outputGain = scaling; 2609 return 0; 2610 } 2611 2612 int 2613 Channel::GetChannelOutputVolumeScaling(float& scaling) const 2614 { 2615 CriticalSectionScoped cs(&volume_settings_critsect_); 2616 scaling = _outputGain; 2617 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2618 VoEId(_instanceId,_channelId), 2619 "GetChannelOutputVolumeScaling() => scaling=%3.2f", scaling); 2620 return 0; 2621 } 2622 2623 int Channel::SendTelephoneEventOutband(unsigned char eventCode, 2624 int lengthMs, int attenuationDb, 2625 bool playDtmfEvent) 2626 { 2627 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2628 "Channel::SendTelephoneEventOutband(..., playDtmfEvent=%d)", 2629 playDtmfEvent); 2630 2631 _playOutbandDtmfEvent = playDtmfEvent; 2632 2633 if (_rtpRtcpModule->SendTelephoneEventOutband(eventCode, lengthMs, 2634 attenuationDb) != 0) 2635 { 2636 _engineStatisticsPtr->SetLastError( 2637 VE_SEND_DTMF_FAILED, 2638 kTraceWarning, 2639 "SendTelephoneEventOutband() failed to send event"); 2640 return -1; 2641 } 2642 return 0; 2643 } 2644 2645 int Channel::SendTelephoneEventInband(unsigned char eventCode, 2646 int lengthMs, 2647 int attenuationDb, 2648 bool playDtmfEvent) 2649 { 2650 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 2651 "Channel::SendTelephoneEventInband(..., playDtmfEvent=%d)", 2652 playDtmfEvent); 2653 2654 _playInbandDtmfEvent = playDtmfEvent; 2655 _inbandDtmfQueue.AddDtmf(eventCode, lengthMs, attenuationDb); 2656 2657 return 0; 2658 } 2659 2660 int 2661 Channel::SetDtmfPlayoutStatus(bool enable) 2662 { 2663 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2664 "Channel::SetDtmfPlayoutStatus()"); 2665 if (audio_coding_->SetDtmfPlayoutStatus(enable) != 0) 2666 { 2667 _engineStatisticsPtr->SetLastError( 2668 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning, 2669 "SetDtmfPlayoutStatus() failed to set Dtmf playout"); 2670 return -1; 2671 } 2672 return 0; 2673 } 2674 2675 bool 2676 Channel::DtmfPlayoutStatus() const 2677 { 2678 return audio_coding_->DtmfPlayoutStatus(); 2679 } 2680 2681 int 2682 Channel::SetSendTelephoneEventPayloadType(unsigned char type) 2683 { 2684 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2685 "Channel::SetSendTelephoneEventPayloadType()"); 2686 if (type > 127) 2687 { 2688 _engineStatisticsPtr->SetLastError( 2689 VE_INVALID_ARGUMENT, kTraceError, 2690 "SetSendTelephoneEventPayloadType() invalid type"); 2691 return -1; 2692 } 2693 CodecInst codec = {}; 2694 codec.plfreq = 8000; 2695 codec.pltype = type; 2696 memcpy(codec.plname, "telephone-event", 16); 2697 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) 2698 { 2699 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype); 2700 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) { 2701 _engineStatisticsPtr->SetLastError( 2702 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 2703 "SetSendTelephoneEventPayloadType() failed to register send" 2704 "payload type"); 2705 return -1; 2706 } 2707 } 2708 _sendTelephoneEventPayloadType = type; 2709 return 0; 2710 } 2711 2712 int 2713 Channel::GetSendTelephoneEventPayloadType(unsigned char& type) 2714 { 2715 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2716 "Channel::GetSendTelephoneEventPayloadType()"); 2717 type = _sendTelephoneEventPayloadType; 2718 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2719 VoEId(_instanceId,_channelId), 2720 "GetSendTelephoneEventPayloadType() => type=%u", type); 2721 return 0; 2722 } 2723 2724 int 2725 Channel::UpdateRxVadDetection(AudioFrame& audioFrame) 2726 { 2727 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 2728 "Channel::UpdateRxVadDetection()"); 2729 2730 int vadDecision = 1; 2731 2732 vadDecision = (audioFrame.vad_activity_ == AudioFrame::kVadActive)? 1 : 0; 2733 2734 if ((vadDecision != _oldVadDecision) && _rxVadObserverPtr) 2735 { 2736 OnRxVadDetected(vadDecision); 2737 _oldVadDecision = vadDecision; 2738 } 2739 2740 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 2741 "Channel::UpdateRxVadDetection() => vadDecision=%d", 2742 vadDecision); 2743 return 0; 2744 } 2745 2746 int 2747 Channel::RegisterRxVadObserver(VoERxVadCallback &observer) 2748 { 2749 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2750 "Channel::RegisterRxVadObserver()"); 2751 CriticalSectionScoped cs(&_callbackCritSect); 2752 2753 if (_rxVadObserverPtr) 2754 { 2755 _engineStatisticsPtr->SetLastError( 2756 VE_INVALID_OPERATION, kTraceError, 2757 "RegisterRxVadObserver() observer already enabled"); 2758 return -1; 2759 } 2760 _rxVadObserverPtr = &observer; 2761 _RxVadDetection = true; 2762 return 0; 2763 } 2764 2765 int 2766 Channel::DeRegisterRxVadObserver() 2767 { 2768 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2769 "Channel::DeRegisterRxVadObserver()"); 2770 CriticalSectionScoped cs(&_callbackCritSect); 2771 2772 if (!_rxVadObserverPtr) 2773 { 2774 _engineStatisticsPtr->SetLastError( 2775 VE_INVALID_OPERATION, kTraceWarning, 2776 "DeRegisterRxVadObserver() observer already disabled"); 2777 return 0; 2778 } 2779 _rxVadObserverPtr = NULL; 2780 _RxVadDetection = false; 2781 return 0; 2782 } 2783 2784 int 2785 Channel::VoiceActivityIndicator(int &activity) 2786 { 2787 activity = _sendFrameType; 2788 2789 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2790 "Channel::VoiceActivityIndicator(indicator=%d)", activity); 2791 return 0; 2792 } 2793 2794 #ifdef WEBRTC_VOICE_ENGINE_AGC 2795 2796 int 2797 Channel::SetRxAgcStatus(bool enable, AgcModes mode) 2798 { 2799 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2800 "Channel::SetRxAgcStatus(enable=%d, mode=%d)", 2801 (int)enable, (int)mode); 2802 2803 GainControl::Mode agcMode = kDefaultRxAgcMode; 2804 switch (mode) 2805 { 2806 case kAgcDefault: 2807 break; 2808 case kAgcUnchanged: 2809 agcMode = rx_audioproc_->gain_control()->mode(); 2810 break; 2811 case kAgcFixedDigital: 2812 agcMode = GainControl::kFixedDigital; 2813 break; 2814 case kAgcAdaptiveDigital: 2815 agcMode =GainControl::kAdaptiveDigital; 2816 break; 2817 default: 2818 _engineStatisticsPtr->SetLastError( 2819 VE_INVALID_ARGUMENT, kTraceError, 2820 "SetRxAgcStatus() invalid Agc mode"); 2821 return -1; 2822 } 2823 2824 if (rx_audioproc_->gain_control()->set_mode(agcMode) != 0) 2825 { 2826 _engineStatisticsPtr->SetLastError( 2827 VE_APM_ERROR, kTraceError, 2828 "SetRxAgcStatus() failed to set Agc mode"); 2829 return -1; 2830 } 2831 if (rx_audioproc_->gain_control()->Enable(enable) != 0) 2832 { 2833 _engineStatisticsPtr->SetLastError( 2834 VE_APM_ERROR, kTraceError, 2835 "SetRxAgcStatus() failed to set Agc state"); 2836 return -1; 2837 } 2838 2839 _rxAgcIsEnabled = enable; 2840 channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled); 2841 2842 return 0; 2843 } 2844 2845 int 2846 Channel::GetRxAgcStatus(bool& enabled, AgcModes& mode) 2847 { 2848 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2849 "Channel::GetRxAgcStatus(enable=?, mode=?)"); 2850 2851 bool enable = rx_audioproc_->gain_control()->is_enabled(); 2852 GainControl::Mode agcMode = 2853 rx_audioproc_->gain_control()->mode(); 2854 2855 enabled = enable; 2856 2857 switch (agcMode) 2858 { 2859 case GainControl::kFixedDigital: 2860 mode = kAgcFixedDigital; 2861 break; 2862 case GainControl::kAdaptiveDigital: 2863 mode = kAgcAdaptiveDigital; 2864 break; 2865 default: 2866 _engineStatisticsPtr->SetLastError( 2867 VE_APM_ERROR, kTraceError, 2868 "GetRxAgcStatus() invalid Agc mode"); 2869 return -1; 2870 } 2871 2872 return 0; 2873 } 2874 2875 int 2876 Channel::SetRxAgcConfig(AgcConfig config) 2877 { 2878 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2879 "Channel::SetRxAgcConfig()"); 2880 2881 if (rx_audioproc_->gain_control()->set_target_level_dbfs( 2882 config.targetLeveldBOv) != 0) 2883 { 2884 _engineStatisticsPtr->SetLastError( 2885 VE_APM_ERROR, kTraceError, 2886 "SetRxAgcConfig() failed to set target peak |level|" 2887 "(or envelope) of the Agc"); 2888 return -1; 2889 } 2890 if (rx_audioproc_->gain_control()->set_compression_gain_db( 2891 config.digitalCompressionGaindB) != 0) 2892 { 2893 _engineStatisticsPtr->SetLastError( 2894 VE_APM_ERROR, kTraceError, 2895 "SetRxAgcConfig() failed to set the range in |gain| the" 2896 " digital compression stage may apply"); 2897 return -1; 2898 } 2899 if (rx_audioproc_->gain_control()->enable_limiter( 2900 config.limiterEnable) != 0) 2901 { 2902 _engineStatisticsPtr->SetLastError( 2903 VE_APM_ERROR, kTraceError, 2904 "SetRxAgcConfig() failed to set hard limiter to the signal"); 2905 return -1; 2906 } 2907 2908 return 0; 2909 } 2910 2911 int 2912 Channel::GetRxAgcConfig(AgcConfig& config) 2913 { 2914 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2915 "Channel::GetRxAgcConfig(config=%?)"); 2916 2917 config.targetLeveldBOv = 2918 rx_audioproc_->gain_control()->target_level_dbfs(); 2919 config.digitalCompressionGaindB = 2920 rx_audioproc_->gain_control()->compression_gain_db(); 2921 config.limiterEnable = 2922 rx_audioproc_->gain_control()->is_limiter_enabled(); 2923 2924 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 2925 VoEId(_instanceId,_channelId), "GetRxAgcConfig() => " 2926 "targetLeveldBOv=%u, digitalCompressionGaindB=%u," 2927 " limiterEnable=%d", 2928 config.targetLeveldBOv, 2929 config.digitalCompressionGaindB, 2930 config.limiterEnable); 2931 2932 return 0; 2933 } 2934 2935 #endif // #ifdef WEBRTC_VOICE_ENGINE_AGC 2936 2937 #ifdef WEBRTC_VOICE_ENGINE_NR 2938 2939 int 2940 Channel::SetRxNsStatus(bool enable, NsModes mode) 2941 { 2942 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2943 "Channel::SetRxNsStatus(enable=%d, mode=%d)", 2944 (int)enable, (int)mode); 2945 2946 NoiseSuppression::Level nsLevel = kDefaultNsMode; 2947 switch (mode) 2948 { 2949 2950 case kNsDefault: 2951 break; 2952 case kNsUnchanged: 2953 nsLevel = rx_audioproc_->noise_suppression()->level(); 2954 break; 2955 case kNsConference: 2956 nsLevel = NoiseSuppression::kHigh; 2957 break; 2958 case kNsLowSuppression: 2959 nsLevel = NoiseSuppression::kLow; 2960 break; 2961 case kNsModerateSuppression: 2962 nsLevel = NoiseSuppression::kModerate; 2963 break; 2964 case kNsHighSuppression: 2965 nsLevel = NoiseSuppression::kHigh; 2966 break; 2967 case kNsVeryHighSuppression: 2968 nsLevel = NoiseSuppression::kVeryHigh; 2969 break; 2970 } 2971 2972 if (rx_audioproc_->noise_suppression()->set_level(nsLevel) 2973 != 0) 2974 { 2975 _engineStatisticsPtr->SetLastError( 2976 VE_APM_ERROR, kTraceError, 2977 "SetRxNsStatus() failed to set NS level"); 2978 return -1; 2979 } 2980 if (rx_audioproc_->noise_suppression()->Enable(enable) != 0) 2981 { 2982 _engineStatisticsPtr->SetLastError( 2983 VE_APM_ERROR, kTraceError, 2984 "SetRxNsStatus() failed to set NS state"); 2985 return -1; 2986 } 2987 2988 _rxNsIsEnabled = enable; 2989 channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled); 2990 2991 return 0; 2992 } 2993 2994 int 2995 Channel::GetRxNsStatus(bool& enabled, NsModes& mode) 2996 { 2997 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 2998 "Channel::GetRxNsStatus(enable=?, mode=?)"); 2999 3000 bool enable = 3001 rx_audioproc_->noise_suppression()->is_enabled(); 3002 NoiseSuppression::Level ncLevel = 3003 rx_audioproc_->noise_suppression()->level(); 3004 3005 enabled = enable; 3006 3007 switch (ncLevel) 3008 { 3009 case NoiseSuppression::kLow: 3010 mode = kNsLowSuppression; 3011 break; 3012 case NoiseSuppression::kModerate: 3013 mode = kNsModerateSuppression; 3014 break; 3015 case NoiseSuppression::kHigh: 3016 mode = kNsHighSuppression; 3017 break; 3018 case NoiseSuppression::kVeryHigh: 3019 mode = kNsVeryHighSuppression; 3020 break; 3021 } 3022 3023 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3024 VoEId(_instanceId,_channelId), 3025 "GetRxNsStatus() => enabled=%d, mode=%d", enabled, mode); 3026 return 0; 3027 } 3028 3029 #endif // #ifdef WEBRTC_VOICE_ENGINE_NR 3030 3031 int 3032 Channel::RegisterRTCPObserver(VoERTCPObserver& observer) 3033 { 3034 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3035 "Channel::RegisterRTCPObserver()"); 3036 CriticalSectionScoped cs(&_callbackCritSect); 3037 3038 if (_rtcpObserverPtr) 3039 { 3040 _engineStatisticsPtr->SetLastError( 3041 VE_INVALID_OPERATION, kTraceError, 3042 "RegisterRTCPObserver() observer already enabled"); 3043 return -1; 3044 } 3045 3046 _rtcpObserverPtr = &observer; 3047 _rtcpObserver = true; 3048 3049 return 0; 3050 } 3051 3052 int 3053 Channel::DeRegisterRTCPObserver() 3054 { 3055 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3056 "Channel::DeRegisterRTCPObserver()"); 3057 CriticalSectionScoped cs(&_callbackCritSect); 3058 3059 if (!_rtcpObserverPtr) 3060 { 3061 _engineStatisticsPtr->SetLastError( 3062 VE_INVALID_OPERATION, kTraceWarning, 3063 "DeRegisterRTCPObserver() observer already disabled"); 3064 return 0; 3065 } 3066 3067 _rtcpObserver = false; 3068 _rtcpObserverPtr = NULL; 3069 3070 return 0; 3071 } 3072 3073 int 3074 Channel::SetLocalSSRC(unsigned int ssrc) 3075 { 3076 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3077 "Channel::SetLocalSSRC()"); 3078 if (channel_state_.Get().sending) 3079 { 3080 _engineStatisticsPtr->SetLastError( 3081 VE_ALREADY_SENDING, kTraceError, 3082 "SetLocalSSRC() already sending"); 3083 return -1; 3084 } 3085 _rtpRtcpModule->SetSSRC(ssrc); 3086 return 0; 3087 } 3088 3089 int 3090 Channel::GetLocalSSRC(unsigned int& ssrc) 3091 { 3092 ssrc = _rtpRtcpModule->SSRC(); 3093 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3094 VoEId(_instanceId,_channelId), 3095 "GetLocalSSRC() => ssrc=%lu", ssrc); 3096 return 0; 3097 } 3098 3099 int 3100 Channel::GetRemoteSSRC(unsigned int& ssrc) 3101 { 3102 ssrc = rtp_receiver_->SSRC(); 3103 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3104 VoEId(_instanceId,_channelId), 3105 "GetRemoteSSRC() => ssrc=%lu", ssrc); 3106 return 0; 3107 } 3108 3109 int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) { 3110 _includeAudioLevelIndication = enable; 3111 return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id); 3112 } 3113 3114 int Channel::SetReceiveAudioLevelIndicationStatus(bool enable, 3115 unsigned char id) { 3116 rtp_header_parser_->DeregisterRtpHeaderExtension( 3117 kRtpExtensionAudioLevel); 3118 if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension( 3119 kRtpExtensionAudioLevel, id)) { 3120 return -1; 3121 } 3122 return 0; 3123 } 3124 3125 int Channel::SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id) { 3126 return SetSendRtpHeaderExtension(enable, kRtpExtensionAbsoluteSendTime, id); 3127 } 3128 3129 int Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) { 3130 rtp_header_parser_->DeregisterRtpHeaderExtension( 3131 kRtpExtensionAbsoluteSendTime); 3132 if (enable && !rtp_header_parser_->RegisterRtpHeaderExtension( 3133 kRtpExtensionAbsoluteSendTime, id)) { 3134 return -1; 3135 } 3136 return 0; 3137 } 3138 3139 int 3140 Channel::SetRTCPStatus(bool enable) 3141 { 3142 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3143 "Channel::SetRTCPStatus()"); 3144 if (_rtpRtcpModule->SetRTCPStatus(enable ? 3145 kRtcpCompound : kRtcpOff) != 0) 3146 { 3147 _engineStatisticsPtr->SetLastError( 3148 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3149 "SetRTCPStatus() failed to set RTCP status"); 3150 return -1; 3151 } 3152 return 0; 3153 } 3154 3155 int 3156 Channel::GetRTCPStatus(bool& enabled) 3157 { 3158 RTCPMethod method = _rtpRtcpModule->RTCP(); 3159 enabled = (method != kRtcpOff); 3160 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3161 VoEId(_instanceId,_channelId), 3162 "GetRTCPStatus() => enabled=%d", enabled); 3163 return 0; 3164 } 3165 3166 int 3167 Channel::SetRTCP_CNAME(const char cName[256]) 3168 { 3169 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3170 "Channel::SetRTCP_CNAME()"); 3171 if (_rtpRtcpModule->SetCNAME(cName) != 0) 3172 { 3173 _engineStatisticsPtr->SetLastError( 3174 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3175 "SetRTCP_CNAME() failed to set RTCP CNAME"); 3176 return -1; 3177 } 3178 return 0; 3179 } 3180 3181 int 3182 Channel::GetRTCP_CNAME(char cName[256]) 3183 { 3184 if (_rtpRtcpModule->CNAME(cName) != 0) 3185 { 3186 _engineStatisticsPtr->SetLastError( 3187 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3188 "GetRTCP_CNAME() failed to retrieve RTCP CNAME"); 3189 return -1; 3190 } 3191 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3192 VoEId(_instanceId, _channelId), 3193 "GetRTCP_CNAME() => cName=%s", cName); 3194 return 0; 3195 } 3196 3197 int 3198 Channel::GetRemoteRTCP_CNAME(char cName[256]) 3199 { 3200 if (cName == NULL) 3201 { 3202 _engineStatisticsPtr->SetLastError( 3203 VE_INVALID_ARGUMENT, kTraceError, 3204 "GetRemoteRTCP_CNAME() invalid CNAME input buffer"); 3205 return -1; 3206 } 3207 char cname[RTCP_CNAME_SIZE]; 3208 const uint32_t remoteSSRC = rtp_receiver_->SSRC(); 3209 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) 3210 { 3211 _engineStatisticsPtr->SetLastError( 3212 VE_CANNOT_RETRIEVE_CNAME, kTraceError, 3213 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME"); 3214 return -1; 3215 } 3216 strcpy(cName, cname); 3217 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3218 VoEId(_instanceId, _channelId), 3219 "GetRemoteRTCP_CNAME() => cName=%s", cName); 3220 return 0; 3221 } 3222 3223 int 3224 Channel::GetRemoteRTCPData( 3225 unsigned int& NTPHigh, 3226 unsigned int& NTPLow, 3227 unsigned int& timestamp, 3228 unsigned int& playoutTimestamp, 3229 unsigned int* jitter, 3230 unsigned short* fractionLost) 3231 { 3232 // --- Information from sender info in received Sender Reports 3233 3234 RTCPSenderInfo senderInfo; 3235 if (_rtpRtcpModule->RemoteRTCPStat(&senderInfo) != 0) 3236 { 3237 _engineStatisticsPtr->SetLastError( 3238 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3239 "GetRemoteRTCPData() failed to retrieve sender info for remote " 3240 "side"); 3241 return -1; 3242 } 3243 3244 // We only utilize 12 out of 20 bytes in the sender info (ignores packet 3245 // and octet count) 3246 NTPHigh = senderInfo.NTPseconds; 3247 NTPLow = senderInfo.NTPfraction; 3248 timestamp = senderInfo.RTPtimeStamp; 3249 3250 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3251 VoEId(_instanceId, _channelId), 3252 "GetRemoteRTCPData() => NTPHigh=%lu, NTPLow=%lu, " 3253 "timestamp=%lu", 3254 NTPHigh, NTPLow, timestamp); 3255 3256 // --- Locally derived information 3257 3258 // This value is updated on each incoming RTCP packet (0 when no packet 3259 // has been received) 3260 playoutTimestamp = playout_timestamp_rtcp_; 3261 3262 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3263 VoEId(_instanceId, _channelId), 3264 "GetRemoteRTCPData() => playoutTimestamp=%lu", 3265 playout_timestamp_rtcp_); 3266 3267 if (NULL != jitter || NULL != fractionLost) 3268 { 3269 // Get all RTCP receiver report blocks that have been received on this 3270 // channel. If we receive RTP packets from a remote source we know the 3271 // remote SSRC and use the report block from him. 3272 // Otherwise use the first report block. 3273 std::vector<RTCPReportBlock> remote_stats; 3274 if (_rtpRtcpModule->RemoteRTCPStat(&remote_stats) != 0 || 3275 remote_stats.empty()) { 3276 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3277 VoEId(_instanceId, _channelId), 3278 "GetRemoteRTCPData() failed to measure statistics due" 3279 " to lack of received RTP and/or RTCP packets"); 3280 return -1; 3281 } 3282 3283 uint32_t remoteSSRC = rtp_receiver_->SSRC(); 3284 std::vector<RTCPReportBlock>::const_iterator it = remote_stats.begin(); 3285 for (; it != remote_stats.end(); ++it) { 3286 if (it->remoteSSRC == remoteSSRC) 3287 break; 3288 } 3289 3290 if (it == remote_stats.end()) { 3291 // If we have not received any RTCP packets from this SSRC it probably 3292 // means that we have not received any RTP packets. 3293 // Use the first received report block instead. 3294 it = remote_stats.begin(); 3295 remoteSSRC = it->remoteSSRC; 3296 } 3297 3298 if (jitter) { 3299 *jitter = it->jitter; 3300 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3301 VoEId(_instanceId, _channelId), 3302 "GetRemoteRTCPData() => jitter = %lu", *jitter); 3303 } 3304 3305 if (fractionLost) { 3306 *fractionLost = it->fractionLost; 3307 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3308 VoEId(_instanceId, _channelId), 3309 "GetRemoteRTCPData() => fractionLost = %lu", 3310 *fractionLost); 3311 } 3312 } 3313 return 0; 3314 } 3315 3316 int 3317 Channel::SendApplicationDefinedRTCPPacket(unsigned char subType, 3318 unsigned int name, 3319 const char* data, 3320 unsigned short dataLengthInBytes) 3321 { 3322 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3323 "Channel::SendApplicationDefinedRTCPPacket()"); 3324 if (!channel_state_.Get().sending) 3325 { 3326 _engineStatisticsPtr->SetLastError( 3327 VE_NOT_SENDING, kTraceError, 3328 "SendApplicationDefinedRTCPPacket() not sending"); 3329 return -1; 3330 } 3331 if (NULL == data) 3332 { 3333 _engineStatisticsPtr->SetLastError( 3334 VE_INVALID_ARGUMENT, kTraceError, 3335 "SendApplicationDefinedRTCPPacket() invalid data value"); 3336 return -1; 3337 } 3338 if (dataLengthInBytes % 4 != 0) 3339 { 3340 _engineStatisticsPtr->SetLastError( 3341 VE_INVALID_ARGUMENT, kTraceError, 3342 "SendApplicationDefinedRTCPPacket() invalid length value"); 3343 return -1; 3344 } 3345 RTCPMethod status = _rtpRtcpModule->RTCP(); 3346 if (status == kRtcpOff) 3347 { 3348 _engineStatisticsPtr->SetLastError( 3349 VE_RTCP_ERROR, kTraceError, 3350 "SendApplicationDefinedRTCPPacket() RTCP is disabled"); 3351 return -1; 3352 } 3353 3354 // Create and schedule the RTCP APP packet for transmission 3355 if (_rtpRtcpModule->SetRTCPApplicationSpecificData( 3356 subType, 3357 name, 3358 (const unsigned char*) data, 3359 dataLengthInBytes) != 0) 3360 { 3361 _engineStatisticsPtr->SetLastError( 3362 VE_SEND_ERROR, kTraceError, 3363 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet"); 3364 return -1; 3365 } 3366 return 0; 3367 } 3368 3369 int 3370 Channel::GetRTPStatistics( 3371 unsigned int& averageJitterMs, 3372 unsigned int& maxJitterMs, 3373 unsigned int& discardedPackets) 3374 { 3375 // The jitter statistics is updated for each received RTP packet and is 3376 // based on received packets. 3377 if (_rtpRtcpModule->RTCP() == kRtcpOff) { 3378 // If RTCP is off, there is no timed thread in the RTCP module regularly 3379 // generating new stats, trigger the update manually here instead. 3380 StreamStatistician* statistician = 3381 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); 3382 if (statistician) { 3383 // Don't use returned statistics, use data from proxy instead so that 3384 // max jitter can be fetched atomically. 3385 RtcpStatistics s; 3386 statistician->GetStatistics(&s, true); 3387 } 3388 } 3389 3390 ChannelStatistics stats = statistics_proxy_->GetStats(); 3391 const int32_t playoutFrequency = audio_coding_->PlayoutFrequency(); 3392 if (playoutFrequency > 0) { 3393 // Scale RTP statistics given the current playout frequency 3394 maxJitterMs = stats.max_jitter / (playoutFrequency / 1000); 3395 averageJitterMs = stats.rtcp.jitter / (playoutFrequency / 1000); 3396 } 3397 3398 discardedPackets = _numberOfDiscardedPackets; 3399 3400 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3401 VoEId(_instanceId, _channelId), 3402 "GetRTPStatistics() => averageJitterMs = %lu, maxJitterMs = %lu," 3403 " discardedPackets = %lu)", 3404 averageJitterMs, maxJitterMs, discardedPackets); 3405 return 0; 3406 } 3407 3408 int Channel::GetRemoteRTCPReportBlocks( 3409 std::vector<ReportBlock>* report_blocks) { 3410 if (report_blocks == NULL) { 3411 _engineStatisticsPtr->SetLastError(VE_INVALID_ARGUMENT, kTraceError, 3412 "GetRemoteRTCPReportBlock()s invalid report_blocks."); 3413 return -1; 3414 } 3415 3416 // Get the report blocks from the latest received RTCP Sender or Receiver 3417 // Report. Each element in the vector contains the sender's SSRC and a 3418 // report block according to RFC 3550. 3419 std::vector<RTCPReportBlock> rtcp_report_blocks; 3420 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) { 3421 _engineStatisticsPtr->SetLastError(VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3422 "GetRemoteRTCPReportBlocks() failed to read RTCP SR/RR report block."); 3423 return -1; 3424 } 3425 3426 if (rtcp_report_blocks.empty()) 3427 return 0; 3428 3429 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin(); 3430 for (; it != rtcp_report_blocks.end(); ++it) { 3431 ReportBlock report_block; 3432 report_block.sender_SSRC = it->remoteSSRC; 3433 report_block.source_SSRC = it->sourceSSRC; 3434 report_block.fraction_lost = it->fractionLost; 3435 report_block.cumulative_num_packets_lost = it->cumulativeLost; 3436 report_block.extended_highest_sequence_number = it->extendedHighSeqNum; 3437 report_block.interarrival_jitter = it->jitter; 3438 report_block.last_SR_timestamp = it->lastSR; 3439 report_block.delay_since_last_SR = it->delaySinceLastSR; 3440 report_blocks->push_back(report_block); 3441 } 3442 return 0; 3443 } 3444 3445 int 3446 Channel::GetRTPStatistics(CallStatistics& stats) 3447 { 3448 // --- RtcpStatistics 3449 3450 // The jitter statistics is updated for each received RTP packet and is 3451 // based on received packets. 3452 RtcpStatistics statistics; 3453 StreamStatistician* statistician = 3454 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC()); 3455 if (!statistician || !statistician->GetStatistics( 3456 &statistics, _rtpRtcpModule->RTCP() == kRtcpOff)) { 3457 _engineStatisticsPtr->SetLastError( 3458 VE_CANNOT_RETRIEVE_RTP_STAT, kTraceWarning, 3459 "GetRTPStatistics() failed to read RTP statistics from the " 3460 "RTP/RTCP module"); 3461 } 3462 3463 stats.fractionLost = statistics.fraction_lost; 3464 stats.cumulativeLost = statistics.cumulative_lost; 3465 stats.extendedMax = statistics.extended_max_sequence_number; 3466 stats.jitterSamples = statistics.jitter; 3467 3468 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3469 VoEId(_instanceId, _channelId), 3470 "GetRTPStatistics() => fractionLost=%lu, cumulativeLost=%lu," 3471 " extendedMax=%lu, jitterSamples=%li)", 3472 stats.fractionLost, stats.cumulativeLost, stats.extendedMax, 3473 stats.jitterSamples); 3474 3475 // --- RTT 3476 3477 uint16_t RTT(0); 3478 RTCPMethod method = _rtpRtcpModule->RTCP(); 3479 if (method == kRtcpOff) 3480 { 3481 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3482 VoEId(_instanceId, _channelId), 3483 "GetRTPStatistics() RTCP is disabled => valid RTT " 3484 "measurements cannot be retrieved"); 3485 } else 3486 { 3487 // The remote SSRC will be zero if no RTP packet has been received. 3488 uint32_t remoteSSRC = rtp_receiver_->SSRC(); 3489 if (remoteSSRC > 0) 3490 { 3491 uint16_t avgRTT(0); 3492 uint16_t maxRTT(0); 3493 uint16_t minRTT(0); 3494 3495 if (_rtpRtcpModule->RTT(remoteSSRC, &RTT, &avgRTT, &minRTT, &maxRTT) 3496 != 0) 3497 { 3498 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3499 VoEId(_instanceId, _channelId), 3500 "GetRTPStatistics() failed to retrieve RTT from " 3501 "the RTP/RTCP module"); 3502 } 3503 } else 3504 { 3505 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3506 VoEId(_instanceId, _channelId), 3507 "GetRTPStatistics() failed to measure RTT since no " 3508 "RTP packets have been received yet"); 3509 } 3510 } 3511 3512 stats.rttMs = static_cast<int> (RTT); 3513 3514 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3515 VoEId(_instanceId, _channelId), 3516 "GetRTPStatistics() => rttMs=%d", stats.rttMs); 3517 3518 // --- Data counters 3519 3520 uint32_t bytesSent(0); 3521 uint32_t packetsSent(0); 3522 uint32_t bytesReceived(0); 3523 uint32_t packetsReceived(0); 3524 3525 if (statistician) { 3526 statistician->GetDataCounters(&bytesReceived, &packetsReceived); 3527 } 3528 3529 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, 3530 &packetsSent) != 0) 3531 { 3532 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 3533 VoEId(_instanceId, _channelId), 3534 "GetRTPStatistics() failed to retrieve RTP datacounters =>" 3535 " output will not be complete"); 3536 } 3537 3538 stats.bytesSent = bytesSent; 3539 stats.packetsSent = packetsSent; 3540 stats.bytesReceived = bytesReceived; 3541 stats.packetsReceived = packetsReceived; 3542 3543 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3544 VoEId(_instanceId, _channelId), 3545 "GetRTPStatistics() => bytesSent=%d, packetsSent=%d," 3546 " bytesReceived=%d, packetsReceived=%d)", 3547 stats.bytesSent, stats.packetsSent, stats.bytesReceived, 3548 stats.packetsReceived); 3549 3550 // --- Timestamps 3551 { 3552 CriticalSectionScoped lock(ts_stats_lock_.get()); 3553 stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_; 3554 } 3555 return 0; 3556 } 3557 3558 int Channel::SetREDStatus(bool enable, int redPayloadtype) { 3559 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3560 "Channel::SetREDStatus()"); 3561 3562 if (enable) { 3563 if (redPayloadtype < 0 || redPayloadtype > 127) { 3564 _engineStatisticsPtr->SetLastError( 3565 VE_PLTYPE_ERROR, kTraceError, 3566 "SetREDStatus() invalid RED payload type"); 3567 return -1; 3568 } 3569 3570 if (SetRedPayloadType(redPayloadtype) < 0) { 3571 _engineStatisticsPtr->SetLastError( 3572 VE_CODEC_ERROR, kTraceError, 3573 "SetSecondarySendCodec() Failed to register RED ACM"); 3574 return -1; 3575 } 3576 } 3577 3578 if (audio_coding_->SetREDStatus(enable) != 0) { 3579 _engineStatisticsPtr->SetLastError( 3580 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 3581 "SetREDStatus() failed to set RED state in the ACM"); 3582 return -1; 3583 } 3584 return 0; 3585 } 3586 3587 int 3588 Channel::GetREDStatus(bool& enabled, int& redPayloadtype) 3589 { 3590 enabled = audio_coding_->REDStatus(); 3591 if (enabled) 3592 { 3593 int8_t payloadType(0); 3594 if (_rtpRtcpModule->SendREDPayloadType(payloadType) != 0) 3595 { 3596 _engineStatisticsPtr->SetLastError( 3597 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 3598 "GetREDStatus() failed to retrieve RED PT from RTP/RTCP " 3599 "module"); 3600 return -1; 3601 } 3602 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3603 VoEId(_instanceId, _channelId), 3604 "GetREDStatus() => enabled=%d, redPayloadtype=%d", 3605 enabled, redPayloadtype); 3606 return 0; 3607 } 3608 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3609 VoEId(_instanceId, _channelId), 3610 "GetREDStatus() => enabled=%d", enabled); 3611 return 0; 3612 } 3613 3614 int Channel::SetCodecFECStatus(bool enable) { 3615 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3616 "Channel::SetCodecFECStatus()"); 3617 3618 if (audio_coding_->SetCodecFEC(enable) != 0) { 3619 _engineStatisticsPtr->SetLastError( 3620 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 3621 "SetCodecFECStatus() failed to set FEC state"); 3622 return -1; 3623 } 3624 return 0; 3625 } 3626 3627 bool Channel::GetCodecFECStatus() { 3628 bool enabled = audio_coding_->CodecFEC(); 3629 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 3630 VoEId(_instanceId, _channelId), 3631 "GetCodecFECStatus() => enabled=%d", enabled); 3632 return enabled; 3633 } 3634 3635 void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) { 3636 // None of these functions can fail. 3637 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets); 3638 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets); 3639 rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff); 3640 if (enable) 3641 audio_coding_->EnableNack(maxNumberOfPackets); 3642 else 3643 audio_coding_->DisableNack(); 3644 } 3645 3646 // Called when we are missing one or more packets. 3647 int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) { 3648 return _rtpRtcpModule->SendNACK(sequence_numbers, length); 3649 } 3650 3651 int 3652 Channel::StartRTPDump(const char fileNameUTF8[1024], 3653 RTPDirections direction) 3654 { 3655 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3656 "Channel::StartRTPDump()"); 3657 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing)) 3658 { 3659 _engineStatisticsPtr->SetLastError( 3660 VE_INVALID_ARGUMENT, kTraceError, 3661 "StartRTPDump() invalid RTP direction"); 3662 return -1; 3663 } 3664 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ? 3665 &_rtpDumpIn : &_rtpDumpOut; 3666 if (rtpDumpPtr == NULL) 3667 { 3668 assert(false); 3669 return -1; 3670 } 3671 if (rtpDumpPtr->IsActive()) 3672 { 3673 rtpDumpPtr->Stop(); 3674 } 3675 if (rtpDumpPtr->Start(fileNameUTF8) != 0) 3676 { 3677 _engineStatisticsPtr->SetLastError( 3678 VE_BAD_FILE, kTraceError, 3679 "StartRTPDump() failed to create file"); 3680 return -1; 3681 } 3682 return 0; 3683 } 3684 3685 int 3686 Channel::StopRTPDump(RTPDirections direction) 3687 { 3688 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId), 3689 "Channel::StopRTPDump()"); 3690 if ((direction != kRtpIncoming) && (direction != kRtpOutgoing)) 3691 { 3692 _engineStatisticsPtr->SetLastError( 3693 VE_INVALID_ARGUMENT, kTraceError, 3694 "StopRTPDump() invalid RTP direction"); 3695 return -1; 3696 } 3697 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ? 3698 &_rtpDumpIn : &_rtpDumpOut; 3699 if (rtpDumpPtr == NULL) 3700 { 3701 assert(false); 3702 return -1; 3703 } 3704 if (!rtpDumpPtr->IsActive()) 3705 { 3706 return 0; 3707 } 3708 return rtpDumpPtr->Stop(); 3709 } 3710 3711 bool 3712 Channel::RTPDumpIsActive(RTPDirections direction) 3713 { 3714 if ((direction != kRtpIncoming) && 3715 (direction != kRtpOutgoing)) 3716 { 3717 _engineStatisticsPtr->SetLastError( 3718 VE_INVALID_ARGUMENT, kTraceError, 3719 "RTPDumpIsActive() invalid RTP direction"); 3720 return false; 3721 } 3722 RtpDump* rtpDumpPtr = (direction == kRtpIncoming) ? 3723 &_rtpDumpIn : &_rtpDumpOut; 3724 return rtpDumpPtr->IsActive(); 3725 } 3726 3727 void Channel::SetVideoEngineBWETarget(ViENetwork* vie_network, 3728 int video_channel) { 3729 CriticalSectionScoped cs(&_callbackCritSect); 3730 if (vie_network_) { 3731 vie_network_->Release(); 3732 vie_network_ = NULL; 3733 } 3734 video_channel_ = -1; 3735 3736 if (vie_network != NULL && video_channel != -1) { 3737 vie_network_ = vie_network; 3738 video_channel_ = video_channel; 3739 } 3740 } 3741 3742 uint32_t 3743 Channel::Demultiplex(const AudioFrame& audioFrame) 3744 { 3745 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3746 "Channel::Demultiplex()"); 3747 _audioFrame.CopyFrom(audioFrame); 3748 _audioFrame.id_ = _channelId; 3749 return 0; 3750 } 3751 3752 void Channel::Demultiplex(const int16_t* audio_data, 3753 int sample_rate, 3754 int number_of_frames, 3755 int number_of_channels) { 3756 CodecInst codec; 3757 GetSendCodec(codec); 3758 3759 if (!mono_recording_audio_.get()) { 3760 // Temporary space for DownConvertToCodecFormat. 3761 mono_recording_audio_.reset(new int16_t[kMaxMonoDataSizeSamples]); 3762 } 3763 DownConvertToCodecFormat(audio_data, 3764 number_of_frames, 3765 number_of_channels, 3766 sample_rate, 3767 codec.channels, 3768 codec.plfreq, 3769 mono_recording_audio_.get(), 3770 &input_resampler_, 3771 &_audioFrame); 3772 } 3773 3774 uint32_t 3775 Channel::PrepareEncodeAndSend(int mixingFrequency) 3776 { 3777 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3778 "Channel::PrepareEncodeAndSend()"); 3779 3780 if (_audioFrame.samples_per_channel_ == 0) 3781 { 3782 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3783 "Channel::PrepareEncodeAndSend() invalid audio frame"); 3784 return -1; 3785 } 3786 3787 if (channel_state_.Get().input_file_playing) 3788 { 3789 MixOrReplaceAudioWithFile(mixingFrequency); 3790 } 3791 3792 bool is_muted = Mute(); // Cache locally as Mute() takes a lock. 3793 if (is_muted) { 3794 AudioFrameOperations::Mute(_audioFrame); 3795 } 3796 3797 if (channel_state_.Get().input_external_media) 3798 { 3799 CriticalSectionScoped cs(&_callbackCritSect); 3800 const bool isStereo = (_audioFrame.num_channels_ == 2); 3801 if (_inputExternalMediaCallbackPtr) 3802 { 3803 _inputExternalMediaCallbackPtr->Process( 3804 _channelId, 3805 kRecordingPerChannel, 3806 (int16_t*)_audioFrame.data_, 3807 _audioFrame.samples_per_channel_, 3808 _audioFrame.sample_rate_hz_, 3809 isStereo); 3810 } 3811 } 3812 3813 InsertInbandDtmfTone(); 3814 3815 if (_includeAudioLevelIndication) { 3816 int length = _audioFrame.samples_per_channel_ * _audioFrame.num_channels_; 3817 if (is_muted) { 3818 rms_level_.ProcessMuted(length); 3819 } else { 3820 rms_level_.Process(_audioFrame.data_, length); 3821 } 3822 } 3823 3824 return 0; 3825 } 3826 3827 uint32_t 3828 Channel::EncodeAndSend() 3829 { 3830 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 3831 "Channel::EncodeAndSend()"); 3832 3833 assert(_audioFrame.num_channels_ <= 2); 3834 if (_audioFrame.samples_per_channel_ == 0) 3835 { 3836 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 3837 "Channel::EncodeAndSend() invalid audio frame"); 3838 return -1; 3839 } 3840 3841 _audioFrame.id_ = _channelId; 3842 3843 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz. 3844 3845 // The ACM resamples internally. 3846 _audioFrame.timestamp_ = _timeStamp; 3847 if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) != 0) 3848 { 3849 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), 3850 "Channel::EncodeAndSend() ACM encoding failed"); 3851 return -1; 3852 } 3853 3854 _timeStamp += _audioFrame.samples_per_channel_; 3855 3856 // --- Encode if complete frame is ready 3857 3858 // This call will trigger AudioPacketizationCallback::SendData if encoding 3859 // is done and payload is ready for packetization and transmission. 3860 return audio_coding_->Process(); 3861 } 3862 3863 int Channel::RegisterExternalMediaProcessing( 3864 ProcessingTypes type, 3865 VoEMediaProcess& processObject) 3866 { 3867 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3868 "Channel::RegisterExternalMediaProcessing()"); 3869 3870 CriticalSectionScoped cs(&_callbackCritSect); 3871 3872 if (kPlaybackPerChannel == type) 3873 { 3874 if (_outputExternalMediaCallbackPtr) 3875 { 3876 _engineStatisticsPtr->SetLastError( 3877 VE_INVALID_OPERATION, kTraceError, 3878 "Channel::RegisterExternalMediaProcessing() " 3879 "output external media already enabled"); 3880 return -1; 3881 } 3882 _outputExternalMediaCallbackPtr = &processObject; 3883 _outputExternalMedia = true; 3884 } 3885 else if (kRecordingPerChannel == type) 3886 { 3887 if (_inputExternalMediaCallbackPtr) 3888 { 3889 _engineStatisticsPtr->SetLastError( 3890 VE_INVALID_OPERATION, kTraceError, 3891 "Channel::RegisterExternalMediaProcessing() " 3892 "output external media already enabled"); 3893 return -1; 3894 } 3895 _inputExternalMediaCallbackPtr = &processObject; 3896 channel_state_.SetInputExternalMedia(true); 3897 } 3898 return 0; 3899 } 3900 3901 int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type) 3902 { 3903 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3904 "Channel::DeRegisterExternalMediaProcessing()"); 3905 3906 CriticalSectionScoped cs(&_callbackCritSect); 3907 3908 if (kPlaybackPerChannel == type) 3909 { 3910 if (!_outputExternalMediaCallbackPtr) 3911 { 3912 _engineStatisticsPtr->SetLastError( 3913 VE_INVALID_OPERATION, kTraceWarning, 3914 "Channel::DeRegisterExternalMediaProcessing() " 3915 "output external media already disabled"); 3916 return 0; 3917 } 3918 _outputExternalMedia = false; 3919 _outputExternalMediaCallbackPtr = NULL; 3920 } 3921 else if (kRecordingPerChannel == type) 3922 { 3923 if (!_inputExternalMediaCallbackPtr) 3924 { 3925 _engineStatisticsPtr->SetLastError( 3926 VE_INVALID_OPERATION, kTraceWarning, 3927 "Channel::DeRegisterExternalMediaProcessing() " 3928 "input external media already disabled"); 3929 return 0; 3930 } 3931 channel_state_.SetInputExternalMedia(false); 3932 _inputExternalMediaCallbackPtr = NULL; 3933 } 3934 3935 return 0; 3936 } 3937 3938 int Channel::SetExternalMixing(bool enabled) { 3939 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3940 "Channel::SetExternalMixing(enabled=%d)", enabled); 3941 3942 if (channel_state_.Get().playing) 3943 { 3944 _engineStatisticsPtr->SetLastError( 3945 VE_INVALID_OPERATION, kTraceError, 3946 "Channel::SetExternalMixing() " 3947 "external mixing cannot be changed while playing."); 3948 return -1; 3949 } 3950 3951 _externalMixing = enabled; 3952 3953 return 0; 3954 } 3955 3956 int 3957 Channel::GetNetworkStatistics(NetworkStatistics& stats) 3958 { 3959 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3960 "Channel::GetNetworkStatistics()"); 3961 ACMNetworkStatistics acm_stats; 3962 int return_value = audio_coding_->NetworkStatistics(&acm_stats); 3963 if (return_value >= 0) { 3964 memcpy(&stats, &acm_stats, sizeof(NetworkStatistics)); 3965 } 3966 return return_value; 3967 } 3968 3969 void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const { 3970 audio_coding_->GetDecodingCallStatistics(stats); 3971 } 3972 3973 bool Channel::GetDelayEstimate(int* jitter_buffer_delay_ms, 3974 int* playout_buffer_delay_ms) const { 3975 if (_average_jitter_buffer_delay_us == 0) { 3976 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3977 "Channel::GetDelayEstimate() no valid estimate."); 3978 return false; 3979 } 3980 *jitter_buffer_delay_ms = (_average_jitter_buffer_delay_us + 500) / 1000 + 3981 _recPacketDelayMs; 3982 *playout_buffer_delay_ms = playout_delay_ms_; 3983 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3984 "Channel::GetDelayEstimate()"); 3985 return true; 3986 } 3987 3988 int Channel::SetInitialPlayoutDelay(int delay_ms) 3989 { 3990 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 3991 "Channel::SetInitialPlayoutDelay()"); 3992 if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) || 3993 (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs)) 3994 { 3995 _engineStatisticsPtr->SetLastError( 3996 VE_INVALID_ARGUMENT, kTraceError, 3997 "SetInitialPlayoutDelay() invalid min delay"); 3998 return -1; 3999 } 4000 if (audio_coding_->SetInitialPlayoutDelay(delay_ms) != 0) 4001 { 4002 _engineStatisticsPtr->SetLastError( 4003 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4004 "SetInitialPlayoutDelay() failed to set min playout delay"); 4005 return -1; 4006 } 4007 return 0; 4008 } 4009 4010 4011 int 4012 Channel::SetMinimumPlayoutDelay(int delayMs) 4013 { 4014 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4015 "Channel::SetMinimumPlayoutDelay()"); 4016 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) || 4017 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) 4018 { 4019 _engineStatisticsPtr->SetLastError( 4020 VE_INVALID_ARGUMENT, kTraceError, 4021 "SetMinimumPlayoutDelay() invalid min delay"); 4022 return -1; 4023 } 4024 if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) 4025 { 4026 _engineStatisticsPtr->SetLastError( 4027 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4028 "SetMinimumPlayoutDelay() failed to set min playout delay"); 4029 return -1; 4030 } 4031 return 0; 4032 } 4033 4034 void Channel::UpdatePlayoutTimestamp(bool rtcp) { 4035 uint32_t playout_timestamp = 0; 4036 4037 if (audio_coding_->PlayoutTimestamp(&playout_timestamp) == -1) { 4038 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 4039 "Channel::UpdatePlayoutTimestamp() failed to read playout" 4040 " timestamp from the ACM"); 4041 _engineStatisticsPtr->SetLastError( 4042 VE_CANNOT_RETRIEVE_VALUE, kTraceError, 4043 "UpdatePlayoutTimestamp() failed to retrieve timestamp"); 4044 return; 4045 } 4046 4047 uint16_t delay_ms = 0; 4048 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) { 4049 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 4050 "Channel::UpdatePlayoutTimestamp() failed to read playout" 4051 " delay from the ADM"); 4052 _engineStatisticsPtr->SetLastError( 4053 VE_CANNOT_RETRIEVE_VALUE, kTraceError, 4054 "UpdatePlayoutTimestamp() failed to retrieve playout delay"); 4055 return; 4056 } 4057 4058 jitter_buffer_playout_timestamp_ = playout_timestamp; 4059 4060 // Remove the playout delay. 4061 playout_timestamp -= (delay_ms * (GetPlayoutFrequency() / 1000)); 4062 4063 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 4064 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu", 4065 playout_timestamp); 4066 4067 if (rtcp) { 4068 playout_timestamp_rtcp_ = playout_timestamp; 4069 } else { 4070 playout_timestamp_rtp_ = playout_timestamp; 4071 } 4072 playout_delay_ms_ = delay_ms; 4073 } 4074 4075 int Channel::GetPlayoutTimestamp(unsigned int& timestamp) { 4076 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4077 "Channel::GetPlayoutTimestamp()"); 4078 if (playout_timestamp_rtp_ == 0) { 4079 _engineStatisticsPtr->SetLastError( 4080 VE_CANNOT_RETRIEVE_VALUE, kTraceError, 4081 "GetPlayoutTimestamp() failed to retrieve timestamp"); 4082 return -1; 4083 } 4084 timestamp = playout_timestamp_rtp_; 4085 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, 4086 VoEId(_instanceId,_channelId), 4087 "GetPlayoutTimestamp() => timestamp=%u", timestamp); 4088 return 0; 4089 } 4090 4091 int 4092 Channel::SetInitTimestamp(unsigned int timestamp) 4093 { 4094 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4095 "Channel::SetInitTimestamp()"); 4096 if (channel_state_.Get().sending) 4097 { 4098 _engineStatisticsPtr->SetLastError( 4099 VE_SENDING, kTraceError, "SetInitTimestamp() already sending"); 4100 return -1; 4101 } 4102 if (_rtpRtcpModule->SetStartTimestamp(timestamp) != 0) 4103 { 4104 _engineStatisticsPtr->SetLastError( 4105 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 4106 "SetInitTimestamp() failed to set timestamp"); 4107 return -1; 4108 } 4109 return 0; 4110 } 4111 4112 int 4113 Channel::SetInitSequenceNumber(short sequenceNumber) 4114 { 4115 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4116 "Channel::SetInitSequenceNumber()"); 4117 if (channel_state_.Get().sending) 4118 { 4119 _engineStatisticsPtr->SetLastError( 4120 VE_SENDING, kTraceError, 4121 "SetInitSequenceNumber() already sending"); 4122 return -1; 4123 } 4124 if (_rtpRtcpModule->SetSequenceNumber(sequenceNumber) != 0) 4125 { 4126 _engineStatisticsPtr->SetLastError( 4127 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 4128 "SetInitSequenceNumber() failed to set sequence number"); 4129 return -1; 4130 } 4131 return 0; 4132 } 4133 4134 int 4135 Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const 4136 { 4137 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4138 "Channel::GetRtpRtcp()"); 4139 *rtpRtcpModule = _rtpRtcpModule.get(); 4140 *rtp_receiver = rtp_receiver_.get(); 4141 return 0; 4142 } 4143 4144 // TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use 4145 // a shared helper. 4146 int32_t 4147 Channel::MixOrReplaceAudioWithFile(int mixingFrequency) 4148 { 4149 scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]); 4150 int fileSamples(0); 4151 4152 { 4153 CriticalSectionScoped cs(&_fileCritSect); 4154 4155 if (_inputFilePlayerPtr == NULL) 4156 { 4157 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4158 VoEId(_instanceId, _channelId), 4159 "Channel::MixOrReplaceAudioWithFile() fileplayer" 4160 " doesnt exist"); 4161 return -1; 4162 } 4163 4164 if (_inputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(), 4165 fileSamples, 4166 mixingFrequency) == -1) 4167 { 4168 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4169 VoEId(_instanceId, _channelId), 4170 "Channel::MixOrReplaceAudioWithFile() file mixing " 4171 "failed"); 4172 return -1; 4173 } 4174 if (fileSamples == 0) 4175 { 4176 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4177 VoEId(_instanceId, _channelId), 4178 "Channel::MixOrReplaceAudioWithFile() file is ended"); 4179 return 0; 4180 } 4181 } 4182 4183 assert(_audioFrame.samples_per_channel_ == fileSamples); 4184 4185 if (_mixFileWithMicrophone) 4186 { 4187 // Currently file stream is always mono. 4188 // TODO(xians): Change the code when FilePlayer supports real stereo. 4189 MixWithSat(_audioFrame.data_, 4190 _audioFrame.num_channels_, 4191 fileBuffer.get(), 4192 1, 4193 fileSamples); 4194 } 4195 else 4196 { 4197 // Replace ACM audio with file. 4198 // Currently file stream is always mono. 4199 // TODO(xians): Change the code when FilePlayer supports real stereo. 4200 _audioFrame.UpdateFrame(_channelId, 4201 -1, 4202 fileBuffer.get(), 4203 fileSamples, 4204 mixingFrequency, 4205 AudioFrame::kNormalSpeech, 4206 AudioFrame::kVadUnknown, 4207 1); 4208 4209 } 4210 return 0; 4211 } 4212 4213 int32_t 4214 Channel::MixAudioWithFile(AudioFrame& audioFrame, 4215 int mixingFrequency) 4216 { 4217 assert(mixingFrequency <= 32000); 4218 4219 scoped_ptr<int16_t[]> fileBuffer(new int16_t[640]); 4220 int fileSamples(0); 4221 4222 { 4223 CriticalSectionScoped cs(&_fileCritSect); 4224 4225 if (_outputFilePlayerPtr == NULL) 4226 { 4227 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4228 VoEId(_instanceId, _channelId), 4229 "Channel::MixAudioWithFile() file mixing failed"); 4230 return -1; 4231 } 4232 4233 // We should get the frequency we ask for. 4234 if (_outputFilePlayerPtr->Get10msAudioFromFile(fileBuffer.get(), 4235 fileSamples, 4236 mixingFrequency) == -1) 4237 { 4238 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4239 VoEId(_instanceId, _channelId), 4240 "Channel::MixAudioWithFile() file mixing failed"); 4241 return -1; 4242 } 4243 } 4244 4245 if (audioFrame.samples_per_channel_ == fileSamples) 4246 { 4247 // Currently file stream is always mono. 4248 // TODO(xians): Change the code when FilePlayer supports real stereo. 4249 MixWithSat(audioFrame.data_, 4250 audioFrame.num_channels_, 4251 fileBuffer.get(), 4252 1, 4253 fileSamples); 4254 } 4255 else 4256 { 4257 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), 4258 "Channel::MixAudioWithFile() samples_per_channel_(%d) != " 4259 "fileSamples(%d)", 4260 audioFrame.samples_per_channel_, fileSamples); 4261 return -1; 4262 } 4263 4264 return 0; 4265 } 4266 4267 int 4268 Channel::InsertInbandDtmfTone() 4269 { 4270 // Check if we should start a new tone. 4271 if (_inbandDtmfQueue.PendingDtmf() && 4272 !_inbandDtmfGenerator.IsAddingTone() && 4273 _inbandDtmfGenerator.DelaySinceLastTone() > 4274 kMinTelephoneEventSeparationMs) 4275 { 4276 int8_t eventCode(0); 4277 uint16_t lengthMs(0); 4278 uint8_t attenuationDb(0); 4279 4280 eventCode = _inbandDtmfQueue.NextDtmf(&lengthMs, &attenuationDb); 4281 _inbandDtmfGenerator.AddTone(eventCode, lengthMs, attenuationDb); 4282 if (_playInbandDtmfEvent) 4283 { 4284 // Add tone to output mixer using a reduced length to minimize 4285 // risk of echo. 4286 _outputMixerPtr->PlayDtmfTone(eventCode, lengthMs - 80, 4287 attenuationDb); 4288 } 4289 } 4290 4291 if (_inbandDtmfGenerator.IsAddingTone()) 4292 { 4293 uint16_t frequency(0); 4294 _inbandDtmfGenerator.GetSampleRate(frequency); 4295 4296 if (frequency != _audioFrame.sample_rate_hz_) 4297 { 4298 // Update sample rate of Dtmf tone since the mixing frequency 4299 // has changed. 4300 _inbandDtmfGenerator.SetSampleRate( 4301 (uint16_t) (_audioFrame.sample_rate_hz_)); 4302 // Reset the tone to be added taking the new sample rate into 4303 // account. 4304 _inbandDtmfGenerator.ResetTone(); 4305 } 4306 4307 int16_t toneBuffer[320]; 4308 uint16_t toneSamples(0); 4309 // Get 10ms tone segment and set time since last tone to zero 4310 if (_inbandDtmfGenerator.Get10msTone(toneBuffer, toneSamples) == -1) 4311 { 4312 WEBRTC_TRACE(kTraceWarning, kTraceVoice, 4313 VoEId(_instanceId, _channelId), 4314 "Channel::EncodeAndSend() inserting Dtmf failed"); 4315 return -1; 4316 } 4317 4318 // Replace mixed audio with DTMF tone. 4319 for (int sample = 0; 4320 sample < _audioFrame.samples_per_channel_; 4321 sample++) 4322 { 4323 for (int channel = 0; 4324 channel < _audioFrame.num_channels_; 4325 channel++) 4326 { 4327 const int index = sample * _audioFrame.num_channels_ + channel; 4328 _audioFrame.data_[index] = toneBuffer[sample]; 4329 } 4330 } 4331 4332 assert(_audioFrame.samples_per_channel_ == toneSamples); 4333 } else 4334 { 4335 // Add 10ms to "delay-since-last-tone" counter 4336 _inbandDtmfGenerator.UpdateDelaySinceLastTone(); 4337 } 4338 return 0; 4339 } 4340 4341 int32_t 4342 Channel::SendPacketRaw(const void *data, int len, bool RTCP) 4343 { 4344 CriticalSectionScoped cs(&_callbackCritSect); 4345 if (_transportPtr == NULL) 4346 { 4347 return -1; 4348 } 4349 if (!RTCP) 4350 { 4351 return _transportPtr->SendPacket(_channelId, data, len); 4352 } 4353 else 4354 { 4355 return _transportPtr->SendRTCPPacket(_channelId, data, len); 4356 } 4357 } 4358 4359 // Called for incoming RTP packets after successful RTP header parsing. 4360 void Channel::UpdatePacketDelay(uint32_t rtp_timestamp, 4361 uint16_t sequence_number) { 4362 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId,_channelId), 4363 "Channel::UpdatePacketDelay(timestamp=%lu, sequenceNumber=%u)", 4364 rtp_timestamp, sequence_number); 4365 4366 // Get frequency of last received payload 4367 int rtp_receive_frequency = GetPlayoutFrequency(); 4368 4369 // Update the least required delay. 4370 least_required_delay_ms_ = audio_coding_->LeastRequiredDelayMs(); 4371 4372 // |jitter_buffer_playout_timestamp_| updated in UpdatePlayoutTimestamp for 4373 // every incoming packet. 4374 uint32_t timestamp_diff_ms = (rtp_timestamp - 4375 jitter_buffer_playout_timestamp_) / (rtp_receive_frequency / 1000); 4376 if (!IsNewerTimestamp(rtp_timestamp, jitter_buffer_playout_timestamp_) || 4377 timestamp_diff_ms > (2 * kVoiceEngineMaxMinPlayoutDelayMs)) { 4378 // If |jitter_buffer_playout_timestamp_| is newer than the incoming RTP 4379 // timestamp, the resulting difference is negative, but is set to zero. 4380 // This can happen when a network glitch causes a packet to arrive late, 4381 // and during long comfort noise periods with clock drift. 4382 timestamp_diff_ms = 0; 4383 } 4384 4385 uint16_t packet_delay_ms = (rtp_timestamp - _previousTimestamp) / 4386 (rtp_receive_frequency / 1000); 4387 4388 _previousTimestamp = rtp_timestamp; 4389 4390 if (timestamp_diff_ms == 0) return; 4391 4392 if (packet_delay_ms >= 10 && packet_delay_ms <= 60) { 4393 _recPacketDelayMs = packet_delay_ms; 4394 } 4395 4396 if (_average_jitter_buffer_delay_us == 0) { 4397 _average_jitter_buffer_delay_us = timestamp_diff_ms * 1000; 4398 return; 4399 } 4400 4401 // Filter average delay value using exponential filter (alpha is 4402 // 7/8). We derive 1000 *_average_jitter_buffer_delay_us here (reduces 4403 // risk of rounding error) and compensate for it in GetDelayEstimate() 4404 // later. 4405 _average_jitter_buffer_delay_us = (_average_jitter_buffer_delay_us * 7 + 4406 1000 * timestamp_diff_ms + 500) / 8; 4407 } 4408 4409 void 4410 Channel::RegisterReceiveCodecsToRTPModule() 4411 { 4412 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), 4413 "Channel::RegisterReceiveCodecsToRTPModule()"); 4414 4415 4416 CodecInst codec; 4417 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs(); 4418 4419 for (int idx = 0; idx < nSupportedCodecs; idx++) 4420 { 4421 // Open up the RTP/RTCP receiver for all supported codecs 4422 if ((audio_coding_->Codec(idx, &codec) == -1) || 4423 (rtp_receiver_->RegisterReceivePayload( 4424 codec.plname, 4425 codec.pltype, 4426 codec.plfreq, 4427 codec.channels, 4428 (codec.rate < 0) ? 0 : codec.rate) == -1)) 4429 { 4430 WEBRTC_TRACE( 4431 kTraceWarning, 4432 kTraceVoice, 4433 VoEId(_instanceId, _channelId), 4434 "Channel::RegisterReceiveCodecsToRTPModule() unable" 4435 " to register %s (%d/%d/%d/%d) to RTP/RTCP receiver", 4436 codec.plname, codec.pltype, codec.plfreq, 4437 codec.channels, codec.rate); 4438 } 4439 else 4440 { 4441 WEBRTC_TRACE( 4442 kTraceInfo, 4443 kTraceVoice, 4444 VoEId(_instanceId, _channelId), 4445 "Channel::RegisterReceiveCodecsToRTPModule() %s " 4446 "(%d/%d/%d/%d) has been added to the RTP/RTCP " 4447 "receiver", 4448 codec.plname, codec.pltype, codec.plfreq, 4449 codec.channels, codec.rate); 4450 } 4451 } 4452 } 4453 4454 int Channel::SetSecondarySendCodec(const CodecInst& codec, 4455 int red_payload_type) { 4456 // Sanity check for payload type. 4457 if (red_payload_type < 0 || red_payload_type > 127) { 4458 _engineStatisticsPtr->SetLastError( 4459 VE_PLTYPE_ERROR, kTraceError, 4460 "SetRedPayloadType() invalid RED payload type"); 4461 return -1; 4462 } 4463 4464 if (SetRedPayloadType(red_payload_type) < 0) { 4465 _engineStatisticsPtr->SetLastError( 4466 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4467 "SetSecondarySendCodec() Failed to register RED ACM"); 4468 return -1; 4469 } 4470 if (audio_coding_->RegisterSecondarySendCodec(codec) < 0) { 4471 _engineStatisticsPtr->SetLastError( 4472 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4473 "SetSecondarySendCodec() Failed to register secondary send codec in " 4474 "ACM"); 4475 return -1; 4476 } 4477 4478 return 0; 4479 } 4480 4481 void Channel::RemoveSecondarySendCodec() { 4482 audio_coding_->UnregisterSecondarySendCodec(); 4483 } 4484 4485 int Channel::GetSecondarySendCodec(CodecInst* codec) { 4486 if (audio_coding_->SecondarySendCodec(codec) < 0) { 4487 _engineStatisticsPtr->SetLastError( 4488 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4489 "GetSecondarySendCodec() Failed to get secondary sent codec from ACM"); 4490 return -1; 4491 } 4492 return 0; 4493 } 4494 4495 // Assuming this method is called with valid payload type. 4496 int Channel::SetRedPayloadType(int red_payload_type) { 4497 CodecInst codec; 4498 bool found_red = false; 4499 4500 // Get default RED settings from the ACM database 4501 const int num_codecs = AudioCodingModule::NumberOfCodecs(); 4502 for (int idx = 0; idx < num_codecs; idx++) { 4503 audio_coding_->Codec(idx, &codec); 4504 if (!STR_CASE_CMP(codec.plname, "RED")) { 4505 found_red = true; 4506 break; 4507 } 4508 } 4509 4510 if (!found_red) { 4511 _engineStatisticsPtr->SetLastError( 4512 VE_CODEC_ERROR, kTraceError, 4513 "SetRedPayloadType() RED is not supported"); 4514 return -1; 4515 } 4516 4517 codec.pltype = red_payload_type; 4518 if (audio_coding_->RegisterSendCodec(codec) < 0) { 4519 _engineStatisticsPtr->SetLastError( 4520 VE_AUDIO_CODING_MODULE_ERROR, kTraceError, 4521 "SetRedPayloadType() RED registration in ACM module failed"); 4522 return -1; 4523 } 4524 4525 if (_rtpRtcpModule->SetSendREDPayloadType(red_payload_type) != 0) { 4526 _engineStatisticsPtr->SetLastError( 4527 VE_RTP_RTCP_MODULE_ERROR, kTraceError, 4528 "SetRedPayloadType() RED registration in RTP/RTCP module failed"); 4529 return -1; 4530 } 4531 return 0; 4532 } 4533 4534 int Channel::SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, 4535 unsigned char id) { 4536 int error = 0; 4537 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type); 4538 if (enable) { 4539 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id); 4540 } 4541 return error; 4542 } 4543 4544 int32_t Channel::GetPlayoutFrequency() { 4545 int32_t playout_frequency = audio_coding_->PlayoutFrequency(); 4546 CodecInst current_recive_codec; 4547 if (audio_coding_->ReceiveCodec(¤t_recive_codec) == 0) { 4548 if (STR_CASE_CMP("G722", current_recive_codec.plname) == 0) { 4549 // Even though the actual sampling rate for G.722 audio is 4550 // 16,000 Hz, the RTP clock rate for the G722 payload format is 4551 // 8,000 Hz because that value was erroneously assigned in 4552 // RFC 1890 and must remain unchanged for backward compatibility. 4553 playout_frequency = 8000; 4554 } else if (STR_CASE_CMP("opus", current_recive_codec.plname) == 0) { 4555 // We are resampling Opus internally to 32,000 Hz until all our 4556 // DSP routines can operate at 48,000 Hz, but the RTP clock 4557 // rate for the Opus payload format is standardized to 48,000 Hz, 4558 // because that is the maximum supported decoding sampling rate. 4559 playout_frequency = 48000; 4560 } 4561 } 4562 return playout_frequency; 4563 } 4564 4565 } // namespace voe 4566 } // namespace webrtc 4567