Revert "Make relative arrival delay mode default in NetEq delay manager."

This reverts commit 77c71d1488b1c821b2b3481f23a3264f1b1d37a5.

Reason for revert: breaking downstream projects

Original change's description:
> Make relative arrival delay mode default in NetEq delay manager.
> 
> Bug: webrtc:10333
> Change-Id: I9b1e0bec0b1813cf31259492f83eb2ca86a44d3f
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/150782
> Reviewed-by: Sebastian Jansson <srte@webrtc.org>
> Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
> Reviewed-by: Minyue Li <minyue@webrtc.org>
> Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#29075}

TBR=henrik.lundin@webrtc.org,srte@webrtc.org,minyue@webrtc.org,jakobi@webrtc.org

Change-Id: I67c5b9c7a6e854d3aac379aa4d98bfeb5425d312
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:10333
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/151642
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29078}
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index 31c561f..b0dd90c 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -933,35 +933,35 @@
 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
     defined(WEBRTC_CODEC_ILBC)
 TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
-  Run(8000, PlatformChecksum("6c204b289486b0695b08a9e94fab1948",
-                             "ff5ffee2ee92f8fe61d9f2010b8a68a3",
-                             "53494a96f3db4a5b07d723e0cbac0ad7",
+  Run(8000, PlatformChecksum("73e82368b90b0708bd970da1f357f71d",
+                             "e777abcc66fccf8e86ac18450ad8b23c",
+                             "5a668d4075a39cd07a2db82ec3bf19ba",
                              "4598140b5e4f7ee66c5adad609e65a3e",
-                             "516c2859126ea4913f30d51af4a4f3dc"));
+                             "99d17cc50d41232a4f96c976231cb59b"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
-  Run(16000, PlatformChecksum("226dbdbce2354399c6df05371042cda3",
-                              "9c80bf5ec496c41ce8112e1523bf8c83",
-                              "11a6f170fdaffa81a2948af121f370af",
+  Run(16000, PlatformChecksum("f0b9d6961c243a3397b0bb95191b189b",
+                              "c73877b73a7ae2687eabc88de3d3f5bc",
+                              "70d24360be8290abbd0e56c38f83cdef",
                               "f2aad418af974a3b1694d5ae5cc2c3c7",
-                              "6133301a18be95c416984182816d859f"));
+                              "564b1b5d2d9bcace5285623cd9822b57"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
-  Run(32000, PlatformChecksum("f94665cc0e904d5d5cf0394e30ee4edd",
-                              "697934bcf0849f80d76ce20854161220",
-                              "3609aa5288c1d512e8e652ceabecb495",
+  Run(32000, PlatformChecksum("881a799ad91f845b1cd833e4e42d1791",
+                              "90e478af57f11bcf678b72ed1ba87765",
+                              "774657761e20fdec6d325d7d4b4101a7",
                               "100869c8dcde51346c2073e52a272d98",
-                              "55363bc9cdda6464a58044919157827b"));
+                              "4b77795ba2581097dc8e4db6e6a3a921"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
-  Run(48000, PlatformChecksum("2955d0b83602541fd92d9b820ebce68d",
-                              "f4a8386a6a49439ced60ed9a7c7f75fd",
-                              "d8169dfeba708b5212bdc365e08aee9d",
+  Run(48000, PlatformChecksum("991b729aef7f08eca75d4c9ece848264",
+                              "0334f53d4e96156edc302e46ff5cfaec",
+                              "a578705020fe94ebde31b27d61035299",
                               "bd44bf97e7899186532f91235cef444d",
-                              "47594deaab5d9166cfbf577203b2563e"));
+                              "c0d4185eacde6cd470c1a2ce4cd45318"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
@@ -1044,11 +1044,11 @@
   rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
       new rtc::RefCountedObject<ADFactory>);
   Run(48000,
-      PlatformChecksum("2955d0b83602541fd92d9b820ebce68d",
-                       "f4a8386a6a49439ced60ed9a7c7f75fd",
-                       "d8169dfeba708b5212bdc365e08aee9d",
+      PlatformChecksum("991b729aef7f08eca75d4c9ece848264",
+                       "0334f53d4e96156edc302e46ff5cfaec",
+                       "a578705020fe94ebde31b27d61035299",
                        "bd44bf97e7899186532f91235cef444d",
-                       "47594deaab5d9166cfbf577203b2563e"),
+                       "c0d4185eacde6cd470c1a2ce4cd45318"),
       factory, [](AudioCodingModule* acm) {
         acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
                                {103, {"ISAC", 16000, 1}},
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 70991f3..5d6dc00 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -31,8 +31,11 @@
 
 namespace {
 
+constexpr int kLimitProbability = 1020054733;  // 19/20 in Q30.
 constexpr int kMinBaseMinimumDelayMs = 0;
 constexpr int kMaxBaseMinimumDelayMs = 10000;
+constexpr int kIatFactor = 32745;  // 0.9993 in Q15.
+constexpr int kMaxIat = 64;        // Max inter-arrival time to register.
 constexpr int kMaxReorderedPackets =
     10;  // Max number of consecutive reordered packets.
 constexpr int kMaxHistoryMs = 2000;  // Oldest packet to include in history to
@@ -44,19 +47,43 @@
   return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
 }
 
+absl::optional<int> GetForcedLimitProbability() {
+  constexpr char kForceTargetDelayPercentileFieldTrial[] =
+      "WebRTC-Audio-NetEqForceTargetDelayPercentile";
+  const bool use_forced_target_delay_percentile =
+      webrtc::field_trial::IsEnabled(kForceTargetDelayPercentileFieldTrial);
+  if (use_forced_target_delay_percentile) {
+    const std::string field_trial_string = webrtc::field_trial::FindFullName(
+        kForceTargetDelayPercentileFieldTrial);
+    double percentile = -1.0;
+    if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 &&
+        percentile >= 0.0 && percentile <= 100.0) {
+      return absl::make_optional<int>(
+          PercentileToQuantile(percentile));  // in Q30.
+    } else {
+      RTC_LOG(LS_WARNING) << "Invalid parameter for "
+                          << kForceTargetDelayPercentileFieldTrial
+                          << ", ignored.";
+    }
+  }
+  return absl::nullopt;
+}
+
 struct DelayHistogramConfig {
-  int quantile = 1041529569;  // 0.97 in Q30.
+  int quantile = 1020054733;  // 0.95 in Q30.
   int forget_factor = 32745;  // 0.9993 in Q15.
-  absl::optional<double> start_forget_weight = 2;
+  absl::optional<double> start_forget_weight;
 };
 
-DelayHistogramConfig GetDelayHistogramConfig() {
+absl::optional<DelayHistogramConfig> GetDelayHistogramConfig() {
   constexpr char kDelayHistogramFieldTrial[] =
       "WebRTC-Audio-NetEqDelayHistogram";
-  DelayHistogramConfig config;
-  if (webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial)) {
+  const bool use_new_delay_manager =
+      webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial);
+  if (use_new_delay_manager) {
     const auto field_trial_string =
         webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
+    DelayHistogramConfig config;
     double percentile = -1.0;
     double forget_factor = -1.0;
     double start_forget_weight = -1.0;
@@ -66,17 +93,18 @@
         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;
+      if (start_forget_weight >= 1) {
+        config.start_forget_weight = start_forget_weight;
+      }
     }
+    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 absl::make_optional(config);
   }
-  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;
+  return absl::nullopt;
 }
 
 absl::optional<int> GetDecelerationTargetLevelOffsetMs() {
@@ -172,11 +200,21 @@
     DelayPeakDetector* peak_detector,
     const TickTimer* tick_timer,
     StatisticsCalculator* statistics) {
-  const HistogramMode mode = RELATIVE_ARRIVAL_DELAY;
-  DelayHistogramConfig config = GetDelayHistogramConfig();
-  const int quantile = config.quantile;
-  std::unique_ptr<Histogram> histogram = absl::make_unique<Histogram>(
-      kDelayBuckets, config.forget_factor, config.start_forget_weight);
+  int quantile;
+  std::unique_ptr<Histogram> histogram;
+  HistogramMode mode;
+  auto delay_histogram_config = GetDelayHistogramConfig();
+  if (delay_histogram_config) {
+    DelayHistogramConfig config = delay_histogram_config.value();
+    quantile = config.quantile;
+    histogram = absl::make_unique<Histogram>(
+        kDelayBuckets, config.forget_factor, config.start_forget_weight);
+    mode = RELATIVE_ARRIVAL_DELAY;
+  } else {
+    quantile = GetForcedLimitProbability().value_or(kLimitProbability);
+    histogram = absl::make_unique<Histogram>(kMaxIat + 1, kIatFactor);
+    mode = INTER_ARRIVAL_TIME;
+  }
   return absl::make_unique<DelayManager>(
       max_packets_in_buffer, base_minimum_delay_ms, quantile, mode,
       enable_rtx_handling, peak_detector, tick_timer, statistics,
diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc
index beb61b0..ab316e2 100644
--- a/modules/audio_coding/neteq/delay_manager_unittest.cc
+++ b/modules/audio_coding/neteq/delay_manager_unittest.cc
@@ -62,7 +62,7 @@
   bool enable_rtx_handling_ = false;
   bool use_mock_histogram_ = false;
   DelayManager::HistogramMode histogram_mode_ =
-      DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
+      DelayManager::HistogramMode::INTER_ARRIVAL_TIME;
 };
 
 DelayManagerTest::DelayManagerTest()
@@ -143,6 +143,10 @@
   // Advance time by one frame size.
   IncreaseTime(kFrameSizeMs);
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return false to indicate no peaks found.
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(1, dm_->base_target_level());
@@ -162,6 +166,10 @@
   // Advance time by two frame size.
   IncreaseTime(2 * kFrameSizeMs);
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return false to indicate no peaks found.
+  EXPECT_CALL(detector_, Update(2, false, 2)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(2 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(2, dm_->base_target_level());
@@ -174,6 +182,51 @@
   EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher);
 }
 
+TEST_F(DelayManagerTest, UpdatePeakFound) {
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Advance time by one frame size.
+  IncreaseTime(kFrameSizeMs);
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return true to indicate that peaks are found. Let the peak height be 5.
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight()).WillOnce(Return(5));
+  InsertNextPacket();
+  EXPECT_EQ(5 << 8, dm_->TargetLevel());
+  EXPECT_EQ(1, dm_->base_target_level());  // Base target level is w/o peaks.
+  int lower, higher;
+  dm_->BufferLimits(&lower, &higher);
+  // Expect |lower| to be 75% of target level, and |higher| to be target level.
+  EXPECT_EQ((5 << 8) * 3 / 4, lower);
+  EXPECT_EQ(5 << 8, higher);
+}
+
+TEST_F(DelayManagerTest, TargetDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Advance time by one frame size.
+  IncreaseTime(kFrameSizeMs);
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return false to indicate no peaks found.
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
+  InsertNextPacket();
+  const int kExpectedTarget = 1;
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
+  EXPECT_EQ(1, dm_->base_target_level());
+  int lower, higher;
+  dm_->BufferLimits(&lower, &higher);
+  // Expect |lower| to be 75% of base target level, and |higher| to be
+  // lower + 20 ms headroom.
+  EXPECT_EQ((1 << 8) * 3 / 4, lower);
+  EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher);
+}
+
 TEST_F(DelayManagerTest, MaxDelay) {
   const int kExpectedTarget = 5;
   const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
@@ -181,6 +234,12 @@
   // First packet arrival.
   InsertNextPacket();
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
 
@@ -205,6 +264,12 @@
   // First packet arrival.
   InsertNextPacket();
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
 
@@ -214,7 +279,7 @@
   int kMinDelayPackets = kExpectedTarget + 2;
   int kMinDelayMs = kMinDelayPackets * kFrameSizeMs;
   dm_->SetMinimumDelay(kMinDelayMs);
-  IncreaseTime(kFrameSizeMs);
+  IncreaseTime(kTimeIncrement);
   InsertNextPacket();
   EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
 }
@@ -354,6 +419,12 @@
   // First packet arrival.
   InsertNextPacket();
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
 
@@ -365,7 +436,7 @@
   EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
   EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
 
-  IncreaseTime(kFrameSizeMs);
+  IncreaseTime(kTimeIncrement);
   InsertNextPacket();
   EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
   EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
@@ -378,6 +449,12 @@
   // First packet arrival.
   InsertNextPacket();
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget|. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
 
@@ -397,12 +474,21 @@
   EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
   EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
 
-  IncreaseTime(kFrameSizeMs);
+  IncreaseTime(kTimeIncrement);
   InsertNextPacket();
   EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
   EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
 }
 
+TEST_F(DelayManagerTest, UpdateReorderedPacket) {
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
+
+  // Insert packet that was sent before the previous packet.
+  EXPECT_CALL(detector_, Update(_, true, _));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 1, ts_ - kFrameSizeMs, kFs));
+}
+
 TEST_F(DelayManagerTest, EnableRtxHandling) {
   enable_rtx_handling_ = true;
   use_mock_histogram_ = true;
@@ -414,23 +500,22 @@
   InsertNextPacket();
 
   // Insert reordered packet.
-  EXPECT_CALL(*mock_histogram_, Add(2));
+  EXPECT_CALL(*mock_histogram_, Add(3));
   EXPECT_EQ(0, dm_->Update(seq_no_ - 3, ts_ - 3 * kFrameSizeMs, kFs));
 
   // Insert another reordered packet.
-  EXPECT_CALL(*mock_histogram_, Add(1));
+  EXPECT_CALL(*mock_histogram_, Add(2));
   EXPECT_EQ(0, dm_->Update(seq_no_ - 2, ts_ - 2 * kFrameSizeMs, kFs));
 
   // Insert the next packet in order and verify that the inter-arrival time is
   // estimated correctly.
   IncreaseTime(kFrameSizeMs);
-  EXPECT_CALL(*mock_histogram_, Add(0));
+  EXPECT_CALL(*mock_histogram_, Add(1));
   InsertNextPacket();
 }
 
 // Tests that skipped sequence numbers (simulating empty packets) are handled
 // correctly.
-// TODO(jakobi): Make delay manager independent of sequence numbers.
 TEST_F(DelayManagerTest, EmptyPacketsReported) {
   SetPacketAudioLength(kFrameSizeMs);
   // First packet arrival.
@@ -447,13 +532,17 @@
   }
 
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return false to indicate no peaks found.
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
 
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
 }
 
-// Same as above, but do not call RegisterEmptyPacket. Target level stays the
-// same.
+// Same as above, but do not call RegisterEmptyPacket. Observe the target level
+// increase dramatically.
 TEST_F(DelayManagerTest, EmptyPacketsNotReported) {
   SetPacketAudioLength(kFrameSizeMs);
   // First packet arrival.
@@ -462,14 +551,19 @@
   // Advance time by one frame size.
   IncreaseTime(kFrameSizeMs);
 
-  // Advance the sequence number by 10, simulating that 10 empty packets were
+  // Advance the sequence number by 5, simulating that 5 empty packets were
   // received, but never inserted.
   seq_no_ += 10;
 
   // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet, and (base) target level equal to 1 as well.
+  // Return false to indicate no peaks found.
+  EXPECT_CALL(detector_, Update(10, false, 10)).WillOnce(Return(false));
   InsertNextPacket();
 
-  EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
+  // Note 10 times higher target value.
+  EXPECT_EQ(10 * 1 << 8, dm_->TargetLevel());  // In Q8.
 }
 
 TEST_F(DelayManagerTest, Failures) {
@@ -489,6 +583,58 @@
   EXPECT_FALSE(dm_->SetMaximumDelay(60));
 }
 
+TEST_F(DelayManagerTest, TargetDelayGreaterThanOne) {
+  test::ScopedFieldTrials field_trial(
+      "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-0/");
+  RecreateDelayManager();
+  EXPECT_EQ(0, dm_->histogram_quantile());
+
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Advance time by one frame size.
+  IncreaseTime(kFrameSizeMs);
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to 1 packet.
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
+  InsertNextPacket();
+  constexpr int kExpectedTarget = 1;
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
+}
+
+TEST_F(DelayManagerTest, ForcedTargetDelayPercentile) {
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-95/");
+    RecreateDelayManager();
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/");
+    RecreateDelayManager();
+    EXPECT_EQ(1073204953, dm_->histogram_quantile());  // 0.9995 in Q30.
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Disabled/");
+    RecreateDelayManager();
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled--1/");
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-100.1/");
+    RecreateDelayManager();
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
+  }
+}
+
 TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
   {
     test::ScopedFieldTrials field_trial(
@@ -514,6 +660,49 @@
         dm_->histogram()->base_forget_factor_for_testing());  // 0.998 in Q15.
     EXPECT_FALSE(dm_->histogram()->start_forget_weight_for_testing());
   }
+  {
+    // NetEqDelayHistogram should take precedence over
+    // NetEqForceTargetDelayPercentile.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/"
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1030792151, dm_->histogram_quantile());  // 0.96 in Q30.
+    EXPECT_EQ(
+        32702,
+        dm_->histogram()->base_forget_factor_for_testing());  // 0.998 in Q15.
+    EXPECT_FALSE(dm_->histogram()->start_forget_weight_for_testing());
+  }
+  {
+    // Invalid parameters.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());  // 0.95 in Q30.
+    EXPECT_EQ(
+        kForgetFactor,
+        dm_->histogram()->base_forget_factor_for_testing());  // 0.9993 in Q15.
+    EXPECT_FALSE(dm_->histogram()->start_forget_weight_for_testing());
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Disabled/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());  // 0.95 in Q30.
+    EXPECT_EQ(
+        kForgetFactor,
+        dm_->histogram()->base_forget_factor_for_testing());  // 0.9993 in Q15.
+    EXPECT_FALSE(dm_->histogram()->start_forget_weight_for_testing());
+  }
+
   // Test parameter for new call start adaptation.
   {
     test::ScopedFieldTrials field_trial(
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index 769ec56..0db6fc7 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -456,16 +456,16 @@
       webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
 
   const std::string output_checksum =
-      PlatformChecksum("6ae9f643dc3e5f3452d28a772eef7e00e74158bc",
-                       "f4374430e870d66268c1b8e22fb700eb072d567e", "not used",
-                       "6ae9f643dc3e5f3452d28a772eef7e00e74158bc",
-                       "8d73c98645917cdeaaa01c20cf095ccc5a10b2b5");
+      PlatformChecksum("998be2e5a707e636af0b6298f54bedfabe72aae1",
+                       "61e238ece4cd3b67d66a0b7047e06b20607dcb79", "not used",
+                       "998be2e5a707e636af0b6298f54bedfabe72aae1",
+                       "4116ac2a6e75baac3194b712d6fabe28b384275e");
 
   const std::string network_stats_checksum =
-      PlatformChecksum("3d186ea7e243abfdbd3d39b8ebf8f02a318117e4",
-                       "0b725774133da5dd823f2046663c12a76e0dbd79", "not used",
-                       "3d186ea7e243abfdbd3d39b8ebf8f02a318117e4",
-                       "3d186ea7e243abfdbd3d39b8ebf8f02a318117e4");
+      PlatformChecksum("5e5230b2d5042eccd197dac29edade1cc233586c",
+                       "2183564f11b53259ba7f86f48f4df3d7d653c678", "not used",
+                       "5e5230b2d5042eccd197dac29edade1cc233586c",
+                       "5e5230b2d5042eccd197dac29edade1cc233586c");
 
   DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
                    absl::GetFlag(FLAGS_gen_ref));
@@ -733,7 +733,7 @@
   const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
   const double kNetworkFreezeTimeMs = 0.0;
   const bool kGetAudioDuringFreezeRecovery = false;
-  const int kDelayToleranceMs = 40;
+  const int kDelayToleranceMs = 20;
   const int kMaxTimeToSpeechMs = 100;
   LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
                         kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
@@ -757,7 +757,7 @@
   const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
   const double kNetworkFreezeTimeMs = 5000.0;
   const bool kGetAudioDuringFreezeRecovery = false;
-  const int kDelayToleranceMs = 40;
+  const int kDelayToleranceMs = 20;
   const int kMaxTimeToSpeechMs = 100;
   LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
                         kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
@@ -769,7 +769,7 @@
   const double kDriftFactor = 1000.0 / (1000.0 - 25.0);
   const double kNetworkFreezeTimeMs = 5000.0;
   const bool kGetAudioDuringFreezeRecovery = true;
-  const int kDelayToleranceMs = 40;
+  const int kDelayToleranceMs = 20;
   const int kMaxTimeToSpeechMs = 100;
   LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
                         kGetAudioDuringFreezeRecovery, kDelayToleranceMs,
diff --git a/modules/audio_coding/test/target_delay_unittest.cc b/modules/audio_coding/test/target_delay_unittest.cc
index 2b7aacd..77a2e5a 100644
--- a/modules/audio_coding/test/target_delay_unittest.cc
+++ b/modules/audio_coding/test/target_delay_unittest.cc
@@ -53,6 +53,20 @@
     EXPECT_EQ(-1, SetMinimumDelay(10001));
   }
 
