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

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

Issue 2474913002: Logging basic bad call detection (Closed)
Patch Set: Comments Created 4 years 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
« no previous file with comments | « webrtc/video/receive_statistics_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <cmath> 13 #include <cmath>
14 14
15 #include "webrtc/base/checks.h" 15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
16 #include "webrtc/modules/video_coding/include/video_codec_interface.h" 17 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
17 #include "webrtc/system_wrappers/include/clock.h" 18 #include "webrtc/system_wrappers/include/clock.h"
18 #include "webrtc/system_wrappers/include/field_trial.h" 19 #include "webrtc/system_wrappers/include/field_trial.h"
19 #include "webrtc/system_wrappers/include/metrics.h" 20 #include "webrtc/system_wrappers/include/metrics.h"
20 21
21 namespace webrtc { 22 namespace webrtc {
22 namespace { 23 namespace {
23 // Periodic time interval for processing samples for |freq_offset_counter_|. 24 // Periodic time interval for processing samples for |freq_offset_counter_|.
24 const int64_t kFreqOffsetProcessIntervalMs = 40000; 25 const int64_t kFreqOffsetProcessIntervalMs = 40000;
26
27 // Configuration for bad call detection.
28 const int kMinSampleLengthMs = 990;
29 const int kNumMeasurements = 10;
30 const int kNumMeasurementsVariance = kNumMeasurements * 1.5;
31 const float kBadFraction = 0.8f;
32 // For fps:
33 // Low means low enough to be bad, high means high enough to be good
34 const int kLowFpsThreshold = 12;
35 const int kHighFpsThreshold = 14;
36 // For qp and fps variance:
37 // Low means low enough to be good, high means high enough to be bad
38 const int kLowQpThresholdVp8 = 60;
39 const int kHighQpThresholdVp8 = 70;
40 const int kLowVarianceThreshold = 1;
41 const int kHighVarianceThreshold = 2;
25 } // namespace 42 } // namespace
26 43
27 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 44 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
28 const VideoReceiveStream::Config* config, 45 const VideoReceiveStream::Config* config,
29 Clock* clock) 46 Clock* clock)
30 : clock_(clock), 47 : clock_(clock),
31 config_(*config), 48 config_(*config),
32 start_ms_(clock->TimeInMilliseconds()), 49 start_ms_(clock->TimeInMilliseconds()),
50 last_sample_time_(clock->TimeInMilliseconds()),
51 fps_threshold_(kLowFpsThreshold,
52 kHighFpsThreshold,
53 kBadFraction,
54 kNumMeasurements),
55 qp_threshold_(kLowQpThresholdVp8,
56 kHighQpThresholdVp8,
57 kBadFraction,
58 kNumMeasurements),
59 variance_threshold_(kLowVarianceThreshold,
60 kHighVarianceThreshold,
61 kBadFraction,
62 kNumMeasurementsVariance),
33 // 1000ms window, scale 1000 for ms to s. 63 // 1000ms window, scale 1000 for ms to s.
34 decode_fps_estimator_(1000, 1000), 64 decode_fps_estimator_(1000, 1000),
35 renders_fps_estimator_(1000, 1000), 65 renders_fps_estimator_(1000, 1000),
36 render_fps_tracker_(100, 10u), 66 render_fps_tracker_(100, 10u),
37 render_pixel_tracker_(100, 10u), 67 render_pixel_tracker_(100, 10u),
38 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), 68 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
39 first_report_block_time_ms_(-1) { 69 first_report_block_time_ms_(-1) {
40 stats_.ssrc = config_.rtp.remote_ssrc; 70 stats_.ssrc = config_.rtp.remote_ssrc;
41 for (auto it : config_.rtp.rtx) 71 for (auto it : config_.rtp.rtx)
42 rtx_stats_[it.second.ssrc] = StreamDataCounters(); 72 rtx_stats_[it.second.ssrc] = StreamDataCounters();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 counters.fir_packets * 60 / elapsed_sec); 196 counters.fir_packets * 60 / elapsed_sec);
167 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", 197 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute",
168 counters.pli_packets * 60 / elapsed_sec); 198 counters.pli_packets * 60 / elapsed_sec);
169 if (counters.nack_requests > 0) { 199 if (counters.nack_requests > 0) {
170 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", 200 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent",
171 counters.UniqueNackRequestsInPercent()); 201 counters.UniqueNackRequestsInPercent());
172 } 202 }
173 } 203 }
174 } 204 }
175 205
206 void ReceiveStatisticsProxy::QualitySample() {
207 int64_t now = clock_->TimeInMilliseconds();
208 if (last_sample_time_ + kMinSampleLengthMs > now)
209 return;
210
211 double fps =
212 render_fps_tracker_.ComputeRateForInterval(now - last_sample_time_);
213 int qp = qp_sample_.Avg(1);
214
215 bool prev_fps_bad = !fps_threshold_.IsHigh().value_or(true);
216 bool prev_qp_bad = qp_threshold_.IsHigh().value_or(false);
217 bool prev_variance_bad = variance_threshold_.IsHigh().value_or(false);
218 bool prev_any_bad = prev_fps_bad || prev_qp_bad || prev_variance_bad;
219
220 fps_threshold_.AddMeasurement(static_cast<int>(fps));
221 if (qp != -1)
222 qp_threshold_.AddMeasurement(qp);
223 rtc::Optional<double> fps_variance_opt = fps_threshold_.CalculateVariance();
224 double fps_variance = fps_variance_opt.value_or(0);
225 if (fps_variance_opt) {
226 variance_threshold_.AddMeasurement(static_cast<int>(fps_variance));
227 }
228
229 bool fps_bad = !fps_threshold_.IsHigh().value_or(true);
230 bool qp_bad = qp_threshold_.IsHigh().value_or(false);
231 bool variance_bad = variance_threshold_.IsHigh().value_or(false);
232 bool any_bad = fps_bad || qp_bad || variance_bad;
233
234 if (!prev_any_bad && any_bad) {
235 LOG(LS_WARNING) << "Bad call (any) start: " << now;
236 } else if (prev_any_bad && !any_bad) {
237 LOG(LS_WARNING) << "Bad call (any) end: " << now;
238 }
239
240 if (!prev_fps_bad && fps_bad) {
241 LOG(LS_WARNING) << "Bad call (fps) start: " << now;
242 } else if (prev_fps_bad && !fps_bad) {
243 LOG(LS_WARNING) << "Bad call (fps) end: " << now;
244 }
245
246 if (!prev_qp_bad && qp_bad) {
247 LOG(LS_WARNING) << "Bad call (qp) start: " << now;
248 } else if (prev_qp_bad && !qp_bad) {
249 LOG(LS_WARNING) << "Bad call (qp) end: " << now;
250 }
251
252 if (!prev_variance_bad && variance_bad) {
253 LOG(LS_WARNING) << "Bad call (variance) start: " << now;
254 } else if (prev_variance_bad && !variance_bad) {
255 LOG(LS_WARNING) << "Bad call (variance) end: " << now;
256 }
257
258 LOG(LS_INFO) << "SAMPLE: sample_length: " << (now - last_sample_time_)
259 << " fps: " << fps << " fps_bad: " << fps_bad << " qp: " << qp
260 << " qp_bad: " << qp_bad << " variance_bad: " << variance_bad
261 << " fps_variance: " << fps_variance;
262
263 last_sample_time_ = now;
264 qp_sample_.Reset();
265 }
266
176 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const { 267 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
177 rtc::CritScope lock(&crit_); 268 rtc::CritScope lock(&crit_);
178 return stats_; 269 return stats_;
179 } 270 }
180 271
181 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) { 272 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) {
182 rtc::CritScope lock(&crit_); 273 rtc::CritScope lock(&crit_);
183 stats_.current_payload_type = payload_type; 274 stats_.current_payload_type = payload_type;
184 } 275 }
185 276
186 void ReceiveStatisticsProxy::OnDecoderImplementationName( 277 void ReceiveStatisticsProxy::OnDecoderImplementationName(
187 const char* implementation_name) { 278 const char* implementation_name) {
188 rtc::CritScope lock(&crit_); 279 rtc::CritScope lock(&crit_);
189 stats_.decoder_implementation_name = implementation_name; 280 stats_.decoder_implementation_name = implementation_name;
190 } 281 }
191 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate, 282 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
192 unsigned int bitrate_bps) { 283 unsigned int bitrate_bps) {
193 rtc::CritScope lock(&crit_); 284 rtc::CritScope lock(&crit_);
285 QualitySample();
194 stats_.network_frame_rate = framerate; 286 stats_.network_frame_rate = framerate;
195 stats_.total_bitrate_bps = bitrate_bps; 287 stats_.total_bitrate_bps = bitrate_bps;
196 } 288 }
197 289
198 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms, 290 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms,
199 int max_decode_ms, 291 int max_decode_ms,
200 int current_delay_ms, 292 int current_delay_ms,
201 int target_delay_ms, 293 int target_delay_ms,
202 int jitter_buffer_ms, 294 int jitter_buffer_ms,
203 int min_playout_delay_ms, 295 int min_playout_delay_ms,
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 } 425 }
334 426
335 void ReceiveStatisticsProxy::OnPreDecode( 427 void ReceiveStatisticsProxy::OnPreDecode(
336 const EncodedImage& encoded_image, 428 const EncodedImage& encoded_image,
337 const CodecSpecificInfo* codec_specific_info) { 429 const CodecSpecificInfo* codec_specific_info) {
338 if (!codec_specific_info || encoded_image.qp_ == -1) { 430 if (!codec_specific_info || encoded_image.qp_ == -1) {
339 return; 431 return;
340 } 432 }
341 if (codec_specific_info->codecType == kVideoCodecVP8) { 433 if (codec_specific_info->codecType == kVideoCodecVP8) {
342 qp_counters_.vp8.Add(encoded_image.qp_); 434 qp_counters_.vp8.Add(encoded_image.qp_);
435 rtc::CritScope lock(&crit_);
436 qp_sample_.Add(encoded_image.qp_);
343 } 437 }
344 } 438 }
345 439
346 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { 440 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
347 sum += sample; 441 sum += sample;
348 ++num_samples; 442 ++num_samples;
349 } 443 }
350 444
351 int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const { 445 int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
352 if (num_samples < min_required_samples || num_samples == 0) 446 if (num_samples < min_required_samples || num_samples == 0)
353 return -1; 447 return -1;
354 return sum / num_samples; 448 return sum / num_samples;
355 } 449 }
356 450
451 void ReceiveStatisticsProxy::SampleCounter::Reset() {
452 num_samples = 0;
453 sum = 0;
454 }
455
357 } // namespace webrtc 456 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/receive_statistics_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698