From 84abeb1d37ee27147674cd94a5606bd4ac725d9a Mon Sep 17 00:00:00 2001 From: hbos Date: Mon, 16 Jan 2017 06:16:44 -0800 Subject: [PATCH] RTC[In/Out]boundRTPStreamStats.mediaTrackId collected. Based on the mapping between [Audio/Video]TrackInterface and [Voice/Video][Sender/Receiver]Info. The IDs of RTCMediaStreamTrackStats are updated to distinguish between local and remote cases. Previously, if local and remote cases had the same label only one of them would be included in the report (bug). BUG=webrtc:6758, chromium:657854, chromium:657855, chromium:657856, chromium:627816 Review-Url: https://codereview.webrtc.org/2610843003 Cr-Commit-Position: refs/heads/master@{#16095} --- webrtc/api/rtcstats_integrationtest.cc | 3 +- webrtc/api/rtcstatscollector.cc | 150 ++++++++++++++++------ webrtc/api/rtcstatscollector.h | 24 ++-- webrtc/api/rtcstatscollector_unittest.cc | 157 ++++++++++++++++++++--- webrtc/api/stats/rtcstats_objects.h | 1 - webrtc/api/statscollector_unittest.cc | 4 + webrtc/api/test/mock_peerconnection.h | 4 + 7 files changed, 275 insertions(+), 68 deletions(-) diff --git a/webrtc/api/rtcstats_integrationtest.cc b/webrtc/api/rtcstats_integrationtest.cc index 545f80165f..69dc834a11 100644 --- a/webrtc/api/rtcstats_integrationtest.cc +++ b/webrtc/api/rtcstats_integrationtest.cc @@ -490,7 +490,8 @@ class RTCStatsReportVerifier { verifier->TestMemberIsUndefined(stream.associate_stats_id); verifier->TestMemberIsDefined(stream.is_remote); verifier->TestMemberIsDefined(stream.media_type); - verifier->TestMemberIsUndefined(stream.media_track_id); + verifier->TestMemberIsIDReference( + stream.media_track_id, RTCMediaStreamTrackStats::kType); verifier->TestMemberIsIDReference( stream.transport_id, RTCTransportStats::kType); verifier->TestMemberIsIDReference(stream.codec_id, RTCCodecStats::kType); diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc index dc14970854..eade3d355e 100644 --- a/webrtc/api/rtcstatscollector.cc +++ b/webrtc/api/rtcstatscollector.cc @@ -53,9 +53,10 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo( info.remote_candidate.id(); } -std::string RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( - const MediaStreamTrackInterface& track) { - return "RTCMediaStreamTrack_" + track.id(); +std::string RTCMediaStreamTrackStatsIDFromTrackID( + const std::string& id, bool is_local) { + return (is_local ? "RTCMediaStreamTrack_local_" + id + : "RTCMediaStreamTrack_remote_" + id); } std::string RTCTransportStatsIDFromTransportChannel( @@ -327,8 +328,8 @@ void ProduceMediaStreamAndTrackStats( // Audio Tracks for (const rtc::scoped_refptr& audio_track : stream->GetAudioTracks()) { - std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( - *audio_track.get()); + std::string id = RTCMediaStreamTrackStatsIDFromTrackID( + audio_track->id(), is_local); if (report->Get(id)) { // Skip track, stats already exist for it. continue; @@ -365,8 +366,8 @@ void ProduceMediaStreamAndTrackStats( // Video Tracks for (const rtc::scoped_refptr& video_track : stream->GetVideoTracks()) { - std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( - *video_track.get()); + std::string id = RTCMediaStreamTrackStatsIDFromTrackID( + video_track->id(), is_local); if (report->Get(id)) { // Skip track, stats already exist for it. continue; @@ -450,7 +451,7 @@ void RTCStatsCollector::GetStatsReport( num_pending_partial_reports_ = 2; partial_report_timestamp_us_ = cache_now_us; - // Prepare |channel_names_| and |media_info_| for use in + // Prepare |channel_name_pairs_| for use in // |ProducePartialResultsOnNetworkThread|. channel_name_pairs_.reset(new ChannelNamePairs()); if (pc_->session()->voice_channel()) { @@ -474,7 +475,14 @@ void RTCStatsCollector::GetStatsReport( ChannelNamePair(*pc_->session()->sctp_content_name(), *pc_->session()->sctp_transport_name())); } - media_info_.reset(PrepareMediaInfo_s().release()); + // Prepare |track_media_info_map_| 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(); invoker_.AsyncInvoke(RTC_FROM_HERE, network_thread_, rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnNetworkThread, @@ -527,11 +535,11 @@ void RTCStatsCollector::ProducePartialResultsOnNetworkThread( ProduceCertificateStats_n( timestamp_us, transport_cert_stats, report.get()); ProduceCodecStats_n( - timestamp_us, *media_info_, report.get()); + timestamp_us, *track_media_info_map_, report.get()); ProduceIceCandidateAndPairStats_n( timestamp_us, *session_stats, report.get()); ProduceRTPStreamStats_n( - timestamp_us, *session_stats, *media_info_, report.get()); + timestamp_us, *session_stats, *track_media_info_map_, report.get()); ProduceTransportStats_n( timestamp_us, *session_stats, transport_cert_stats, report.get()); } @@ -564,6 +572,9 @@ void RTCStatsCollector::AddPartialResults_s( cache_timestamp_us_ = partial_report_timestamp_us_; cached_report_ = partial_report_; partial_report_ = nullptr; + channel_name_pairs_.reset(); + track_media_info_map_.reset(); + track_to_id_.clear(); DeliverCachedReport(); } } @@ -597,31 +608,35 @@ void RTCStatsCollector::ProduceCertificateStats_n( } void RTCStatsCollector::ProduceCodecStats_n( - int64_t timestamp_us, const MediaInfo& media_info, + int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); // Audio - if (media_info.voice) { + if (track_media_info_map.voice_media_info()) { // Inbound - for (const auto& pair : media_info.voice->receive_codecs) { + for (const auto& pair : + track_media_info_map.voice_media_info()->receive_codecs) { report->AddStats(CodecStatsFromRtpCodecParameters( timestamp_us, true, true, pair.second)); } // Outbound - for (const auto& pair : media_info.voice->send_codecs) { + for (const auto& pair : + track_media_info_map.voice_media_info()->send_codecs) { report->AddStats(CodecStatsFromRtpCodecParameters( timestamp_us, false, true, pair.second)); } } // Video - if (media_info.video) { + if (track_media_info_map.video_media_info()) { // Inbound - for (const auto& pair : media_info.video->receive_codecs) { + 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 : media_info.video->send_codecs) { + for (const auto& pair : + track_media_info_map.video_media_info()->send_codecs) { report->AddStats(CodecStatsFromRtpCodecParameters( timestamp_us, false, false, pair.second)); } @@ -731,17 +746,18 @@ void RTCStatsCollector::ProducePeerConnectionStats_s( void RTCStatsCollector::ProduceRTPStreamStats_n( int64_t timestamp_us, const SessionStats& session_stats, - const MediaInfo& media_info, RTCStatsReport* report) const { + const TrackMediaInfoMap& track_media_info_map, + RTCStatsReport* report) const { RTC_DCHECK(network_thread_->IsCurrent()); // Audio - if (media_info.voice) { + if (track_media_info_map.voice_media_info()) { std::string transport_id = RTCTransportStatsIDFromBaseChannel( session_stats.proxy_to_transport, *pc_->session()->voice_channel()); RTC_DCHECK(!transport_id.empty()); // Inbound for (const cricket::VoiceReceiverInfo& voice_receiver_info : - media_info.voice->receivers) { + track_media_info_map.voice_media_info()->receivers) { // TODO(nisse): SSRC == 0 currently means none. Delete check when that // is fixed. if (voice_receiver_info.ssrc() == 0) @@ -753,6 +769,14 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( timestamp_us)); SetInboundRTPStreamStatsFromVoiceReceiverInfo( voice_receiver_info, inbound_audio.get()); + 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->media_track_id = + RTCMediaStreamTrackStatsIDFromTrackID( + track_to_id_.find(audio_track.get())->second, false); + } inbound_audio->transport_id = transport_id; if (voice_receiver_info.codec_payload_type) { inbound_audio->codec_id = @@ -763,7 +787,7 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( } // Outbound for (const cricket::VoiceSenderInfo& voice_sender_info : - media_info.voice->senders) { + track_media_info_map.voice_media_info()->senders) { // TODO(nisse): SSRC == 0 currently means none. Delete check when that // is fixed. if (voice_sender_info.ssrc() == 0) @@ -775,6 +799,14 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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->media_track_id = + RTCMediaStreamTrackStatsIDFromTrackID( + track_to_id_.find(audio_track.get())->second, true); + } outbound_audio->transport_id = transport_id; if (voice_sender_info.codec_payload_type) { outbound_audio->codec_id = @@ -785,13 +817,13 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( } } // Video - if (media_info.video) { + if (track_media_info_map.video_media_info()) { std::string transport_id = RTCTransportStatsIDFromBaseChannel( session_stats.proxy_to_transport, *pc_->session()->video_channel()); RTC_DCHECK(!transport_id.empty()); // Inbound for (const cricket::VideoReceiverInfo& video_receiver_info : - media_info.video->receivers) { + 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.ssrc() == 0) @@ -803,6 +835,14 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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->media_track_id = + RTCMediaStreamTrackStatsIDFromTrackID( + track_to_id_.find(video_track.get())->second, false); + } inbound_video->transport_id = transport_id; if (video_receiver_info.codec_payload_type) { inbound_video->codec_id = @@ -813,7 +853,7 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( } // Outbound for (const cricket::VideoSenderInfo& video_sender_info : - media_info.video->senders) { + track_media_info_map.video_media_info()->senders) { // TODO(nisse): SSRC == 0 currently means none. Delete check when that // is fixed. if (video_sender_info.ssrc() == 0) @@ -825,6 +865,14 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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->media_track_id = + RTCMediaStreamTrackStatsIDFromTrackID( + track_to_id_.find(video_track.get())->second, true); + } outbound_video->transport_id = transport_id; if (video_sender_info.codec_payload_type) { outbound_video->codec_id = @@ -928,25 +976,53 @@ RTCStatsCollector::PrepareTransportCertificateStats_n( return transport_cert_stats; } -std::unique_ptr -RTCStatsCollector::PrepareMediaInfo_s() const { +std::unique_ptr +RTCStatsCollector::PrepareTrackMediaInfoMap_s() const { RTC_DCHECK(signaling_thread_->IsCurrent()); - std::unique_ptr media_info(new MediaInfo()); + std::unique_ptr voice_media_info; if (pc_->session()->voice_channel()) { - cricket::VoiceMediaInfo voice_media_info; - if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) { - media_info->voice = rtc::Optional( - std::move(voice_media_info)); + voice_media_info.reset(new cricket::VoiceMediaInfo()); + if (!pc_->session()->voice_channel()->GetStats(voice_media_info.get())) { + voice_media_info.reset(); } } + std::unique_ptr video_media_info; if (pc_->session()->video_channel()) { - cricket::VideoMediaInfo video_media_info; - if (pc_->session()->video_channel()->GetStats(&video_media_info)) { - media_info->video = rtc::Optional( - std::move(video_media_info)); + video_media_info.reset(new cricket::VideoMediaInfo()); + if (!pc_->session()->video_channel()->GetStats(video_media_info.get())) { + video_media_info.reset(); } } - return media_info; + 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::map +RTCStatsCollector::PrepareTrackToID_s() const { + RTC_DCHECK(signaling_thread_->IsCurrent()); + std::map track_to_id; + StreamCollectionInterface* local_and_remote_streams[] = + { pc_->local_streams().get(), pc_->remote_streams().get() }; + for (auto& streams : local_and_remote_streams) { + if (streams) { + for (size_t i = 0; i < streams->count(); ++i) { + MediaStreamInterface* stream = streams->at(i); + for (const rtc::scoped_refptr& audio_track : + stream->GetAudioTracks()) { + track_to_id[audio_track.get()] = audio_track->id(); + } + for (const rtc::scoped_refptr& video_track : + stream->GetVideoTracks()) { + track_to_id[video_track.get()] = video_track->id(); + } + } + } + } + return track_to_id; } void RTCStatsCollector::OnDataChannelCreated(DataChannel* channel) { diff --git a/webrtc/api/rtcstatscollector.h b/webrtc/api/rtcstatscollector.h index 0a99ae9703..cd3c55ee89 100644 --- a/webrtc/api/rtcstatscollector.h +++ b/webrtc/api/rtcstatscollector.h @@ -20,6 +20,7 @@ #include "webrtc/api/datachannelinterface.h" #include "webrtc/api/stats/rtcstats_objects.h" #include "webrtc/api/stats/rtcstatsreport.h" +#include "webrtc/api/trackmediainfomap.h" #include "webrtc/base/asyncinvoker.h" #include "webrtc/base/optional.h" #include "webrtc/base/refcount.h" @@ -93,10 +94,6 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, std::unique_ptr local; std::unique_ptr remote; }; - struct MediaInfo { - rtc::Optional voice; - rtc::Optional video; - }; void AddPartialResults_s(rtc::scoped_refptr partial_report); void DeliverCachedReport(); @@ -108,7 +105,7 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, RTCStatsReport* report) const; // Produces |RTCCodecStats|. void ProduceCodecStats_n( - int64_t timestamp_us, const MediaInfo& media_info, + int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, RTCStatsReport* report) const; // Produces |RTCDataChannelStats|. void ProduceDataChannelStats_s( @@ -126,7 +123,8 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, // Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|. void ProduceRTPStreamStats_n( int64_t timestamp_us, const SessionStats& session_stats, - const MediaInfo& media_info, RTCStatsReport* report) const; + const TrackMediaInfoMap& track_media_info_map, + RTCStatsReport* report) const; // Produces |RTCTransportStats|. void ProduceTransportStats_n( int64_t timestamp_us, const SessionStats& session_stats, @@ -136,7 +134,8 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, // Helper function to stats-producing functions. std::map PrepareTransportCertificateStats_n(const SessionStats& session_stats) const; - std::unique_ptr PrepareMediaInfo_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); @@ -155,12 +154,13 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, rtc::scoped_refptr partial_report_; std::vector> callbacks_; - // Set in |GetStatsReport|, used in |ProducePartialResultsOnNetworkThread| - // (not passed as arguments to avoid copies). This is thread safe - it is set - // at the start of |GetStatsReport| after making sure there are no pending - // stats requests in progress. + // Set in |GetStatsReport|, read in |ProducePartialResultsOnNetworkThread| and + // |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::unique_ptr channel_name_pairs_; - std::unique_ptr media_info_; + std::unique_ptr track_media_info_map_; + std::map track_to_id_; // A timestamp, in microseconds, that is based on a timer that is // monotonically increasing. That is, even if the system clock is modified the diff --git a/webrtc/api/rtcstatscollector_unittest.cc b/webrtc/api/rtcstatscollector_unittest.cc index a9426622fb..53925862f0 100644 --- a/webrtc/api/rtcstatscollector_unittest.cc +++ b/webrtc/api/rtcstatscollector_unittest.cc @@ -23,6 +23,8 @@ #include "webrtc/api/stats/rtcstatsreport.h" #include "webrtc/api/test/mock_datachannel.h" #include "webrtc/api/test/mock_peerconnection.h" +#include "webrtc/api/test/mock_rtpreceiver.h" +#include "webrtc/api/test/mock_rtpsender.h" #include "webrtc/api/test/mock_webrtcsession.h" #include "webrtc/api/test/rtcstatsobtainer.h" #include "webrtc/base/checks.h" @@ -288,6 +290,26 @@ class FakeVideoTrackForStats rtc::scoped_refptr source_; }; +rtc::scoped_refptr CreateFakeTrack( + cricket::MediaType media_type, + const std::string& track_id) { + if (media_type == cricket::MEDIA_TYPE_AUDIO) { + return FakeAudioTrackForStats::Create( + track_id, + MediaStreamTrackInterface::TrackState::kLive, + 32767, + new FakeAudioProcessorForStats( + AudioProcessorInterface::AudioProcessorStats())); + } else { + RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO); + return FakeVideoTrackForStats::Create( + track_id, + MediaStreamTrackInterface::TrackState::kLive, + new FakeVideoTrackSourceForStats( + VideoTrackSourceInterface::Stats())); + } +} + class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { public: RTCStatsCollectorTestHelper() @@ -309,6 +331,10 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr)); EXPECT_CALL(pc_, remote_streams()).WillRepeatedly(Return(nullptr)); EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_)); + EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( + std::vector>())); + EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( + std::vector>())); EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly( ReturnRef(data_channels_)); EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); @@ -336,6 +362,81 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { RTC_NOTREACHED() << error; } + void SetupLocalTrackAndSender(cricket::MediaType media_type, + const std::string& track_id, + uint32_t ssrc) { + rtc::scoped_refptr local_streams = + StreamCollection::Create(); + EXPECT_CALL(pc_, local_streams()) + .WillRepeatedly(Return(local_streams)); + + rtc::scoped_refptr local_stream = + MediaStream::Create("LocalStreamLabel"); + local_streams->AddStream(local_stream); + + rtc::scoped_refptr track; + if (media_type == cricket::MEDIA_TYPE_AUDIO) { + track = CreateFakeTrack(media_type, track_id); + local_stream->AddTrack(static_cast(track.get())); + } else { + track = CreateFakeTrack(media_type, track_id); + local_stream->AddTrack(static_cast(track.get())); + } + + 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(media_type)); + EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke( + [ssrc]() { + RtpParameters params; + params.encodings.push_back(RtpEncodingParameters()); + params.encodings[0].ssrc = rtc::Optional(ssrc); + return params; + })); + EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( + std::vector>({ + rtc::scoped_refptr(sender.get()) }))); + } + + void SetupRemoteTrackAndReceiver(cricket::MediaType media_type, + const std::string& track_id, + uint32_t ssrc) { + rtc::scoped_refptr remote_streams = + StreamCollection::Create(); + EXPECT_CALL(pc_, remote_streams()) + .WillRepeatedly(Return(remote_streams)); + + rtc::scoped_refptr remote_stream = + MediaStream::Create("RemoteStreamLabel"); + remote_streams->AddStream(remote_stream); + + rtc::scoped_refptr track; + if (media_type == cricket::MEDIA_TYPE_AUDIO) { + track = CreateFakeTrack(media_type, track_id); + remote_stream->AddTrack(static_cast(track.get())); + } else { + track = CreateFakeTrack(media_type, track_id); + remote_stream->AddTrack(static_cast(track.get())); + } + + rtc::scoped_refptr receiver( + new rtc::RefCountedObject()); + EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); + EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return(media_type)); + EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke( + [ssrc]() { + RtpParameters params; + params.encodings.push_back(RtpEncodingParameters()); + params.encodings[0].ssrc = rtc::Optional(ssrc); + return params; + })); + EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( + std::vector>({ + rtc::scoped_refptr(receiver.get()) }))); + } + private: rtc::ScopedFakeClock fake_clock_; RtcEventLogNullImpl event_log_; @@ -1260,7 +1361,7 @@ TEST_F(RTCStatsCollectorTest, expected_local_stream.stream_identifier = local_stream->label(); expected_local_stream.track_ids = std::vector(); expected_local_stream.track_ids->push_back( - "RTCMediaStreamTrack_LocalAudioTrackID"); + "RTCMediaStreamTrack_local_LocalAudioTrackID"); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1271,14 +1372,14 @@ TEST_F(RTCStatsCollectorTest, expected_remote_stream.stream_identifier = remote_stream->label(); expected_remote_stream.track_ids = std::vector(); expected_remote_stream.track_ids->push_back( - "RTCMediaStreamTrack_RemoteAudioTrackID"); + "RTCMediaStreamTrack_remote_RemoteAudioTrackID"); ASSERT_TRUE(report->Get(expected_remote_stream.id())); EXPECT_EQ(expected_remote_stream, report->Get(expected_remote_stream.id())->cast_to< RTCMediaStreamStats>()); RTCMediaStreamTrackStats expected_local_audio_track( - "RTCMediaStreamTrack_LocalAudioTrackID", report->timestamp_us()); + "RTCMediaStreamTrack_local_LocalAudioTrackID", report->timestamp_us()); expected_local_audio_track.track_identifier = local_audio_track->id(); expected_local_audio_track.remote_source = false; expected_local_audio_track.ended = true; @@ -1292,7 +1393,7 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamTrackStats>()); RTCMediaStreamTrackStats expected_remote_audio_track( - "RTCMediaStreamTrack_RemoteAudioTrackID", report->timestamp_us()); + "RTCMediaStreamTrack_remote_RemoteAudioTrackID", report->timestamp_us()); expected_remote_audio_track.track_identifier = remote_audio_track->id(); expected_remote_audio_track.remote_source = true; expected_remote_audio_track.ended = false; @@ -1332,7 +1433,7 @@ TEST_F(RTCStatsCollectorTest, rtc::scoped_refptr report = GetStatsReport(); RTCMediaStreamTrackStats expected_local_audio_track( - "RTCMediaStreamTrack_LocalAudioTrackID", report->timestamp_us()); + "RTCMediaStreamTrack_local_LocalAudioTrackID", report->timestamp_us()); expected_local_audio_track.track_identifier = local_audio_track->id(); expected_local_audio_track.remote_source = false; expected_local_audio_track.ended = true; @@ -1397,7 +1498,7 @@ TEST_F(RTCStatsCollectorTest, expected_local_stream.stream_identifier = local_stream->label(); expected_local_stream.track_ids = std::vector(); expected_local_stream.track_ids->push_back( - "RTCMediaStreamTrack_LocalVideoTrackID"); + "RTCMediaStreamTrack_local_LocalVideoTrackID"); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1408,14 +1509,14 @@ TEST_F(RTCStatsCollectorTest, expected_remote_stream.stream_identifier = remote_stream->label(); expected_remote_stream.track_ids = std::vector(); expected_remote_stream.track_ids->push_back( - "RTCMediaStreamTrack_RemoteVideoTrackID"); + "RTCMediaStreamTrack_remote_RemoteVideoTrackID"); ASSERT_TRUE(report->Get(expected_remote_stream.id())); EXPECT_EQ(expected_remote_stream, report->Get(expected_remote_stream.id())->cast_to< RTCMediaStreamStats>()); RTCMediaStreamTrackStats expected_local_video_track( - "RTCMediaStreamTrack_LocalVideoTrackID", report->timestamp_us()); + "RTCMediaStreamTrack_local_LocalVideoTrackID", report->timestamp_us()); expected_local_video_track.track_identifier = local_video_track->id(); expected_local_video_track.remote_source = false; expected_local_video_track.ended = false; @@ -1428,7 +1529,7 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamTrackStats>()); RTCMediaStreamTrackStats expected_remote_video_track( - "RTCMediaStreamTrack_RemoteVideoTrackID", report->timestamp_us()); + "RTCMediaStreamTrack_remote_RemoteVideoTrackID", report->timestamp_us()); expected_remote_video_track.track_identifier = remote_video_track->id(); expected_remote_video_track.remote_source = true; expected_remote_video_track.ended = true; @@ -1448,6 +1549,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { test_->media_engine(), voice_media_channel, "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); + test_->SetupRemoteTrackAndReceiver( + cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", 1); + cricket::VoiceMediaInfo voice_media_info; voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo()); @@ -1496,6 +1600,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.ssrc = "1"; expected_audio.is_remote = false; expected_audio.media_type = "audio"; + expected_audio.media_track_id = + "RTCMediaStreamTrack_remote_RemoteAudioTrackID"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_InboundAudio_42"; @@ -1510,8 +1616,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.id())->cast_to(); EXPECT_EQ(audio, expected_audio); - ASSERT_TRUE(report->Get(*expected_audio.transport_id)); - ASSERT_TRUE(report->Get(*expected_audio.codec_id)); + EXPECT_TRUE(report->Get(*expected_audio.media_track_id)); + EXPECT_TRUE(report->Get(*expected_audio.transport_id)); + EXPECT_TRUE(report->Get(*expected_audio.codec_id)); } TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { @@ -1521,6 +1628,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { video_media_channel, "VideoContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); + test_->SetupRemoteTrackAndReceiver( + cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", 1); + cricket::VideoMediaInfo video_media_info; video_media_info.receivers.push_back(cricket::VideoReceiverInfo()); @@ -1572,6 +1682,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { expected_video.ssrc = "1"; expected_video.is_remote = false; expected_video.media_type = "video"; + expected_video.media_track_id = + "RTCMediaStreamTrack_remote_RemoteVideoTrackID"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_InboundVideo_42"; @@ -1589,8 +1701,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { expected_video.id())->cast_to(); EXPECT_EQ(video, expected_video); - ASSERT_TRUE(report->Get(*expected_video.transport_id)); - ASSERT_TRUE(report->Get(*video.codec_id)); + EXPECT_TRUE(report->Get(*expected_video.media_track_id)); + EXPECT_TRUE(report->Get(*expected_video.transport_id)); + EXPECT_TRUE(report->Get(*video.codec_id)); } TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { @@ -1600,6 +1713,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { test_->media_engine(), voice_media_channel, "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); + test_->SetupLocalTrackAndSender( + cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1); + cricket::VoiceMediaInfo voice_media_info; voice_media_info.senders.push_back(cricket::VoiceSenderInfo()); @@ -1645,6 +1761,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.ssrc = "1"; expected_audio.is_remote = false; expected_audio.media_type = "audio"; + expected_audio.media_track_id = "RTCMediaStreamTrack_local_LocalAudioTrackID"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; @@ -1657,8 +1774,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { expected_audio.id())->cast_to(); EXPECT_EQ(audio, expected_audio); - ASSERT_TRUE(report->Get(*expected_audio.transport_id)); - ASSERT_TRUE(report->Get(*expected_audio.codec_id)); + EXPECT_TRUE(report->Get(*expected_audio.media_track_id)); + EXPECT_TRUE(report->Get(*expected_audio.transport_id)); + EXPECT_TRUE(report->Get(*expected_audio.codec_id)); } TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { @@ -1668,6 +1786,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { video_media_channel, "VideoContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); + test_->SetupLocalTrackAndSender( + cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 1); + cricket::VideoMediaInfo video_media_info; video_media_info.senders.push_back(cricket::VideoSenderInfo()); @@ -1718,6 +1839,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.ssrc = "1"; expected_video.is_remote = false; expected_video.media_type = "video"; + expected_video.media_track_id = "RTCMediaStreamTrack_local_LocalVideoTrackID"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_OutboundVideo_42"; @@ -1735,8 +1857,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.id())->cast_to(); EXPECT_EQ(video, expected_video); - ASSERT_TRUE(report->Get(*expected_video.transport_id)); - ASSERT_TRUE(report->Get(*expected_video.codec_id)); + EXPECT_TRUE(report->Get(*expected_video.media_track_id)); + EXPECT_TRUE(report->Get(*expected_video.transport_id)); + EXPECT_TRUE(report->Get(*expected_video.codec_id)); } TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Default) { diff --git a/webrtc/api/stats/rtcstats_objects.h b/webrtc/api/stats/rtcstats_objects.h index 22c06e4fcb..80830c3c8a 100644 --- a/webrtc/api/stats/rtcstats_objects.h +++ b/webrtc/api/stats/rtcstats_objects.h @@ -295,7 +295,6 @@ class RTCRTPStreamStats : public RTCStats { // crbug.com/657855, 657856 RTCStatsMember is_remote; // = false RTCStatsMember media_type; - // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/657854, 659137 RTCStatsMember media_track_id; RTCStatsMember transport_id; RTCStatsMember codec_id; diff --git a/webrtc/api/statscollector_unittest.cc b/webrtc/api/statscollector_unittest.cc index 0f0c0fcb1b..30bb2b8091 100644 --- a/webrtc/api/statscollector_unittest.cc +++ b/webrtc/api/statscollector_unittest.cc @@ -522,6 +522,10 @@ class StatsCollectorTest : public testing::Test { EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_)); EXPECT_CALL(pc_, sctp_data_channels()) .WillRepeatedly(ReturnRef(data_channels_)); + EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( + std::vector>())); + EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( + std::vector>())); } ~StatsCollectorTest() {} diff --git a/webrtc/api/test/mock_peerconnection.h b/webrtc/api/test/mock_peerconnection.h index 7cc2b0dd92..ca39d2abb5 100644 --- a/webrtc/api/test/mock_peerconnection.h +++ b/webrtc/api/test/mock_peerconnection.h @@ -33,6 +33,10 @@ class MockPeerConnection MOCK_METHOD0(remote_streams, rtc::scoped_refptr()); MOCK_METHOD0(session, WebRtcSession*()); + MOCK_CONST_METHOD0(GetSenders, + std::vector>()); + MOCK_CONST_METHOD0(GetReceivers, + std::vector>()); MOCK_CONST_METHOD0(sctp_data_channels, const std::vector>&()); };