Index: webrtc/video/stats_counter.cc |
diff --git a/webrtc/video/stats_counter.cc b/webrtc/video/stats_counter.cc |
index 42d23adcfc60f71015e690090c8d779e47959421..9a7eccb7fc1150b561c25a48c694a168cf19d8c2 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/system_wrappers/include/clock.h" |
@@ -19,6 +21,9 @@ namespace webrtc { |
namespace { |
// Periodic time interval for processing samples. |
const int64_t kProcessIntervalMs = 2000; |
+ |
+const uint32_t kSsrc0 = 0; |
+ |
} // namespace |
// Class holding periodically computed metrics. |
@@ -54,16 +59,91 @@ class AggregatedCounter { |
AggregatedStats stats_; |
}; |
+// Class holding gathered samples within a process interval. |
+class Samples { |
+ public: |
+ Samples() {} |
+ ~Samples() {} |
+ |
+ void Add(int sample, uint32_t ssrc) { samples_[ssrc].Add(sample); } |
+ void Set(int sample, uint32_t ssrc) { samples_[ssrc].Set(sample); } |
+ |
+ int64_t Num() const { |
stefan-webrtc
2016/09/08 07:13:34
Should we rename Num and num_ Count() and count_?
åsapersson
2016/09/19 12:45:40
Done.
|
+ int64_t num = 0; |
+ for (const auto& it : samples_) |
+ num += it.second.num_; |
+ return num; |
+ } |
+ |
+ 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(); |
+ } |
+ |
+ int64_t Diff() const { |
+ int64_t sum_diff = 0; |
+ int num = 0; |
+ for (const auto& it : samples_) { |
+ if (it.second.num_ > 0) { |
+ int64_t diff = it.second.sum_ - it.second.last_sum_; |
+ if (diff >= 0) { |
+ sum_diff += diff; |
+ ++num; |
+ } |
+ } |
+ } |
+ return (num > 0) ? sum_diff : -1; |
+ } |
+ |
+ private: |
+ struct Stats { |
+ void Add(int sample) { |
+ sum_ += sample; |
+ ++num_; |
+ max_ = std::max(sample, max_); |
+ } |
+ void Set(int sample) { |
+ sum_ = sample; |
+ ++num_; |
+ } |
+ void Reset() { |
+ if (num_ > 0) |
+ last_sum_ = sum_; |
+ sum_ = 0; |
+ num_ = 0; |
+ max_ = std::numeric_limits<int>::min(); |
+ } |
+ |
+ int max_ = std::numeric_limits<int>::min(); |
+ int64_t num_ = 0; |
+ int64_t sum_ = 0; |
+ int64_t last_sum_ = 0; |
+ }; |
+ |
+ std::map<uint32_t, Stats> samples_; // Gathered samples mapped by SSRC. |
+}; |
+ |
// StatsCounter class. |
StatsCounter::StatsCounter(Clock* clock, |
bool include_empty_intervals, |
StatsCounterObserver* observer) |
- : max_(0), |
- sum_(0), |
- num_samples_(0), |
- last_sum_(0), |
- clock_(clock), |
+ : samples_(new Samples()), |
include_empty_intervals_(include_empty_intervals), |
+ clock_(clock), |
observer_(observer), |
aggregated_counter_(new AggregatedCounter()), |
last_process_time_ms_(-1) {} |
@@ -98,20 +178,14 @@ bool StatsCounter::TimeToProcess() { |
return true; |
} |
-void StatsCounter::Set(int sample) { |
+void StatsCounter::Set(int sample, uint32_t ssrc) { |
TryProcess(); |
- ++num_samples_; |
- sum_ = sample; |
+ samples_->Set(sample, ssrc); |
} |
void StatsCounter::Add(int sample) { |
stefan-webrtc
2016/09/08 07:15:13
Do you think it would be better to just expose the
åsapersson
2016/09/19 12:45:40
It is only one subclass that have use for setting
|
TryProcess(); |
- ++num_samples_; |
- sum_ += sample; |
- |
- if (num_samples_ == 1) |
- max_ = sample; |
- max_ = std::max(sample, max_); |
+ samples_->Add(sample, kSsrc0); |
} |
void StatsCounter::TryProcess() { |
@@ -124,10 +198,8 @@ void StatsCounter::TryProcess() { |
if (observer_) |
observer_->OnMetricUpdated(metric); |
} |
- last_sum_ = sum_; |
- sum_ = 0; |
- max_ = 0; |
- num_samples_ = 0; |
+ |
+ samples_->Reset(); |
} |
// StatsCounter sub-classes. |
@@ -141,9 +213,11 @@ void AvgCounter::Add(int sample) { |
} |
bool AvgCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0) |
+ int64_t num = samples_->Num(); |
+ if (num == 0) |
return false; |
stefan-webrtc
2016/09/08 07:13:34
This is a fairly expensive way of checking for no
åsapersson
2016/09/19 12:45:40
The expected size will be one for all sub-classes
|
- *metric = (sum_ + num_samples_ / 2) / num_samples_; |
+ |
+ *metric = (samples_->Sum() + num / 2) / num; |
return true; |
} |
@@ -157,9 +231,11 @@ void MaxCounter::Add(int sample) { |
} |
bool MaxCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0) |
+ int64_t num = samples_->Num(); |
+ if (num == 0) |
return false; |
- *metric = max_; |
+ |
+ *metric = samples_->Max(); |
return true; |
} |
@@ -173,9 +249,11 @@ void PercentCounter::Add(bool sample) { |
} |
bool PercentCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0) |
+ int64_t num = samples_->Num(); |
+ if (num == 0) |
return false; |
- *metric = (sum_ * 100 + num_samples_ / 2) / num_samples_; |
+ |
+ *metric = (samples_->Sum() * 100 + num / 2) / num; |
return true; |
} |
@@ -189,9 +267,11 @@ void PermilleCounter::Add(bool sample) { |
} |
bool PermilleCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0) |
+ int64_t num = samples_->Num(); |
+ if (num == 0) |
return false; |
- *metric = (sum_ * 1000 + num_samples_ / 2) / num_samples_; |
+ |
+ *metric = (samples_->Sum() * 1000 + num / 2) / num; |
return true; |
} |
@@ -205,9 +285,11 @@ void RateCounter::Add(int sample) { |
} |
bool RateCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0) |
+ if (samples_->Num() == 0) |
return false; |
- *metric = (sum_ * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; |
+ |
+ *metric = |
+ (samples_->Sum() * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; |
return true; |
} |
@@ -216,15 +298,19 @@ RateAccCounter::RateAccCounter(Clock* clock, |
bool include_empty_intervals) |
: StatsCounter(clock, include_empty_intervals, observer) {} |
-void RateAccCounter::Set(int sample) { |
- StatsCounter::Set(sample); |
+void RateAccCounter::Set(int sample, uint32_t ssrc) { |
+ StatsCounter::Set(sample, ssrc); |
} |
bool RateAccCounter::GetMetric(int* metric) const { |
- if (num_samples_ == 0 || last_sum_ > sum_) |
+ if (samples_->Num() == 0) |
return false; |
- *metric = |
- ((sum_ - last_sum_) * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; |
+ |
+ int64_t diff = samples_->Diff(); |
+ if (diff < 0 || (!include_empty_intervals_ && diff == 0)) |
+ return false; |
+ |
+ *metric = (diff * 1000 + kProcessIntervalMs / 2) / kProcessIntervalMs; |
return true; |
} |