diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn index 923f00a74c..fd52b2dcb9 100644 --- a/modules/remote_bitrate_estimator/BUILD.gn +++ b/modules/remote_bitrate_estimator/BUILD.gn @@ -122,6 +122,7 @@ if (rtc_include_tests) { "../../api/transport:field_trial_based_config", "../../api/transport:mock_network_control", "../../api/transport:network_control", + "../../api/units:data_rate", "../../rtc_base", "../../rtc_base:checks", "../../rtc_base:rtc_base_approved", diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.cc b/modules/remote_bitrate_estimator/aimd_rate_control.cc index bf1d431879..1714dd115a 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -99,7 +99,8 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, link_capacity_fix_("link_capacity_fix") { ParseFieldTrial( {&disable_estimate_bounded_increase_, &estimate_bounded_increase_ratio_, - &ignore_throughput_limit_if_network_estimate_}, + &ignore_throughput_limit_if_network_estimate_, + &ignore_network_estimate_decrease_}, key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease")); // E.g // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/ @@ -380,7 +381,10 @@ DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const { 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); + if (ignore_network_estimate_decrease_) { + upper_bound = std::max(upper_bound, current_bitrate_); + } + new_bitrate = std::min(upper_bound, new_bitrate); } new_bitrate = std::max(new_bitrate, min_configured_bitrate_); return new_bitrate; diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.h b/modules/remote_bitrate_estimator/aimd_rate_control.h index 12dec32b4d..699b185c2d 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -113,6 +113,8 @@ class AimdRateControl { FieldTrialParameter estimate_bounded_increase_ratio_{"ratio", 1.0}; FieldTrialParameter ignore_throughput_limit_if_network_estimate_{ "ignore_acked", false}; + FieldTrialParameter ignore_network_estimate_decrease_{"ignore_decr", + false}; absl::optional last_decrease_; FieldTrialOptional 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 34aafb4f91..5d9c328e06 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc +++ b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc @@ -12,6 +12,7 @@ #include #include "api/transport/field_trial_based_config.h" +#include "api/units/data_rate.h" #include "system_wrappers/include/clock.h" #include "test/field_trial.h" #include "test/gtest.h" @@ -254,6 +255,37 @@ TEST(AimdRateControlTest, SetEstimateIncreaseBweInAlr) { 2 * kInitialBitrateBps); } +TEST(AimdRateControlTest, SetEstimateClampedByNetworkEstimate) { + auto states = CreateAimdRateControlStates(/*send_side=*/true); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(400); + states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); + SetEstimate(states, 500'000); + EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), + network_estimate.link_capacity_upper); +} + +TEST(AimdRateControlTest, SetEstimateIgnoresNetworkEstimatesLowerThanCurrent) { + test::ScopedFieldTrials override_field_trials( + "WebRTC-Bwe-EstimateBoundedIncrease/" + "ratio:0.85,ignore_acked:true,ignore_decr:true/"); + auto states = CreateAimdRateControlStates(/*send_side=*/true); + states.aimd_rate_control->SetStartBitrate(DataRate::KilobitsPerSec(30)); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(400); + states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); + SetEstimate(states, 500'000); + ASSERT_EQ(states.aimd_rate_control->LatestEstimate(), + network_estimate.link_capacity_upper * 0.85); + + NetworkStateEstimate lower_network_estimate; + lower_network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(300); + states.aimd_rate_control->SetNetworkStateEstimate(lower_network_estimate); + SetEstimate(states, 500'000); + EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), + network_estimate.link_capacity_upper * 0.85); +} + TEST(AimdRateControlTest, EstimateIncreaseWhileNotInAlr) { // Allow the estimate to increase as long as alr is not detected to ensure // tha BWE can not get stuck at a certain bitrate. @@ -317,6 +349,57 @@ TEST(AimdRateControlTest, EstimateLimitedByNetworkEstimateInAlrIfSet) { network_estimate.link_capacity_upper * 0.85); } +TEST(AimdRateControlTest, EstimateNotLoweredByNetworkEstimate) { + // The delay based estimator is allowed to increase up to a percentage of + // upper link capacity but does not decrease unless the delay detector + // discover an overuse. + test::ScopedFieldTrials override_field_trials( + "WebRTC-Bwe-EstimateBoundedIncrease/" + "ratio:0.85,ignore_acked:true,ignore_decr:true/" + "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); + auto states = CreateAimdRateControlStates(/*send_side=*/true); + constexpr int kInitialBitrateBps = 123000; + constexpr int kEstimatedThroughputBps = 30'000; + SetEstimate(states, kInitialBitrateBps); + + 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, + kEstimatedThroughputBps, + states.simulated_clock->TimeInMilliseconds()); + states.simulated_clock->AdvanceTimeMilliseconds(100); + } + DataRate estimate_after_increase = states.aimd_rate_control->LatestEstimate(); + ASSERT_EQ(estimate_after_increase, + network_estimate.link_capacity_upper * 0.85); + + // A lower network estimate does not decrease the estimate immediately, + // but the estimate is not allowed to increase. + network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(100); + network_estimate.link_capacity_lower = DataRate::KilobitsPerSec(80); + states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); + for (int i = 0; i < 10; ++i) { + UpdateRateControl(states, BandwidthUsage::kBwNormal, + kEstimatedThroughputBps, + states.simulated_clock->TimeInMilliseconds()); + states.simulated_clock->AdvanceTimeMilliseconds(100); + EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), + estimate_after_increase); + } + + // If the detector detects and overuse, BWE drops to a value relative the + // network estimate. + UpdateRateControl(states, BandwidthUsage::kBwOverusing, + kEstimatedThroughputBps, + states.simulated_clock->TimeInMilliseconds()); + EXPECT_LT(states.aimd_rate_control->LatestEstimate(), + network_estimate.link_capacity_lower); + EXPECT_GT(states.aimd_rate_control->LatestEstimate().bps(), + kEstimatedThroughputBps); +} + 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