1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "video/stats_counter.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <limits>
15*d9f75844SAndroid Build Coastguard Worker #include <map>
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
19*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h"
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Worker namespace {
24*d9f75844SAndroid Build Coastguard Worker // Default periodic time interval for processing samples.
25*d9f75844SAndroid Build Coastguard Worker const int64_t kDefaultProcessIntervalMs = 2000;
26*d9f75844SAndroid Build Coastguard Worker const uint32_t kStreamId0 = 0;
27*d9f75844SAndroid Build Coastguard Worker } // namespace
28*d9f75844SAndroid Build Coastguard Worker
ToString() const29*d9f75844SAndroid Build Coastguard Worker std::string AggregatedStats::ToString() const {
30*d9f75844SAndroid Build Coastguard Worker return ToStringWithMultiplier(1);
31*d9f75844SAndroid Build Coastguard Worker }
32*d9f75844SAndroid Build Coastguard Worker
ToStringWithMultiplier(int multiplier) const33*d9f75844SAndroid Build Coastguard Worker std::string AggregatedStats::ToStringWithMultiplier(int multiplier) const {
34*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder ss;
35*d9f75844SAndroid Build Coastguard Worker ss << "periodic_samples:" << num_samples << ", {";
36*d9f75844SAndroid Build Coastguard Worker ss << "min:" << (min * multiplier) << ", ";
37*d9f75844SAndroid Build Coastguard Worker ss << "avg:" << (average * multiplier) << ", ";
38*d9f75844SAndroid Build Coastguard Worker ss << "max:" << (max * multiplier) << "}";
39*d9f75844SAndroid Build Coastguard Worker return ss.Release();
40*d9f75844SAndroid Build Coastguard Worker }
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker // Class holding periodically computed metrics.
43*d9f75844SAndroid Build Coastguard Worker class AggregatedCounter {
44*d9f75844SAndroid Build Coastguard Worker public:
AggregatedCounter()45*d9f75844SAndroid Build Coastguard Worker AggregatedCounter() : last_sample_(0), sum_samples_(0) {}
~AggregatedCounter()46*d9f75844SAndroid Build Coastguard Worker ~AggregatedCounter() {}
47*d9f75844SAndroid Build Coastguard Worker
Add(int sample)48*d9f75844SAndroid Build Coastguard Worker void Add(int sample) {
49*d9f75844SAndroid Build Coastguard Worker last_sample_ = sample;
50*d9f75844SAndroid Build Coastguard Worker sum_samples_ += sample;
51*d9f75844SAndroid Build Coastguard Worker ++stats_.num_samples;
52*d9f75844SAndroid Build Coastguard Worker if (stats_.num_samples == 1) {
53*d9f75844SAndroid Build Coastguard Worker stats_.min = sample;
54*d9f75844SAndroid Build Coastguard Worker stats_.max = sample;
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker stats_.min = std::min(sample, stats_.min);
57*d9f75844SAndroid Build Coastguard Worker stats_.max = std::max(sample, stats_.max);
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker
ComputeStats()60*d9f75844SAndroid Build Coastguard Worker AggregatedStats ComputeStats() {
61*d9f75844SAndroid Build Coastguard Worker Compute();
62*d9f75844SAndroid Build Coastguard Worker return stats_;
63*d9f75844SAndroid Build Coastguard Worker }
64*d9f75844SAndroid Build Coastguard Worker
Empty() const65*d9f75844SAndroid Build Coastguard Worker bool Empty() const { return stats_.num_samples == 0; }
66*d9f75844SAndroid Build Coastguard Worker
last_sample() const67*d9f75844SAndroid Build Coastguard Worker int last_sample() const { return last_sample_; }
68*d9f75844SAndroid Build Coastguard Worker
69*d9f75844SAndroid Build Coastguard Worker private:
Compute()70*d9f75844SAndroid Build Coastguard Worker void Compute() {
71*d9f75844SAndroid Build Coastguard Worker if (stats_.num_samples == 0)
72*d9f75844SAndroid Build Coastguard Worker return;
73*d9f75844SAndroid Build Coastguard Worker
74*d9f75844SAndroid Build Coastguard Worker stats_.average =
75*d9f75844SAndroid Build Coastguard Worker (sum_samples_ + stats_.num_samples / 2) / stats_.num_samples;
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker int last_sample_;
78*d9f75844SAndroid Build Coastguard Worker int64_t sum_samples_;
79*d9f75844SAndroid Build Coastguard Worker AggregatedStats stats_;
80*d9f75844SAndroid Build Coastguard Worker };
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker // Class holding gathered samples within a process interval.
83*d9f75844SAndroid Build Coastguard Worker class Samples {
84*d9f75844SAndroid Build Coastguard Worker public:
Samples()85*d9f75844SAndroid Build Coastguard Worker Samples() : total_count_(0) {}
~Samples()86*d9f75844SAndroid Build Coastguard Worker ~Samples() {}
87*d9f75844SAndroid Build Coastguard Worker
Add(int sample,uint32_t stream_id)88*d9f75844SAndroid Build Coastguard Worker void Add(int sample, uint32_t stream_id) {
89*d9f75844SAndroid Build Coastguard Worker samples_[stream_id].Add(sample);
90*d9f75844SAndroid Build Coastguard Worker ++total_count_;
91*d9f75844SAndroid Build Coastguard Worker }
Set(int64_t sample,uint32_t stream_id)92*d9f75844SAndroid Build Coastguard Worker void Set(int64_t sample, uint32_t stream_id) {
93*d9f75844SAndroid Build Coastguard Worker samples_[stream_id].Set(sample);
94*d9f75844SAndroid Build Coastguard Worker ++total_count_;
95*d9f75844SAndroid Build Coastguard Worker }
SetLast(int64_t sample,uint32_t stream_id)96*d9f75844SAndroid Build Coastguard Worker void SetLast(int64_t sample, uint32_t stream_id) {
97*d9f75844SAndroid Build Coastguard Worker samples_[stream_id].SetLast(sample);
98*d9f75844SAndroid Build Coastguard Worker }
GetLast(uint32_t stream_id)99*d9f75844SAndroid Build Coastguard Worker int64_t GetLast(uint32_t stream_id) { return samples_[stream_id].GetLast(); }
100*d9f75844SAndroid Build Coastguard Worker
Count() const101*d9f75844SAndroid Build Coastguard Worker int64_t Count() const { return total_count_; }
Empty() const102*d9f75844SAndroid Build Coastguard Worker bool Empty() const { return total_count_ == 0; }
103*d9f75844SAndroid Build Coastguard Worker
Sum() const104*d9f75844SAndroid Build Coastguard Worker int64_t Sum() const {
105*d9f75844SAndroid Build Coastguard Worker int64_t sum = 0;
106*d9f75844SAndroid Build Coastguard Worker for (const auto& it : samples_)
107*d9f75844SAndroid Build Coastguard Worker sum += it.second.sum_;
108*d9f75844SAndroid Build Coastguard Worker return sum;
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
Max() const111*d9f75844SAndroid Build Coastguard Worker int Max() const {
112*d9f75844SAndroid Build Coastguard Worker int max = std::numeric_limits<int>::min();
113*d9f75844SAndroid Build Coastguard Worker for (const auto& it : samples_)
114*d9f75844SAndroid Build Coastguard Worker max = std::max(it.second.max_, max);
115*d9f75844SAndroid Build Coastguard Worker return max;
116*d9f75844SAndroid Build Coastguard Worker }
117*d9f75844SAndroid Build Coastguard Worker
Reset()118*d9f75844SAndroid Build Coastguard Worker void Reset() {
119*d9f75844SAndroid Build Coastguard Worker for (auto& it : samples_)
120*d9f75844SAndroid Build Coastguard Worker it.second.Reset();
121*d9f75844SAndroid Build Coastguard Worker total_count_ = 0;
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker
Diff() const124*d9f75844SAndroid Build Coastguard Worker int64_t Diff() const {
125*d9f75844SAndroid Build Coastguard Worker int64_t sum_diff = 0;
126*d9f75844SAndroid Build Coastguard Worker int count = 0;
127*d9f75844SAndroid Build Coastguard Worker for (const auto& it : samples_) {
128*d9f75844SAndroid Build Coastguard Worker if (it.second.count_ > 0) {
129*d9f75844SAndroid Build Coastguard Worker int64_t diff = it.second.sum_ - it.second.last_sum_;
130*d9f75844SAndroid Build Coastguard Worker if (diff >= 0) {
131*d9f75844SAndroid Build Coastguard Worker sum_diff += diff;
132*d9f75844SAndroid Build Coastguard Worker ++count;
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker }
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker return (count > 0) ? sum_diff : -1;
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker
139*d9f75844SAndroid Build Coastguard Worker private:
140*d9f75844SAndroid Build Coastguard Worker struct Stats {
Addwebrtc::Samples::Stats141*d9f75844SAndroid Build Coastguard Worker void Add(int sample) {
142*d9f75844SAndroid Build Coastguard Worker sum_ += sample;
143*d9f75844SAndroid Build Coastguard Worker ++count_;
144*d9f75844SAndroid Build Coastguard Worker max_ = std::max(sample, max_);
145*d9f75844SAndroid Build Coastguard Worker }
Setwebrtc::Samples::Stats146*d9f75844SAndroid Build Coastguard Worker void Set(int64_t sample) {
147*d9f75844SAndroid Build Coastguard Worker sum_ = sample;
148*d9f75844SAndroid Build Coastguard Worker ++count_;
149*d9f75844SAndroid Build Coastguard Worker }
SetLastwebrtc::Samples::Stats150*d9f75844SAndroid Build Coastguard Worker void SetLast(int64_t sample) { last_sum_ = sample; }
GetLastwebrtc::Samples::Stats151*d9f75844SAndroid Build Coastguard Worker int64_t GetLast() const { return last_sum_; }
Resetwebrtc::Samples::Stats152*d9f75844SAndroid Build Coastguard Worker void Reset() {
153*d9f75844SAndroid Build Coastguard Worker if (count_ > 0)
154*d9f75844SAndroid Build Coastguard Worker last_sum_ = sum_;
155*d9f75844SAndroid Build Coastguard Worker sum_ = 0;
156*d9f75844SAndroid Build Coastguard Worker count_ = 0;
157*d9f75844SAndroid Build Coastguard Worker max_ = std::numeric_limits<int>::min();
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker
160*d9f75844SAndroid Build Coastguard Worker int max_ = std::numeric_limits<int>::min();
161*d9f75844SAndroid Build Coastguard Worker int64_t count_ = 0;
162*d9f75844SAndroid Build Coastguard Worker int64_t sum_ = 0;
163*d9f75844SAndroid Build Coastguard Worker int64_t last_sum_ = 0;
164*d9f75844SAndroid Build Coastguard Worker };
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker int64_t total_count_;
167*d9f75844SAndroid Build Coastguard Worker std::map<uint32_t, Stats> samples_; // Gathered samples mapped by stream id.
168*d9f75844SAndroid Build Coastguard Worker };
169*d9f75844SAndroid Build Coastguard Worker
170*d9f75844SAndroid Build Coastguard Worker // StatsCounter class.
StatsCounter(Clock * clock,int64_t process_intervals_ms,bool include_empty_intervals,StatsCounterObserver * observer)171*d9f75844SAndroid Build Coastguard Worker StatsCounter::StatsCounter(Clock* clock,
172*d9f75844SAndroid Build Coastguard Worker int64_t process_intervals_ms,
173*d9f75844SAndroid Build Coastguard Worker bool include_empty_intervals,
174*d9f75844SAndroid Build Coastguard Worker StatsCounterObserver* observer)
175*d9f75844SAndroid Build Coastguard Worker : include_empty_intervals_(include_empty_intervals),
176*d9f75844SAndroid Build Coastguard Worker process_intervals_ms_(process_intervals_ms),
177*d9f75844SAndroid Build Coastguard Worker aggregated_counter_(new AggregatedCounter()),
178*d9f75844SAndroid Build Coastguard Worker samples_(new Samples()),
179*d9f75844SAndroid Build Coastguard Worker clock_(clock),
180*d9f75844SAndroid Build Coastguard Worker observer_(observer),
181*d9f75844SAndroid Build Coastguard Worker last_process_time_ms_(-1),
182*d9f75844SAndroid Build Coastguard Worker paused_(false),
183*d9f75844SAndroid Build Coastguard Worker pause_time_ms_(-1),
184*d9f75844SAndroid Build Coastguard Worker min_pause_time_ms_(0) {
185*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_GT(process_intervals_ms_, 0);
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker
~StatsCounter()188*d9f75844SAndroid Build Coastguard Worker StatsCounter::~StatsCounter() {}
189*d9f75844SAndroid Build Coastguard Worker
GetStats()190*d9f75844SAndroid Build Coastguard Worker AggregatedStats StatsCounter::GetStats() {
191*d9f75844SAndroid Build Coastguard Worker return aggregated_counter_->ComputeStats();
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
ProcessAndGetStats()194*d9f75844SAndroid Build Coastguard Worker AggregatedStats StatsCounter::ProcessAndGetStats() {
195*d9f75844SAndroid Build Coastguard Worker if (HasSample())
196*d9f75844SAndroid Build Coastguard Worker TryProcess();
197*d9f75844SAndroid Build Coastguard Worker return aggregated_counter_->ComputeStats();
198*d9f75844SAndroid Build Coastguard Worker }
199*d9f75844SAndroid Build Coastguard Worker
ProcessAndPauseForDuration(int64_t min_pause_time_ms)200*d9f75844SAndroid Build Coastguard Worker void StatsCounter::ProcessAndPauseForDuration(int64_t min_pause_time_ms) {
201*d9f75844SAndroid Build Coastguard Worker ProcessAndPause();
202*d9f75844SAndroid Build Coastguard Worker min_pause_time_ms_ = min_pause_time_ms;
203*d9f75844SAndroid Build Coastguard Worker }
204*d9f75844SAndroid Build Coastguard Worker
ProcessAndPause()205*d9f75844SAndroid Build Coastguard Worker void StatsCounter::ProcessAndPause() {
206*d9f75844SAndroid Build Coastguard Worker if (HasSample())
207*d9f75844SAndroid Build Coastguard Worker TryProcess();
208*d9f75844SAndroid Build Coastguard Worker paused_ = true;
209*d9f75844SAndroid Build Coastguard Worker pause_time_ms_ = clock_->TimeInMilliseconds();
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker
ProcessAndStopPause()212*d9f75844SAndroid Build Coastguard Worker void StatsCounter::ProcessAndStopPause() {
213*d9f75844SAndroid Build Coastguard Worker if (HasSample())
214*d9f75844SAndroid Build Coastguard Worker TryProcess();
215*d9f75844SAndroid Build Coastguard Worker Resume();
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker
HasSample() const218*d9f75844SAndroid Build Coastguard Worker bool StatsCounter::HasSample() const {
219*d9f75844SAndroid Build Coastguard Worker return last_process_time_ms_ != -1;
220*d9f75844SAndroid Build Coastguard Worker }
221*d9f75844SAndroid Build Coastguard Worker
TimeToProcess(int * elapsed_intervals)222*d9f75844SAndroid Build Coastguard Worker bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
223*d9f75844SAndroid Build Coastguard Worker int64_t now = clock_->TimeInMilliseconds();
224*d9f75844SAndroid Build Coastguard Worker if (last_process_time_ms_ == -1)
225*d9f75844SAndroid Build Coastguard Worker last_process_time_ms_ = now;
226*d9f75844SAndroid Build Coastguard Worker
227*d9f75844SAndroid Build Coastguard Worker int64_t diff_ms = now - last_process_time_ms_;
228*d9f75844SAndroid Build Coastguard Worker if (diff_ms < process_intervals_ms_)
229*d9f75844SAndroid Build Coastguard Worker return false;
230*d9f75844SAndroid Build Coastguard Worker
231*d9f75844SAndroid Build Coastguard Worker // Advance number of complete `process_intervals_ms_` that have passed.
232*d9f75844SAndroid Build Coastguard Worker int64_t num_intervals = diff_ms / process_intervals_ms_;
233*d9f75844SAndroid Build Coastguard Worker last_process_time_ms_ += num_intervals * process_intervals_ms_;
234*d9f75844SAndroid Build Coastguard Worker
235*d9f75844SAndroid Build Coastguard Worker *elapsed_intervals = num_intervals;
236*d9f75844SAndroid Build Coastguard Worker return true;
237*d9f75844SAndroid Build Coastguard Worker }
238*d9f75844SAndroid Build Coastguard Worker
Add(int sample)239*d9f75844SAndroid Build Coastguard Worker void StatsCounter::Add(int sample) {
240*d9f75844SAndroid Build Coastguard Worker TryProcess();
241*d9f75844SAndroid Build Coastguard Worker samples_->Add(sample, kStreamId0);
242*d9f75844SAndroid Build Coastguard Worker ResumeIfMinTimePassed();
243*d9f75844SAndroid Build Coastguard Worker }
244*d9f75844SAndroid Build Coastguard Worker
Set(int64_t sample,uint32_t stream_id)245*d9f75844SAndroid Build Coastguard Worker void StatsCounter::Set(int64_t sample, uint32_t stream_id) {
246*d9f75844SAndroid Build Coastguard Worker if (paused_ && sample == samples_->GetLast(stream_id)) {
247*d9f75844SAndroid Build Coastguard Worker // Do not add same sample while paused (will reset pause).
248*d9f75844SAndroid Build Coastguard Worker return;
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker TryProcess();
251*d9f75844SAndroid Build Coastguard Worker samples_->Set(sample, stream_id);
252*d9f75844SAndroid Build Coastguard Worker ResumeIfMinTimePassed();
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker
SetLast(int64_t sample,uint32_t stream_id)255*d9f75844SAndroid Build Coastguard Worker void StatsCounter::SetLast(int64_t sample, uint32_t stream_id) {
256*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!HasSample()) << "Should be set before first sample is added.";
257*d9f75844SAndroid Build Coastguard Worker samples_->SetLast(sample, stream_id);
258*d9f75844SAndroid Build Coastguard Worker }
259*d9f75844SAndroid Build Coastguard Worker
260*d9f75844SAndroid Build Coastguard Worker // Reports periodically computed metric.
ReportMetricToAggregatedCounter(int value,int num_values_to_add) const261*d9f75844SAndroid Build Coastguard Worker void StatsCounter::ReportMetricToAggregatedCounter(
262*d9f75844SAndroid Build Coastguard Worker int value,
263*d9f75844SAndroid Build Coastguard Worker int num_values_to_add) const {
264*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < num_values_to_add; ++i) {
265*d9f75844SAndroid Build Coastguard Worker aggregated_counter_->Add(value);
266*d9f75844SAndroid Build Coastguard Worker if (observer_)
267*d9f75844SAndroid Build Coastguard Worker observer_->OnMetricUpdated(value);
268*d9f75844SAndroid Build Coastguard Worker }
269*d9f75844SAndroid Build Coastguard Worker }
270*d9f75844SAndroid Build Coastguard Worker
TryProcess()271*d9f75844SAndroid Build Coastguard Worker void StatsCounter::TryProcess() {
272*d9f75844SAndroid Build Coastguard Worker int elapsed_intervals;
273*d9f75844SAndroid Build Coastguard Worker if (!TimeToProcess(&elapsed_intervals))
274*d9f75844SAndroid Build Coastguard Worker return;
275*d9f75844SAndroid Build Coastguard Worker
276*d9f75844SAndroid Build Coastguard Worker // Get and report periodically computed metric.
277*d9f75844SAndroid Build Coastguard Worker int metric;
278*d9f75844SAndroid Build Coastguard Worker if (GetMetric(&metric))
279*d9f75844SAndroid Build Coastguard Worker ReportMetricToAggregatedCounter(metric, 1);
280*d9f75844SAndroid Build Coastguard Worker
281*d9f75844SAndroid Build Coastguard Worker // Report value for elapsed intervals without samples.
282*d9f75844SAndroid Build Coastguard Worker if (IncludeEmptyIntervals()) {
283*d9f75844SAndroid Build Coastguard Worker // If there are no samples, all elapsed intervals are empty (otherwise one
284*d9f75844SAndroid Build Coastguard Worker // interval contains sample(s), discard this interval).
285*d9f75844SAndroid Build Coastguard Worker int empty_intervals =
286*d9f75844SAndroid Build Coastguard Worker samples_->Empty() ? elapsed_intervals : (elapsed_intervals - 1);
287*d9f75844SAndroid Build Coastguard Worker ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
288*d9f75844SAndroid Build Coastguard Worker empty_intervals);
289*d9f75844SAndroid Build Coastguard Worker }
290*d9f75844SAndroid Build Coastguard Worker
291*d9f75844SAndroid Build Coastguard Worker // Reset samples for elapsed interval.
292*d9f75844SAndroid Build Coastguard Worker samples_->Reset();
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker
IncludeEmptyIntervals() const295*d9f75844SAndroid Build Coastguard Worker bool StatsCounter::IncludeEmptyIntervals() const {
296*d9f75844SAndroid Build Coastguard Worker return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty();
297*d9f75844SAndroid Build Coastguard Worker }
ResumeIfMinTimePassed()298*d9f75844SAndroid Build Coastguard Worker void StatsCounter::ResumeIfMinTimePassed() {
299*d9f75844SAndroid Build Coastguard Worker if (paused_ &&
300*d9f75844SAndroid Build Coastguard Worker (clock_->TimeInMilliseconds() - pause_time_ms_) >= min_pause_time_ms_) {
301*d9f75844SAndroid Build Coastguard Worker Resume();
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker }
304*d9f75844SAndroid Build Coastguard Worker
Resume()305*d9f75844SAndroid Build Coastguard Worker void StatsCounter::Resume() {
306*d9f75844SAndroid Build Coastguard Worker paused_ = false;
307*d9f75844SAndroid Build Coastguard Worker min_pause_time_ms_ = 0;
308*d9f75844SAndroid Build Coastguard Worker }
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker // StatsCounter sub-classes.
AvgCounter(Clock * clock,StatsCounterObserver * observer,bool include_empty_intervals)311*d9f75844SAndroid Build Coastguard Worker AvgCounter::AvgCounter(Clock* clock,
312*d9f75844SAndroid Build Coastguard Worker StatsCounterObserver* observer,
313*d9f75844SAndroid Build Coastguard Worker bool include_empty_intervals)
314*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
315*d9f75844SAndroid Build Coastguard Worker kDefaultProcessIntervalMs,
316*d9f75844SAndroid Build Coastguard Worker include_empty_intervals,
317*d9f75844SAndroid Build Coastguard Worker observer) {}
318*d9f75844SAndroid Build Coastguard Worker
Add(int sample)319*d9f75844SAndroid Build Coastguard Worker void AvgCounter::Add(int sample) {
320*d9f75844SAndroid Build Coastguard Worker StatsCounter::Add(sample);
321*d9f75844SAndroid Build Coastguard Worker }
322*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const323*d9f75844SAndroid Build Coastguard Worker bool AvgCounter::GetMetric(int* metric) const {
324*d9f75844SAndroid Build Coastguard Worker int64_t count = samples_->Count();
325*d9f75844SAndroid Build Coastguard Worker if (count == 0)
326*d9f75844SAndroid Build Coastguard Worker return false;
327*d9f75844SAndroid Build Coastguard Worker
328*d9f75844SAndroid Build Coastguard Worker *metric = (samples_->Sum() + count / 2) / count;
329*d9f75844SAndroid Build Coastguard Worker return true;
330*d9f75844SAndroid Build Coastguard Worker }
331*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const332*d9f75844SAndroid Build Coastguard Worker int AvgCounter::GetValueForEmptyInterval() const {
333*d9f75844SAndroid Build Coastguard Worker return aggregated_counter_->last_sample();
334*d9f75844SAndroid Build Coastguard Worker }
335*d9f75844SAndroid Build Coastguard Worker
MaxCounter(Clock * clock,StatsCounterObserver * observer,int64_t process_intervals_ms)336*d9f75844SAndroid Build Coastguard Worker MaxCounter::MaxCounter(Clock* clock,
337*d9f75844SAndroid Build Coastguard Worker StatsCounterObserver* observer,
338*d9f75844SAndroid Build Coastguard Worker int64_t process_intervals_ms)
339*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
340*d9f75844SAndroid Build Coastguard Worker process_intervals_ms,
341*d9f75844SAndroid Build Coastguard Worker false, // `include_empty_intervals`
342*d9f75844SAndroid Build Coastguard Worker observer) {}
343*d9f75844SAndroid Build Coastguard Worker
Add(int sample)344*d9f75844SAndroid Build Coastguard Worker void MaxCounter::Add(int sample) {
345*d9f75844SAndroid Build Coastguard Worker StatsCounter::Add(sample);
346*d9f75844SAndroid Build Coastguard Worker }
347*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const348*d9f75844SAndroid Build Coastguard Worker bool MaxCounter::GetMetric(int* metric) const {
349*d9f75844SAndroid Build Coastguard Worker if (samples_->Empty())
350*d9f75844SAndroid Build Coastguard Worker return false;
351*d9f75844SAndroid Build Coastguard Worker
352*d9f75844SAndroid Build Coastguard Worker *metric = samples_->Max();
353*d9f75844SAndroid Build Coastguard Worker return true;
354*d9f75844SAndroid Build Coastguard Worker }
355*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const356*d9f75844SAndroid Build Coastguard Worker int MaxCounter::GetValueForEmptyInterval() const {
357*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
358*d9f75844SAndroid Build Coastguard Worker return 0;
359*d9f75844SAndroid Build Coastguard Worker }
360*d9f75844SAndroid Build Coastguard Worker
PercentCounter(Clock * clock,StatsCounterObserver * observer)361*d9f75844SAndroid Build Coastguard Worker PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
362*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
363*d9f75844SAndroid Build Coastguard Worker kDefaultProcessIntervalMs,
364*d9f75844SAndroid Build Coastguard Worker false, // `include_empty_intervals`
365*d9f75844SAndroid Build Coastguard Worker observer) {}
366*d9f75844SAndroid Build Coastguard Worker
Add(bool sample)367*d9f75844SAndroid Build Coastguard Worker void PercentCounter::Add(bool sample) {
368*d9f75844SAndroid Build Coastguard Worker StatsCounter::Add(sample ? 1 : 0);
369*d9f75844SAndroid Build Coastguard Worker }
370*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const371*d9f75844SAndroid Build Coastguard Worker bool PercentCounter::GetMetric(int* metric) const {
372*d9f75844SAndroid Build Coastguard Worker int64_t count = samples_->Count();
373*d9f75844SAndroid Build Coastguard Worker if (count == 0)
374*d9f75844SAndroid Build Coastguard Worker return false;
375*d9f75844SAndroid Build Coastguard Worker
376*d9f75844SAndroid Build Coastguard Worker *metric = (samples_->Sum() * 100 + count / 2) / count;
377*d9f75844SAndroid Build Coastguard Worker return true;
378*d9f75844SAndroid Build Coastguard Worker }
379*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const380*d9f75844SAndroid Build Coastguard Worker int PercentCounter::GetValueForEmptyInterval() const {
381*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
382*d9f75844SAndroid Build Coastguard Worker return 0;
383*d9f75844SAndroid Build Coastguard Worker }
384*d9f75844SAndroid Build Coastguard Worker
PermilleCounter(Clock * clock,StatsCounterObserver * observer)385*d9f75844SAndroid Build Coastguard Worker PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
386*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
387*d9f75844SAndroid Build Coastguard Worker kDefaultProcessIntervalMs,
388*d9f75844SAndroid Build Coastguard Worker false, // `include_empty_intervals`
389*d9f75844SAndroid Build Coastguard Worker observer) {}
390*d9f75844SAndroid Build Coastguard Worker
Add(bool sample)391*d9f75844SAndroid Build Coastguard Worker void PermilleCounter::Add(bool sample) {
392*d9f75844SAndroid Build Coastguard Worker StatsCounter::Add(sample ? 1 : 0);
393*d9f75844SAndroid Build Coastguard Worker }
394*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const395*d9f75844SAndroid Build Coastguard Worker bool PermilleCounter::GetMetric(int* metric) const {
396*d9f75844SAndroid Build Coastguard Worker int64_t count = samples_->Count();
397*d9f75844SAndroid Build Coastguard Worker if (count == 0)
398*d9f75844SAndroid Build Coastguard Worker return false;
399*d9f75844SAndroid Build Coastguard Worker
400*d9f75844SAndroid Build Coastguard Worker *metric = (samples_->Sum() * 1000 + count / 2) / count;
401*d9f75844SAndroid Build Coastguard Worker return true;
402*d9f75844SAndroid Build Coastguard Worker }
403*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const404*d9f75844SAndroid Build Coastguard Worker int PermilleCounter::GetValueForEmptyInterval() const {
405*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
406*d9f75844SAndroid Build Coastguard Worker return 0;
407*d9f75844SAndroid Build Coastguard Worker }
408*d9f75844SAndroid Build Coastguard Worker
RateCounter(Clock * clock,StatsCounterObserver * observer,bool include_empty_intervals)409*d9f75844SAndroid Build Coastguard Worker RateCounter::RateCounter(Clock* clock,
410*d9f75844SAndroid Build Coastguard Worker StatsCounterObserver* observer,
411*d9f75844SAndroid Build Coastguard Worker bool include_empty_intervals)
412*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
413*d9f75844SAndroid Build Coastguard Worker kDefaultProcessIntervalMs,
414*d9f75844SAndroid Build Coastguard Worker include_empty_intervals,
415*d9f75844SAndroid Build Coastguard Worker observer) {}
416*d9f75844SAndroid Build Coastguard Worker
Add(int sample)417*d9f75844SAndroid Build Coastguard Worker void RateCounter::Add(int sample) {
418*d9f75844SAndroid Build Coastguard Worker StatsCounter::Add(sample);
419*d9f75844SAndroid Build Coastguard Worker }
420*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const421*d9f75844SAndroid Build Coastguard Worker bool RateCounter::GetMetric(int* metric) const {
422*d9f75844SAndroid Build Coastguard Worker if (samples_->Empty())
423*d9f75844SAndroid Build Coastguard Worker return false;
424*d9f75844SAndroid Build Coastguard Worker
425*d9f75844SAndroid Build Coastguard Worker *metric = (samples_->Sum() * 1000 + process_intervals_ms_ / 2) /
426*d9f75844SAndroid Build Coastguard Worker process_intervals_ms_;
427*d9f75844SAndroid Build Coastguard Worker return true;
428*d9f75844SAndroid Build Coastguard Worker }
429*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const430*d9f75844SAndroid Build Coastguard Worker int RateCounter::GetValueForEmptyInterval() const {
431*d9f75844SAndroid Build Coastguard Worker return 0;
432*d9f75844SAndroid Build Coastguard Worker }
433*d9f75844SAndroid Build Coastguard Worker
RateAccCounter(Clock * clock,StatsCounterObserver * observer,bool include_empty_intervals)434*d9f75844SAndroid Build Coastguard Worker RateAccCounter::RateAccCounter(Clock* clock,
435*d9f75844SAndroid Build Coastguard Worker StatsCounterObserver* observer,
436*d9f75844SAndroid Build Coastguard Worker bool include_empty_intervals)
437*d9f75844SAndroid Build Coastguard Worker : StatsCounter(clock,
438*d9f75844SAndroid Build Coastguard Worker kDefaultProcessIntervalMs,
439*d9f75844SAndroid Build Coastguard Worker include_empty_intervals,
440*d9f75844SAndroid Build Coastguard Worker observer) {}
441*d9f75844SAndroid Build Coastguard Worker
Set(int64_t sample,uint32_t stream_id)442*d9f75844SAndroid Build Coastguard Worker void RateAccCounter::Set(int64_t sample, uint32_t stream_id) {
443*d9f75844SAndroid Build Coastguard Worker StatsCounter::Set(sample, stream_id);
444*d9f75844SAndroid Build Coastguard Worker }
445*d9f75844SAndroid Build Coastguard Worker
SetLast(int64_t sample,uint32_t stream_id)446*d9f75844SAndroid Build Coastguard Worker void RateAccCounter::SetLast(int64_t sample, uint32_t stream_id) {
447*d9f75844SAndroid Build Coastguard Worker StatsCounter::SetLast(sample, stream_id);
448*d9f75844SAndroid Build Coastguard Worker }
449*d9f75844SAndroid Build Coastguard Worker
GetMetric(int * metric) const450*d9f75844SAndroid Build Coastguard Worker bool RateAccCounter::GetMetric(int* metric) const {
451*d9f75844SAndroid Build Coastguard Worker int64_t diff = samples_->Diff();
452*d9f75844SAndroid Build Coastguard Worker if (diff < 0 || (!include_empty_intervals_ && diff == 0))
453*d9f75844SAndroid Build Coastguard Worker return false;
454*d9f75844SAndroid Build Coastguard Worker
455*d9f75844SAndroid Build Coastguard Worker *metric = (diff * 1000 + process_intervals_ms_ / 2) / process_intervals_ms_;
456*d9f75844SAndroid Build Coastguard Worker return true;
457*d9f75844SAndroid Build Coastguard Worker }
458*d9f75844SAndroid Build Coastguard Worker
GetValueForEmptyInterval() const459*d9f75844SAndroid Build Coastguard Worker int RateAccCounter::GetValueForEmptyInterval() const {
460*d9f75844SAndroid Build Coastguard Worker return 0;
461*d9f75844SAndroid Build Coastguard Worker }
462*d9f75844SAndroid Build Coastguard Worker
463*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
464