Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: webrtc/api/rtcstatscollector.cc

Issue 2456463002: RTCOutboundRTPStreamStats added. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/api/rtcstatscollector.h" 11 #include "webrtc/api/rtcstatscollector.h"
12 12
13 #include <memory> 13 #include <memory>
14 #include <utility> 14 #include <utility>
15 #include <vector> 15 #include <vector>
16 16
17 #include "webrtc/api/peerconnection.h" 17 #include "webrtc/api/peerconnection.h"
18 #include "webrtc/api/webrtcsession.h" 18 #include "webrtc/api/webrtcsession.h"
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/timeutils.h"
21 #include "webrtc/media/base/mediachannel.h"
20 #include "webrtc/p2p/base/candidate.h" 22 #include "webrtc/p2p/base/candidate.h"
21 #include "webrtc/p2p/base/p2pconstants.h" 23 #include "webrtc/p2p/base/p2pconstants.h"
22 #include "webrtc/p2p/base/port.h" 24 #include "webrtc/p2p/base/port.h"
23 25
24 namespace webrtc { 26 namespace webrtc {
25 27
26 namespace { 28 namespace {
27 29
28 std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) { 30 std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
29 return "RTCCertificate_" + fingerprint; 31 return "RTCCertificate_" + fingerprint;
30 } 32 }
31 33
32 std::string RTCIceCandidatePairStatsIDFromConnectionInfo( 34 std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
33 const cricket::ConnectionInfo& info) { 35 const cricket::ConnectionInfo& info) {
34 return "RTCIceCandidatePair_" + info.local_candidate.id() + "_" + 36 return "RTCIceCandidatePair_" + info.local_candidate.id() + "_" +
35 info.remote_candidate.id(); 37 info.remote_candidate.id();
36 } 38 }
37 39
38 std::string RTCTransportStatsIDFromTransportChannel( 40 std::string RTCTransportStatsIDFromTransportChannel(
39 const std::string& transport_name, int channel_component) { 41 const std::string& transport_name, int channel_component) {
40 return "RTCTransport_" + transport_name + "_" + 42 return "RTCTransport_" + transport_name + "_" +
41 rtc::ToString<>(channel_component); 43 rtc::ToString<>(channel_component);
42 } 44 }
43 45
46 std::string RTCTransportStatsIDFromBaseChannel(
47 const ProxyTransportMap& proxy_to_transport,
48 const cricket::BaseChannel& base_channel) {
49 auto proxy_it = proxy_to_transport.find(base_channel.content_name());
50 if (proxy_it == proxy_to_transport.cend())
51 return "";
52 return RTCTransportStatsIDFromTransportChannel(
53 proxy_it->second, cricket::ICE_CANDIDATE_COMPONENT_RTP);
54 }
55
56 std::string RTCOutboundRTPStreamStatsIDFromSSRC(bool audio, uint32_t ssrc) {
57 return audio ? "RTCOutboundRTPAudioStream_" + rtc::ToString<>(ssrc)
58 : "RTCOutboundRTPVideoStream_" + rtc::ToString<>(ssrc);
59 }
60
44 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) { 61 const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
45 if (type == cricket::LOCAL_PORT_TYPE) 62 if (type == cricket::LOCAL_PORT_TYPE)
46 return RTCIceCandidateType::kHost; 63 return RTCIceCandidateType::kHost;
47 if (type == cricket::STUN_PORT_TYPE) 64 if (type == cricket::STUN_PORT_TYPE)
48 return RTCIceCandidateType::kSrflx; 65 return RTCIceCandidateType::kSrflx;
49 if (type == cricket::PRFLX_PORT_TYPE) 66 if (type == cricket::PRFLX_PORT_TYPE)
50 return RTCIceCandidateType::kPrflx; 67 return RTCIceCandidateType::kPrflx;
51 if (type == cricket::RELAY_PORT_TYPE) 68 if (type == cricket::RELAY_PORT_TYPE)
52 return RTCIceCandidateType::kRelay; 69 return RTCIceCandidateType::kRelay;
53 RTC_NOTREACHED(); 70 RTC_NOTREACHED();
(...skipping 10 matching lines...) Expand all
64 case DataChannelInterface::kClosing: 81 case DataChannelInterface::kClosing:
65 return RTCDataChannelState::kClosing; 82 return RTCDataChannelState::kClosing;
66 case DataChannelInterface::kClosed: 83 case DataChannelInterface::kClosed:
67 return RTCDataChannelState::kClosed; 84 return RTCDataChannelState::kClosed;
68 default: 85 default:
69 RTC_NOTREACHED(); 86 RTC_NOTREACHED();
70 return nullptr; 87 return nullptr;
71 } 88 }
72 } 89 }
73 90
91 void SetOutboundRTPStreamStatsFromMediaSenderInfo(
92 const cricket::MediaSenderInfo& media_sender_info,
93 RTCOutboundRTPStreamStats* outbound_stats) {
94 RTC_DCHECK(outbound_stats);
95 outbound_stats->ssrc = rtc::ToString<>(media_sender_info.ssrc());
96 // TODO(hbos): Support the remote case. crbug.com/657856
97 outbound_stats->is_remote = false;
98 // TODO(hbos): Set |codec_id| when we have |RTCCodecStats|. Maybe relevant:
99 // |media_sender_info.codec_name|. crbug.com/657854, 657856, 659117
100 outbound_stats->packets_sent =
101 static_cast<uint32_t>(media_sender_info.packets_sent);
102 outbound_stats->bytes_sent =
103 static_cast<uint64_t>(media_sender_info.bytes_sent);
104 outbound_stats->round_trip_time =
105 static_cast<double>(media_sender_info.rtt_ms) / rtc::kNumMillisecsPerSec;
106 }
107
108 void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
109 const cricket::VoiceSenderInfo& voice_sender_info,
110 RTCOutboundRTPStreamStats* outbound_stats) {
111 SetOutboundRTPStreamStatsFromMediaSenderInfo(
112 voice_sender_info, outbound_stats);
113 outbound_stats->media_type = "audio";
114 // |fir_count|, |pli_count|, |nack_count| and |sli_count| are only valid for
115 // video and are purposefully left undefined for audio.
hbos 2016/10/26 10:26:11 Is this true? Even for NACK? FIR and SLI are docu
Taylor Brandstetter 2016/10/27 21:44:36 NACK seems relevant to audio, PLI doesn't. I'll ma
hbos 2016/10/28 09:42:37 Acknowledged.
116 }
117
118 void SetOutboundRTPStreamStatsFromVideoSenderInfo(
119 const cricket::VideoSenderInfo& video_sender_info,
120 RTCOutboundRTPStreamStats* outbound_stats) {
121 SetOutboundRTPStreamStatsFromMediaSenderInfo(
122 video_sender_info, outbound_stats);
123 outbound_stats->media_type = "video";
124 outbound_stats->fir_count =
125 static_cast<uint32_t>(video_sender_info.firs_rcvd);
126 outbound_stats->pli_count =
127 static_cast<uint32_t>(video_sender_info.plis_rcvd);
128 outbound_stats->nack_count =
129 static_cast<uint32_t>(video_sender_info.nacks_rcvd);
130 outbound_stats->target_bitrate =
131 static_cast<double>(video_sender_info.preferred_bitrate);
hbos 2016/10/26 10:26:11 Is this the correct value? There is also bandwidth
Taylor Brandstetter 2016/10/27 21:44:36 I came to the same conclusion; it should be target
hbos 2016/10/28 09:42:37 Done. Note that this means that all video-RTCOutbo
Taylor Brandstetter 2016/10/28 17:31:34 Wait, that doesn't seem right. I didn't realize ta
hbos 2016/10/31 09:21:01 That will be easy to surface but I'll do it in a s
132 }
133
74 } // namespace 134 } // namespace
75 135
76 rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create( 136 rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
77 PeerConnection* pc, int64_t cache_lifetime_us) { 137 PeerConnection* pc, int64_t cache_lifetime_us) {
78 return rtc::scoped_refptr<RTCStatsCollector>( 138 return rtc::scoped_refptr<RTCStatsCollector>(
79 new rtc::RefCountedObject<RTCStatsCollector>(pc, cache_lifetime_us)); 139 new rtc::RefCountedObject<RTCStatsCollector>(pc, cache_lifetime_us));
80 } 140 }
81 141
82 RTCStatsCollector::RTCStatsCollector(PeerConnection* pc, 142 RTCStatsCollector::RTCStatsCollector(PeerConnection* pc,
83 int64_t cache_lifetime_us) 143 int64_t cache_lifetime_us)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 } 193 }
134 194
135 void RTCStatsCollector::ClearCachedStatsReport() { 195 void RTCStatsCollector::ClearCachedStatsReport() {
136 RTC_DCHECK(signaling_thread_->IsCurrent()); 196 RTC_DCHECK(signaling_thread_->IsCurrent());
137 cached_report_ = nullptr; 197 cached_report_ = nullptr;
138 } 198 }
139 199
140 void RTCStatsCollector::ProducePartialResultsOnSignalingThread( 200 void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
141 int64_t timestamp_us) { 201 int64_t timestamp_us) {
142 RTC_DCHECK(signaling_thread_->IsCurrent()); 202 RTC_DCHECK(signaling_thread_->IsCurrent());
143 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); 203 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
204 timestamp_us);
144 205
145 SessionStats session_stats; 206 SessionStats session_stats;
146 if (pc_->session()->GetTransportStats(&session_stats)) { 207 if (pc_->session()->GetTransportStats(&session_stats)) {
147 std::map<std::string, CertificateStatsPair> transport_cert_stats = 208 std::map<std::string, CertificateStatsPair> transport_cert_stats =
148 PrepareTransportCertificateStats_s(session_stats); 209 PrepareTransportCertificateStats_s(session_stats);
149 210
150 ProduceCertificateStats_s( 211 ProduceCertificateStats_s(
151 timestamp_us, transport_cert_stats, report.get()); 212 timestamp_us, transport_cert_stats, report.get());
152 ProduceIceCandidateAndPairStats_s( 213 ProduceIceCandidateAndPairStats_s(
153 timestamp_us, session_stats, report.get()); 214 timestamp_us, session_stats, report.get());
215 ProduceRTPStreamStats_s(
216 timestamp_us, session_stats, report.get());
154 ProduceTransportStats_s( 217 ProduceTransportStats_s(
155 timestamp_us, session_stats, transport_cert_stats, report.get()); 218 timestamp_us, session_stats, transport_cert_stats, report.get());
156 } 219 }
157 ProduceDataChannelStats_s(timestamp_us, report.get()); 220 ProduceDataChannelStats_s(timestamp_us, report.get());
158 ProducePeerConnectionStats_s(timestamp_us, report.get()); 221 ProducePeerConnectionStats_s(timestamp_us, report.get());
159 222
160 AddPartialResults(report); 223 AddPartialResults(report);
161 } 224 }
162 225
163 void RTCStatsCollector::ProducePartialResultsOnWorkerThread( 226 void RTCStatsCollector::ProducePartialResultsOnWorkerThread(
164 int64_t timestamp_us) { 227 int64_t timestamp_us) {
165 RTC_DCHECK(worker_thread_->IsCurrent()); 228 RTC_DCHECK(worker_thread_->IsCurrent());
166 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); 229 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
230 timestamp_us);
167 231
168 // TODO(hbos): Gather stats on worker thread. 232 // TODO(hbos): Gather stats on worker thread.
233 // pc_->session()'s channels are owned by the signaling thread but there are
234 // some stats that are gathered on the worker thread. Instead of a synchronous
235 // invoke on "s->w" we could to the "w" work here asynchronously if it wasn't
236 // for the ownership issue. Synchronous invokes in other places makes it
237 // difficult to introduce locks without introducing deadlocks and the channels
238 // are not reference counted.
169 239
170 AddPartialResults(report); 240 AddPartialResults(report);
171 } 241 }
172 242
173 void RTCStatsCollector::ProducePartialResultsOnNetworkThread( 243 void RTCStatsCollector::ProducePartialResultsOnNetworkThread(
174 int64_t timestamp_us) { 244 int64_t timestamp_us) {
175 RTC_DCHECK(network_thread_->IsCurrent()); 245 RTC_DCHECK(network_thread_->IsCurrent());
176 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); 246 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(
247 timestamp_us);
177 248
178 // TODO(hbos): Gather stats on network thread. 249 // TODO(hbos): Gather stats on network thread.
250 // pc_->session()'s channels are owned by the signaling thread but there are
251 // some stats that are gathered on the network thread. Instead of a
252 // synchronous invoke on "s->n" we could to the "n" work here asynchronously
253 // if it wasn't for the ownership issue. Synchronous invokes in other places
254 // makes it difficult to introduce locks without introducing deadlocks and the
255 // channels are not reference counted.
179 256
180 AddPartialResults(report); 257 AddPartialResults(report);
181 } 258 }
182 259
183 void RTCStatsCollector::AddPartialResults( 260 void RTCStatsCollector::AddPartialResults(
184 const rtc::scoped_refptr<RTCStatsReport>& partial_report) { 261 const rtc::scoped_refptr<RTCStatsReport>& partial_report) {
185 if (!signaling_thread_->IsCurrent()) { 262 if (!signaling_thread_->IsCurrent()) {
186 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_, 263 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
187 rtc::Bind(&RTCStatsCollector::AddPartialResults_s, 264 rtc::Bind(&RTCStatsCollector::AddPartialResults_s,
188 rtc::scoped_refptr<RTCStatsCollector>(this), 265 rtc::scoped_refptr<RTCStatsCollector>(this),
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 // crbug.com/633550 382 // crbug.com/633550
306 candidate_pair_stats->writable = info.writable; 383 candidate_pair_stats->writable = info.writable;
307 candidate_pair_stats->bytes_sent = 384 candidate_pair_stats->bytes_sent =
308 static_cast<uint64_t>(info.sent_total_bytes); 385 static_cast<uint64_t>(info.sent_total_bytes);
309 candidate_pair_stats->bytes_received = 386 candidate_pair_stats->bytes_received =
310 static_cast<uint64_t>(info.recv_total_bytes); 387 static_cast<uint64_t>(info.recv_total_bytes);
311 // TODO(hbos): The |info.rtt| measurement is smoothed. It shouldn't be 388 // TODO(hbos): The |info.rtt| measurement is smoothed. It shouldn't be
312 // smoothed according to the spec. crbug.com/633550. See 389 // smoothed according to the spec. crbug.com/633550. See
313 // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-curr entrtt 390 // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-curr entrtt
314 candidate_pair_stats->current_rtt = 391 candidate_pair_stats->current_rtt =
315 static_cast<double>(info.rtt) / 1000.0; 392 static_cast<double>(info.rtt) / rtc::kNumMillisecsPerSec;
316 candidate_pair_stats->requests_sent = 393 candidate_pair_stats->requests_sent =
317 static_cast<uint64_t>(info.sent_ping_requests_total); 394 static_cast<uint64_t>(info.sent_ping_requests_total);
318 candidate_pair_stats->responses_received = 395 candidate_pair_stats->responses_received =
319 static_cast<uint64_t>(info.recv_ping_responses); 396 static_cast<uint64_t>(info.recv_ping_responses);
320 candidate_pair_stats->responses_sent = 397 candidate_pair_stats->responses_sent =
321 static_cast<uint64_t>(info.sent_ping_responses); 398 static_cast<uint64_t>(info.sent_ping_responses);
322 399
323 report->AddStats(std::move(candidate_pair_stats)); 400 report->AddStats(std::move(candidate_pair_stats));
324 } 401 }
325 } 402 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 // There is always just one |RTCPeerConnectionStats| so its |id| can be a 446 // There is always just one |RTCPeerConnectionStats| so its |id| can be a
370 // constant. 447 // constant.
371 std::unique_ptr<RTCPeerConnectionStats> stats( 448 std::unique_ptr<RTCPeerConnectionStats> stats(
372 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us)); 449 new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us));
373 stats->data_channels_opened = data_channels_opened; 450 stats->data_channels_opened = data_channels_opened;
374 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - 451 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) -
375 data_channels_opened; 452 data_channels_opened;
376 report->AddStats(std::move(stats)); 453 report->AddStats(std::move(stats));
377 } 454 }
378 455
456 void RTCStatsCollector::ProduceRTPStreamStats_s(
457 int64_t timestamp_us, const SessionStats& session_stats,
458 RTCStatsReport* report) const {
459 RTC_DCHECK(signaling_thread_->IsCurrent());
460
461 // Audio
462 if (pc_->session()->voice_channel()) {
463 cricket::VoiceMediaInfo voice_media_info;
464 if (pc_->session()->voice_channel()->GetStats(&voice_media_info)) {
465 std::string transport_id = RTCTransportStatsIDFromBaseChannel(
466 session_stats.proxy_to_transport, *pc_->session()->voice_channel());
467 for (const cricket::VoiceSenderInfo& voice_sender_info :
468 voice_media_info.senders) {
469 // TODO(nisse): SSRC == 0 currently means none. Delete check when that
470 // is fixed.
471 if (voice_sender_info.ssrc() == 0)
472 continue;
473 std::unique_ptr<RTCOutboundRTPStreamStats> outbound_audio(
474 new RTCOutboundRTPStreamStats(
475 RTCOutboundRTPStreamStatsIDFromSSRC(
476 true, voice_sender_info.ssrc()),
477 timestamp_us));
478 SetOutboundRTPStreamStatsFromVoiceSenderInfo(
479 voice_sender_info, outbound_audio.get());
480 if (!transport_id.empty())
481 outbound_audio->transport_id = transport_id;
482 report->AddStats(std::move(outbound_audio));
483 }
484 }
485 }
486 // Video
487 if (pc_->session()->video_channel()) {
488 cricket::VideoMediaInfo video_media_info;
489 if (pc_->session()->video_channel()->GetStats(&video_media_info)) {
490 std::string transport_id = RTCTransportStatsIDFromBaseChannel(
491 session_stats.proxy_to_transport, *pc_->session()->video_channel());
492 for (const cricket::VideoSenderInfo& video_sender_info :
493 video_media_info.senders) {
494 // TODO(nisse): SSRC == 0 currently means none. Delete check when that
495 // is fixed.
496 if (video_sender_info.ssrc() == 0)
497 continue;
498 std::unique_ptr<RTCOutboundRTPStreamStats> outbound_video(
499 new RTCOutboundRTPStreamStats(
500 RTCOutboundRTPStreamStatsIDFromSSRC(
501 false, video_sender_info.ssrc()),
502 timestamp_us));
503 SetOutboundRTPStreamStatsFromVideoSenderInfo(
504 video_sender_info, outbound_video.get());
505 if (!transport_id.empty())
506 outbound_video->transport_id = transport_id;
507 report->AddStats(std::move(outbound_video));
508 }
509 }
510 }
511 }
512
379 void RTCStatsCollector::ProduceTransportStats_s( 513 void RTCStatsCollector::ProduceTransportStats_s(
380 int64_t timestamp_us, const SessionStats& session_stats, 514 int64_t timestamp_us, const SessionStats& session_stats,
381 const std::map<std::string, CertificateStatsPair>& transport_cert_stats, 515 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
382 RTCStatsReport* report) const { 516 RTCStatsReport* report) const {
383 RTC_DCHECK(signaling_thread_->IsCurrent()); 517 RTC_DCHECK(signaling_thread_->IsCurrent());
384 for (const auto& transport : session_stats.transport_stats) { 518 for (const auto& transport : session_stats.transport_stats) {
385 // Get reference to RTCP channel, if it exists. 519 // Get reference to RTCP channel, if it exists.
386 std::string rtcp_transport_stats_id; 520 std::string rtcp_transport_stats_id;
387 for (const auto& channel_stats : transport.second.channel_stats) { 521 for (const auto& channel_stats : transport.second.channel_stats) {
388 if (channel_stats.component == 522 if (channel_stats.component ==
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 const std::string& type) { 606 const std::string& type) {
473 return CandidateTypeToRTCIceCandidateType(type); 607 return CandidateTypeToRTCIceCandidateType(type);
474 } 608 }
475 609
476 const char* DataStateToRTCDataChannelStateForTesting( 610 const char* DataStateToRTCDataChannelStateForTesting(
477 DataChannelInterface::DataState state) { 611 DataChannelInterface::DataState state) {
478 return DataStateToRTCDataChannelState(state); 612 return DataStateToRTCDataChannelState(state);
479 } 613 }
480 614
481 } // namespace webrtc 615 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698