Improve adaptation to reordered packets in delay manager.

This is done by adding a reorder optimizer that estimates the probability of receiving reordered packets.

The optimal delay is decided by balancing the cost of increasing the delay against the probability of missing a reordered packet, resulting in a loss. This balance is decided using the `ms_per_loss_percent` parameter.

The usage and parameters can be controlled via field trial.

Bug: webrtc:10178
Change-Id: Ic484df0412af35610e74b3a6070f2bac7a926a63
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231541
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34954}
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 9f7eebd..97d1d2e 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -32,6 +32,16 @@
 constexpr int kMaxBaseMinimumDelayMs = 10000;
 constexpr int kStartDelayMs = 80;
 
+std::unique_ptr<ReorderOptimizer> MaybeCreateReorderOptimizer(
+    const DelayManager::Config& config) {
+  if (!config.use_reorder_optimizer) {
+    return nullptr;
+  }
+  return std::make_unique<ReorderOptimizer>(
+      (1 << 15) * config.reorder_forget_factor, config.ms_per_loss_percent,
+      config.start_forget_weight);
+}
+
 }  // namespace
 
 DelayManager::Config::Config() {
@@ -47,16 +57,22 @@
                    << " start_forget_weight=" << start_forget_weight.value_or(0)
                    << " resample_interval_ms="
                    << resample_interval_ms.value_or(0)
-                   << " max_history_ms=" << max_history_ms;
+                   << " max_history_ms=" << max_history_ms
+                   << " use_reorder_optimizer=" << use_reorder_optimizer
+                   << " reorder_forget_factor=" << reorder_forget_factor
+                   << " ms_per_loss_percent=" << ms_per_loss_percent;
 }
 
 std::unique_ptr<StructParametersParser> DelayManager::Config::Parser() {
-  return 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);
+  return 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,                //
+      "use_reorder_optimizer", &use_reorder_optimizer,  //
+      "reorder_forget_factor", &reorder_forget_factor,  //
+      "ms_per_loss_percent", &ms_per_loss_percent);
 }
 
 // TODO(jakobi): remove legacy field trial.
@@ -90,6 +106,7 @@
                           (1 << 15) * config.forget_factor,
                           config.start_forget_weight,
                           config.resample_interval_ms),
+      reorder_optimizer_(MaybeCreateReorderOptimizer(config)),
       relative_arrival_delay_tracker_(tick_timer, config.max_history_ms),
       base_minimum_delay_ms_(config.base_minimum_delay_ms),
       effective_minimum_delay_ms_(config.base_minimum_delay_ms),
@@ -115,9 +132,18 @@
     return absl::nullopt;
   }
 
-  underrun_optimizer_.Update(*relative_delay);
+  bool reordered =
+      relative_arrival_delay_tracker_.newest_timestamp() != timestamp;
+  if (!reorder_optimizer_ || !reordered) {
+    underrun_optimizer_.Update(*relative_delay);
+  }
   target_level_ms_ =
       underrun_optimizer_.GetOptimalDelayMs().value_or(kStartDelayMs);
+  if (reorder_optimizer_) {
+    reorder_optimizer_->Update(*relative_delay, reordered, target_level_ms_);
+    target_level_ms_ = std::max(
+        target_level_ms_, reorder_optimizer_->GetOptimalDelayMs().value_or(0));
+  }
   target_level_ms_ = std::max(target_level_ms_, effective_minimum_delay_ms_);
   if (maximum_delay_ms_ > 0) {
     target_level_ms_ = std::min(target_level_ms_, maximum_delay_ms_);
@@ -148,6 +174,9 @@
   underrun_optimizer_.Reset();
   relative_arrival_delay_tracker_.Reset();
   target_level_ms_ = kStartDelayMs;
+  if (reorder_optimizer_) {
+    reorder_optimizer_->Reset();
+  }
 }
 
 int DelayManager::TargetDelayMs() const {