blob: 916ffb3baa4bfbdd9745ea90c90933bb4405b5ea [file] [log] [blame]
sprang@webrtc.orgccd42842014-01-07 09:54:34 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/video/send_statistics_proxy.h"
12
asaperssond89920b2015-07-22 06:52:00 -070013#include <algorithm>
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000014#include <map>
15
pbos@webrtc.org49096de2015-02-24 22:37:52 +000016#include "webrtc/base/checks.h"
17
Peter Boström415d2cd2015-10-26 11:35:17 +010018#include "webrtc/base/logging.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010019#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
20#include "webrtc/system_wrappers/include/metrics.h"
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000021
22namespace webrtc {
asapersson2a0a2a42015-10-27 01:32:00 -070023namespace {
24// Used by histograms. Values of entries should not be changed.
25enum HistogramCodecType {
26 kVideoUnknown = 0,
27 kVideoVp8 = 1,
28 kVideoVp9 = 2,
29 kVideoH264 = 3,
30 kVideoMax = 64,
31};
32
33HistogramCodecType PayloadNameToHistogramCodecType(
34 const std::string& payload_name) {
35 if (payload_name == "VP8") {
36 return kVideoVp8;
37 } else if (payload_name == "VP9") {
38 return kVideoVp9;
39 } else if (payload_name == "H264") {
40 return kVideoH264;
41 } else {
42 return kVideoUnknown;
43 }
44}
45
46void UpdateCodecTypeHistogram(const std::string& payload_name) {
47 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.Encoder.CodecType",
48 PayloadNameToHistogramCodecType(payload_name), kVideoMax);
49}
50} // namespace
51
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000052
pbos@webrtc.org273a4142014-12-01 15:23:21 +000053const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
54
55SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
56 const VideoSendStream::Config& config)
asaperssond89920b2015-07-22 06:52:00 -070057 : clock_(clock),
58 config_(config),
Tim Psiaki63046262015-09-14 10:38:08 -070059 input_frame_rate_tracker_(100u, 10u),
60 sent_frame_rate_tracker_(100u, 10u),
asaperssond89920b2015-07-22 06:52:00 -070061 last_sent_frame_timestamp_(0),
62 max_sent_width_per_timestamp_(0),
63 max_sent_height_per_timestamp_(0) {
asapersson2a0a2a42015-10-27 01:32:00 -070064 UpdateCodecTypeHistogram(config_.encoder_settings.payload_name);
pbos@webrtc.orgde1429e2014-04-28 13:00:21 +000065}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +000066
Åsa Persson24b4eda2015-06-16 10:17:01 +020067SendStatisticsProxy::~SendStatisticsProxy() {
68 UpdateHistograms();
69}
70
71void SendStatisticsProxy::UpdateHistograms() {
72 int input_fps =
Tim Psiaki63046262015-09-14 10:38:08 -070073 static_cast<int>(input_frame_rate_tracker_.ComputeTotalRate());
Åsa Persson24b4eda2015-06-16 10:17:01 +020074 if (input_fps > 0)
75 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.InputFramesPerSecond", input_fps);
asaperssond89920b2015-07-22 06:52:00 -070076 int sent_fps =
Tim Psiaki63046262015-09-14 10:38:08 -070077 static_cast<int>(sent_frame_rate_tracker_.ComputeTotalRate());
Åsa Persson24b4eda2015-06-16 10:17:01 +020078 if (sent_fps > 0)
79 RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.SentFramesPerSecond", sent_fps);
asaperssond89920b2015-07-22 06:52:00 -070080
asapersson6718e972015-07-24 00:20:58 -070081 const int kMinRequiredSamples = 200;
asaperssond89920b2015-07-22 06:52:00 -070082 int in_width = input_width_counter_.Avg(kMinRequiredSamples);
83 int in_height = input_height_counter_.Avg(kMinRequiredSamples);
84 if (in_width != -1) {
85 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputWidthInPixels", in_width);
86 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.InputHeightInPixels", in_height);
87 }
88 int sent_width = sent_width_counter_.Avg(kMinRequiredSamples);
89 int sent_height = sent_height_counter_.Avg(kMinRequiredSamples);
90 if (sent_width != -1) {
91 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentWidthInPixels", sent_width);
92 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.SentHeightInPixels", sent_height);
93 }
asapersson6718e972015-07-24 00:20:58 -070094 int encode_ms = encode_time_counter_.Avg(kMinRequiredSamples);
95 if (encode_ms != -1)
96 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.EncodeTimeInMs", encode_ms);
asaperssondec5ebf2015-10-05 02:36:17 -070097
98 int key_frames_permille = key_frame_counter_.Permille(kMinRequiredSamples);
99 if (key_frames_permille != -1) {
100 RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesSentInPermille",
101 key_frames_permille);
102 }
asapersson4306fc72015-10-19 00:35:21 -0700103 int quality_limited =
104 quality_limited_frame_counter_.Percent(kMinRequiredSamples);
105 if (quality_limited != -1) {
106 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.QualityLimitedResolutionInPercent",
107 quality_limited);
108 }
109 int downscales = quality_downscales_counter_.Avg(kMinRequiredSamples);
110 if (downscales != -1) {
111 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.QualityLimitedResolutionDownscales",
112 downscales, 20);
113 }
asaperssonda535c42015-10-19 23:32:41 -0700114 int bw_limited = bw_limited_frame_counter_.Percent(kMinRequiredSamples);
115 if (bw_limited != -1) {
116 RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.BandwidthLimitedResolutionInPercent",
117 bw_limited);
118 }
119 int num_disabled = bw_resolutions_disabled_counter_.Avg(kMinRequiredSamples);
120 if (num_disabled != -1) {
121 RTC_HISTOGRAM_ENUMERATION(
122 "WebRTC.Video.BandwidthLimitedResolutionsDisabled", num_disabled, 10);
123 }
asaperssonf040b232015-11-04 00:59:03 -0800124 int delay_ms = delay_counter_.Avg(kMinRequiredSamples);
125 if (delay_ms != -1)
126 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Video.SendSideDelayInMs", delay_ms);
127
128 int max_delay_ms = max_delay_counter_.Avg(kMinRequiredSamples);
129 if (max_delay_ms != -1) {
130 RTC_HISTOGRAM_COUNTS_100000(
131 "WebRTC.Video.SendSideDelayMaxInMs", max_delay_ms);
132 }
Åsa Persson24b4eda2015-06-16 10:17:01 +0200133}
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000134
Peter Boström7083e112015-09-22 16:28:51 +0200135void SendStatisticsProxy::OnOutgoingRate(uint32_t framerate, uint32_t bitrate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200136 rtc::CritScope lock(&crit_);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000137 stats_.encode_frame_rate = framerate;
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000138 stats_.media_bitrate_bps = bitrate;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000139}
140
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000141void SendStatisticsProxy::CpuOveruseMetricsUpdated(
142 const CpuOveruseMetrics& metrics) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200143 rtc::CritScope lock(&crit_);
asapersson6718e972015-07-24 00:20:58 -0700144 // TODO(asapersson): Change to use OnEncodedFrame() for avg_encode_time_ms.
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +0000145 stats_.avg_encode_time_ms = metrics.avg_encode_time_ms;
146 stats_.encode_usage_percent = metrics.encode_usage_percent;
147}
148
Peter Boström7083e112015-09-22 16:28:51 +0200149void SendStatisticsProxy::OnSuspendChange(bool is_suspended) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200150 rtc::CritScope lock(&crit_);
henrik.lundin@webrtc.orgb10363f2014-03-13 13:31:21 +0000151 stats_.suspended = is_suspended;
152}
153
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000154VideoSendStream::Stats SendStatisticsProxy::GetStats() {
Peter Boströmf2f82832015-05-01 13:00:41 +0200155 rtc::CritScope lock(&crit_);
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000156 PurgeOldStats();
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000157 stats_.input_frame_rate =
Tim Psiaki63046262015-09-14 10:38:08 -0700158 static_cast<int>(input_frame_rate_tracker_.ComputeRate());
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000159 return stats_;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000160}
161
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000162void SendStatisticsProxy::PurgeOldStats() {
Peter Boström20f3f942015-05-15 11:33:39 +0200163 int64_t old_stats_ms = clock_->TimeInMilliseconds() - kStatsTimeoutMs;
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000164 for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
165 stats_.substreams.begin();
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000166 it != stats_.substreams.end(); ++it) {
167 uint32_t ssrc = it->first;
Peter Boström20f3f942015-05-15 11:33:39 +0200168 if (update_times_[ssrc].resolution_update_ms <= old_stats_ms) {
169 it->second.width = 0;
170 it->second.height = 0;
171 }
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000172 }
173}
174
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000175VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
176 uint32_t ssrc) {
177 std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
178 stats_.substreams.find(ssrc);
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000179 if (it != stats_.substreams.end())
180 return &it->second;
181
182 if (std::find(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc) ==
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000183 config_.rtp.ssrcs.end() &&
184 std::find(config_.rtp.rtx.ssrcs.begin(),
185 config_.rtp.rtx.ssrcs.end(),
186 ssrc) == config_.rtp.rtx.ssrcs.end()) {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000187 return nullptr;
stefan@webrtc.org58e2d262014-08-14 15:10:49 +0000188 }
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000189
190 return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
191}
192
Peter Boström20f3f942015-05-15 11:33:39 +0200193void SendStatisticsProxy::OnInactiveSsrc(uint32_t ssrc) {
194 rtc::CritScope lock(&crit_);
195 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
196 if (stats == nullptr)
197 return;
198
199 stats->total_bitrate_bps = 0;
200 stats->retransmit_bitrate_bps = 0;
201 stats->height = 0;
202 stats->width = 0;
203}
204
pbos@webrtc.org891d4832015-02-26 13:15:22 +0000205void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200206 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +0000207 stats_.target_media_bitrate_bps = bitrate_bps;
208}
209
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000210void SendStatisticsProxy::OnSendEncodedImage(
211 const EncodedImage& encoded_image,
212 const RTPVideoHeader* rtp_video_header) {
213 size_t simulcast_idx =
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000214 rtp_video_header != nullptr ? rtp_video_header->simulcastIdx : 0;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000215 if (simulcast_idx >= config_.rtp.ssrcs.size()) {
216 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
217 << " >= " << config_.rtp.ssrcs.size() << ").";
218 return;
219 }
220 uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];
221
Peter Boströmf2f82832015-05-01 13:00:41 +0200222 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000223 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000224 if (stats == nullptr)
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000225 return;
226
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000227 stats->width = encoded_image._encodedWidth;
228 stats->height = encoded_image._encodedHeight;
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000229 update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
asaperssond89920b2015-07-22 06:52:00 -0700230
Peter Boström49e196a2015-10-23 15:58:18 +0200231 key_frame_counter_.Add(encoded_image._frameType == kVideoFrameKey);
asaperssondec5ebf2015-10-05 02:36:17 -0700232
asapersson4306fc72015-10-19 00:35:21 -0700233 if (encoded_image.adapt_reason_.quality_resolution_downscales != -1) {
234 bool downscaled =
235 encoded_image.adapt_reason_.quality_resolution_downscales > 0;
236 quality_limited_frame_counter_.Add(downscaled);
237 if (downscaled) {
238 quality_downscales_counter_.Add(
239 encoded_image.adapt_reason_.quality_resolution_downscales);
240 }
241 }
asaperssonda535c42015-10-19 23:32:41 -0700242 if (encoded_image.adapt_reason_.bw_resolutions_disabled != -1) {
243 bool bw_limited = encoded_image.adapt_reason_.bw_resolutions_disabled > 0;
244 bw_limited_frame_counter_.Add(bw_limited);
245 if (bw_limited) {
246 bw_resolutions_disabled_counter_.Add(
247 encoded_image.adapt_reason_.bw_resolutions_disabled);
248 }
249 }
asapersson4306fc72015-10-19 00:35:21 -0700250
asaperssond89920b2015-07-22 06:52:00 -0700251 // TODO(asapersson): This is incorrect if simulcast layers are encoded on
252 // different threads and there is no guarantee that one frame of all layers
253 // are encoded before the next start.
254 if (last_sent_frame_timestamp_ > 0 &&
255 encoded_image._timeStamp != last_sent_frame_timestamp_) {
Tim Psiaki63046262015-09-14 10:38:08 -0700256 sent_frame_rate_tracker_.AddSamples(1);
asaperssond89920b2015-07-22 06:52:00 -0700257 sent_width_counter_.Add(max_sent_width_per_timestamp_);
258 sent_height_counter_.Add(max_sent_height_per_timestamp_);
259 max_sent_width_per_timestamp_ = 0;
260 max_sent_height_per_timestamp_ = 0;
Åsa Persson24b4eda2015-06-16 10:17:01 +0200261 }
asaperssond89920b2015-07-22 06:52:00 -0700262 last_sent_frame_timestamp_ = encoded_image._timeStamp;
263 max_sent_width_per_timestamp_ =
264 std::max(max_sent_width_per_timestamp_,
265 static_cast<int>(encoded_image._encodedWidth));
266 max_sent_height_per_timestamp_ =
267 std::max(max_sent_height_per_timestamp_,
268 static_cast<int>(encoded_image._encodedHeight));
pbos@webrtc.org273a4142014-12-01 15:23:21 +0000269}
270
asaperssond89920b2015-07-22 06:52:00 -0700271void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200272 rtc::CritScope lock(&crit_);
Tim Psiaki63046262015-09-14 10:38:08 -0700273 input_frame_rate_tracker_.AddSamples(1);
asaperssond89920b2015-07-22 06:52:00 -0700274 input_width_counter_.Add(width);
275 input_height_counter_.Add(height);
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000276}
277
asapersson6718e972015-07-24 00:20:58 -0700278void SendStatisticsProxy::OnEncodedFrame(int encode_time_ms) {
279 rtc::CritScope lock(&crit_);
280 encode_time_counter_.Add(encode_time_ms);
281}
282
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000283void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
284 uint32_t ssrc,
285 const RtcpPacketTypeCounter& packet_counter) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200286 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000287 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000288 if (stats == nullptr)
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000289 return;
290
291 stats->rtcp_packet_type_counts = packet_counter;
292}
293
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000294void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
295 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200296 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000297 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000298 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000299 return;
300
301 stats->rtcp_stats = statistics;
302}
303
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000304void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
305}
306
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000307void SendStatisticsProxy::DataCountersUpdated(
308 const StreamDataCounters& counters,
309 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200310 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000311 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
henrikg91d6ede2015-09-17 00:24:34 -0700312 RTC_DCHECK(stats != nullptr)
313 << "DataCountersUpdated reported for unknown ssrc: " << ssrc;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000314
315 stats->rtp_stats = counters;
316}
317
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000318void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
319 const BitrateStatistics& retransmit_stats,
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000320 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200321 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000322 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000323 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000324 return;
325
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +0000326 stats->total_bitrate_bps = total_stats.bitrate_bps;
327 stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000328}
329
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000330void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
331 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200332 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000333 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000334 if (stats == nullptr)
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000335 return;
336
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000337 stats->frame_counts = frame_counts;
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000338}
339
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000340void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
341 int max_delay_ms,
342 uint32_t ssrc) {
Peter Boströmf2f82832015-05-01 13:00:41 +0200343 rtc::CritScope lock(&crit_);
pbos@webrtc.org09c77b92015-02-25 10:42:16 +0000344 VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +0000345 if (stats == nullptr)
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000346 return;
347 stats->avg_delay_ms = avg_delay_ms;
348 stats->max_delay_ms = max_delay_ms;
asaperssonf040b232015-11-04 00:59:03 -0800349
350 delay_counter_.Add(avg_delay_ms);
351 max_delay_counter_.Add(max_delay_ms);
stefan@webrtc.org168f23f2014-07-11 13:44:02 +0000352}
353
asaperssond89920b2015-07-22 06:52:00 -0700354void SendStatisticsProxy::SampleCounter::Add(int sample) {
355 sum += sample;
356 ++num_samples;
357}
358
359int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
360 if (num_samples < min_required_samples || num_samples == 0)
361 return -1;
asaperssonda535c42015-10-19 23:32:41 -0700362 return (sum + (num_samples / 2)) / num_samples;
asaperssond89920b2015-07-22 06:52:00 -0700363}
364
asaperssondec5ebf2015-10-05 02:36:17 -0700365void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
366 if (sample)
367 ++sum;
368 ++num_samples;
369}
370
371int SendStatisticsProxy::BoolSampleCounter::Percent(
372 int min_required_samples) const {
373 return Fraction(min_required_samples, 100.0f);
374}
375
376int SendStatisticsProxy::BoolSampleCounter::Permille(
377 int min_required_samples) const {
378 return Fraction(min_required_samples, 1000.0f);
379}
380
381int SendStatisticsProxy::BoolSampleCounter::Fraction(
382 int min_required_samples, float multiplier) const {
383 if (num_samples < min_required_samples || num_samples == 0)
384 return -1;
385 return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
386}
387
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000388} // namespace webrtc