Add field trial for limiting probes and delay based estimates to link
capacity.

Allow delay based estimate to increase up to 85% of the current NetworkStateEstimate
even if in ALR. The estimate may not increase higher than that.
WebRTC-Bwe-EstimateBoundedIncrease/ratio:0.85,ignore_acked:true

Bug: none
Change-Id: I6f34af7fab03082ca168e624ddea06f216790fbc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/252442
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36096}
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.cc b/modules/remote_bitrate_estimator/aimd_rate_control.cc
index a3da2b5..bf1d431 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control.cc
+++ b/modules/remote_bitrate_estimator/aimd_rate_control.cc
@@ -95,11 +95,12 @@
       estimate_bounded_backoff_(
           IsNotDisabled(*key_value_config,
                         "WebRTC-Bwe-EstimateBoundedBackoff")),
-      estimate_bounded_increase_(
-          IsNotDisabled(*key_value_config,
-                        "WebRTC-Bwe-EstimateBoundedIncrease")),
       initial_backoff_interval_("initial_backoff_interval"),
       link_capacity_fix_("link_capacity_fix") {
+  ParseFieldTrial(
+      {&disable_estimate_bounded_increase_, &estimate_bounded_increase_ratio_,
+       &ignore_throughput_limit_if_network_estimate_},
+      key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease"));
   // E.g
   // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/
   ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_},
@@ -272,27 +273,34 @@
 
   ChangeState(input, at_time);
 
-  // We limit the new bitrate based on the troughput to avoid unlimited bitrate
-  // increases. We allow a bit more lag at very low rates to not too easily get
-  // stuck if the encoder produces uneven outputs.
-  const DataRate troughput_based_limit =
-      1.5 * estimated_throughput + DataRate::KilobitsPerSec(10);
-
   switch (rate_control_state_) {
     case RateControlState::kRcHold:
       break;
 
-    case RateControlState::kRcIncrease:
+    case RateControlState::kRcIncrease: {
       if (estimated_throughput > link_capacity_.UpperBound())
         link_capacity_.Reset();
 
-      // Do not increase the delay based estimate in alr since the estimator
-      // will not be able to get transport feedback necessary to detect if
-      // the new estimate is correct.
-      // If we have previously increased above the limit (for instance due to
-      // probing), we don't allow further changes.
-      if (current_bitrate_ < troughput_based_limit &&
-          !(send_side_ && in_alr_ && no_bitrate_increase_in_alr_)) {
+      // We limit the new bitrate based on the troughput to avoid unlimited
+      // bitrate increases. We allow a bit more lag at very low rates to not too
+      // easily get stuck if the encoder produces uneven outputs.
+      DataRate increase_limit =
+          1.5 * estimated_throughput + DataRate::KilobitsPerSec(10);
+      if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ &&
+          network_estimate_->link_capacity_upper.IsFinite()) {
+        // If we have a Network estimate, we do allow the estimate to increase.
+        increase_limit = network_estimate_->link_capacity_upper *
+                         estimate_bounded_increase_ratio_.Get();
+      } else if (send_side_ && in_alr_ && no_bitrate_increase_in_alr_) {
+        // Do not increase the delay based estimate in alr since the estimator
+        // will not be able to get transport feedback necessary to detect if
+        // the new estimate is correct.
+        // If we have previously increased above the limit (for instance due to
+        // probing), we don't allow further changes.
+        increase_limit = current_bitrate_;
+      }
+
+      if (current_bitrate_ < increase_limit) {
         DataRate increased_bitrate = DataRate::MinusInfinity();
         if (link_capacity_.has_estimate()) {
           // The link_capacity estimate is reset if the measured throughput
@@ -309,11 +317,11 @@
               at_time, time_last_bitrate_change_, current_bitrate_);
           increased_bitrate = current_bitrate_ + multiplicative_increase;
         }
-        new_bitrate = std::min(increased_bitrate, troughput_based_limit);
+        new_bitrate = std::min(increased_bitrate, increase_limit);
       }
-
       time_last_bitrate_change_ = at_time;
       break;
+    }
 
     case RateControlState::kRcDecrease: {
       DataRate decreased_bitrate = DataRate::PlusInfinity();
@@ -368,8 +376,10 @@
 }
 
 DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const {
-  if (estimate_bounded_increase_ && network_estimate_) {
-    DataRate upper_bound = network_estimate_->link_capacity_upper;
+  if (!disable_estimate_bounded_increase_ && network_estimate_ &&
+      network_estimate_->link_capacity_upper.IsFinite()) {
+    DataRate upper_bound = network_estimate_->link_capacity_upper *
+                           estimate_bounded_increase_ratio_.Get();
     new_bitrate = std::min(new_bitrate, upper_bound);
   }
   new_bitrate = std::max(new_bitrate, min_configured_bitrate_);
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.h b/modules/remote_bitrate_estimator/aimd_rate_control.h
index 3e0d541..12dec32 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control.h
+++ b/modules/remote_bitrate_estimator/aimd_rate_control.h
@@ -107,9 +107,12 @@
   // Use estimated link capacity lower bound if it is higher than the
   // acknowledged rate when backing off due to overuse.
   const bool estimate_bounded_backoff_;
-  // Use estimated link capacity upper bound as upper limit for increasing
-  // bitrate over the acknowledged rate.
-  const bool estimate_bounded_increase_;
+  // If false, uses estimated link capacity upper bound *
+  // `estimate_bounded_increase_ratio_` as upper limit for the estimate.
+  FieldTrialFlag disable_estimate_bounded_increase_{"Disabled"};
+  FieldTrialParameter<double> estimate_bounded_increase_ratio_{"ratio", 1.0};
+  FieldTrialParameter<bool> ignore_throughput_limit_if_network_estimate_{
+      "ignore_acked", false};
   absl::optional<DataRate> last_decrease_;
   FieldTrialOptional<TimeDelta> initial_backoff_interval_;
   FieldTrialFlag link_capacity_fix_;
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
index 6cbccf6..34aafb4 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
+++ b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
@@ -274,4 +274,72 @@
             kInitialBitrateBps);
 }
 
+TEST(AimdRateControlTest, EstimateNotLimitedByNetworkEstimateIfDisabled) {
+  test::ScopedFieldTrials override_field_trials(
+      "WebRTC-Bwe-EstimateBoundedIncrease/Disabled/");
+  auto states = CreateAimdRateControlStates(/*send_side=*/true);
+  constexpr int kInitialBitrateBps = 123000;
+  SetEstimate(states, kInitialBitrateBps);
+  states.aimd_rate_control->SetInApplicationLimitedRegion(false);
+  NetworkStateEstimate network_estimate;
+  network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(150);
+  states.aimd_rate_control->SetNetworkStateEstimate(network_estimate);
+
+  for (int i = 0; i < 100; ++i) {
+    UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
+                      states.simulated_clock->TimeInMilliseconds());
+    states.simulated_clock->AdvanceTimeMilliseconds(100);
+  }
+  EXPECT_GT(states.aimd_rate_control->LatestEstimate(),
+            network_estimate.link_capacity_upper);
+}
+
+TEST(AimdRateControlTest, EstimateLimitedByNetworkEstimateInAlrIfSet) {
+  // Even if alr is detected, the delay based estimator is allowed to increase
+  // up to a percentage of upper link capacity.
+  test::ScopedFieldTrials override_field_trials(
+      "WebRTC-Bwe-EstimateBoundedIncrease/ratio:0.85,ignore_acked:true/"
+      "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/");
+  auto states = CreateAimdRateControlStates(/*send_side=*/true);
+  constexpr int kInitialBitrateBps = 123000;
+  SetEstimate(states, kInitialBitrateBps);
+  states.aimd_rate_control->SetInApplicationLimitedRegion(true);
+
+  NetworkStateEstimate network_estimate;
+  network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(200);
+  states.aimd_rate_control->SetNetworkStateEstimate(network_estimate);
+  for (int i = 0; i < 100; ++i) {
+    UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
+                      states.simulated_clock->TimeInMilliseconds());
+    states.simulated_clock->AdvanceTimeMilliseconds(100);
+  }
+  EXPECT_EQ(states.aimd_rate_control->LatestEstimate(),
+            network_estimate.link_capacity_upper * 0.85);
+}
+
+TEST(AimdRateControlTest, EstimateDoesNotIncreaseInAlrIfNetworkEstimateNotSet) {
+  // When alr is detected, the delay based estimator is not allowed to increase
+  // bwe since there will be no feedback from the network if the new estimate
+  // is correct.
+  test::ScopedFieldTrials override_field_trials(
+      "WebRTC-Bwe-EstimateBoundedIncrease/ratio:0.85,ignore_acked:true/"
+      "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/");
+  auto states = CreateAimdRateControlStates(/*send_side=*/true);
+  constexpr int kInitialBitrateBps = 123000;
+  SetEstimate(states, kInitialBitrateBps);
+  states.aimd_rate_control->SetInApplicationLimitedRegion(true);
+  UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps,
+                    states.simulated_clock->TimeInMilliseconds());
+  ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
+            kInitialBitrateBps);
+
+  for (int i = 0; i < 100; ++i) {
+    UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
+                      states.simulated_clock->TimeInMilliseconds());
+    states.simulated_clock->AdvanceTimeMilliseconds(100);
+  }
+  EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
+            kInitialBitrateBps);
+}
+
 }  // namespace webrtc