Split PushNewMediaChannelAndDeleteChannel

This admits to the fact that a transceiver's channel can't change, it's just
either created or deleted.

Bug: webrtc:42224170
Change-Id: I9a44bf0c0bace74eda6cdf1a1d6967eb8c697594
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/372380
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43713}
This commit is contained in:
Harald Alvestrand 2025-01-12 13:44:44 +00:00 committed by WebRTC LUCI CQ
parent 27a8f0a699
commit f94bddf72c
2 changed files with 31 additions and 18 deletions

View File

@ -334,7 +334,7 @@ void RtpTransceiver::SetChannel(
SafeTask(std::move(flag), [this]() { OnFirstPacketSent(); })); SafeTask(std::move(flag), [this]() { OnFirstPacketSent(); }));
}); });
}); });
PushNewMediaChannelAndDeleteChannel(nullptr); PushNewMediaChannel();
RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2); RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
} }
@ -358,35 +358,46 @@ void RtpTransceiver::ClearChannel() {
}); });
RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1); RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
PushNewMediaChannelAndDeleteChannel(std::move(channel_)); DeleteChannel();
RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2); RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
} }
void RtpTransceiver::PushNewMediaChannelAndDeleteChannel( void RtpTransceiver::PushNewMediaChannel() {
std::unique_ptr<cricket::ChannelInterface> channel_to_delete) { RTC_DCHECK(channel_);
// The clumsy combination of pushing down media channel and deleting if (senders_.empty() && receivers_.empty()) {
// the channel is due to the desire to do both things in one Invoke().
if (!channel_to_delete && senders_.empty() && receivers_.empty()) {
return; return;
} }
context()->worker_thread()->BlockingCall([&]() { context()->worker_thread()->BlockingCall([&]() {
// Push down the new media_channel, if any, otherwise clear it. // Push down the new media_channel.
auto* media_send_channel = auto* media_send_channel = channel_->media_send_channel();
channel_ ? channel_->media_send_channel() : nullptr;
for (const auto& sender : senders_) { for (const auto& sender : senders_) {
sender->internal()->SetMediaChannel(media_send_channel); sender->internal()->SetMediaChannel(media_send_channel);
} }
auto* media_receive_channel = auto* media_receive_channel = channel_->media_receive_channel();
channel_ ? channel_->media_receive_channel() : nullptr;
for (const auto& receiver : receivers_) { for (const auto& receiver : receivers_) {
receiver->internal()->SetMediaChannel(media_receive_channel); receiver->internal()->SetMediaChannel(media_receive_channel);
} }
});
}
// Destroy the channel, if we had one, now _after_ updating the receivers void RtpTransceiver::DeleteChannel() {
// who might have had references to the previous channel. RTC_DCHECK(channel_);
channel_to_delete = nullptr; // Ensure that channel_ is not reachable via transceiver, but is deleted
// only after clearing the references in senders_ and receivers_.
context()->worker_thread()->BlockingCall([&]() {
auto channel_to_delete = std::move(channel_);
// Clear the media channel reference from senders and receivers.
for (const auto& sender : senders_) {
sender->internal()->SetMediaChannel(nullptr);
}
for (const auto& receiver : receivers_) {
receiver->internal()->SetMediaChannel(nullptr);
}
// The channel is destroyed here, on the worker thread as it needs to
// be.
channel_to_delete.reset();
}); });
} }

View File

@ -304,10 +304,12 @@ class RtpTransceiver : public RtpTransceiverInterface {
void OnFirstPacketReceived(); void OnFirstPacketReceived();
void OnFirstPacketSent(); void OnFirstPacketSent();
void StopSendingAndReceiving(); void StopSendingAndReceiving();
// Delete a channel, and ensure that references to its media channel // Tell the senders and receivers about possibly-new media channels
// in a newly created `channel_`.
void PushNewMediaChannel();
// Delete `channel_`, and ensure that references to its media channels
// are updated before deleting it. // are updated before deleting it.
void PushNewMediaChannelAndDeleteChannel( void DeleteChannel();
std::unique_ptr<cricket::ChannelInterface> channel_to_delete);
// Enforce that this object is created, used and destroyed on one thread. // Enforce that this object is created, used and destroyed on one thread.
TaskQueueBase* const thread_; TaskQueueBase* const thread_;