diff --git a/media/base/fake_media_engine.h b/media/base/fake_media_engine.h index ef7701400e..e1376c287b 100644 --- a/media/base/fake_media_engine.h +++ b/media/base/fake_media_engine.h @@ -121,6 +121,9 @@ class RtpHelper : public Base { return RemoveStreamBySsrc(&send_streams_, ssrc); } virtual void ResetUnsignaledRecvStream() {} + virtual absl::optional GetUnsignaledSsrc() const { + return absl::nullopt; + } virtual void OnDemuxerCriteriaUpdatePending() {} virtual void OnDemuxerCriteriaUpdateComplete() {} diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 9dced9485e..30e7571ab8 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -282,6 +282,8 @@ class MediaReceiveChannelInterface // Resets any cached StreamParams for an unsignaled RecvStream, and removes // any existing unsignaled streams. virtual void ResetUnsignaledRecvStream() = 0; + // Gets the current unsignaled receive stream's SSRC, if there is one. + virtual absl::optional GetUnsignaledSsrc() const = 0; // This is currently a workaround because of the demuxer state being managed // across two separate threads. Once the state is consistently managed on // the same thread (network), this workaround can be removed. diff --git a/media/base/media_channel_impl.h b/media/base/media_channel_impl.h index b4263f4a86..91b91c118a 100644 --- a/media/base/media_channel_impl.h +++ b/media/base/media_channel_impl.h @@ -420,6 +420,9 @@ class VoiceMediaReceiveChannel : public VoiceMediaReceiveChannelInterface { void ResetUnsignaledRecvStream() override { return impl()->ResetUnsignaledRecvStream(); } + absl::optional GetUnsignaledSsrc() const override { + return impl()->GetUnsignaledSsrc(); + } void OnDemuxerCriteriaUpdatePending() override { impl()->OnDemuxerCriteriaUpdatePending(); } @@ -614,6 +617,9 @@ class VideoMediaReceiveChannel : public VideoMediaReceiveChannelInterface { void ResetUnsignaledRecvStream() override { return impl()->ResetUnsignaledRecvStream(); } + absl::optional GetUnsignaledSsrc() const override { + return impl()->GetUnsignaledSsrc(); + } void OnDemuxerCriteriaUpdatePending() override { impl()->OnDemuxerCriteriaUpdatePending(); } diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index d023f21da2..cd80b3f027 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc @@ -548,8 +548,7 @@ UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc( WebRtcVideoChannel* channel, uint32_t ssrc, absl::optional rtx_ssrc) { - absl::optional default_recv_ssrc = - channel->GetDefaultReceiveStreamSsrc(); + absl::optional default_recv_ssrc = channel->GetUnsignaledSsrc(); if (default_recv_ssrc) { RTC_LOG(LS_INFO) << "Destroying old default receive stream for SSRC=" @@ -588,8 +587,7 @@ void DefaultUnsignalledSsrcHandler::SetDefaultSink( WebRtcVideoChannel* channel, rtc::VideoSinkInterface* sink) { default_sink_ = sink; - absl::optional default_recv_ssrc = - channel->GetDefaultReceiveStreamSsrc(); + absl::optional default_recv_ssrc = channel->GetUnsignaledSsrc(); if (default_recv_ssrc) { channel->SetSink(*default_recv_ssrc, default_sink_); } @@ -1566,6 +1564,18 @@ void WebRtcVideoChannel::ResetUnsignaledRecvStream() { } } +absl::optional WebRtcVideoChannel::GetUnsignaledSsrc() const { + RTC_DCHECK_RUN_ON(&thread_checker_); + absl::optional ssrc; + for (auto it = receive_streams_.begin(); it != receive_streams_.end(); ++it) { + if (it->second->IsDefaultStream()) { + ssrc.emplace(it->first); + break; + } + } + return ssrc; +} + void WebRtcVideoChannel::OnDemuxerCriteriaUpdatePending() { RTC_DCHECK_RUN_ON(&thread_checker_); ++demuxer_criteria_id_; @@ -1756,7 +1766,7 @@ void WebRtcVideoChannel::OnPacketReceived(rtc::CopyOnWriteBuffer packet, // stream, which will be associated with unsignaled media stream. // It is not possible to update the ssrcs of a receive stream, so we // recreate it insead if found. - auto default_ssrc = GetDefaultReceiveStreamSsrc(); + auto default_ssrc = GetUnsignaledSsrc(); if (!default_ssrc) { return; } @@ -1919,7 +1929,7 @@ void WebRtcVideoChannel::SetVideoCodecSwitchingEnabled(bool enabled) { bool WebRtcVideoChannel::SetBaseMinimumPlayoutDelayMs(uint32_t ssrc, int delay_ms) { RTC_DCHECK_RUN_ON(&thread_checker_); - absl::optional default_ssrc = GetDefaultReceiveStreamSsrc(); + absl::optional default_ssrc = GetUnsignaledSsrc(); // SSRC of 0 represents the default receive stream. if (ssrc == 0) { @@ -1961,18 +1971,6 @@ absl::optional WebRtcVideoChannel::GetBaseMinimumPlayoutDelayMs( } } -absl::optional WebRtcVideoChannel::GetDefaultReceiveStreamSsrc() { - RTC_DCHECK_RUN_ON(&thread_checker_); - absl::optional ssrc; - for (auto it = receive_streams_.begin(); it != receive_streams_.end(); ++it) { - if (it->second->IsDefaultStream()) { - ssrc.emplace(it->first); - break; - } - } - return ssrc; -} - std::vector WebRtcVideoChannel::GetSources( uint32_t ssrc) const { RTC_DCHECK_RUN_ON(&thread_checker_); @@ -3496,7 +3494,7 @@ WebRtcVideoChannel::MapCodecs(const std::vector& codecs) { WebRtcVideoChannel::WebRtcVideoReceiveStream* WebRtcVideoChannel::FindReceiveStream(uint32_t ssrc) { if (ssrc == 0) { - absl::optional default_ssrc = GetDefaultReceiveStreamSsrc(); + absl::optional default_ssrc = GetUnsignaledSsrc(); if (!default_ssrc) { return nullptr; } diff --git a/media/engine/webrtc_video_engine.h b/media/engine/webrtc_video_engine.h index 8b7e4561bd..bf27defc92 100644 --- a/media/engine/webrtc_video_engine.h +++ b/media/engine/webrtc_video_engine.h @@ -165,6 +165,7 @@ class WebRtcVideoChannel : public VideoMediaChannel, bool AddRecvStream(const StreamParams& sp, bool default_stream); bool RemoveRecvStream(uint32_t ssrc) override; void ResetUnsignaledRecvStream() override; + absl::optional GetUnsignaledSsrc() const override; void OnDemuxerCriteriaUpdatePending() override; void OnDemuxerCriteriaUpdateComplete() override; bool SetSink(uint32_t ssrc, @@ -216,8 +217,6 @@ class WebRtcVideoChannel : public VideoMediaChannel, return sending_; } - absl::optional GetDefaultReceiveStreamSsrc(); - StreamParams unsignaled_stream_params() { RTC_DCHECK_RUN_ON(&thread_checker_); return unsignaled_stream_params_; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index c87eca5fdf..694b8b9196 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -1966,6 +1966,15 @@ void WebRtcVoiceMediaChannel::ResetUnsignaledRecvStream() { } } +absl::optional WebRtcVoiceMediaChannel::GetUnsignaledSsrc() const { + if (unsignaled_recv_ssrcs_.empty()) { + return absl::nullopt; + } + // In the event of multiple unsignaled ssrcs, the last in the vector will be + // the most recent one (the one forwarded to the MediaStreamTrack). + return unsignaled_recv_ssrcs_.back(); +} + // Not implemented. // TODO(https://crbug.com/webrtc/12676): Implement a fix for the unsignalled // SSRC race that can happen when an m= section goes from receiving to not diff --git a/media/engine/webrtc_voice_engine.h b/media/engine/webrtc_voice_engine.h index 35dad9f679..835be360e7 100644 --- a/media/engine/webrtc_voice_engine.h +++ b/media/engine/webrtc_voice_engine.h @@ -173,6 +173,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, bool AddRecvStream(const StreamParams& sp) override; bool RemoveRecvStream(uint32_t ssrc) override; void ResetUnsignaledRecvStream() override; + absl::optional GetUnsignaledSsrc() const override; void OnDemuxerCriteriaUpdatePending() override; void OnDemuxerCriteriaUpdateComplete() override; diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc index 7af460b80e..9e687b9b55 100644 --- a/pc/audio_rtp_receiver.cc +++ b/pc/audio_rtp_receiver.cc @@ -212,9 +212,12 @@ void AudioRtpReceiver::SetupUnsignaledMediaChannel() { RestartMediaChannel(absl::nullopt); } -uint32_t AudioRtpReceiver::ssrc() const { +absl::optional AudioRtpReceiver::ssrc() const { RTC_DCHECK_RUN_ON(worker_thread_); - return ssrc_.value_or(0); + if (!ssrc_.has_value() && media_channel_) { + return media_channel_->GetUnsignaledSsrc(); + } + return ssrc_; } void AudioRtpReceiver::set_stream_ids(std::vector stream_ids) { diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h index 2e0f77c85c..6ef8f61efd 100644 --- a/pc/audio_rtp_receiver.h +++ b/pc/audio_rtp_receiver.h @@ -100,7 +100,7 @@ class AudioRtpReceiver : public ObserverInterface, void Stop() override; void SetupMediaChannel(uint32_t ssrc) override; void SetupUnsignaledMediaChannel() override; - uint32_t ssrc() const override; + absl::optional ssrc() const override; void NotifyFirstPacketReceived() override; void set_stream_ids(std::vector stream_ids) override; void set_transport( diff --git a/pc/legacy_stats_collector.cc b/pc/legacy_stats_collector.cc index 0df1957fcb..6829e359b8 100644 --- a/pc/legacy_stats_collector.cc +++ b/pc/legacy_stats_collector.cc @@ -1231,7 +1231,7 @@ void LegacyStatsCollector::ExtractMediaInfo( for (const auto& receiver : transceiver->internal()->receivers()) { gatherer->receiver_track_id_by_ssrc.insert(std::make_pair( - receiver->internal()->ssrc(), receiver->track()->id())); + receiver->internal()->ssrc().value_or(0), receiver->track()->id())); } } diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index da86afa52d..78e7f4d96b 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -1249,7 +1249,10 @@ void ProduceReceiverMediaTrackStats( } } -rtc::scoped_refptr CreateReportFilteredBySelector( +} // namespace + +rtc::scoped_refptr +RTCStatsCollector::CreateReportFilteredBySelector( bool filter_by_sender_selector, rtc::scoped_refptr report, rtc::scoped_refptr sender_selector, @@ -1258,40 +1261,35 @@ rtc::scoped_refptr CreateReportFilteredBySelector( if (filter_by_sender_selector) { // Filter mode: RTCStatsCollector::RequestInfo::kSenderSelector if (sender_selector) { - // Find outbound-rtp(s) of the sender, i.e. the outbound-rtp(s) that - // reference the sender stats. - // Because we do not implement sender stats, we look at outbound-rtp(s) - // that reference the track attachment stats for the sender instead. - std::string track_id = - DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kDirectionOutbound, sender_selector->AttachmentId()); - for (const auto& stats : *report) { - if (stats.type() != RTCOutboundRTPStreamStats::kType) - continue; - const auto& outbound_rtp = stats.cast_to(); - if (outbound_rtp.track_id.is_defined() && - *outbound_rtp.track_id == track_id) { - rtpstream_ids.push_back(outbound_rtp.id()); + // Find outbound-rtp(s) of the sender using ssrc lookup. + auto encodings = sender_selector->GetParametersInternal().encodings; + for (const auto* outbound_rtp : + report->GetStatsOfType()) { + RTC_DCHECK(outbound_rtp->ssrc.is_defined()); + auto it = std::find_if( + encodings.begin(), encodings.end(), + [ssrc = + *outbound_rtp->ssrc](const RtpEncodingParameters& encoding) { + return encoding.ssrc.has_value() && encoding.ssrc.value() == ssrc; + }); + if (it != encodings.end()) { + rtpstream_ids.push_back(outbound_rtp->id()); } } } } else { // Filter mode: RTCStatsCollector::RequestInfo::kReceiverSelector if (receiver_selector) { - // Find inbound-rtp(s) of the receiver, i.e. the inbound-rtp(s) that - // reference the receiver stats. - // Because we do not implement receiver stats, we look at inbound-rtp(s) - // that reference the track attachment stats for the receiver instead. - std::string track_id = - DEPRECATED_RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kDirectionInbound, receiver_selector->AttachmentId()); - for (const auto& stats : *report) { - if (stats.type() != RTCInboundRTPStreamStats::kType) - continue; - const auto& inbound_rtp = stats.cast_to(); - if (inbound_rtp.track_id.is_defined() && - *inbound_rtp.track_id == track_id) { - rtpstream_ids.push_back(inbound_rtp.id()); + // Find the inbound-rtp of the receiver using ssrc lookup. + absl::optional ssrc; + worker_thread_->BlockingCall([&] { ssrc = receiver_selector->ssrc(); }); + if (ssrc.has_value()) { + for (const auto* inbound_rtp : + report->GetStatsOfType()) { + RTC_DCHECK(inbound_rtp->ssrc.is_defined()); + if (*inbound_rtp->ssrc == *ssrc) { + rtpstream_ids.push_back(inbound_rtp->id()); + } } } } @@ -1301,8 +1299,6 @@ rtc::scoped_refptr CreateReportFilteredBySelector( return TakeReferencedStats(report->Copy(), rtpstream_ids); } -} // namespace - RTCStatsCollector::CertificateStatsPair RTCStatsCollector::CertificateStatsPair::Copy() const { CertificateStatsPair copy; diff --git a/pc/rtc_stats_collector.h b/pc/rtc_stats_collector.h index b3e60ef379..be366140c2 100644 --- a/pc/rtc_stats_collector.h +++ b/pc/rtc_stats_collector.h @@ -244,6 +244,12 @@ class RTCStatsCollector : public rtc::RefCountInterface, // This is a NO-OP if `network_report_` is null. void MergeNetworkReport_s(); + rtc::scoped_refptr CreateReportFilteredBySelector( + bool filter_by_sender_selector, + rtc::scoped_refptr report, + rtc::scoped_refptr sender_selector, + rtc::scoped_refptr receiver_selector); + // Slots for signals (sigslot) that are wired up to `pc_`. void OnSctpDataChannelCreated(SctpDataChannel* channel); // Slots for signals (sigslot) that are wired up to `channel`. diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 1916b92cb8..b75a15f322 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -388,7 +388,10 @@ rtc::scoped_refptr CreateMockSender( EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track)); EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc)); EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type)); - EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke([ssrc]() { + EXPECT_CALL(*sender, GetParameters()) + .WillRepeatedly( + Invoke([s = sender.get()]() { return s->GetParametersInternal(); })); + EXPECT_CALL(*sender, GetParametersInternal()).WillRepeatedly(Invoke([ssrc]() { RtpParameters params; params.encodings.push_back(RtpEncodingParameters()); params.encodings[0].ssrc = ssrc; @@ -406,6 +409,9 @@ rtc::scoped_refptr CreateMockReceiver( int attachment_id) { auto receiver = rtc::make_ref_counted(); EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); + EXPECT_CALL(*receiver, ssrc()).WillRepeatedly(Invoke([ssrc]() { + return ssrc; + })); EXPECT_CALL(*receiver, streams()) .WillRepeatedly( Return(std::vector>({}))); diff --git a/pc/rtp_receiver.h b/pc/rtp_receiver.h index 7622139f83..16ab011f14 100644 --- a/pc/rtp_receiver.h +++ b/pc/rtp_receiver.h @@ -68,7 +68,7 @@ class RtpReceiverInternal : public RtpReceiverInterface { rtc::scoped_refptr dtls_transport) = 0; // This SSRC is used as an identifier for the receiver between the API layer // and the WebRtcVideoEngine, WebRtcVoiceEngine layer. - virtual uint32_t ssrc() const = 0; + virtual absl::optional ssrc() const = 0; // Call this to notify the RtpReceiver when the first packet has been received // on the corresponding channel. diff --git a/pc/test/mock_rtp_receiver_internal.h b/pc/test/mock_rtp_receiver_internal.h index e2a81c0dd3..e76b56755d 100644 --- a/pc/test/mock_rtp_receiver_internal.h +++ b/pc/test/mock_rtp_receiver_internal.h @@ -63,7 +63,7 @@ class MockRtpReceiverInternal : public RtpReceiverInternal { (override)); MOCK_METHOD(void, SetupMediaChannel, (uint32_t), (override)); MOCK_METHOD(void, SetupUnsignaledMediaChannel, (), (override)); - MOCK_METHOD(uint32_t, ssrc, (), (const, override)); + MOCK_METHOD(absl::optional, ssrc, (), (const, override)); MOCK_METHOD(void, NotifyFirstPacketReceived, (), (override)); MOCK_METHOD(void, set_stream_ids, (std::vector), (override)); MOCK_METHOD(void, diff --git a/pc/test/mock_voice_media_channel.h b/pc/test/mock_voice_media_channel.h index e89e7e7892..e01e235a6f 100644 --- a/pc/test/mock_voice_media_channel.h +++ b/pc/test/mock_voice_media_channel.h @@ -53,6 +53,10 @@ class MockVoiceMediaChannel : public VoiceMediaChannel { MOCK_METHOD(bool, AddRecvStream, (const StreamParams& sp), (override)); MOCK_METHOD(bool, RemoveRecvStream, (uint32_t ssrc), (override)); MOCK_METHOD(void, ResetUnsignaledRecvStream, (), (override)); + MOCK_METHOD(absl::optional, + GetUnsignaledSsrc, + (), + (const, override)); MOCK_METHOD(void, OnDemuxerCriteriaUpdatePending, (), (override)); MOCK_METHOD(void, OnDemuxerCriteriaUpdateComplete, (), (override)); MOCK_METHOD(int, GetRtpSendTimeExtnId, (), (const, override)); diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc index 18dfc82a2e..e7e7726ab0 100644 --- a/pc/video_rtp_receiver.cc +++ b/pc/video_rtp_receiver.cc @@ -184,9 +184,12 @@ void VideoRtpReceiver::SetupUnsignaledMediaChannel() { RestartMediaChannel(absl::nullopt); } -uint32_t VideoRtpReceiver::ssrc() const { +absl::optional VideoRtpReceiver::ssrc() const { RTC_DCHECK_RUN_ON(worker_thread_); - return ssrc_.value_or(0); + if (!ssrc_.has_value() && media_channel_) { + return media_channel_->GetUnsignaledSsrc(); + } + return ssrc_; } void VideoRtpReceiver::set_stream_ids(std::vector stream_ids) { diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h index 086246daae..caf035e36f 100644 --- a/pc/video_rtp_receiver.h +++ b/pc/video_rtp_receiver.h @@ -89,7 +89,7 @@ class VideoRtpReceiver : public RtpReceiverInternal { void Stop() override; void SetupMediaChannel(uint32_t ssrc) override; void SetupUnsignaledMediaChannel() override; - uint32_t ssrc() const override; + absl::optional ssrc() const override; void NotifyFirstPacketReceived() override; void set_stream_ids(std::vector stream_ids) override; void set_transport(