Add delay manager config options.

Add a new field trial with more flexible parsing and new options:
- Resample packet delays to only update histogram with maximum observed
 delay every X ms.
- Setting the maximum history size (in ms) used for calculating the
 relative arrival delay.

Legacy field trial used for configuration is maintained.

Bug: webrtc:10333
Change-Id: I35b004f5d8209c85b33cb49def3816db51650946
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/192789
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32591}
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 6b10d33..33eeb96 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -22,6 +22,7 @@
 #include "modules/audio_coding/neteq/histogram.h"
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/experiments/struct_parameters_parser.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/numerics/safe_minmax.h"
@@ -32,29 +33,34 @@
 
 constexpr int kMinBaseMinimumDelayMs = 0;
 constexpr int kMaxBaseMinimumDelayMs = 10000;
-constexpr int kMaxHistoryMs = 2000;  // Oldest packet to include in history to
-                                     // calculate relative packet arrival delay.
 constexpr int kDelayBuckets = 100;
 constexpr int kBucketSizeMs = 20;
 constexpr int kStartDelayMs = 80;
 constexpr int kMaxNumReorderedPackets = 5;
 
-int PercentileToQuantile(double percentile) {
-  return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
-}
-
-struct DelayHistogramConfig {
-  int quantile = 1041529569;  // 0.97 in Q30.
-  int forget_factor = 32745;  // 0.9993 in Q15.
+struct DelayManagerConfig {
+  double quantile = 0.97;
+  double forget_factor = 0.9993;
   absl::optional<double> start_forget_weight = 2;
-};
+  absl::optional<int> resample_interval_ms;
+  int max_history_ms = 2000;
 
-// TODO(jakobi): Remove legacy field trial.
-DelayHistogramConfig GetDelayHistogramConfig() {
-  constexpr char kDelayHistogramFieldTrial[] =
-      "WebRTC-Audio-NetEqDelayHistogram";
-  DelayHistogramConfig config;
-  if (webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
+  std::unique_ptr<webrtc::StructParametersParser> Parser() {
+    return webrtc::StructParametersParser::Create(      //
+        "quantile", &quantile,                          //
+        "forget_factor", &forget_factor,                //
+        "start_forget_weight", &start_forget_weight,    //
+        "resample_interval_ms", &resample_interval_ms,  //
+        "max_history_ms", &max_history_ms);
+  }
+
+  // TODO(jakobi): remove legacy field trial.
+  void MaybeUpdateFromLegacyFieldTrial() {
+    constexpr char kDelayHistogramFieldTrial[] =
+        "WebRTC-Audio-NetEqDelayHistogram";
+    if (!webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
+      return;
+    }
     const auto field_trial_string =
         webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
     double percentile = -1.0;
@@ -64,27 +70,36 @@
                &forget_factor, &start_forget_weight) >= 2 &&
         percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
         forget_factor <= 1.0) {
-      config.quantile = PercentileToQuantile(percentile);
-      config.forget_factor = (1 << 15) * forget_factor;
-      config.start_forget_weight =
-          start_forget_weight >= 1 ? absl::make_optional(start_forget_weight)
-                                   : absl::nullopt;
+      this->quantile = percentile / 100;
+      this->forget_factor = forget_factor;
+      this->start_forget_weight = start_forget_weight >= 1
+                                      ? absl::make_optional(start_forget_weight)
+                                      : absl::nullopt;
     }
   }
-  RTC_LOG(LS_INFO) << "Delay histogram config:"
-                      " quantile="
-                   << config.quantile
-                   << " forget_factor=" << config.forget_factor
-                   << " start_forget_weight="
-                   << config.start_forget_weight.value_or(0);
-  return config;
-}
+
+  explicit DelayManagerConfig() {
+    Parser()->Parse(webrtc::field_trial::FindFullName(
+        "WebRTC-Audio-NetEqDelayManagerConfig"));
+    MaybeUpdateFromLegacyFieldTrial();
+    RTC_LOG(LS_INFO) << "Delay manager config:"
+                        " quantile="
+                     << quantile << " forget_factor=" << forget_factor
+                     << " start_forget_weight="
+                     << start_forget_weight.value_or(0)
+                     << " resample_interval_ms="
+                     << resample_interval_ms.value_or(0)
+                     << " max_history_ms=" << max_history_ms;
+  }
+};
 
 }  // namespace
 
 DelayManager::DelayManager(int max_packets_in_buffer,
                            int base_minimum_delay_ms,
                            int histogram_quantile,
+                           absl::optional<int> resample_interval_ms,
+                           int max_history_ms,
                            const TickTimer* tick_timer,
                            std::unique_ptr<Histogram> histogram)
     : first_packet_received_(false),
