Add field trial to not probe if estimates are larger that max needed.

This add field trial string "skip_if_est_larger_than_fraction_of_max"
Dont send a probe if min(estimate, network state estimate) is larger than this
fraction of the set max bitrate.



Bug: webrtc:14392
Change-Id: I7333f6ef45ab0c019f21b9e4c604352219e1d025
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/275940
Reviewed-by: Diep Bui <diepbp@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38123}
diff --git a/modules/congestion_controller/goog_cc/probe_controller.cc b/modules/congestion_controller/goog_cc/probe_controller.cc
index cd6334e..0dfb8a3 100644
--- a/modules/congestion_controller/goog_cc/probe_controller.cc
+++ b/modules/congestion_controller/goog_cc/probe_controller.cc
@@ -101,7 +101,10 @@
       min_probe_packets_sent("min_probe_packets_sent", 5),
       min_probe_duration("min_probe_duration", TimeDelta::Millis(15)),
       limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe",
-                                          false) {
+                                          false),
+      skip_if_estimate_larger_than_fraction_of_max(
+          "skip_if_est_larger_than_fraction_of_max",
+          0.0) {
   ParseFieldTrial(
       {&first_exponential_probe_scale, &second_exponential_probe_scale,
        &further_exponential_probe_scale, &further_probe_threshold,
@@ -111,7 +114,8 @@
        &network_state_estimate_fast_rampup_rate,
        &network_state_estimate_drop_down_rate, &network_state_probe_scale,
        &network_state_probe_duration, &min_probe_packets_sent,
-       &limit_probe_target_rate_to_loss_bwe},
+       &limit_probe_target_rate_to_loss_bwe,
+       &skip_if_estimate_larger_than_fraction_of_max},
       key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration"));
 
   // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration
@@ -450,10 +454,20 @@
     Timestamp now,
     std::vector<DataRate> bitrates_to_probe,
     bool probe_further) {
+  if (config_.skip_if_estimate_larger_than_fraction_of_max > 0) {
+    DataRate network_estimate = network_estimate_
+                                    ? network_estimate_->link_capacity_upper
+                                    : DataRate::PlusInfinity();
+    if (std::min(network_estimate, estimated_bitrate_) >
+        config_.skip_if_estimate_larger_than_fraction_of_max * max_bitrate_) {
+      return {};
+    }
+  }
+
   DataRate max_probe_bitrate = max_bitrate_;
   if (bwe_limited_due_to_packet_loss_ &&
       config_.limit_probe_target_rate_to_loss_bwe) {
-    max_probe_bitrate = estimated_bitrate_;
+    max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_);
   }
   if (config_.network_state_estimate_probing_interval->IsFinite() &&
       network_estimate_ &&
@@ -472,6 +486,7 @@
     max_probe_bitrate =
         std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2);
   }
+
   send_probe_on_next_process_interval_ = false;
 
   std::vector<ProbeClusterConfig> pending_probes;
diff --git a/modules/congestion_controller/goog_cc/probe_controller.h b/modules/congestion_controller/goog_cc/probe_controller.h
index c32f25e..e1ee08f 100644
--- a/modules/congestion_controller/goog_cc/probe_controller.h
+++ b/modules/congestion_controller/goog_cc/probe_controller.h
@@ -74,6 +74,9 @@
   // Max limit the target rate of a probe to current estimate if BWE is loss
   // limited.
   FieldTrialParameter<bool> limit_probe_target_rate_to_loss_bwe;
+  // Dont send a probe if min(estimate, network state estimate) is larger than
+  // this fraction of the set max bitrate.
+  FieldTrialParameter<double> skip_if_estimate_larger_than_fraction_of_max;
 };
 
 // This class controls initiation of probing to estimate initial channel
diff --git a/modules/congestion_controller/goog_cc/probe_controller_unittest.cc b/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
index bf2235a..06ec681 100644
--- a/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
+++ b/modules/congestion_controller/goog_cc/probe_controller_unittest.cc
@@ -833,5 +833,81 @@
   EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
 }
 
+TEST(ProbeControllerTest, SkipAlrProbeIfEstimateLargerThanMaxProbe) {
+  ProbeControllerFixture fixture(
+      "WebRTC-Bwe-ProbingConfiguration/"
+      "skip_if_est_larger_than_fraction_of_max:0.9/");
+  std::unique_ptr<ProbeController> probe_controller =
+      fixture.CreateController();
+  probe_controller->EnablePeriodicAlrProbing(true);
+  auto probes = probe_controller->SetBitrates(
+      kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
+  ASSERT_FALSE(probes.empty());
+
+  probes = probe_controller->SetEstimatedBitrate(
+      kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
+      fixture.CurrentTime());
+  EXPECT_TRUE(probes.empty());
+
+  probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
+  fixture.AdvanceTime(TimeDelta::Seconds(10));
+  probes = probe_controller->Process(fixture.CurrentTime());
+  EXPECT_TRUE(probes.empty());
+
+  // But if the max rate increase, A new probe is sent.
+  probe_controller->SetMaxBitrate(2 * kMaxBitrate);
+  probes = probe_controller->Process(fixture.CurrentTime());
+  EXPECT_FALSE(probes.empty());
+}
+
+TEST(ProbeControllerTest, SkipNetworkStateProbeIfEstimateLargerThanMaxProbe) {
+  ProbeControllerFixture fixture(
+      "WebRTC-Bwe-ProbingConfiguration/"
+      "network_state_interval:2s,skip_if_est_larger_than_fraction_of_max:0.9/");
+  std::unique_ptr<ProbeController> probe_controller =
+      fixture.CreateController();
+  auto probes = probe_controller->SetBitrates(
+      kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
+  ASSERT_FALSE(probes.empty());
+
+  probe_controller->SetNetworkStateEstimate(
+      {.link_capacity_upper = 2 * kMaxBitrate});
+  probes = probe_controller->SetEstimatedBitrate(
+      kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
+      fixture.CurrentTime());
+  EXPECT_TRUE(probes.empty());
+
+  fixture.AdvanceTime(TimeDelta::Seconds(10));
+  probes = probe_controller->Process(fixture.CurrentTime());
+  EXPECT_TRUE(probes.empty());
+}
+
+TEST(ProbeControllerTest, SendsProbeIfNetworkStateEstimateLowerThanMaxProbe) {
+  ProbeControllerFixture fixture(
+      "WebRTC-Bwe-ProbingConfiguration/"
+      "network_state_interval:2s,skip_if_est_larger_than_fraction_of_max:0.9,"
+      "network_state_drop_down_rate:0.5/");
+  std::unique_ptr<ProbeController> probe_controller =
+      fixture.CreateController();
+  auto probes = probe_controller->SetBitrates(
+      kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
+  ASSERT_FALSE(probes.empty());
+  probe_controller->SetNetworkStateEstimate(
+      {.link_capacity_upper = 2 * kMaxBitrate});
+  probes = probe_controller->SetEstimatedBitrate(
+      kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
+      fixture.CurrentTime());
+  EXPECT_TRUE(probes.empty());
+
+  // Need to wait at least one second before process can trigger a new probe.
+  fixture.AdvanceTime(TimeDelta::Millis(1100));
+
+  // Sends a probe immediately if NetworkState estimate decrease.
+  probe_controller->SetNetworkStateEstimate(
+      {.link_capacity_upper = kStartBitrate});
+  probes = probe_controller->Process(fixture.CurrentTime());
+  EXPECT_FALSE(probes.empty());
+}
+
 }  // namespace test
 }  // namespace webrtc