diff --git a/webrtc/api/rtcstats_integrationtest.cc b/webrtc/api/rtcstats_integrationtest.cc index 98eafb0ac3..33b1436e7b 100644 --- a/webrtc/api/rtcstats_integrationtest.cc +++ b/webrtc/api/rtcstats_integrationtest.cc @@ -433,17 +433,10 @@ class RTCStatsReportVerifier { // Video or audio media stream track? if (*media_stream_track.kind == RTCMediaStreamTrackKind::kVideo) { // Video-only members - if (!*media_stream_track.remote_source) { - verifier.TestMemberIsNonNegative( - media_stream_track.frame_width); - verifier.TestMemberIsNonNegative( - media_stream_track.frame_height); - } else { - // TODO(hbos): Frame width/height should be defined for the remote case. - // Is this a real problem or an artifact of testing? crbug.com/659137 - verifier.TestMemberIsUndefined(media_stream_track.frame_width); - verifier.TestMemberIsUndefined(media_stream_track.frame_height); - } + verifier.TestMemberIsNonNegative( + media_stream_track.frame_width); + verifier.TestMemberIsNonNegative( + media_stream_track.frame_height); verifier.TestMemberIsUndefined(media_stream_track.frames_per_second); verifier.TestMemberIsUndefined(media_stream_track.frames_sent); verifier.TestMemberIsUndefined(media_stream_track.frames_received); @@ -470,14 +463,14 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost); verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost); // Audio-only members - // TODO(hbos): Why are the audio track missing |audio_level|, - // |echo_return_loss| and |echo_return_loss_enhancement|? Is this a real - // problem or does it have to do with testing and not using real devices? + verifier.TestMemberIsNonNegative(media_stream_track.audio_level); + // TODO(hbos): Find out why |echo_return_loss| and + // |echo_return_loss_enhancement| are undefined in the integration test. + // Is this a real problem or a test problem? Update test so that they are. // crbug.com/627816 - verifier.MarkMemberTested(media_stream_track.audio_level, true); - verifier.MarkMemberTested(media_stream_track.echo_return_loss, true); - verifier.MarkMemberTested( - media_stream_track.echo_return_loss_enhancement, true); + verifier.TestMemberIsUndefined(media_stream_track.echo_return_loss); + verifier.TestMemberIsUndefined( + media_stream_track.echo_return_loss_enhancement); } return verifier.ExpectAllMembersSuccessfullyTested(); } diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc index 7f2f45e84a..216a5ac299 100644 --- a/webrtc/api/rtcstatscollector.cc +++ b/webrtc/api/rtcstatscollector.cc @@ -11,6 +11,7 @@ #include "webrtc/api/rtcstatscollector.h" #include +#include #include #include @@ -53,10 +54,17 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo( info.remote_candidate.id(); } -std::string RTCMediaStreamTrackStatsIDFromTrackID( - const std::string& id, bool is_local) { - return (is_local ? "RTCMediaStreamTrack_local_" + id - : "RTCMediaStreamTrack_remote_" + id); +std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + bool is_local, const char* kind, const std::string& id, uint32_t ssrc) { + RTC_DCHECK(kind == MediaStreamTrackInterface::kAudioKind || + kind == MediaStreamTrackInterface::kVideoKind); + std::ostringstream oss; + oss << (is_local ? "RTCMediaStreamTrack_local_" + : "RTCMediaStreamTrack_remote_"); + oss << kind << "_"; + oss << id << "_"; + oss << ssrc; + return oss.str(); } std::string RTCTransportStatsIDFromTransportChannel( @@ -151,6 +159,12 @@ const char* DtlsTransportStateToRTCDtlsTransportState( } } +double DoubleAudioLevelFromIntAudioLevel(int audio_level) { + RTC_DCHECK_GE(audio_level, 0); + RTC_DCHECK_LE(audio_level, 32767); + return audio_level / 32767.0; +} + std::unique_ptr CodecStatsFromRtpCodecParameters( uint64_t timestamp_us, bool inbound, bool audio, const RtpCodecParameters& codec_params) { @@ -322,8 +336,112 @@ const std::string& ProduceIceCandidateStats( return stats->id(); } +std::unique_ptr +ProduceMediaStreamTrackStatsFromVoiceSenderInfo( + int64_t timestamp_us, + const AudioTrackInterface& audio_track, + const cricket::VoiceSenderInfo& voice_sender_info) { + std::unique_ptr audio_track_stats( + new RTCMediaStreamTrackStats( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + true, MediaStreamTrackInterface::kAudioKind, audio_track.id(), + voice_sender_info.ssrc()), + timestamp_us, + RTCMediaStreamTrackKind::kAudio)); + SetMediaStreamTrackStatsFromMediaStreamTrackInterface( + audio_track, audio_track_stats.get()); + audio_track_stats->remote_source = false; + audio_track_stats->detached = false; + if (voice_sender_info.audio_level >= 0) { + audio_track_stats->audio_level = DoubleAudioLevelFromIntAudioLevel( + voice_sender_info.audio_level); + } + if (voice_sender_info.echo_return_loss != -100) { + audio_track_stats->echo_return_loss = static_cast( + voice_sender_info.echo_return_loss); + } + if (voice_sender_info.echo_return_loss_enhancement != -100) { + audio_track_stats->echo_return_loss_enhancement = static_cast( + voice_sender_info.echo_return_loss_enhancement); + } + return audio_track_stats; +} + +std::unique_ptr +ProduceMediaStreamTrackStatsFromVoiceReceiverInfo( + int64_t timestamp_us, + const AudioTrackInterface& audio_track, + const cricket::VoiceReceiverInfo& voice_receiver_info) { + std::unique_ptr audio_track_stats( + new RTCMediaStreamTrackStats( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + false, MediaStreamTrackInterface::kAudioKind, audio_track.id(), + voice_receiver_info.ssrc()), + timestamp_us, + RTCMediaStreamTrackKind::kAudio)); + SetMediaStreamTrackStatsFromMediaStreamTrackInterface( + audio_track, audio_track_stats.get()); + audio_track_stats->remote_source = true; + audio_track_stats->detached = false; + if (voice_receiver_info.audio_level >= 0) { + audio_track_stats->audio_level = DoubleAudioLevelFromIntAudioLevel( + voice_receiver_info.audio_level); + } + return audio_track_stats; +} + +std::unique_ptr +ProduceMediaStreamTrackStatsFromVideoSenderInfo( + int64_t timestamp_us, + const VideoTrackInterface& video_track, + const cricket::VideoSenderInfo& video_sender_info) { + std::unique_ptr video_track_stats( + new RTCMediaStreamTrackStats( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + true, MediaStreamTrackInterface::kVideoKind, video_track.id(), + video_sender_info.ssrc()), + timestamp_us, + RTCMediaStreamTrackKind::kVideo)); + SetMediaStreamTrackStatsFromMediaStreamTrackInterface( + video_track, video_track_stats.get()); + video_track_stats->remote_source = false; + video_track_stats->detached = false; + video_track_stats->frame_width = static_cast( + video_sender_info.send_frame_width); + video_track_stats->frame_height = static_cast( + video_sender_info.send_frame_height); + return video_track_stats; +} + +std::unique_ptr +ProduceMediaStreamTrackStatsFromVideoReceiverInfo( + int64_t timestamp_us, + const VideoTrackInterface& video_track, + const cricket::VideoReceiverInfo& video_receiver_info) { + std::unique_ptr video_track_stats( + new RTCMediaStreamTrackStats( + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + false, MediaStreamTrackInterface::kVideoKind, video_track.id(), + video_receiver_info.ssrc()), + timestamp_us, + RTCMediaStreamTrackKind::kVideo)); + SetMediaStreamTrackStatsFromMediaStreamTrackInterface( + video_track, video_track_stats.get()); + video_track_stats->remote_source = true; + video_track_stats->detached = false; + if (video_receiver_info.frame_width > 0 && + video_receiver_info.frame_height > 0) { + video_track_stats->frame_width = static_cast( + video_receiver_info.frame_width); + video_track_stats->frame_height = static_cast( + video_receiver_info.frame_height); + } + return video_track_stats; +} + void ProduceMediaStreamAndTrackStats( int64_t timestamp_us, + const TrackMediaInfoMap& track_media_info_map, rtc::scoped_refptr streams, bool is_local, RTCStatsReport* report) { @@ -344,73 +462,71 @@ void ProduceMediaStreamAndTrackStats( stream->label(), timestamp_us)); stream_stats->stream_identifier = stream->label(); stream_stats->track_ids = std::vector(); - // Audio Tracks - for (const rtc::scoped_refptr& audio_track : - stream->GetAudioTracks()) { - std::string id = RTCMediaStreamTrackStatsIDFromTrackID( - audio_track->id(), is_local); - if (report->Get(id)) { - // Skip track, stats already exist for it. - continue; - } - std::unique_ptr audio_track_stats( - new RTCMediaStreamTrackStats(id, timestamp_us, - RTCMediaStreamTrackKind::kAudio)); - stream_stats->track_ids->push_back(audio_track_stats->id()); - SetMediaStreamTrackStatsFromMediaStreamTrackInterface( - *audio_track.get(), - audio_track_stats.get()); - audio_track_stats->remote_source = !is_local; - audio_track_stats->detached = false; - int signal_level; - if (audio_track->GetSignalLevel(&signal_level)) { - // Convert signal level from [0,32767] int to [0,1] double. - RTC_DCHECK_GE(signal_level, 0); - RTC_DCHECK_LE(signal_level, 32767); - audio_track_stats->audio_level = signal_level / 32767.0; - } - if (audio_track->GetAudioProcessor()) { - AudioProcessorInterface::AudioProcessorStats audio_processor_stats; - audio_track->GetAudioProcessor()->GetStats(&audio_processor_stats); - if (audio_processor_stats.echo_return_loss != -100) { - audio_track_stats->echo_return_loss = static_cast( - audio_processor_stats.echo_return_loss); + // The track stats are per-attachment to the connection. There can be one + // for receiving (remote) tracks and multiple attachments for sending + // (local) tracks. + if (is_local) { + // Local Audio Tracks + for (const rtc::scoped_refptr& audio_track : + stream->GetAudioTracks()) { + const std::vector* voice_sender_infos = + track_media_info_map.GetVoiceSenderInfos(*audio_track); + if (!voice_sender_infos) { + continue; } - if (audio_processor_stats.echo_return_loss_enhancement != -100) { - audio_track_stats->echo_return_loss_enhancement = static_cast( - audio_processor_stats.echo_return_loss_enhancement); + for (const auto& voice_sender_info : *voice_sender_infos) { + std::unique_ptr audio_track_stats = + ProduceMediaStreamTrackStatsFromVoiceSenderInfo( + timestamp_us, *audio_track, *voice_sender_info); + stream_stats->track_ids->push_back(audio_track_stats->id()); + report->AddStats(std::move(audio_track_stats)); } } - report->AddStats(std::move(audio_track_stats)); - } - // Video Tracks - for (const rtc::scoped_refptr& video_track : - stream->GetVideoTracks()) { - std::string id = RTCMediaStreamTrackStatsIDFromTrackID( - video_track->id(), is_local); - if (report->Get(id)) { - // Skip track, stats already exist for it. - continue; - } - std::unique_ptr video_track_stats( - new RTCMediaStreamTrackStats(id, timestamp_us, - RTCMediaStreamTrackKind::kVideo)); - stream_stats->track_ids->push_back(video_track_stats->id()); - SetMediaStreamTrackStatsFromMediaStreamTrackInterface( - *video_track.get(), - video_track_stats.get()); - video_track_stats->remote_source = !is_local; - video_track_stats->detached = false; - if (video_track->GetSource()) { - VideoTrackSourceInterface::Stats video_track_source_stats; - if (video_track->GetSource()->GetStats(&video_track_source_stats)) { - video_track_stats->frame_width = static_cast( - video_track_source_stats.input_width); - video_track_stats->frame_height = static_cast( - video_track_source_stats.input_height); + // Local Video Tracks + for (const rtc::scoped_refptr& video_track : + stream->GetVideoTracks()) { + const std::vector* video_sender_infos = + track_media_info_map.GetVideoSenderInfos(*video_track); + if (!video_sender_infos) { + continue; + } + for (const auto& video_sender_info : *video_sender_infos) { + std::unique_ptr video_track_stats = + ProduceMediaStreamTrackStatsFromVideoSenderInfo( + timestamp_us, *video_track, *video_sender_info); + stream_stats->track_ids->push_back(video_track_stats->id()); + report->AddStats(std::move(video_track_stats)); } } - report->AddStats(std::move(video_track_stats)); + } else { + // Remote Audio Tracks + for (const rtc::scoped_refptr& audio_track : + stream->GetAudioTracks()) { + const cricket::VoiceReceiverInfo* voice_receiver_info = + track_media_info_map.GetVoiceReceiverInfo(*audio_track); + if (!voice_receiver_info) { + continue; + } + std::unique_ptr audio_track_stats = + ProduceMediaStreamTrackStatsFromVoiceReceiverInfo( + timestamp_us, *audio_track, *voice_receiver_info); + stream_stats->track_ids->push_back(audio_track_stats->id()); + report->AddStats(std::move(audio_track_stats)); + } + // Remote Video Tracks + for (const rtc::scoped_refptr& video_track : + stream->GetVideoTracks()) { + const cricket::VideoReceiverInfo* video_receiver_info = + track_media_info_map.GetVideoReceiverInfo(*video_track); + if (!video_receiver_info) { + continue; + } + std::unique_ptr video_track_stats = + ProduceMediaStreamTrackStatsFromVideoReceiverInfo( + timestamp_us, *video_track, *video_receiver_info); + stream_stats->track_ids->push_back(video_track_stats->id()); + report->AddStats(std::move(video_track_stats)); + } } report->AddStats(std::move(stream_stats)); } @@ -749,10 +865,17 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n( void RTCStatsCollector::ProduceMediaStreamAndTrackStats_s( int64_t timestamp_us, RTCStatsReport* report) const { RTC_DCHECK(signaling_thread_->IsCurrent()); - ProduceMediaStreamAndTrackStats( - timestamp_us, pc_->local_streams(), true, report); - ProduceMediaStreamAndTrackStats( - timestamp_us, pc_->remote_streams(), false, report); + RTC_DCHECK(track_media_info_map_); + ProduceMediaStreamAndTrackStats(timestamp_us, + *track_media_info_map_, + pc_->local_streams(), + true, + report); + ProduceMediaStreamAndTrackStats(timestamp_us, + *track_media_info_map_, + pc_->remote_streams(), + false, + report); } void RTCStatsCollector::ProducePeerConnectionStats_s( @@ -795,8 +918,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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); + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + false, + MediaStreamTrackInterface::kAudioKind, + track_to_id_.find(audio_track.get())->second, + voice_receiver_info.ssrc()); } inbound_audio->transport_id = transport_id; if (voice_receiver_info.codec_payload_type) { @@ -825,8 +951,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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); + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + true, + MediaStreamTrackInterface::kAudioKind, + track_to_id_.find(audio_track.get())->second, + voice_sender_info.ssrc()); } outbound_audio->transport_id = transport_id; if (voice_sender_info.codec_payload_type) { @@ -861,8 +990,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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); + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + false, + MediaStreamTrackInterface::kVideoKind, + track_to_id_.find(video_track.get())->second, + video_receiver_info.ssrc()); } inbound_video->transport_id = transport_id; if (video_receiver_info.codec_payload_type) { @@ -891,8 +1023,11 @@ void RTCStatsCollector::ProduceRTPStreamStats_n( 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); + RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc( + true, + MediaStreamTrackInterface::kVideoKind, + track_to_id_.find(video_track.get())->second, + video_sender_info.ssrc()); } outbound_video->transport_id = transport_id; if (video_sender_info.codec_payload_type) { diff --git a/webrtc/api/rtcstatscollector_unittest.cc b/webrtc/api/rtcstatscollector_unittest.cc index 0ba9abff85..cf6dcf6ec1 100644 --- a/webrtc/api/rtcstatscollector_unittest.cc +++ b/webrtc/api/rtcstatscollector_unittest.cc @@ -10,6 +10,7 @@ #include "webrtc/api/rtcstatscollector.h" +#include #include #include #include @@ -170,44 +171,20 @@ std::unique_ptr CreateFakeCandidate( return candidate; } -class FakeAudioProcessorForStats - : public rtc::RefCountedObject { - public: - FakeAudioProcessorForStats( - AudioProcessorInterface::AudioProcessorStats stats) - : stats_(stats) { - } - - void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override { - *stats = stats_; - } - - private: - AudioProcessorInterface::AudioProcessorStats stats_; -}; - class FakeAudioTrackForStats : public MediaStreamTrack { public: static rtc::scoped_refptr Create( const std::string& id, - MediaStreamTrackInterface::TrackState state, - int signal_level, - rtc::scoped_refptr processor) { + MediaStreamTrackInterface::TrackState state) { rtc::scoped_refptr audio_track_stats( - new rtc::RefCountedObject( - id, signal_level, processor)); + new rtc::RefCountedObject(id)); audio_track_stats->set_state(state); return audio_track_stats; } - FakeAudioTrackForStats( - const std::string& id, - int signal_level, - rtc::scoped_refptr processor) - : MediaStreamTrack(id), - signal_level_(signal_level), - processor_(processor) { + FakeAudioTrackForStats(const std::string& id) + : MediaStreamTrack(id) { } std::string kind() const override { @@ -216,47 +193,10 @@ class FakeAudioTrackForStats webrtc::AudioSourceInterface* GetSource() const override { return nullptr; } void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} - bool GetSignalLevel(int* level) override { - *level = signal_level_; - return true; - } + bool GetSignalLevel(int* level) override { return false; } rtc::scoped_refptr GetAudioProcessor() override { - return processor_; + return nullptr; } - - private: - int signal_level_; - rtc::scoped_refptr processor_; -}; - -class FakeVideoTrackSourceForStats - : public rtc::RefCountedObject { - public: - FakeVideoTrackSourceForStats(VideoTrackSourceInterface::Stats stats) - : stats_(stats) { - } - - MediaSourceInterface::SourceState state() const override { - return MediaSourceInterface::kLive; - } - bool remote() const override { return false; } - void RegisterObserver(ObserverInterface* observer) override {} - void UnregisterObserver(ObserverInterface* observer) override {} - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override {} - void RemoveSink(rtc::VideoSinkInterface* sink) override { - } - bool is_screencast() const override { return false; } - rtc::Optional needs_denoising() const override { - return rtc::Optional(); - } - bool GetStats(VideoTrackSourceInterface::Stats* stats) override { - *stats = stats_; - return true; - } - - private: - VideoTrackSourceInterface::Stats stats_; }; class FakeVideoTrackForStats @@ -264,52 +204,72 @@ class FakeVideoTrackForStats public: static rtc::scoped_refptr Create( const std::string& id, - MediaStreamTrackInterface::TrackState state, - rtc::scoped_refptr source) { + MediaStreamTrackInterface::TrackState state) { rtc::scoped_refptr video_track( - new rtc::RefCountedObject(id, source)); + new rtc::RefCountedObject(id)); video_track->set_state(state); return video_track; } - FakeVideoTrackForStats( - const std::string& id, - rtc::scoped_refptr source) - : MediaStreamTrack(id), - source_(source) { + FakeVideoTrackForStats(const std::string& id) + : MediaStreamTrack(id) { } std::string kind() const override { return MediaStreamTrackInterface::kVideoKind; } - VideoTrackSourceInterface* GetSource() const override { - return source_; - } - - private: - rtc::scoped_refptr source_; + VideoTrackSourceInterface* GetSource() const override { return nullptr; } }; rtc::scoped_refptr CreateFakeTrack( cricket::MediaType media_type, - const std::string& track_id) { + const std::string& track_id, + MediaStreamTrackInterface::TrackState track_state) { if (media_type == cricket::MEDIA_TYPE_AUDIO) { - return FakeAudioTrackForStats::Create( - track_id, - MediaStreamTrackInterface::TrackState::kLive, - 32767, - new FakeAudioProcessorForStats( - AudioProcessorInterface::AudioProcessorStats())); + return FakeAudioTrackForStats::Create(track_id, track_state); } else { RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO); - return FakeVideoTrackForStats::Create( - track_id, - MediaStreamTrackInterface::TrackState::kLive, - new FakeVideoTrackSourceForStats( - VideoTrackSourceInterface::Stats())); + return FakeVideoTrackForStats::Create(track_id, track_state); } } +rtc::scoped_refptr CreateMockSender( + rtc::scoped_refptr track, uint32_t ssrc) { + 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( + track->kind() == MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO)); + EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke( + [ssrc]() { + RtpParameters params; + params.encodings.push_back(RtpEncodingParameters()); + params.encodings[0].ssrc = rtc::Optional(ssrc); + return params; + })); + return sender; +} + +rtc::scoped_refptr CreateMockReceiver( + rtc::scoped_refptr track, uint32_t ssrc) { + rtc::scoped_refptr receiver( + new rtc::RefCountedObject()); + EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); + EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return( + track->kind() == MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO)); + EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke( + [ssrc]() { + RtpParameters params; + params.encodings.push_back(RtpEncodingParameters()); + params.encodings[0].ssrc = rtc::Optional(ssrc); + return params; + })); + return receiver; +} + class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { public: RTCStatsCollectorTestHelper() @@ -377,25 +337,16 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { rtc::scoped_refptr track; if (media_type == cricket::MEDIA_TYPE_AUDIO) { - track = CreateFakeTrack(media_type, track_id); + track = CreateFakeTrack(media_type, track_id, + MediaStreamTrackInterface::kLive); local_stream->AddTrack(static_cast(track.get())); } else { - track = CreateFakeTrack(media_type, track_id); + track = CreateFakeTrack(media_type, track_id, + MediaStreamTrackInterface::kLive); 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; - })); + rtc::scoped_refptr sender = CreateMockSender(track, ssrc); EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( std::vector>({ rtc::scoped_refptr(sender.get()) }))); @@ -415,29 +366,123 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { rtc::scoped_refptr track; if (media_type == cricket::MEDIA_TYPE_AUDIO) { - track = CreateFakeTrack(media_type, track_id); + track = CreateFakeTrack(media_type, track_id, + MediaStreamTrackInterface::kLive); remote_stream->AddTrack(static_cast(track.get())); } else { - track = CreateFakeTrack(media_type, track_id); + track = CreateFakeTrack(media_type, track_id, + MediaStreamTrackInterface::kLive); 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; - })); + rtc::scoped_refptr receiver = + CreateMockReceiver(track, ssrc); EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( std::vector>({ rtc::scoped_refptr(receiver.get()) }))); } + // Attaches tracks to peer connections by configuring RTP senders and RTP + // receivers according to the tracks' pairings with + // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be + // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only + // be associated with one |[Voice/Video]ReceiverInfo|. + void CreateMockRtpSendersReceiversAndChannels( + std::initializer_list> local_audio_track_info_pairs, + std::initializer_list> remote_audio_track_info_pairs, + std::initializer_list> local_video_track_info_pairs, + std::initializer_list> remote_video_track_info_pairs) { + voice_media_info_.reset(new cricket::VoiceMediaInfo()); + video_media_info_.reset(new cricket::VideoMediaInfo()); + rtp_senders_.clear(); + rtp_receivers_.clear(); + // Local audio tracks and voice sender infos + for (auto& pair : local_audio_track_info_pairs) { + MediaStreamTrackInterface* local_audio_track = pair.first; + const cricket::VoiceSenderInfo& voice_sender_info = pair.second; + RTC_DCHECK_EQ(local_audio_track->kind(), + MediaStreamTrackInterface::kAudioKind); + + voice_media_info_->senders.push_back(voice_sender_info); + rtc::scoped_refptr rtp_sender = + CreateMockSender(rtc::scoped_refptr( + local_audio_track), + voice_sender_info.local_stats[0].ssrc); + rtp_senders_.push_back(rtc::scoped_refptr( + rtp_sender.get())); + } + // Remote audio tracks and voice receiver infos + for (auto& pair : remote_audio_track_info_pairs) { + MediaStreamTrackInterface* remote_audio_track = pair.first; + const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second; + RTC_DCHECK_EQ(remote_audio_track->kind(), + 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); + rtp_receivers_.push_back(rtc::scoped_refptr( + rtp_receiver.get())); + } + // Local video tracks and video sender infos + for (auto& pair : local_video_track_info_pairs) { + MediaStreamTrackInterface* local_video_track = pair.first; + const cricket::VideoSenderInfo& video_sender_info = pair.second; + RTC_DCHECK_EQ(local_video_track->kind(), + MediaStreamTrackInterface::kVideoKind); + + video_media_info_->senders.push_back(video_sender_info); + rtc::scoped_refptr rtp_sender = + CreateMockSender(rtc::scoped_refptr( + local_video_track), + video_sender_info.local_stats[0].ssrc); + rtp_senders_.push_back(rtc::scoped_refptr( + rtp_sender.get())); + } + // Remote video tracks and video receiver infos + for (auto& pair : remote_video_track_info_pairs) { + MediaStreamTrackInterface* remote_video_track = pair.first; + const cricket::VideoReceiverInfo& video_receiver_info = pair.second; + RTC_DCHECK_EQ(remote_video_track->kind(), + 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); + rtp_receivers_.push_back(rtc::scoped_refptr( + rtp_receiver.get())); + } + EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return(rtp_senders_)); + EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return(rtp_receivers_)); + + MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); + voice_channel_.reset(new cricket::VoiceChannel( + worker_thread_, network_thread_, nullptr, media_engine_, + voice_media_channel, "VoiceContentName", kDefaultRtcpMuxRequired, + kDefaultSrtpRequired)); + EXPECT_CALL(session_, voice_channel()) + .WillRepeatedly(Return(voice_channel_.get())); + EXPECT_CALL(*voice_media_channel, GetStats(_)) + .WillOnce(DoAll(SetArgPointee<0>(*voice_media_info_), Return(true))); + + MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); + video_channel_.reset(new cricket::VideoChannel( + worker_thread_, network_thread_, nullptr, video_media_channel, + "VideoContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired)); + EXPECT_CALL(session_, video_channel()) + .WillRepeatedly(Return(video_channel_.get())); + EXPECT_CALL(*video_media_channel, GetStats(_)) + .WillOnce(DoAll(SetArgPointee<0>(*video_media_info_), Return(true))); + } + private: rtc::ScopedFakeClock fake_clock_; RtcEventLogNullImpl event_log_; @@ -451,6 +496,12 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { MockPeerConnection pc_; std::vector> data_channels_; + std::unique_ptr voice_channel_; + std::unique_ptr video_channel_; + std::unique_ptr voice_media_info_; + std::unique_ptr video_media_info_; + std::vector> rtp_senders_; + std::vector> rtp_receivers_; }; class RTCTestStats : public RTCStats { @@ -1333,37 +1384,54 @@ TEST_F(RTCStatsCollectorTest, remote_streams->AddStream(remote_stream); // Local audio track - AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats; - local_audio_processor_stats.echo_return_loss = 42; - local_audio_processor_stats.echo_return_loss_enhancement = 52; - rtc::scoped_refptr local_audio_track = - FakeAudioTrackForStats::Create( - "LocalAudioTrackID", - MediaStreamTrackInterface::TrackState::kEnded, - 32767, - new FakeAudioProcessorForStats(local_audio_processor_stats)); - local_stream->AddTrack(local_audio_track); + rtc::scoped_refptr local_audio_track = + CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", + MediaStreamTrackInterface::kEnded); + local_stream->AddTrack(static_cast( + local_audio_track.get())); + + cricket::VoiceSenderInfo voice_sender_info_ssrc1; + voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo()); + voice_sender_info_ssrc1.local_stats[0].ssrc = 1; + voice_sender_info_ssrc1.audio_level = 32767; + voice_sender_info_ssrc1.echo_return_loss = 42; + voice_sender_info_ssrc1.echo_return_loss_enhancement = 52; + + // Uses default values, the corresponding stats object should contain + // undefined members. + cricket::VoiceSenderInfo voice_sender_info_ssrc2; + voice_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); + voice_sender_info_ssrc2.local_stats[0].ssrc = 2; + voice_sender_info_ssrc2.audio_level = 0; + voice_sender_info_ssrc2.echo_return_loss = -100; + voice_sender_info_ssrc2.echo_return_loss_enhancement = -100; // Remote audio track - AudioProcessorInterface::AudioProcessorStats remote_audio_processor_stats; - remote_audio_processor_stats.echo_return_loss = 13; - remote_audio_processor_stats.echo_return_loss_enhancement = 37; - rtc::scoped_refptr remote_audio_track = - FakeAudioTrackForStats::Create( - "RemoteAudioTrackID", - MediaStreamTrackInterface::TrackState::kLive, - 0, - new FakeAudioProcessorForStats(remote_audio_processor_stats)); - remote_stream->AddTrack(remote_audio_track); + rtc::scoped_refptr remote_audio_track = + CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", + MediaStreamTrackInterface::kLive); + remote_stream->AddTrack(static_cast( + remote_audio_track.get())); + + cricket::VoiceReceiverInfo voice_receiver_info; + voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo()); + voice_receiver_info.local_stats[0].ssrc = 3; + voice_receiver_info.audio_level = 16383; + + test_->CreateMockRtpSendersReceiversAndChannels( + { std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1), + std::make_pair(local_audio_track.get(), voice_sender_info_ssrc2) }, + { std::make_pair(remote_audio_track.get(), voice_receiver_info) }, + {}, {}); rtc::scoped_refptr report = GetStatsReport(); RTCMediaStreamStats expected_local_stream( "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); expected_local_stream.stream_identifier = local_stream->label(); - expected_local_stream.track_ids = std::vector(); - expected_local_stream.track_ids->push_back( - "RTCMediaStreamTrack_local_LocalAudioTrackID"); + expected_local_stream.track_ids = std::vector( + { "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2" }); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1372,86 +1440,57 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamStats expected_remote_stream( "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); expected_remote_stream.stream_identifier = remote_stream->label(); - expected_remote_stream.track_ids = std::vector(); - expected_remote_stream.track_ids->push_back( - "RTCMediaStreamTrack_remote_RemoteAudioTrackID"); + expected_remote_stream.track_ids = std::vector({ + "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3" }); 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_local_LocalAudioTrackID", report->timestamp_us(), - RTCMediaStreamTrackKind::kAudio); - expected_local_audio_track.track_identifier = local_audio_track->id(); - expected_local_audio_track.remote_source = false; - expected_local_audio_track.ended = true; - expected_local_audio_track.detached = false; - expected_local_audio_track.audio_level = 1.0; - expected_local_audio_track.echo_return_loss = 42.0; - expected_local_audio_track.echo_return_loss_enhancement = 52.0; - ASSERT_TRUE(report->Get(expected_local_audio_track.id())); - EXPECT_EQ(expected_local_audio_track, - report->Get(expected_local_audio_track.id())->cast_to< + RTCMediaStreamTrackStats expected_local_audio_track_ssrc1( + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", + report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); + expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id(); + expected_local_audio_track_ssrc1.remote_source = false; + expected_local_audio_track_ssrc1.ended = true; + expected_local_audio_track_ssrc1.detached = false; + expected_local_audio_track_ssrc1.audio_level = 1.0; + expected_local_audio_track_ssrc1.echo_return_loss = 42.0; + expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0; + ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id())); + EXPECT_EQ(expected_local_audio_track_ssrc1, + report->Get(expected_local_audio_track_ssrc1.id())->cast_to< + RTCMediaStreamTrackStats>()); + + RTCMediaStreamTrackStats expected_local_audio_track_ssrc2( + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2", + report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); + expected_local_audio_track_ssrc2.track_identifier = local_audio_track->id(); + expected_local_audio_track_ssrc2.remote_source = false; + expected_local_audio_track_ssrc2.ended = true; + expected_local_audio_track_ssrc2.detached = false; + expected_local_audio_track_ssrc2.audio_level = 0.0; + // Should be undefined: |expected_local_audio_track_ssrc2.echo_return_loss| + // and |expected_local_audio_track_ssrc2.echo_return_loss_enhancement|. + ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc2.id())); + EXPECT_EQ(expected_local_audio_track_ssrc2, + report->Get(expected_local_audio_track_ssrc2.id())->cast_to< RTCMediaStreamTrackStats>()); RTCMediaStreamTrackStats expected_remote_audio_track( - "RTCMediaStreamTrack_remote_RemoteAudioTrackID", report->timestamp_us(), - RTCMediaStreamTrackKind::kAudio); + "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3", + report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); expected_remote_audio_track.track_identifier = remote_audio_track->id(); expected_remote_audio_track.remote_source = true; expected_remote_audio_track.ended = false; expected_remote_audio_track.detached = false; - expected_remote_audio_track.audio_level = 0.0; - expected_remote_audio_track.echo_return_loss = 13.0; - expected_remote_audio_track.echo_return_loss_enhancement = 37.0; + expected_remote_audio_track.audio_level = 16383.0 / 32767.0; ASSERT_TRUE(report->Get(expected_remote_audio_track.id())); EXPECT_EQ(expected_remote_audio_track, report->Get(expected_remote_audio_track.id())->cast_to< RTCMediaStreamTrackStats>()); } -TEST_F(RTCStatsCollectorTest, - CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio_Defaults) { - rtc::scoped_refptr local_streams = - StreamCollection::Create(); - EXPECT_CALL(test_->pc(), local_streams()) - .WillRepeatedly(Return(local_streams)); - - rtc::scoped_refptr local_stream = - MediaStream::Create("LocalStreamLabel"); - local_streams->AddStream(local_stream); - - // Local audio track - AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats; - local_audio_processor_stats.echo_return_loss = -100; - local_audio_processor_stats.echo_return_loss_enhancement = -100; - rtc::scoped_refptr local_audio_track = - FakeAudioTrackForStats::Create( - "LocalAudioTrackID", - MediaStreamTrackInterface::TrackState::kEnded, - 32767, - new FakeAudioProcessorForStats(local_audio_processor_stats)); - local_stream->AddTrack(local_audio_track); - - rtc::scoped_refptr report = GetStatsReport(); - - RTCMediaStreamTrackStats expected_local_audio_track( - "RTCMediaStreamTrack_local_LocalAudioTrackID", report->timestamp_us(), - RTCMediaStreamTrackKind::kAudio); - expected_local_audio_track.track_identifier = local_audio_track->id(); - expected_local_audio_track.remote_source = false; - expected_local_audio_track.ended = true; - expected_local_audio_track.detached = false; - expected_local_audio_track.audio_level = 1.0; - // Should be undefined: |expected_local_audio_track.echo_return_loss| and - // |expected_local_audio_track.echo_return_loss_enhancement|. - ASSERT_TRUE(report->Get(expected_local_audio_track.id())); - EXPECT_EQ(expected_local_audio_track, - report->Get(expected_local_audio_track.id())->cast_to< - RTCMediaStreamTrackStats>()); -} - TEST_F(RTCStatsCollectorTest, CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) { rtc::scoped_refptr local_streams = @@ -1471,39 +1510,67 @@ TEST_F(RTCStatsCollectorTest, remote_streams->AddStream(remote_stream); // Local video track - VideoTrackSourceInterface::Stats local_video_track_source_stats; - local_video_track_source_stats.input_width = 1234; - local_video_track_source_stats.input_height = 4321; - rtc::scoped_refptr local_video_track_source = - new FakeVideoTrackSourceForStats(local_video_track_source_stats); - rtc::scoped_refptr local_video_track = - FakeVideoTrackForStats::Create( - "LocalVideoTrackID", - MediaStreamTrackInterface::TrackState::kLive, - local_video_track_source); - local_stream->AddTrack(local_video_track); + rtc::scoped_refptr local_video_track = + CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", + MediaStreamTrackInterface::kLive); + local_stream->AddTrack(static_cast( + local_video_track.get())); - // Remote video track - VideoTrackSourceInterface::Stats remote_video_track_source_stats; - remote_video_track_source_stats.input_width = 1234; - remote_video_track_source_stats.input_height = 4321; - rtc::scoped_refptr remote_video_track_source = - new FakeVideoTrackSourceForStats(remote_video_track_source_stats); - rtc::scoped_refptr remote_video_track = - FakeVideoTrackForStats::Create( - "RemoteVideoTrackID", - MediaStreamTrackInterface::TrackState::kEnded, - remote_video_track_source); - remote_stream->AddTrack(remote_video_track); + cricket::VideoSenderInfo video_sender_info_ssrc1; + video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo()); + video_sender_info_ssrc1.local_stats[0].ssrc = 1; + video_sender_info_ssrc1.send_frame_width = 1234; + video_sender_info_ssrc1.send_frame_height = 4321; + + cricket::VideoSenderInfo video_sender_info_ssrc2; + video_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); + video_sender_info_ssrc2.local_stats[0].ssrc = 2; + video_sender_info_ssrc2.send_frame_width = 4321; + video_sender_info_ssrc2.send_frame_height = 1234; + + // Remote video track with values + rtc::scoped_refptr remote_video_track_ssrc3 = + CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3", + MediaStreamTrackInterface::kEnded); + remote_stream->AddTrack(static_cast( + remote_video_track_ssrc3.get())); + + cricket::VideoReceiverInfo video_receiver_info_ssrc3; + video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo()); + video_receiver_info_ssrc3.local_stats[0].ssrc = 3; + video_receiver_info_ssrc3.frame_width = 6789; + video_receiver_info_ssrc3.frame_height = 9876; + + // Remote video track with undefined (default) values + rtc::scoped_refptr remote_video_track_ssrc4 = + CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID4", + MediaStreamTrackInterface::kLive); + remote_stream->AddTrack(static_cast( + remote_video_track_ssrc4.get())); + + cricket::VideoReceiverInfo video_receiver_info_ssrc4; + video_receiver_info_ssrc4.local_stats.push_back(cricket::SsrcReceiverInfo()); + video_receiver_info_ssrc4.local_stats[0].ssrc = 4; + video_receiver_info_ssrc4.frame_width = 0; + video_receiver_info_ssrc4.frame_height = 0; + + test_->CreateMockRtpSendersReceiversAndChannels( + {}, {}, + { std::make_pair(local_video_track.get(), video_sender_info_ssrc1), + std::make_pair(local_video_track.get(), video_sender_info_ssrc2) }, + { std::make_pair(remote_video_track_ssrc3.get(), + video_receiver_info_ssrc3), + std::make_pair(remote_video_track_ssrc4.get(), + video_receiver_info_ssrc4) }); rtc::scoped_refptr report = GetStatsReport(); RTCMediaStreamStats expected_local_stream( "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); expected_local_stream.stream_identifier = local_stream->label(); - expected_local_stream.track_ids = std::vector(); - expected_local_stream.track_ids->push_back( - "RTCMediaStreamTrack_local_LocalVideoTrackID"); + expected_local_stream.track_ids = std::vector({ + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2" }); ASSERT_TRUE(report->Get(expected_local_stream.id())); EXPECT_EQ(expected_local_stream, report->Get(expected_local_stream.id())->cast_to< @@ -1512,40 +1579,70 @@ TEST_F(RTCStatsCollectorTest, RTCMediaStreamStats expected_remote_stream( "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); expected_remote_stream.stream_identifier = remote_stream->label(); - expected_remote_stream.track_ids = std::vector(); - expected_remote_stream.track_ids->push_back( - "RTCMediaStreamTrack_remote_RemoteVideoTrackID"); + expected_remote_stream.track_ids = std::vector({ + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4" }); 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_local_LocalVideoTrackID", report->timestamp_us(), - RTCMediaStreamTrackKind::kVideo); - expected_local_video_track.track_identifier = local_video_track->id(); - expected_local_video_track.remote_source = false; - expected_local_video_track.ended = false; - expected_local_video_track.detached = false; - expected_local_video_track.frame_width = 1234; - expected_local_video_track.frame_height = 4321; - ASSERT_TRUE(report->Get(expected_local_video_track.id())); - EXPECT_EQ(expected_local_video_track, - report->Get(expected_local_video_track.id())->cast_to< + RTCMediaStreamTrackStats expected_local_video_track_ssrc1( + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", + report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); + expected_local_video_track_ssrc1.track_identifier = local_video_track->id(); + expected_local_video_track_ssrc1.remote_source = false; + expected_local_video_track_ssrc1.ended = false; + expected_local_video_track_ssrc1.detached = false; + expected_local_video_track_ssrc1.frame_width = 1234; + expected_local_video_track_ssrc1.frame_height = 4321; + ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id())); + EXPECT_EQ(expected_local_video_track_ssrc1, + report->Get(expected_local_video_track_ssrc1.id())->cast_to< RTCMediaStreamTrackStats>()); - RTCMediaStreamTrackStats expected_remote_video_track( - "RTCMediaStreamTrack_remote_RemoteVideoTrackID", report->timestamp_us(), - RTCMediaStreamTrackKind::kVideo); - expected_remote_video_track.track_identifier = remote_video_track->id(); - expected_remote_video_track.remote_source = true; - expected_remote_video_track.ended = true; - expected_remote_video_track.detached = false; - expected_remote_video_track.frame_width = 1234; - expected_remote_video_track.frame_height = 4321; - ASSERT_TRUE(report->Get(expected_remote_video_track.id())); - EXPECT_EQ(expected_remote_video_track, - report->Get(expected_remote_video_track.id())->cast_to< + RTCMediaStreamTrackStats expected_local_video_track_ssrc2( + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2", + report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); + expected_local_video_track_ssrc2.track_identifier = local_video_track->id(); + expected_local_video_track_ssrc2.remote_source = false; + expected_local_video_track_ssrc2.ended = false; + expected_local_video_track_ssrc2.detached = false; + expected_local_video_track_ssrc2.frame_width = 4321; + expected_local_video_track_ssrc2.frame_height = 1234; + ASSERT_TRUE(report->Get(expected_local_video_track_ssrc2.id())); + EXPECT_EQ(expected_local_video_track_ssrc2, + report->Get(expected_local_video_track_ssrc2.id())->cast_to< + RTCMediaStreamTrackStats>()); + + RTCMediaStreamTrackStats expected_remote_video_track_ssrc3( + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", + report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); + expected_remote_video_track_ssrc3.track_identifier = + remote_video_track_ssrc3->id(); + expected_remote_video_track_ssrc3.remote_source = true; + expected_remote_video_track_ssrc3.ended = true; + expected_remote_video_track_ssrc3.detached = false; + expected_remote_video_track_ssrc3.frame_width = 6789; + expected_remote_video_track_ssrc3.frame_height = 9876; + ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id())); + EXPECT_EQ(expected_remote_video_track_ssrc3, + report->Get(expected_remote_video_track_ssrc3.id())->cast_to< + RTCMediaStreamTrackStats>()); + + RTCMediaStreamTrackStats expected_remote_video_track_ssrc4( + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4", + report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); + expected_remote_video_track_ssrc4.track_identifier = + remote_video_track_ssrc4->id(); + expected_remote_video_track_ssrc4.remote_source = true; + expected_remote_video_track_ssrc4.ended = false; + expected_remote_video_track_ssrc4.detached = false; + // Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and + // |expected_remote_video_track_ssrc4.frame_height|. + ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id())); + EXPECT_EQ(expected_remote_video_track_ssrc4, + report->Get(expected_remote_video_track_ssrc4.id())->cast_to< RTCMediaStreamTrackStats>()); } @@ -1608,7 +1705,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.is_remote = false; expected_audio.media_type = "audio"; expected_audio.media_track_id = - "RTCMediaStreamTrack_remote_RemoteAudioTrackID"; + "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_1"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_InboundAudio_42"; @@ -1690,7 +1787,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { expected_video.is_remote = false; expected_video.media_type = "video"; expected_video.media_track_id = - "RTCMediaStreamTrack_remote_RemoteVideoTrackID"; + "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_1"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_InboundVideo_42"; @@ -1768,7 +1865,8 @@ 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.media_track_id = + "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1"; expected_audio.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; @@ -1846,7 +1944,8 @@ 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.media_track_id = + "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1"; expected_video.transport_id = "RTCTransport_TransportName_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); expected_video.codec_id = "RTCCodec_OutboundVideo_42";