/* * Copyright (c) 2017 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 "modules/rtp_rtcp/source/rtcp_transceiver.h" #include #include "absl/memory/memory.h" #include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include "rtc_base/checks.h" #include "rtc_base/event.h" #include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/time_utils.h" namespace webrtc { namespace { struct Destructor { void operator()() { rtcp_transceiver->StopPeriodicTask(); rtcp_transceiver = nullptr; } std::unique_ptr rtcp_transceiver; }; } // namespace RtcpTransceiver::RtcpTransceiver(const RtcpTransceiverConfig& config) : task_queue_(config.task_queue), rtcp_transceiver_(absl::make_unique(config)) { RTC_DCHECK(task_queue_); } RtcpTransceiver::~RtcpTransceiver() { if (!rtcp_transceiver_) return; task_queue_->PostTask(Destructor{std::move(rtcp_transceiver_)}); RTC_DCHECK(!rtcp_transceiver_); } void RtcpTransceiver::Stop(std::function on_destroyed) { RTC_DCHECK(rtcp_transceiver_); task_queue_->PostTask(ToQueuedTask(Destructor{std::move(rtcp_transceiver_)}, std::move(on_destroyed))); RTC_DCHECK(!rtcp_transceiver_); } void RtcpTransceiver::AddMediaReceiverRtcpObserver( uint32_t remote_ssrc, MediaReceiverRtcpObserver* observer) { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); task_queue_->PostTask([ptr, remote_ssrc, observer] { ptr->AddMediaReceiverRtcpObserver(remote_ssrc, observer); }); } void RtcpTransceiver::RemoveMediaReceiverRtcpObserver( uint32_t remote_ssrc, MediaReceiverRtcpObserver* observer, std::function on_removed) { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); auto remove = [ptr, remote_ssrc, observer] { ptr->RemoveMediaReceiverRtcpObserver(remote_ssrc, observer); }; task_queue_->PostTask(ToQueuedTask(std::move(remove), std::move(on_removed))); } void RtcpTransceiver::SetReadyToSend(bool ready) { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); task_queue_->PostTask([ptr, ready] { ptr->SetReadyToSend(ready); }); } void RtcpTransceiver::ReceivePacket(rtc::CopyOnWriteBuffer packet) { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); int64_t now_us = rtc::TimeMicros(); task_queue_->PostTask( [ptr, packet, now_us] { ptr->ReceivePacket(packet, now_us); }); } void RtcpTransceiver::SendCompoundPacket() { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); task_queue_->PostTask([ptr] { ptr->SendCompoundPacket(); }); } void RtcpTransceiver::SetRemb(int64_t bitrate_bps, std::vector ssrcs) { RTC_CHECK(rtcp_transceiver_); // TODO(danilchap): Replace with lambda with move capture when available. struct SetRembClosure { void operator()() { ptr->SetRemb(bitrate_bps, std::move(ssrcs)); } RtcpTransceiverImpl* ptr; int64_t bitrate_bps; std::vector ssrcs; }; task_queue_->PostTask( SetRembClosure{rtcp_transceiver_.get(), bitrate_bps, std::move(ssrcs)}); } void RtcpTransceiver::UnsetRemb() { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); task_queue_->PostTask([ptr] { ptr->UnsetRemb(); }); } uint32_t RtcpTransceiver::SSRC() const { return rtcp_transceiver_->sender_ssrc(); } bool RtcpTransceiver::SendFeedbackPacket( const rtcp::TransportFeedback& packet) { RTC_CHECK(rtcp_transceiver_); struct Closure { void operator()() { ptr->SendRawPacket(raw_packet); } RtcpTransceiverImpl* ptr; rtc::Buffer raw_packet; }; task_queue_->PostTask(Closure{rtcp_transceiver_.get(), packet.Build()}); return true; } bool RtcpTransceiver::SendNetworkStateEstimatePacket( const rtcp::RemoteEstimate& packet) { RTC_CHECK(rtcp_transceiver_); struct Closure { void operator()() { ptr->SendRawPacket(raw_packet); } RtcpTransceiverImpl* ptr; rtc::Buffer raw_packet; }; task_queue_->PostTask(Closure{rtcp_transceiver_.get(), packet.Build()}); return true; } void RtcpTransceiver::SendNack(uint32_t ssrc, std::vector sequence_numbers) { RTC_CHECK(rtcp_transceiver_); // TODO(danilchap): Replace with lambda with move capture when available. struct Closure { void operator()() { ptr->SendNack(ssrc, std::move(sequence_numbers)); } RtcpTransceiverImpl* ptr; uint32_t ssrc; std::vector sequence_numbers; }; task_queue_->PostTask( Closure{rtcp_transceiver_.get(), ssrc, std::move(sequence_numbers)}); } void RtcpTransceiver::SendPictureLossIndication(uint32_t ssrc) { RTC_CHECK(rtcp_transceiver_); RtcpTransceiverImpl* ptr = rtcp_transceiver_.get(); task_queue_->PostTask([ptr, ssrc] { ptr->SendPictureLossIndication(ssrc); }); } void RtcpTransceiver::SendFullIntraRequest(std::vector ssrcs) { RTC_CHECK(rtcp_transceiver_); // TODO(danilchap): Replace with lambda with move capture when available. struct Closure { void operator()() { ptr->SendFullIntraRequest(ssrcs); } RtcpTransceiverImpl* ptr; std::vector ssrcs; }; task_queue_->PostTask(Closure{rtcp_transceiver_.get(), std::move(ssrcs)}); } } // namespace webrtc