Index: webrtc/api/rtcstatscollector.cc |
diff --git a/webrtc/api/rtcstatscollector.cc b/webrtc/api/rtcstatscollector.cc |
index dc2b1896cc0ad1ad44630c1cbc8ccc1225e69338..543181ede46c232f01a3e2020c8fe754ae13afb5 100644 |
--- a/webrtc/api/rtcstatscollector.cc |
+++ b/webrtc/api/rtcstatscollector.cc |
@@ -17,6 +17,8 @@ |
#include "webrtc/api/peerconnection.h" |
#include "webrtc/api/webrtcsession.h" |
#include "webrtc/base/checks.h" |
+#include "webrtc/base/timeutils.h" |
+#include "webrtc/media/base/mediachannel.h" |
#include "webrtc/p2p/base/candidate.h" |
#include "webrtc/p2p/base/p2pconstants.h" |
#include "webrtc/p2p/base/port.h" |
@@ -41,6 +43,21 @@ std::string RTCTransportStatsIDFromTransportChannel( |
rtc::ToString<>(channel_component); |
} |
+std::string RTCTransportStatsIDFromBaseChannel( |
+ const ProxyTransportMap& proxy_to_transport, |
+ const cricket::BaseChannel& base_channel) { |
+ auto proxy_it = proxy_to_transport.find(base_channel.content_name()); |
+ if (proxy_it == proxy_to_transport.cend()) |
+ return ""; |
+ return RTCTransportStatsIDFromTransportChannel( |
+ proxy_it->second, cricket::ICE_CANDIDATE_COMPONENT_RTP); |
+} |
+ |
+std::string RTCOutboundRTPStreamStatsIDFromSSRC(bool audio, uint32_t ssrc) { |
+ return audio ? "RTCOutboundRTPAudioStream_" + rtc::ToString<>(ssrc) |
+ : "RTCOutboundRTPVideoStream_" + rtc::ToString<>(ssrc); |
+} |
+ |
const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { |
if (type == cricket::LOCAL_PORT_TYPE) |
return RTCIceCandidateType::kHost; |
@@ -71,6 +88,47 @@ const char* DataStateToRTCDataChannelState( |
} |
} |
+void SetOutboundRTPStreamStatsFromMediaSenderInfo( |
+ const cricket::MediaSenderInfo& media_sender_info, |
+ RTCOutboundRTPStreamStats* outbound_stats) { |
+ RTC_DCHECK(outbound_stats); |
+ outbound_stats->ssrc = rtc::ToString<>(media_sender_info.ssrc()); |
+ // TODO(hbos): Support the remote case. crbug.com/657856 |
+ outbound_stats->is_remote = false; |
+ // TODO(hbos): Set |codec_id| when we have |RTCCodecStats|. Maybe relevant: |
+ // |media_sender_info.codec_name|. crbug.com/657854, 657856, 659117 |
+ outbound_stats->packets_sent = |
+ static_cast<uint32_t>(media_sender_info.packets_sent); |
+ outbound_stats->bytes_sent = |
+ static_cast<uint64_t>(media_sender_info.bytes_sent); |
+ outbound_stats->round_trip_time = |
+ static_cast<double>(media_sender_info.rtt_ms) / rtc::kNumMillisecsPerSec; |
+} |
+ |
+void SetOutboundRTPStreamStatsFromVoiceSenderInfo( |
+ const cricket::VoiceSenderInfo& voice_sender_info, |
+ RTCOutboundRTPStreamStats* outbound_audio) { |
+ SetOutboundRTPStreamStatsFromMediaSenderInfo( |
+ voice_sender_info, outbound_audio); |
+ outbound_audio->media_type = "audio"; |
+ // |fir_count|, |pli_count| and |sli_count| are only valid for video and are |
+ // purposefully left undefined for audio. |
+} |
+ |
+void SetOutboundRTPStreamStatsFromVideoSenderInfo( |
+ const cricket::VideoSenderInfo& video_sender_info, |
+ RTCOutboundRTPStreamStats* outbound_video) { |
+ SetOutboundRTPStreamStatsFromMediaSenderInfo( |
+ video_sender_info, outbound_video); |
+ outbound_video->media_type = "video"; |
+ outbound_video->fir_count = |
+ static_cast<uint32_t>(video_sender_info.firs_rcvd); |
+ outbound_video->pli_count = |
+ static_cast<uint32_t>(video_sender_info.plis_rcvd); |
+ outbound_video->nack_count = |
+ static_cast<uint32_t>(video_sender_info.nacks_rcvd); |
+} |
+ |
void ProduceCertificateStatsFromSSLCertificateStats( |
int64_t timestamp_us, const rtc::SSLCertificateStats& certificate_stats, |
RTCStatsReport* report) { |
@@ -184,7 +242,8 @@ void RTCStatsCollector::ClearCachedStatsReport() { |
void RTCStatsCollector::ProducePartialResultsOnSignalingThread( |
int64_t timestamp_us) { |
RTC_DCHECK(signaling_thread_->IsCurrent()); |
- rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
+ rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create( |
+ timestamp_us); |
SessionStats session_stats; |
if (pc_->session()->GetTransportStats(&session_stats)) { |
@@ -195,6 +254,8 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread( |
timestamp_us, transport_cert_stats, report.get()); |
ProduceIceCandidateAndPairStats_s( |
timestamp_us, session_stats, report.get()); |
+ ProduceRTPStreamStats_s( |
+ timestamp_us, session_stats, report.get()); |
ProduceTransportStats_s( |
timestamp_us, session_stats, transport_cert_stats, report.get()); |
} |
@@ -207,9 +268,16 @@ void RTCStatsCollector::ProducePartialResultsOnSignalingThread( |
void RTCStatsCollector::ProducePartialResultsOnWorkerThread( |
int64_t timestamp_us) { |
RTC_DCHECK(worker_thread_->IsCurrent()); |
- rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
+ rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create( |
+ timestamp_us); |
// TODO(hbos): Gather stats on worker thread. |
+ // pc_->session()'s channels are owned by the signaling thread but there are |
+ // some stats that are gathered on the worker thread. Instead of a synchronous |
+ // invoke on "s->w" we could to the "w" work here asynchronously if it wasn't |
+ // for the ownership issue. Synchronous invokes in other places makes it |
+ // difficult to introduce locks without introducing deadlocks and the channels |
+ // are not reference counted. |
AddPartialResults(report); |
} |
@@ -217,9 +285,16 @@ void RTCStatsCollector::ProducePartialResultsOnWorkerThread( |
void RTCStatsCollector::ProducePartialResultsOnNetworkThread( |
int64_t timestamp_us) { |
RTC_DCHECK(network_thread_->IsCurrent()); |
- rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); |
+ rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create( |
+ timestamp_us); |
// TODO(hbos): Gather stats on network thread. |
+ // pc_->session()'s channels are owned by the signaling thread but there are |
+ // some stats that are gathered on the network thread. Instead of a |
+ // synchronous invoke on "s->n" we could to the "n" work here asynchronously |
+ // if it wasn't for the ownership issue. Synchronous invokes in other places |
+ // makes it difficult to introduce locks without introducing deadlocks and the |
+ // channels are not reference counted. |
AddPartialResults(report); |
} |
@@ -337,7 +412,7 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_s( |
// smoothed according to the spec. crbug.com/633550. See |
// https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-currentrtt |
candidate_pair_stats->current_rtt = |
- static_cast<double>(info.rtt) / 1000.0; |
+ static_cast<double>(info.rtt) / rtc::kNumMillisecsPerSec; |
candidate_pair_stats->requests_sent = |
static_cast<uint64_t>(info.sent_ping_requests_total); |
candidate_pair_stats->responses_received = |
@@ -374,6 +449,63 @@ void RTCStatsCollector::ProducePeerConnectionStats_s( |
report->AddStats(std::move(stats)); |
} |
+void RTCStatsCollector::ProduceRTPStreamStats_s( |
+ int64_t timestamp_us, const SessionStats& session_stats, |
+ RTCStatsReport* report) const { |
+ RTC_DCHECK(signaling_thread_->IsCurrent()); |
+ |
+ // Audio |
+ if (pc_->session()->voice_channel()) { |
+ cricket::VoiceMediaInfo voice_media_info; |
+ if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) { |
+ std::string transport_id = RTCTransportStatsIDFromBaseChannel( |
+ session_stats.proxy_to_transport, *pc_->session()->voice_channel()); |
+ for (const cricket::VoiceSenderInfo& voice_sender_info : |
+ voice_media_info.senders) { |
+ // TODO(nisse): SSRC == 0 currently means none. Delete check when that |
+ // is fixed. |
+ if (voice_sender_info.ssrc() == 0) |
+ continue; |
+ std::unique_ptr<RTCOutboundRTPStreamStats> outbound_audio( |
+ new RTCOutboundRTPStreamStats( |
+ RTCOutboundRTPStreamStatsIDFromSSRC( |
+ true, voice_sender_info.ssrc()), |
+ timestamp_us)); |
+ SetOutboundRTPStreamStatsFromVoiceSenderInfo( |
+ voice_sender_info, outbound_audio.get()); |
+ if (!transport_id.empty()) |
+ outbound_audio->transport_id = transport_id; |
+ report->AddStats(std::move(outbound_audio)); |
+ } |
+ } |
+ } |
+ // Video |
+ if (pc_->session()->video_channel()) { |
+ cricket::VideoMediaInfo video_media_info; |
+ if (pc_->session()->video_channel()->GetStats(&video_media_info)) { |
+ std::string transport_id = RTCTransportStatsIDFromBaseChannel( |
+ session_stats.proxy_to_transport, *pc_->session()->video_channel()); |
+ for (const cricket::VideoSenderInfo& video_sender_info : |
+ video_media_info.senders) { |
+ // TODO(nisse): SSRC == 0 currently means none. Delete check when that |
+ // is fixed. |
+ if (video_sender_info.ssrc() == 0) |
+ continue; |
+ std::unique_ptr<RTCOutboundRTPStreamStats> outbound_video( |
+ new RTCOutboundRTPStreamStats( |
+ RTCOutboundRTPStreamStatsIDFromSSRC( |
+ false, video_sender_info.ssrc()), |
+ timestamp_us)); |
+ SetOutboundRTPStreamStatsFromVideoSenderInfo( |
+ video_sender_info, outbound_video.get()); |
+ if (!transport_id.empty()) |
+ outbound_video->transport_id = transport_id; |
+ report->AddStats(std::move(outbound_video)); |
+ } |
+ } |
+ } |
+} |
+ |
void RTCStatsCollector::ProduceTransportStats_s( |
int64_t timestamp_us, const SessionStats& session_stats, |
const std::map<std::string, CertificateStatsPair>& transport_cert_stats, |