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>&()); };