diff --git a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc index 37a0d50946..df139f7bba 100644 --- a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc +++ b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc @@ -13,12 +13,90 @@ #include #include // memset +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/neteq/decision_logic.h" #include "webrtc/modules/audio_coding/neteq/delay_manager.h" #include "webrtc/system_wrappers/interface/metrics.h" namespace webrtc { +StatisticsCalculator::PeriodicUmaLogger::PeriodicUmaLogger( + const std::string& uma_name, + int report_interval_ms, + int max_value) + : uma_name_(uma_name), + report_interval_ms_(report_interval_ms), + max_value_(max_value), + timer_(0) { +} + +StatisticsCalculator::PeriodicUmaLogger::~PeriodicUmaLogger() = default; + +void StatisticsCalculator::PeriodicUmaLogger::AdvanceClock(int step_ms) { + timer_ += step_ms; + if (timer_ < report_interval_ms_) { + return; + } + LogToUma(Metric()); + Reset(); + timer_ -= report_interval_ms_; + DCHECK_GE(timer_, 0); +} + +void StatisticsCalculator::PeriodicUmaLogger::LogToUma(int value) const { + RTC_HISTOGRAM_COUNTS(uma_name_, value, 1, max_value_, 50); +} + +StatisticsCalculator::PeriodicUmaCount::PeriodicUmaCount( + const std::string& uma_name, + int report_interval_ms, + int max_value) + : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) { +} + +StatisticsCalculator::PeriodicUmaCount::~PeriodicUmaCount() { + // Log the count for the current (incomplete) interval. + LogToUma(Metric()); +} + +void StatisticsCalculator::PeriodicUmaCount::RegisterSample() { + ++counter_; +} + +int StatisticsCalculator::PeriodicUmaCount::Metric() const { + return counter_; +} + +void StatisticsCalculator::PeriodicUmaCount::Reset() { + counter_ = 0; +} + +StatisticsCalculator::PeriodicUmaAverage::PeriodicUmaAverage( + const std::string& uma_name, + int report_interval_ms, + int max_value) + : PeriodicUmaLogger(uma_name, report_interval_ms, max_value) { +} + +StatisticsCalculator::PeriodicUmaAverage::~PeriodicUmaAverage() { + // Log the average for the current (incomplete) interval. + LogToUma(Metric()); +} + +void StatisticsCalculator::PeriodicUmaAverage::RegisterSample(int value) { + sum_ += value; + ++counter_; +} + +int StatisticsCalculator::PeriodicUmaAverage::Metric() const { + return static_cast(sum_ / counter_); +} + +void StatisticsCalculator::PeriodicUmaAverage::Reset() { + sum_ = 0.0; + counter_ = 0; +} + StatisticsCalculator::StatisticsCalculator() : preemptive_samples_(0), accelerate_samples_(0), @@ -30,7 +108,14 @@ StatisticsCalculator::StatisticsCalculator() timestamps_since_last_report_(0), len_waiting_times_(0), next_waiting_time_index_(0), - secondary_decoded_samples_(0) { + secondary_decoded_samples_(0), + delayed_packet_outage_counter_( + "WebRTC.Audio.DelayedPacketOutageEventsPerMinute", + 60000, // 60 seconds report interval. + 100), + excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs", + 60000, // 60 seconds report interval. + 1000) { memset(waiting_times_, 0, kLenWaitingTimes * sizeof(waiting_times_[0])); } @@ -84,6 +169,9 @@ void StatisticsCalculator::LostSamples(int num_samples) { } void StatisticsCalculator::IncreaseCounter(int num_samples, int fs_hz) { + const int time_step_ms = rtc::CheckedDivExact(1000 * num_samples, fs_hz); + delayed_packet_outage_counter_.AdvanceClock(time_step_ms); + excess_buffer_delay_.AdvanceClock(time_step_ms); timestamps_since_last_report_ += static_cast(num_samples); if (timestamps_since_last_report_ > static_cast(fs_hz * kMaxReportPeriod)) { @@ -101,9 +189,11 @@ void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) { RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs", outage_duration_ms, 1 /* min */, 2000 /* max */, 100 /* bucket count */); + delayed_packet_outage_counter_.RegisterSample(); } void StatisticsCalculator::StoreWaitingTime(int waiting_time_ms) { + excess_buffer_delay_.RegisterSample(waiting_time_ms); assert(next_waiting_time_index_ < kLenWaitingTimes); waiting_times_[next_waiting_time_index_] = waiting_time_ms; next_waiting_time_index_++; diff --git a/webrtc/modules/audio_coding/neteq/statistics_calculator.h b/webrtc/modules/audio_coding/neteq/statistics_calculator.h index 513322f882..d743e5f578 100644 --- a/webrtc/modules/audio_coding/neteq/statistics_calculator.h +++ b/webrtc/modules/audio_coding/neteq/statistics_calculator.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_STATISTICS_CALCULATOR_H_ +#include #include #include "webrtc/base/constructormagic.h" @@ -64,7 +65,8 @@ class StatisticsCalculator { void LostSamples(int num_samples); // Increases the report interval counter with |num_samples| at a sample rate - // of |fs_hz|. + // of |fs_hz|. This is how the StatisticsCalculator gets notified that current + // time is increasing. void IncreaseCounter(int num_samples, int fs_hz); // Stores new packet waiting time in waiting time statistics. @@ -95,6 +97,58 @@ class StatisticsCalculator { static const int kMaxReportPeriod = 60; // Seconds before auto-reset. static const int kLenWaitingTimes = 100; + class PeriodicUmaLogger { + public: + PeriodicUmaLogger(const std::string& uma_name, + int report_interval_ms, + int max_value); + virtual ~PeriodicUmaLogger(); + void AdvanceClock(int step_ms); + + protected: + void LogToUma(int value) const; + virtual int Metric() const = 0; + virtual void Reset() = 0; + + const std::string uma_name_; + const int report_interval_ms_; + const int max_value_; + int timer_ = 0; + }; + + class PeriodicUmaCount final : public PeriodicUmaLogger { + public: + PeriodicUmaCount(const std::string& uma_name, + int report_interval_ms, + int max_value); + ~PeriodicUmaCount() override; + void RegisterSample(); + + protected: + int Metric() const override; + void Reset() override; + + private: + int counter_ = 0; + }; + + class PeriodicUmaAverage final : public PeriodicUmaLogger { + public: + PeriodicUmaAverage(const std::string& uma_name, + int report_interval_ms, + int max_value); + ~PeriodicUmaAverage() override; + void RegisterSample(int value); + + protected: + int Metric() const override; + void Reset() override; + + private: + double sum_ = 0.0; + int counter_ = 0; + }; + // Calculates numerator / denominator, and returns the value in Q14. static uint16_t CalculateQ14Ratio(uint32_t numerator, uint32_t denominator); @@ -110,6 +164,8 @@ class StatisticsCalculator { int len_waiting_times_; int next_waiting_time_index_; uint32_t secondary_decoded_samples_; + PeriodicUmaCount delayed_packet_outage_counter_; + PeriodicUmaAverage excess_buffer_delay_; DISALLOW_COPY_AND_ASSIGN(StatisticsCalculator); };