diff --git a/api/rtpreceiverinterface.cc b/api/rtpreceiverinterface.cc index 96815a9f36..b62f744f3e 100644 --- a/api/rtpreceiverinterface.cc +++ b/api/rtpreceiverinterface.cc @@ -41,4 +41,8 @@ std::vector RtpReceiverInterface::GetSources() const { return {}; } +int RtpReceiverInterface::AttachmentId() const { + return 0; +} + } // namespace webrtc diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h index 0e32eae8cb..017c95a2aa 100644 --- a/api/rtpreceiverinterface.h +++ b/api/rtpreceiverinterface.h @@ -120,6 +120,14 @@ class RtpReceiverInterface : public rtc::RefCountInterface { // content::FakeRtpReceiver in Chromium. virtual std::vector GetSources() const; + // TODO(hta): Remove default implementation or move function to + // an internal interface. content::FakeRtpReceiver in Chromium needs this. + + // Returns an ID that changes if the attached track changes, but + // otherwise remains constant. Used to generate IDs for stats. + // The special value zero means that no track is attached. + virtual int AttachmentId() const; + protected: ~RtpReceiverInterface() override = default; }; @@ -138,6 +146,7 @@ BEGIN_SIGNALING_PROXY_MAP(RtpReceiver) PROXY_METHOD1(bool, SetParameters, const RtpParameters&) PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*); PROXY_CONSTMETHOD0(std::vector, GetSources); + PROXY_CONSTMETHOD0(int, AttachmentId); END_PROXY_MAP() } // namespace webrtc diff --git a/api/rtpsenderinterface.h b/api/rtpsenderinterface.h index 2ca2edc830..83e135f350 100644 --- a/api/rtpsenderinterface.h +++ b/api/rtpsenderinterface.h @@ -60,6 +60,13 @@ class RtpSenderInterface : public rtc::RefCountInterface { // Returns null for a video sender. virtual rtc::scoped_refptr GetDtmfSender() const = 0; + // Returns an ID that changes every time SetTrack() is called, but + // otherwise remains constant. Used to generate IDs for stats. + // The special value zero means that no track is attached. + // TODO(hta): Remove default implementation when callers have updated, + // or move function to an internal interface. + virtual int AttachmentId() const { return 0; } + protected: virtual ~RtpSenderInterface() {} }; @@ -78,6 +85,7 @@ BEGIN_SIGNALING_PROXY_MAP(RtpSender) PROXY_CONSTMETHOD0(RtpParameters, GetParameters); PROXY_METHOD1(RTCError, SetParameters, const RtpParameters&) PROXY_CONSTMETHOD0(rtc::scoped_refptr, GetDtmfSender); + PROXY_CONSTMETHOD0(int, AttachmentId); END_PROXY_MAP() } // namespace webrtc diff --git a/api/test/mock_rtpreceiver.h b/api/test/mock_rtpreceiver.h index de69ceaccd..7a612004ba 100644 --- a/api/test/mock_rtpreceiver.h +++ b/api/test/mock_rtpreceiver.h @@ -31,6 +31,7 @@ class MockRtpReceiver : public rtc::RefCountedObject { MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*)); MOCK_CONST_METHOD0(GetSources, std::vector()); + MOCK_CONST_METHOD0(AttachmentId, int()); }; } // namespace webrtc diff --git a/api/test/mock_rtpsender.h b/api/test/mock_rtpsender.h index dda5f45675..728ceca1a8 100644 --- a/api/test/mock_rtpsender.h +++ b/api/test/mock_rtpsender.h @@ -30,6 +30,7 @@ class MockRtpSender : public rtc::RefCountedObject { MOCK_CONST_METHOD0(GetParameters, RtpParameters()); MOCK_METHOD1(SetParameters, RTCError(const RtpParameters&)); MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr()); + MOCK_CONST_METHOD0(AttachmentId, int()); }; } // namespace webrtc diff --git a/ortc/ortcrtpreceiveradapter.cc b/ortc/ortcrtpreceiveradapter.cc index 8e05a8518b..16cb2485d0 100644 --- a/ortc/ortcrtpreceiveradapter.cc +++ b/ortc/ortcrtpreceiveradapter.cc @@ -156,7 +156,7 @@ void OrtcRtpReceiverAdapter::MaybeRecreateInternalReceiver() { rtc::CreateRandomUuid(), {}); auto* voice_channel = rtp_transport_controller_->voice_channel(); RTC_DCHECK(voice_channel); - audio_receiver->SetVoiceMediaChannel(voice_channel->media_channel()); + audio_receiver->SetMediaChannel(voice_channel->media_channel()); internal_receiver_ = audio_receiver; break; } @@ -166,7 +166,7 @@ void OrtcRtpReceiverAdapter::MaybeRecreateInternalReceiver() { rtc::CreateRandomUuid(), {}); auto* video_channel = rtp_transport_controller_->video_channel(); RTC_DCHECK(video_channel); - video_receiver->SetVideoMediaChannel(video_channel->media_channel()); + video_receiver->SetMediaChannel(video_channel->media_channel()); internal_receiver_ = video_receiver; break; } diff --git a/ortc/ortcrtpsenderadapter.cc b/ortc/ortcrtpsenderadapter.cc index 283ec3556e..2b25d46eeb 100644 --- a/ortc/ortcrtpsenderadapter.cc +++ b/ortc/ortcrtpsenderadapter.cc @@ -160,7 +160,7 @@ void OrtcRtpSenderAdapter::CreateInternalSender() { rtp_transport_controller_->worker_thread(), nullptr); auto* voice_channel = rtp_transport_controller_->voice_channel(); RTC_DCHECK(voice_channel); - audio_sender->SetVoiceMediaChannel(voice_channel->media_channel()); + audio_sender->SetMediaChannel(voice_channel->media_channel()); internal_sender_ = audio_sender; break; } @@ -169,7 +169,7 @@ void OrtcRtpSenderAdapter::CreateInternalSender() { new VideoRtpSender(rtp_transport_controller_->worker_thread()); auto* video_channel = rtp_transport_controller_->video_channel(); RTC_DCHECK(video_channel); - video_sender->SetVideoMediaChannel(video_channel->media_channel()); + video_sender->SetMediaChannel(video_channel->media_channel()); internal_sender_ = video_sender; break; } diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 21be8575be..cf506bf0c4 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -339,8 +339,6 @@ if (rtc_include_tests) { "test/fakevideotracksource.h", "test/mock_datachannel.h", "test/mock_peerconnection.h", - "test/mock_rtpreceiverinternal.h", - "test/mock_rtpsenderinternal.h", "test/mockpeerconnectionobservers.h", "test/peerconnectiontestwrapper.cc", "test/peerconnectiontestwrapper.h", diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index db6cad6995..90bb2677c1 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -1114,7 +1114,8 @@ PeerConnection::AddTrackPlanB( : cricket::MEDIA_TYPE_VIDEO); auto new_sender = CreateSender(media_type, track, stream_labels); if (track->kind() == MediaStreamTrackInterface::kAudioKind) { - new_sender->internal()->SetVoiceMediaChannel(voice_media_channel()); + static_cast(new_sender->internal()) + ->SetMediaChannel(voice_media_channel()); GetAudioTransceiver()->internal()->AddSender(new_sender); const RtpSenderInfo* sender_info = FindSenderInfo(local_audio_sender_infos_, @@ -1124,7 +1125,8 @@ PeerConnection::AddTrackPlanB( } } else { RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind()); - new_sender->internal()->SetVideoMediaChannel(video_media_channel()); + static_cast(new_sender->internal()) + ->SetMediaChannel(video_media_channel()); GetVideoTransceiver()->internal()->AddSender(new_sender); const RtpSenderInfo* sender_info = FindSenderInfo(local_video_sender_infos_, @@ -1415,14 +1417,14 @@ rtc::scoped_refptr PeerConnection::CreateSender( if (kind == MediaStreamTrackInterface::kAudioKind) { auto* audio_sender = new AudioRtpSender(worker_thread(), nullptr, stream_labels, stats_.get()); - audio_sender->SetVoiceMediaChannel(voice_media_channel()); + audio_sender->SetMediaChannel(voice_media_channel()); new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), audio_sender); GetAudioTransceiver()->internal()->AddSender(new_sender); } else if (kind == MediaStreamTrackInterface::kVideoKind) { auto* video_sender = new VideoRtpSender(worker_thread(), nullptr, stream_labels); - video_sender->SetVideoMediaChannel(video_media_channel()); + video_sender->SetMediaChannel(video_media_channel()); new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), video_sender); GetVideoTransceiver()->internal()->AddSender(new_sender); @@ -3017,7 +3019,7 @@ void PeerConnection::CreateAudioReceiver( streams.push_back(rtc::scoped_refptr(stream)); auto* audio_receiver = new AudioRtpReceiver( worker_thread(), remote_sender_info.sender_id, streams); - audio_receiver->SetVoiceMediaChannel(voice_media_channel()); + audio_receiver->SetMediaChannel(voice_media_channel()); audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), audio_receiver); @@ -3032,7 +3034,7 @@ void PeerConnection::CreateVideoReceiver( streams.push_back(rtc::scoped_refptr(stream)); auto* video_receiver = new VideoRtpReceiver( worker_thread(), remote_sender_info.sender_id, streams); - video_receiver->SetVideoMediaChannel(video_media_channel()); + video_receiver->SetMediaChannel(video_media_channel()); video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), video_receiver); @@ -3072,7 +3074,8 @@ void PeerConnection::AddAudioTrack(AudioTrackInterface* track, // Normal case; we've never seen this track before. auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track, {stream->label()}); - new_sender->internal()->SetVoiceMediaChannel(voice_media_channel()); + static_cast(new_sender->internal()) + ->SetMediaChannel(voice_media_channel()); GetAudioTransceiver()->internal()->AddSender(new_sender); // If the sender has already been configured in SDP, we call SetSsrc, // which will connect the sender to the underlying transport. This can @@ -3115,7 +3118,8 @@ void PeerConnection::AddVideoTrack(VideoTrackInterface* track, // Normal case; we've never seen this track before. auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track, {stream->label()}); - new_sender->internal()->SetVideoMediaChannel(video_media_channel()); + static_cast(new_sender->internal()) + ->SetMediaChannel(video_media_channel()); GetVideoTransceiver()->internal()->AddSender(new_sender); const RtpSenderInfo* sender_info = FindSenderInfo(local_video_sender_infos_, stream->label(), track->id()); diff --git a/pc/peerconnectioninterface_unittest.cc b/pc/peerconnectioninterface_unittest.cc index 8413b79dd0..e496e4ede6 100644 --- a/pc/peerconnectioninterface_unittest.cc +++ b/pc/peerconnectioninterface_unittest.cc @@ -32,7 +32,6 @@ #include "pc/mediasession.h" #include "pc/mediastream.h" #include "pc/peerconnection.h" -#include "pc/rtpsender.h" #include "pc/streamcollection.h" #include "pc/test/fakeaudiocapturemodule.h" #include "pc/test/fakertccertificategenerator.h" @@ -351,8 +350,6 @@ using webrtc::RTCError; using webrtc::RTCErrorType; using webrtc::RtpReceiverInterface; using webrtc::RtpSenderInterface; -using webrtc::RtpSenderProxyWithInternal; -using webrtc::RtpSenderInternal; using webrtc::RtpTransceiverDirection; using webrtc::SdpParseError; using webrtc::SdpType; @@ -1495,29 +1492,19 @@ TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddTrack) { std::unique_ptr( new cricket::FakeVideoCapturer())))); auto audio_sender = pc_->AddTrack(audio_track, std::vector()); - ASSERT_TRUE(audio_sender.ok()); - auto* audio_sender_proxy = - static_cast*>( - audio_sender.value().get()); - EXPECT_NE(0, audio_sender_proxy->internal()->AttachmentId()); - auto video_sender = pc_->AddTrack(video_track, std::vector()); - ASSERT_TRUE(video_sender.ok()); - auto* video_sender_proxy = - static_cast*>( - video_sender.value().get()); - EXPECT_NE(0, video_sender_proxy->internal()->AttachmentId()); + EXPECT_TRUE(audio_sender.ok()); + EXPECT_TRUE(video_sender.ok()); + EXPECT_NE(0, video_sender.value()->AttachmentId()); + EXPECT_NE(0, audio_sender.value()->AttachmentId()); } TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddStream) { CreatePeerConnectionWithoutDtls(); AddVideoStream(kStreamLabel1); auto senders = pc_->GetSenders(); - ASSERT_EQ(1u, senders.size()); - auto* sender_proxy = - static_cast*>( - senders[0].get()); - EXPECT_NE(0, sender_proxy->internal()->AttachmentId()); + EXPECT_EQ(1u, senders.size()); + EXPECT_NE(0, senders[0]->AttachmentId()); } TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) { diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc index e2be5ff0ed..77dde9591a 100644 --- a/pc/rtcstatscollector.cc +++ b/pc/rtcstatscollector.cc @@ -24,7 +24,6 @@ #include "p2p/base/port.h" #include "pc/peerconnection.h" #include "rtc_base/checks.h" -#include "rtc_base/ptr_util.h" #include "rtc_base/stringutils.h" #include "rtc_base/timeutils.h" #include "rtc_base/trace_event.h" @@ -37,11 +36,19 @@ std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) { return "RTCCertificate_" + fingerprint; } -std::string RTCCodecStatsIDFromMidDirectionAndPayload(const std::string& mid, - bool inbound, - uint32_t payload_type) { - return "RTCCodec_" + mid + "_" + (inbound ? "Inbound" : "Outbound") + "_" + - rtc::ToString<>(payload_type); +std::string RTCCodecStatsIDFromDirectionMediaAndPayload( + bool inbound, bool audio, uint32_t payload_type) { + // TODO(hbos): The present codec ID assignment is not sufficient to support + // Unified Plan or unbundled connections in all cases. When we are able to + // handle multiple m= lines of the same media type (and multiple BaseChannels + // for the same type is possible?) this needs to be updated to differentiate + // the transport being used, and stats need to be collected for all of them. + if (inbound) { + return audio ? "RTCCodec_InboundAudio_" + rtc::ToString<>(payload_type) + : "RTCCodec_InboundVideo_" + rtc::ToString<>(payload_type); + } + return audio ? "RTCCodec_OutboundAudio_" + rtc::ToString<>(payload_type) + : "RTCCodec_OutboundVideo_" + rtc::ToString<>(payload_type); } std::string RTCIceCandidatePairStatsIDFromConnectionInfo( @@ -168,16 +175,14 @@ double DoubleAudioLevelFromIntAudioLevel(int audio_level) { } std::unique_ptr CodecStatsFromRtpCodecParameters( - uint64_t timestamp_us, - const std::string& mid, - bool inbound, + uint64_t timestamp_us, bool inbound, bool audio, const RtpCodecParameters& codec_params) { RTC_DCHECK_GE(codec_params.payload_type, 0); RTC_DCHECK_LE(codec_params.payload_type, 127); RTC_DCHECK(codec_params.clock_rate); uint32_t payload_type = static_cast(codec_params.payload_type); std::unique_ptr codec_stats(new RTCCodecStats( - RTCCodecStatsIDFromMidDirectionAndPayload(mid, inbound, payload_type), + RTCCodecStatsIDFromDirectionMediaAndPayload(inbound, audio, payload_type), timestamp_us)); codec_stats->payload_type = payload_type; codec_stats->mime_type = codec_params.mime_type(); @@ -213,15 +218,15 @@ void SetInboundRTPStreamStatsFromMediaReceiverInfo( } void SetInboundRTPStreamStatsFromVoiceReceiverInfo( - const std::string& mid, const cricket::VoiceReceiverInfo& voice_receiver_info, RTCInboundRTPStreamStats* inbound_audio) { SetInboundRTPStreamStatsFromMediaReceiverInfo( voice_receiver_info, inbound_audio); inbound_audio->media_type = "audio"; if (voice_receiver_info.codec_payload_type) { - inbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( - mid, true, *voice_receiver_info.codec_payload_type); + inbound_audio->codec_id = + RTCCodecStatsIDFromDirectionMediaAndPayload( + true, true, *voice_receiver_info.codec_payload_type); } inbound_audio->jitter = static_cast(voice_receiver_info.jitter_ms) / @@ -231,15 +236,15 @@ void SetInboundRTPStreamStatsFromVoiceReceiverInfo( } void SetInboundRTPStreamStatsFromVideoReceiverInfo( - const std::string& mid, const cricket::VideoReceiverInfo& video_receiver_info, RTCInboundRTPStreamStats* inbound_video) { SetInboundRTPStreamStatsFromMediaReceiverInfo( video_receiver_info, inbound_video); inbound_video->media_type = "video"; if (video_receiver_info.codec_payload_type) { - inbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( - mid, true, *video_receiver_info.codec_payload_type); + inbound_video->codec_id = + RTCCodecStatsIDFromDirectionMediaAndPayload( + true, false, *video_receiver_info.codec_payload_type); } inbound_video->fir_count = static_cast(video_receiver_info.firs_sent); @@ -267,30 +272,30 @@ void SetOutboundRTPStreamStatsFromMediaSenderInfo( } void SetOutboundRTPStreamStatsFromVoiceSenderInfo( - const std::string& mid, const cricket::VoiceSenderInfo& voice_sender_info, RTCOutboundRTPStreamStats* outbound_audio) { SetOutboundRTPStreamStatsFromMediaSenderInfo( voice_sender_info, outbound_audio); outbound_audio->media_type = "audio"; if (voice_sender_info.codec_payload_type) { - outbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( - mid, false, *voice_sender_info.codec_payload_type); + outbound_audio->codec_id = + RTCCodecStatsIDFromDirectionMediaAndPayload( + false, true, *voice_sender_info.codec_payload_type); } // |fir_count|, |pli_count| and |sli_count| are only valid for video and are // purposefully left undefined for audio. } void SetOutboundRTPStreamStatsFromVideoSenderInfo( - const std::string& mid, const cricket::VideoSenderInfo& video_sender_info, RTCOutboundRTPStreamStats* outbound_video) { SetOutboundRTPStreamStatsFromMediaSenderInfo( video_sender_info, outbound_video); outbound_video->media_type = "video"; if (video_sender_info.codec_payload_type) { - outbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( - mid, false, *video_sender_info.codec_payload_type); + outbound_video->codec_id = + RTCCodecStatsIDFromDirectionMediaAndPayload( + false, false, *video_sender_info.codec_payload_type); } outbound_video->fir_count = static_cast(video_sender_info.firs_rcvd); @@ -497,14 +502,14 @@ ProduceMediaStreamTrackStatsFromVideoReceiverInfo( void ProduceSenderMediaTrackStats( int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, - std::vector> senders, + std::vector> senders, RTCStatsReport* report) { // This function iterates over the senders to generate outgoing track stats. // TODO(hbos): Return stats of detached tracks. We have to perform stats // gathering at the time of detachment to get accurate stats and timestamps. // https://crbug.com/659137 - for (auto sender : senders) { + for (auto const sender : senders) { if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) { AudioTrackInterface* track = static_cast(sender->track().get()); @@ -515,11 +520,11 @@ void ProduceSenderMediaTrackStats( // TODO(hta): Checking on ssrc is not proper. There should be a way // to see from a sender whether it's connected or not. // Related to https://crbug.com/8694 (using ssrc 0 to indicate "none") - if (sender->ssrc() != 0) { + if (sender->ssrc()) { // When pc.close is called, sender info is discarded, so // we generate zeroes instead. Bug: It should be retained. // https://crbug.com/807174 - const cricket::VoiceSenderInfo* sender_info = + auto sender_info = track_media_info_map.GetVoiceSenderInfoBySsrc(sender->ssrc()); if (sender_info) { voice_sender_info = sender_info; @@ -543,11 +548,11 @@ void ProduceSenderMediaTrackStats( // TODO(hta): Check on state not ssrc when state is available // Related to https://bugs.webrtc.org/8694 (using ssrc 0 to indicate // "none") - if (sender->ssrc() != 0) { + if (sender->ssrc()) { // When pc.close is called, sender info is discarded, so // we generate zeroes instead. Bug: It should be retained. // https://crbug.com/807174 - const cricket::VideoSenderInfo* sender_info = + auto sender_info = track_media_info_map.GetVideoSenderInfoBySsrc(sender->ssrc()); if (sender_info) { video_sender_info = sender_info; @@ -569,10 +574,10 @@ void ProduceSenderMediaTrackStats( void ProduceReceiverMediaTrackStats( int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, - std::vector> receivers, + std::vector> receivers, RTCStatsReport* report) { // This function iterates over the receivers to find the remote tracks. - for (auto receiver : receivers) { + for (auto const receiver : receivers) { if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { AudioTrackInterface* track = static_cast(receiver->track().get()); @@ -605,6 +610,38 @@ void ProduceReceiverMediaTrackStats( } } +void ProduceMediaStreamStats( + int64_t timestamp_us, + const std::vector>& rtp_senders, + const std::vector>& rtp_receivers, + RTCStatsReport* report) { + std::map> track_ids; + + for (auto& sender : rtp_senders) { + std::string track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kSender, sender->AttachmentId()); + for (auto& stream_id : sender->stream_ids()) { + track_ids[stream_id].push_back(track_id); + } + } + for (auto& receiver : rtp_receivers) { + std::string track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kReceiver, receiver->AttachmentId()); + for (auto& stream : receiver->streams()) { + track_ids[stream->label()].push_back(track_id); + } + } + + // Build stats for each stream ID known. + for (auto& it : track_ids) { + std::unique_ptr stream_stats( + new RTCMediaStreamStats("RTCMediaStream_" + it.first, timestamp_us)); + stream_stats->stream_identifier = it.first; + stream_stats->track_ids = it.second; + report->AddStats(std::move(stream_stats)); + } +} + } // namespace rtc::scoped_refptr RTCStatsCollector::Create( @@ -662,10 +699,27 @@ void RTCStatsCollector::GetStatsReport( num_pending_partial_reports_ = 2; partial_report_timestamp_us_ = cache_now_us; - // Prepare |transceiver_stats_infos_| for use in + // Prepare |transport_name_by_mid_| for use in + // |ProducePartialResultsOnNetworkThread|. + transport_names_by_mid_ = pc_->GetTransportNamesByMid(); + // Prepare |track_media_info_map_| for use in // |ProducePartialResultsOnNetworkThread| and // |ProducePartialResultsOnSignalingThread|. - transceiver_stats_infos_ = PrepareTransceiverStatsInfos_s(); + track_media_info_map_.reset(PrepareTrackMediaInfoMap_s().release()); + // Prepare |track_to_id_| for use in |ProducePartialResultsOnNetworkThread|. + // This avoids a possible deadlock if |MediaStreamTrackInterface::id| is + // implemented to invoke on the signaling thread. + track_to_id_ = PrepareTrackToID_s(); + + voice_mid_.reset(); + if (pc_->voice_channel()) { + voice_mid_ = pc_->voice_channel()->content_name(); + } + + video_mid_.reset(); + if (pc_->video_channel()) { + video_mid_ = pc_->video_channel()->content_name(); + } // Prepare |call_stats_| here since GetCallStats() will hop to the worker // thread. @@ -704,8 +758,7 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread( timestamp_us); ProduceDataChannelStats_s(timestamp_us, report.get()); - ProduceMediaStreamStats_s(timestamp_us, report.get()); - ProduceMediaStreamTrackStats_s(timestamp_us, report.get()); + ProduceMediaStreamAndTrackStats_s(timestamp_us, report.get()); ProducePeerConnectionStats_s(timestamp_us, report.get()); AddPartialResults(report); @@ -718,8 +771,8 @@ void RTCStatsCollector::ProducePartialResultsOnNetworkThread( timestamp_us); std::set transport_names; - for (const auto& stats : transceiver_stats_infos_) { - transport_names.insert(stats.transport_name); + for (const auto& entry : transport_names_by_mid_) { + transport_names.insert(entry.second); } std::map transport_stats_by_name = pc_->GetTransportStatsByNames(transport_names); @@ -728,10 +781,12 @@ void RTCStatsCollector::ProducePartialResultsOnNetworkThread( PrepareTransportCertificateStats_n(transport_stats_by_name); ProduceCertificateStats_n(timestamp_us, transport_cert_stats, report.get()); - ProduceCodecStats_n(timestamp_us, transceiver_stats_infos_, report.get()); + ProduceCodecStats_n(timestamp_us, *track_media_info_map_, report.get()); ProduceIceCandidateAndPairStats_n(timestamp_us, transport_stats_by_name, + track_media_info_map_->video_media_info(), call_stats_, report.get()); - ProduceRTPStreamStats_n(timestamp_us, transceiver_stats_infos_, report.get()); + ProduceRTPStreamStats_n(timestamp_us, transport_names_by_mid_, + *track_media_info_map_, report.get()); ProduceTransportStats_n(timestamp_us, transport_stats_by_name, transport_cert_stats, report.get()); @@ -763,7 +818,9 @@ void RTCStatsCollector::AddPartialResults_s( cache_timestamp_us_ = partial_report_timestamp_us_; cached_report_ = partial_report_; partial_report_ = nullptr; - transceiver_stats_infos_.clear(); + transport_names_by_mid_.clear(); + track_media_info_map_.reset(); + track_to_id_.clear(); // Trace WebRTC Stats when getStats is called on Javascript. // This allows access to WebRTC stats from trace logs. To enable them, // select the "webrtc_stats" category when recording traces. @@ -802,40 +859,37 @@ void RTCStatsCollector::ProduceCertificateStats_n( } void RTCStatsCollector::ProduceCodecStats_n( - int64_t timestamp_us, - const std::vector& transceiver_stats_infos, + int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); - for (const auto& stats : transceiver_stats_infos) { - const cricket::VoiceMediaInfo* voice_media_info = - stats.track_media_info_map->voice_media_info(); - const cricket::VideoMediaInfo* video_media_info = - stats.track_media_info_map->video_media_info(); - // Audio - if (voice_media_info) { - // Inbound - for (const auto& pair : voice_media_info->receive_codecs) { - report->AddStats(CodecStatsFromRtpCodecParameters( - timestamp_us, stats.mid, true, pair.second)); - } - // Outbound - for (const auto& pair : voice_media_info->send_codecs) { - report->AddStats(CodecStatsFromRtpCodecParameters( - timestamp_us, stats.mid, false, pair.second)); - } + // Audio + if (track_media_info_map.voice_media_info()) { + // Inbound + for (const auto& pair : + track_media_info_map.voice_media_info()->receive_codecs) { + report->AddStats(CodecStatsFromRtpCodecParameters( + timestamp_us, true, true, pair.second)); } - // Video - if (video_media_info) { - // Inbound - for (const auto& pair : video_media_info->receive_codecs) { - report->AddStats(CodecStatsFromRtpCodecParameters( - timestamp_us, stats.mid, true, pair.second)); - } - // Outbound - for (const auto& pair : video_media_info->send_codecs) { - report->AddStats(CodecStatsFromRtpCodecParameters( - timestamp_us, stats.mid, false, pair.second)); - } + // Outbound + for (const auto& pair : + track_media_info_map.voice_media_info()->send_codecs) { + report->AddStats(CodecStatsFromRtpCodecParameters( + timestamp_us, false, true, pair.second)); + } + } + // Video + if (track_media_info_map.video_media_info()) { + // Inbound + for (const auto& pair : + track_media_info_map.video_media_info()->receive_codecs) { + report->AddStats(CodecStatsFromRtpCodecParameters( + timestamp_us, true, false, pair.second)); + } + // Outbound + for (const auto& pair : + track_media_info_map.video_media_info()->send_codecs) { + report->AddStats(CodecStatsFromRtpCodecParameters( + timestamp_us, false, false, pair.second)); } } } @@ -866,6 +920,7 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n( int64_t timestamp_us, const std::map& transport_stats_by_name, + const cricket::VideoMediaInfo* video_media_info, const Call::Stats& call_stats, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); @@ -945,61 +1000,16 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n( } } -void RTCStatsCollector::ProduceMediaStreamStats_s( - int64_t timestamp_us, - RTCStatsReport* report) const { +void RTCStatsCollector::ProduceMediaStreamAndTrackStats_s( + int64_t timestamp_us, RTCStatsReport* report) const { RTC_DCHECK(signaling_thread_->IsCurrent()); - - std::map> track_ids; - - for (const auto& stats : transceiver_stats_infos_) { - for (auto sender : stats.transceiver->senders()) { - std::string track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kSender, sender->internal()->AttachmentId()); - for (auto& stream_id : sender->stream_ids()) { - track_ids[stream_id].push_back(track_id); - } - } - for (auto receiver : stats.transceiver->receivers()) { - std::string track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kReceiver, receiver->internal()->AttachmentId()); - for (auto& stream : receiver->streams()) { - track_ids[stream->label()].push_back(track_id); - } - } - } - - // Build stats for each stream ID known. - for (auto& it : track_ids) { - std::unique_ptr stream_stats( - new RTCMediaStreamStats("RTCMediaStream_" + it.first, timestamp_us)); - stream_stats->stream_identifier = it.first; - stream_stats->track_ids = it.second; - report->AddStats(std::move(stream_stats)); - } -} - -void RTCStatsCollector::ProduceMediaStreamTrackStats_s( - int64_t timestamp_us, - RTCStatsReport* report) const { - RTC_DCHECK(signaling_thread_->IsCurrent()); - for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos_) { - std::vector> senders; - for (auto sender : stats.transceiver->senders()) { - senders.push_back(sender->internal()); - } - ProduceSenderMediaTrackStats(timestamp_us, *stats.track_media_info_map, - senders, report); - - std::vector> receivers; - for (auto receiver : stats.transceiver->receivers()) { - receivers.push_back(receiver->internal()); - } - ProduceReceiverMediaTrackStats(timestamp_us, *stats.track_media_info_map, - receivers, report); - } + RTC_DCHECK(track_media_info_map_); + ProduceMediaStreamStats(timestamp_us, pc_->GetSenders(), pc_->GetReceivers(), + report); + ProduceSenderMediaTrackStats(timestamp_us, *track_media_info_map_, + pc_->GetSenders(), report); + ProduceReceiverMediaTrackStats(timestamp_us, *track_media_info_map_, + pc_->GetReceivers(), report); } void RTCStatsCollector::ProducePeerConnectionStats_s( @@ -1014,125 +1024,122 @@ void RTCStatsCollector::ProducePeerConnectionStats_s( void RTCStatsCollector::ProduceRTPStreamStats_n( int64_t timestamp_us, - const std::vector& transceiver_stats_infos, + const std::map& transport_names_by_mid, + const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); - for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos) { - if (stats.media_type == cricket::MEDIA_TYPE_AUDIO) { - ProduceAudioRTPStreamStats_n(timestamp_us, stats, report); - } else if (stats.media_type == cricket::MEDIA_TYPE_VIDEO) { - ProduceVideoRTPStreamStats_n(timestamp_us, stats, report); - } else { - RTC_NOTREACHED(); - } - } -} + // Audio + if (track_media_info_map.voice_media_info()) { + RTC_DCHECK(voice_mid_); + const std::string& transport_name = transport_names_by_mid.at(*voice_mid_); + std::string transport_id = RTCTransportStatsIDFromTransportChannel( + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); + // Inbound + for (const cricket::VoiceReceiverInfo& voice_receiver_info : + track_media_info_map.voice_media_info()->receivers) { + if (!voice_receiver_info.connected()) + continue; -void RTCStatsCollector::ProduceAudioRTPStreamStats_n( - int64_t timestamp_us, - const RtpTransceiverStatsInfo& stats, - RTCStatsReport* report) const { - RTC_DCHECK(stats.track_media_info_map); - const TrackMediaInfoMap& track_media_info_map = *stats.track_media_info_map; - RTC_DCHECK(track_media_info_map.voice_media_info()); - std::string transport_id = RTCTransportStatsIDFromTransportChannel( - stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); - // Inbound - for (const cricket::VoiceReceiverInfo& voice_receiver_info : - track_media_info_map.voice_media_info()->receivers) { - if (!voice_receiver_info.connected()) - continue; - auto inbound_audio = rtc::MakeUnique( - RTCInboundRTPStreamStatsIDFromSSRC(true, voice_receiver_info.ssrc()), - timestamp_us); - SetInboundRTPStreamStatsFromVoiceReceiverInfo( - stats.mid, voice_receiver_info, inbound_audio.get()); - // TODO(hta): This lookup should look for the sender, not the track. - rtc::scoped_refptr audio_track = - track_media_info_map.GetAudioTrack(voice_receiver_info); - if (audio_track) { - inbound_audio->track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kReceiver, - track_media_info_map.GetAttachmentIdByTrack(audio_track).value()); + std::unique_ptr inbound_audio( + new RTCInboundRTPStreamStats(RTCInboundRTPStreamStatsIDFromSSRC( + true, voice_receiver_info.ssrc()), + timestamp_us)); + SetInboundRTPStreamStatsFromVoiceReceiverInfo(voice_receiver_info, + inbound_audio.get()); + // TODO(hta): This lookup should look for the sender, not the track. + rtc::scoped_refptr audio_track = + track_media_info_map_->GetAudioTrack(voice_receiver_info); + if (audio_track) { + RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end()); + inbound_audio + ->track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kReceiver, + track_media_info_map_->GetAttachmentIdByTrack(audio_track).value()); + } + inbound_audio->transport_id = transport_id; + report->AddStats(std::move(inbound_audio)); + } + // Outbound + for (const cricket::VoiceSenderInfo& voice_sender_info : + track_media_info_map.voice_media_info()->senders) { + if (!voice_sender_info.connected()) + continue; + std::unique_ptr outbound_audio( + new RTCOutboundRTPStreamStats( + RTCOutboundRTPStreamStatsIDFromSSRC( + true, voice_sender_info.ssrc()), + timestamp_us)); + SetOutboundRTPStreamStatsFromVoiceSenderInfo( + voice_sender_info, outbound_audio.get()); + rtc::scoped_refptr audio_track = + track_media_info_map_->GetAudioTrack(voice_sender_info); + if (audio_track) { + RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end()); + outbound_audio + ->track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kSender, + track_media_info_map.GetAttachmentIdByTrack(audio_track).value()); + } + outbound_audio->transport_id = transport_id; + report->AddStats(std::move(outbound_audio)); } - inbound_audio->transport_id = transport_id; - report->AddStats(std::move(inbound_audio)); } - // Outbound - for (const cricket::VoiceSenderInfo& voice_sender_info : - track_media_info_map.voice_media_info()->senders) { - if (!voice_sender_info.connected()) - continue; - auto outbound_audio = rtc::MakeUnique( - RTCOutboundRTPStreamStatsIDFromSSRC(true, voice_sender_info.ssrc()), - timestamp_us); - SetOutboundRTPStreamStatsFromVoiceSenderInfo(stats.mid, voice_sender_info, - outbound_audio.get()); - rtc::scoped_refptr audio_track = - track_media_info_map.GetAudioTrack(voice_sender_info); - if (audio_track) { - outbound_audio->track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kSender, - track_media_info_map.GetAttachmentIdByTrack(audio_track).value()); + // Video + if (track_media_info_map.video_media_info()) { + RTC_DCHECK(video_mid_); + const std::string& transport_name = transport_names_by_mid.at(*video_mid_); + std::string transport_id = RTCTransportStatsIDFromTransportChannel( + transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); + // Inbound + for (const cricket::VideoReceiverInfo& video_receiver_info : + track_media_info_map.video_media_info()->receivers) { + // TODO(nisse): SSRC == 0 currently means none. Delete check when that + // is fixed. + if (!video_receiver_info.connected()) + continue; + std::unique_ptr inbound_video( + new RTCInboundRTPStreamStats( + RTCInboundRTPStreamStatsIDFromSSRC( + false, video_receiver_info.ssrc()), + timestamp_us)); + SetInboundRTPStreamStatsFromVideoReceiverInfo( + video_receiver_info, inbound_video.get()); + rtc::scoped_refptr video_track = + track_media_info_map_->GetVideoTrack(video_receiver_info); + if (video_track) { + RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end()); + inbound_video + ->track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kReceiver, + track_media_info_map_->GetAttachmentIdByTrack(video_track).value()); + } + inbound_video->transport_id = transport_id; + report->AddStats(std::move(inbound_video)); } - outbound_audio->transport_id = transport_id; - report->AddStats(std::move(outbound_audio)); - } -} - -void RTCStatsCollector::ProduceVideoRTPStreamStats_n( - int64_t timestamp_us, - const RtpTransceiverStatsInfo& stats, - RTCStatsReport* report) const { - RTC_DCHECK(stats.track_media_info_map); - const TrackMediaInfoMap& track_media_info_map = *stats.track_media_info_map; - RTC_DCHECK(track_media_info_map.video_media_info()); - std::string transport_id = RTCTransportStatsIDFromTransportChannel( - stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP); - // Inbound - for (const cricket::VideoReceiverInfo& video_receiver_info : - track_media_info_map.video_media_info()->receivers) { - if (!video_receiver_info.connected()) - continue; - auto inbound_video = rtc::MakeUnique( - RTCInboundRTPStreamStatsIDFromSSRC(false, video_receiver_info.ssrc()), - timestamp_us); - SetInboundRTPStreamStatsFromVideoReceiverInfo( - stats.mid, video_receiver_info, inbound_video.get()); - rtc::scoped_refptr video_track = - track_media_info_map.GetVideoTrack(video_receiver_info); - if (video_track) { - inbound_video->track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kReceiver, - track_media_info_map.GetAttachmentIdByTrack(video_track).value()); + // Outbound + for (const cricket::VideoSenderInfo& video_sender_info : + track_media_info_map.video_media_info()->senders) { + if (!video_sender_info.connected()) + continue; + std::unique_ptr outbound_video( + new RTCOutboundRTPStreamStats(RTCOutboundRTPStreamStatsIDFromSSRC( + false, video_sender_info.ssrc()), + timestamp_us)); + SetOutboundRTPStreamStatsFromVideoSenderInfo( + video_sender_info, outbound_video.get()); + rtc::scoped_refptr video_track = + track_media_info_map_->GetVideoTrack(video_sender_info); + if (video_track) { + RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end()); + outbound_video + ->track_id = RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( + kSender, + track_media_info_map_->GetAttachmentIdByTrack(video_track).value()); + } + outbound_video->transport_id = transport_id; + report->AddStats(std::move(outbound_video)); } - inbound_video->transport_id = transport_id; - report->AddStats(std::move(inbound_video)); - } - // Outbound - for (const cricket::VideoSenderInfo& video_sender_info : - track_media_info_map.video_media_info()->senders) { - if (!video_sender_info.connected()) - continue; - auto outbound_video = rtc::MakeUnique( - RTCOutboundRTPStreamStatsIDFromSSRC(false, video_sender_info.ssrc()), - timestamp_us); - SetOutboundRTPStreamStatsFromVideoSenderInfo(stats.mid, video_sender_info, - outbound_video.get()); - rtc::scoped_refptr video_track = - track_media_info_map.GetVideoTrack(video_sender_info); - if (video_track) { - outbound_video->track_id = - RTCMediaStreamTrackStatsIDFromDirectionAndAttachment( - kSender, - track_media_info_map.GetAttachmentIdByTrack(video_track).value()); - } - outbound_video->transport_id = transport_id; - report->AddStats(std::move(outbound_video)); } } @@ -1236,100 +1243,47 @@ RTCStatsCollector::PrepareTransportCertificateStats_n( return transport_cert_stats; } -std::vector -RTCStatsCollector::PrepareTransceiverStatsInfos_s() const { - std::vector transceiver_stats_infos; - - // These are used to invoke GetStats for all the media channels together in - // one worker thread hop. - std::map> - voice_stats; - std::map> - video_stats; - - for (auto transceiver : pc_->GetTransceiversInternal()) { - cricket::MediaType media_type = transceiver->internal()->media_type(); - cricket::BaseChannel* channel = transceiver->internal()->channel(); - if (!channel) { - // No BaseChannel, no stats to collect. - continue; - } - - // Prepare stats entry. The TrackMediaInfoMap will be filled in after the - // stats have been fetched on the worker thread. - transceiver_stats_infos.emplace_back(); - RtpTransceiverStatsInfo& stats = transceiver_stats_infos.back(); - stats.transceiver = transceiver->internal(); - stats.media_type = media_type; - stats.mid = channel->content_name(); - stats.transport_name = channel->transport_name(); - - if (media_type == cricket::MEDIA_TYPE_AUDIO) { - auto* voice_channel = static_cast(channel); - RTC_DCHECK(voice_stats.find(voice_channel->media_channel()) == - voice_stats.end()); - voice_stats[voice_channel->media_channel()] = - rtc::MakeUnique(); - } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { - auto* video_channel = static_cast(channel); - RTC_DCHECK(video_stats.find(video_channel->media_channel()) == - video_stats.end()); - video_stats[video_channel->media_channel()] = - rtc::MakeUnique(); - } else { - RTC_NOTREACHED(); +std::unique_ptr +RTCStatsCollector::PrepareTrackMediaInfoMap_s() const { + RTC_DCHECK(signaling_thread_->IsCurrent()); + std::unique_ptr voice_media_info; + if (pc_->voice_channel()) { + voice_media_info.reset(new cricket::VoiceMediaInfo()); + if (!pc_->voice_channel()->GetStats(voice_media_info.get())) { + voice_media_info.reset(); } } - - // Call GetStats for all media channels together on the worker thread in one - // hop. - worker_thread_->Invoke(RTC_FROM_HERE, [&] { - for (const auto& entry : voice_stats) { - if (!entry.first->GetStats(entry.second.get())) { - RTC_LOG(LS_WARNING) << "Failed to get voice stats."; - } + std::unique_ptr video_media_info; + if (pc_->video_channel()) { + video_media_info.reset(new cricket::VideoMediaInfo()); + if (!pc_->video_channel()->GetStats(video_media_info.get())) { + video_media_info.reset(); } - for (const auto& entry : video_stats) { - if (!entry.first->GetStats(entry.second.get())) { - RTC_LOG(LS_WARNING) << "Failed to get video stats."; - } - } - }); - - // Create the TrackMediaInfoMap for each transceiver stats object. - for (auto& stats : transceiver_stats_infos) { - auto transceiver = stats.transceiver; - RTC_DCHECK(transceiver->channel()); - std::unique_ptr voice_media_info; - std::unique_ptr video_media_info; - cricket::MediaType media_type = transceiver->media_type(); - if (media_type == cricket::MEDIA_TYPE_AUDIO) { - auto* voice_channel = - static_cast(transceiver->channel()); - RTC_DCHECK(voice_stats[voice_channel->media_channel()]); - voice_media_info = std::move(voice_stats[voice_channel->media_channel()]); - } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { - auto* video_channel = - static_cast(transceiver->channel()); - RTC_DCHECK(video_stats[video_channel->media_channel()]); - video_media_info = std::move(video_stats[video_channel->media_channel()]); - } - std::vector> senders; - for (auto sender : transceiver->senders()) { - senders.push_back(sender->internal()); - } - std::vector> receivers; - for (auto receiver : transceiver->receivers()) { - receivers.push_back(receiver->internal()); - } - stats.track_media_info_map = rtc::MakeUnique( - std::move(voice_media_info), std::move(video_media_info), senders, - receivers); } + std::unique_ptr track_media_info_map(new TrackMediaInfoMap( + std::move(voice_media_info), std::move(video_media_info), + pc_->GetSenders(), pc_->GetReceivers())); + return track_media_info_map; +} - return transceiver_stats_infos; +std::map +RTCStatsCollector::PrepareTrackToID_s() const { + // TODO(hta): Remove this method, and vector its callers via + // senders / receivers instead. + // It ignores tracks that are multiply connected to the PC. + RTC_DCHECK(signaling_thread_->IsCurrent()); + std::map track_to_id; + for (auto sender : pc_->GetSenders()) { + auto track = sender->track(); + if (track) + track_to_id[track.get()] = track->id(); + } + for (auto receiver : pc_->GetReceivers()) { + auto track = receiver->track(); + if (track) + track_to_id[track.get()] = track->id(); + } + return track_to_id; } void RTCStatsCollector::OnDataChannelCreated(DataChannel* channel) { diff --git a/pc/rtcstatscollector.h b/pc/rtcstatscollector.h index f88586ae1f..24a7bb2f0e 100644 --- a/pc/rtcstatscollector.h +++ b/pc/rtcstatscollector.h @@ -78,19 +78,6 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, std::unique_ptr remote; }; - // Structure for tracking stats about each RtpTransceiver managed by the - // PeerConnection. This can either by a Plan B style or Unified Plan style - // transceiver (i.e., can have 0 or many senders and receivers). - // Some fields are copied from the RtpTransceiver/BaseChannel object so that - // they can be accessed safely on threads other than the signaling thread. - struct RtpTransceiverStatsInfo { - rtc::scoped_refptr transceiver; - cricket::MediaType media_type; - std::string mid; - std::string transport_name; - std::unique_ptr track_media_info_map; - }; - void AddPartialResults_s(rtc::scoped_refptr partial_report); void DeliverCachedReport(); @@ -101,8 +88,7 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, RTCStatsReport* report) const; // Produces |RTCCodecStats|. void ProduceCodecStats_n( - int64_t timestamp_us, - const std::vector& transceiver_stats_infos, + int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const; // Produces |RTCDataChannelStats|. void ProduceDataChannelStats_s( @@ -112,28 +98,21 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, int64_t timestamp_us, const std::map& transport_stats_by_name, + const cricket::VideoMediaInfo* video_media_info, const Call::Stats& call_stats, RTCStatsReport* report) const; - // Produces |RTCMediaStreamStats|. - void ProduceMediaStreamStats_s(int64_t timestamp_us, - RTCStatsReport* report) const; - // Produces |RTCMediaStreamTrackStats|. - void ProduceMediaStreamTrackStats_s(int64_t timestamp_us, - RTCStatsReport* report) const; + // Produces |RTCMediaStreamStats| and |RTCMediaStreamTrackStats|. + void ProduceMediaStreamAndTrackStats_s( + int64_t timestamp_us, RTCStatsReport* report) const; // Produces |RTCPeerConnectionStats|. void ProducePeerConnectionStats_s( int64_t timestamp_us, RTCStatsReport* report) const; // Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|. void ProduceRTPStreamStats_n( int64_t timestamp_us, - const std::vector& transceiver_stats_infos, + const std::map& transport_names_by_mid, + const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const; - void ProduceAudioRTPStreamStats_n(int64_t timestamp_us, - const RtpTransceiverStatsInfo& stats, - RTCStatsReport* report) const; - void ProduceVideoRTPStreamStats_n(int64_t timestamp_us, - const RtpTransceiverStatsInfo& stats, - RTCStatsReport* report) const; // Produces |RTCTransportStats|. void ProduceTransportStats_n( int64_t timestamp_us, @@ -147,7 +126,8 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, PrepareTransportCertificateStats_n( const std::map& transport_stats_by_name) const; - std::vector PrepareTransceiverStatsInfos_s() const; + std::unique_ptr PrepareTrackMediaInfoMap_s() const; + std::map PrepareTrackToID_s() const; // Slots for signals (sigslot) that are wired up to |pc_|. void OnDataChannelCreated(DataChannel* channel); @@ -170,7 +150,12 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, // |ProducePartialResultsOnSignalingThread|, reset after work is complete. Not // passed as arguments to avoid copies. This is thread safe - when we // set/reset we know there are no pending stats requests in progress. - std::vector transceiver_stats_infos_; + std::map transport_names_by_mid_; + std::unique_ptr track_media_info_map_; + std::map track_to_id_; + + rtc::Optional voice_mid_; + rtc::Optional video_mid_; Call::Stats call_stats_; diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc index a54367d983..566d677661 100644 --- a/pc/rtcstatscollector_unittest.cc +++ b/pc/rtcstatscollector_unittest.cc @@ -18,6 +18,8 @@ #include "api/rtpparameters.h" #include "api/stats/rtcstats_objects.h" #include "api/stats/rtcstatsreport.h" +#include "api/test/mock_rtpreceiver.h" +#include "api/test/mock_rtpsender.h" #include "p2p/base/p2pconstants.h" #include "p2p/base/port.h" #include "pc/mediastream.h" @@ -25,8 +27,6 @@ #include "pc/rtcstatscollector.h" #include "pc/test/fakepeerconnectionforstats.h" #include "pc/test/mock_datachannel.h" -#include "pc/test/mock_rtpreceiverinternal.h" -#include "pc/test/mock_rtpsenderinternal.h" #include "pc/test/rtcstatsobtainer.h" #include "rtc_base/checks.h" #include "rtc_base/fakeclock.h" @@ -38,7 +38,6 @@ #include "rtc_base/timedelta.h" #include "rtc_base/timeutils.h" -using testing::AtLeast; using testing::Invoke; using testing::Return; @@ -244,13 +243,13 @@ rtc::scoped_refptr CreateFakeTrack( } } -rtc::scoped_refptr CreateMockSender( +rtc::scoped_refptr CreateMockSender( const rtc::scoped_refptr& track, uint32_t ssrc, int attachment_id, std::vector local_stream_ids) { - rtc::scoped_refptr sender( - new rtc::RefCountedObject()); + rtc::scoped_refptr sender( + new rtc::RefCountedObject()); EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track)); EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc)); EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return( @@ -268,12 +267,12 @@ rtc::scoped_refptr CreateMockSender( return sender; } -rtc::scoped_refptr CreateMockReceiver( +rtc::scoped_refptr CreateMockReceiver( const rtc::scoped_refptr& track, uint32_t ssrc, int attachment_id) { - rtc::scoped_refptr receiver( - new rtc::RefCountedObject()); + rtc::scoped_refptr receiver( + new rtc::RefCountedObject()); EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); EXPECT_CALL(*receiver, streams()) .WillRepeatedly( @@ -347,7 +346,7 @@ class RTCStatsCollectorWrapper { } } - rtc::scoped_refptr sender = + rtc::scoped_refptr sender = CreateMockSender(track, ssrc, 50, {}); pc_->AddSender(sender); } @@ -370,7 +369,7 @@ class RTCStatsCollectorWrapper { remote_stream->AddTrack(static_cast(track.get())); } - rtc::scoped_refptr receiver = + rtc::scoped_refptr receiver = CreateMockReceiver(track, ssrc, 62); EXPECT_CALL(*receiver, streams()) .WillRepeatedly( @@ -411,7 +410,7 @@ class RTCStatsCollectorWrapper { MediaStreamTrackInterface::kAudioKind); voice_media_info.senders.push_back(voice_sender_info); - rtc::scoped_refptr rtp_sender = CreateMockSender( + rtc::scoped_refptr rtp_sender = CreateMockSender( rtc::scoped_refptr(local_audio_track), voice_sender_info.local_stats[0].ssrc, attachment_id++, local_stream_ids); @@ -427,10 +426,9 @@ class RTCStatsCollectorWrapper { MediaStreamTrackInterface::kAudioKind); voice_media_info.receivers.push_back(voice_receiver_info); - rtc::scoped_refptr rtp_receiver = - CreateMockReceiver( - rtc::scoped_refptr(remote_audio_track), - voice_receiver_info.local_stats[0].ssrc, attachment_id++); + rtc::scoped_refptr rtp_receiver = CreateMockReceiver( + rtc::scoped_refptr(remote_audio_track), + voice_receiver_info.local_stats[0].ssrc, attachment_id++); EXPECT_CALL(*rtp_receiver, streams()) .WillRepeatedly(Return(remote_streams)); pc_->AddReceiver(rtp_receiver); @@ -445,7 +443,7 @@ class RTCStatsCollectorWrapper { MediaStreamTrackInterface::kVideoKind); video_media_info.senders.push_back(video_sender_info); - rtc::scoped_refptr rtp_sender = CreateMockSender( + rtc::scoped_refptr rtp_sender = CreateMockSender( rtc::scoped_refptr(local_video_track), video_sender_info.local_stats[0].ssrc, attachment_id++, local_stream_ids); @@ -461,10 +459,9 @@ class RTCStatsCollectorWrapper { MediaStreamTrackInterface::kVideoKind); video_media_info.receivers.push_back(video_receiver_info); - rtc::scoped_refptr rtp_receiver = - CreateMockReceiver( - rtc::scoped_refptr(remote_video_track), - video_receiver_info.local_stats[0].ssrc, attachment_id++); + rtc::scoped_refptr rtp_receiver = CreateMockReceiver( + rtc::scoped_refptr(remote_video_track), + video_receiver_info.local_stats[0].ssrc, attachment_id++); EXPECT_CALL(*rtp_receiver, streams()) .WillRepeatedly(Return(remote_streams)); pc_->AddReceiver(rtp_receiver); @@ -609,7 +606,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) { voice_media_info.send_codecs.insert( std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec)); - auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("audio", "TransportName"); voice_media_channel->SetStats(voice_media_info); // Video @@ -631,31 +628,31 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) { video_media_info.send_codecs.insert( std::make_pair(outbound_video_codec.payload_type, outbound_video_codec)); - auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("video", "TransportName"); video_media_channel->SetStats(video_media_info); rtc::scoped_refptr report = stats_->GetStatsReport(); - RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1", - report->timestamp_us()); + RTCCodecStats expected_inbound_audio_codec( + "RTCCodec_InboundAudio_1", report->timestamp_us()); expected_inbound_audio_codec.payload_type = 1; expected_inbound_audio_codec.mime_type = "audio/opus"; expected_inbound_audio_codec.clock_rate = 1337; - RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2", - report->timestamp_us()); + RTCCodecStats expected_outbound_audio_codec( + "RTCCodec_OutboundAudio_2", report->timestamp_us()); expected_outbound_audio_codec.payload_type = 2; expected_outbound_audio_codec.mime_type = "audio/isac"; expected_outbound_audio_codec.clock_rate = 1338; - RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3", - report->timestamp_us()); + RTCCodecStats expected_inbound_video_codec( + "RTCCodec_InboundVideo_3", report->timestamp_us()); expected_inbound_video_codec.payload_type = 3; expected_inbound_video_codec.mime_type = "video/H264"; expected_inbound_video_codec.clock_rate = 1339; - RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4", - report->timestamp_us()); + RTCCodecStats expected_outbound_video_codec( + "RTCCodec_OutboundVideo_4", report->timestamp_us()); expected_outbound_video_codec.payload_type = 4; expected_outbound_video_codec.mime_type = "video/VP8"; expected_outbound_video_codec.clock_rate = 1340; @@ -1447,6 +1444,8 @@ TEST_F(RTCStatsCollectorTest, } TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { + const char kTransportName[] = "TransportName"; + cricket::VoiceMediaInfo voice_media_info; voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo()); @@ -1468,7 +1467,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { voice_media_info.receive_codecs.insert( std::make_pair(codec_parameters.payload_type, codec_parameters)); - auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("voice", kTransportName); voice_media_channel->SetStats(voice_media_info); stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", 1); @@ -1484,8 +1483,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = stats_of_track_type[0]->id(); - expected_audio.transport_id = "RTCTransport_TransportName_1"; - expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42"; + expected_audio.transport_id = + "RTCTransport_TransportName_" + + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); + expected_audio.codec_id = "RTCCodec_InboundAudio_42"; expected_audio.packets_received = 2; expected_audio.bytes_received = 3; expected_audio.packets_lost = -1; @@ -1526,7 +1527,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { video_media_info.receive_codecs.insert( std::make_pair(codec_parameters.payload_type, codec_parameters)); - auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("video", "TransportName"); video_media_channel->SetStats(video_media_info); stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", 1); @@ -1539,8 +1540,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { expected_video.is_remote = false; expected_video.media_type = "video"; expected_video.track_id = IdForType(report); - expected_video.transport_id = "RTCTransport_TransportName_1"; - expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42"; + expected_video.transport_id = "RTCTransport_TransportName_" + + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); + expected_video.codec_id = "RTCCodec_InboundVideo_42"; expected_video.fir_count = 5; expected_video.pli_count = 6; expected_video.nack_count = 7; @@ -1590,7 +1592,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { voice_media_info.send_codecs.insert( std::make_pair(codec_parameters.payload_type, codec_parameters)); - auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("audio", "TransportName"); voice_media_channel->SetStats(voice_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1, true); @@ -1603,8 +1605,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = IdForType(report); - expected_audio.transport_id = "RTCTransport_TransportName_1"; - expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; + expected_audio.transport_id = "RTCTransport_TransportName_" + + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); + expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; expected_audio.packets_sent = 2; expected_audio.bytes_sent = 3; @@ -1645,7 +1648,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { video_media_info.send_codecs.insert( std::make_pair(codec_parameters.payload_type, codec_parameters)); - auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("video", "TransportName"); video_media_channel->SetStats(video_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 1, true); @@ -1663,8 +1666,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.is_remote = false; expected_video.media_type = "video"; expected_video.track_id = stats_of_track_type[0]->id(); - expected_video.transport_id = "RTCTransport_TransportName_1"; - expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42"; + expected_video.transport_id = "RTCTransport_TransportName_" + + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); + expected_video.codec_id = "RTCCodec_OutboundVideo_42"; expected_video.fir_count = 2; expected_video.pli_count = 3; expected_video.nack_count = 4; @@ -1850,7 +1854,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { std::make_pair(codec_parameters.payload_type, codec_parameters)); // Emulates the case where AddTrack is used without an associated MediaStream - auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("audio", "TransportName"); voice_media_channel->SetStats(voice_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1, false); @@ -1863,8 +1867,10 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.track_id = IdForType(report); - expected_audio.transport_id = "RTCTransport_TransportName_1"; - expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; + expected_audio.transport_id = + "RTCTransport_TransportName_" + + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); + expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; expected_audio.packets_sent = 2; expected_audio.bytes_sent = 3; @@ -1881,13 +1887,10 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { // SSRC 0, meaning "unconnected". // In this state, we report on track stats, but not RTP stats. TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) { - pc_->AddVoiceChannel("audio", "transport"); - rtc::scoped_refptr track = CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack", MediaStreamTrackInterface::kLive); - rtc::scoped_refptr sender = - CreateMockSender(track, 0, 49, {}); + rtc::scoped_refptr sender = CreateMockSender(track, 0, 49, {}); pc_->AddSender(sender); rtc::scoped_refptr report = stats_->GetStatsReport(); @@ -1902,12 +1905,10 @@ TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) { } TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) { - pc_->AddVoiceChannel("audio", "transport"); - rtc::scoped_refptr track = CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack", MediaStreamTrackInterface::kLive); - rtc::scoped_refptr sender = + rtc::scoped_refptr sender = CreateMockSender(track, 4711, 49, {}); pc_->AddSender(sender); diff --git a/pc/rtpreceiver.cc b/pc/rtpreceiver.cc index bf0b1d68da..05990f4e03 100644 --- a/pc/rtpreceiver.cc +++ b/pc/rtpreceiver.cc @@ -202,6 +202,11 @@ void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) { } } +void AudioRtpReceiver::SetMediaChannel( + cricket::VoiceMediaChannel* media_channel) { + media_channel_ = media_channel; +} + void AudioRtpReceiver::NotifyFirstPacketReceived() { if (observer_) { observer_->OnFirstPacketReceived(media_type()); @@ -337,6 +342,11 @@ void VideoRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) { } } +void VideoRtpReceiver::SetMediaChannel( + cricket::VideoMediaChannel* media_channel) { + media_channel_ = media_channel; +} + void VideoRtpReceiver::NotifyFirstPacketReceived() { if (observer_) { observer_->OnFirstPacketReceived(media_type()); diff --git a/pc/rtpreceiver.h b/pc/rtpreceiver.h index da92298c4f..887f828312 100644 --- a/pc/rtpreceiver.h +++ b/pc/rtpreceiver.h @@ -34,16 +34,6 @@ class RtpReceiverInternal : public RtpReceiverInterface { public: virtual void Stop() = 0; - // Sets the underlying MediaEngine channel associated with this RtpSender. - // SetVoiceMediaChannel should be used for audio RtpSenders and - // SetVideoMediaChannel should be used for video RtpSenders. Must call the - // appropriate SetXxxMediaChannel(nullptr) before the media channel is - // destroyed. - virtual void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) = 0; - virtual void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_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. @@ -62,11 +52,6 @@ class RtpReceiverInternal : public RtpReceiverInterface { // any new streams. virtual void SetStreams( const std::vector>& streams) = 0; - - // Returns an ID that changes if the attached track changes, but - // otherwise remains constant. Used to generate IDs for stats. - // The special value zero means that no track is attached. - virtual int AttachmentId() const = 0; }; class AudioRtpReceiver : public ObserverInterface, @@ -117,14 +102,9 @@ class AudioRtpReceiver : public ObserverInterface, void SetObserver(RtpReceiverObserverInterface* observer) override; - void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) override { - media_channel_ = voice_media_channel; - } - void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_media_channel) override { - RTC_NOTREACHED(); - } + // Does not take ownership. + // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. + void SetMediaChannel(cricket::VoiceMediaChannel* media_channel); std::vector GetSources() const override; int AttachmentId() const override { return attachment_id_; } @@ -191,16 +171,9 @@ class VideoRtpReceiver : public rtc::RefCountedObject { void SetObserver(RtpReceiverObserverInterface* observer) override; - void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) override { - RTC_NOTREACHED(); - } - void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_media_channel) override { - media_channel_ = video_media_channel; - } - - int AttachmentId() const override { return attachment_id_; } + // Does not take ownership. + // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. + void SetMediaChannel(cricket::VideoMediaChannel* media_channel); private: bool SetSink(rtc::VideoSinkInterface* sink); diff --git a/pc/rtpsender.h b/pc/rtpsender.h index 000df94a56..97e32e2638 100644 --- a/pc/rtpsender.h +++ b/pc/rtpsender.h @@ -34,16 +34,6 @@ class StatsCollector; // Internal interface used by PeerConnection. class RtpSenderInternal : public RtpSenderInterface { public: - // Sets the underlying MediaEngine channel associated with this RtpSender. - // SetVoiceMediaChannel should be used for audio RtpSenders and - // SetVideoMediaChannel should be used for video RtpSenders. Must call the - // appropriate SetXxxMediaChannel(nullptr) before the media channel is - // destroyed. - virtual void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) = 0; - virtual void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_media_channel) = 0; - // Used to set the SSRC of the sender, once a local description has been set. // If |ssrc| is 0, this indiates that the sender should disconnect from the // underlying transport (this occurs if the sender isn't seen in a local @@ -59,11 +49,6 @@ class RtpSenderInternal : public RtpSenderInterface { virtual void set_stream_ids(const std::vector& stream_ids) = 0; virtual void Stop() = 0; - - // Returns an ID that changes every time SetTrack() is called, but - // otherwise remains constant. Used to generate IDs for stats. - // The special value zero means that no track is attached. - virtual int AttachmentId() const = 0; }; // LocalAudioSinkAdapter receives data callback as a sink to the local @@ -154,13 +139,10 @@ class AudioRtpSender : public DtmfProviderInterface, int AttachmentId() const override { return attachment_id_; } - void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) override { - media_channel_ = voice_media_channel; - } - void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_media_channel) override { - RTC_NOTREACHED(); + // Does not take ownership. + // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. + void SetMediaChannel(cricket::VoiceMediaChannel* media_channel) { + media_channel_ = media_channel; } private: @@ -247,13 +229,10 @@ class VideoRtpSender : public ObserverInterface, void Stop() override; int AttachmentId() const override { return attachment_id_; } - void SetVoiceMediaChannel( - cricket::VoiceMediaChannel* voice_media_channel) override { - RTC_NOTREACHED(); - } - void SetVideoMediaChannel( - cricket::VideoMediaChannel* video_media_channel) override { - media_channel_ = video_media_channel; + // Does not take ownership. + // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. + void SetMediaChannel(cricket::VideoMediaChannel* media_channel) { + media_channel_ = media_channel; } private: diff --git a/pc/rtpsenderreceiver_unittest.cc b/pc/rtpsenderreceiver_unittest.cc index 4223264599..40ed3686f9 100644 --- a/pc/rtpsenderreceiver_unittest.cc +++ b/pc/rtpsenderreceiver_unittest.cc @@ -139,7 +139,7 @@ class RtpSenderReceiverTest : public testing::Test, audio_rtp_sender_ = new AudioRtpSender(worker_thread_, local_stream_->GetAudioTracks()[0], {local_stream_->label()}, nullptr); - audio_rtp_sender_->SetVoiceMediaChannel(voice_media_channel_); + audio_rtp_sender_->SetMediaChannel(voice_media_channel_); audio_rtp_sender_->SetSsrc(kAudioSsrc); audio_rtp_sender_->GetOnDestroyedSignal()->connect( this, &RtpSenderReceiverTest::OnAudioSenderDestroyed); @@ -148,7 +148,7 @@ class RtpSenderReceiverTest : public testing::Test, void CreateAudioRtpSenderWithNoTrack() { audio_rtp_sender_ = new AudioRtpSender(worker_thread_, nullptr); - audio_rtp_sender_->SetVoiceMediaChannel(voice_media_channel_); + audio_rtp_sender_->SetMediaChannel(voice_media_channel_); } void OnAudioSenderDestroyed() { audio_sender_destroyed_signal_fired_ = true; } @@ -160,14 +160,14 @@ class RtpSenderReceiverTest : public testing::Test, video_rtp_sender_ = new VideoRtpSender(worker_thread_, local_stream_->GetVideoTracks()[0], {local_stream_->label()}); - video_rtp_sender_->SetVideoMediaChannel(video_media_channel_); + video_rtp_sender_->SetMediaChannel(video_media_channel_); video_rtp_sender_->SetSsrc(kVideoSsrc); VerifyVideoChannelInput(); } void CreateVideoRtpSenderWithNoTrack() { video_rtp_sender_ = new VideoRtpSender(worker_thread_); - video_rtp_sender_->SetVideoMediaChannel(video_media_channel_); + video_rtp_sender_->SetMediaChannel(video_media_channel_); } void DestroyAudioRtpSender() { @@ -184,7 +184,7 @@ class RtpSenderReceiverTest : public testing::Test, std::vector> streams = {}) { audio_rtp_receiver_ = new AudioRtpReceiver( rtc::Thread::Current(), kAudioTrackId, std::move(streams)); - audio_rtp_receiver_->SetVoiceMediaChannel(voice_media_channel_); + audio_rtp_receiver_->SetMediaChannel(voice_media_channel_); audio_rtp_receiver_->SetupMediaChannel(kAudioSsrc); audio_track_ = audio_rtp_receiver_->audio_track(); VerifyVoiceChannelOutput(); @@ -194,7 +194,7 @@ class RtpSenderReceiverTest : public testing::Test, std::vector> streams = {}) { video_rtp_receiver_ = new VideoRtpReceiver( rtc::Thread::Current(), kVideoTrackId, std::move(streams)); - video_rtp_receiver_->SetVideoMediaChannel(video_media_channel_); + video_rtp_receiver_->SetMediaChannel(video_media_channel_); video_rtp_receiver_->SetupMediaChannel(kVideoSsrc); video_track_ = video_rtp_receiver_->video_track(); VerifyVideoChannelOutput(); @@ -783,7 +783,7 @@ TEST_F(RtpSenderReceiverTest, video_rtp_sender_ = new VideoRtpSender(worker_thread_, local_stream_->GetVideoTracks()[0], {local_stream_->label()}); - video_rtp_sender_->SetVideoMediaChannel(video_media_channel_); + video_rtp_sender_->SetMediaChannel(video_media_channel_); video_track_->set_enabled(true); // Sender is not ready to send (no SSRC) so no option should have been set. diff --git a/pc/rtptransceiver.cc b/pc/rtptransceiver.cc index 1f1a850c9f..310c4c49ad 100644 --- a/pc/rtptransceiver.cc +++ b/pc/rtptransceiver.cc @@ -61,12 +61,14 @@ void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) { for (auto sender : senders_) { if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); - sender->internal()->SetVoiceMediaChannel( - voice_channel ? voice_channel->media_channel() : nullptr); + static_cast(sender->internal()) + ->SetMediaChannel(voice_channel ? voice_channel->media_channel() + : nullptr); } else { auto* video_channel = static_cast(channel); - sender->internal()->SetVideoMediaChannel( - video_channel ? video_channel->media_channel() : nullptr); + static_cast(sender->internal()) + ->SetMediaChannel(video_channel ? video_channel->media_channel() + : nullptr); } } @@ -76,12 +78,14 @@ void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) { } if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); - receiver->internal()->SetVoiceMediaChannel( - voice_channel ? voice_channel->media_channel() : nullptr); + static_cast(receiver->internal()) + ->SetMediaChannel(voice_channel ? voice_channel->media_channel() + : nullptr); } else { auto* video_channel = static_cast(channel); - receiver->internal()->SetVideoMediaChannel( - video_channel ? video_channel->media_channel() : nullptr); + static_cast(receiver->internal()) + ->SetMediaChannel(video_channel ? video_channel->media_channel() + : nullptr); } } } diff --git a/pc/test/fakepeerconnectionforstats.h b/pc/test/fakepeerconnectionforstats.h index be8003e891..d73e734367 100644 --- a/pc/test/fakepeerconnectionforstats.h +++ b/pc/test/fakepeerconnectionforstats.h @@ -97,23 +97,12 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { return remote_streams_; } - void AddSender(rtc::scoped_refptr sender) { - // TODO(steveanton): Switch tests to use RtpTransceivers directly. - auto sender_proxy = RtpSenderProxyWithInternal::Create( - signaling_thread_, sender); - GetOrCreateFirstTransceiverOfType(sender->media_type()) - ->internal() - ->AddSender(sender_proxy); + void AddSender(rtc::scoped_refptr sender) { + senders_.push_back(sender); } - void AddReceiver(rtc::scoped_refptr receiver) { - // TODO(steveanton): Switch tests to use RtpTransceivers directly. - auto receiver_proxy = - RtpReceiverProxyWithInternal::Create( - signaling_thread_, receiver); - GetOrCreateFirstTransceiverOfType(receiver->media_type()) - ->internal() - ->AddReceiver(receiver_proxy); + void AddReceiver(rtc::scoped_refptr receiver) { + receivers_.push_back(receiver); } FakeVoiceMediaChannelForStats* AddVoiceChannel( @@ -127,9 +116,10 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::move(voice_media_channel), mid, kDefaultRtcpMuxRequired, kDefaultSrtpRequired); voice_channel_->set_transport_name_for_testing(transport_name); - GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO) - ->internal() - ->SetChannel(voice_channel_.get()); + auto transceiver = RtpTransceiverProxyWithInternal::Create( + signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)); + transceiver->internal()->SetChannel(voice_channel_.get()); + transceivers_.push_back(transceiver); return voice_media_channel_ptr; } @@ -144,9 +134,10 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::move(video_media_channel), mid, kDefaultRtcpMuxRequired, kDefaultSrtpRequired); video_channel_->set_transport_name_for_testing(transport_name); - GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO) - ->internal() - ->SetChannel(video_channel_.get()); + auto transceiver = RtpTransceiverProxyWithInternal::Create( + signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)); + transceiver->internal()->SetChannel(video_channel_.get()); + transceivers_.push_back(transceiver); return video_media_channel_ptr; } @@ -213,24 +204,12 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::vector> GetSenders() const override { - std::vector> senders; - for (auto transceiver : transceivers_) { - for (auto sender : transceiver->internal()->senders()) { - senders.push_back(sender); - } - } - return senders; + return senders_; } std::vector> GetReceivers() const override { - std::vector> receivers; - for (auto transceiver : transceivers_) { - for (auto receiver : transceiver->internal()->receivers()) { - receivers.push_back(receiver); - } - } - return receivers; + return receivers_; } // PeerConnectionInternal overrides. @@ -344,19 +323,6 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { return transport_stats; } - rtc::scoped_refptr> - GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type) { - for (auto transceiver : transceivers_) { - if (transceiver->internal()->media_type() == media_type) { - return transceiver; - } - } - auto transceiver = RtpTransceiverProxyWithInternal::Create( - signaling_thread_, new RtpTransceiver(media_type)); - transceivers_.push_back(transceiver); - return transceiver; - } - rtc::Thread* const network_thread_; rtc::Thread* const worker_thread_; rtc::Thread* const signaling_thread_; @@ -367,6 +333,8 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::vector< rtc::scoped_refptr>> transceivers_; + std::vector> senders_; + std::vector> receivers_; FakeDataChannelProvider data_channel_provider_; diff --git a/pc/test/mock_rtpreceiverinternal.h b/pc/test/mock_rtpreceiverinternal.h deleted file mode 100644 index 8fb93b4f37..0000000000 --- a/pc/test/mock_rtpreceiverinternal.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef PC_TEST_MOCK_RTPRECEIVERINTERNAL_H_ -#define PC_TEST_MOCK_RTPRECEIVERINTERNAL_H_ - -#include -#include - -#include "pc/rtpreceiver.h" -#include "test/gmock.h" - -namespace webrtc { - -// The definition of MockRtpReceiver is copied in to avoid multiple inheritance. -class MockRtpReceiverInternal : public RtpReceiverInternal { - public: - // RtpReceiverInterface methods. - MOCK_METHOD1(SetTrack, void(MediaStreamTrackInterface*)); - MOCK_CONST_METHOD0(track, rtc::scoped_refptr()); - MOCK_CONST_METHOD0(streams, - std::vector>()); - MOCK_CONST_METHOD0(media_type, cricket::MediaType()); - MOCK_CONST_METHOD0(id, std::string()); - MOCK_CONST_METHOD0(GetParameters, RtpParameters()); - MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); - MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*)); - MOCK_CONST_METHOD0(GetSources, std::vector()); - - // RtpReceiverInternal methods. - MOCK_METHOD0(Stop, void()); - MOCK_METHOD1(SetVoiceMediaChannel, void(cricket::VoiceMediaChannel*)); - MOCK_METHOD1(SetVideoMediaChannel, void(cricket::VideoMediaChannel*)); - MOCK_METHOD1(SetupMediaChannel, void(uint32_t)); - MOCK_CONST_METHOD0(ssrc, uint32_t()); - MOCK_METHOD0(NotifyFirstPacketReceived, void()); - MOCK_METHOD1( - SetStreams, - void(const std::vector>&)); - MOCK_CONST_METHOD0(AttachmentId, int()); -}; - -} // namespace webrtc - -#endif // PC_TEST_MOCK_RTPRECEIVERINTERNAL_H_ diff --git a/pc/test/mock_rtpsenderinternal.h b/pc/test/mock_rtpsenderinternal.h deleted file mode 100644 index b76a9ac0ba..0000000000 --- a/pc/test/mock_rtpsenderinternal.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef PC_TEST_MOCK_RTPSENDERINTERNAL_H_ -#define PC_TEST_MOCK_RTPSENDERINTERNAL_H_ - -#include -#include - -#include "pc/rtpsender.h" -#include "test/gmock.h" - -namespace webrtc { - -// The definition of MockRtpSender is copied in to avoid multiple inheritance. -class MockRtpSenderInternal : public RtpSenderInternal { - public: - // RtpSenderInterface methods. - MOCK_METHOD1(SetTrack, bool(MediaStreamTrackInterface*)); - MOCK_CONST_METHOD0(track, rtc::scoped_refptr()); - MOCK_CONST_METHOD0(ssrc, uint32_t()); - MOCK_CONST_METHOD0(media_type, cricket::MediaType()); - MOCK_CONST_METHOD0(id, std::string()); - MOCK_CONST_METHOD0(stream_ids, std::vector()); - MOCK_CONST_METHOD0(GetParameters, RtpParameters()); - MOCK_METHOD1(SetParameters, RTCError(const RtpParameters&)); - MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr()); - - // RtpSenderInternal methods. - MOCK_METHOD1(SetVoiceMediaChannel, void(cricket::VoiceMediaChannel*)); - MOCK_METHOD1(SetVideoMediaChannel, void(cricket::VideoMediaChannel*)); - MOCK_METHOD1(SetSsrc, void(uint32_t)); - MOCK_METHOD1(set_stream_id, void(const std::string&)); - MOCK_CONST_METHOD0(stream_id, std::string()); - MOCK_METHOD1(set_stream_ids, void(const std::vector&)); - MOCK_METHOD0(Stop, void()); - MOCK_CONST_METHOD0(AttachmentId, int()); -}; - -} // namespace webrtc - -#endif // PC_TEST_MOCK_RTPSENDERINTERNAL_H_ diff --git a/pc/trackmediainfomap.cc b/pc/trackmediainfomap.cc index 5450cee7f0..654db15c04 100644 --- a/pc/trackmediainfomap.cc +++ b/pc/trackmediainfomap.cc @@ -30,8 +30,8 @@ const V* FindAddressOrNull(const std::map& map, const K& key) { } void GetAudioAndVideoTrackBySsrc( - const std::vector>& rtp_senders, - const std::vector>& rtp_receivers, + const std::vector>& rtp_senders, + const std::vector>& rtp_receivers, std::map* local_audio_track_by_ssrc, std::map* local_video_track_by_ssrc, std::map* remote_audio_track_by_ssrc, @@ -47,7 +47,7 @@ void GetAudioAndVideoTrackBySsrc( // means one thread jump if on signaling thread and two thread jumps if on any // other threads). Is there a way to avoid thread jump(s) on a per // sender/receiver, per method basis? - for (auto rtp_sender : rtp_senders) { + for (const rtc::scoped_refptr& rtp_sender : rtp_senders) { cricket::MediaType media_type = rtp_sender->media_type(); MediaStreamTrackInterface* track = rtp_sender->track(); if (!track) { @@ -72,7 +72,8 @@ void GetAudioAndVideoTrackBySsrc( } } } - for (auto rtp_receiver : rtp_receivers) { + for (const rtc::scoped_refptr& rtp_receiver : + rtp_receivers) { cricket::MediaType media_type = rtp_receiver->media_type(); MediaStreamTrackInterface* track = rtp_receiver->track(); RTC_DCHECK(track); @@ -110,8 +111,8 @@ void GetAudioAndVideoTrackBySsrc( TrackMediaInfoMap::TrackMediaInfoMap( std::unique_ptr voice_media_info, std::unique_ptr video_media_info, - const std::vector>& rtp_senders, - const std::vector>& rtp_receivers) + const std::vector>& rtp_senders, + const std::vector>& rtp_receivers) : voice_media_info_(std::move(voice_media_info)), video_media_info_(std::move(video_media_info)) { std::map local_audio_track_by_ssrc; @@ -126,10 +127,10 @@ TrackMediaInfoMap::TrackMediaInfoMap( &remote_video_track_by_ssrc, &unsignaled_audio_track, &unsignaled_video_track); - for (auto sender : rtp_senders) { + for (auto& sender : rtp_senders) { attachment_id_by_track_[sender->track()] = sender->AttachmentId(); } - for (auto receiver : rtp_receivers) { + for (auto& receiver : rtp_receivers) { attachment_id_by_track_[receiver->track()] = receiver->AttachmentId(); } diff --git a/pc/trackmediainfomap.h b/pc/trackmediainfomap.h index d6036264ea..a0f882d941 100644 --- a/pc/trackmediainfomap.h +++ b/pc/trackmediainfomap.h @@ -17,9 +17,9 @@ #include #include "api/mediastreaminterface.h" +#include "api/rtpreceiverinterface.h" +#include "api/rtpsenderinterface.h" #include "media/base/mediachannel.h" -#include "pc/rtpreceiver.h" -#include "pc/rtpsender.h" #include "rtc_base/refcount.h" namespace webrtc { @@ -39,8 +39,8 @@ class TrackMediaInfoMap { TrackMediaInfoMap( std::unique_ptr voice_media_info, std::unique_ptr video_media_info, - const std::vector>& rtp_senders, - const std::vector>& + const std::vector>& rtp_senders, + const std::vector>& rtp_receivers); const cricket::VoiceMediaInfo* voice_media_info() const { diff --git a/pc/trackmediainfomap_unittest.cc b/pc/trackmediainfomap_unittest.cc index c1355647be..93d6155af0 100644 --- a/pc/trackmediainfomap_unittest.cc +++ b/pc/trackmediainfomap_unittest.cc @@ -18,11 +18,11 @@ #include "api/rtpreceiverinterface.h" #include "api/rtpsenderinterface.h" +#include "api/test/mock_rtpreceiver.h" +#include "api/test/mock_rtpsender.h" #include "media/base/mediachannel.h" #include "pc/audiotrack.h" #include "pc/test/fakevideotracksource.h" -#include "pc/test/mock_rtpreceiverinternal.h" -#include "pc/test/mock_rtpsenderinternal.h" #include "pc/videotrack.h" #include "rtc_base/refcount.h" #include "test/gtest.h" @@ -42,7 +42,7 @@ RtpParameters CreateRtpParametersWithSsrcs( return params; } -rtc::scoped_refptr CreateMockRtpSender( +rtc::scoped_refptr CreateMockRtpSender( cricket::MediaType media_type, std::initializer_list ssrcs, rtc::scoped_refptr track) { @@ -52,8 +52,8 @@ rtc::scoped_refptr CreateMockRtpSender( } else { first_ssrc = 0; } - rtc::scoped_refptr sender( - new rtc::RefCountedObject()); + rtc::scoped_refptr sender( + new rtc::RefCountedObject()); EXPECT_CALL(*sender, track()) .WillRepeatedly(testing::Return(std::move(track))); EXPECT_CALL(*sender, ssrc()).WillRepeatedly(testing::Return(first_ssrc)); @@ -65,12 +65,12 @@ rtc::scoped_refptr CreateMockRtpSender( return sender; } -rtc::scoped_refptr CreateMockRtpReceiver( +rtc::scoped_refptr CreateMockRtpReceiver( cricket::MediaType media_type, std::initializer_list ssrcs, rtc::scoped_refptr track) { - rtc::scoped_refptr receiver( - new rtc::RefCountedObject()); + rtc::scoped_refptr receiver( + new rtc::RefCountedObject()); EXPECT_CALL(*receiver, track()) .WillRepeatedly(testing::Return(std::move(track))); EXPECT_CALL(*receiver, media_type()) @@ -108,7 +108,7 @@ class TrackMediaInfoMapTest : public testing::Test { void AddRtpSenderWithSsrcs(std::initializer_list ssrcs, MediaStreamTrackInterface* local_track) { - rtc::scoped_refptr rtp_sender = CreateMockRtpSender( + rtc::scoped_refptr rtp_sender = CreateMockRtpSender( local_track->kind() == MediaStreamTrackInterface::kAudioKind ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO, @@ -136,7 +136,7 @@ class TrackMediaInfoMapTest : public testing::Test { void AddRtpReceiverWithSsrcs(std::initializer_list ssrcs, MediaStreamTrackInterface* remote_track) { - auto rtp_receiver = CreateMockRtpReceiver( + rtc::scoped_refptr rtp_receiver = CreateMockRtpReceiver( remote_track->kind() == MediaStreamTrackInterface::kAudioKind ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO, @@ -173,8 +173,8 @@ class TrackMediaInfoMapTest : public testing::Test { protected: cricket::VoiceMediaInfo* voice_media_info_; cricket::VideoMediaInfo* video_media_info_; - std::vector> rtp_senders_; - std::vector> rtp_receivers_; + std::vector> rtp_senders_; + std::vector> rtp_receivers_; std::unique_ptr map_; rtc::scoped_refptr local_audio_track_; rtc::scoped_refptr remote_audio_track_;