| Index: webrtc/video/stats_counter.cc
|
| diff --git a/webrtc/video/stats_counter.cc b/webrtc/video/stats_counter.cc
|
| index 5bcef991d29997808c7c20bdaa276c980ecdb01f..0a66015cee6db31ed858cc3a81a574b28aae0409 100644
|
| --- a/webrtc/video/stats_counter.cc
|
| +++ b/webrtc/video/stats_counter.cc
|
| @@ -12,6 +12,7 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "webrtc/base/checks.h"
|
| #include "webrtc/system_wrappers/include/clock.h"
|
|
|
| namespace webrtc {
|
| @@ -24,11 +25,12 @@ const int64_t kProcessIntervalMs = 2000;
|
| // Class holding periodically computed metrics.
|
| class AggregatedCounter {
|
| public:
|
| - AggregatedCounter() : sum_(0) {}
|
| + AggregatedCounter() : last_sample_(0), sum_samples_(0) {}
|
| ~AggregatedCounter() {}
|
|
|
| void Add(int sample) {
|
| - sum_ += sample;
|
| + last_sample_ = sample;
|
| + sum_samples_ += sample;
|
| ++stats_.num_samples;
|
| if (stats_.num_samples == 1) {
|
| stats_.min = sample;
|
| @@ -43,14 +45,20 @@ class AggregatedCounter {
|
| return stats_;
|
| }
|
|
|
| + bool Empty() const { return stats_.num_samples == 0; }
|
| +
|
| + int last_sample() const { return last_sample_; }
|
| +
|
| private:
|
| void Compute() {
|
| if (stats_.num_samples == 0)
|
| return;
|
|
|
| - stats_.average = (sum_ + stats_.num_samples / 2) / stats_.num_samples;
|
| + stats_.average =
|
| + (sum_samples_ + stats_.num_samples / 2) / stats_.num_samples;
|
| }
|
| - int64_t sum_;
|
| + int last_sample_;
|
| + int64_t sum_samples_;
|
| AggregatedStats stats_;
|
| };
|
|
|
| @@ -62,11 +70,12 @@ StatsCounter::StatsCounter(Clock* clock,
|
| sum_(0),
|
| num_samples_(0),
|
| last_sum_(0),
|
| + aggregated_counter_(new AggregatedCounter()),
|
| clock_(clock),
|
| include_empty_intervals_(include_empty_intervals),
|
| observer_(observer),
|
| - aggregated_counter_(new AggregatedCounter()),
|
| - last_process_time_ms_(-1) {}
|
| + last_process_time_ms_(-1),
|
| + paused_(false) {}
|
|
|
| StatsCounter::~StatsCounter() {}
|
|
|
| @@ -74,11 +83,23 @@ AggregatedStats StatsCounter::GetStats() {
|
| return aggregated_counter_->ComputeStats();
|
| }
|
|
|
| +AggregatedStats StatsCounter::ProcessAndGetStats() {
|
| + if (HasSample())
|
| + TryProcess();
|
| + return aggregated_counter_->ComputeStats();
|
| +}
|
| +
|
| +void StatsCounter::ProcessAndPause() {
|
| + if (HasSample())
|
| + TryProcess();
|
| + paused_ = true;
|
| +}
|
| +
|
| bool StatsCounter::HasSample() const {
|
| return last_process_time_ms_ != -1;
|
| }
|
|
|
| -bool StatsCounter::TimeToProcess() {
|
| +bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
|
| int64_t now = clock_->TimeInMilliseconds();
|
| if (last_process_time_ms_ == -1)
|
| last_process_time_ms_ = now;
|
| @@ -91,14 +112,7 @@ bool StatsCounter::TimeToProcess() {
|
| int64_t num_intervals = diff_ms / kProcessIntervalMs;
|
| last_process_time_ms_ += num_intervals * kProcessIntervalMs;
|
|
|
| - // Add zero for intervals without samples.
|
| - if (include_empty_intervals_) {
|
| - for (int64_t i = 0; i < num_intervals - 1; ++i) {
|
| - aggregated_counter_->Add(0);
|
| - if (observer_)
|
| - observer_->OnMetricUpdated(0);
|
| - }
|
| - }
|
| + *elapsed_intervals = num_intervals;
|
| return true;
|
| }
|
|
|
| @@ -106,6 +120,7 @@ void StatsCounter::Set(int sample) {
|
| TryProcess();
|
| ++num_samples_;
|
| sum_ = sample;
|
| + paused_ = false;
|
| }
|
|
|
| void StatsCounter::Add(int sample) {
|
| @@ -116,29 +131,57 @@ void StatsCounter::Add(int sample) {
|
| if (num_samples_ == 1)
|
| max_ = sample;
|
| max_ = std::max(sample, max_);
|
| + paused_ = false;
|
| +}
|
| +
|
| +// Reports periodically computed metric.
|
| +void StatsCounter::ReportMetricToAggregatedCounter(
|
| + int value,
|
| + int num_values_to_add) const {
|
| + for (int i = 0; i < num_values_to_add; ++i) {
|
| + aggregated_counter_->Add(value);
|
| + if (observer_)
|
| + observer_->OnMetricUpdated(value);
|
| + }
|
| }
|
|
|
| void StatsCounter::TryProcess() {
|
| - if (!TimeToProcess())
|
| + int elapsed_intervals;
|
| + if (!TimeToProcess(&elapsed_intervals))
|
| return;
|
|
|
| + // Get and report periodically computed metric.
|
| int metric;
|
| - if (GetMetric(&metric)) {
|
| - aggregated_counter_->Add(metric);
|
| - if (observer_)
|
| - observer_->OnMetricUpdated(metric);
|
| + if (GetMetric(&metric))
|
| + ReportMetricToAggregatedCounter(metric, 1);
|
| +
|
| + // Report value for elapsed intervals without samples.
|
| + if (IncludeEmptyIntervals()) {
|
| + // If there are no samples, all elapsed intervals are empty (otherwise one
|
| + // interval contains sample(s), discard this interval).
|
| + int empty_intervals =
|
| + (num_samples_ == 0) ? elapsed_intervals : (elapsed_intervals - 1);
|
| + ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
|
| + empty_intervals);
|
| }
|
| - last_sum_ = sum_;
|
| +
|
| + // Reset samples for elapsed interval.
|
| + if (num_samples_ > 0)
|
| + last_sum_ = sum_;
|
| sum_ = 0;
|
| max_ = 0;
|
| num_samples_ = 0;
|
| }
|
|
|
| +bool StatsCounter::IncludeEmptyIntervals() const {
|
| + return include_empty_intervals_ && !paused_ && !aggregated_counter_->Empty();
|
| +}
|
| +
|
| // StatsCounter sub-classes.
|
| -AvgCounter::AvgCounter(Clock* clock, StatsCounterObserver* observer)
|
| - : StatsCounter(clock,
|
| - false, // |include_empty_intervals|
|
| - observer) {}
|
| +AvgCounter::AvgCounter(Clock* clock,
|
| + StatsCounterObserver* observer,
|
| + bool include_empty_intervals)
|
| + : StatsCounter(clock, include_empty_intervals, observer) {}
|
|
|
| void AvgCounter::Add(int sample) {
|
| StatsCounter::Add(sample);
|
| @@ -151,6 +194,10 @@ bool AvgCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int AvgCounter::GetValueForEmptyInterval() const {
|
| + return aggregated_counter_->last_sample();
|
| +}
|
| +
|
| MaxCounter::MaxCounter(Clock* clock, StatsCounterObserver* observer)
|
| : StatsCounter(clock,
|
| false, // |include_empty_intervals|
|
| @@ -167,6 +214,11 @@ bool MaxCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int MaxCounter::GetValueForEmptyInterval() const {
|
| + RTC_NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| PercentCounter::PercentCounter(Clock* clock, StatsCounterObserver* observer)
|
| : StatsCounter(clock,
|
| false, // |include_empty_intervals|
|
| @@ -183,6 +235,11 @@ bool PercentCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int PercentCounter::GetValueForEmptyInterval() const {
|
| + RTC_NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| PermilleCounter::PermilleCounter(Clock* clock, StatsCounterObserver* observer)
|
| : StatsCounter(clock,
|
| false, // |include_empty_intervals|
|
| @@ -199,6 +256,11 @@ bool PermilleCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int PermilleCounter::GetValueForEmptyInterval() const {
|
| + RTC_NOTREACHED();
|
| + return 0;
|
| +}
|
| +
|
| RateCounter::RateCounter(Clock* clock,
|
| StatsCounterObserver* observer,
|
| bool include_empty_intervals)
|
| @@ -215,6 +277,10 @@ bool RateCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int RateCounter::GetValueForEmptyInterval() const {
|
| + return 0;
|
| +}
|
| +
|
| RateAccCounter::RateAccCounter(Clock* clock,
|
| StatsCounterObserver* observer,
|
| bool include_empty_intervals)
|
| @@ -232,4 +298,8 @@ bool RateAccCounter::GetMetric(int* metric) const {
|
| return true;
|
| }
|
|
|
| +int RateAccCounter::GetValueForEmptyInterval() const {
|
| + return 0;
|
| +}
|
| +
|
| } // namespace webrtc
|
|
|