| Index: webrtc/video/stats_counter.cc
|
| diff --git a/webrtc/video/stats_counter.cc b/webrtc/video/stats_counter.cc
|
| index f1b82e8f5772101622ea90b9d492aef0bae0e33c..9923ed20d7a2e2a25c6bcb078ea7a8b42e9190a2 100644
|
| --- a/webrtc/video/stats_counter.cc
|
| +++ b/webrtc/video/stats_counter.cc
|
| @@ -11,6 +11,8 @@
|
| #include "webrtc/video/stats_counter.h"
|
|
|
| #include <algorithm>
|
| +#include <limits>
|
| +#include <map>
|
|
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/system_wrappers/include/clock.h"
|
| @@ -20,6 +22,7 @@ namespace webrtc {
|
| namespace {
|
| // Default periodic time interval for processing samples.
|
| const int64_t kDefaultProcessIntervalMs = 2000;
|
| +const uint32_t kStreamId0 = 0;
|
| } // namespace
|
|
|
| // Class holding periodically computed metrics.
|
| @@ -62,19 +65,98 @@ class AggregatedCounter {
|
| AggregatedStats stats_;
|
| };
|
|
|
| +// Class holding gathered samples within a process interval.
|
| +class Samples {
|
| + public:
|
| + Samples() : total_count_(0) {}
|
| + ~Samples() {}
|
| +
|
| + void Add(int sample, uint32_t stream_id) {
|
| + samples_[stream_id].Add(sample);
|
| + ++total_count_;
|
| + }
|
| + void Set(int sample, uint32_t stream_id) {
|
| + samples_[stream_id].Set(sample);
|
| + ++total_count_;
|
| + }
|
| +
|
| + int64_t Count() const { return total_count_; }
|
| + bool Empty() const { return total_count_ == 0; }
|
| +
|
| + int64_t Sum() const {
|
| + int64_t sum = 0;
|
| + for (const auto& it : samples_)
|
| + sum += it.second.sum_;
|
| + return sum;
|
| + }
|
| +
|
| + int Max() const {
|
| + int max = std::numeric_limits<int>::min();
|
| + for (const auto& it : samples_)
|
| + max = std::max(it.second.max_, max);
|
| + return max;
|
| + }
|
| +
|
| + void Reset() {
|
| + for (auto& it : samples_)
|
| + it.second.Reset();
|
| + total_count_ = 0;
|
| + }
|
| +
|
| + int64_t Diff() const {
|
| + int64_t sum_diff = 0;
|
| + int count = 0;
|
| + for (const auto& it : samples_) {
|
| + if (it.second.count_ > 0) {
|
| + int64_t diff = it.second.sum_ - it.second.last_sum_;
|
| + if (diff >= 0) {
|
| + sum_diff += diff;
|
| + ++count;
|
| + }
|
| + }
|
| + }
|
| + return (count > 0) ? sum_diff : -1;
|
| + }
|
| +
|
| + private:
|
| + struct Stats {
|
| + void Add(int sample) {
|
| + sum_ += sample;
|
| + ++count_;
|
| + max_ = std::max(sample, max_);
|
| + }
|
| + void Set(int sample) {
|
| + sum_ = sample;
|
| + ++count_;
|
| + }
|
| + void Reset() {
|
| + if (count_ > 0)
|
| + last_sum_ = sum_;
|
| + sum_ = 0;
|
| + count_ = 0;
|
| + max_ = std::numeric_limits<int>::min();
|
| + }
|
| +
|
| + int max_ = std::numeric_limits<int>::min();
|
| + int64_t count_ = 0;
|
| + int64_t sum_ = 0;
|
| + int64_t last_sum_ = 0;
|
| + };
|
| +
|
| + int64_t total_count_;
|
| + std::map<uint32_t, Stats> samples_; // Gathered samples mapped by stream id.
|
| +};
|
| +
|
| // StatsCounter class.
|
| StatsCounter::StatsCounter(Clock* clock,
|
| int64_t process_intervals_ms,
|
| bool include_empty_intervals,
|
| StatsCounterObserver* observer)
|
| - : max_(0),
|
| - sum_(0),
|
| - num_samples_(0),
|
| - last_sum_(0),
|
| - aggregated_counter_(new AggregatedCounter()),
|
| + : include_empty_intervals_(include_empty_intervals),
|
| process_intervals_ms_(process_intervals_ms),
|
| + aggregated_counter_(new AggregatedCounter()),
|
| + samples_(new Samples()),
|
| clock_(clock),
|
| - include_empty_intervals_(include_empty_intervals),
|
| observer_(observer),
|
| last_process_time_ms_(-1),
|
| paused_(false) {
|
| @@ -120,21 +202,15 @@ bool StatsCounter::TimeToProcess(int* elapsed_intervals) {
|
| return true;
|
| }
|
|
|
| -void StatsCounter::Set(int sample) {
|
| +void StatsCounter::Set(int sample, uint32_t stream_id) {
|
| TryProcess();
|
| - ++num_samples_;
|
| - sum_ = sample;
|
| + samples_->Set(sample, stream_id);
|
| paused_ = false;
|
| }
|
|
|
| void StatsCounter::Add(int sample) {
|
| TryProcess();
|
| - ++num_samples_;
|
| - sum_ += sample;
|
| -
|
| - if (num_samples_ == 1)
|
| - max_ = sample;
|
| - max_ = std::max(sample, max_);
|
| + samples_->Add(sample, kStreamId0);
|
| paused_ = false;
|
| }
|
|
|
| @@ -164,17 +240,13 @@ void StatsCounter::TryProcess() {
|
| // 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);
|
| + samples_->Empty() ? elapsed_intervals : (elapsed_intervals - 1);
|
| ReportMetricToAggregatedCounter(GetValueForEmptyInterval(),
|
| empty_intervals);
|
| }
|
|
|
| // Reset samples for elapsed interval.
|
| - if (num_samples_ > 0)
|
| - last_sum_ = sum_;
|
| - sum_ = 0;
|
| - max_ = 0;
|
| - num_samples_ = 0;
|
| + samples_->Reset();
|
| }
|
|
|
| bool StatsCounter::IncludeEmptyIntervals() const {
|
| @@ -195,9 +267,11 @@ void AvgCounter::Add(int sample) {
|
| }
|
|
|
| bool AvgCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0)
|
| + int64_t count = samples_->Count();
|
| + if (count == 0)
|
| return false;
|
| - *metric = (sum_ + num_samples_ / 2) / num_samples_;
|
| +
|
| + *metric = (samples_->Sum() + count / 2) / count;
|
| return true;
|
| }
|
|
|
| @@ -218,9 +292,10 @@ void MaxCounter::Add(int sample) {
|
| }
|
|
|
| bool MaxCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0)
|
| + if (samples_->Empty())
|
| return false;
|
| - *metric = max_;
|
| +
|
| + *metric = samples_->Max();
|
| return true;
|
| }
|
|
|
| @@ -240,9 +315,11 @@ void PercentCounter::Add(bool sample) {
|
| }
|
|
|
| bool PercentCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0)
|
| + int64_t count = samples_->Count();
|
| + if (count == 0)
|
| return false;
|
| - *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_;
|
| +
|
| + *metric = (samples_->Sum() * 100 + count / 2) / count;
|
| return true;
|
| }
|
|
|
| @@ -262,9 +339,11 @@ void PermilleCounter::Add(bool sample) {
|
| }
|
|
|
| bool PermilleCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0)
|
| + int64_t count = samples_->Count();
|
| + if (count == 0)
|
| return false;
|
| - *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_;
|
| +
|
| + *metric = (samples_->Sum() * 1000 + count / 2) / count;
|
| return true;
|
| }
|
|
|
| @@ -286,9 +365,11 @@ void RateCounter::Add(int sample) {
|
| }
|
|
|
| bool RateCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0)
|
| + if (samples_->Empty())
|
| return false;
|
| - *metric = (sum_ * 1000 + process_intervals_ms_ / 2) / process_intervals_ms_;
|
| +
|
| + *metric = (samples_->Sum() * 1000 + process_intervals_ms_ / 2) /
|
| + process_intervals_ms_;
|
| return true;
|
| }
|
|
|
| @@ -304,15 +385,16 @@ RateAccCounter::RateAccCounter(Clock* clock,
|
| include_empty_intervals,
|
| observer) {}
|
|
|
| -void RateAccCounter::Set(int sample) {
|
| - StatsCounter::Set(sample);
|
| +void RateAccCounter::Set(int sample, uint32_t stream_id) {
|
| + StatsCounter::Set(sample, stream_id);
|
| }
|
|
|
| bool RateAccCounter::GetMetric(int* metric) const {
|
| - if (num_samples_ == 0 || last_sum_ > sum_)
|
| + int64_t diff = samples_->Diff();
|
| + if (diff < 0 || (!include_empty_intervals_ && diff == 0))
|
| return false;
|
| - *metric = ((sum_ - last_sum_) * 1000 + process_intervals_ms_ / 2) /
|
| - process_intervals_ms_;
|
| +
|
| + *metric = (diff * 1000 + process_intervals_ms_ / 2) / process_intervals_ms_;
|
| return true;
|
| }
|
|
|
|
|