diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.h b/modules/congestion_controller/goog_cc/delay_based_bwe.h index 21dff35735..e91a1dff54 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -82,6 +82,7 @@ class DelayBasedBwe { DataRate TriggerOveruse(Timestamp at_time, absl::optional link_capacity); DataRate last_estimate() const { return prev_bitrate_; } + BandwidthUsage last_state() const { return prev_state_; } private: friend class GoogCcStatePrinter; diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index be7027f88a..3a9de8c4dc 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -22,6 +22,7 @@ #include #include "absl/strings/match.h" +#include "api/network_state_predictor.h" #include "api/units/data_rate.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" @@ -62,7 +63,14 @@ bool IsNotDisabled(const FieldTrialsView* config, absl::string_view key) { } BandwidthLimitedCause GetBandwidthLimitedCause( - LossBasedState loss_based_state) { + LossBasedState loss_based_state, + BandwidthUsage bandwidth_usage, + bool not_probe_if_delay_increased) { + if (not_probe_if_delay_increased && + (bandwidth_usage == BandwidthUsage::kBwOverusing || + bandwidth_usage == BandwidthUsage::kBwUnderusing)) { + return BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased; + } switch (loss_based_state) { case LossBasedState::kDecreasing: return BandwidthLimitedCause::kLossLimitedBweDecreasing; @@ -676,7 +684,10 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( auto probes = probe_controller_->SetEstimatedBitrate( loss_based_target_rate, - GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()), + GetBandwidthLimitedCause( + bandwidth_estimation_->loss_based_state(), + delay_based_bwe_->last_state(), + probe_controller_->DontProbeIfDelayIncreased()), at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); diff --git a/modules/congestion_controller/goog_cc/probe_controller.cc b/modules/congestion_controller/goog_cc/probe_controller.cc index 00e1b59a55..fcbcbc13b4 100644 --- a/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/modules/congestion_controller/goog_cc/probe_controller.cc @@ -109,7 +109,8 @@ ProbeControllerConfig::ProbeControllerConfig( loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", - 0.0) { + 0.0), + not_probe_if_delay_increased("not_probe_if_delay_increased", false) { ParseFieldTrial({&first_exponential_probe_scale, &second_exponential_probe_scale, &further_exponential_probe_scale, @@ -129,7 +130,8 @@ ProbeControllerConfig::ProbeControllerConfig( &min_probe_packets_sent, &limit_probe_target_rate_to_loss_bwe, &loss_limited_probe_scale, - &skip_if_estimate_larger_than_fraction_of_max}, + &skip_if_estimate_larger_than_fraction_of_max, + ¬_probe_if_delay_increased}, key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration @@ -512,8 +514,16 @@ std::vector ProbeController::InitiateProbing( break; case BandwidthLimitedCause::kDelayBasedLimited: break; + default: + break; } } + if (config_.not_probe_if_delay_increased && + bandwidth_limited_cause_ == + BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased) { + return {}; + } + if (config_.network_state_estimate_probing_interval->IsFinite() && network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { if (network_estimate_->link_capacity_upper.IsZero()) { diff --git a/modules/congestion_controller/goog_cc/probe_controller.h b/modules/congestion_controller/goog_cc/probe_controller.h index 9680d61a97..2d22f84d08 100644 --- a/modules/congestion_controller/goog_cc/probe_controller.h +++ b/modules/congestion_controller/goog_cc/probe_controller.h @@ -78,6 +78,8 @@ struct ProbeControllerConfig { // Dont send a probe if min(estimate, network state estimate) is larger than // this fraction of the set max bitrate. FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; + // Do not send probes if network is either overusing or underusing. + FieldTrialParameter not_probe_if_delay_increased; }; // Reason that bandwidth estimate is limited. Bandwidth estimate can be limited @@ -86,7 +88,8 @@ struct ProbeControllerConfig { enum class BandwidthLimitedCause { kLossLimitedBweIncreasing = 0, kLossLimitedBweDecreasing = 1, - kDelayBasedLimited = 2 + kDelayBasedLimited = 2, + kDelayBasedLimitedDelayIncreased = 3, }; // This class controls initiation of probing to estimate initial channel @@ -138,6 +141,11 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector Process( Timestamp at_time); + // Gets the value of field trial not_probe_if_delay_increased. + bool DontProbeIfDelayIncreased() { + return config_.not_probe_if_delay_increased; + } + private: enum class State { // Initial state where no probing has been triggered yet. diff --git a/modules/congestion_controller/goog_cc/probe_controller_unittest.cc b/modules/congestion_controller/goog_cc/probe_controller_unittest.cc index 5d971e98b1..e6a5c8ceef 100644 --- a/modules/congestion_controller/goog_cc/probe_controller_unittest.cc +++ b/modules/congestion_controller/goog_cc/probe_controller_unittest.cc @@ -1098,5 +1098,34 @@ TEST(ProbeControllerTest, DontSendProbeIfNetworkStateEstimateIsZero) { probes = probe_controller->Process(fixture.CurrentTime()); EXPECT_TRUE(probes.empty()); } + +TEST(ProbeControllerTest, DontProbeIfDelayIncreased) { + ProbeControllerFixture fixture( + "WebRTC-Bwe-ProbingConfiguration/" + "network_state_interval:5s,not_probe_if_delay_increased:true/"); + std::unique_ptr probe_controller = + fixture.CreateController(); + + auto probes = probe_controller->SetBitrates( + kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime()); + ASSERT_FALSE(probes.empty()); + + // Need to wait at least one second before process can trigger a new probe. + fixture.AdvanceTime(TimeDelta::Millis(1100)); + probes = probe_controller->Process(fixture.CurrentTime()); + ASSERT_TRUE(probes.empty()); + + NetworkStateEstimate state_estimate; + state_estimate.link_capacity_upper = 3 * kStartBitrate; + probe_controller->SetNetworkStateEstimate(state_estimate); + probes = probe_controller->SetEstimatedBitrate( + kStartBitrate, BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased, + fixture.CurrentTime()); + ASSERT_TRUE(probes.empty()); + + fixture.AdvanceTime(TimeDelta::Seconds(5)); + probes = probe_controller->Process(fixture.CurrentTime()); + EXPECT_TRUE(probes.empty()); +} } // namespace test } // namespace webrtc