From 57858b3be09492ee81caff14da3fbf9e0bb796b9 Mon Sep 17 00:00:00 2001 From: Steve Anton Date: Thu, 15 Feb 2018 15:19:50 -0800 Subject: [PATCH] Reland "Update RTCStatsCollector to work with RtpTransceivers" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original change's description: > Update RTCStatsCollector to work with RtpTransceivers > > Bug: webrtc:8764 > Change-Id: I8b442345869eb6d8b65fd12241ed7cb6e7d7ce3d > Reviewed-on: https://webrtc-review.googlesource.com/49580 > Commit-Queue: Steve Anton > Reviewed-by: Taylor Brandstetter > Reviewed-by: Henrik Boström > Cr-Commit-Position: refs/heads/master@{#22026} Bug: webrtc:8764 Change-Id: I6a682824febf3f4f41397fc1a8dd7396c4ffa8e3 Reviewed-on: https://webrtc-review.googlesource.com/54160 Reviewed-by: Taylor Brandstetter Commit-Queue: Steve Anton Cr-Commit-Position: refs/heads/master@{#22064} --- api/rtpreceiverinterface.cc | 4 - api/rtpreceiverinterface.h | 9 - api/rtpsenderinterface.h | 8 - api/test/mock_rtpreceiver.h | 1 - api/test/mock_rtpsender.h | 1 - ortc/ortcrtpreceiveradapter.cc | 4 +- ortc/ortcrtpsenderadapter.cc | 4 +- pc/BUILD.gn | 2 + pc/peerconnection.cc | 20 +- pc/peerconnectioninterface_unittest.cc | 25 +- pc/rtcstatscollector.cc | 624 ++++++++++++++----------- pc/rtcstatscollector.h | 47 +- pc/rtcstatscollector_unittest.cc | 103 ++-- pc/rtpreceiver.cc | 10 - pc/rtpreceiver.h | 39 +- pc/rtpsender.h | 37 +- pc/rtpsenderreceiver_unittest.cc | 14 +- pc/rtptransceiver.cc | 20 +- pc/test/fakepeerconnectionforstats.h | 64 ++- pc/test/mock_rtpreceiverinternal.h | 52 +++ pc/test/mock_rtpsenderinternal.h | 49 ++ pc/trackmediainfomap.cc | 17 +- pc/trackmediainfomap.h | 8 +- pc/trackmediainfomap_unittest.cc | 24 +- 24 files changed, 708 insertions(+), 478 deletions(-) create mode 100644 pc/test/mock_rtpreceiverinternal.h create mode 100644 pc/test/mock_rtpsenderinternal.h diff --git a/api/rtpreceiverinterface.cc b/api/rtpreceiverinterface.cc index b62f744f3e..96815a9f36 100644 --- a/api/rtpreceiverinterface.cc +++ b/api/rtpreceiverinterface.cc @@ -41,8 +41,4 @@ 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 017c95a2aa..0e32eae8cb 100644 --- a/api/rtpreceiverinterface.h +++ b/api/rtpreceiverinterface.h @@ -120,14 +120,6 @@ 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; }; @@ -146,7 +138,6 @@ 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 83e135f350..2ca2edc830 100644 --- a/api/rtpsenderinterface.h +++ b/api/rtpsenderinterface.h @@ -60,13 +60,6 @@ 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() {} }; @@ -85,7 +78,6 @@ 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 7a612004ba..de69ceaccd 100644 --- a/api/test/mock_rtpreceiver.h +++ b/api/test/mock_rtpreceiver.h @@ -31,7 +31,6 @@ 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 728ceca1a8..dda5f45675 100644 --- a/api/test/mock_rtpsender.h +++ b/api/test/mock_rtpsender.h @@ -30,7 +30,6 @@ 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 16cb2485d0..8e05a8518b 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->SetMediaChannel(voice_channel->media_channel()); + audio_receiver->SetVoiceMediaChannel(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->SetMediaChannel(video_channel->media_channel()); + video_receiver->SetVideoMediaChannel(video_channel->media_channel()); internal_receiver_ = video_receiver; break; } diff --git a/ortc/ortcrtpsenderadapter.cc b/ortc/ortcrtpsenderadapter.cc index 2b25d46eeb..283ec3556e 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->SetMediaChannel(voice_channel->media_channel()); + audio_sender->SetVoiceMediaChannel(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->SetMediaChannel(video_channel->media_channel()); + video_sender->SetVideoMediaChannel(video_channel->media_channel()); internal_sender_ = video_sender; break; } diff --git a/pc/BUILD.gn b/pc/BUILD.gn index cf506bf0c4..21be8575be 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -339,6 +339,8 @@ 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 4f5bd8e75f..39822678fc 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -1114,8 +1114,7 @@ PeerConnection::AddTrackPlanB( : cricket::MEDIA_TYPE_VIDEO); auto new_sender = CreateSender(media_type, track, stream_labels); if (track->kind() == MediaStreamTrackInterface::kAudioKind) { - static_cast(new_sender->internal()) - ->SetMediaChannel(voice_media_channel()); + new_sender->internal()->SetVoiceMediaChannel(voice_media_channel()); GetAudioTransceiver()->internal()->AddSender(new_sender); const RtpSenderInfo* sender_info = FindSenderInfo(local_audio_sender_infos_, @@ -1125,8 +1124,7 @@ PeerConnection::AddTrackPlanB( } } else { RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind()); - static_cast(new_sender->internal()) - ->SetMediaChannel(video_media_channel()); + new_sender->internal()->SetVideoMediaChannel(video_media_channel()); GetVideoTransceiver()->internal()->AddSender(new_sender); const RtpSenderInfo* sender_info = FindSenderInfo(local_video_sender_infos_, @@ -1417,14 +1415,14 @@ rtc::scoped_refptr PeerConnection::CreateSender( if (kind == MediaStreamTrackInterface::kAudioKind) { auto* audio_sender = new AudioRtpSender(worker_thread(), nullptr, stream_labels, stats_.get()); - audio_sender->SetMediaChannel(voice_media_channel()); + audio_sender->SetVoiceMediaChannel(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->SetMediaChannel(video_media_channel()); + video_sender->SetVideoMediaChannel(video_media_channel()); new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), video_sender); GetVideoTransceiver()->internal()->AddSender(new_sender); @@ -3022,7 +3020,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->SetMediaChannel(voice_media_channel()); + audio_receiver->SetVoiceMediaChannel(voice_media_channel()); audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), audio_receiver); @@ -3037,7 +3035,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->SetMediaChannel(video_media_channel()); + video_receiver->SetVideoMediaChannel(video_media_channel()); video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc); auto receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), video_receiver); @@ -3077,8 +3075,7 @@ 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()}); - static_cast(new_sender->internal()) - ->SetMediaChannel(voice_media_channel()); + new_sender->internal()->SetVoiceMediaChannel(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 @@ -3121,8 +3118,7 @@ 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()}); - static_cast(new_sender->internal()) - ->SetMediaChannel(video_media_channel()); + new_sender->internal()->SetVideoMediaChannel(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 e496e4ede6..8413b79dd0 100644 --- a/pc/peerconnectioninterface_unittest.cc +++ b/pc/peerconnectioninterface_unittest.cc @@ -32,6 +32,7 @@ #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" @@ -350,6 +351,8 @@ 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; @@ -1492,19 +1495,29 @@ 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()); - EXPECT_TRUE(audio_sender.ok()); - EXPECT_TRUE(video_sender.ok()); - EXPECT_NE(0, video_sender.value()->AttachmentId()); - EXPECT_NE(0, audio_sender.value()->AttachmentId()); + ASSERT_TRUE(video_sender.ok()); + auto* video_sender_proxy = + static_cast*>( + video_sender.value().get()); + EXPECT_NE(0, video_sender_proxy->internal()->AttachmentId()); } TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddStream) { CreatePeerConnectionWithoutDtls(); AddVideoStream(kStreamLabel1); auto senders = pc_->GetSenders(); - EXPECT_EQ(1u, senders.size()); - EXPECT_NE(0, senders[0]->AttachmentId()); + ASSERT_EQ(1u, senders.size()); + auto* sender_proxy = + static_cast*>( + senders[0].get()); + EXPECT_NE(0, sender_proxy->internal()->AttachmentId()); } TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) { diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc index 77dde9591a..dd8f69e785 100644 --- a/pc/rtcstatscollector.cc +++ b/pc/rtcstatscollector.cc @@ -24,6 +24,7 @@ #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" @@ -36,19 +37,11 @@ std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) { return "RTCCertificate_" + fingerprint; } -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 RTCCodecStatsIDFromMidDirectionAndPayload(const std::string& mid, + bool inbound, + uint32_t payload_type) { + return "RTCCodec_" + mid + "_" + (inbound ? "Inbound" : "Outbound") + "_" + + rtc::ToString<>(payload_type); } std::string RTCIceCandidatePairStatsIDFromConnectionInfo( @@ -175,14 +168,16 @@ double DoubleAudioLevelFromIntAudioLevel(int audio_level) { } std::unique_ptr CodecStatsFromRtpCodecParameters( - uint64_t timestamp_us, bool inbound, bool audio, + uint64_t timestamp_us, + const std::string& mid, + bool inbound, 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( - RTCCodecStatsIDFromDirectionMediaAndPayload(inbound, audio, payload_type), + RTCCodecStatsIDFromMidDirectionAndPayload(mid, inbound, payload_type), timestamp_us)); codec_stats->payload_type = payload_type; codec_stats->mime_type = codec_params.mime_type(); @@ -218,15 +213,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 = - RTCCodecStatsIDFromDirectionMediaAndPayload( - true, true, *voice_receiver_info.codec_payload_type); + inbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( + mid, true, *voice_receiver_info.codec_payload_type); } inbound_audio->jitter = static_cast(voice_receiver_info.jitter_ms) / @@ -236,15 +231,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 = - RTCCodecStatsIDFromDirectionMediaAndPayload( - true, false, *video_receiver_info.codec_payload_type); + inbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( + mid, true, *video_receiver_info.codec_payload_type); } inbound_video->fir_count = static_cast(video_receiver_info.firs_sent); @@ -272,30 +267,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 = - RTCCodecStatsIDFromDirectionMediaAndPayload( - false, true, *voice_sender_info.codec_payload_type); + outbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( + mid, false, *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 = - RTCCodecStatsIDFromDirectionMediaAndPayload( - false, false, *video_sender_info.codec_payload_type); + outbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload( + mid, false, *video_sender_info.codec_payload_type); } outbound_video->fir_count = static_cast(video_sender_info.firs_rcvd); @@ -502,14 +497,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 const sender : senders) { + for (auto sender : senders) { if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) { AudioTrackInterface* track = static_cast(sender->track().get()); @@ -520,11 +515,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()) { + if (sender->ssrc() != 0) { // When pc.close is called, sender info is discarded, so // we generate zeroes instead. Bug: It should be retained. // https://crbug.com/807174 - auto sender_info = + const cricket::VoiceSenderInfo* sender_info = track_media_info_map.GetVoiceSenderInfoBySsrc(sender->ssrc()); if (sender_info) { voice_sender_info = sender_info; @@ -548,11 +543,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()) { + if (sender->ssrc() != 0) { // When pc.close is called, sender info is discarded, so // we generate zeroes instead. Bug: It should be retained. // https://crbug.com/807174 - auto sender_info = + const cricket::VideoSenderInfo* sender_info = track_media_info_map.GetVideoSenderInfoBySsrc(sender->ssrc()); if (sender_info) { video_sender_info = sender_info; @@ -574,10 +569,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 const receiver : receivers) { + for (auto receiver : receivers) { if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { AudioTrackInterface* track = static_cast(receiver->track().get()); @@ -610,38 +605,6 @@ 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( @@ -699,27 +662,10 @@ void RTCStatsCollector::GetStatsReport( num_pending_partial_reports_ = 2; partial_report_timestamp_us_ = cache_now_us; - // Prepare |transport_name_by_mid_| for use in - // |ProducePartialResultsOnNetworkThread|. - transport_names_by_mid_ = pc_->GetTransportNamesByMid(); - // Prepare |track_media_info_map_| for use in + // Prepare |transceiver_stats_infos_| for use in // |ProducePartialResultsOnNetworkThread| and // |ProducePartialResultsOnSignalingThread|. - 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(); - } + transceiver_stats_infos_ = PrepareTransceiverStatsInfos_s(); // Prepare |call_stats_| here since GetCallStats() will hop to the worker // thread. @@ -758,7 +704,8 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread( timestamp_us); ProduceDataChannelStats_s(timestamp_us, report.get()); - ProduceMediaStreamAndTrackStats_s(timestamp_us, report.get()); + ProduceMediaStreamStats_s(timestamp_us, report.get()); + ProduceMediaStreamTrackStats_s(timestamp_us, report.get()); ProducePeerConnectionStats_s(timestamp_us, report.get()); AddPartialResults(report); @@ -771,8 +718,10 @@ void RTCStatsCollector::ProducePartialResultsOnNetworkThread( timestamp_us); std::set transport_names; - for (const auto& entry : transport_names_by_mid_) { - transport_names.insert(entry.second); + for (const auto& stats : transceiver_stats_infos_) { + if (stats.transport_name) { + transport_names.insert(*stats.transport_name); + } } std::map transport_stats_by_name = pc_->GetTransportStatsByNames(transport_names); @@ -781,12 +730,10 @@ void RTCStatsCollector::ProducePartialResultsOnNetworkThread( PrepareTransportCertificateStats_n(transport_stats_by_name); ProduceCertificateStats_n(timestamp_us, transport_cert_stats, report.get()); - ProduceCodecStats_n(timestamp_us, *track_media_info_map_, report.get()); + ProduceCodecStats_n(timestamp_us, transceiver_stats_infos_, 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, transport_names_by_mid_, - *track_media_info_map_, report.get()); + ProduceRTPStreamStats_n(timestamp_us, transceiver_stats_infos_, report.get()); ProduceTransportStats_n(timestamp_us, transport_stats_by_name, transport_cert_stats, report.get()); @@ -818,9 +765,7 @@ void RTCStatsCollector::AddPartialResults_s( cache_timestamp_us_ = partial_report_timestamp_us_; cached_report_ = partial_report_; partial_report_ = nullptr; - transport_names_by_mid_.clear(); - track_media_info_map_.reset(); - track_to_id_.clear(); + transceiver_stats_infos_.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. @@ -859,37 +804,43 @@ void RTCStatsCollector::ProduceCertificateStats_n( } void RTCStatsCollector::ProduceCodecStats_n( - int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, + int64_t timestamp_us, + const std::vector& transceiver_stats_infos, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); - // 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)); + for (const auto& stats : transceiver_stats_infos) { + if (!stats.mid) { + continue; } - // Outbound - for (const auto& pair : - track_media_info_map.voice_media_info()->send_codecs) { - report->AddStats(CodecStatsFromRtpCodecParameters( - timestamp_us, false, true, pair.second)); + 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)); + } } - } - // 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)); + // 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)); + } } } } @@ -920,7 +871,6 @@ 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()); @@ -1000,16 +950,61 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n( } } -void RTCStatsCollector::ProduceMediaStreamAndTrackStats_s( - int64_t timestamp_us, RTCStatsReport* report) const { +void RTCStatsCollector::ProduceMediaStreamStats_s( + int64_t timestamp_us, + RTCStatsReport* report) const { RTC_DCHECK(signaling_thread_->IsCurrent()); - 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); + + 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); + } } void RTCStatsCollector::ProducePeerConnectionStats_s( @@ -1024,122 +1019,133 @@ void RTCStatsCollector::ProducePeerConnectionStats_s( void RTCStatsCollector::ProduceRTPStreamStats_n( int64_t timestamp_us, - const std::map& transport_names_by_mid, - const TrackMediaInfoMap& track_media_info_map, + const std::vector& transceiver_stats_infos, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); - // 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; - - 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)); + 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(); } } - // 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)); +} + +void RTCStatsCollector::ProduceAudioRTPStreamStats_n( + int64_t timestamp_us, + const RtpTransceiverStatsInfo& stats, + RTCStatsReport* report) const { + if (!stats.mid || !stats.transport_name) { + return; + } + 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 mid = *stats.mid; + 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(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()); } - // 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_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(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()); } + 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 { + if (!stats.mid || !stats.transport_name) { + return; + } + 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 mid = *stats.mid; + 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(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()); + } + 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(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)); } } @@ -1243,47 +1249,105 @@ RTCStatsCollector::PrepareTransportCertificateStats_n( return transport_cert_stats; } -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(); - } - } - 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(); - } - } - 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; -} +std::vector +RTCStatsCollector::PrepareTransceiverStatsInfos_s() const { + std::vector 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(); + // 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->media_type(); + + // 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; + + cricket::BaseChannel* channel = transceiver->internal()->channel(); + if (!channel) { + // The remaining fields require a BaseChannel. + continue; + } + + 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(); + } } - for (auto receiver : pc_->GetReceivers()) { - auto track = receiver->track(); - if (track) - track_to_id[track.get()] = track->id(); + + // 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."; + } + } + 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; + std::unique_ptr voice_media_info; + std::unique_ptr video_media_info; + if (transceiver->channel()) { + 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); } - return track_to_id; + + return transceiver_stats_infos; } void RTCStatsCollector::OnDataChannelCreated(DataChannel* channel) { diff --git a/pc/rtcstatscollector.h b/pc/rtcstatscollector.h index 24a7bb2f0e..2ff4c49065 100644 --- a/pc/rtcstatscollector.h +++ b/pc/rtcstatscollector.h @@ -78,6 +78,21 @@ 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. + // If a BaseChannel is not available (e.g., if signaling has not started), + // then |mid| and |transport_name| will be null. + struct RtpTransceiverStatsInfo { + rtc::scoped_refptr transceiver; + cricket::MediaType media_type; + rtc::Optional mid; + rtc::Optional transport_name; + std::unique_ptr track_media_info_map; + }; + void AddPartialResults_s(rtc::scoped_refptr partial_report); void DeliverCachedReport(); @@ -88,7 +103,8 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, RTCStatsReport* report) const; // Produces |RTCCodecStats|. void ProduceCodecStats_n( - int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, + int64_t timestamp_us, + const std::vector& transceiver_stats_infos, RTCStatsReport* report) const; // Produces |RTCDataChannelStats|. void ProduceDataChannelStats_s( @@ -98,21 +114,28 @@ 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| and |RTCMediaStreamTrackStats|. - void ProduceMediaStreamAndTrackStats_s( - int64_t timestamp_us, 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 |RTCPeerConnectionStats|. void ProducePeerConnectionStats_s( int64_t timestamp_us, RTCStatsReport* report) const; // Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|. void ProduceRTPStreamStats_n( int64_t timestamp_us, - const std::map& transport_names_by_mid, - const TrackMediaInfoMap& track_media_info_map, + const std::vector& transceiver_stats_infos, 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, @@ -126,8 +149,7 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, PrepareTransportCertificateStats_n( const std::map& transport_stats_by_name) const; - std::unique_ptr PrepareTrackMediaInfoMap_s() const; - std::map PrepareTrackToID_s() const; + std::vector PrepareTransceiverStatsInfos_s() const; // Slots for signals (sigslot) that are wired up to |pc_|. void OnDataChannelCreated(DataChannel* channel); @@ -150,12 +172,7 @@ 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::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_; + std::vector transceiver_stats_infos_; Call::Stats call_stats_; diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc index 566d677661..f95914b71c 100644 --- a/pc/rtcstatscollector_unittest.cc +++ b/pc/rtcstatscollector_unittest.cc @@ -18,8 +18,6 @@ #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" @@ -27,6 +25,8 @@ #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,6 +38,7 @@ #include "rtc_base/timedelta.h" #include "rtc_base/timeutils.h" +using testing::AtLeast; using testing::Invoke; using testing::Return; @@ -243,13 +244,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( @@ -267,12 +268,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( @@ -346,7 +347,7 @@ class RTCStatsCollectorWrapper { } } - rtc::scoped_refptr sender = + rtc::scoped_refptr sender = CreateMockSender(track, ssrc, 50, {}); pc_->AddSender(sender); } @@ -369,7 +370,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( @@ -410,7 +411,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); @@ -426,9 +427,10 @@ 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); @@ -443,7 +445,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); @@ -459,9 +461,10 @@ 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); @@ -606,7 +609,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("audio", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); voice_media_channel->SetStats(voice_media_info); // Video @@ -628,31 +631,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("video", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); video_media_channel->SetStats(video_media_info); rtc::scoped_refptr report = stats_->GetStatsReport(); - RTCCodecStats expected_inbound_audio_codec( - "RTCCodec_InboundAudio_1", report->timestamp_us()); + RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_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_OutboundAudio_2", report->timestamp_us()); + RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_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_InboundVideo_3", report->timestamp_us()); + RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_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_OutboundVideo_4", report->timestamp_us()); + RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_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; @@ -1444,8 +1447,6 @@ 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()); @@ -1467,7 +1468,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("voice", kTransportName); + auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); voice_media_channel->SetStats(voice_media_info); stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", 1); @@ -1483,10 +1484,8 @@ 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_" + - rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); - expected_audio.codec_id = "RTCCodec_InboundAudio_42"; + expected_audio.transport_id = "RTCTransport_TransportName_1"; + expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42"; expected_audio.packets_received = 2; expected_audio.bytes_received = 3; expected_audio.packets_lost = -1; @@ -1527,7 +1526,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("video", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); video_media_channel->SetStats(video_media_info); stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", 1); @@ -1540,9 +1539,8 @@ 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_" + - rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); - expected_video.codec_id = "RTCCodec_InboundVideo_42"; + expected_video.transport_id = "RTCTransport_TransportName_1"; + expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42"; expected_video.fir_count = 5; expected_video.pli_count = 6; expected_video.nack_count = 7; @@ -1592,7 +1590,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("audio", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); voice_media_channel->SetStats(voice_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1, true); @@ -1605,9 +1603,8 @@ 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_" + - rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); - expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; + expected_audio.transport_id = "RTCTransport_TransportName_1"; + expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; expected_audio.packets_sent = 2; expected_audio.bytes_sent = 3; @@ -1648,7 +1645,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("video", "TransportName"); + auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName"); video_media_channel->SetStats(video_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 1, true); @@ -1666,9 +1663,8 @@ 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_" + - rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); - expected_video.codec_id = "RTCCodec_OutboundVideo_42"; + expected_video.transport_id = "RTCTransport_TransportName_1"; + expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42"; expected_video.fir_count = 2; expected_video.pli_count = 3; expected_video.nack_count = 4; @@ -1854,7 +1850,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("audio", "TransportName"); + auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName"); voice_media_channel->SetStats(voice_media_info); stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1, false); @@ -1867,10 +1863,8 @@ 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_" + - rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); - expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; + expected_audio.transport_id = "RTCTransport_TransportName_1"; + expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42"; expected_audio.packets_sent = 2; expected_audio.bytes_sent = 3; @@ -1890,7 +1884,8 @@ TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) { 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(); @@ -1908,7 +1903,7 @@ TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) { 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 05990f4e03..bf0b1d68da 100644 --- a/pc/rtpreceiver.cc +++ b/pc/rtpreceiver.cc @@ -202,11 +202,6 @@ 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()); @@ -342,11 +337,6 @@ 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 887f828312..da92298c4f 100644 --- a/pc/rtpreceiver.h +++ b/pc/rtpreceiver.h @@ -34,6 +34,16 @@ 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. @@ -52,6 +62,11 @@ 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, @@ -102,9 +117,14 @@ class AudioRtpReceiver : public ObserverInterface, void SetObserver(RtpReceiverObserverInterface* observer) override; - // Does not take ownership. - // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. - void SetMediaChannel(cricket::VoiceMediaChannel* media_channel); + void SetVoiceMediaChannel( + cricket::VoiceMediaChannel* voice_media_channel) override { + media_channel_ = voice_media_channel; + } + void SetVideoMediaChannel( + cricket::VideoMediaChannel* video_media_channel) override { + RTC_NOTREACHED(); + } std::vector GetSources() const override; int AttachmentId() const override { return attachment_id_; } @@ -171,9 +191,16 @@ class VideoRtpReceiver : public rtc::RefCountedObject { void SetObserver(RtpReceiverObserverInterface* observer) override; - // Does not take ownership. - // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. - void SetMediaChannel(cricket::VideoMediaChannel* media_channel); + 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_; } private: bool SetSink(rtc::VideoSinkInterface* sink); diff --git a/pc/rtpsender.h b/pc/rtpsender.h index 97e32e2638..000df94a56 100644 --- a/pc/rtpsender.h +++ b/pc/rtpsender.h @@ -34,6 +34,16 @@ 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 @@ -49,6 +59,11 @@ 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 @@ -139,10 +154,13 @@ class AudioRtpSender : public DtmfProviderInterface, int AttachmentId() const override { return attachment_id_; } - // Does not take ownership. - // Should call SetMediaChannel(nullptr) before |media_channel| is destroyed. - void SetMediaChannel(cricket::VoiceMediaChannel* media_channel) { - media_channel_ = media_channel; + void SetVoiceMediaChannel( + cricket::VoiceMediaChannel* voice_media_channel) override { + media_channel_ = voice_media_channel; + } + void SetVideoMediaChannel( + cricket::VideoMediaChannel* video_media_channel) override { + RTC_NOTREACHED(); } private: @@ -229,10 +247,13 @@ class VideoRtpSender : public ObserverInterface, void Stop() override; 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) { - media_channel_ = media_channel; + void SetVoiceMediaChannel( + cricket::VoiceMediaChannel* voice_media_channel) override { + RTC_NOTREACHED(); + } + void SetVideoMediaChannel( + cricket::VideoMediaChannel* video_media_channel) override { + media_channel_ = video_media_channel; } private: diff --git a/pc/rtpsenderreceiver_unittest.cc b/pc/rtpsenderreceiver_unittest.cc index 40ed3686f9..4223264599 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_->SetMediaChannel(voice_media_channel_); + audio_rtp_sender_->SetVoiceMediaChannel(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_->SetMediaChannel(voice_media_channel_); + audio_rtp_sender_->SetVoiceMediaChannel(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_->SetMediaChannel(video_media_channel_); + video_rtp_sender_->SetVideoMediaChannel(video_media_channel_); video_rtp_sender_->SetSsrc(kVideoSsrc); VerifyVideoChannelInput(); } void CreateVideoRtpSenderWithNoTrack() { video_rtp_sender_ = new VideoRtpSender(worker_thread_); - video_rtp_sender_->SetMediaChannel(video_media_channel_); + video_rtp_sender_->SetVideoMediaChannel(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_->SetMediaChannel(voice_media_channel_); + audio_rtp_receiver_->SetVoiceMediaChannel(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_->SetMediaChannel(video_media_channel_); + video_rtp_receiver_->SetVideoMediaChannel(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_->SetMediaChannel(video_media_channel_); + video_rtp_sender_->SetVideoMediaChannel(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 310c4c49ad..1f1a850c9f 100644 --- a/pc/rtptransceiver.cc +++ b/pc/rtptransceiver.cc @@ -61,14 +61,12 @@ void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) { for (auto sender : senders_) { if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); - static_cast(sender->internal()) - ->SetMediaChannel(voice_channel ? voice_channel->media_channel() - : nullptr); + sender->internal()->SetVoiceMediaChannel( + voice_channel ? voice_channel->media_channel() : nullptr); } else { auto* video_channel = static_cast(channel); - static_cast(sender->internal()) - ->SetMediaChannel(video_channel ? video_channel->media_channel() - : nullptr); + sender->internal()->SetVideoMediaChannel( + video_channel ? video_channel->media_channel() : nullptr); } } @@ -78,14 +76,12 @@ void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) { } if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); - static_cast(receiver->internal()) - ->SetMediaChannel(voice_channel ? voice_channel->media_channel() - : nullptr); + receiver->internal()->SetVoiceMediaChannel( + voice_channel ? voice_channel->media_channel() : nullptr); } else { auto* video_channel = static_cast(channel); - static_cast(receiver->internal()) - ->SetMediaChannel(video_channel ? video_channel->media_channel() - : nullptr); + receiver->internal()->SetVideoMediaChannel( + video_channel ? video_channel->media_channel() : nullptr); } } } diff --git a/pc/test/fakepeerconnectionforstats.h b/pc/test/fakepeerconnectionforstats.h index d73e734367..be8003e891 100644 --- a/pc/test/fakepeerconnectionforstats.h +++ b/pc/test/fakepeerconnectionforstats.h @@ -97,12 +97,23 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { return remote_streams_; } - void AddSender(rtc::scoped_refptr sender) { - senders_.push_back(sender); + 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 AddReceiver(rtc::scoped_refptr receiver) { - receivers_.push_back(receiver); + 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); } FakeVoiceMediaChannelForStats* AddVoiceChannel( @@ -116,10 +127,9 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::move(voice_media_channel), mid, kDefaultRtcpMuxRequired, kDefaultSrtpRequired); voice_channel_->set_transport_name_for_testing(transport_name); - auto transceiver = RtpTransceiverProxyWithInternal::Create( - signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)); - transceiver->internal()->SetChannel(voice_channel_.get()); - transceivers_.push_back(transceiver); + GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO) + ->internal() + ->SetChannel(voice_channel_.get()); return voice_media_channel_ptr; } @@ -134,10 +144,9 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::move(video_media_channel), mid, kDefaultRtcpMuxRequired, kDefaultSrtpRequired); video_channel_->set_transport_name_for_testing(transport_name); - auto transceiver = RtpTransceiverProxyWithInternal::Create( - signaling_thread_, new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)); - transceiver->internal()->SetChannel(video_channel_.get()); - transceivers_.push_back(transceiver); + GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO) + ->internal() + ->SetChannel(video_channel_.get()); return video_media_channel_ptr; } @@ -204,12 +213,24 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { std::vector> GetSenders() const override { - return senders_; + std::vector> senders; + for (auto transceiver : transceivers_) { + for (auto sender : transceiver->internal()->senders()) { + senders.push_back(sender); + } + } + return senders; } std::vector> GetReceivers() const override { - return receivers_; + std::vector> receivers; + for (auto transceiver : transceivers_) { + for (auto receiver : transceiver->internal()->receivers()) { + receivers.push_back(receiver); + } + } + return receivers; } // PeerConnectionInternal overrides. @@ -323,6 +344,19 @@ 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_; @@ -333,8 +367,6 @@ 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 new file mode 100644 index 0000000000..8fb93b4f37 --- /dev/null +++ b/pc/test/mock_rtpreceiverinternal.h @@ -0,0 +1,52 @@ +/* + * 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 new file mode 100644 index 0000000000..b76a9ac0ba --- /dev/null +++ b/pc/test/mock_rtpsenderinternal.h @@ -0,0 +1,49 @@ +/* + * 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 654db15c04..5450cee7f0 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 (const rtc::scoped_refptr& rtp_sender : rtp_senders) { + for (auto rtp_sender : rtp_senders) { cricket::MediaType media_type = rtp_sender->media_type(); MediaStreamTrackInterface* track = rtp_sender->track(); if (!track) { @@ -72,8 +72,7 @@ void GetAudioAndVideoTrackBySsrc( } } } - for (const rtc::scoped_refptr& rtp_receiver : - rtp_receivers) { + for (auto rtp_receiver : rtp_receivers) { cricket::MediaType media_type = rtp_receiver->media_type(); MediaStreamTrackInterface* track = rtp_receiver->track(); RTC_DCHECK(track); @@ -111,8 +110,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; @@ -127,10 +126,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 a0f882d941..d6036264ea 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 93d6155af0..c1355647be 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) { - rtc::scoped_refptr rtp_receiver = CreateMockRtpReceiver( + auto 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_;