From 09bc128603909680a3d9d09100d9be7d3f008036 Mon Sep 17 00:00:00 2001 From: hbos Date: Tue, 8 Nov 2016 06:29:22 -0800 Subject: [PATCH] RTCMediaStream[Track]Stats added. Not all members are collected by RTCStatsCollector and detached tracks are not visible in the returned stats. This needs to be addressed before closing crbug.com/660827 and crbug.com/659137 BUG=chromium:660827, chromium:659137, chromium:627816 Review-Url: https://codereview.webrtc.org/2467873005 Cr-Commit-Position: refs/heads/master@{#14978} --- webrtc/api/rtcstatscollector.cc | 111 ++++++++ webrtc/api/rtcstatscollector.h | 3 + webrtc/api/rtcstatscollector_unittest.cc | 326 ++++++++++++++++++++++- webrtc/api/stats/rtcstats_objects.h | 59 ++++ webrtc/api/test/mock_peerconnection.h | 4 + webrtc/stats/rtcstats_objects.cc | 100 +++++++ 6 files changed, 601 insertions(+), 2 deletions(-) diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc index b14b39670e..ce3176b94c 100644 --- a/webrtc/api/rtcstatscollector.cc +++ b/webrtc/api/rtcstatscollector.cc @@ -15,6 +15,8 @@ #include #include "webrtc/api/peerconnection.h" +#include "webrtc/api/peerconnectioninterface.h" +#include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/webrtcsession.h" #include "webrtc/base/checks.h" #include "webrtc/base/timeutils.h" @@ -37,6 +39,11 @@ std::string RTCIceCandidatePairStatsIDFromConnectionInfo( info.remote_candidate.id(); } +std::string RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( + const MediaStreamTrackInterface& track) { + return "RTCMediaStreamTrack_" + track.id(); +} + std::string RTCTransportStatsIDFromTransportChannel( const std::string& transport_name, int channel_component) { return "RTCTransport_" + transport_name + "_" + @@ -93,6 +100,13 @@ const char* DataStateToRTCDataChannelState( } } +void SetMediaStreamTrackStatsFromMediaStreamTrackInterface( + const MediaStreamTrackInterface& track, + RTCMediaStreamTrackStats* track_stats) { + track_stats->track_identifier = track.id(); + track_stats->ended = (track.state() == MediaStreamTrackInterface::kEnded); +} + void SetInboundRTPStreamStatsFromMediaReceiverInfo( const cricket::MediaReceiverInfo& media_receiver_info, RTCInboundRTPStreamStats* inbound_stats) { @@ -214,6 +228,93 @@ const std::string& ProduceIceCandidateStats( return stats->id(); } +void ProduceMediaStreamAndTrackStats( + int64_t timestamp_us, + rtc::scoped_refptr streams, + bool is_local, + RTCStatsReport* report) { + // TODO(hbos): When "AddTrack" is implemented we should iterate tracks to + // find which streams exist, not iterate streams to find tracks. + // crbug.com/659137 + // TODO(hbos): Return stats of detached tracks. We have to perform stats + // gathering at the time of detachment to get accurate stats and timestamps. + // crbug.com/659137 + if (!streams) + return; + for (size_t i = 0; i < streams->count(); ++i) { + MediaStreamInterface* stream = streams->at(i); + + std::unique_ptr stream_stats( + new RTCMediaStreamStats("RTCMediaStream_" + stream->label(), + timestamp_us)); + stream_stats->stream_identifier = stream->label(); + stream_stats->track_ids = std::vector(); + // Audio Tracks + for (rtc::scoped_refptr audio_track : + stream->GetAudioTracks()) { + std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( + *audio_track.get()); + if (report->Get(id)) { + // Skip track, stats already exist for it. + continue; + } + std::unique_ptr audio_track_stats( + new RTCMediaStreamTrackStats(id, timestamp_us)); + 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); + audio_track_stats->echo_return_loss = static_cast( + audio_processor_stats.echo_return_loss); + audio_track_stats->echo_return_loss_enhancement = static_cast( + audio_processor_stats.echo_return_loss_enhancement); + } + report->AddStats(std::move(audio_track_stats)); + } + // Video Tracks + for (rtc::scoped_refptr video_track : + stream->GetVideoTracks()) { + std::string id = RTCMediaStreamTrackStatsIDFromMediaStreamTrackInterface( + *video_track.get()); + if (report->Get(id)) { + // Skip track, stats already exist for it. + continue; + } + std::unique_ptr video_track_stats( + new RTCMediaStreamTrackStats(id, timestamp_us)); + 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); + } + } + report->AddStats(std::move(video_track_stats)); + } + report->AddStats(std::move(stream_stats)); + } +} + } // namespace rtc::scoped_refptr RTCStatsCollector::Create( @@ -301,6 +402,7 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread( timestamp_us, session_stats, transport_cert_stats, report.get()); } ProduceDataChannelStats_s(timestamp_us, report.get()); + ProduceMediaStreamAndTrackStats_s(timestamp_us, report.get()); ProducePeerConnectionStats_s(timestamp_us, report.get()); AddPartialResults(report); @@ -467,6 +569,15 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( } } +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); +} + void RTCStatsCollector::ProducePeerConnectionStats_s( int64_t timestamp_us, RTCStatsReport* report) const { RTC_DCHECK(signaling_thread_->IsCurrent()); diff --git a/webrtc/api/rtcstatscollector.h b/webrtc/api/rtcstatscollector.h index 2c160ee414..ae4ba19abc 100644 --- a/webrtc/api/rtcstatscollector.h +++ b/webrtc/api/rtcstatscollector.h @@ -98,6 +98,9 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface { void ProduceIceCandidateAndPairStats_s( int64_t timestamp_us, const SessionStats& session_stats, RTCStatsReport* report) const; + // Produces |RTCMediaStreamStats| and |RTCMediaStreamTrackStats|. + void ProduceMediaStreamAndTrackStats_s( + int64_t timestamp_us, RTCStatsReport* report) const; // Produces |RTCPeerConnectionStats|. void ProducePeerConnectionStats_s( int64_t timestamp_us, RTCStatsReport* report) const; diff --git a/webrtc/api/rtcstatscollector_unittest.cc b/webrtc/api/rtcstatscollector_unittest.cc index 808668b35c..adc1520a34 100644 --- a/webrtc/api/rtcstatscollector_unittest.cc +++ b/webrtc/api/rtcstatscollector_unittest.cc @@ -15,6 +15,8 @@ #include #include +#include "webrtc/api/mediastream.h" +#include "webrtc/api/mediastreamtrack.h" #include "webrtc/api/jsepsessiondescription.h" #include "webrtc/api/stats/rtcstats_objects.h" #include "webrtc/api/stats/rtcstatsreport.h" @@ -70,6 +72,14 @@ void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) { *os << stats.ToString(); } +void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) { + *os << stats.ToString(); +} + +void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) { + *os << stats.ToString(); +} + void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) { *os << stats.ToString(); } @@ -150,6 +160,126 @@ 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) { + rtc::scoped_refptr audio_track_stats( + new rtc::RefCountedObject( + id, signal_level, processor)); + 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) { + } + + std::string kind() const override { + return MediaStreamTrackInterface::kAudioKind; + } + 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; + } + rtc::scoped_refptr GetAudioProcessor() override { + return processor_; + } + + 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 + : public MediaStreamTrack { + public: + static rtc::scoped_refptr Create( + const std::string& id, + MediaStreamTrackInterface::TrackState state, + rtc::scoped_refptr source) { + rtc::scoped_refptr video_track( + new rtc::RefCountedObject(id, source)); + video_track->set_state(state); + return video_track; + } + + FakeVideoTrackForStats( + const std::string& id, + rtc::scoped_refptr source) + : MediaStreamTrack(id), + source_(source) { + } + + std::string kind() const override { + return MediaStreamTrackInterface::kVideoKind; + } + VideoTrackSourceInterface* GetSource() const override { + return source_; + } + + private: + rtc::scoped_refptr source_; +}; + class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { public: RTCStatsCollectorTestHelper() @@ -168,6 +298,8 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { session_(media_controller_.get()), pc_() { // Default return values for mocks. + 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_, sctp_data_channels()).WillRepeatedly( ReturnRef(data_channels_)); @@ -198,12 +330,12 @@ class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { private: rtc::ScopedFakeClock fake_clock_; - webrtc::RtcEventLogNullImpl event_log_; + RtcEventLogNullImpl event_log_; rtc::Thread* const worker_thread_; rtc::Thread* const network_thread_; cricket::FakeMediaEngine* media_engine_; std::unique_ptr channel_manager_; - std::unique_ptr media_controller_; + std::unique_ptr media_controller_; MockWebRtcSession session_; MockPeerConnection pc_; @@ -979,6 +1111,196 @@ TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) { } } +TEST_F(RTCStatsCollectorTest, + CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) { + rtc::scoped_refptr local_streams = + StreamCollection::Create(); + rtc::scoped_refptr remote_streams = + StreamCollection::Create(); + EXPECT_CALL(test_->pc(), local_streams()) + .WillRepeatedly(Return(local_streams)); + EXPECT_CALL(test_->pc(), remote_streams()) + .WillRepeatedly(Return(remote_streams)); + + rtc::scoped_refptr local_stream = + MediaStream::Create("LocalStreamLabel"); + local_streams->AddStream(local_stream); + rtc::scoped_refptr remote_stream = + MediaStream::Create("RemoteStreamLabel"); + 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); + + // 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 report = GetStatsReport(); + + RTCMediaStreamStats expected_local_stream( + "RTCMediaStream_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_LocalAudioTrackID"); + EXPECT_TRUE(report->Get(expected_local_stream.id())); + EXPECT_EQ(expected_local_stream, + report->Get(expected_local_stream.id())->cast_to< + RTCMediaStreamStats>()); + + RTCMediaStreamStats expected_remote_stream( + "RTCMediaStream_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_RemoteAudioTrackID"); + EXPECT_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()); + 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; + EXPECT_TRUE(report->Get(expected_local_audio_track.id())); + EXPECT_EQ(expected_local_audio_track, + report->Get(expected_local_audio_track.id())->cast_to< + RTCMediaStreamTrackStats>()); + + RTCMediaStreamTrackStats expected_remote_audio_track( + "RTCMediaStreamTrack_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; + 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; + EXPECT_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_Video) { + rtc::scoped_refptr local_streams = + StreamCollection::Create(); + rtc::scoped_refptr remote_streams = + StreamCollection::Create(); + EXPECT_CALL(test_->pc(), local_streams()) + .WillRepeatedly(Return(local_streams)); + EXPECT_CALL(test_->pc(), remote_streams()) + .WillRepeatedly(Return(remote_streams)); + + rtc::scoped_refptr local_stream = + MediaStream::Create("LocalStreamLabel"); + local_streams->AddStream(local_stream); + rtc::scoped_refptr remote_stream = + MediaStream::Create("RemoteStreamLabel"); + 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); + + // 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); + + rtc::scoped_refptr report = GetStatsReport(); + + RTCMediaStreamStats expected_local_stream( + "RTCMediaStream_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_LocalVideoTrackID"); + EXPECT_TRUE(report->Get(expected_local_stream.id())); + EXPECT_EQ(expected_local_stream, + report->Get(expected_local_stream.id())->cast_to< + RTCMediaStreamStats>()); + + RTCMediaStreamStats expected_remote_stream( + "RTCMediaStream_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_RemoteVideoTrackID"); + EXPECT_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()); + 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; + EXPECT_TRUE(report->Get(expected_local_video_track.id())); + EXPECT_EQ(expected_local_video_track, + report->Get(expected_local_video_track.id())->cast_to< + RTCMediaStreamTrackStats>()); + + RTCMediaStreamTrackStats expected_remote_video_track( + "RTCMediaStreamTrack_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; + expected_remote_video_track.detached = false; + expected_remote_video_track.frame_width = 1234; + expected_remote_video_track.frame_height = 4321; + EXPECT_TRUE(report->Get(expected_remote_video_track.id())); + EXPECT_EQ(expected_remote_video_track, + report->Get(expected_remote_video_track.id())->cast_to< + RTCMediaStreamTrackStats>()); +} + TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); cricket::VoiceChannel voice_channel( diff --git a/webrtc/api/stats/rtcstats_objects.h b/webrtc/api/stats/rtcstats_objects.h index 4788a14154..3263379e22 100644 --- a/webrtc/api/stats/rtcstats_objects.h +++ b/webrtc/api/stats/rtcstats_objects.h @@ -183,6 +183,65 @@ class RTCRemoteIceCandidateStats final : public RTCIceCandidateStats { const char* type() const override; }; +// https://w3c.github.io/webrtc-stats/#msstats-dict* +// TODO(hbos): Finish implementation. Tracking bug crbug.com/660827 +class RTCMediaStreamStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCMediaStreamStats(const std::string& id, int64_t timestamp_us); + RTCMediaStreamStats(std::string&& id, int64_t timestamp_us); + RTCMediaStreamStats(const RTCMediaStreamStats& other); + ~RTCMediaStreamStats() override; + + RTCStatsMember stream_identifier; + RTCStatsMember> track_ids; +}; + +// https://w3c.github.io/webrtc-stats/#mststats-dict* +// TODO(hbos): Finish implementation. Tracking bug crbug.com/659137 +class RTCMediaStreamTrackStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCMediaStreamTrackStats(const std::string& id, int64_t timestamp_us); + RTCMediaStreamTrackStats(std::string&& id, int64_t timestamp_us); + RTCMediaStreamTrackStats(const RTCMediaStreamTrackStats& other); + ~RTCMediaStreamTrackStats() override; + + RTCStatsMember track_identifier; + RTCStatsMember remote_source; + RTCStatsMember ended; + // TODO(hbos): |RTCStatsCollector| does not return stats for detached tracks. + // crbug.com/659137 + RTCStatsMember detached; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember> ssrc_ids; + // Video-only members + RTCStatsMember frame_width; + RTCStatsMember frame_height; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_per_second; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_sent; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_received; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_decoded; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_dropped; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_corrupted; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember partial_frames_lost; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember full_frames_lost; + // Audio-only members + RTCStatsMember audio_level; + RTCStatsMember echo_return_loss; + RTCStatsMember echo_return_loss_enhancement; +}; + // https://w3c.github.io/webrtc-stats/#pcstats-dict* // TODO(hbos): Finish implementation. Tracking bug crbug.com/636818 class RTCPeerConnectionStats final : public RTCStats { diff --git a/webrtc/api/test/mock_peerconnection.h b/webrtc/api/test/mock_peerconnection.h index 50e66185d4..7cc2b0dd92 100644 --- a/webrtc/api/test/mock_peerconnection.h +++ b/webrtc/api/test/mock_peerconnection.h @@ -28,6 +28,10 @@ class MockPeerConnection MockPeerConnection() : rtc::RefCountedObject( new FakePeerConnectionFactory()) {} + MOCK_METHOD0(local_streams, + rtc::scoped_refptr()); + MOCK_METHOD0(remote_streams, + rtc::scoped_refptr()); MOCK_METHOD0(session, WebRtcSession*()); MOCK_CONST_METHOD0(sctp_data_channels, const std::vector>&()); diff --git a/webrtc/stats/rtcstats_objects.cc b/webrtc/stats/rtcstats_objects.cc index 2523e36a88..54b587b129 100644 --- a/webrtc/stats/rtcstats_objects.cc +++ b/webrtc/stats/rtcstats_objects.cc @@ -267,6 +267,106 @@ const char* RTCRemoteIceCandidateStats::type() const { return kType; } +WEBRTC_RTCSTATS_IMPL(RTCMediaStreamStats, RTCStats, "stream", + &stream_identifier, + &track_ids); + +RTCMediaStreamStats::RTCMediaStreamStats( + const std::string& id, int64_t timestamp_us) + : RTCMediaStreamStats(std::string(id), timestamp_us) { +} + +RTCMediaStreamStats::RTCMediaStreamStats( + std::string&& id, int64_t timestamp_us) + : RTCStats(std::move(id), timestamp_us), + stream_identifier("streamIdentifier"), + track_ids("trackIds") { +} + +RTCMediaStreamStats::RTCMediaStreamStats( + const RTCMediaStreamStats& other) + : RTCStats(other.id(), other.timestamp_us()), + stream_identifier(other.stream_identifier), + track_ids(other.track_ids) { +} + +RTCMediaStreamStats::~RTCMediaStreamStats() { +} + +WEBRTC_RTCSTATS_IMPL(RTCMediaStreamTrackStats, RTCStats, "track", + &track_identifier, + &remote_source, + &ended, + &detached, + &ssrc_ids, + &frame_width, + &frame_height, + &frames_per_second, + &frames_sent, + &frames_received, + &frames_decoded, + &frames_dropped, + &frames_corrupted, + &partial_frames_lost, + &full_frames_lost, + &audio_level, + &echo_return_loss, + &echo_return_loss_enhancement); + +RTCMediaStreamTrackStats::RTCMediaStreamTrackStats( + const std::string& id, int64_t timestamp_us) + : RTCMediaStreamTrackStats(std::string(id), timestamp_us) { +} + +RTCMediaStreamTrackStats::RTCMediaStreamTrackStats( + std::string&& id, int64_t timestamp_us) + : RTCStats(std::move(id), timestamp_us), + track_identifier("trackIdentifier"), + remote_source("remoteSource"), + ended("ended"), + detached("detached"), + ssrc_ids("ssrcIds"), + frame_width("frameWidth"), + frame_height("frameHeight"), + frames_per_second("framesPerSecond"), + frames_sent("framesSent"), + frames_received("framesReceived"), + frames_decoded("framesDecoded"), + frames_dropped("framesDropped"), + frames_corrupted("framesCorrupted"), + partial_frames_lost("partialFramesLost"), + full_frames_lost("fullFramesLost"), + audio_level("audioLevel"), + echo_return_loss("echoReturnLoss"), + echo_return_loss_enhancement("echoReturnLossEnhancement") { +} + +RTCMediaStreamTrackStats::RTCMediaStreamTrackStats( + const RTCMediaStreamTrackStats& other) + : RTCStats(other.id(), other.timestamp_us()), + track_identifier(other.track_identifier), + remote_source(other.remote_source), + ended(other.ended), + detached(other.detached), + ssrc_ids(other.ssrc_ids), + frame_width(other.frame_width), + frame_height(other.frame_height), + frames_per_second(other.frames_per_second), + frames_sent(other.frames_sent), + frames_received(other.frames_received), + frames_decoded(other.frames_decoded), + frames_dropped(other.frames_dropped), + frames_corrupted(other.frames_corrupted), + partial_frames_lost(other.partial_frames_lost), + full_frames_lost(other.full_frames_lost), + audio_level(other.audio_level), + echo_return_loss(other.echo_return_loss), + echo_return_loss_enhancement(other.echo_return_loss_enhancement) { +} + +RTCMediaStreamTrackStats::~RTCMediaStreamTrackStats() { +} + WEBRTC_RTCSTATS_IMPL(RTCPeerConnectionStats, RTCStats, "peer-connection", &data_channels_opened, &data_channels_closed);