OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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/video/receive_statistics_proxy.h" | 11 #include "webrtc/video/receive_statistics_proxy.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <cmath> | 14 #include <cmath> |
15 #include <sstream> | |
15 #include <utility> | 16 #include <utility> |
16 | 17 |
18 #include "webrtc/modules/pacing/alr_detector.h" | |
17 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 19 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
18 #include "webrtc/rtc_base/checks.h" | 20 #include "webrtc/rtc_base/checks.h" |
19 #include "webrtc/rtc_base/logging.h" | 21 #include "webrtc/rtc_base/logging.h" |
20 #include "webrtc/system_wrappers/include/clock.h" | 22 #include "webrtc/system_wrappers/include/clock.h" |
21 #include "webrtc/system_wrappers/include/field_trial.h" | 23 #include "webrtc/system_wrappers/include/field_trial.h" |
22 #include "webrtc/system_wrappers/include/metrics.h" | 24 #include "webrtc/system_wrappers/include/metrics.h" |
23 | 25 |
24 namespace webrtc { | 26 namespace webrtc { |
25 namespace { | 27 namespace { |
26 // Periodic time interval for processing samples for |freq_offset_counter_|. | 28 // Periodic time interval for processing samples for |freq_offset_counter_|. |
(...skipping 11 matching lines...) Expand all Loading... | |
38 const int kHighFpsThreshold = 14; | 40 const int kHighFpsThreshold = 14; |
39 // For qp and fps variance: | 41 // For qp and fps variance: |
40 // Low means low enough to be good, high means high enough to be bad | 42 // Low means low enough to be good, high means high enough to be bad |
41 const int kLowQpThresholdVp8 = 60; | 43 const int kLowQpThresholdVp8 = 60; |
42 const int kHighQpThresholdVp8 = 70; | 44 const int kHighQpThresholdVp8 = 70; |
43 const int kLowVarianceThreshold = 1; | 45 const int kLowVarianceThreshold = 1; |
44 const int kHighVarianceThreshold = 2; | 46 const int kHighVarianceThreshold = 2; |
45 | 47 |
46 // How large window we use to calculate the framerate/bitrate. | 48 // How large window we use to calculate the framerate/bitrate. |
47 const int kRateStatisticsWindowSizeMs = 1000; | 49 const int kRateStatisticsWindowSizeMs = 1000; |
50 | |
51 std::string UmaPrefixForContentType(VideoContentType content_type) { | |
52 std::stringstream ss; | |
53 ss << "WebRTC.Video"; | |
54 if (content_type.IsScreenshare()) { | |
55 ss << ".Screenshare"; | |
56 } | |
57 return ss.str(); | |
58 } | |
59 | |
60 std::string UmaSuffixForContentType(VideoContentType content_type) { | |
61 std::stringstream ss; | |
62 int simulcast_id = content_type.GetSimulcastId(); | |
63 if (simulcast_id > 0) { | |
64 ss << ".S" << simulcast_id - 1; | |
65 } | |
66 return ss.str(); | |
67 } | |
68 | |
69 std::string UmaPrefixForExperiment(VideoContentType content_type) { | |
70 std::stringstream ss; | |
71 ss << "WebRTC.Video.AlrExperiment"; | |
72 if (content_type.IsScreenshare()) { | |
73 ss << ".Screenshare"; | |
74 } | |
75 return ss.str(); | |
76 } | |
77 | |
78 std::string UmaSuffixForExperiment(VideoContentType content_type) { | |
79 std::stringstream ss; | |
80 int experiment_id = content_type.GetExperimentId(); | |
81 if (experiment_id > 0) { | |
82 ss << ".Group" << experiment_id - 1; | |
83 } | |
84 return ss.str(); | |
85 } | |
48 } // namespace | 86 } // namespace |
49 | 87 |
50 ReceiveStatisticsProxy::ReceiveStatisticsProxy( | 88 ReceiveStatisticsProxy::ReceiveStatisticsProxy( |
51 const VideoReceiveStream::Config* config, | 89 const VideoReceiveStream::Config* config, |
52 Clock* clock) | 90 Clock* clock) |
53 : clock_(clock), | 91 : clock_(clock), |
54 config_(*config), | 92 config_(*config), |
55 start_ms_(clock->TimeInMilliseconds()), | 93 start_ms_(clock->TimeInMilliseconds()), |
56 last_sample_time_(clock->TimeInMilliseconds()), | 94 last_sample_time_(clock->TimeInMilliseconds()), |
57 fps_threshold_(kLowFpsThreshold, | 95 fps_threshold_(kLowFpsThreshold, |
58 kHighFpsThreshold, | 96 kHighFpsThreshold, |
59 kBadFraction, | 97 kBadFraction, |
60 kNumMeasurements), | 98 kNumMeasurements), |
61 qp_threshold_(kLowQpThresholdVp8, | 99 qp_threshold_(kLowQpThresholdVp8, |
62 kHighQpThresholdVp8, | 100 kHighQpThresholdVp8, |
63 kBadFraction, | 101 kBadFraction, |
64 kNumMeasurements), | 102 kNumMeasurements), |
65 variance_threshold_(kLowVarianceThreshold, | 103 variance_threshold_(kLowVarianceThreshold, |
66 kHighVarianceThreshold, | 104 kHighVarianceThreshold, |
67 kBadFraction, | 105 kBadFraction, |
68 kNumMeasurementsVariance), | 106 kNumMeasurementsVariance), |
69 num_bad_states_(0), | 107 num_bad_states_(0), |
70 num_certain_states_(0), | 108 num_certain_states_(0), |
71 // 1000ms window, scale 1000 for ms to s. | 109 // 1000ms window, scale 1000 for ms to s. |
72 decode_fps_estimator_(1000, 1000), | 110 decode_fps_estimator_(1000, 1000), |
73 renders_fps_estimator_(1000, 1000), | 111 renders_fps_estimator_(1000, 1000), |
74 render_fps_tracker_(100, 10u), | 112 render_fps_tracker_(100, 10u), |
75 render_pixel_tracker_(100, 10u), | 113 render_pixel_tracker_(100, 10u), |
76 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count | 114 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count |
77 e2e_delay_max_ms_video_(-1), | |
78 e2e_delay_max_ms_screenshare_(-1), | |
79 interframe_delay_max_ms_video_(-1), | |
80 interframe_delay_max_ms_screenshare_(-1), | |
81 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), | 115 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), |
82 first_report_block_time_ms_(-1), | 116 first_report_block_time_ms_(-1), |
83 avg_rtt_ms_(0), | 117 avg_rtt_ms_(0), |
84 last_content_type_(VideoContentType::UNSPECIFIED) { | 118 last_content_type_(VideoContentType::UNSPECIFIED) { |
85 stats_.ssrc = config_.rtp.remote_ssrc; | 119 stats_.ssrc = config_.rtp.remote_ssrc; |
86 // TODO(brandtr): Replace |rtx_stats_| with a single instance of | 120 // TODO(brandtr): Replace |rtx_stats_| with a single instance of |
87 // StreamDataCounters. | 121 // StreamDataCounters. |
88 if (config_.rtp.rtx_ssrc) { | 122 if (config_.rtp.rtx_ssrc) { |
89 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); | 123 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); |
90 } | 124 } |
91 } | 125 } |
92 | 126 |
93 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { | 127 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { |
94 UpdateHistograms(); | 128 UpdateHistograms(); |
95 } | 129 } |
96 | 130 |
97 void ReceiveStatisticsProxy::UpdateHistograms() { | 131 void ReceiveStatisticsProxy::UpdateHistograms() { |
132 // Use to report experiment-specific metrics. | |
133 int experiment_id = last_content_type_.GetExperimentId(); | |
134 | |
98 RTC_HISTOGRAM_COUNTS_100000( | 135 RTC_HISTOGRAM_COUNTS_100000( |
99 "WebRTC.Video.ReceiveStreamLifetimeInSeconds", | 136 "WebRTC.Video.ReceiveStreamLifetimeInSeconds", |
100 (clock_->TimeInMilliseconds() - start_ms_) / 1000); | 137 (clock_->TimeInMilliseconds() - start_ms_) / 1000); |
101 | 138 |
102 if (first_report_block_time_ms_ != -1 && | 139 if (first_report_block_time_ms_ != -1 && |
103 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >= | 140 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >= |
104 metrics::kMinRunTimeInSeconds) { | 141 metrics::kMinRunTimeInSeconds) { |
105 int fraction_lost = report_block_stats_.FractionLostInPercent(); | 142 int fraction_lost = report_block_stats_.FractionLostInPercent(); |
106 if (fraction_lost != -1) { | 143 if (fraction_lost != -1) { |
107 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent", | 144 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent", |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples); | 215 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples); |
179 if (current_delay_ms != -1) { | 216 if (current_delay_ms != -1) { |
180 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", | 217 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", |
181 current_delay_ms); | 218 current_delay_ms); |
182 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms; | 219 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms; |
183 } | 220 } |
184 int delay_ms = delay_counter_.Avg(kMinRequiredSamples); | 221 int delay_ms = delay_counter_.Avg(kMinRequiredSamples); |
185 if (delay_ms != -1) | 222 if (delay_ms != -1) |
186 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms); | 223 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms); |
187 | 224 |
188 int e2e_delay_ms_video = e2e_delay_counter_video_.Avg(kMinRequiredSamples); | 225 int avg_interframe_delay = 0; |
189 if (e2e_delay_ms_video != -1) { | 226 int max_interframe_delay = -1; |
190 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.EndToEndDelayInMs", | 227 int interframe_delay_slices = 0; |
191 e2e_delay_ms_video); | 228 int avg_e2e_delay = 0; |
192 LOG(LS_INFO) << "WebRTC.Video.EndToEndDelayInMs " << e2e_delay_ms_video; | 229 int max_e2e_delay = -1; |
230 int e2e_delay_slices = 0; | |
231 | |
232 // Slice on content type and simulcast id. | |
233 for (auto it : content_specific_stats_) { | |
234 auto content_type = it.first; | |
235 auto stats = it.second; | |
236 std::string uma_prefix = UmaPrefixForContentType(content_type); | |
237 std::string uma_suffix = UmaSuffixForContentType(content_type); | |
238 // The same line of code can't report different histograms because of how | |
239 // macro is done. Additional index needed to be different for all different | |
240 // names. Since experiment can't change during call, we could report 4*2 | |
241 // different content types (4 simulcast_ids x 2 content types). | |
242 // Conveniently all of these are stored in 3 lower bits in VideoContentType. | |
243 int idx = content_type.content_type & 0x07; | |
244 int e2e_delay_ms = stats.e2e_delay_counter.Avg(kMinRequiredSamples); | |
245 if (e2e_delay_ms != -1) { | |
246 RTC_HISTOGRAMS_COUNTS_10000( | |
247 idx, uma_prefix + ".EndToEndDelayInMs" + uma_suffix, e2e_delay_ms); | |
248 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayInMs" << uma_suffix << " " | |
249 << e2e_delay_ms; | |
250 avg_e2e_delay += e2e_delay_ms; | |
251 ++e2e_delay_slices; | |
252 } | |
253 int e2e_delay_max_ms = stats.e2e_delay_counter.Max(); | |
254 | |
255 if (e2e_delay_max_ms != -1 && e2e_delay_ms != -1) { | |
256 RTC_HISTOGRAMS_COUNTS_100000( | |
257 idx, uma_prefix + ".EndToEndDelayMaxInMs" + uma_suffix, | |
258 e2e_delay_max_ms); | |
259 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayMaxInMs" << uma_suffix << " " | |
260 << e2e_delay_max_ms; | |
261 if (e2e_delay_max_ms > max_e2e_delay) | |
262 max_e2e_delay = e2e_delay_max_ms; | |
263 } | |
264 int interframe_delay_ms = | |
265 stats.interframe_delay_counter.Avg(kMinRequiredSamples); | |
266 if (interframe_delay_ms != -1) { | |
267 RTC_HISTOGRAMS_COUNTS_10000( | |
268 idx, uma_prefix + ".InterframeDelayInMs" + uma_suffix, | |
269 interframe_delay_ms); | |
270 LOG(LS_INFO) << uma_prefix << ".InterframeDelayInMs" << uma_suffix << " " | |
271 << interframe_delay_ms; | |
272 avg_interframe_delay += interframe_delay_ms; | |
273 ++interframe_delay_slices; | |
274 } | |
275 int interframe_delay_max_ms = stats.interframe_delay_counter.Max(); | |
276 if (interframe_delay_max_ms != -1 && interframe_delay_ms != -1) { | |
277 RTC_HISTOGRAMS_COUNTS_10000( | |
278 idx, uma_prefix + ".InterframeDelayMaxInMs" + uma_suffix, | |
279 interframe_delay_max_ms); | |
280 LOG(LS_INFO) << uma_prefix << ".InterframeDelayMaxInMs" << uma_suffix | |
281 << " " << interframe_delay_max_ms; | |
282 if (interframe_delay_max_ms > max_interframe_delay) | |
283 max_interframe_delay = interframe_delay_max_ms; | |
284 } | |
285 } | |
286 if (e2e_delay_slices > 0) { | |
287 avg_e2e_delay /= e2e_delay_slices; | |
288 } else { | |
289 avg_e2e_delay = -1; | |
290 } | |
291 if (interframe_delay_slices > 0) { | |
292 avg_interframe_delay /= interframe_delay_slices; | |
293 } else { | |
294 avg_interframe_delay = -1; | |
193 } | 295 } |
194 | 296 |
195 int e2e_delay_ms_screenshare = | 297 int media_bitrate = 0; |
196 e2e_delay_counter_screenshare_.Avg(kMinRequiredSamples); | |
197 if (e2e_delay_ms_screenshare != -1) { | |
198 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.EndToEndDelayInMs", | |
199 e2e_delay_ms_screenshare); | |
200 } | |
201 | |
202 int e2e_delay_max_ms_video = e2e_delay_max_ms_video_; | |
203 if (e2e_delay_max_ms_video != -1) { | |
204 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.EndToEndDelayMaxInMs", | |
205 e2e_delay_max_ms_video); | |
206 } | |
207 | |
208 int e2e_delay_max_ms_screenshare = e2e_delay_max_ms_screenshare_; | |
209 if (e2e_delay_max_ms_screenshare != -1) { | |
210 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs", | |
211 e2e_delay_max_ms_screenshare); | |
212 } | |
213 | |
214 int interframe_delay_ms_screenshare = | |
215 interframe_delay_counter_screenshare_.Avg(kMinRequiredSamples); | |
216 if (interframe_delay_ms_screenshare != -1) { | |
217 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.InterframeDelayInMs", | |
218 interframe_delay_ms_screenshare); | |
219 RTC_DCHECK_GE(interframe_delay_max_ms_screenshare_, | |
220 interframe_delay_ms_screenshare); | |
221 RTC_HISTOGRAM_COUNTS_10000( | |
222 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs", | |
223 interframe_delay_max_ms_screenshare_); | |
224 } | |
225 | |
226 int interframe_delay_ms_video = | |
227 interframe_delay_counter_video_.Avg(kMinRequiredSamples); | |
228 if (interframe_delay_ms_video != -1) { | |
229 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InterframeDelayInMs", | |
230 interframe_delay_ms_video); | |
231 RTC_DCHECK_GE(interframe_delay_max_ms_video_, interframe_delay_ms_video); | |
232 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InterframeDelayMaxInMs", | |
233 interframe_delay_max_ms_video_); | |
234 } | |
235 | 298 |
236 StreamDataCounters rtp = stats_.rtp_stats; | 299 StreamDataCounters rtp = stats_.rtp_stats; |
237 StreamDataCounters rtx; | 300 StreamDataCounters rtx; |
238 for (auto it : rtx_stats_) | 301 for (auto it : rtx_stats_) |
239 rtx.Add(it.second); | 302 rtx.Add(it.second); |
240 StreamDataCounters rtp_rtx = rtp; | 303 StreamDataCounters rtp_rtx = rtp; |
241 rtp_rtx.Add(rtx); | 304 rtp_rtx.Add(rtx); |
242 int64_t elapsed_sec = | 305 int64_t elapsed_sec = |
243 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; | 306 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; |
244 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { | 307 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { |
245 RTC_HISTOGRAM_COUNTS_10000( | 308 RTC_HISTOGRAM_COUNTS_10000( |
246 "WebRTC.Video.BitrateReceivedInKbps", | 309 "WebRTC.Video.BitrateReceivedInKbps", |
247 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / | 310 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / |
248 1000)); | 311 1000)); |
249 RTC_HISTOGRAM_COUNTS_10000( | 312 media_bitrate = |
250 "WebRTC.Video.MediaBitrateReceivedInKbps", | 313 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000); |
251 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000)); | 314 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps", |
315 media_bitrate); | |
252 RTC_HISTOGRAM_COUNTS_10000( | 316 RTC_HISTOGRAM_COUNTS_10000( |
253 "WebRTC.Video.PaddingBitrateReceivedInKbps", | 317 "WebRTC.Video.PaddingBitrateReceivedInKbps", |
254 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / | 318 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / |
255 1000)); | 319 1000)); |
256 RTC_HISTOGRAM_COUNTS_10000( | 320 RTC_HISTOGRAM_COUNTS_10000( |
257 "WebRTC.Video.RetransmittedBitrateReceivedInKbps", | 321 "WebRTC.Video.RetransmittedBitrateReceivedInKbps", |
258 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / | 322 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / |
259 1000)); | 323 1000)); |
260 if (!rtx_stats_.empty()) { | 324 if (!rtx_stats_.empty()) { |
261 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", | 325 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", |
(...skipping 11 matching lines...) Expand all Loading... | |
273 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsSentPerMinute", | 337 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.FirPacketsSentPerMinute", |
274 counters.fir_packets * 60 / elapsed_sec); | 338 counters.fir_packets * 60 / elapsed_sec); |
275 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", | 339 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", |
276 counters.pli_packets * 60 / elapsed_sec); | 340 counters.pli_packets * 60 / elapsed_sec); |
277 if (counters.nack_requests > 0) { | 341 if (counters.nack_requests > 0) { |
278 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", | 342 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", |
279 counters.UniqueNackRequestsInPercent()); | 343 counters.UniqueNackRequestsInPercent()); |
280 } | 344 } |
281 } | 345 } |
282 | 346 |
347 // Report metrics sliced on ALR experiment group. | |
348 if (experiment_id > 0 && content_specific_stats_.size() > 0) { | |
349 VideoContentType content_type = content_specific_stats_.begin()->first; | |
350 std::string uma_prefix = UmaPrefixForExperiment(content_type); | |
351 std::string uma_suffix = UmaSuffixForExperiment(content_type); | |
352 if (avg_e2e_delay != -1) { | |
353 RTC_HISTOGRAM_COUNTS_10000(uma_prefix + ".EndToEndDelayInMs" + uma_suffix, | |
354 avg_e2e_delay); | |
355 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayInMs" << uma_suffix << " " | |
356 << avg_e2e_delay; | |
357 } | |
358 if (max_e2e_delay != -1) { | |
359 RTC_HISTOGRAM_COUNTS_100000( | |
360 uma_prefix + ".EndToEndDelayMaxInMs" + uma_suffix, max_e2e_delay); | |
361 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayMaxInMs" << uma_suffix << " " | |
362 << max_e2e_delay; | |
363 } | |
364 if (avg_interframe_delay != -1) { | |
365 RTC_HISTOGRAM_COUNTS_10000( | |
366 uma_prefix + ".InterframeDelayInMs" + uma_suffix, | |
367 avg_interframe_delay); | |
368 LOG(LS_INFO) << uma_prefix << ".InterframeDelayInMs" << uma_suffix << " " | |
369 << avg_interframe_delay; | |
370 } | |
371 if (max_interframe_delay != -1) { | |
372 RTC_HISTOGRAM_COUNTS_10000( | |
373 uma_prefix + ".InterframeDelayMaxInMs" + uma_suffix, | |
374 max_interframe_delay); | |
375 LOG(LS_INFO) << uma_prefix << ".InterframeDelayMaxInMs" << uma_suffix | |
376 << " " << max_interframe_delay; | |
377 } | |
378 if (media_bitrate != 0) { | |
379 RTC_HISTOGRAM_COUNTS_10000( | |
380 uma_prefix + ".MediaBitrateReceivedInKbps" + uma_suffix, | |
381 media_bitrate); | |
382 LOG(LS_INFO) << uma_prefix << ".MediaBitrateReceivedInKbps" << uma_suffix | |
383 << " " << media_bitrate; | |
384 } | |
385 } | |
386 | |
sprang_webrtc
2017/08/24 09:13:16
Why isn't this reported in the same way as for the
ilnik
2017/08/25 12:35:07
Because currently we can't get slice on both simul
| |
283 if (num_certain_states_ >= kBadCallMinRequiredSamples) { | 387 if (num_certain_states_ >= kBadCallMinRequiredSamples) { |
284 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.Any", | 388 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.Any", |
285 100 * num_bad_states_ / num_certain_states_); | 389 100 * num_bad_states_ / num_certain_states_); |
286 } | 390 } |
287 rtc::Optional<double> fps_fraction = | 391 rtc::Optional<double> fps_fraction = |
288 fps_threshold_.FractionHigh(kBadCallMinRequiredSamples); | 392 fps_threshold_.FractionHigh(kBadCallMinRequiredSamples); |
289 if (fps_fraction) { | 393 if (fps_fraction) { |
290 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.FrameRate", | 394 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BadCall.FrameRate", |
291 static_cast<int>(100 * (1 - *fps_fraction))); | 395 static_cast<int>(100 * (1 - *fps_fraction))); |
292 } | 396 } |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 LOG(LS_WARNING) | 642 LOG(LS_WARNING) |
539 << "QP sum was already set and no QP was given for a frame."; | 643 << "QP sum was already set and no QP was given for a frame."; |
540 stats_.qp_sum = rtc::Optional<uint64_t>(); | 644 stats_.qp_sum = rtc::Optional<uint64_t>(); |
541 } | 645 } |
542 last_content_type_ = content_type; | 646 last_content_type_ = content_type; |
543 decode_fps_estimator_.Update(1, now); | 647 decode_fps_estimator_.Update(1, now); |
544 if (last_decoded_frame_time_ms_) { | 648 if (last_decoded_frame_time_ms_) { |
545 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_; | 649 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_; |
546 RTC_DCHECK_GE(interframe_delay_ms, 0); | 650 RTC_DCHECK_GE(interframe_delay_ms, 0); |
547 stats_.interframe_delay_sum_ms += interframe_delay_ms; | 651 stats_.interframe_delay_sum_ms += interframe_delay_ms; |
548 if (last_content_type_ == VideoContentType::SCREENSHARE) { | 652 auto it = content_specific_stats_.find(last_content_type_); |
549 interframe_delay_counter_screenshare_.Add(interframe_delay_ms); | 653 if (it == content_specific_stats_.end()) { |
550 if (interframe_delay_max_ms_screenshare_ < interframe_delay_ms) { | 654 content_specific_stats_[last_content_type_] = ContentSpecificStats(); |
551 interframe_delay_max_ms_screenshare_ = interframe_delay_ms; | 655 it = content_specific_stats_.find(last_content_type_); |
552 } | |
553 } else { | |
554 interframe_delay_counter_video_.Add(interframe_delay_ms); | |
555 if (interframe_delay_max_ms_video_ < interframe_delay_ms) { | |
556 interframe_delay_max_ms_video_ = interframe_delay_ms; | |
557 } | |
558 } | 656 } |
sprang_webrtc
2017/08/24 09:13:16
I think you can just do
auto it = content_specif
ilnik
2017/08/25 12:35:07
Redone using plain [] operator. According to docum
| |
657 ContentSpecificStats* stats = &it->second; | |
658 stats->interframe_delay_counter.Add(interframe_delay_ms); | |
559 } | 659 } |
560 last_decoded_frame_time_ms_.emplace(now); | 660 last_decoded_frame_time_ms_.emplace(now); |
561 } | 661 } |
562 | 662 |
563 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) { | 663 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) { |
564 int width = frame.width(); | 664 int width = frame.width(); |
565 int height = frame.height(); | 665 int height = frame.height(); |
566 RTC_DCHECK_GT(width, 0); | 666 RTC_DCHECK_GT(width, 0); |
567 RTC_DCHECK_GT(height, 0); | 667 RTC_DCHECK_GT(height, 0); |
568 uint64_t now = clock_->TimeInMilliseconds(); | 668 uint64_t now = clock_->TimeInMilliseconds(); |
569 | 669 |
570 rtc::CritScope lock(&crit_); | 670 rtc::CritScope lock(&crit_); |
571 renders_fps_estimator_.Update(1, now); | 671 renders_fps_estimator_.Update(1, now); |
572 ++stats_.frames_rendered; | 672 ++stats_.frames_rendered; |
573 stats_.width = width; | 673 stats_.width = width; |
574 stats_.height = height; | 674 stats_.height = height; |
575 render_width_counter_.Add(width); | 675 render_width_counter_.Add(width); |
576 render_height_counter_.Add(height); | 676 render_height_counter_.Add(height); |
577 render_fps_tracker_.AddSamples(1); | 677 render_fps_tracker_.AddSamples(1); |
578 render_pixel_tracker_.AddSamples(sqrt(width * height)); | 678 render_pixel_tracker_.AddSamples(sqrt(width * height)); |
579 | 679 |
580 if (frame.ntp_time_ms() > 0) { | 680 if (frame.ntp_time_ms() > 0) { |
581 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms(); | 681 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms(); |
582 if (delay_ms >= 0) { | 682 if (delay_ms >= 0) { |
583 if (last_content_type_ == VideoContentType::SCREENSHARE) { | 683 auto it = content_specific_stats_.find(last_content_type_); |
584 e2e_delay_max_ms_screenshare_ = | 684 if (it == content_specific_stats_.end()) { |
585 std::max(delay_ms, e2e_delay_max_ms_screenshare_); | 685 content_specific_stats_[last_content_type_] = ContentSpecificStats(); |
586 e2e_delay_counter_screenshare_.Add(delay_ms); | 686 it = content_specific_stats_.find(last_content_type_); |
587 } else { | |
588 e2e_delay_max_ms_video_ = std::max(delay_ms, e2e_delay_max_ms_video_); | |
589 e2e_delay_counter_video_.Add(delay_ms); | |
590 } | 687 } |
688 ContentSpecificStats* stats = &it->second; | |
689 stats->e2e_delay_counter.Add(delay_ms); | |
591 } | 690 } |
592 } | 691 } |
593 } | 692 } |
594 | 693 |
595 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms, | 694 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms, |
596 double estimated_freq_khz) { | 695 double estimated_freq_khz) { |
597 rtc::CritScope lock(&crit_); | 696 rtc::CritScope lock(&crit_); |
598 sync_offset_counter_.Add(std::abs(sync_offset_ms)); | 697 sync_offset_counter_.Add(std::abs(sync_offset_ms)); |
599 stats_.sync_offset_ms = sync_offset_ms; | 698 stats_.sync_offset_ms = sync_offset_ms; |
600 | 699 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
652 // TODO(sprang): Figure out any other state that should be reset. | 751 // TODO(sprang): Figure out any other state that should be reset. |
653 | 752 |
654 rtc::CritScope lock(&crit_); | 753 rtc::CritScope lock(&crit_); |
655 // Don't report inter-frame delay if stream was paused. | 754 // Don't report inter-frame delay if stream was paused. |
656 last_decoded_frame_time_ms_.reset(); | 755 last_decoded_frame_time_ms_.reset(); |
657 } | 756 } |
658 | 757 |
659 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { | 758 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { |
660 sum += sample; | 759 sum += sample; |
661 ++num_samples; | 760 ++num_samples; |
761 if (!max || *max < sample) { | |
762 max.emplace(sample); | |
763 } | |
662 } | 764 } |
663 | 765 |
664 int ReceiveStatisticsProxy::SampleCounter::Avg( | 766 int ReceiveStatisticsProxy::SampleCounter::Avg( |
665 int64_t min_required_samples) const { | 767 int64_t min_required_samples) const { |
666 if (num_samples < min_required_samples || num_samples == 0) | 768 if (num_samples < min_required_samples || num_samples == 0) |
667 return -1; | 769 return -1; |
668 return static_cast<int>(sum / num_samples); | 770 return static_cast<int>(sum / num_samples); |
669 } | 771 } |
670 | 772 |
773 int ReceiveStatisticsProxy::SampleCounter::Max() const { | |
774 if (!max) { | |
775 return -1; | |
776 } else { | |
777 return *max; | |
778 } | |
779 } | |
780 | |
671 void ReceiveStatisticsProxy::SampleCounter::Reset() { | 781 void ReceiveStatisticsProxy::SampleCounter::Reset() { |
672 num_samples = 0; | 782 num_samples = 0; |
673 sum = 0; | 783 sum = 0; |
784 max.reset(); | |
674 } | 785 } |
675 | 786 |
676 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms, | 787 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms, |
677 int64_t max_rtt_ms) { | 788 int64_t max_rtt_ms) { |
678 rtc::CritScope lock(&crit_); | 789 rtc::CritScope lock(&crit_); |
679 avg_rtt_ms_ = avg_rtt_ms; | 790 avg_rtt_ms_ = avg_rtt_ms; |
680 } | 791 } |
681 | 792 |
682 } // namespace webrtc | 793 } // namespace webrtc |
OLD | NEW |