@@ -92,6 +107,8 @@
       histogram_(std::move(histogram)),
       histogram_quantile_(histogram_quantile),
       tick_timer_(tick_timer),
+      resample_interval_ms_(resample_interval_ms),
+      max_history_ms_(max_history_ms),
       base_minimum_delay_ms_(base_minimum_delay_ms),
       effective_minimum_delay_ms_(base_minimum_delay_ms),
       minimum_delay_ms_(0),
@@ -108,12 +125,15 @@
     int max_packets_in_buffer,
     int base_minimum_delay_ms,
     const TickTimer* tick_timer) {
-  auto config = GetDelayHistogramConfig();
+  DelayManagerConfig config;
+  int forget_factor_q15 = (1 << 15) * config.forget_factor;
+  int quantile_q30 = (1 << 30) * config.quantile;
   std::unique_ptr<Histogram> histogram = std::make_unique<Histogram>(
-      kDelayBuckets, config.forget_factor, config.start_forget_weight);
-  return std::make_unique<DelayManager>(max_packets_in_buffer,
-                                        base_minimum_delay_ms, config.quantile,
-                                        tick_timer, std::move(histogram));
+      kDelayBuckets, forget_factor_q15, config.start_forget_weight);
+  return std::make_unique<DelayManager>(
+      max_packets_in_buffer, base_minimum_delay_ms, quantile_q30,
+      config.resample_interval_ms, config.max_history_ms, tick_timer,
+      std::move(histogram));
 }
 
 DelayManager::~DelayManager() {}
@@ -132,6 +152,8 @@
     last_timestamp_ = timestamp;
     first_packet_received_ = true;
     num_reordered_packets_ = 0;
+    resample_stopwatch_ = tick_timer_->GetNewStopwatch();
+    max_delay_in_interval_ms_ = 0;
     return absl::nullopt;
   }
 
@@ -139,7 +161,7 @@
       1000 * static_cast<int32_t>(timestamp - last_timestamp_) / sample_rate_hz;
   const int iat_ms = packet_iat_stopwatch_->ElapsedMs();
   const int iat_delay_ms = iat_ms - expected_iat_ms;
-  absl::optional<int> relative_delay;
+  int relative_delay;
   bool reordered = !IsNewerTimestamp(timestamp, last_timestamp_);
   if (reordered) {
     relative_delay = std::max(iat_delay_ms, 0);
@@ -147,11 +169,28 @@
     UpdateDelayHistory(iat_delay_ms, timestamp, sample_rate_hz);
     relative_delay = CalculateRelativePacketArrivalDelay();
   }
-  const int index = relative_delay.value() / kBucketSizeMs;
-  if (index < histogram_->NumBuckets()) {
-    // Maximum delay to register is 2000 ms.
-    histogram_->Add(index);
+
+  absl::optional<int> histogram_update;
+  if (resample_interval_ms_) {
+    if (static_cast<int>(resample_stopwatch_->ElapsedMs()) >
+        *resample_interval_ms_) {
+      histogram_update = max_delay_in_interval_ms_;
+      resample_stopwatch_ = tick_timer_->GetNewStopwatch();
+      max_delay_in_interval_ms_ = 0;
+    }
+    max_delay_in_interval_ms_ =
+        std::max(max_delay_in_interval_ms_, relative_delay);
+  } else {
+    histogram_update = relative_delay;
   }
+  if (histogram_update) {
+    const int index = *histogram_update / kBucketSizeMs;
+    if (index < histogram_->NumBuckets()) {
+      // Maximum delay to register is 2000 ms.
+      histogram_->Add(index);
+    }
+  }
+
   // Calculate new |target_level_ms_| based on updated statistics.
   int bucket_index = histogram_->Quantile(histogram_quantile_);
   target_level_ms_ = (1 + bucket_index) * kBucketSizeMs;
@@ -191,7 +230,7 @@
   delay.timestamp = timestamp;
   delay_history_.push_back(delay);
   while (timestamp - delay_history_.front().timestamp >
-         static_cast<uint32_t>(kMaxHistoryMs * sample_rate_hz / 1000)) {
+         static_cast<uint32_t>(max_history_ms_ * sample_rate_hz / 1000)) {
     delay_history_.pop_front();
   }
 }
@@ -226,6 +265,8 @@
   packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   first_packet_received_ = false;
   num_reordered_packets_ = 0;
+  resample_stopwatch_ = tick_timer_->GetNewStopwatch();
+  max_delay_in_interval_ms_ = 0;
 }
 
 int DelayManager::TargetDelayMs() const {