Index: webrtc/api/rtcstatscollector.cc |
diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc |
index b14b39670e61ce8d08bd71118c7b296ca3c5d7e7..ce3176b94c38f23276eb75631aa64ac6d3b61e73 100644 |
--- a/webrtc/api/rtcstatscollector.cc |
+++ b/webrtc/api/rtcstatscollector.cc |
@@ -15,6 +15,8 @@ |
#include <vector> |
#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<StreamCollectionInterface> 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<RTCMediaStreamStats> stream_stats( |
+ new RTCMediaStreamStats("RTCMediaStream_" + stream->label(), |
+ timestamp_us)); |
+ stream_stats->stream_identifier = stream->label(); |
+ stream_stats->track_ids = std::vector<std::string>(); |
+ // Audio Tracks |
+ for (rtc::scoped_refptr<AudioTrackInterface> 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<RTCMediaStreamTrackStats> 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<double>( |
+ audio_processor_stats.echo_return_loss); |
+ audio_track_stats->echo_return_loss_enhancement = static_cast<double>( |
+ audio_processor_stats.echo_return_loss_enhancement); |
+ } |
+ report->AddStats(std::move(audio_track_stats)); |
+ } |
+ // Video Tracks |
+ for (rtc::scoped_refptr<VideoTrackInterface> 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<RTCMediaStreamTrackStats> 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<uint32_t>( |
+ video_track_source_stats.input_width); |
+ video_track_stats->frame_height = static_cast<uint32_t>( |
+ video_track_source_stats.input_height); |
+ } |
+ } |
+ report->AddStats(std::move(video_track_stats)); |
+ } |
+ report->AddStats(std::move(stream_stats)); |
+ } |
+} |
+ |
} // namespace |
rtc::scoped_refptr<RTCStatsCollector> 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()); |