diff options
Diffstat (limited to 'third_party/libwebrtc/video/stats_counter.h')
-rw-r--r-- | third_party/libwebrtc/video/stats_counter.h | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/third_party/libwebrtc/video/stats_counter.h b/third_party/libwebrtc/video/stats_counter.h new file mode 100644 index 0000000000..9e2b8702d6 --- /dev/null +++ b/third_party/libwebrtc/video/stats_counter.h @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VIDEO_STATS_COUNTER_H_ +#define VIDEO_STATS_COUNTER_H_ + +#include <memory> +#include <string> + +namespace webrtc { + +class AggregatedCounter; +class Clock; +class Samples; + +// `StatsCounterObserver` is called periodically when a metric is updated. +class StatsCounterObserver { + public: + virtual void OnMetricUpdated(int sample) = 0; + + virtual ~StatsCounterObserver() {} +}; + +struct AggregatedStats { + std::string ToString() const; + std::string ToStringWithMultiplier(int multiplier) const; + + int64_t num_samples = 0; + int min = -1; + int max = -1; + int average = -1; + // TODO(asapersson): Consider adding median/percentiles. +}; + +// Classes which periodically computes a metric. +// +// During a period, `kProcessIntervalMs`, different metrics can be computed e.g: +// - `AvgCounter`: average of samples +// - `PercentCounter`: percentage of samples +// - `PermilleCounter`: permille of samples +// +// Each periodic metric can be either: +// - reported to an `observer` each period +// - aggregated during the call (e.g. min, max, average) +// +// periodically computed +// GetMetric() GetMetric() => AggregatedStats +// ^ ^ (e.g. min/max/avg) +// | | +// | * * * * | ** * * * * | ... +// |<- process interval ->| +// +// (*) - samples +// +// +// Example usage: +// +// AvgCounter counter(&clock, nullptr); +// counter.Add(5); +// counter.Add(1); +// counter.Add(6); // process interval passed -> GetMetric() avg:4 +// counter.Add(7); +// counter.Add(3); // process interval passed -> GetMetric() avg:5 +// counter.Add(10); +// counter.Add(20); // process interval passed -> GetMetric() avg:15 +// AggregatedStats stats = counter.GetStats(); +// stats: {min:4, max:15, avg:8} +// + +// Note: StatsCounter takes ownership of `observer`. + +class StatsCounter { + public: + virtual ~StatsCounter(); + + // Gets metric within an interval. Returns true on success false otherwise. + virtual bool GetMetric(int* metric) const = 0; + + // Gets the value to use for an interval without samples. + virtual int GetValueForEmptyInterval() const = 0; + + // Gets aggregated stats (i.e. aggregate of periodically computed metrics). + AggregatedStats GetStats(); + + // Reports metrics for elapsed intervals to AggregatedCounter and GetStats. + AggregatedStats ProcessAndGetStats(); + + // Reports metrics for elapsed intervals to AggregatedCounter and pauses stats + // (i.e. empty intervals will be discarded until next sample is added). + void ProcessAndPause(); + + // As above with a minimum pause time. Added samples within this interval will + // not resume the stats (i.e. stop the pause). + void ProcessAndPauseForDuration(int64_t min_pause_time_ms); + + // Reports metrics for elapsed intervals to AggregatedCounter and stops pause. + void ProcessAndStopPause(); + + // Checks if a sample has been added (i.e. Add or Set called). + bool HasSample() const; + + protected: + StatsCounter(Clock* clock, + int64_t process_intervals_ms, + bool include_empty_intervals, + StatsCounterObserver* observer); + + void Add(int sample); + void Set(int64_t sample, uint32_t stream_id); + void SetLast(int64_t sample, uint32_t stream_id); + + const bool include_empty_intervals_; + const int64_t process_intervals_ms_; + const std::unique_ptr<AggregatedCounter> aggregated_counter_; + const std::unique_ptr<Samples> samples_; + + private: + bool TimeToProcess(int* num_elapsed_intervals); + void TryProcess(); + void ReportMetricToAggregatedCounter(int value, int num_values_to_add) const; + bool IncludeEmptyIntervals() const; + void Resume(); + void ResumeIfMinTimePassed(); + + Clock* const clock_; + const std::unique_ptr<StatsCounterObserver> observer_; + int64_t last_process_time_ms_; + bool paused_; + int64_t pause_time_ms_; + int64_t min_pause_time_ms_; +}; + +// AvgCounter: average of samples +// +// | * * * | * * | ... +// | Add(5) Add(1) Add(6) | Add(5) Add(5) | +// GetMetric | (5 + 1 + 6) / 3 | (5 + 5) / 2 | +// +// `include_empty_intervals`: If set, intervals without samples will be included +// in the stats. The value for an interval is +// determined by GetValueForEmptyInterval(). +// +class AvgCounter : public StatsCounter { + public: + AvgCounter(Clock* clock, + StatsCounterObserver* observer, + bool include_empty_intervals); + ~AvgCounter() override {} + + AvgCounter(const AvgCounter&) = delete; + AvgCounter& operator=(const AvgCounter&) = delete; + + void Add(int sample); + + private: + bool GetMetric(int* metric) const override; + + // Returns the last computed metric (i.e. from GetMetric). + int GetValueForEmptyInterval() const override; +}; + +// MaxCounter: maximum of samples +// +// | * * * | * * | ... +// | Add(5) Add(1) Add(6) | Add(5) Add(5) | +// GetMetric | max: (5, 1, 6) | max: (5, 5) | +// +class MaxCounter : public StatsCounter { + public: + MaxCounter(Clock* clock, + StatsCounterObserver* observer, + int64_t process_intervals_ms); + ~MaxCounter() override {} + + MaxCounter(const MaxCounter&) = delete; + MaxCounter& operator=(const MaxCounter&) = delete; + + void Add(int sample); + + private: + bool GetMetric(int* metric) const override; + int GetValueForEmptyInterval() const override; +}; + +// PercentCounter: percentage of samples +// +// | * * * | * * | ... +// | Add(T) Add(F) Add(T) | Add(F) Add(T) | +// GetMetric | 100 * 2 / 3 | 100 * 1 / 2 | +// +class PercentCounter : public StatsCounter { + public: + PercentCounter(Clock* clock, StatsCounterObserver* observer); + ~PercentCounter() override {} + + PercentCounter(const PercentCounter&) = delete; + PercentCounter& operator=(const PercentCounter&) = delete; + + void Add(bool sample); + + private: + bool GetMetric(int* metric) const override; + int GetValueForEmptyInterval() const override; +}; + +// PermilleCounter: permille of samples +// +// | * * * | * * | ... +// | Add(T) Add(F) Add(T) | Add(F) Add(T) | +// GetMetric | 1000 * 2 / 3 | 1000 * 1 / 2 | +// +class PermilleCounter : public StatsCounter { + public: + PermilleCounter(Clock* clock, StatsCounterObserver* observer); + ~PermilleCounter() override {} + + PermilleCounter(const PermilleCounter&) = delete; + PermilleCounter& operator=(const PermilleCounter&) = delete; + + void Add(bool sample); + + private: + bool GetMetric(int* metric) const override; + int GetValueForEmptyInterval() const override; +}; + +// RateCounter: units per second +// +// | * * * | * * | ... +// | Add(5) Add(1) Add(6) | Add(5) Add(5) | +// |<------ 2 sec ------->| | +// GetMetric | (5 + 1 + 6) / 2 | (5 + 5) / 2 | +// +// `include_empty_intervals`: If set, intervals without samples will be included +// in the stats. The value for an interval is +// determined by GetValueForEmptyInterval(). +// +class RateCounter : public StatsCounter { + public: + RateCounter(Clock* clock, + StatsCounterObserver* observer, + bool include_empty_intervals); + ~RateCounter() override {} + + RateCounter(const RateCounter&) = delete; + RateCounter& operator=(const RateCounter&) = delete; + + void Add(int sample); + + private: + bool GetMetric(int* metric) const override; + int GetValueForEmptyInterval() const override; // Returns zero. +}; + +// RateAccCounter: units per second (used for counters) +// +// | * * * | * * | ... +// | Set(5) Set(6) Set(8) | Set(11) Set(13) | +// |<------ 2 sec ------->| | +// GetMetric | (8 - 0) / 2 | (13 - 8) / 2 | +// +// `include_empty_intervals`: If set, intervals without samples will be included +// in the stats. The value for an interval is +// determined by GetValueForEmptyInterval(). +// +class RateAccCounter : public StatsCounter { + public: + RateAccCounter(Clock* clock, + StatsCounterObserver* observer, + bool include_empty_intervals); + ~RateAccCounter() override {} + + RateAccCounter(const RateAccCounter&) = delete; + RateAccCounter& operator=(const RateAccCounter&) = delete; + + void Set(int64_t sample, uint32_t stream_id); + + // Sets the value for previous interval. + // To be used if a value other than zero is initially required. + void SetLast(int64_t sample, uint32_t stream_id); + + private: + bool GetMetric(int* metric) const override; + int GetValueForEmptyInterval() const override; // Returns zero. +}; + +} // namespace webrtc + +#endif // VIDEO_STATS_COUNTER_H_ |