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

Side by Side Diff: webrtc/video/receive_statistics_proxy.cc

Issue 2986893002: Piggybacking simulcast id and ALR experiment id into video content type extension. (Closed)
Patch Set: use namespace instead of struct Created 3 years, 3 months 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 (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"
22 #include "webrtc/system_wrappers/include/metrics.h" 23 #include "webrtc/system_wrappers/include/metrics.h"
23 24
24 namespace webrtc { 25 namespace webrtc {
25 namespace { 26 namespace {
26 // Periodic time interval for processing samples for |freq_offset_counter_|. 27 // Periodic time interval for processing samples for |freq_offset_counter_|.
27 const int64_t kFreqOffsetProcessIntervalMs = 40000; 28 const int64_t kFreqOffsetProcessIntervalMs = 40000;
28 29
29 // Configuration for bad call detection. 30 // Configuration for bad call detection.
30 const int kBadCallMinRequiredSamples = 10; 31 const int kBadCallMinRequiredSamples = 10;
31 const int kMinSampleLengthMs = 990; 32 const int kMinSampleLengthMs = 990;
32 const int kNumMeasurements = 10; 33 const int kNumMeasurements = 10;
33 const int kNumMeasurementsVariance = kNumMeasurements * 1.5; 34 const int kNumMeasurementsVariance = kNumMeasurements * 1.5;
34 const float kBadFraction = 0.8f; 35 const float kBadFraction = 0.8f;
35 // For fps: 36 // For fps:
36 // Low means low enough to be bad, high means high enough to be good 37 // Low means low enough to be bad, high means high enough to be good
37 const int kLowFpsThreshold = 12; 38 const int kLowFpsThreshold = 12;
38 const int kHighFpsThreshold = 14; 39 const int kHighFpsThreshold = 14;
39 // For qp and fps variance: 40 // For qp and fps variance:
40 // Low means low enough to be good, high means high enough to be bad 41 // Low means low enough to be good, high means high enough to be bad
41 const int kLowQpThresholdVp8 = 60; 42 const int kLowQpThresholdVp8 = 60;
42 const int kHighQpThresholdVp8 = 70; 43 const int kHighQpThresholdVp8 = 70;
43 const int kLowVarianceThreshold = 1; 44 const int kLowVarianceThreshold = 1;
44 const int kHighVarianceThreshold = 2; 45 const int kHighVarianceThreshold = 2;
45 46
46 // Some metrics are reported as a maximum over this period. 47 // Some metrics are reported as a maximum over this period.
47 const int kMovingMaxWindowMs = 10000; 48 const int kMovingMaxWindowMs = 10000;
48 49
49 // How large window we use to calculate the framerate/bitrate. 50 // How large window we use to calculate the framerate/bitrate.
50 const int kRateStatisticsWindowSizeMs = 1000; 51 const int kRateStatisticsWindowSizeMs = 1000;
52
53 std::string UmaPrefixForContentType(VideoContentType content_type) {
54 std::stringstream ss;
55 ss << "WebRTC.Video";
56 if (videocontenttypehelpers::IsScreenshare(content_type)) {
57 ss << ".Screenshare";
58 }
59 return ss.str();
60 }
61
62 std::string UmaSuffixForContentType(VideoContentType content_type) {
63 std::stringstream ss;
64 int simulcast_id = videocontenttypehelpers::GetSimulcastId(content_type);
65 if (simulcast_id > 0) {
66 ss << ".S" << simulcast_id - 1;
67 }
68 int experiment_id = videocontenttypehelpers::GetExperimentId(content_type);
69 if (experiment_id > 0) {
70 ss << ".ExperimentGroup" << experiment_id - 1;
71 }
72 return ss.str();
73 }
51 } // namespace 74 } // namespace
52 75
53 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 76 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
54 const VideoReceiveStream::Config* config, 77 const VideoReceiveStream::Config* config,
55 Clock* clock) 78 Clock* clock)
56 : clock_(clock), 79 : clock_(clock),
57 config_(*config), 80 config_(*config),
58 start_ms_(clock->TimeInMilliseconds()), 81 start_ms_(clock->TimeInMilliseconds()),
59 last_sample_time_(clock->TimeInMilliseconds()), 82 last_sample_time_(clock->TimeInMilliseconds()),
60 fps_threshold_(kLowFpsThreshold, 83 fps_threshold_(kLowFpsThreshold,
61 kHighFpsThreshold, 84 kHighFpsThreshold,
62 kBadFraction, 85 kBadFraction,
63 kNumMeasurements), 86 kNumMeasurements),
64 qp_threshold_(kLowQpThresholdVp8, 87 qp_threshold_(kLowQpThresholdVp8,
65 kHighQpThresholdVp8, 88 kHighQpThresholdVp8,
66 kBadFraction, 89 kBadFraction,
67 kNumMeasurements), 90 kNumMeasurements),
68 variance_threshold_(kLowVarianceThreshold, 91 variance_threshold_(kLowVarianceThreshold,
69 kHighVarianceThreshold, 92 kHighVarianceThreshold,
70 kBadFraction, 93 kBadFraction,
71 kNumMeasurementsVariance), 94 kNumMeasurementsVariance),
72 num_bad_states_(0), 95 num_bad_states_(0),
73 num_certain_states_(0), 96 num_certain_states_(0),
74 // 1000ms window, scale 1000 for ms to s. 97 // 1000ms window, scale 1000 for ms to s.
75 decode_fps_estimator_(1000, 1000), 98 decode_fps_estimator_(1000, 1000),
76 renders_fps_estimator_(1000, 1000), 99 renders_fps_estimator_(1000, 1000),
77 render_fps_tracker_(100, 10u), 100 render_fps_tracker_(100, 10u),
78 render_pixel_tracker_(100, 10u), 101 render_pixel_tracker_(100, 10u),
79 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count 102 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count
80 e2e_delay_max_ms_video_(-1),
81 e2e_delay_max_ms_screenshare_(-1),
82 interframe_delay_max_ms_video_(-1),
83 interframe_delay_max_ms_screenshare_(-1),
84 interframe_delay_max_moving_(kMovingMaxWindowMs), 103 interframe_delay_max_moving_(kMovingMaxWindowMs),
85 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), 104 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
86 first_report_block_time_ms_(-1), 105 first_report_block_time_ms_(-1),
87 avg_rtt_ms_(0), 106 avg_rtt_ms_(0),
88 last_content_type_(VideoContentType::UNSPECIFIED) { 107 last_content_type_(VideoContentType::UNSPECIFIED) {
89 stats_.ssrc = config_.rtp.remote_ssrc; 108 stats_.ssrc = config_.rtp.remote_ssrc;
90 // TODO(brandtr): Replace |rtx_stats_| with a single instance of 109 // TODO(brandtr): Replace |rtx_stats_| with a single instance of
91 // StreamDataCounters. 110 // StreamDataCounters.
92 if (config_.rtp.rtx_ssrc) { 111 if (config_.rtp.rtx_ssrc) {
93 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); 112 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters();
94 } 113 }
95 } 114 }
96 115
97 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { 116 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
98 UpdateHistograms(); 117 UpdateHistograms();
99 } 118 }
100 119
101 void ReceiveStatisticsProxy::UpdateHistograms() { 120 void ReceiveStatisticsProxy::UpdateHistograms() {
102 RTC_HISTOGRAM_COUNTS_100000( 121 int stream_duration_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000;
103 "WebRTC.Video.ReceiveStreamLifetimeInSeconds", 122 if (stats_.frame_counts.key_frames > 0 ||
104 (clock_->TimeInMilliseconds() - start_ms_) / 1000); 123 stats_.frame_counts.delta_frames > 0) {
124 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
125 stream_duration_sec);
126 LOG(LS_INFO) << "WebRTC.Video.ReceiveStreamLifetimeInSeconds "
127 << stream_duration_sec;
128 }
105 129
106 if (first_report_block_time_ms_ != -1 && 130 if (first_report_block_time_ms_ != -1 &&
107 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >= 131 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >=
108 metrics::kMinRunTimeInSeconds) { 132 metrics::kMinRunTimeInSeconds) {
109 int fraction_lost = report_block_stats_.FractionLostInPercent(); 133 int fraction_lost = report_block_stats_.FractionLostInPercent();
110 if (fraction_lost != -1) { 134 if (fraction_lost != -1) {
111 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent", 135 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
112 fraction_lost); 136 fraction_lost);
113 LOG(LS_INFO) << "WebRTC.Video.ReceivedPacketsLostInPercent " 137 LOG(LS_INFO) << "WebRTC.Video.ReceivedPacketsLostInPercent "
114 << fraction_lost; 138 << fraction_lost;
115 } 139 }
116 } 140 }
117 141
118 const int kMinRequiredSamples = 200; 142 const int kMinRequiredSamples = 200;
119 int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount()); 143 int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount());
120 if (samples >= kMinRequiredSamples) { 144 if (samples >= kMinRequiredSamples) {
121 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond", 145 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond",
122 round(render_fps_tracker_.ComputeTotalRate())); 146 round(render_fps_tracker_.ComputeTotalRate()));
123 RTC_HISTOGRAM_COUNTS_100000( 147 RTC_HISTOGRAM_COUNTS_100000(
124 "WebRTC.Video.RenderSqrtPixelsPerSecond", 148 "WebRTC.Video.RenderSqrtPixelsPerSecond",
125 round(render_pixel_tracker_.ComputeTotalRate())); 149 round(render_pixel_tracker_.ComputeTotalRate()));
126 } 150 }
127 int width = render_width_counter_.Avg(kMinRequiredSamples); 151
128 int height = render_height_counter_.Avg(kMinRequiredSamples);
129 if (width != -1) {
130 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedWidthInPixels", width);
131 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedHeightInPixels", height);
132 LOG(LS_INFO) << "WebRTC.Video.ReceivedWidthInPixels " << width;
133 LOG(LS_INFO) << "WebRTC.Video.ReceivedHeightInPixels " << height;
134 }
135 int sync_offset_ms = sync_offset_counter_.Avg(kMinRequiredSamples); 152 int sync_offset_ms = sync_offset_counter_.Avg(kMinRequiredSamples);
136 if (sync_offset_ms != -1) { 153 if (sync_offset_ms != -1) {
137 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms); 154 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms);
138 LOG(LS_INFO) << "WebRTC.Video.AVSyncOffsetInMs " << sync_offset_ms; 155 LOG(LS_INFO) << "WebRTC.Video.AVSyncOffsetInMs " << sync_offset_ms;
139 } 156 }
140 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats(); 157 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats();
141 if (freq_offset_stats.num_samples > 0) { 158 if (freq_offset_stats.num_samples > 0) {
142 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 159 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz",
143 freq_offset_stats.average); 160 freq_offset_stats.average);
144 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, " 161 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, "
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples); 199 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples);
183 if (current_delay_ms != -1) { 200 if (current_delay_ms != -1) {
184 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", 201 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs",
185 current_delay_ms); 202 current_delay_ms);
186 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms; 203 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms;
187 } 204 }
188 int delay_ms = delay_counter_.Avg(kMinRequiredSamples); 205 int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
189 if (delay_ms != -1) 206 if (delay_ms != -1)
190 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms); 207 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms);
191 208
192 int e2e_delay_ms_video = e2e_delay_counter_video_.Avg(kMinRequiredSamples); 209 // Aggregate content_specific_stats_ by removing experiment or simulcast
193 if (e2e_delay_ms_video != -1) { 210 // information;
194 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.EndToEndDelayInMs", 211 std::map<VideoContentType, ContentSpecificStats> aggregated_stats;
195 e2e_delay_ms_video); 212 for (auto it : content_specific_stats_) {
196 LOG(LS_INFO) << "WebRTC.Video.EndToEndDelayInMs " << e2e_delay_ms_video; 213 // Calculate simulcast specific metrics (".S0" ... ".S2" suffixes).
214 VideoContentType content_type = it.first;
215 if (videocontenttypehelpers::GetSimulcastId(content_type) > 0) {
216 // Aggregate on experiment id.
217 videocontenttypehelpers::SetExperimentId(&content_type, 0);
218 aggregated_stats[content_type].Add(it.second);
219 }
220 // Calculate experiment specific metrics (".ExperimentGroup[0-7]" suffixes).
221 content_type = it.first;
222 if (videocontenttypehelpers::GetExperimentId(content_type) > 0) {
223 // Aggregate on simulcast id.
224 videocontenttypehelpers::SetSimulcastId(&content_type, 0);
225 aggregated_stats[content_type].Add(it.second);
226 }
227 // Calculate aggregated metrics (no suffixes. Aggregated on everything).
228 content_type = it.first;
229 videocontenttypehelpers::SetSimulcastId(&content_type, 0);
230 videocontenttypehelpers::SetExperimentId(&content_type, 0);
231 aggregated_stats[content_type].Add(it.second);
197 } 232 }
198 233
199 int e2e_delay_ms_screenshare = 234 for (auto it : aggregated_stats) {
200 e2e_delay_counter_screenshare_.Avg(kMinRequiredSamples); 235 // For the metric Foo we report the following slices:
201 if (e2e_delay_ms_screenshare != -1) { 236 // WebRTC.Video.Foo,
202 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.EndToEndDelayInMs", 237 // WebRTC.Video.Screenshare.Foo,
203 e2e_delay_ms_screenshare); 238 // WebRTC.Video.Foo.S[0-3],
204 } 239 // WebRTC.Video.Foo.ExperimentGroup[0-7],
240 // WebRTC.Video.Screenshare.Foo.S[0-3],
241 // WebRTC.Video.Screenshare.Foo.ExperimentGroup[0-7].
242 auto content_type = it.first;
243 auto stats = it.second;
244 std::string uma_prefix = UmaPrefixForContentType(content_type);
245 std::string uma_suffix = UmaSuffixForContentType(content_type);
246 // Metrics can be sliced on either simulcast id or experiment id but not
247 // both.
248 RTC_DCHECK(videocontenttypehelpers::GetExperimentId(content_type) == 0 ||
249 videocontenttypehelpers::GetSimulcastId(content_type) == 0);
205 250
206 int e2e_delay_max_ms_video = e2e_delay_max_ms_video_; 251 int e2e_delay_ms = stats.e2e_delay_counter.Avg(kMinRequiredSamples);
207 if (e2e_delay_max_ms_video != -1) { 252 if (e2e_delay_ms != -1) {
208 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.EndToEndDelayMaxInMs", 253 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
209 e2e_delay_max_ms_video); 254 uma_prefix + ".EndToEndDelayInMs" + uma_suffix, e2e_delay_ms);
210 } 255 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayInMs" << uma_suffix << " "
256 << e2e_delay_ms;
257 }
258 int e2e_delay_max_ms = stats.e2e_delay_counter.Max();
259 if (e2e_delay_max_ms != -1 && e2e_delay_ms != -1) {
260 RTC_HISTOGRAM_COUNTS_SPARSE_100000(
261 uma_prefix + ".EndToEndDelayMaxInMs" + uma_suffix, e2e_delay_max_ms);
262 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayMaxInMs" << uma_suffix << " "
263 << e2e_delay_max_ms;
264 }
265 int interframe_delay_ms =
266 stats.interframe_delay_counter.Avg(kMinRequiredSamples);
267 if (interframe_delay_ms != -1) {
268 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
269 uma_prefix + ".InterframeDelayInMs" + uma_suffix,
270 interframe_delay_ms);
271 LOG(LS_INFO) << uma_prefix << ".InterframeDelayInMs" << uma_suffix << " "
272 << interframe_delay_ms;
273 }
274 int interframe_delay_max_ms = stats.interframe_delay_counter.Max();
275 if (interframe_delay_max_ms != -1 && interframe_delay_ms != -1) {
276 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
277 uma_prefix + ".InterframeDelayMaxInMs" + uma_suffix,
278 interframe_delay_max_ms);
279 LOG(LS_INFO) << uma_prefix << ".InterframeDelayMaxInMs" << uma_suffix
280 << " " << interframe_delay_max_ms;
281 }
211 282
212 int e2e_delay_max_ms_screenshare = e2e_delay_max_ms_screenshare_; 283 int width = stats.received_width.Avg(kMinRequiredSamples);
213 if (e2e_delay_max_ms_screenshare != -1) { 284 if (width != -1) {
214 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs", 285 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
215 e2e_delay_max_ms_screenshare); 286 uma_prefix + ".ReceivedWidthInPixels" + uma_suffix, width);
216 } 287 LOG(LS_INFO) << uma_prefix << ".ReceivedWidthInPixels" << uma_suffix
288 << " " << width;
289 }
217 290
218 int interframe_delay_ms_screenshare = 291 int height = stats.received_height.Avg(kMinRequiredSamples);
219 interframe_delay_counter_screenshare_.Avg(kMinRequiredSamples); 292 if (height != -1) {
220 if (interframe_delay_ms_screenshare != -1) { 293 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
221 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.InterframeDelayInMs", 294 uma_prefix + ".ReceivedHeightInPixels" + uma_suffix, height);
222 interframe_delay_ms_screenshare); 295 LOG(LS_INFO) << uma_prefix << ".ReceivedHeightInPixels" << uma_suffix
223 RTC_DCHECK_GE(interframe_delay_max_ms_screenshare_, 296 << " " << height;
224 interframe_delay_ms_screenshare); 297 }
225 RTC_HISTOGRAM_COUNTS_10000(
226 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs",
227 interframe_delay_max_ms_screenshare_);
228 }
229 298
230 int interframe_delay_ms_video = 299 if (content_type != VideoContentType::UNSPECIFIED) {
231 interframe_delay_counter_video_.Avg(kMinRequiredSamples); 300 // Don't report these 3 metrics unsliced, as more precise variants
232 if (interframe_delay_ms_video != -1) { 301 // are reported separately in this method.
233 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InterframeDelayInMs", 302 float flow_duration_sec = stats.flow_duration_ms / 1000.0;
234 interframe_delay_ms_video); 303 if (flow_duration_sec >= metrics::kMinRunTimeInSeconds) {
235 RTC_DCHECK_GE(interframe_delay_max_ms_video_, interframe_delay_ms_video); 304 int media_bitrate_kbps = static_cast<int>(stats.total_media_bytes * 8 /
236 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InterframeDelayMaxInMs", 305 flow_duration_sec / 1000);
237 interframe_delay_max_ms_video_); 306 RTC_HISTOGRAM_COUNTS_SPARSE_10000(
307 uma_prefix + ".MediaBitrateReceivedInKbps" + uma_suffix,
308 media_bitrate_kbps);
309 LOG(LS_INFO) << uma_prefix << ".MediaBitrateReceivedInKbps"
310 << uma_suffix << " " << media_bitrate_kbps;
311 }
312
313 int num_total_frames =
314 stats.frame_counts.key_frames + stats.frame_counts.delta_frames;
315 if (num_total_frames >= kMinRequiredSamples) {
316 int num_key_frames = stats.frame_counts.key_frames;
317 int key_frames_permille =
318 (num_key_frames * 1000 + num_total_frames / 2) / num_total_frames;
319 RTC_HISTOGRAM_COUNTS_SPARSE_1000(
320 uma_prefix + ".KeyFramesReceivedInPermille" + uma_suffix,
321 key_frames_permille);
322 LOG(LS_INFO) << uma_prefix << ".KeyFramesReceivedInPermille"
323 << uma_suffix << " " << key_frames_permille;
324 }
325
326 int qp = stats.qp_counter.Avg(kMinRequiredSamples);
327 if (qp != -1) {
328 RTC_HISTOGRAM_COUNTS_SPARSE_200(
329 uma_prefix + ".Decoded.Vp8.Qp" + uma_suffix, qp);
330 LOG(LS_INFO) << uma_prefix << ".Decoded.Vp8.Qp" << uma_suffix << " "
331 << qp;
332 }
333 }
238 } 334 }
239 335
240 StreamDataCounters rtp = stats_.rtp_stats; 336 StreamDataCounters rtp = stats_.rtp_stats;
241 StreamDataCounters rtx; 337 StreamDataCounters rtx;
242 for (auto it : rtx_stats_) 338 for (auto it : rtx_stats_)
243 rtx.Add(it.second); 339 rtx.Add(it.second);
244 StreamDataCounters rtp_rtx = rtp; 340 StreamDataCounters rtp_rtx = rtp;
245 rtp_rtx.Add(rtx); 341 rtp_rtx.Add(rtx);
246 int64_t elapsed_sec = 342 int64_t elapsed_sec =
247 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; 343 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000;
248 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { 344 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
249 RTC_HISTOGRAM_COUNTS_10000( 345 RTC_HISTOGRAM_COUNTS_10000(
250 "WebRTC.Video.BitrateReceivedInKbps", 346 "WebRTC.Video.BitrateReceivedInKbps",
251 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 347 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
252 1000)); 348 1000));
253 RTC_HISTOGRAM_COUNTS_10000( 349 int media_bitrate_kbs =
254 "WebRTC.Video.MediaBitrateReceivedInKbps", 350 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000);
255 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000)); 351 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps",
352 media_bitrate_kbs);
353 LOG(LS_INFO) << "WebRTC.Video.MediaBitrateReceivedInKbps "
354 << media_bitrate_kbs;
256 RTC_HISTOGRAM_COUNTS_10000( 355 RTC_HISTOGRAM_COUNTS_10000(
257 "WebRTC.Video.PaddingBitrateReceivedInKbps", 356 "WebRTC.Video.PaddingBitrateReceivedInKbps",
258 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / 357 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec /
259 1000)); 358 1000));
260 RTC_HISTOGRAM_COUNTS_10000( 359 RTC_HISTOGRAM_COUNTS_10000(
261 "WebRTC.Video.RetransmittedBitrateReceivedInKbps", 360 "WebRTC.Video.RetransmittedBitrateReceivedInKbps",
262 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / 361 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec /
263 1000)); 362 1000));
264 if (!rtx_stats_.empty()) { 363 if (!rtx_stats_.empty()) {
265 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", 364 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps",
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 } 621 }
523 if (total_bytes > last_total_bytes) 622 if (total_bytes > last_total_bytes)
524 total_byte_tracker_.AddSamples(total_bytes - last_total_bytes); 623 total_byte_tracker_.AddSamples(total_bytes - last_total_bytes);
525 } 624 }
526 625
527 void ReceiveStatisticsProxy::OnDecodedFrame(rtc::Optional<uint8_t> qp, 626 void ReceiveStatisticsProxy::OnDecodedFrame(rtc::Optional<uint8_t> qp,
528 VideoContentType content_type) { 627 VideoContentType content_type) {
529 uint64_t now = clock_->TimeInMilliseconds(); 628 uint64_t now = clock_->TimeInMilliseconds();
530 629
531 rtc::CritScope lock(&crit_); 630 rtc::CritScope lock(&crit_);
631
632 ContentSpecificStats* content_specific_stats =
633 &content_specific_stats_[content_type];
532 ++stats_.frames_decoded; 634 ++stats_.frames_decoded;
533 if (qp) { 635 if (qp) {
534 if (!stats_.qp_sum) { 636 if (!stats_.qp_sum) {
535 if (stats_.frames_decoded != 1) { 637 if (stats_.frames_decoded != 1) {
536 LOG(LS_WARNING) 638 LOG(LS_WARNING)
537 << "Frames decoded was not 1 when first qp value was received."; 639 << "Frames decoded was not 1 when first qp value was received.";
538 stats_.frames_decoded = 1; 640 stats_.frames_decoded = 1;
539 } 641 }
540 stats_.qp_sum = rtc::Optional<uint64_t>(0); 642 stats_.qp_sum = rtc::Optional<uint64_t>(0);
541 } 643 }
542 *stats_.qp_sum += *qp; 644 *stats_.qp_sum += *qp;
645 content_specific_stats->qp_counter.Add(*qp);
543 } else if (stats_.qp_sum) { 646 } else if (stats_.qp_sum) {
544 LOG(LS_WARNING) 647 LOG(LS_WARNING)
545 << "QP sum was already set and no QP was given for a frame."; 648 << "QP sum was already set and no QP was given for a frame.";
546 stats_.qp_sum = rtc::Optional<uint64_t>(); 649 stats_.qp_sum = rtc::Optional<uint64_t>();
547 } 650 }
548 last_content_type_ = content_type; 651 last_content_type_ = content_type;
549 decode_fps_estimator_.Update(1, now); 652 decode_fps_estimator_.Update(1, now);
550 if (last_decoded_frame_time_ms_) { 653 if (last_decoded_frame_time_ms_) {
551 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_; 654 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_;
552 RTC_DCHECK_GE(interframe_delay_ms, 0); 655 RTC_DCHECK_GE(interframe_delay_ms, 0);
553 interframe_delay_max_moving_.Add(interframe_delay_ms, now); 656 interframe_delay_max_moving_.Add(interframe_delay_ms, now);
554 if (last_content_type_ == VideoContentType::SCREENSHARE) { 657 content_specific_stats->interframe_delay_counter.Add(interframe_delay_ms);
555 interframe_delay_counter_screenshare_.Add(interframe_delay_ms); 658 content_specific_stats->flow_duration_ms += interframe_delay_ms;
556 if (interframe_delay_max_ms_screenshare_ < interframe_delay_ms) {
557 interframe_delay_max_ms_screenshare_ = interframe_delay_ms;
558 }
559 } else {
560 interframe_delay_counter_video_.Add(interframe_delay_ms);
561 if (interframe_delay_max_ms_video_ < interframe_delay_ms) {
562 interframe_delay_max_ms_video_ = interframe_delay_ms;
563 }
564 }
565 } 659 }
566 last_decoded_frame_time_ms_.emplace(now); 660 last_decoded_frame_time_ms_.emplace(now);
567 } 661 }
568 662
569 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) { 663 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
570 int width = frame.width(); 664 int width = frame.width();
571 int height = frame.height(); 665 int height = frame.height();
572 RTC_DCHECK_GT(width, 0); 666 RTC_DCHECK_GT(width, 0);
573 RTC_DCHECK_GT(height, 0); 667 RTC_DCHECK_GT(height, 0);
574 uint64_t now = clock_->TimeInMilliseconds(); 668 uint64_t now = clock_->TimeInMilliseconds();
575
576 rtc::CritScope lock(&crit_); 669 rtc::CritScope lock(&crit_);
670 ContentSpecificStats* content_specific_stats =
671 &content_specific_stats_[last_content_type_];
577 renders_fps_estimator_.Update(1, now); 672 renders_fps_estimator_.Update(1, now);
578 ++stats_.frames_rendered; 673 ++stats_.frames_rendered;
579 stats_.width = width; 674 stats_.width = width;
580 stats_.height = height; 675 stats_.height = height;
581 render_width_counter_.Add(width);
582 render_height_counter_.Add(height);
583 render_fps_tracker_.AddSamples(1); 676 render_fps_tracker_.AddSamples(1);
584 render_pixel_tracker_.AddSamples(sqrt(width * height)); 677 render_pixel_tracker_.AddSamples(sqrt(width * height));
678 content_specific_stats->received_width.Add(width);
679 content_specific_stats->received_height.Add(height);
585 680
586 if (frame.ntp_time_ms() > 0) { 681 if (frame.ntp_time_ms() > 0) {
587 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms(); 682 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
588 if (delay_ms >= 0) { 683 if (delay_ms >= 0) {
589 if (last_content_type_ == VideoContentType::SCREENSHARE) { 684 content_specific_stats->e2e_delay_counter.Add(delay_ms);
590 e2e_delay_max_ms_screenshare_ =
591 std::max(delay_ms, e2e_delay_max_ms_screenshare_);
592 e2e_delay_counter_screenshare_.Add(delay_ms);
593 } else {
594 e2e_delay_max_ms_video_ = std::max(delay_ms, e2e_delay_max_ms_video_);
595 e2e_delay_counter_video_.Add(delay_ms);
596 }
597 } 685 }
598 } 686 }
599 } 687 }
600 688
601 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms, 689 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms,
602 double estimated_freq_khz) { 690 double estimated_freq_khz) {
603 rtc::CritScope lock(&crit_); 691 rtc::CritScope lock(&crit_);
604 sync_offset_counter_.Add(std::abs(sync_offset_ms)); 692 sync_offset_counter_.Add(std::abs(sync_offset_ms));
605 stats_.sync_offset_ms = sync_offset_ms; 693 stats_.sync_offset_ms = sync_offset_ms;
606 694
607 const double kMaxFreqKhz = 10000.0; 695 const double kMaxFreqKhz = 10000.0;
608 int offset_khz = kMaxFreqKhz; 696 int offset_khz = kMaxFreqKhz;
609 // Should not be zero or negative. If so, report max. 697 // Should not be zero or negative. If so, report max.
610 if (estimated_freq_khz < kMaxFreqKhz && estimated_freq_khz > 0.0) 698 if (estimated_freq_khz < kMaxFreqKhz && estimated_freq_khz > 0.0)
611 offset_khz = static_cast<int>(std::fabs(estimated_freq_khz - 90.0) + 0.5); 699 offset_khz = static_cast<int>(std::fabs(estimated_freq_khz - 90.0) + 0.5);
612 700
613 freq_offset_counter_.Add(offset_khz); 701 freq_offset_counter_.Add(offset_khz);
614 } 702 }
615 703
616 void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate, 704 void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate,
617 uint32_t frameRate) { 705 uint32_t frameRate) {
618 } 706 }
619 707
620 void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe, 708 void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe,
621 size_t size_bytes) { 709 size_t size_bytes,
710 VideoContentType content_type) {
622 rtc::CritScope lock(&crit_); 711 rtc::CritScope lock(&crit_);
623 if (is_keyframe) 712 if (is_keyframe) {
624 ++stats_.frame_counts.key_frames; 713 ++stats_.frame_counts.key_frames;
625 else 714 } else {
626 ++stats_.frame_counts.delta_frames; 715 ++stats_.frame_counts.delta_frames;
716 }
717
718 ContentSpecificStats* content_specific_stats =
719 &content_specific_stats_[content_type];
720
721 content_specific_stats->total_media_bytes += size_bytes;
722 if (is_keyframe) {
723 ++content_specific_stats->frame_counts.key_frames;
724 } else {
725 ++content_specific_stats->frame_counts.delta_frames;
726 }
627 727
628 int64_t now_ms = clock_->TimeInMilliseconds(); 728 int64_t now_ms = clock_->TimeInMilliseconds();
629 frame_window_.insert(std::make_pair(now_ms, size_bytes)); 729 frame_window_.insert(std::make_pair(now_ms, size_bytes));
630 UpdateFramerate(now_ms); 730 UpdateFramerate(now_ms);
631 } 731 }
632 732
633 void ReceiveStatisticsProxy::OnFrameCountsUpdated( 733 void ReceiveStatisticsProxy::OnFrameCountsUpdated(
634 const FrameCounts& frame_counts) { 734 const FrameCounts& frame_counts) {
635 rtc::CritScope lock(&crit_); 735 rtc::CritScope lock(&crit_);
636 stats_.frame_counts = frame_counts; 736 stats_.frame_counts = frame_counts;
(...skipping 21 matching lines...) Expand all
658 // TODO(sprang): Figure out any other state that should be reset. 758 // TODO(sprang): Figure out any other state that should be reset.
659 759
660 rtc::CritScope lock(&crit_); 760 rtc::CritScope lock(&crit_);
661 // Don't report inter-frame delay if stream was paused. 761 // Don't report inter-frame delay if stream was paused.
662 last_decoded_frame_time_ms_.reset(); 762 last_decoded_frame_time_ms_.reset();
663 } 763 }
664 764
665 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { 765 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
666 sum += sample; 766 sum += sample;
667 ++num_samples; 767 ++num_samples;
768 if (!max || sample > *max) {
769 max.emplace(sample);
770 }
771 }
772
773 void ReceiveStatisticsProxy::SampleCounter::Add(const SampleCounter& other) {
774 sum += other.sum;
775 num_samples += other.num_samples;
776 if (other.max && (!max || *max < *other.max))
777 max = other.max;
668 } 778 }
669 779
670 int ReceiveStatisticsProxy::SampleCounter::Avg( 780 int ReceiveStatisticsProxy::SampleCounter::Avg(
671 int64_t min_required_samples) const { 781 int64_t min_required_samples) const {
672 if (num_samples < min_required_samples || num_samples == 0) 782 if (num_samples < min_required_samples || num_samples == 0)
673 return -1; 783 return -1;
674 return static_cast<int>(sum / num_samples); 784 return static_cast<int>(sum / num_samples);
675 } 785 }
676 786
787 int ReceiveStatisticsProxy::SampleCounter::Max() const {
788 return max.value_or(-1);
789 }
790
677 void ReceiveStatisticsProxy::SampleCounter::Reset() { 791 void ReceiveStatisticsProxy::SampleCounter::Reset() {
678 num_samples = 0; 792 num_samples = 0;
679 sum = 0; 793 sum = 0;
794 max.reset();
680 } 795 }
681 796
682 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms, 797 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
683 int64_t max_rtt_ms) { 798 int64_t max_rtt_ms) {
684 rtc::CritScope lock(&crit_); 799 rtc::CritScope lock(&crit_);
685 avg_rtt_ms_ = avg_rtt_ms; 800 avg_rtt_ms_ = avg_rtt_ms;
686 } 801 }
687 802
803 void ReceiveStatisticsProxy::ContentSpecificStats::Add(
804 const ContentSpecificStats& other) {
805 e2e_delay_counter.Add(other.e2e_delay_counter);
806 interframe_delay_counter.Add(other.interframe_delay_counter);
807 flow_duration_ms += other.flow_duration_ms;
808 total_media_bytes += other.total_media_bytes;
809 received_height.Add(other.received_height);
810 received_width.Add(other.received_width);
811 qp_counter.Add(other.qp_counter);
812 frame_counts.key_frames += other.frame_counts.key_frames;
813 frame_counts.delta_frames += other.frame_counts.delta_frames;
814 }
815
688 } // namespace webrtc 816 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/receive_statistics_proxy.h ('k') | webrtc/video/receive_statistics_proxy_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698