Separate base minimum delay and minimum delay.

On NetEq level latency corresponds to delay and two terms can be used interchangeably here.

In order to implement latency constraint we need to provide a range of possible values which should be constant. See getCapabilities() here:
https://www.w3.org/TR/mediacapture-streams/#dfn-applyconstraints-algorithm

Lowest possible value accepted value is constant and equals 0. But because |packet_len_ms_| and |maximum_delay_ms_| may be updated during live of DelayManager upper bound is not constant. Moreover, due to change in |packet_len_ms_| the |minimum_delay_ms_| which was valid when its was set may be considered invalid later on.

To circumvent that and provide constant range for capabilities we separate base minimum delay and minimum delay. ApplyConstraints algorithm will set base minimum delay. Base minimum delay will act as recommendation for lower bound of minimum delay and will be used to limit target delay. If user sets base minimum delay through ApplyConstraints which is bigger than currently
possible maximum (e.g. bigger than NetEq maximum buffer size in milliseconds) then base minimum delay will be clamped to currently possible maximum to match user's intentions as best as possible.

Note, that we keep original behavior when minimum_delay_ms_ (effective_minimum_delay_ms after this CL) in LimitTargetLevel method may be above upper bound due to changing packet audio length.

Bug: webrtc:10287
Change-Id: I06b8f5cd3fd1bc36800af0447f91f7c4dc21a766
Reviewed-on: https://webrtc-review.googlesource.com/c/121700
Commit-Queue: Ruslan Burakov <kuddai@google.com>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26666}
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index c97d535..2f397d5 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -22,6 +22,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace {
@@ -31,6 +32,8 @@
 constexpr int kMaxStreamingPeakPeriodMs = 600000;   // 10 minutes in ms.
 constexpr int kCumulativeSumDrift = 2;  // Drift term for cumulative sum
                                         // |iat_cumulative_sum_|.
+constexpr int kMinBaseMinimumDelayMs = 0;
+constexpr int kMaxBaseMinimumDelayMs = 10000;
 // Steady-state forgetting factor for |iat_vector_|, 0.9993 in Q15.
 constexpr int kIatFactor_ = 32745;
 constexpr int kMaxIat = 64;  // Max inter-arrival time to register.
@@ -64,7 +67,7 @@
 namespace webrtc {
 
 DelayManager::DelayManager(size_t max_packets_in_buffer,
-                           int base_min_target_delay_ms,
+                           int base_minimum_delay_ms,
                            bool enable_rtx_handling,
                            DelayPeakDetector* peak_detector,
                            const TickTimer* tick_timer)
@@ -73,14 +76,15 @@
       iat_vector_(kMaxIat + 1, 0),
       iat_factor_(0),
       tick_timer_(tick_timer),
-      base_min_target_delay_ms_(base_min_target_delay_ms),
+      base_minimum_delay_ms_(base_minimum_delay_ms),
+      effective_minimum_delay_ms_(base_minimum_delay_ms),
       base_target_level_(4),                   // In Q0 domain.
       target_level_(base_target_level_ << 8),  // In Q8 domain.
       packet_len_ms_(0),
       streaming_mode_(false),
       last_seq_no_(0),
       last_timestamp_(0),
-      minimum_delay_ms_(base_min_target_delay_ms_),
+      minimum_delay_ms_(base_minimum_delay_ms_),
       maximum_delay_ms_(target_level_),
       iat_cumulative_sum_(0),
       max_iat_cumulative_sum_(0),
@@ -91,7 +95,7 @@
       forced_limit_probability_(GetForcedLimitProbability()),
       enable_rtx_handling_(enable_rtx_handling) {
   assert(peak_detector);  // Should never be NULL.
-  RTC_DCHECK_GE(base_min_target_delay_ms_, 0);
+  RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
   RTC_DCHECK_LE(minimum_delay_ms_, maximum_delay_ms_);
 
   Reset();
@@ -283,12 +287,13 @@
 // |maximum_delay_ms_| in packets. Note that in practice, if no
 // |maximum_delay_ms_| is specified, this does not have any impact, since the
 // target level is far below the buffer capacity in all reasonable cases.
-// The lower limit is equivalent of |minimum_delay_ms_| in packets. We update
-// |least_required_level_| while the above limits are applied.
+// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
+// We update |least_required_level_| while the above limits are applied.
 // TODO(hlundin): Move this check to the buffer logistics class.
 void DelayManager::LimitTargetLevel() {
-  if (packet_len_ms_ > 0 && minimum_delay_ms_ > 0) {
-    int minimum_delay_packet_q8 = (minimum_delay_ms_ << 8) / packet_len_ms_;
+  if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
+    int minimum_delay_packet_q8 =
+        (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
     target_level_ = std::max(target_level_, minimum_delay_packet_q8);
   }
 
@@ -492,49 +497,51 @@
   return new_histogram;
 }
 
-bool DelayManager::IsValidMinimumDelay(int delay_ms) {
-  const int q75 =
-      rtc::dchecked_cast<int>(3 * max_packets_in_buffer_ * packet_len_ms_ / 4);
-  return delay_ms >= 0 &&
-         (maximum_delay_ms_ <= 0 || delay_ms <= maximum_delay_ms_) &&
-         (packet_len_ms_ <= 0 || delay_ms <= q75);
+bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
+  return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
+}
+
+bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
+  return kMinBaseMinimumDelayMs <= delay_ms &&
+         delay_ms <= kMaxBaseMinimumDelayMs;
 }
 
 bool DelayManager::SetMinimumDelay(int delay_ms) {
   if (!IsValidMinimumDelay(delay_ms)) {
     return false;
   }
-  // Ensure that minimum_delay_ms is no bigger than base_min_target_delay_ms_
-  minimum_delay_ms_ = std::max(delay_ms, base_min_target_delay_ms_);
+
+  minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
 bool DelayManager::SetMaximumDelay(int delay_ms) {
-  if (delay_ms == 0) {
-    // Zero input unsets the maximum delay.
-    maximum_delay_ms_ = 0;
-    return true;
-  } else if (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_) {
+  // If |delay_ms| is zero then it unsets the maximum delay and target level is
+  // unconstrained by maximum delay.
+  if (delay_ms != 0 &&
+      (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
     // Maximum delay shouldn't be less than minimum delay or less than a packet.
     return false;
   }
+
   maximum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
 bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
-  if (!IsValidMinimumDelay(delay_ms)) {
+  if (!IsValidBaseMinimumDelay(delay_ms)) {
     return false;
   }
 
-  base_min_target_delay_ms_ = delay_ms;
-  // Ensure that minimum_delay_ms is no bigger than base_min_target_delay_ms_
-  minimum_delay_ms_ = std::max(delay_ms, base_min_target_delay_ms_);
+  base_minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
 int DelayManager::GetBaseMinimumDelay() const {
-  return base_min_target_delay_ms_;
+  return base_minimum_delay_ms_;
 }
 
 int DelayManager::base_target_level() const {
@@ -550,4 +557,28 @@
 void DelayManager::set_last_pack_cng_or_dtmf(int value) {
   last_pack_cng_or_dtmf_ = value;
 }
+
+void DelayManager::UpdateEffectiveMinimumDelay() {
+  // Clamp |base_minimum_delay_ms_| into the range which can be effectively
+  // used.
+  const int base_minimum_delay_ms =
+      rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
+  effective_minimum_delay_ms_ =
+      std::max(minimum_delay_ms_, base_minimum_delay_ms);
+}
+
+int DelayManager::MinimumDelayUpperBound() const {
+  // Choose the lowest possible bound discarding 0 cases which mean the value
+  // is not set and unconstrained.
+  int q75 = MaxBufferTimeQ75();
+  q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
+  const int maximum_delay_ms =
+      maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
+  return std::min(maximum_delay_ms, q75);
+}
+
+int DelayManager::MaxBufferTimeQ75() const {
+  const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
+  return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
+}
 }  // namespace webrtc