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

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
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/metrics.h" 19 #include "webrtc/system_wrappers/include/metrics.h"
19 20
20 namespace webrtc { 21 namespace webrtc {
21 namespace { 22 namespace {
22 // Periodic time interval for processing samples for |freq_offset_counter_|. 23 // Periodic time interval for processing samples for |freq_offset_counter_|.
23 const int64_t kFreqOffsetProcessIntervalMs = 40000; 24 const int64_t kFreqOffsetProcessIntervalMs = 40000;
25
26 // Configuration for bad call detection.
27 const int kNumMeasurements = 10;
28 const float kBadFraction = 0.8f;
29 const int kLowFpsThreshold = 12;
30 const int kHighFpsThreshold = 14;
31 const int kLowQpThreshold = 60;
stefan-webrtc 2016/11/28 15:55:25 seems like a high threshold to be considered "low"
palmkvist 2016/12/01 13:03:45 It means it is low enough to not be considered bad
stefan-webrtc 2016/12/02 09:31:55 Ok, I'd rename it I think. Comment is probably fin
32 const int kHighQpThreshold = 70;
33 const int kNumMeasurementsVariance = kNumMeasurements * 1.5;
34 const int kLowVarianceThreshold = 1;
35 const int kHighVarianceThreshold = 2;
24 } // namespace 36 } // namespace
25 37
26 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 38 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
27 const VideoReceiveStream::Config* config, 39 const VideoReceiveStream::Config* config,
28 Clock* clock) 40 Clock* clock)
29 : clock_(clock), 41 : clock_(clock),
30 config_(*config), 42 config_(*config),
31 start_ms_(clock->TimeInMilliseconds()), 43 start_ms_(clock->TimeInMilliseconds()),
32 // 1000ms window, scale 1000 for ms to s. 44 // 1000ms window, scale 1000 for ms to s.
45 last_sample_time_(clock->TimeInMilliseconds()),
46 fps_threshold_(kLowFpsThreshold,
47 kHighFpsThreshold,
48 kBadFraction,
49 kNumMeasurements),
50 qp_threshold_(kLowQpThreshold,
51 kHighQpThreshold,
52 kBadFraction,
53 kNumMeasurements),
54 variance_threshold_(kLowVarianceThreshold,
55 kHighVarianceThreshold,
56 kBadFraction,
57 kNumMeasurementsVariance),
33 decode_fps_estimator_(1000, 1000), 58 decode_fps_estimator_(1000, 1000),
34 renders_fps_estimator_(1000, 1000), 59 renders_fps_estimator_(1000, 1000),
35 render_fps_tracker_(100, 10u), 60 render_fps_tracker_(100, 10u),
36 render_pixel_tracker_(100, 10u), 61 render_pixel_tracker_(100, 10u),
37 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs) { 62 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs) {
38 stats_.ssrc = config_.rtp.remote_ssrc; 63 stats_.ssrc = config_.rtp.remote_ssrc;
39 for (auto it : config_.rtp.rtx) 64 for (auto it : config_.rtp.rtx)
40 rtx_stats_[it.second.ssrc] = StreamDataCounters(); 65 rtx_stats_[it.second.ssrc] = StreamDataCounters();
41 } 66 }
42 67
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 counters.fir_packets * 60 / elapsed_sec); 178 counters.fir_packets * 60 / elapsed_sec);
154 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute", 179 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute",
155 counters.pli_packets * 60 / elapsed_sec); 180 counters.pli_packets * 60 / elapsed_sec);
156 if (counters.nack_requests > 0) { 181 if (counters.nack_requests > 0) {
157 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent", 182 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.UniqueNackRequestsSentInPercent",
158 counters.UniqueNackRequestsInPercent()); 183 counters.UniqueNackRequestsInPercent());
159 } 184 }
160 } 185 }
161 } 186 }
162 187
188 void ReceiveStatisticsProxy::QualitySample() {
189 uint64_t now = clock_->TimeInMilliseconds();
190
191 double fps =
192 render_fps_tracker_.ComputeRateForInterval(now - last_sample_time_);
193 int qp = qp_sample_.Avg(1);
stefan-webrtc 2016/11/28 15:55:24 What does 1 mean here?
palmkvist 2016/12/01 13:03:45 It's number of samples required to return an avera
stefan-webrtc 2016/12/02 09:31:55 I see. I guess it's fine as is.
194
195 bool prev_fps_bad = !fps_threshold_.IsHigh().value_or(true);
196 bool prev_qp_bad = qp_threshold_.IsHigh().value_or(false);
197 bool prev_variance_bad = variance_threshold_.IsHigh().value_or(false);
198 bool prev_any_bad = prev_fps_bad || prev_qp_bad || prev_variance_bad;
199
200 fps_threshold_.AddMeasurement(static_cast<int>(fps));
201 qp_threshold_.AddMeasurement(qp);
202 rtc::Optional<double> fps_variance_opt = fps_threshold_.CalculateVariance();
203 double fps_variance = fps_variance_opt.value_or(0);
204 if (fps_variance_opt) {
205 variance_threshold_.AddMeasurement(static_cast<int>(fps_variance));
206 }
207
208 bool fps_bad = !fps_threshold_.IsHigh().value_or(true);
209 bool qp_bad = qp_threshold_.IsHigh().value_or(false);
210 bool variance_bad = variance_threshold_.IsHigh().value_or(false);
211 bool any_bad = fps_bad || qp_bad || variance_bad;
212
213 if (!prev_any_bad && any_bad) {
214 LOG(LS_WARNING) << "Bad call (any) start: " << now;
215 } else if (prev_any_bad && !any_bad) {
216 LOG(LS_WARNING) << "Bad call (any) end: " << now;
217 }
218
219 if (!prev_fps_bad && fps_bad) {
220 LOG(LS_WARNING) << "Bad call (fps) start: " << now;
221 } else if (prev_fps_bad && !fps_bad) {
222 LOG(LS_WARNING) << "Bad call (fps) end: " << now;
223 }
224
225 if (!prev_qp_bad && qp_bad) {
226 LOG(LS_WARNING) << "Bad call (qp) start: " << now;
227 } else if (prev_qp_bad && !qp_bad) {
228 LOG(LS_WARNING) << "Bad call (qp) end: " << now;
229 }
230
231 if (!prev_variance_bad && variance_bad) {
232 LOG(LS_WARNING) << "Bad call (variance) start: " << now;
233 } else if (prev_variance_bad && !variance_bad) {
234 LOG(LS_WARNING) << "Bad call (variance) end: " << now;
235 }
236
237 LOG(LS_INFO) << "SAMPLE: sample_length: " << (now - last_sample_time_)
238 << " fps: " << fps << " fps_bad: " << fps_bad << " qp: " << qp
239 << " qp_bad: " << qp_bad << " variance_bad: " << variance_bad
240 << " fps_variance: " << fps_variance;
241
242 last_sample_time_ = now;
243 qp_sample_.Reset();
244 }
245
163 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const { 246 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
164 rtc::CritScope lock(&crit_); 247 rtc::CritScope lock(&crit_);
165 return stats_; 248 return stats_;
166 } 249 }
167 250
168 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) { 251 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) {
169 rtc::CritScope lock(&crit_); 252 rtc::CritScope lock(&crit_);
170 stats_.current_payload_type = payload_type; 253 stats_.current_payload_type = payload_type;
171 } 254 }
172 255
173 void ReceiveStatisticsProxy::OnDecoderImplementationName( 256 void ReceiveStatisticsProxy::OnDecoderImplementationName(
174 const char* implementation_name) { 257 const char* implementation_name) {
175 rtc::CritScope lock(&crit_); 258 rtc::CritScope lock(&crit_);
176 stats_.decoder_implementation_name = implementation_name; 259 stats_.decoder_implementation_name = implementation_name;
177 } 260 }
178 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate, 261 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
179 unsigned int bitrate_bps) { 262 unsigned int bitrate_bps) {
180 rtc::CritScope lock(&crit_); 263 rtc::CritScope lock(&crit_);
264 QualitySample();
181 stats_.network_frame_rate = framerate; 265 stats_.network_frame_rate = framerate;
182 stats_.total_bitrate_bps = bitrate_bps; 266 stats_.total_bitrate_bps = bitrate_bps;
183 } 267 }
184 268
185 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms, 269 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms,
186 int max_decode_ms, 270 int max_decode_ms,
187 int current_delay_ms, 271 int current_delay_ms,
188 int target_delay_ms, 272 int target_delay_ms,
189 int jitter_buffer_ms, 273 int jitter_buffer_ms,
190 int min_playout_delay_ms, 274 int min_playout_delay_ms,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 } 401 }
318 402
319 void ReceiveStatisticsProxy::OnPreDecode( 403 void ReceiveStatisticsProxy::OnPreDecode(
320 const EncodedImage& encoded_image, 404 const EncodedImage& encoded_image,
321 const CodecSpecificInfo* codec_specific_info) { 405 const CodecSpecificInfo* codec_specific_info) {
322 if (!codec_specific_info || encoded_image.qp_ == -1) { 406 if (!codec_specific_info || encoded_image.qp_ == -1) {
323 return; 407 return;
324 } 408 }
325 if (codec_specific_info->codecType == kVideoCodecVP8) { 409 if (codec_specific_info->codecType == kVideoCodecVP8) {
326 qp_counters_.vp8.Add(encoded_image.qp_); 410 qp_counters_.vp8.Add(encoded_image.qp_);
411 rtc::CritScope lock(&crit_);
412 qp_sample_.Add(encoded_image.qp_);
327 } 413 }
328 } 414 }
329 415
330 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { 416 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
331 sum += sample; 417 sum += sample;
332 ++num_samples; 418 ++num_samples;
333 } 419 }
334 420
335 int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const { 421 int ReceiveStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
336 if (num_samples < min_required_samples || num_samples == 0) 422 if (num_samples < min_required_samples || num_samples == 0)
337 return -1; 423 return -1;
338 return sum / num_samples; 424 return sum / num_samples;
339 } 425 }
340 426
427 void ReceiveStatisticsProxy::SampleCounter::Reset() {
428 num_samples = 0;
429 sum = 0;
stefan-webrtc 2016/11/28 15:55:25 num_samples_ sum_
430 }
431
341 } // namespace webrtc 432 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698