Align sender/receiver teardown in RtpTransceiver.
This makes SetChannel() consistently make 2 invokes instead of a
multiple of senders+receivers (previous minimum was 4 but could be
larger).
* Stop() doesn't hop to the worker thread.
* SetMediaChannel(), an already-required step on the worker thread for
senders and *sometimes* for receivers[1], is now consistently required
for both. This simplifies transceiver teardown and enables the next
bullet.
* Transceiver stops all senders and receivers in one go rather than
ping ponging between threads.
[1] When not required, it was done implicitly inside of Stop().
See changes in `RtpTransceiver::SetChannel`
Bug: webrtc:13540
Change-Id: Ied61636c8ef09d782bf519524fff2a31e15219a8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/249797
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36057}
diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc
index a49b7ce..43294c7 100644
--- a/pc/audio_rtp_receiver.cc
+++ b/pc/audio_rtp_receiver.cc
@@ -25,20 +25,24 @@
namespace webrtc {
-AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
- std::string receiver_id,
- std::vector<std::string> stream_ids,
- bool is_unified_plan)
+AudioRtpReceiver::AudioRtpReceiver(
+ rtc::Thread* worker_thread,
+ std::string receiver_id,
+ std::vector<std::string> stream_ids,
+ bool is_unified_plan,
+ cricket::VoiceMediaChannel* voice_channel /*= nullptr*/)
: AudioRtpReceiver(worker_thread,
receiver_id,
CreateStreamsFromIds(std::move(stream_ids)),
- is_unified_plan) {}
+ is_unified_plan,
+ voice_channel) {}
AudioRtpReceiver::AudioRtpReceiver(
rtc::Thread* worker_thread,
const std::string& receiver_id,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams,
- bool is_unified_plan)
+ bool is_unified_plan,
+ cricket::VoiceMediaChannel* voice_channel /*= nullptr*/)
: worker_thread_(worker_thread),
id_(receiver_id),
source_(rtc::make_ref_counted<RemoteAudioSource>(
@@ -49,7 +53,8 @@
track_(AudioTrackProxyWithInternal<AudioTrack>::Create(
rtc::Thread::Current(),
AudioTrack::Create(receiver_id, source_))),
- cached_track_enabled_(track_->enabled()),
+ media_channel_(voice_channel),
+ cached_track_enabled_(track_->internal()->enabled()),
attachment_id_(GenerateUniqueId()),
worker_thread_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()) {
RTC_DCHECK(worker_thread_);
@@ -69,15 +74,15 @@
void AudioRtpReceiver::OnChanged() {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
- if (cached_track_enabled_ != track_->enabled()) {
- cached_track_enabled_ = track_->enabled();
- worker_thread_->PostTask(ToQueuedTask(
- worker_thread_safety_,
- [this, enabled = cached_track_enabled_, volume = cached_volume_]() {
- RTC_DCHECK_RUN_ON(worker_thread_);
- Reconfigure(enabled, volume);
- }));
- }
+ const bool enabled = track_->internal()->enabled();
+ if (cached_track_enabled_ == enabled)
+ return;
+ cached_track_enabled_ = enabled;
+ worker_thread_->PostTask(
+ ToQueuedTask(worker_thread_safety_, [this, enabled]() {
+ RTC_DCHECK_RUN_ON(worker_thread_);
+ Reconfigure(enabled);
+ }));
}
// RTC_RUN_ON(worker_thread_)
@@ -97,20 +102,18 @@
RTC_DCHECK_GE(volume, 0);
RTC_DCHECK_LE(volume, 10);
- // Update the cached_volume_ even when stopped, to allow clients to set the
- // volume before starting/restarting, eg see crbug.com/1272566.
- cached_volume_ = volume;
-
- // When the track is disabled, the volume of the source, which is the
- // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
- // setting the volume to the source when the track is disabled.
- if (track_->enabled()) {
- worker_thread_->PostTask(
- ToQueuedTask(worker_thread_safety_, [this, volume = cached_volume_]() {
- RTC_DCHECK_RUN_ON(worker_thread_);
- SetOutputVolume_w(volume);
- }));
- }
+ bool track_enabled = track_->internal()->enabled();
+ worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() {
+ RTC_DCHECK_RUN_ON(worker_thread_);
+ // Update the cached_volume_ even when stopped, to allow clients to set
+ // the volume before starting/restarting, eg see crbug.com/1272566.
+ cached_volume_ = volume;
+ // When the track is disabled, the volume of the source, which is the
+ // corresponding WebRtc Voice Engine channel will be 0. So we do not
+ // allow setting the volume to the source when the track is disabled.
+ if (track_enabled)
+ SetOutputVolume_w(volume);
+ });
}
rtc::scoped_refptr<DtlsTransportInterface> AudioRtpReceiver::dtls_transport()
@@ -159,52 +162,49 @@
void AudioRtpReceiver::Stop() {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
- // TODO(deadbeef): Need to do more here to fully stop receiving packets.
source_->SetState(MediaSourceInterface::kEnded);
-
- worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() {
- RTC_DCHECK_RUN_ON(worker_thread_);
-
- if (media_channel_)
- SetOutputVolume_w(0.0);
-
- SetMediaChannel_w(nullptr);
- });
-}
-
-void AudioRtpReceiver::StopAndEndTrack() {
- RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
- Stop();
track_->internal()->set_ended();
}
-void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
+void AudioRtpReceiver::SetSourceEnded() {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
+ source_->SetState(MediaSourceInterface::kEnded);
+}
+
+// RTC_RUN_ON(&signaling_thread_checker_)
+void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
+ bool enabled = track_->internal()->enabled();
MediaSourceInterface::SourceState state = source_->state();
- worker_thread_->Invoke<void>(
- RTC_FROM_HERE,
- [&, enabled = cached_track_enabled_, volume = cached_volume_]() {
- RTC_DCHECK_RUN_ON(worker_thread_);
- if (!media_channel_)
- return; // Can't restart.
-
- if (state != MediaSourceInterface::kInitializing) {
- if (ssrc_ == ssrc)
- return;
- source_->Stop(media_channel_, ssrc_);
- }
-
- ssrc_ = std::move(ssrc);
- source_->Start(media_channel_, ssrc_);
- if (ssrc_) {
- media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
- }
-
- Reconfigure(enabled, volume);
- });
+ worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() {
+ RTC_DCHECK_RUN_ON(worker_thread_);
+ RestartMediaChannel_w(std::move(ssrc), enabled, state);
+ });
source_->SetState(MediaSourceInterface::kLive);
}
+// RTC_RUN_ON(worker_thread_)
+void AudioRtpReceiver::RestartMediaChannel_w(
+ absl::optional<uint32_t> ssrc,
+ bool track_enabled,
+ MediaSourceInterface::SourceState state) {
+ if (!media_channel_)
+ return; // Can't restart.
+
+ if (state != MediaSourceInterface::kInitializing) {
+ if (ssrc_ == ssrc)
+ return;
+ source_->Stop(media_channel_, ssrc_);
+ }
+
+ ssrc_ = std::move(ssrc);
+ source_->Start(media_channel_, ssrc_);
+ if (ssrc_) {
+ media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs());
+ }
+
+ Reconfigure(track_enabled);
+}
+
void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
RestartMediaChannel(ssrc);
@@ -284,10 +284,10 @@
}
// RTC_RUN_ON(worker_thread_)
-void AudioRtpReceiver::Reconfigure(bool track_enabled, double volume) {
+void AudioRtpReceiver::Reconfigure(bool track_enabled) {
RTC_DCHECK(media_channel_);
- SetOutputVolume_w(track_enabled ? volume : 0);
+ SetOutputVolume_w(track_enabled ? cached_volume_ : 0);
if (ssrc_ && frame_decryptor_) {
// Reattach the frame decryptor if we were reconfigured.
@@ -318,18 +318,12 @@
}
void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
- RTC_DCHECK_RUN_ON(&signaling_thread_checker_);
+ RTC_DCHECK_RUN_ON(worker_thread_);
RTC_DCHECK(media_channel == nullptr ||
media_channel->media_type() == media_type());
+ if (!media_channel && media_channel_)
+ SetOutputVolume_w(0.0);
- worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
- RTC_DCHECK_RUN_ON(worker_thread_);
- SetMediaChannel_w(media_channel);
- });
-}
-
-// RTC_RUN_ON(worker_thread_)
-void AudioRtpReceiver::SetMediaChannel_w(cricket::MediaChannel* media_channel) {
media_channel ? worker_thread_safety_->SetAlive()
: worker_thread_safety_->SetNotAlive();
media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);