diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc index 9bf66594b0..d67b249630 100644 --- a/pc/audio_rtp_receiver.cc +++ b/pc/audio_rtp_receiver.cc @@ -74,9 +74,10 @@ bool AudioRtpReceiver::SetOutputVolume(double volume) { RTC_DCHECK_GE(volume, 0.0); RTC_DCHECK_LE(volume, 10.0); RTC_DCHECK(media_channel_); - RTC_DCHECK(ssrc_); + RTC_DCHECK(!stopped_); return worker_thread_->Invoke(RTC_FROM_HERE, [&] { - return media_channel_->SetOutputVolume(*ssrc_, volume); + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC value. + return media_channel_->SetOutputVolume(ssrc_.value_or(0), volume); }); } @@ -84,7 +85,7 @@ void AudioRtpReceiver::OnSetVolume(double volume) { RTC_DCHECK_GE(volume, 0); RTC_DCHECK_LE(volume, 10); cached_volume_ = volume; - if (!media_channel_ || !ssrc_) { + if (!media_channel_ || stopped_) { RTC_LOG(LS_ERROR) << "AudioRtpReceiver::OnSetVolume: No audio channel exists."; return; @@ -107,21 +108,23 @@ std::vector AudioRtpReceiver::stream_ids() const { } RtpParameters AudioRtpReceiver::GetParameters() const { - if (!media_channel_ || !ssrc_ || stopped_) { + if (!media_channel_ || stopped_) { return RtpParameters(); } return worker_thread_->Invoke(RTC_FROM_HERE, [&] { - return media_channel_->GetRtpReceiveParameters(*ssrc_); + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC value. + return media_channel_->GetRtpReceiveParameters(ssrc_.value_or(0)); }); } bool AudioRtpReceiver::SetParameters(const RtpParameters& parameters) { TRACE_EVENT0("webrtc", "AudioRtpReceiver::SetParameters"); - if (!media_channel_ || !ssrc_ || stopped_) { + if (!media_channel_ || stopped_) { return false; } return worker_thread_->Invoke(RTC_FROM_HERE, [&] { - return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); + return media_channel_->SetRtpReceiveParameters(ssrc_.value_or(0), + parameters); }); } @@ -146,7 +149,7 @@ void AudioRtpReceiver::Stop() { if (stopped_) { return; } - if (media_channel_ && ssrc_) { + if (media_channel_) { // Allow that SetOutputVolume fail. This is the normal case when the // underlying media channel has already been deleted. SetOutputVolume(0.0); @@ -154,23 +157,38 @@ void AudioRtpReceiver::Stop() { stopped_ = true; } +void AudioRtpReceiver::RestartMediaChannel(absl::optional ssrc) { + RTC_DCHECK(media_channel_); + if (!stopped_ && ssrc_ == ssrc) { + return; + } + + if (!stopped_) { + source_->Stop(media_channel_, ssrc_.value_or(0)); + delay_->OnStop(); + } + ssrc_ = ssrc; + stopped_ = false; + source_->Start(media_channel_, ssrc.value_or(0)); + delay_->OnStart(media_channel_, ssrc.value_or(0)); + Reconfigure(); +} + void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) { if (!media_channel_) { RTC_LOG(LS_ERROR) << "AudioRtpReceiver::SetupMediaChannel: No audio channel exists."; return; } - if (ssrc_ == ssrc) { - return; + RestartMediaChannel(ssrc); +} + +void AudioRtpReceiver::SetupUnsignaledMediaChannel() { + if (!media_channel_) { + RTC_LOG(LS_ERROR) << "AudioRtpReceiver::SetupUnsignaledMediaChannel: No " + "audio channel exists."; } - if (ssrc_) { - source_->Stop(media_channel_, *ssrc_); - delay_->OnStop(); - } - ssrc_ = ssrc; - source_->Start(media_channel_, *ssrc_); - delay_->OnStart(media_channel_, *ssrc_); - Reconfigure(); + RestartMediaChannel(absl::nullopt); } void AudioRtpReceiver::set_stream_ids(std::vector stream_ids) { @@ -219,8 +237,7 @@ std::vector AudioRtpReceiver::GetSources() const { } void AudioRtpReceiver::Reconfigure() { - RTC_DCHECK(!stopped_); - if (!media_channel_ || !ssrc_) { + if (!media_channel_ || stopped_) { RTC_LOG(LS_ERROR) << "AudioRtpReceiver::Reconfigure: No audio channel exists."; return; diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h index cef6081fff..e1b1888aa7 100644 --- a/pc/audio_rtp_receiver.h +++ b/pc/audio_rtp_receiver.h @@ -86,6 +86,7 @@ class AudioRtpReceiver : public ObserverInterface, // RtpReceiverInternal implementation. void Stop() override; void SetupMediaChannel(uint32_t ssrc) override; + void SetupUnsignaledMediaChannel() override; uint32_t ssrc() const override { return ssrc_.value_or(0); } void NotifyFirstPacketReceived() override; void set_stream_ids(std::vector stream_ids) override; @@ -106,6 +107,7 @@ class AudioRtpReceiver : public ObserverInterface, int AttachmentId() const override { return attachment_id_; } private: + void RestartMediaChannel(absl::optional ssrc); void Reconfigure(); bool SetOutputVolume(double volume); @@ -118,7 +120,7 @@ class AudioRtpReceiver : public ObserverInterface, std::vector> streams_; bool cached_track_enabled_; double cached_volume_ = 1; - bool stopped_ = false; + bool stopped_ = true; RtpReceiverObserverInterface* observer_ = nullptr; bool received_first_packet_ = false; int attachment_id_ = 0; diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index e2e6bd57e1..6f0fd60d9b 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -2901,13 +2901,15 @@ RTCError PeerConnection::ApplyRemoteDescription( } if (!content->rejected && RtpTransceiverDirectionHasRecv(local_direction)) { - // Set ssrc to 0 in the case of an unsignalled ssrc. - uint32_t ssrc = 0; if (!media_desc->streams().empty() && media_desc->streams()[0].has_ssrcs()) { - ssrc = media_desc->streams()[0].first_ssrc(); + uint32_t ssrc = media_desc->streams()[0].first_ssrc(); + transceiver->internal()->receiver_internal()->SetupMediaChannel(ssrc); + } else { + transceiver->internal() + ->receiver_internal() + ->SetupUnsignaledMediaChannel(); } - transceiver->internal()->receiver_internal()->SetupMediaChannel(ssrc); } } // Once all processing has finished, fire off callbacks. @@ -4101,7 +4103,11 @@ void PeerConnection::CreateAudioReceiver( auto* audio_receiver = new AudioRtpReceiver( worker_thread(), remote_sender_info.sender_id, streams); audio_receiver->SetMediaChannel(voice_media_channel()); - audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); + if (remote_sender_info.sender_id == kDefaultAudioSenderId) { + audio_receiver->SetupUnsignaledMediaChannel(); + } else { + audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); + } auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), audio_receiver); GetAudioTransceiver()->internal()->AddReceiver(receiver); @@ -4119,7 +4125,11 @@ void PeerConnection::CreateVideoReceiver( auto* video_receiver = new VideoRtpReceiver( worker_thread(), remote_sender_info.sender_id, streams); video_receiver->SetMediaChannel(video_media_channel()); - video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); + if (remote_sender_info.sender_id == kDefaultVideoSenderId) { + video_receiver->SetupUnsignaledMediaChannel(); + } else { + video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); + } auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), video_receiver); GetVideoTransceiver()->internal()->AddReceiver(receiver); diff --git a/pc/rtp_receiver.h b/pc/rtp_receiver.h index b33878ec18..84c2ff723b 100644 --- a/pc/rtp_receiver.h +++ b/pc/rtp_receiver.h @@ -50,10 +50,13 @@ class RtpReceiverInternal : public RtpReceiverInterface { virtual void SetMediaChannel(cricket::MediaChannel* media_channel) = 0; // Configures the RtpReceiver with the underlying media channel, with the - // given SSRC as the stream identifier. If |ssrc| is 0, the receiver will - // receive packets on unsignaled SSRCs. + // given SSRC as the stream identifier. virtual void SetupMediaChannel(uint32_t ssrc) = 0; + // Configures the RtpReceiver with the underlying media channel to receive an + // unsignaled receive stream. + virtual void SetupUnsignaledMediaChannel() = 0; + virtual void set_transport( rtc::scoped_refptr dtls_transport) = 0; // This SSRC is used as an identifier for the receiver between the API layer diff --git a/pc/test/mock_rtp_receiver_internal.h b/pc/test/mock_rtp_receiver_internal.h index 0838adabf1..f854e3372b 100644 --- a/pc/test/mock_rtp_receiver_internal.h +++ b/pc/test/mock_rtp_receiver_internal.h @@ -14,6 +14,7 @@ #include #include +#include "absl/types/optional.h" #include "pc/rtp_receiver.h" #include "test/gmock.h" @@ -46,6 +47,7 @@ class MockRtpReceiverInternal : public RtpReceiverInternal { MOCK_METHOD0(Stop, void()); MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*)); MOCK_METHOD1(SetupMediaChannel, void(uint32_t)); + MOCK_METHOD0(SetupUnsignaledMediaChannel, void()); MOCK_CONST_METHOD0(ssrc, uint32_t()); MOCK_METHOD0(NotifyFirstPacketReceived, void()); MOCK_METHOD1(set_stream_ids, void(std::vector)); diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc index a2ba3cb959..e6de6c71b3 100644 --- a/pc/video_rtp_receiver.cc +++ b/pc/video_rtp_receiver.cc @@ -77,27 +77,32 @@ std::vector VideoRtpReceiver::stream_ids() const { bool VideoRtpReceiver::SetSink(rtc::VideoSinkInterface* sink) { RTC_DCHECK(media_channel_); - RTC_DCHECK(ssrc_); - return worker_thread_->Invoke( - RTC_FROM_HERE, [&] { return media_channel_->SetSink(*ssrc_, sink); }); + RTC_DCHECK(!stopped_); + return worker_thread_->Invoke(RTC_FROM_HERE, [&] { + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC + return media_channel_->SetSink(ssrc_.value_or(0), sink); + }); } RtpParameters VideoRtpReceiver::GetParameters() const { - if (!media_channel_ || !ssrc_ || stopped_) { + if (!media_channel_ || stopped_) { return RtpParameters(); } return worker_thread_->Invoke(RTC_FROM_HERE, [&] { - return media_channel_->GetRtpReceiveParameters(*ssrc_); + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC + return media_channel_->GetRtpReceiveParameters(ssrc_.value_or(0)); }); } bool VideoRtpReceiver::SetParameters(const RtpParameters& parameters) { TRACE_EVENT0("webrtc", "VideoRtpReceiver::SetParameters"); - if (!media_channel_ || !ssrc_ || stopped_) { + if (!media_channel_ || stopped_) { return false; } return worker_thread_->Invoke(RTC_FROM_HERE, [&] { - return media_channel_->SetRtpReceiveParameters(*ssrc_, parameters); + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC + return media_channel_->SetRtpReceiveParameters(ssrc_.value_or(0), + parameters); }); } @@ -123,7 +128,7 @@ void VideoRtpReceiver::Stop() { return; } source_->SetState(MediaSourceInterface::kEnded); - if (!media_channel_ || !ssrc_) { + if (!media_channel_) { RTC_LOG(LS_WARNING) << "VideoRtpReceiver::Stop: No video channel exists."; } else { // Allow that SetSink fail. This is the normal case when the underlying @@ -134,24 +139,40 @@ void VideoRtpReceiver::Stop() { stopped_ = true; } +void VideoRtpReceiver::RestartMediaChannel(absl::optional ssrc) { + RTC_DCHECK(media_channel_); + if (!stopped_ && ssrc_ == ssrc) { + return; + } + if (!stopped_) { + SetSink(nullptr); + } + stopped_ = false; + ssrc_ = ssrc; + SetSink(source_->sink()); + + // Attach any existing frame decryptor to the media channel. + MaybeAttachFrameDecryptorToMediaChannel( + ssrc, worker_thread_, frame_decryptor_, media_channel_, stopped_); + // TODO(bugs.webrtc.org/8694): Stop using 0 to mean unsignalled SSRC + // value. + delay_->OnStart(media_channel_, ssrc.value_or(0)); +} + void VideoRtpReceiver::SetupMediaChannel(uint32_t ssrc) { if (!media_channel_) { RTC_LOG(LS_ERROR) << "VideoRtpReceiver::SetupMediaChannel: No video channel exists."; } - if (ssrc_ == ssrc) { - return; - } - if (ssrc_) { - SetSink(nullptr); - } - ssrc_ = ssrc; - SetSink(source_->sink()); - // Attach any existing frame decryptor to the media channel. - MaybeAttachFrameDecryptorToMediaChannel( - ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_); + RestartMediaChannel(ssrc); +} - delay_->OnStart(media_channel_, ssrc); +void VideoRtpReceiver::SetupUnsignaledMediaChannel() { + if (!media_channel_) { + RTC_LOG(LS_ERROR) << "VideoRtpReceiver::SetupUnsignaledMediaChannel: No " + "video channel exists."; + } + RestartMediaChannel(absl::nullopt); } void VideoRtpReceiver::set_stream_ids(std::vector stream_ids) { diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h index a06865f160..1f33f114fe 100644 --- a/pc/video_rtp_receiver.h +++ b/pc/video_rtp_receiver.h @@ -87,6 +87,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject { // RtpReceiverInternal implementation. void Stop() override; void SetupMediaChannel(uint32_t ssrc) override; + void SetupUnsignaledMediaChannel() override; uint32_t ssrc() const override { return ssrc_.value_or(0); } void NotifyFirstPacketReceived() override; void set_stream_ids(std::vector stream_ids) override; @@ -125,6 +126,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject { rtc::VideoBroadcaster broadcaster_; }; + void RestartMediaChannel(absl::optional ssrc); bool SetSink(rtc::VideoSinkInterface* sink); rtc::Thread* const worker_thread_; @@ -136,7 +138,7 @@ class VideoRtpReceiver : public rtc::RefCountedObject { rtc::scoped_refptr source_; rtc::scoped_refptr track_; std::vector> streams_; - bool stopped_ = false; + bool stopped_ = true; RtpReceiverObserverInterface* observer_ = nullptr; bool received_first_packet_ = false; int attachment_id_ = 0; diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc index 24fa41a24b..5e076b3d77 100644 --- a/video/rtp_video_stream_receiver.cc +++ b/video/rtp_video_stream_receiver.cc @@ -201,7 +201,6 @@ RtpVideoStreamReceiver::RtpVideoStreamReceiver( RTC_DCHECK(config_.rtp.rtcp_mode != RtcpMode::kOff) << "A stream should not be configured with RTCP disabled. This value is " "reserved for internal usage."; - RTC_DCHECK(config_.rtp.remote_ssrc != 0); // TODO(pbos): What's an appropriate local_ssrc for receive-only streams? RTC_DCHECK(config_.rtp.local_ssrc != 0); RTC_DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);