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

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

Issue 2627463004: Make the new jitter buffer the default jitter buffer. (Closed)
Patch Set: Offline feedback. Created 3 years, 11 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 <cmath> 14 #include <cmath>
15 #include <utility>
14 16
15 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h" 18 #include "webrtc/base/logging.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/system_wrappers/include/clock.h" 20 #include "webrtc/system_wrappers/include/clock.h"
19 #include "webrtc/system_wrappers/include/field_trial.h" 21 #include "webrtc/system_wrappers/include/field_trial.h"
20 #include "webrtc/system_wrappers/include/metrics.h" 22 #include "webrtc/system_wrappers/include/metrics.h"
21 23
22 namespace webrtc { 24 namespace webrtc {
23 namespace { 25 namespace {
24 // Periodic time interval for processing samples for |freq_offset_counter_|. 26 // Periodic time interval for processing samples for |freq_offset_counter_|.
25 const int64_t kFreqOffsetProcessIntervalMs = 40000; 27 const int64_t kFreqOffsetProcessIntervalMs = 40000;
26 28
27 // Configuration for bad call detection. 29 // Configuration for bad call detection.
28 const int kMinSampleLengthMs = 990; 30 const int kMinSampleLengthMs = 990;
29 const int kNumMeasurements = 10; 31 const int kNumMeasurements = 10;
30 const int kNumMeasurementsVariance = kNumMeasurements * 1.5; 32 const int kNumMeasurementsVariance = kNumMeasurements * 1.5;
31 const float kBadFraction = 0.8f; 33 const float kBadFraction = 0.8f;
32 // For fps: 34 // For fps:
33 // Low means low enough to be bad, high means high enough to be good 35 // Low means low enough to be bad, high means high enough to be good
34 const int kLowFpsThreshold = 12; 36 const int kLowFpsThreshold = 12;
35 const int kHighFpsThreshold = 14; 37 const int kHighFpsThreshold = 14;
36 // For qp and fps variance: 38 // For qp and fps variance:
37 // Low means low enough to be good, high means high enough to be bad 39 // Low means low enough to be good, high means high enough to be bad
38 const int kLowQpThresholdVp8 = 60; 40 const int kLowQpThresholdVp8 = 60;
39 const int kHighQpThresholdVp8 = 70; 41 const int kHighQpThresholdVp8 = 70;
40 const int kLowVarianceThreshold = 1; 42 const int kLowVarianceThreshold = 1;
41 const int kHighVarianceThreshold = 2; 43 const int kHighVarianceThreshold = 2;
44
45 // How large window we use to calculate the framerate/bitrate.
46 const int kRateStatisticsWindowSizeMs = 1000;
42 } // namespace 47 } // namespace
43 48
44 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 49 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
45 const VideoReceiveStream::Config* config, 50 const VideoReceiveStream::Config* config,
46 Clock* clock) 51 Clock* clock)
47 : clock_(clock), 52 : clock_(clock),
48 config_(*config), 53 config_(*config),
49 start_ms_(clock->TimeInMilliseconds()), 54 start_ms_(clock->TimeInMilliseconds()),
50 last_sample_time_(clock->TimeInMilliseconds()), 55 last_sample_time_(clock->TimeInMilliseconds()),
51 fps_threshold_(kLowFpsThreshold, 56 fps_threshold_(kLowFpsThreshold,
52 kHighFpsThreshold, 57 kHighFpsThreshold,
53 kBadFraction, 58 kBadFraction,
54 kNumMeasurements), 59 kNumMeasurements),
55 qp_threshold_(kLowQpThresholdVp8, 60 qp_threshold_(kLowQpThresholdVp8,
56 kHighQpThresholdVp8, 61 kHighQpThresholdVp8,
57 kBadFraction, 62 kBadFraction,
58 kNumMeasurements), 63 kNumMeasurements),
59 variance_threshold_(kLowVarianceThreshold, 64 variance_threshold_(kLowVarianceThreshold,
60 kHighVarianceThreshold, 65 kHighVarianceThreshold,
61 kBadFraction, 66 kBadFraction,
62 kNumMeasurementsVariance), 67 kNumMeasurementsVariance),
63 // 1000ms window, scale 1000 for ms to s. 68 // 1000ms window, scale 1000 for ms to s.
64 decode_fps_estimator_(1000, 1000), 69 decode_fps_estimator_(1000, 1000),
65 renders_fps_estimator_(1000, 1000), 70 renders_fps_estimator_(1000, 1000),
66 render_fps_tracker_(100, 10u), 71 render_fps_tracker_(100, 10u),
67 render_pixel_tracker_(100, 10u), 72 render_pixel_tracker_(100, 10u),
68 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), 73 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
69 first_report_block_time_ms_(-1) { 74 first_report_block_time_ms_(-1),
75 avg_rtt_ms_(0) {
70 stats_.ssrc = config_.rtp.remote_ssrc; 76 stats_.ssrc = config_.rtp.remote_ssrc;
71 for (auto it : config_.rtp.rtx) 77 for (auto it : config_.rtp.rtx)
72 rtx_stats_[it.second.ssrc] = StreamDataCounters(); 78 rtx_stats_[it.second.ssrc] = StreamDataCounters();
73 } 79 }
74 80
75 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { 81 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
76 UpdateHistograms(); 82 UpdateHistograms();
77 } 83 }
78 84
79 void ReceiveStatisticsProxy::UpdateHistograms() { 85 void ReceiveStatisticsProxy::UpdateHistograms() {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms); 117 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.AVSyncOffsetInMs", sync_offset_ms);
112 } 118 }
113 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats(); 119 AggregatedStats freq_offset_stats = freq_offset_counter_.GetStats();
114 if (freq_offset_stats.num_samples > 0) { 120 if (freq_offset_stats.num_samples > 0) {
115 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 121 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtpToNtpFreqOffsetInKhz",
116 freq_offset_stats.average); 122 freq_offset_stats.average);
117 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, " 123 LOG(LS_INFO) << "WebRTC.Video.RtpToNtpFreqOffsetInKhz, "
118 << freq_offset_stats.ToString(); 124 << freq_offset_stats.ToString();
119 } 125 }
120 126
127 if (stats_.frame_counts.key_frames > 0 ||
128 stats_.frame_counts.delta_frames > 0) {
129 float num_key_frames = stats_.frame_counts.key_frames;
130 float num_total_frames =
131 stats_.frame_counts.key_frames + stats_.frame_counts.delta_frames;
132 int key_frames_permille =
133 (num_key_frames * 1000.0f / num_total_frames + 0.5f);
134 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille",
135 key_frames_permille);
136 }
137
121 int qp = qp_counters_.vp8.Avg(kMinRequiredSamples); 138 int qp = qp_counters_.vp8.Avg(kMinRequiredSamples);
122 if (qp != -1) 139 if (qp != -1)
123 RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", qp); 140 RTC_HISTOGRAM_COUNTS_200("WebRTC.Video.Decoded.Vp8.Qp", qp);
124 141
125 // TODO(asapersson): DecoderTiming() is call periodically (each 1000ms) and 142 // TODO(asapersson): DecoderTiming() is call periodically (each 1000ms) and
126 // not per frame. Change decode time to include every frame. 143 // not per frame. Change decode time to include every frame.
127 const int kMinRequiredDecodeSamples = 5; 144 const int kMinRequiredDecodeSamples = 5;
128 int decode_ms = decode_time_counter_.Avg(kMinRequiredDecodeSamples); 145 int decode_ms = decode_time_counter_.Avg(kMinRequiredDecodeSamples);
129 if (decode_ms != -1) 146 if (decode_ms != -1)
130 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", decode_ms); 147 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.DecodeTimeInMs", decode_ms);
131 148
132 if (field_trial::FindFullName("WebRTC-NewVideoJitterBuffer") != 149 int jb_delay_ms = jitter_buffer_delay_counter_.Avg(kMinRequiredDecodeSamples);
133 "Enabled") { 150 if (jb_delay_ms != -1) {
134 int jb_delay_ms = 151 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs",
135 jitter_buffer_delay_counter_.Avg(kMinRequiredDecodeSamples); 152 jb_delay_ms);
136 if (jb_delay_ms != -1) {
137 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.JitterBufferDelayInMs",
138 jb_delay_ms);
139 }
140 } 153 }
154
141 int target_delay_ms = target_delay_counter_.Avg(kMinRequiredDecodeSamples); 155 int target_delay_ms = target_delay_counter_.Avg(kMinRequiredDecodeSamples);
142 if (target_delay_ms != -1) { 156 if (target_delay_ms != -1) {
143 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.TargetDelayInMs", target_delay_ms); 157 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.TargetDelayInMs", target_delay_ms);
144 } 158 }
145 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredDecodeSamples); 159 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredDecodeSamples);
146 if (current_delay_ms != -1) { 160 if (current_delay_ms != -1) {
147 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", 161 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs",
148 current_delay_ms); 162 current_delay_ms);
149 } 163 }
150 int delay_ms = delay_counter_.Avg(kMinRequiredDecodeSamples); 164 int delay_ms = delay_counter_.Avg(kMinRequiredDecodeSamples);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 271
258 LOG(LS_VERBOSE) << "SAMPLE: sample_length: " << (now - last_sample_time_) 272 LOG(LS_VERBOSE) << "SAMPLE: sample_length: " << (now - last_sample_time_)
259 << " fps: " << fps << " fps_bad: " << fps_bad << " qp: " << qp 273 << " fps: " << fps << " fps_bad: " << fps_bad << " qp: " << qp
260 << " qp_bad: " << qp_bad << " variance_bad: " << variance_bad 274 << " qp_bad: " << qp_bad << " variance_bad: " << variance_bad
261 << " fps_variance: " << fps_variance; 275 << " fps_variance: " << fps_variance;
262 276
263 last_sample_time_ = now; 277 last_sample_time_ = now;
264 qp_sample_.Reset(); 278 qp_sample_.Reset();
265 } 279 }
266 280
281 void ReceiveStatisticsProxy::UpdateFrameAndBitrate(int64_t now_ms) const {
282 int64_t old_frames_ms = now_ms - kRateStatisticsWindowSizeMs;
283 while (!frame_window_.empty() &&
284 frame_window_.begin()->first < old_frames_ms) {
285 frame_window_accumulated_bytes_ -= frame_window_.begin()->second;
286 frame_window_.erase(frame_window_.begin());
287 }
288
289 int framerate =
290 (frame_window_.size() * 1000 + 500) / kRateStatisticsWindowSizeMs;
291 size_t bitrate_bps =
292 frame_window_accumulated_bytes_ * 8000 / kRateStatisticsWindowSizeMs;
293 stats_.network_frame_rate = framerate;
294 stats_.total_bitrate_bps = bitrate_bps;
295 }
296
267 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const { 297 VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
268 rtc::CritScope lock(&crit_); 298 rtc::CritScope lock(&crit_);
299 UpdateFrameAndBitrate(clock_->TimeInMilliseconds());
269 return stats_; 300 return stats_;
270 } 301 }
271 302
272 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) { 303 void ReceiveStatisticsProxy::OnIncomingPayloadType(int payload_type) {
273 rtc::CritScope lock(&crit_); 304 rtc::CritScope lock(&crit_);
274 stats_.current_payload_type = payload_type; 305 stats_.current_payload_type = payload_type;
275 } 306 }
276 307
277 void ReceiveStatisticsProxy::OnDecoderImplementationName( 308 void ReceiveStatisticsProxy::OnDecoderImplementationName(
278 const char* implementation_name) { 309 const char* implementation_name) {
279 rtc::CritScope lock(&crit_); 310 rtc::CritScope lock(&crit_);
280 stats_.decoder_implementation_name = implementation_name; 311 stats_.decoder_implementation_name = implementation_name;
281 } 312 }
282 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate, 313 void ReceiveStatisticsProxy::OnIncomingRate(unsigned int framerate,
283 unsigned int bitrate_bps) { 314 unsigned int bitrate_bps) {
284 rtc::CritScope lock(&crit_); 315 rtc::CritScope lock(&crit_);
285 QualitySample(); 316 QualitySample();
philipel 2017/01/11 16:12:34 This function is still called about every second f
stefan-webrtc 2017/01/12 14:16:15 Ouch... Why is it called here? Can we move it to s
philipel 2017/01/12 16:41:35 I will take a look at it in one of my clean up CLs
286 stats_.network_frame_rate = framerate;
287 stats_.total_bitrate_bps = bitrate_bps;
288 } 317 }
289 318
290 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms, 319 void ReceiveStatisticsProxy::OnDecoderTiming(int decode_ms,
291 int max_decode_ms, 320 int max_decode_ms,
292 int current_delay_ms, 321 int current_delay_ms,
293 int target_delay_ms, 322 int target_delay_ms,
294 int jitter_buffer_ms, 323 int jitter_buffer_ms,
295 int min_playout_delay_ms, 324 int min_playout_delay_ms,
296 int render_delay_ms, 325 int render_delay_ms) {
297 int64_t rtt_ms) {
298 rtc::CritScope lock(&crit_); 326 rtc::CritScope lock(&crit_);
299 stats_.decode_ms = decode_ms; 327 stats_.decode_ms = decode_ms;
300 stats_.max_decode_ms = max_decode_ms; 328 stats_.max_decode_ms = max_decode_ms;
301 stats_.current_delay_ms = current_delay_ms; 329 stats_.current_delay_ms = current_delay_ms;
302 stats_.target_delay_ms = target_delay_ms; 330 stats_.target_delay_ms = target_delay_ms;
303 stats_.jitter_buffer_ms = jitter_buffer_ms; 331 stats_.jitter_buffer_ms = jitter_buffer_ms;
304 stats_.min_playout_delay_ms = min_playout_delay_ms; 332 stats_.min_playout_delay_ms = min_playout_delay_ms;
305 stats_.render_delay_ms = render_delay_ms; 333 stats_.render_delay_ms = render_delay_ms;
306 decode_time_counter_.Add(decode_ms); 334 decode_time_counter_.Add(decode_ms);
307 jitter_buffer_delay_counter_.Add(jitter_buffer_ms); 335 jitter_buffer_delay_counter_.Add(jitter_buffer_ms);
308 target_delay_counter_.Add(target_delay_ms); 336 target_delay_counter_.Add(target_delay_ms);
309 current_delay_counter_.Add(current_delay_ms); 337 current_delay_counter_.Add(current_delay_ms);
310 // Network delay (rtt/2) + target_delay_ms (jitter delay + decode time + 338 // Network delay (rtt/2) + target_delay_ms (jitter delay + decode time +
311 // render delay). 339 // render delay).
312 delay_counter_.Add(target_delay_ms + rtt_ms / 2); 340 delay_counter_.Add(target_delay_ms + avg_rtt_ms_ / 2);
313 } 341 }
314 342
315 void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated( 343 void ReceiveStatisticsProxy::RtcpPacketTypesCounterUpdated(
316 uint32_t ssrc, 344 uint32_t ssrc,
317 const RtcpPacketTypeCounter& packet_counter) { 345 const RtcpPacketTypeCounter& packet_counter) {
318 rtc::CritScope lock(&crit_); 346 rtc::CritScope lock(&crit_);
319 if (stats_.ssrc != ssrc) 347 if (stats_.ssrc != ssrc)
320 return; 348 return;
321 stats_.rtcp_packet_type_counts = packet_counter; 349 stats_.rtcp_packet_type_counts = packet_counter;
322 } 350 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 if (estimated_freq_khz < kMaxFreqKhz && estimated_freq_khz > 0.0) 434 if (estimated_freq_khz < kMaxFreqKhz && estimated_freq_khz > 0.0)
407 offset_khz = static_cast<int>(std::fabs(estimated_freq_khz - 90.0) + 0.5); 435 offset_khz = static_cast<int>(std::fabs(estimated_freq_khz - 90.0) + 0.5);
408 436
409 freq_offset_counter_.Add(offset_khz); 437 freq_offset_counter_.Add(offset_khz);
410 } 438 }
411 439
412 void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate, 440 void ReceiveStatisticsProxy::OnReceiveRatesUpdated(uint32_t bitRate,
413 uint32_t frameRate) { 441 uint32_t frameRate) {
414 } 442 }
415 443
444 void ReceiveStatisticsProxy::OnCompleteFrame(bool is_keyframe,
445 size_t size_bytes) {
446 rtc::CritScope lock(&crit_);
447 if (is_keyframe)
448 ++stats_.frame_counts.key_frames;
449 else
450 ++stats_.frame_counts.delta_frames;
451
452 int64_t now_ms = clock_->TimeInMilliseconds();
453 frame_window_accumulated_bytes_ += size_bytes;
454 frame_window_.insert(std::make_pair(now_ms, size_bytes));
455 UpdateFrameAndBitrate(now_ms);
456 }
457
416 void ReceiveStatisticsProxy::OnFrameCountsUpdated( 458 void ReceiveStatisticsProxy::OnFrameCountsUpdated(
417 const FrameCounts& frame_counts) { 459 const FrameCounts& frame_counts) {
418 rtc::CritScope lock(&crit_); 460 rtc::CritScope lock(&crit_);
419 stats_.frame_counts = frame_counts; 461 stats_.frame_counts = frame_counts;
420 } 462 }
421 463
422 void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) { 464 void ReceiveStatisticsProxy::OnDiscardedPacketsUpdated(int discarded_packets) {
423 rtc::CritScope lock(&crit_); 465 rtc::CritScope lock(&crit_);
424 stats_.discarded_packets = discarded_packets; 466 stats_.discarded_packets = discarded_packets;
425 } 467 }
(...skipping 21 matching lines...) Expand all
447 if (num_samples < min_required_samples || num_samples == 0) 489 if (num_samples < min_required_samples || num_samples == 0)
448 return -1; 490 return -1;
449 return static_cast<int>(sum / num_samples); 491 return static_cast<int>(sum / num_samples);
450 } 492 }
451 493
452 void ReceiveStatisticsProxy::SampleCounter::Reset() { 494 void ReceiveStatisticsProxy::SampleCounter::Reset() {
453 num_samples = 0; 495 num_samples = 0;
454 sum = 0; 496 sum = 0;
455 } 497 }
456 498
499 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
500 int64_t max_rtt_ms) {
501 rtc::CritScope lock(&crit_);
502 avg_rtt_ms_ = avg_rtt_ms;
503 }
504
457 } // namespace webrtc 505 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698