Batch resetting of unsignaled receive streams Batch up resetting of receive streams when payload type demuxing is disabled. This introduces a new method, `GetResetUnsignaledRecvStreamCallback`, which follows the same pattern and behavior as `GetStatsCallback`. Bug: webrtc:42222804 Change-Id: I523d340046e9544091b4b1417c947bc439d00efc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/461660 Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47338}
diff --git a/media/base/fake_media_engine.h b/media/base/fake_media_engine.h index acff856..18c278b 100644 --- a/media/base/fake_media_engine.h +++ b/media/base/fake_media_engine.h
@@ -125,6 +125,10 @@ bool CheckNoRtcp() { return rtcp_packets_.empty(); } void set_fail_set_recv_codecs(bool fail) { fail_set_recv_codecs_ = fail; } void ResetUnsignaledRecvStream() override {} + absl::AnyInvocable<void() &&> GetResetUnsignaledRecvStreamCallback() + override { + return [this]() { ResetUnsignaledRecvStream(); }; + } std::optional<uint32_t> GetUnsignaledSsrc() const override { return std::nullopt; }
diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 95d1e7e..641b6e9 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h
@@ -279,6 +279,11 @@ // Resets any cached StreamParams for an unsignaled RecvStream, and removes // any existing unsignaled streams. virtual void ResetUnsignaledRecvStream() = 0; + // Returns a callback that can be used to reset unsignaled receive streams. + // The purpose is to allow binding the channel's safety flag to a callback + // that is run on the worker thread, ensuring the channel is alive. + virtual absl::AnyInvocable<void() &&> + GetResetUnsignaledRecvStreamCallback() = 0; // Sets the abstract interface class for sending RTP/RTCP data. virtual void SetInterface(MediaChannelNetworkInterface* iface) = 0; // Called on the network when an RTP packet is received.
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 0e6ce01..cf1ff5d 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc
@@ -3143,11 +3143,6 @@ } void WebRtcVideoReceiveChannel::ResetUnsignaledRecvStream() { - if (!worker_thread_->IsCurrent()) { - worker_thread_->PostTask(SafeTask( - task_safety_.flag(), [this]() { ResetUnsignaledRecvStream(); })); - return; - } RTC_DCHECK_RUN_ON(&thread_checker_); RTC_LOG(LS_INFO) << "ResetUnsignaledRecvStream."; unsignaled_stream_params_ = StreamParams(); @@ -3168,6 +3163,12 @@ } } +absl::AnyInvocable<void() &&> +WebRtcVideoReceiveChannel::GetResetUnsignaledRecvStreamCallback() { + return SafeTask(task_safety_.flag(), + [this]() { ResetUnsignaledRecvStream(); }); +} + std::optional<uint32_t> WebRtcVideoReceiveChannel::GetUnsignaledSsrc() const { RTC_DCHECK_RUN_ON(&thread_checker_); std::optional<uint32_t> ssrc;
diff --git a/media/engine/webrtc_video_engine.h b/media/engine/webrtc_video_engine.h index 8c5442b..3630eb5 100644 --- a/media/engine/webrtc_video_engine.h +++ b/media/engine/webrtc_video_engine.h
@@ -529,6 +529,7 @@ } bool RemoveRecvStream(uint32_t ssrc) override; void ResetUnsignaledRecvStream() override; + absl::AnyInvocable<void() &&> GetResetUnsignaledRecvStreamCallback() override; std::optional<uint32_t> GetUnsignaledSsrc() const override; void OnDemuxerCriteriaUpdatePending() override; void OnDemuxerCriteriaUpdateComplete() override;
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index 4000fb1..05bfafe 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc
@@ -2495,11 +2495,6 @@ } void WebRtcVoiceReceiveChannel::ResetUnsignaledRecvStream() { - if (!worker_thread_->IsCurrent()) { - worker_thread_->PostTask(SafeTask( - task_safety_.flag(), [this]() { ResetUnsignaledRecvStream(); })); - return; - } RTC_DCHECK_RUN_ON(worker_thread_); RTC_LOG(LS_INFO) << "ResetUnsignaledRecvStream."; unsignaled_stream_params_ = StreamParams(); @@ -2510,6 +2505,12 @@ } } +absl::AnyInvocable<void() &&> +WebRtcVoiceReceiveChannel::GetResetUnsignaledRecvStreamCallback() { + return SafeTask(task_safety_.flag(), + [this]() { ResetUnsignaledRecvStream(); }); +} + std::optional<uint32_t> WebRtcVoiceReceiveChannel::GetUnsignaledSsrc() const { RTC_DCHECK_RUN_ON(worker_thread_); if (unsignaled_recv_ssrcs_.empty()) {
diff --git a/media/engine/webrtc_voice_engine.h b/media/engine/webrtc_voice_engine.h index f033c21..450e99a 100644 --- a/media/engine/webrtc_voice_engine.h +++ b/media/engine/webrtc_voice_engine.h
@@ -358,6 +358,7 @@ bool AddRecvStream(const StreamParams& sp) override; bool RemoveRecvStream(uint32_t ssrc) override; void ResetUnsignaledRecvStream() override; + absl::AnyInvocable<void() &&> GetResetUnsignaledRecvStreamCallback() override; std::optional<uint32_t> GetUnsignaledSsrc() const override; void OnDemuxerCriteriaUpdatePending() override;
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc index 58da29f..59e4ef9 100644 --- a/pc/rtp_transceiver.cc +++ b/pc/rtp_transceiver.cc
@@ -1378,13 +1378,6 @@ channel_->Enable(enable); } -void RtpTransceiver::ResetUnsignaledRecvStream() { - RTC_DCHECK_RUN_ON(thread_); - if (MediaReceiveChannelInterface* receive_channel = media_receive_channel()) { - receive_channel->ResetUnsignaledRecvStream(); - } -} - const std::vector<StreamParams>& RtpTransceiver::channel_local_streams() const { RTC_DCHECK_RUN_ON(thread_); RTC_DCHECK(channel_);
diff --git a/pc/rtp_transceiver.h b/pc/rtp_transceiver.h index 86e76f8..66aa443 100644 --- a/pc/rtp_transceiver.h +++ b/pc/rtp_transceiver.h
@@ -393,7 +393,6 @@ SdpType type, ScopedOperationsBatcher& batcher); void EnableChannel(bool enable); - void ResetUnsignaledRecvStream(); const std::vector<StreamParams>& channel_local_streams() const; const std::vector<StreamParams>& channel_remote_streams() const;
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc index ac88e6f..e5dae81 100644 --- a/pc/sdp_offer_answer.cc +++ b/pc/sdp_offer_answer.cc
@@ -56,6 +56,7 @@ #include "api/video/video_codec_constants.h" #include "media/base/codec.h" #include "media/base/codec_comparators.h" +#include "media/base/media_channel.h" #include "media/base/media_constants.h" #include "media/base/media_engine.h" #include "media/base/rid_description.h" @@ -5166,9 +5167,12 @@ RTC_DCHECK(sdesc); if (ConfiguredForMedia()) { + // Batch up operations for the worker thread. + ScopedOperationsBatcher batcher(context_->worker_thread()); + // Note: This may perform a BlockingCall over to the network thread, which // we'll also do in a loop below. - UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid); + UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid, batcher); // Push down the new SDP media section for each audio/video transceiver. auto rtp_transceivers = transceivers()->ListInternal(); @@ -5215,9 +5219,6 @@ "types, ignoring all."; } - // Batch up the calls to set the local/remote channel content. - ScopedOperationsBatcher batcher(context_->worker_thread()); - for (const auto& [transceiver, content] : channels) { if (source == CS_LOCAL) { transceiver->SetChannelLocalContent(content, type, batcher); @@ -5770,7 +5771,8 @@ void SdpOfferAnswerHandler::UpdatePayloadTypeDemuxingState( ContentSource source, - const flat_map<std::string, const ContentGroup*>& bundle_groups_by_mid) { + const flat_map<std::string, const ContentGroup*>& bundle_groups_by_mid, + ScopedOperationsBatcher& worker_tasks) { TRACE_EVENT0("webrtc", "SdpOfferAnswerHandler::UpdatePayloadTypeDemuxingState"); RTC_DCHECK_RUN_ON(signaling_thread()); @@ -5939,10 +5941,6 @@ // unsignaled streams that might have been created previously based on // payload type matches. This prevents SSRC collisions if those SSRCs // are later reused. - // TODO(tommi): Could/should we rather issue the calls to the transceivers - // on the network thread? This will post tasks per transceiver to the worker - // thread. A common configuration will have joined worker and network threads, - // so bundling with the network thread may be more efficient. for (RtpTransceiver* transceiver : transceivers()->ListInternal()) { const ContentInfo* content = FindMediaSectionForTransceiver(transceiver, sdesc); @@ -5951,13 +5949,17 @@ } auto it = transports_to_update.find(content->mid()); if (it != transports_to_update.end() && !it->second) { - // TODO: bugs.webrtc.org/42221580 - This will remove *all* unsignaled - // streams (those without an explicitly signaled SSRC), which may include - // streams that were matched to this channel by MID or RID. Ideally we'd - // remove only the streams that were matched based on payload type alone, - // but currently there is no straightforward way to identify those - // streams. - transceiver->ResetUnsignaledRecvStream(); + if (MediaReceiveChannelInterface* receive_channel = + transceiver->media_receive_channel()) { + // TODO: bugs.webrtc.org/42221580 - This will remove *all* unsignaled + // streams (those without an explicitly signaled SSRC), which may + // include streams that were matched to this channel by MID or RID. + // Ideally we'd remove only the streams that were matched based on + // payload type alone, but currently there is no straightforward way to + // identify those streams. + worker_tasks.Add( + receive_channel->GetResetUnsignaledRecvStreamCallback()); + } } } }
diff --git a/pc/sdp_offer_answer.h b/pc/sdp_offer_answer.h index a2b9ef1..919459d 100644 --- a/pc/sdp_offer_answer.h +++ b/pc/sdp_offer_answer.h
@@ -72,6 +72,8 @@ namespace webrtc { +class ScopedOperationsBatcher; + // SdpOfferAnswerHandler is a component // of the PeerConnection object as defined // by the PeerConnectionInterface API surface. @@ -575,7 +577,8 @@ // payload type based demuxing in the affected channels. void UpdatePayloadTypeDemuxingState( ContentSource source, - const flat_map<std::string, const ContentGroup*>& bundle_groups_by_mid); + const flat_map<std::string, const ContentGroup*>& bundle_groups_by_mid, + ScopedOperationsBatcher& worker_tasks); // Updates the error state, signaling if necessary. void SetSessionError(SessionError error, const std::string& error_desc);
diff --git a/pc/test/mock_voice_media_receive_channel_interface.h b/pc/test/mock_voice_media_receive_channel_interface.h index feac0ee..688120d 100644 --- a/pc/test/mock_voice_media_receive_channel_interface.h +++ b/pc/test/mock_voice_media_receive_channel_interface.h
@@ -101,6 +101,10 @@ (override)); MOCK_METHOD(bool, RemoveRecvStream, (uint32_t ssrc), (override)); MOCK_METHOD(void, ResetUnsignaledRecvStream, (), (override)); + MOCK_METHOD(absl::AnyInvocable<void() &&>, + GetResetUnsignaledRecvStreamCallback, + (), + (override)); MOCK_METHOD(void, SetInterface, (webrtc::MediaChannelNetworkInterface * iface),