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