+  void WithTargetDelayBufferNotChanging() {
+    // A target delay that is one packet larger than jitter.
+    const int kTargetDelayMs =
+        (kInterarrivalJitterPacket + 1) * kNum10msPerFrame * 10;
+    ASSERT_EQ(0, SetMinimumDelay(kTargetDelayMs));
+    for (int n = 0; n < 30; ++n)  // Run enough iterations to fill the buffer.
+      Run(true);
+    int clean_optimal_delay = GetCurrentOptimalDelayMs();
+    EXPECT_EQ(kTargetDelayMs, clean_optimal_delay);
+    Run(false);  // Run with jitter.
+    int jittery_optimal_delay = GetCurrentOptimalDelayMs();
+    EXPECT_EQ(jittery_optimal_delay, clean_optimal_delay);
+  }
+
   void TargetDelayBufferMinMax() {
     const int kTargetMinDelayMs = kNum10msPerFrame * 10;
     ASSERT_EQ(0, SetMinimumDelay(kTargetMinDelayMs));
@@ -150,6 +164,17 @@
 
 // Flaky on iOS: webrtc:7057.
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
+#define MAYBE_WithTargetDelayBufferNotChanging \
+  DISABLED_WithTargetDelayBufferNotChanging
+#else
+#define MAYBE_WithTargetDelayBufferNotChanging WithTargetDelayBufferNotChanging
+#endif
+TEST_F(TargetDelayTest, MAYBE_WithTargetDelayBufferNotChanging) {
+  WithTargetDelayBufferNotChanging();
+}
+
+// Flaky on iOS: webrtc:7057.
+#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
 #define MAYBE_TargetDelayBufferMinMax DISABLED_TargetDelayBufferMinMax
 #else
 #define MAYBE_TargetDelayBufferMinMax TargetDelayBufferMinMax