/* * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "audio/voip/audio_channel.h" #include #include #include "api/audio_codecs/audio_format.h" #include "api/task_queue/task_queue_factory.h" #include "modules/rtp_rtcp/include/receive_statistics.h" #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h" #include "rtc_base/location.h" #include "rtc_base/logging.h" namespace webrtc { namespace { constexpr int kRtcpReportIntervalMs = 5000; } // namespace AudioChannel::AudioChannel( Transport* transport, uint32_t local_ssrc, TaskQueueFactory* task_queue_factory, ProcessThread* process_thread, AudioMixer* audio_mixer, rtc::scoped_refptr decoder_factory) : audio_mixer_(audio_mixer), process_thread_(process_thread) { RTC_DCHECK(task_queue_factory); RTC_DCHECK(process_thread); RTC_DCHECK(audio_mixer); Clock* clock = Clock::GetRealTimeClock(); receive_statistics_ = ReceiveStatistics::Create(clock); RtpRtcpInterface::Configuration rtp_config; rtp_config.clock = clock; rtp_config.audio = true; rtp_config.receive_statistics = receive_statistics_.get(); rtp_config.rtcp_report_interval_ms = kRtcpReportIntervalMs; rtp_config.outgoing_transport = transport; rtp_config.local_media_ssrc = local_ssrc; rtp_rtcp_ = ModuleRtpRtcpImpl2::Create(rtp_config); rtp_rtcp_->SetSendingMediaStatus(false); rtp_rtcp_->SetRTCPStatus(RtcpMode::kCompound); // ProcessThread periodically services RTP stack for RTCP. process_thread_->RegisterModule(rtp_rtcp_.get(), RTC_FROM_HERE); ingress_ = std::make_unique(rtp_rtcp_.get(), clock, receive_statistics_.get(), std::move(decoder_factory)); egress_ = std::make_unique(rtp_rtcp_.get(), clock, task_queue_factory); // Set the instance of audio ingress to be part of audio mixer for ADM to // fetch audio samples to play. audio_mixer_->AddSource(ingress_.get()); } AudioChannel::~AudioChannel() { if (egress_->IsSending()) { StopSend(); } if (ingress_->IsPlaying()) { StopPlay(); } audio_mixer_->RemoveSource(ingress_.get()); process_thread_->DeRegisterModule(rtp_rtcp_.get()); } void AudioChannel::StartSend() { egress_->StartSend(); // Start sending with RTP stack if it has not been sending yet. if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) { RTC_DLOG(LS_ERROR) << "StartSend() RTP/RTCP failed to start sending"; } } void AudioChannel::StopSend() { egress_->StopSend(); // If the channel is not playing and RTP stack is active then deactivate RTP // stack. SetSendingStatus(false) triggers the transmission of RTCP BYE // message to remote endpoint. if (!IsPlaying() && rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(false) != 0) { RTC_DLOG(LS_ERROR) << "StopSend() RTP/RTCP failed to stop sending"; } } void AudioChannel::StartPlay() { ingress_->StartPlay(); // If RTP stack is not sending then start sending as in recv-only mode, RTCP // receiver report is expected. if (!rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(true) != 0) { RTC_DLOG(LS_ERROR) << "StartPlay() RTP/RTCP failed to start sending"; } } void AudioChannel::StopPlay() { ingress_->StopPlay(); // Deactivate RTP stack only when both sending and receiving are stopped. if (!IsSendingMedia() && rtp_rtcp_->Sending() && rtp_rtcp_->SetSendingStatus(false) != 0) { RTC_DLOG(LS_ERROR) << "StopPlay() RTP/RTCP failed to stop sending"; } } } // namespace webrtc