NetEq: Implement two UMA stats for delay adaptation.

This CL adds calculation and logging of average excess buffer delay
and number of delayed packet outage events per minute.

The first is the average of time spent in the packet buffer for all
packets. The average is calculated for intervals of one minute, and
the result is logged to the UMA stat
WebRTC.Audio.AverageExcessBufferDelayMs.

The second is a counter of delayed packet outage events that is
restarted every minute, and the result is logged to the UMA stat
WebRTC.Audio.DelayedPacketOutageEventsPerMinute. For a description of
delayed packet outages, see previous CL implementing a duration log
for these events.

BUG=webrtc:4915, chromium:488124
R=minyue@webrtc.org

Review URL: https://codereview.webrtc.org/1287333005 .

Cr-Commit-Position: refs/heads/master@{#9731}
diff --git a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc
index 37a0d50..df139f7 100644
--- a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc
@@ -13,12 +13,90 @@
 #include <assert.h>
 #include <string.h>  // 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<int>(sum_ / counter_);
+}
+
+void StatisticsCalculator::PeriodicUmaAverage::Reset() {
+  sum_ = 0.0;
+  counter_ = 0;
+}
+
 StatisticsCalculator::StatisticsCalculator()
     : preemptive_samples_(0),
       accelerate_samples_(0),
@@ -30,7 +108,14 @@
       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::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<uint32_t>(num_samples);
   if (timestamps_since_last_report_ >
       static_cast<uint32_t>(fs_hz * kMaxReportPeriod)) {
@@ -101,9 +189,11 @@
   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 513322f..d743e5f 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 <string>
 #include <vector>
 
 #include "webrtc/base/constructormagic.h"
@@ -64,7 +65,8 @@
   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 @@
   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 @@
   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);
 };