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

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: Add new sliced metrics, tests and implement commets by Sprang@ 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" 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
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 UmaSpatialSuffixForContentType(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 UmaExperimentSuffixConentType(VideoContentType content_type) {
sprang_webrtc 2017/08/25 13:56:29 nit: UmaExperimentSuffixForContentType
ilnik 2017/08/25 14:14:27 Done.
70 std::stringstream ss;
71 int experiment_id = content_type.GetExperimentId();
72 if (experiment_id > 0) {
73 ss << ".ExperimentGroup" << experiment_id - 1;
74 }
75 return ss.str();
76 }
48 } // namespace 77 } // namespace
49 78
50 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 79 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
51 const VideoReceiveStream::Config* config, 80 const VideoReceiveStream::Config* config,
52 Clock* clock) 81 Clock* clock)
53 : clock_(clock), 82 : clock_(clock),
54 config_(*config), 83 config_(*config),
55 start_ms_(clock->TimeInMilliseconds()), 84 start_ms_(clock->TimeInMilliseconds()),
56 last_sample_time_(clock->TimeInMilliseconds()), 85 last_sample_time_(clock->TimeInMilliseconds()),
57 fps_threshold_(kLowFpsThreshold, 86 fps_threshold_(kLowFpsThreshold,
58 kHighFpsThreshold, 87 kHighFpsThreshold,
59 kBadFraction, 88 kBadFraction,
60 kNumMeasurements), 89 kNumMeasurements),
61 qp_threshold_(kLowQpThresholdVp8, 90 qp_threshold_(kLowQpThresholdVp8,
62 kHighQpThresholdVp8, 91 kHighQpThresholdVp8,
63 kBadFraction, 92 kBadFraction,
64 kNumMeasurements), 93 kNumMeasurements),
65 variance_threshold_(kLowVarianceThreshold, 94 variance_threshold_(kLowVarianceThreshold,
66 kHighVarianceThreshold, 95 kHighVarianceThreshold,
67 kBadFraction, 96 kBadFraction,
68 kNumMeasurementsVariance), 97 kNumMeasurementsVariance),
69 num_bad_states_(0), 98 num_bad_states_(0),
70 num_certain_states_(0), 99 num_certain_states_(0),
71 // 1000ms window, scale 1000 for ms to s. 100 // 1000ms window, scale 1000 for ms to s.
72 decode_fps_estimator_(1000, 1000), 101 decode_fps_estimator_(1000, 1000),
73 renders_fps_estimator_(1000, 1000), 102 renders_fps_estimator_(1000, 1000),
74 render_fps_tracker_(100, 10u), 103 render_fps_tracker_(100, 10u),
75 render_pixel_tracker_(100, 10u), 104 render_pixel_tracker_(100, 10u),
76 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count 105 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), 106 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
82 first_report_block_time_ms_(-1), 107 first_report_block_time_ms_(-1),
83 avg_rtt_ms_(0), 108 avg_rtt_ms_(0),
84 last_content_type_(VideoContentType::UNSPECIFIED) { 109 last_content_type_(VideoContentType::UNSPECIFIED) {
85 stats_.ssrc = config_.rtp.remote_ssrc; 110 stats_.ssrc = config_.rtp.remote_ssrc;
86 // TODO(brandtr): Replace |rtx_stats_| with a single instance of 111 // TODO(brandtr): Replace |rtx_stats_| with a single instance of
87 // StreamDataCounters. 112 // StreamDataCounters.
88 if (config_.rtp.rtx_ssrc) { 113 if (config_.rtp.rtx_ssrc) {
89 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); 114 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters();
90 } 115 }
91 } 116 }
92 117
93 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { 118 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
94 UpdateHistograms(); 119 UpdateHistograms();
95 } 120 }
96 121
97 void ReceiveStatisticsProxy::UpdateHistograms() { 122 void ReceiveStatisticsProxy::UpdateHistograms() {
98 RTC_HISTOGRAM_COUNTS_100000( 123 const int kMinRequiredSamples = 200;
99 "WebRTC.Video.ReceiveStreamLifetimeInSeconds",
100 (clock_->TimeInMilliseconds() - start_ms_) / 1000);
101 124
102 if (first_report_block_time_ms_ != -1 &&
103 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >=
104 metrics::kMinRunTimeInSeconds) {
105 int fraction_lost = report_block_stats_.FractionLostInPercent();
106 if (fraction_lost != -1) {
107 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
108 fraction_lost);
109 LOG(LS_INFO) << "WebRTC.Video.ReceivedPacketsLostInPercent "
110 << fraction_lost;
111 }
112 }
113
114 const int kMinRequiredSamples = 200;
115 int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount()); 125 int samples = static_cast<int>(render_fps_tracker_.TotalSampleCount());
116 if (samples >= kMinRequiredSamples) { 126 if (samples >= kMinRequiredSamples) {
117 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond", 127 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.RenderFramesPerSecond",
118 round(render_fps_tracker_.ComputeTotalRate())); 128 round(render_fps_tracker_.ComputeTotalRate()));
119 RTC_HISTOGRAM_COUNTS_100000( 129 RTC_HISTOGRAM_COUNTS_100000(
120 "WebRTC.Video.RenderSqrtPixelsPerSecond", 130 "WebRTC.Video.RenderSqrtPixelsPerSecond",
121 round(render_pixel_tracker_.ComputeTotalRate())); 131 round(render_pixel_tracker_.ComputeTotalRate()));
122 } 132 }
133
134 // Slice on content type and simulcast id.
135 for (auto it : content_specific_stats_) {
136 auto content_type = it.first;
137 if (content_type.GetExperimentId() == 0 &&
138 content_type.GetSimulcastId() == 0) {
139 // Name of a metric sliced on simulcast is the same as sliced on
140 // experiment because no slice information is available in both cases.
141 // Don't report the metric here to not duplicate the metric.
142 continue;
143 }
144 auto stats = it.second;
145 std::string uma_prefix = UmaPrefixForContentType(content_type);
146 std::string uma_suffix = UmaSpatialSuffixForContentType(content_type);
147 // The same line of code can't report different histograms because of how
148 // macro is done. Additional index needed to be different for all different
149 // names. Since experiment can't change during call, we could report 4*2
150 // different content types (4 simulcast_ids x 2 content types).
151 // Conveniently all of these are stored in 3 lower bits in VideoContentType.
152 int idx = content_type.content_type & 0x07;
153 int e2e_delay_ms = stats.e2e_delay_counter.Avg(kMinRequiredSamples);
154 if (e2e_delay_ms != -1) {
155 RTC_HISTOGRAMS_COUNTS_10000(
156 idx, uma_prefix + ".EndToEndDelayInMs" + uma_suffix, e2e_delay_ms);
157 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayInMs" << uma_suffix << " "
158 << e2e_delay_ms;
159 }
160 int e2e_delay_max_ms = stats.e2e_delay_counter.Max();
161 if (e2e_delay_max_ms != -1 && e2e_delay_ms != -1) {
162 RTC_HISTOGRAMS_COUNTS_100000(
163 idx, uma_prefix + ".EndToEndDelayMaxInMs" + uma_suffix,
164 e2e_delay_max_ms);
165 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayMaxInMs" << uma_suffix << " "
166 << e2e_delay_max_ms;
167 }
168 int interframe_delay_ms =
169 stats.interframe_delay_counter.Avg(kMinRequiredSamples);
170 if (interframe_delay_ms != -1) {
171 RTC_HISTOGRAMS_COUNTS_10000(
172 idx, uma_prefix + ".InterframeDelayInMs" + uma_suffix,
173 interframe_delay_ms);
174 LOG(LS_INFO) << uma_prefix << ".InterframeDelayInMs" << uma_suffix << " "
175 << interframe_delay_ms;
176 }
177 int interframe_delay_max_ms = stats.interframe_delay_counter.Max();
178 if (interframe_delay_max_ms != -1 && interframe_delay_ms != -1) {
179 RTC_HISTOGRAMS_COUNTS_10000(
180 idx, uma_prefix + ".InterframeDelayMaxInMs" + uma_suffix,
181 interframe_delay_max_ms);
182 LOG(LS_INFO) << uma_prefix << ".InterframeDelayMaxInMs" << uma_suffix
183 << " " << interframe_delay_max_ms;
184 }
185
186 float flow_duration_sec = stats.flow_duration_ms / 1000.0;
187 if (flow_duration_sec >= metrics::kMinRunTimeInSeconds) {
188 int media_bitrate_kbps = static_cast<int>(stats.total_media_bytes * 8 /
189 flow_duration_sec / 1000);
190 RTC_HISTOGRAM_COUNTS_10000(
191 uma_prefix + ".MediaBitrateReceivedInKbps" + uma_suffix,
192 media_bitrate_kbps);
193 LOG(LS_INFO) << uma_prefix << ".MediaBitrateReceivedInKbps" << uma_suffix
194 << " " << media_bitrate_kbps;
195 }
196
197 int qp = stats.qp_counter.Avg(kMinRequiredSamples);
198 if (qp != -1) {
199 RTC_HISTOGRAMS_COUNTS_200(
200 idx, uma_prefix + ".Decoded.Vp8.Qp" + uma_suffix, qp);
201 LOG(LS_INFO) << uma_prefix << ".Decoded.Vp8.Qp" << uma_suffix << " "
202 << qp;
203 }
204
205 int width = stats.received_width.Avg(kMinRequiredSamples);
206 if (width != -1) {
207 RTC_HISTOGRAMS_COUNTS_10000(
208 idx, uma_prefix + ".ReceivedWidthInPixels" + uma_suffix, width);
209 LOG(LS_INFO) << uma_prefix << ".ReceivedWidthInPixels" << uma_suffix
210 << " " << width;
211 }
212
213 int height = stats.received_height.Avg(kMinRequiredSamples);
214 if (height != -1) {
215 RTC_HISTOGRAMS_COUNTS_10000(
216 idx, uma_prefix + ".ReceivedHeightInPixels" + uma_suffix, height);
217 LOG(LS_INFO) << uma_prefix << ".ReceivedHeightInPixels" << uma_suffix
218 << " " << height;
219 }
220 }
221
222 std::string uma_prefix = UmaPrefixForContentType(last_content_type_);
223 std::string uma_experiment_suffix =
224 UmaExperimentSuffixConentType(last_content_type_);
sprang_webrtc 2017/08/25 13:56:29 I think these might unfortunately change during th
ilnik 2017/08/25 14:14:27 Done.
225 int idx = (last_content_type_.IsScreenshare() ? 1 : 0) +
226 (last_content_type_.GetExperimentId() << 1);
227
228 if (first_report_block_time_ms_ != -1 &&
229 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >=
230 metrics::kMinRunTimeInSeconds) {
231 int fraction_lost = report_block_stats_.FractionLostInPercent();
232 if (fraction_lost != -1) {
233 RTC_HISTOGRAMS_PERCENTAGE(
234 idx,
235 uma_prefix + ".ReceivedPacketsLostInPercent" + uma_experiment_suffix,
236 fraction_lost);
237 LOG(LS_INFO) << uma_prefix << ".ReceivedPacketsLostInPercent"
238 << uma_experiment_suffix << " " << fraction_lost;
239 }
240 }
241
242 int stream_duration_sec = (clock_->TimeInMilliseconds() - start_ms_) / 1000;
243 RTC_HISTOGRAMS_COUNTS_100000(
244 idx,
245 uma_prefix + ".ReceiveStreamLifetimeInSeconds" + uma_experiment_suffix,
246 stream_duration_sec);
247 LOG(LS_INFO) << uma_prefix << ".ReceiveStreamLifetimeInSeconds"
248 << uma_experiment_suffix << " " << stream_duration_sec;
249
250 int e2e_delay_ms = e2e_delay_counter.Avg(kMinRequiredSamples);
251 if (e2e_delay_ms != -1) {
252 RTC_HISTOGRAMS_COUNTS_10000(
253 idx, uma_prefix + ".EndToEndDelayInMs" + uma_experiment_suffix,
254 e2e_delay_ms);
255 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayInMs" << uma_experiment_suffix
256 << " " << e2e_delay_ms;
257 }
258 int e2e_delay_max_ms = e2e_delay_counter.Max();
259 if (e2e_delay_max_ms != -1 && e2e_delay_ms != -1) {
260 RTC_HISTOGRAMS_COUNTS_100000(
261 idx, uma_prefix + ".EndToEndDelayMaxInMs" + uma_experiment_suffix,
262 e2e_delay_max_ms);
263 LOG(LS_INFO) << uma_prefix << ".EndToEndDelayMaxInMs"
264 << uma_experiment_suffix << " " << e2e_delay_max_ms;
265 }
266 int interframe_delay_ms = interframe_delay_counter.Avg(kMinRequiredSamples);
267 if (interframe_delay_ms != -1) {
268 RTC_HISTOGRAMS_COUNTS_10000(
269 idx, uma_prefix + ".InterframeDelayInMs" + uma_experiment_suffix,
270 interframe_delay_ms);
271 LOG(LS_INFO) << uma_prefix << ".InterframeDelayInMs"
272 << uma_experiment_suffix << " " << interframe_delay_ms;
273 }
274 int interframe_delay_max_ms = interframe_delay_counter.Max();
275 if (interframe_delay_max_ms != -1 && interframe_delay_ms != -1) {
276 RTC_HISTOGRAMS_COUNTS_10000(
277 idx, uma_prefix + ".InterframeDelayMaxInMs" + uma_experiment_suffix,
278 interframe_delay_max_ms);
279 LOG(LS_INFO) << uma_prefix << ".InterframeDelayMaxInMs"
280 << uma_experiment_suffix << " " << interframe_delay_max_ms;
281 }
282
123 int width = render_width_counter_.Avg(kMinRequiredSamples); 283 int width = render_width_counter_.Avg(kMinRequiredSamples);
124 int height = render_height_counter_.Avg(kMinRequiredSamples); 284 int height = render_height_counter_.Avg(kMinRequiredSamples);
125 if (width != -1) { 285 if (width != -1) {
126 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedWidthInPixels", width); 286 RTC_HISTOGRAMS_COUNTS_10000(
127 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.ReceivedHeightInPixels", height); 287 idx, uma_prefix + ".ReceivedWidthInPixels" + uma_experiment_suffix,
128 LOG(LS_INFO) << "WebRTC.Video.ReceivedWidthInPixels " << width; 288 width);
129 LOG(LS_INFO) << "WebRTC.Video.ReceivedHeightInPixels " << height; 289 RTC_HISTOGRAMS_COUNTS_10000(
290 idx, uma_prefix + ".ReceivedHeightInPixels" + uma_experiment_suffix,
291 height);
292 LOG(LS_INFO) << uma_prefix << ".ReceivedWidthInPixels"
293 << uma_experiment_suffix << " " << width;
294 LOG(LS_INFO) << uma_prefix << ".ReceivedHeightInPixels"
295 << uma_experiment_suffix << " " << height;
130 } 296 }
131 int sync_offset_ms = sync_offset_counter_.Avg(kMinRequiredSamples); 297 int sync_offset_ms = sync_offset_counter_.Avg(kMinRequiredSamples);
132 if (sync_offset_ms != -1) { 298 if (sync_offset_ms != -1) {
133 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms); 299 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms);
134 LOG(LS_INFO) << "WebRTC.Video.AVSyncOffsetInMs " << sync_offset_ms; 300 LOG(LS_INFO) << "WebRTC.Video.AVSyncOffsetInMs " << sync_offset_ms;
135 } 301 }
136 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats(); 302 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats();
137 if (freq_offset_stats.num_samples > 0) { 303 if (freq_offset_stats.num_samples > 0) {
138 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 304 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz",
139 freq_offset_stats.average); 305 freq_offset_stats.average);
140 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, " 306 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, "
141 << freq_offset_stats.ToString(); 307 << freq_offset_stats.ToString();
142 } 308 }
143 309
144 int num_total_frames = 310 int num_total_frames =
145 stats_.frame_counts.key_frames + stats_.frame_counts.delta_frames; 311 stats_.frame_counts.key_frames + stats_.frame_counts.delta_frames;
146 if (num_total_frames >= kMinRequiredSamples) { 312 if (num_total_frames >= kMinRequiredSamples) {
147 int num_key_frames = stats_.frame_counts.key_frames; 313 int num_key_frames = stats_.frame_counts.key_frames;
148 int key_frames_permille = 314 int key_frames_permille =
149 (num_key_frames * 1000 + num_total_frames / 2) / num_total_frames; 315 (num_key_frames * 1000 + num_total_frames / 2) / num_total_frames;
150 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille", 316 RTC_HISTOGRAMS_COUNTS_1000(
151 key_frames_permille); 317 idx,
152 LOG(LS_INFO) << "WebRTC.Video.KeyFramesReceivedInPermille " 318 uma_prefix + ".KeyFramesReceivedInPermille" + uma_experiment_suffix,
153 << key_frames_permille; 319 key_frames_permille);
320 LOG(LS_INFO) << uma_prefix << ".KeyFramesReceivedInPermille"
321 << uma_experiment_suffix << " " << key_frames_permille;
154 } 322 }
155 323
156 int qp = qp_counters_.vp8.Avg(kMinRequiredSamples); 324 int qp = qp_counters_.vp8.Avg(kMinRequiredSamples);
157 if (qp != -1) { 325 if (qp != -1) {
158 RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", qp); 326 RTC_HISTOGRAMS_COUNTS_200(
159 LOG(LS_INFO) << "WebRTC.Video.Decoded.Vp8.Qp " << qp; 327 idx, uma_prefix + ".Decoded.Vp8.Qp" + uma_experiment_suffix, qp);
328 LOG(LS_INFO) << uma_prefix << ".Decoded.Vp8.Qp" << uma_experiment_suffix
329 << " " << qp;
160 } 330 }
161 int decode_ms = decode_time_counter_.Avg(kMinRequiredSamples); 331 int decode_ms = decode_time_counter_.Avg(kMinRequiredSamples);
162 if (decode_ms != -1) { 332 if (decode_ms != -1) {
163 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", decode_ms); 333 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", decode_ms);
164 LOG(LS_INFO) << "WebRTC.Video.DecodeTimeInMs " << decode_ms; 334 LOG(LS_INFO) << "WebRTC.Video.DecodeTimeInMs " << decode_ms;
165 } 335 }
166 int jb_delay_ms = jitter_buffer_delay_counter_.Avg(kMinRequiredSamples); 336 int jb_delay_ms = jitter_buffer_delay_counter_.Avg(kMinRequiredSamples);
167 if (jb_delay_ms != -1) { 337 if (jb_delay_ms != -1) {
168 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs", 338 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs",
169 jb_delay_ms); 339 jb_delay_ms);
170 LOG(LS_INFO) << "WebRTC.Video.JitterBufferDelayInMs " << jb_delay_ms; 340 LOG(LS_INFO) << "WebRTC.Video.JitterBufferDelayInMs " << jb_delay_ms;
171 } 341 }
172 342
173 int target_delay_ms = target_delay_counter_.Avg(kMinRequiredSamples); 343 int target_delay_ms = target_delay_counter_.Avg(kMinRequiredSamples);
174 if (target_delay_ms != -1) { 344 if (target_delay_ms != -1) {
175 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.TargetDelayInMs", target_delay_ms); 345 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.TargetDelayInMs", target_delay_ms);
176 LOG(LS_INFO) << "WebRTC.Video.TargetDelayInMs " << target_delay_ms; 346 LOG(LS_INFO) << "WebRTC.Video.TargetDelayInMs " << target_delay_ms;
177 } 347 }
178 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples); 348 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples);
179 if (current_delay_ms != -1) { 349 if (current_delay_ms != -1) {
180 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", 350 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs",
181 current_delay_ms); 351 current_delay_ms);
182 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms; 352 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms;
183 } 353 }
184 int delay_ms = delay_counter_.Avg(kMinRequiredSamples); 354 int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
185 if (delay_ms != -1) 355 if (delay_ms != -1)
186 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms); 356 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms);
187 357
188 int e2e_delay_ms_video = e2e_delay_counter_video_.Avg(kMinRequiredSamples);
189 if (e2e_delay_ms_video != -1) {
190 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.EndToEndDelayInMs",
191 e2e_delay_ms_video);
192 LOG(LS_INFO) << "WebRTC.Video.EndToEndDelayInMs " << e2e_delay_ms_video;
193 }
194
195 int e2e_delay_ms_screenshare =
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
236 StreamDataCounters rtp = stats_.rtp_stats; 358 StreamDataCounters rtp = stats_.rtp_stats;
237 StreamDataCounters rtx; 359 StreamDataCounters rtx;
238 for (auto it : rtx_stats_) 360 for (auto it : rtx_stats_)
239 rtx.Add(it.second); 361 rtx.Add(it.second);
240 StreamDataCounters rtp_rtx = rtp; 362 StreamDataCounters rtp_rtx = rtp;
241 rtp_rtx.Add(rtx); 363 rtp_rtx.Add(rtx);
242 int64_t elapsed_sec = 364 int64_t elapsed_sec =
243 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; 365 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000;
244 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { 366 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
245 RTC_HISTOGRAM_COUNTS_10000( 367 RTC_HISTOGRAM_COUNTS_10000(
246 "WebRTC.Video.BitrateReceivedInKbps", 368 "WebRTC.Video.BitrateReceivedInKbps",
247 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / 369 static_cast<int>(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec /
248 1000)); 370 1000));
249 RTC_HISTOGRAM_COUNTS_10000( 371 int media_bitrate_kbs =
250 "WebRTC.Video.MediaBitrateReceivedInKbps", 372 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000);
251 static_cast<int>(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000)); 373 RTC_HISTOGRAMS_COUNTS_10000(
374 idx, uma_prefix + ".MediaBitrateReceivedInKbps" + uma_experiment_suffix,
375 media_bitrate_kbs);
376 LOG(LS_INFO) << uma_prefix << ".MediaBitrateReceivedInKbps"
377 << uma_experiment_suffix << " " << media_bitrate_kbs;
252 RTC_HISTOGRAM_COUNTS_10000( 378 RTC_HISTOGRAM_COUNTS_10000(
253 "WebRTC.Video.PaddingBitrateReceivedInKbps", 379 "WebRTC.Video.PaddingBitrateReceivedInKbps",
254 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / 380 static_cast<int>(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec /
255 1000)); 381 1000));
256 RTC_HISTOGRAM_COUNTS_10000( 382 RTC_HISTOGRAM_COUNTS_10000(
257 "WebRTC.Video.RetransmittedBitrateReceivedInKbps", 383 "WebRTC.Video.RetransmittedBitrateReceivedInKbps",
258 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / 384 static_cast<int>(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec /
259 1000)); 385 1000));
260 if (!rtx_stats_.empty()) { 386 if (!rtx_stats_.empty()) {
261 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", 387 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps",
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 } 642 }
517 if (total_bytes > last_total_bytes) 643 if (total_bytes > last_total_bytes)
518 total_byte_tracker_.AddSamples(total_bytes - last_total_bytes); 644 total_byte_tracker_.AddSamples(total_bytes - last_total_bytes);
519 } 645 }
520 646
521 void ReceiveStatisticsProxy::OnDecodedFrame(rtc::Optional<uint8_t> qp, 647 void ReceiveStatisticsProxy::OnDecodedFrame(rtc::Optional<uint8_t> qp,
522 VideoContentType content_type) { 648 VideoContentType content_type) {
523 uint64_t now = clock_->TimeInMilliseconds(); 649 uint64_t now = clock_->TimeInMilliseconds();
524 650
525 rtc::CritScope lock(&crit_); 651 rtc::CritScope lock(&crit_);
652
653 ContentSpecificStats* content_specific_stats =
654 &content_specific_stats_[content_type];
526 ++stats_.frames_decoded; 655 ++stats_.frames_decoded;
527 if (qp) { 656 if (qp) {
528 if (!stats_.qp_sum) { 657 if (!stats_.qp_sum) {
529 if (stats_.frames_decoded != 1) { 658 if (stats_.frames_decoded != 1) {
530 LOG(LS_WARNING) 659 LOG(LS_WARNING)
531 << "Frames decoded was not 1 when first qp value was received."; 660 << "Frames decoded was not 1 when first qp value was received.";
532 stats_.frames_decoded = 1; 661 stats_.frames_decoded = 1;
533 } 662 }
534 stats_.qp_sum = rtc::Optional<uint64_t>(0); 663 stats_.qp_sum = rtc::Optional<uint64_t>(0);
535 } 664 }
536 *stats_.qp_sum += *qp; 665 *stats_.qp_sum += *qp;
666 content_specific_stats->qp_counter.Add(*qp);
537 } else if (stats_.qp_sum) { 667 } else if (stats_.qp_sum) {
538 LOG(LS_WARNING) 668 LOG(LS_WARNING)
539 << "QP sum was already set and no QP was given for a frame."; 669 << "QP sum was already set and no QP was given for a frame.";
540 stats_.qp_sum = rtc::Optional<uint64_t>(); 670 stats_.qp_sum = rtc::Optional<uint64_t>();
541 } 671 }
542 last_content_type_ = content_type; 672 last_content_type_ = content_type;
543 decode_fps_estimator_.Update(1, now); 673 decode_fps_estimator_.Update(1, now);
544 if (last_decoded_frame_time_ms_) { 674 if (last_decoded_frame_time_ms_) {
545 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_; 675 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_;
546 RTC_DCHECK_GE(interframe_delay_ms, 0); 676 RTC_DCHECK_GE(interframe_delay_ms, 0);
547 stats_.interframe_delay_sum_ms += interframe_delay_ms; 677 stats_.interframe_delay_sum_ms += interframe_delay_ms;
548 if (last_content_type_ == VideoContentType::SCREENSHARE) { 678 content_specific_stats->interframe_delay_counter.Add(interframe_delay_ms);
549 interframe_delay_counter_screenshare_.Add(interframe_delay_ms); 679 content_specific_stats->flow_duration_ms += interframe_delay_ms;
550 if (interframe_delay_max_ms_screenshare_ < interframe_delay_ms) { 680 interframe_delay_counter.Add(interframe_delay_ms);
551 interframe_delay_max_ms_screenshare_ = interframe_delay_ms;
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 }
559 } 681 }
560 last_decoded_frame_time_ms_.emplace(now); 682 last_decoded_frame_time_ms_.emplace(now);
561 } 683 }
562 684
563 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) { 685 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
564 int width = frame.width(); 686 int width = frame.width();
565 int height = frame.height(); 687 int height = frame.height();
566 RTC_DCHECK_GT(width, 0); 688 RTC_DCHECK_GT(width, 0);
567 RTC_DCHECK_GT(height, 0); 689 RTC_DCHECK_GT(height, 0);
568 uint64_t now = clock_->TimeInMilliseconds(); 690 uint64_t now = clock_->TimeInMilliseconds();
569
570 rtc::CritScope lock(&crit_); 691 rtc::CritScope lock(&crit_);
692 ContentSpecificStats* content_specific_stats =
693 &content_specific_stats_[last_content_type_];
571 renders_fps_estimator_.Update(1, now); 694 renders_fps_estimator_.Update(1, now);
572 ++stats_.frames_rendered; 695 ++stats_.frames_rendered;
573 stats_.width = width; 696 stats_.width = width;
574 stats_.height = height; 697 stats_.height = height;
575 render_width_counter_.Add(width); 698 render_width_counter_.Add(width);
576 render_height_counter_.Add(height); 699 render_height_counter_.Add(height);
577 render_fps_tracker_.AddSamples(1); 700 render_fps_tracker_.AddSamples(1);
578 render_pixel_tracker_.AddSamples(sqrt(width * height)); 701 render_pixel_tracker_.AddSamples(sqrt(width * height));
702 content_specific_stats->received_width.Add(width);
703 content_specific_stats->received_height.Add(height);
579 704
580 if (frame.ntp_time_ms() > 0) { 705 if (frame.ntp_time_ms() > 0) {
581 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms(); 706 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
582 if (delay_ms >= 0) { 707 if (delay_ms >= 0) {
583 if (last_content_type_ == VideoContentType::SCREENSHARE) { 708 content_specific_stats->e2e_delay_counter.Add(delay_ms);
584 e2e_delay_max_ms_screenshare_ = 709 e2e_delay_counter.Add(delay_ms);
585 std::max(delay_ms, e2e_delay_max_ms_screenshare_);
586 e2e_delay_counter_screenshare_.Add(delay_ms);
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 }
591 } 710 }
592 } 711 }
593 } 712 }
594 713
595 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms, 714 void ReceiveStatisticsProxy::OnSyncOffsetUpdated(int64_t sync_offset_ms,
596 double estimated_freq_khz) { 715 double estimated_freq_khz) {
597 rtc::CritScope lock(&crit_); 716 rtc::CritScope lock(&crit_);
598 sync_offset_counter_.Add(std::abs(sync_offset_ms)); 717 sync_offset_counter_.Add(std::abs(sync_offset_ms));
599 stats_.sync_offset_ms = sync_offset_ms; 718 stats_.sync_offset_ms = sync_offset_ms;
600 719
(...skipping 11 matching lines...) Expand all
612 } 731 }
613 732
614 void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe, 733 void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe,
615 size_t size_bytes) { 734 size_t size_bytes) {
616 rtc::CritScope lock(&crit_); 735 rtc::CritScope lock(&crit_);
617 if (is_keyframe) 736 if (is_keyframe)
618 ++stats_.frame_counts.key_frames; 737 ++stats_.frame_counts.key_frames;
619 else 738 else
620 ++stats_.frame_counts.delta_frames; 739 ++stats_.frame_counts.delta_frames;
621 740
741 // Todo(ilnik): May be incorrect for the first frame of a new content type
742 // stream. Leads to a bit incorrect |total_media_bytes| count.
743 ContentSpecificStats* content_specific_stats =
744 &content_specific_stats_[last_content_type_];
745
746 content_specific_stats->total_media_bytes += size_bytes;
747
622 int64_t now_ms = clock_->TimeInMilliseconds(); 748 int64_t now_ms = clock_->TimeInMilliseconds();
623 frame_window_.insert(std::make_pair(now_ms, size_bytes)); 749 frame_window_.insert(std::make_pair(now_ms, size_bytes));
624 UpdateFramerate(now_ms); 750 UpdateFramerate(now_ms);
625 } 751 }
626 752
627 void ReceiveStatisticsProxy::OnFrameCountsUpdated( 753 void ReceiveStatisticsProxy::OnFrameCountsUpdated(
628 const FrameCounts& frame_counts) { 754 const FrameCounts& frame_counts) {
629 rtc::CritScope lock(&crit_); 755 rtc::CritScope lock(&crit_);
630 stats_.frame_counts = frame_counts; 756 stats_.frame_counts = frame_counts;
631 } 757 }
(...skipping 20 matching lines...) Expand all
652 // TODO(sprang): Figure out any other state that should be reset. 778 // TODO(sprang): Figure out any other state that should be reset.
653 779
654 rtc::CritScope lock(&crit_); 780 rtc::CritScope lock(&crit_);
655 // Don't report inter-frame delay if stream was paused. 781 // Don't report inter-frame delay if stream was paused.
656 last_decoded_frame_time_ms_.reset(); 782 last_decoded_frame_time_ms_.reset();
657 } 783 }
658 784
659 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { 785 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
660 sum += sample; 786 sum += sample;
661 ++num_samples; 787 ++num_samples;
788 if (!max || *max < sample) {
789 max.emplace(sample);
790 }
662 } 791 }
663 792
664 int ReceiveStatisticsProxy::SampleCounter::Avg( 793 int ReceiveStatisticsProxy::SampleCounter::Avg(
665 int64_t min_required_samples) const { 794 int64_t min_required_samples) const {
666 if (num_samples < min_required_samples || num_samples == 0) 795 if (num_samples < min_required_samples || num_samples == 0)
667 return -1; 796 return -1;
668 return static_cast<int>(sum / num_samples); 797 return static_cast<int>(sum / num_samples);
669 } 798 }
670 799
800 int ReceiveStatisticsProxy::SampleCounter::Max() const {
801 if (!max) {
802 return -1;
803 } else {
804 return *max;
805 }
806 }
807
671 void ReceiveStatisticsProxy::SampleCounter::Reset() { 808 void ReceiveStatisticsProxy::SampleCounter::Reset() {
672 num_samples = 0; 809 num_samples = 0;
673 sum = 0; 810 sum = 0;
811 max.reset();
674 } 812 }
675 813
676 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms, 814 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
677 int64_t max_rtt_ms) { 815 int64_t max_rtt_ms) {
678 rtc::CritScope lock(&crit_); 816 rtc::CritScope lock(&crit_);
679 avg_rtt_ms_ = avg_rtt_ms; 817 avg_rtt_ms_ = avg_rtt_ms;
680 } 818 }
681 819
682 } // namespace webrtc 820 } // 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