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

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

Issue 2986893002: Piggybacking simulcast id and ALR experiment id into video content type extension. (Closed)
Patch Set: Created 3 years, 4 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 <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/rtc_base/trace_event.h" 22 #include "webrtc/rtc_base/trace_event.h"
21 #include "webrtc/system_wrappers/include/clock.h" 23 #include "webrtc/system_wrappers/include/clock.h"
22 #include "webrtc/system_wrappers/include/field_trial.h" 24 #include "webrtc/system_wrappers/include/field_trial.h"
23 #include "webrtc/system_wrappers/include/metrics.h" 25 #include "webrtc/system_wrappers/include/metrics.h"
24 26
25 namespace webrtc { 27 namespace webrtc {
26 namespace { 28 namespace {
(...skipping 12 matching lines...) Expand all
39 const int kHighFpsThreshold = 14; 41 const int kHighFpsThreshold = 14;
40 // For qp and fps variance: 42 // For qp and fps variance:
41 // Low means low enough to be good, high means high enough to be bad 43 // Low means low enough to be good, high means high enough to be bad
42 const int kLowQpThresholdVp8 = 60; 44 const int kLowQpThresholdVp8 = 60;
43 const int kHighQpThresholdVp8 = 70; 45 const int kHighQpThresholdVp8 = 70;
44 const int kLowVarianceThreshold = 1; 46 const int kLowVarianceThreshold = 1;
45 const int kHighVarianceThreshold = 2; 47 const int kHighVarianceThreshold = 2;
46 48
47 // How large window we use to calculate the framerate/bitrate. 49 // How large window we use to calculate the framerate/bitrate.
48 const int kRateStatisticsWindowSizeMs = 1000; 50 const int kRateStatisticsWindowSizeMs = 1000;
51
52 std::string UmaPrefixForContentType(VideoContentType content_type) {
53 std::stringstream ss;
54 ss << "WebRTC.Video";
55 int simulcast_id = content_type.GetSimulcastId();
56 if (content_type.IsScreenshare()) {
57 ss << ".Screenshare";
58 }
59 if (simulcast_id > 0) {
60 ss << "_S" << simulcast_id - 1;
61 }
62 return ss.str();
63 }
64
49 } // namespace 65 } // namespace
50 66
51 ReceiveStatisticsProxy::ReceiveStatisticsProxy( 67 ReceiveStatisticsProxy::ReceiveStatisticsProxy(
52 const VideoReceiveStream::Config* config, 68 const VideoReceiveStream::Config* config,
53 Clock* clock) 69 Clock* clock)
54 : clock_(clock), 70 : clock_(clock),
55 config_(*config), 71 config_(*config),
56 start_ms_(clock->TimeInMilliseconds()), 72 start_ms_(clock->TimeInMilliseconds()),
57 last_sample_time_(clock->TimeInMilliseconds()), 73 last_sample_time_(clock->TimeInMilliseconds()),
58 fps_threshold_(kLowFpsThreshold, 74 fps_threshold_(kLowFpsThreshold,
59 kHighFpsThreshold, 75 kHighFpsThreshold,
60 kBadFraction, 76 kBadFraction,
61 kNumMeasurements), 77 kNumMeasurements),
62 qp_threshold_(kLowQpThresholdVp8, 78 qp_threshold_(kLowQpThresholdVp8,
63 kHighQpThresholdVp8, 79 kHighQpThresholdVp8,
64 kBadFraction, 80 kBadFraction,
65 kNumMeasurements), 81 kNumMeasurements),
66 variance_threshold_(kLowVarianceThreshold, 82 variance_threshold_(kLowVarianceThreshold,
67 kHighVarianceThreshold, 83 kHighVarianceThreshold,
68 kBadFraction, 84 kBadFraction,
69 kNumMeasurementsVariance), 85 kNumMeasurementsVariance),
70 num_bad_states_(0), 86 num_bad_states_(0),
71 num_certain_states_(0), 87 num_certain_states_(0),
72 // 1000ms window, scale 1000 for ms to s. 88 // 1000ms window, scale 1000 for ms to s.
73 decode_fps_estimator_(1000, 1000), 89 decode_fps_estimator_(1000, 1000),
74 renders_fps_estimator_(1000, 1000), 90 renders_fps_estimator_(1000, 1000),
75 render_fps_tracker_(100, 10u), 91 render_fps_tracker_(100, 10u),
76 render_pixel_tracker_(100, 10u), 92 render_pixel_tracker_(100, 10u),
77 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count 93 total_byte_tracker_(100, 10u), // bucket_interval_ms, bucket_count
78 e2e_delay_max_ms_video_(-1),
79 e2e_delay_max_ms_screenshare_(-1),
80 interframe_delay_max_ms_video_(-1),
81 interframe_delay_max_ms_screenshare_(-1),
82 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs), 94 freq_offset_counter_(clock, nullptr, kFreqOffsetProcessIntervalMs),
83 first_report_block_time_ms_(-1), 95 first_report_block_time_ms_(-1),
84 avg_rtt_ms_(0), 96 avg_rtt_ms_(0),
85 last_content_type_(VideoContentType::UNSPECIFIED) { 97 last_content_type_(VideoContentType::UNSPECIFIED) {
86 stats_.ssrc = config_.rtp.remote_ssrc; 98 stats_.ssrc = config_.rtp.remote_ssrc;
87 // TODO(brandtr): Replace |rtx_stats_| with a single instance of 99 // TODO(brandtr): Replace |rtx_stats_| with a single instance of
88 // StreamDataCounters. 100 // StreamDataCounters.
89 if (config_.rtp.rtx_ssrc) { 101 if (config_.rtp.rtx_ssrc) {
90 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); 102 rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters();
91 } 103 }
92 } 104 }
93 105
94 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() { 106 ReceiveStatisticsProxy::~ReceiveStatisticsProxy() {
95 UpdateHistograms(); 107 UpdateHistograms();
96 } 108 }
97 109
98 void ReceiveStatisticsProxy::UpdateHistograms() { 110 void ReceiveStatisticsProxy::UpdateHistograms() {
111 // Set synthetic field trial based on received experiment id.
112 // Since experiment is set at the send side and is not changed during the
113 // call, any received content type may be used.
sprang_webrtc 2017/07/26 14:13:43 Unfortunately this is not necessarily correct. I t
ilnik 2017/07/26 14:49:48 This is a big problem, I realize now. What if seve
114 int experiment_id = last_content_type_.GetExperimentId();
115 if (experiment_id != 0) { // 0 means no experiment is active.
116 std::stringstream group_name;
117 group_name << "Group-" << experiment_id - 1;
118 field_trial::RegisterSyntheticFieldTrial(
119 AlrDetector::kScreenshareProbingBweExperimentNameOnReceiveSide,
120 group_name.str());
121 } else {
122 // No experiment group specified.
123 field_trial::RegisterSyntheticFieldTrial(
124 AlrDetector::kScreenshareProbingBweExperimentNameOnReceiveSide, "");
125 }
126
99 RTC_HISTOGRAM_COUNTS_100000( 127 RTC_HISTOGRAM_COUNTS_100000(
100 "WebRTC.Video.ReceiveStreamLifetimeInSeconds", 128 "WebRTC.Video.ReceiveStreamLifetimeInSeconds",
101 (clock_->TimeInMilliseconds() - start_ms_) / 1000); 129 (clock_->TimeInMilliseconds() - start_ms_) / 1000);
102 130
103 if (first_report_block_time_ms_ != -1 && 131 if (first_report_block_time_ms_ != -1 &&
104 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >= 132 ((clock_->TimeInMilliseconds() - first_report_block_time_ms_) / 1000) >=
105 metrics::kMinRunTimeInSeconds) { 133 metrics::kMinRunTimeInSeconds) {
106 int fraction_lost = report_block_stats_.FractionLostInPercent(); 134 int fraction_lost = report_block_stats_.FractionLostInPercent();
107 if (fraction_lost != -1) { 135 if (fraction_lost != -1) {
108 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent", 136 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.ReceivedPacketsLostInPercent",
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples); 207 int current_delay_ms = current_delay_counter_.Avg(kMinRequiredSamples);
180 if (current_delay_ms != -1) { 208 if (current_delay_ms != -1) {
181 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs", 209 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.CurrentDelayInMs",
182 current_delay_ms); 210 current_delay_ms);
183 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms; 211 LOG(LS_INFO) << "WebRTC.Video.CurrentDelayInMs " << current_delay_ms;
184 } 212 }
185 int delay_ms = delay_counter_.Avg(kMinRequiredSamples); 213 int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
186 if (delay_ms != -1) 214 if (delay_ms != -1)
187 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms); 215 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.OnewayDelayInMs", delay_ms);
188 216
189 int e2e_delay_ms_video = e2e_delay_counter_video_.Avg(kMinRequiredSamples); 217 for (auto it : content_specific_stats_) {
sprang_webrtc 2017/07/26 14:13:43 const auto& it ?
190 if (e2e_delay_ms_video != -1) { 218 auto content_type = it.first;
191 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.EndToEndDelayInMs", 219 auto stats = it.second;
sprang_webrtc 2017/07/26 14:13:43 auto is good for |it| here, since its type is kind
192 e2e_delay_ms_video); 220 std::string uma_prefix = UmaPrefixForContentType(content_type);
193 LOG(LS_INFO) << "WebRTC.Video.EndToEndDelayInMs " << e2e_delay_ms_video; 221 // The same line of code can't report different histograms because of how
222 // macro is done. Additional index needed to be different for all different
223 // names. Since experiment can't change during call, we could report 4*2
224 // different content types (4 simulcast_ids x 2 content types).
225 // Conveniently all of these are stored in 3 lower bits in VideoContentType.
226 int idx = content_type.content_type & 0x07;
227 int e2e_delay_ms = stats.e2e_delay_counter.Avg(kMinRequiredSamples);
228 if (e2e_delay_ms != -1) {
229 RTC_HISTOGRAMS_COUNTS_10000(idx, uma_prefix + ".EndToEndDelayInMs",
230 e2e_delay_ms);
231 LOG(LS_INFO) << uma_prefix + ".EndToEndDelayInMs " << e2e_delay_ms;
232 }
233 int e2e_delay_max_ms = stats.e2e_delay_counter.Max();
234
235 if (e2e_delay_max_ms != -1) {
236 RTC_HISTOGRAMS_COUNTS_100000(idx, uma_prefix + ".EndToEndDelayMaxInMs",
237 e2e_delay_max_ms);
238 LOG(LS_INFO) << uma_prefix + ".EndToEndDelayMaxInMs " << e2e_delay_max_ms;
239 }
240 int interframe_delay_ms =
241 stats.interframe_delay_counter.Avg(kMinRequiredSamples);
242 if (interframe_delay_ms != -1) {
243 RTC_HISTOGRAMS_COUNTS_10000(idx, uma_prefix + ".InterframeDelayInMs",
244 interframe_delay_ms);
245 LOG(LS_INFO) << uma_prefix + ".InterframeDelayInMs "
246 << interframe_delay_ms;
247 }
248 int interframe_delay_max_ms = stats.interframe_delay_counter.Max();
249 if (interframe_delay_max_ms != -1) {
250 RTC_HISTOGRAMS_COUNTS_10000(idx, uma_prefix + ".InterframeDelayMaxInMs",
251 interframe_delay_max_ms);
252 LOG(LS_INFO) << uma_prefix + ".InterframeDelayMaxInMs "
253 << interframe_delay_max_ms;
254 }
194 } 255 }
195 256
196 int e2e_delay_ms_screenshare =
197 e2e_delay_counter_screenshare_.Avg(kMinRequiredSamples);
198 if (e2e_delay_ms_screenshare != -1) {
199 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.EndToEndDelayInMs",
200 e2e_delay_ms_screenshare);
201 }
202
203 int e2e_delay_max_ms_video = e2e_delay_max_ms_video_;
204 if (e2e_delay_max_ms_video != -1) {
205 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.EndToEndDelayMaxInMs",
206 e2e_delay_max_ms_video);
207 }
208
209 int e2e_delay_max_ms_screenshare = e2e_delay_max_ms_screenshare_;
210 if (e2e_delay_max_ms_screenshare != -1) {
211 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.Screenshare.EndToEndDelayMaxInMs",
212 e2e_delay_max_ms_screenshare);
213 }
214
215 int interframe_delay_ms_screenshare =
216 interframe_delay_counter_screenshare_.Avg(kMinRequiredSamples);
217 if (interframe_delay_ms_screenshare != -1) {
218 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.InterframeDelayInMs",
219 interframe_delay_ms_screenshare);
220 }
221
222 int interframe_delay_ms_video =
223 interframe_delay_counter_video_.Avg(kMinRequiredSamples);
224 if (interframe_delay_ms_video != -1) {
225 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InterframeDelayInMs",
226 interframe_delay_ms_video);
227 }
228
229 int interframe_delay_max_ms_screenshare =
230 interframe_delay_max_ms_screenshare_;
231 if (interframe_delay_max_ms_screenshare != -1) {
232 RTC_HISTOGRAM_COUNTS_10000(
233 "WebRTC.Video.Screenshare.InterframeDelayMaxInMs",
234 interframe_delay_ms_screenshare);
235 }
236
237 int interframe_delay_max_ms_video = interframe_delay_max_ms_video_;
238 if (interframe_delay_max_ms_video != -1) {
239 RTC_HISTOGRAM_COUNTS_10000(
240 "WebRTC.Video.InterframeDelayMaxInMs",
241 interframe_delay_ms_video);
242 }
243
244
245 StreamDataCounters rtp = stats_.rtp_stats; 257 StreamDataCounters rtp = stats_.rtp_stats;
246 StreamDataCounters rtx; 258 StreamDataCounters rtx;
247 for (auto it : rtx_stats_) 259 for (auto it : rtx_stats_)
248 rtx.Add(it.second); 260 rtx.Add(it.second);
249 StreamDataCounters rtp_rtx = rtp; 261 StreamDataCounters rtp_rtx = rtp;
250 rtp_rtx.Add(rtx); 262 rtp_rtx.Add(rtx);
251 int64_t elapsed_sec = 263 int64_t elapsed_sec =
252 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; 264 rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000;
253 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { 265 if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
254 RTC_HISTOGRAM_COUNTS_10000( 266 RTC_HISTOGRAM_COUNTS_10000(
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 LOG(LS_WARNING) 579 LOG(LS_WARNING)
568 << "QP sum was already set and no QP was given for a frame."; 580 << "QP sum was already set and no QP was given for a frame.";
569 stats_.qp_sum = rtc::Optional<uint64_t>(); 581 stats_.qp_sum = rtc::Optional<uint64_t>();
570 } 582 }
571 last_content_type_ = content_type; 583 last_content_type_ = content_type;
572 decode_fps_estimator_.Update(1, now); 584 decode_fps_estimator_.Update(1, now);
573 if (last_decoded_frame_time_ms_) { 585 if (last_decoded_frame_time_ms_) {
574 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_; 586 int64_t interframe_delay_ms = now - *last_decoded_frame_time_ms_;
575 RTC_DCHECK_GE(interframe_delay_ms, 0); 587 RTC_DCHECK_GE(interframe_delay_ms, 0);
576 stats_.interframe_delay_sum_ms += interframe_delay_ms; 588 stats_.interframe_delay_sum_ms += interframe_delay_ms;
577 if (last_content_type_ == VideoContentType::SCREENSHARE) { 589 auto it = content_specific_stats_.find(last_content_type_);
578 interframe_delay_counter_screenshare_.Add(interframe_delay_ms); 590 if (it == content_specific_stats_.end()) {
579 if (interframe_delay_max_ms_screenshare_ < interframe_delay_ms) { 591 content_specific_stats_[last_content_type_] = ContentSpecificStats();
580 interframe_delay_max_ms_screenshare_ = interframe_delay_ms; 592 it = content_specific_stats_.find(last_content_type_);
581 }
582 } else {
583 interframe_delay_counter_video_.Add(interframe_delay_ms);
584 if (interframe_delay_max_ms_video_ < interframe_delay_ms) {
585 interframe_delay_max_ms_video_ = interframe_delay_ms;
586 }
587 } 593 }
594 ContentSpecificStats* stats = &it->second;
595 stats->interframe_delay_counter.Add(interframe_delay_ms);
588 } 596 }
589 last_decoded_frame_time_ms_.emplace(now); 597 last_decoded_frame_time_ms_.emplace(now);
590 } 598 }
591 599
592 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) { 600 void ReceiveStatisticsProxy::OnRenderedFrame(const VideoFrame& frame) {
593 int width = frame.width(); 601 int width = frame.width();
594 int height = frame.height(); 602 int height = frame.height();
595 RTC_DCHECK_GT(width, 0); 603 RTC_DCHECK_GT(width, 0);
596 RTC_DCHECK_GT(height, 0); 604 RTC_DCHECK_GT(height, 0);
597 uint64_t now = clock_->TimeInMilliseconds(); 605 uint64_t now = clock_->TimeInMilliseconds();
598 606
599 rtc::CritScope lock(&crit_); 607 rtc::CritScope lock(&crit_);
600 renders_fps_estimator_.Update(1, now); 608 renders_fps_estimator_.Update(1, now);
601 ++stats_.frames_rendered; 609 ++stats_.frames_rendered;
602 stats_.width = width; 610 stats_.width = width;
603 stats_.height = height; 611 stats_.height = height;
604 render_width_counter_.Add(width); 612 render_width_counter_.Add(width);
605 render_height_counter_.Add(height); 613 render_height_counter_.Add(height);
606 render_fps_tracker_.AddSamples(1); 614 render_fps_tracker_.AddSamples(1);
607 render_pixel_tracker_.AddSamples(sqrt(width * height)); 615 render_pixel_tracker_.AddSamples(sqrt(width * height));
608 616
609 if (frame.ntp_time_ms() > 0) { 617 if (frame.ntp_time_ms() > 0) {
610 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms(); 618 int64_t delay_ms = clock_->CurrentNtpInMilliseconds() - frame.ntp_time_ms();
611 if (delay_ms >= 0) { 619 if (delay_ms >= 0) {
612 if (last_content_type_ == VideoContentType::SCREENSHARE) { 620 auto it = content_specific_stats_.find(last_content_type_);
613 e2e_delay_max_ms_screenshare_ = 621 if (it == content_specific_stats_.end()) {
614 std::max(delay_ms, e2e_delay_max_ms_screenshare_); 622 content_specific_stats_[last_content_type_] = ContentSpecificStats();
615 e2e_delay_counter_screenshare_.Add(delay_ms); 623 it = content_specific_stats_.find(last_content_type_);
616 } else {
617 e2e_delay_max_ms_video_ = std::max(delay_ms, e2e_delay_max_ms_video_);
618 e2e_delay_counter_video_.Add(delay_ms);
619 } 624 }
625 ContentSpecificStats* stats = &it->second;
626 stats->e2e_delay_counter.Add(delay_ms);
620 } 627 }
621 } 628 }
622 629
623 TRACE_EVENT_INSTANT2("webrtc_stats", "WebRTC.Video.ReceivedWidthInPixels", 630 TRACE_EVENT_INSTANT2("webrtc_stats", "WebRTC.Video.ReceivedWidthInPixels",
624 "width", width, "ssrc", stats_.ssrc); 631 "width", width, "ssrc", stats_.ssrc);
625 TRACE_EVENT_INSTANT2("webrtc_stats", "WebRTC.Video.ReceivedHeightInPixels", 632 TRACE_EVENT_INSTANT2("webrtc_stats", "WebRTC.Video.ReceivedHeightInPixels",
626 "height", height, "ssrc", stats_.ssrc); 633 "height", height, "ssrc", stats_.ssrc);
627 TRACE_EVENT_INSTANT1("webrtc_stats", "WebRTC.Video.OnRenderedFrame", 634 TRACE_EVENT_INSTANT1("webrtc_stats", "WebRTC.Video.OnRenderedFrame",
628 "ssrc", stats_.ssrc); 635 "ssrc", stats_.ssrc);
629 } 636 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 if (codec_specific_info->codecType == kVideoCodecVP8) { 687 if (codec_specific_info->codecType == kVideoCodecVP8) {
681 qp_counters_.vp8.Add(encoded_image.qp_); 688 qp_counters_.vp8.Add(encoded_image.qp_);
682 rtc::CritScope lock(&crit_); 689 rtc::CritScope lock(&crit_);
683 qp_sample_.Add(encoded_image.qp_); 690 qp_sample_.Add(encoded_image.qp_);
684 } 691 }
685 } 692 }
686 693
687 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) { 694 void ReceiveStatisticsProxy::SampleCounter::Add(int sample) {
688 sum += sample; 695 sum += sample;
689 ++num_samples; 696 ++num_samples;
697 if (!max || *max < sample) {
698 max.emplace(sample);
699 }
690 } 700 }
691 701
692 int ReceiveStatisticsProxy::SampleCounter::Avg( 702 int ReceiveStatisticsProxy::SampleCounter::Avg(
693 int64_t min_required_samples) const { 703 int64_t min_required_samples) const {
694 if (num_samples < min_required_samples || num_samples == 0) 704 if (num_samples < min_required_samples || num_samples == 0)
695 return -1; 705 return -1;
696 return static_cast<int>(sum / num_samples); 706 return static_cast<int>(sum / num_samples);
697 } 707 }
698 708
709 int ReceiveStatisticsProxy::SampleCounter::Max() const {
710 if (!max) {
711 return -1;
712 } else {
713 return static_cast<int>(*max);
714 }
sprang_webrtc 2017/07/26 14:13:43 return max.value_or(-1);
715 }
716
699 void ReceiveStatisticsProxy::SampleCounter::Reset() { 717 void ReceiveStatisticsProxy::SampleCounter::Reset() {
700 num_samples = 0; 718 num_samples = 0;
701 sum = 0; 719 sum = 0;
720 max.reset();
702 } 721 }
703 722
704 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms, 723 void ReceiveStatisticsProxy::OnRttUpdate(int64_t avg_rtt_ms,
705 int64_t max_rtt_ms) { 724 int64_t max_rtt_ms) {
706 rtc::CritScope lock(&crit_); 725 rtc::CritScope lock(&crit_);
707 avg_rtt_ms_ = avg_rtt_ms; 726 avg_rtt_ms_ = avg_rtt_ms;
708 } 727 }
709 728
710 } // namespace webrtc 729 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698