When stopping a transceiver, end the receiver's track.
Bug: webrtc:11840
Change-Id: Ib8171c58fcb13c33ab03398eb3021c07e55ff008
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/185181
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32188}
diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc
index 54912a5..8ff685d 100644
--- a/pc/audio_rtp_receiver.cc
+++ b/pc/audio_rtp_receiver.cc
@@ -42,8 +42,9 @@
: worker_thread_(worker_thread),
id_(receiver_id),
source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
- track_(AudioTrackProxy::Create(rtc::Thread::Current(),
- AudioTrack::Create(receiver_id, source_))),
+ track_(AudioTrackProxyWithInternal<AudioTrack>::Create(
+ rtc::Thread::Current(),
+ AudioTrack::Create(receiver_id, source_))),
cached_track_enabled_(track_->enabled()),
attachment_id_(GenerateUniqueId()),
delay_(JitterBufferDelayProxy::Create(
@@ -146,6 +147,11 @@
stopped_ = true;
}
+void AudioRtpReceiver::StopAndEndTrack() {
+ Stop();
+ track_->internal()->set_ended();
+}
+
void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
RTC_DCHECK(media_channel_);
if (!stopped_ && ssrc_ == ssrc) {
diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h
index 88b16ee..f4b8210 100644
--- a/pc/audio_rtp_receiver.h
+++ b/pc/audio_rtp_receiver.h
@@ -19,10 +19,12 @@
#include "absl/types/optional.h"
#include "api/crypto/frame_decryptor_interface.h"
#include "api/media_stream_interface.h"
+#include "api/media_stream_track_proxy.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
#include "api/scoped_refptr.h"
#include "media/base/media_channel.h"
+#include "pc/audio_track.h"
#include "pc/jitter_buffer_delay_interface.h"
#include "pc/remote_audio_source.h"
#include "pc/rtp_receiver.h"
@@ -84,6 +86,7 @@
// RtpReceiverInternal implementation.
void Stop() override;
+ void StopAndEndTrack() override;
void SetupMediaChannel(uint32_t ssrc) override;
void SetupUnsignaledMediaChannel() override;
uint32_t ssrc() const override { return ssrc_.value_or(0); }
@@ -116,7 +119,7 @@
rtc::Thread* const worker_thread_;
const std::string id_;
const rtc::scoped_refptr<RemoteAudioSource> source_;
- const rtc::scoped_refptr<AudioTrackInterface> track_;
+ const rtc::scoped_refptr<AudioTrackProxyWithInternal<AudioTrack>> track_;
cricket::VoiceMediaChannel* media_channel_ = nullptr;
absl::optional<uint32_t> ssrc_;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
diff --git a/pc/audio_track.h b/pc/audio_track.h
index f89bbcd..f8ad471 100644
--- a/pc/audio_track.h
+++ b/pc/audio_track.h
@@ -34,10 +34,10 @@
const std::string& id,
const rtc::scoped_refptr<AudioSourceInterface>& source);
- private:
// MediaStreamTrack implementation.
std::string kind() const override;
+ private:
// AudioTrackInterface implementation.
AudioSourceInterface* GetSource() const override;
diff --git a/pc/media_stream_track.h b/pc/media_stream_track.h
index 25c3663..fd63569 100644
--- a/pc/media_stream_track.h
+++ b/pc/media_stream_track.h
@@ -15,6 +15,7 @@
#include "api/media_stream_interface.h"
#include "api/notifier.h"
+#include "rtc_base/logging.h"
namespace webrtc {
@@ -38,6 +39,7 @@
}
return fire_on_change;
}
+ void set_ended() { set_state(MediaStreamTrackInterface::TrackState::kEnded); }
protected:
explicit MediaStreamTrack(const std::string& id)
diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc
index 4b098e1..a8471c9 100644
--- a/pc/peer_connection_integrationtest.cc
+++ b/pc/peer_connection_integrationtest.cc
@@ -5603,6 +5603,52 @@
PeerConnectionInterface::kIceGatheringNew));
}
+TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
+ StopTransceiverEndsIncomingAudioTrack) {
+ RTCConfiguration config;
+ ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(config, config));
+ ConnectFakeSignaling();
+ auto audio_transceiver_or_error =
+ caller()->pc()->AddTransceiver(caller()->CreateLocalAudioTrack());
+ ASSERT_TRUE(audio_transceiver_or_error.ok());
+ auto audio_transceiver = audio_transceiver_or_error.MoveValue();
+
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ auto caller_track = audio_transceiver->receiver()->track();
+ auto callee_track = callee()->pc()->GetReceivers()[0]->track();
+ audio_transceiver->StopStandard();
+ EXPECT_EQ(MediaStreamTrackInterface::TrackState::kEnded,
+ caller_track->state());
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ EXPECT_EQ(MediaStreamTrackInterface::TrackState::kEnded,
+ callee_track->state());
+}
+
+TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
+ StopTransceiverEndsIncomingVideoTrack) {
+ RTCConfiguration config;
+ ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(config, config));
+ ConnectFakeSignaling();
+ auto audio_transceiver_or_error =
+ caller()->pc()->AddTransceiver(caller()->CreateLocalVideoTrack());
+ ASSERT_TRUE(audio_transceiver_or_error.ok());
+ auto audio_transceiver = audio_transceiver_or_error.MoveValue();
+
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ auto caller_track = audio_transceiver->receiver()->track();
+ auto callee_track = callee()->pc()->GetReceivers()[0]->track();
+ audio_transceiver->StopStandard();
+ EXPECT_EQ(MediaStreamTrackInterface::TrackState::kEnded,
+ caller_track->state());
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ EXPECT_EQ(MediaStreamTrackInterface::TrackState::kEnded,
+ callee_track->state());
+}
+
#ifdef HAVE_SCTP
TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
diff --git a/pc/rtp_receiver.h b/pc/rtp_receiver.h
index 84c2ff7..2cfccd4 100644
--- a/pc/rtp_receiver.h
+++ b/pc/rtp_receiver.h
@@ -41,7 +41,11 @@
// Internal class used by PeerConnection.
class RtpReceiverInternal : public RtpReceiverInterface {
public:
+ // Stops receiving. The track may be reactivated.
virtual void Stop() = 0;
+ // Stops the receiver permanently.
+ // Causes the associated track to enter kEnded state. Cannot be reversed.
+ virtual void StopAndEndTrack() = 0;
// Sets the underlying MediaEngine channel associated with this RtpSender.
// A VoiceMediaChannel should be used for audio RtpSenders and
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc
index fd6f4bb..fd8ff81 100644
--- a/pc/rtp_transceiver.cc
+++ b/pc/rtp_transceiver.cc
@@ -346,7 +346,7 @@
// 5. Stop receiving media with receiver.
for (const auto& receiver : receivers_)
- receiver->internal()->Stop();
+ receiver->internal()->StopAndEndTrack();
stopping_ = true;
direction_ = webrtc::RtpTransceiverDirection::kInactive;
diff --git a/pc/test/mock_rtp_receiver_internal.h b/pc/test/mock_rtp_receiver_internal.h
index 779dcdc..ba24403 100644
--- a/pc/test/mock_rtp_receiver_internal.h
+++ b/pc/test/mock_rtp_receiver_internal.h
@@ -57,6 +57,7 @@
// RtpReceiverInternal methods.
MOCK_METHOD(void, Stop, (), (override));
+ MOCK_METHOD(void, StopAndEndTrack, (), (override));
MOCK_METHOD(void, SetMediaChannel, (cricket::MediaChannel*), (override));
MOCK_METHOD(void, SetupMediaChannel, (uint32_t), (override));
MOCK_METHOD(void, SetupUnsignaledMediaChannel, (), (override));
diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc
index f093bf4..dd60125 100644
--- a/pc/video_rtp_receiver.cc
+++ b/pc/video_rtp_receiver.cc
@@ -16,7 +16,6 @@
#include <vector>
#include "api/media_stream_proxy.h"
-#include "api/media_stream_track_proxy.h"
#include "api/video_track_source_proxy.h"
#include "pc/jitter_buffer_delay.h"
#include "pc/jitter_buffer_delay_proxy.h"
@@ -43,7 +42,7 @@
: worker_thread_(worker_thread),
id_(receiver_id),
source_(new RefCountedObject<VideoRtpTrackSource>(this)),
- track_(VideoTrackProxy::Create(
+ track_(VideoTrackProxyWithInternal<VideoTrack>::Create(
rtc::Thread::Current(),
worker_thread,
VideoTrack::Create(
@@ -136,6 +135,11 @@
stopped_ = true;
}
+void VideoRtpReceiver::StopAndEndTrack() {
+ Stop();
+ track_->internal()->set_ended();
+}
+
void VideoRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
RTC_DCHECK(media_channel_);
if (!stopped_ && ssrc_ == ssrc) {
diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h
index f66a8a7..74ae444 100644
--- a/pc/video_rtp_receiver.h
+++ b/pc/video_rtp_receiver.h
@@ -20,6 +20,7 @@
#include "api/crypto/frame_decryptor_interface.h"
#include "api/frame_transformer_interface.h"
#include "api/media_stream_interface.h"
+#include "api/media_stream_track_proxy.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
#include "api/rtp_receiver_interface.h"
@@ -31,6 +32,7 @@
#include "pc/jitter_buffer_delay_interface.h"
#include "pc/rtp_receiver.h"
#include "pc/video_rtp_track_source.h"
+#include "pc/video_track.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/thread.h"
@@ -89,6 +91,7 @@
// RtpReceiverInternal implementation.
void Stop() override;
+ void StopAndEndTrack() override;
void SetupMediaChannel(uint32_t ssrc) override;
void SetupUnsignaledMediaChannel() override;
uint32_t ssrc() const override { return ssrc_.value_or(0); }
@@ -130,7 +133,7 @@
// |source_| is held here to be able to change the state of the source when
// the VideoRtpReceiver is stopped.
rtc::scoped_refptr<VideoRtpTrackSource> source_;
- rtc::scoped_refptr<VideoTrackInterface> track_;
+ rtc::scoped_refptr<VideoTrackProxyWithInternal<VideoTrack>> track_;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
bool stopped_ = true;
RtpReceiverObserverInterface* observer_ = nullptr;