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

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

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

Powered by Google App Engine
This is Rietveld 408576698