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}
This commit is contained in:
parent
5a5a775a88
commit
141007668c
@ -95,11 +95,12 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config,
|
|||||||
estimate_bounded_backoff_(
|
estimate_bounded_backoff_(
|
||||||
IsNotDisabled(*key_value_config,
|
IsNotDisabled(*key_value_config,
|
||||||
"WebRTC-Bwe-EstimateBoundedBackoff")),
|
"WebRTC-Bwe-EstimateBoundedBackoff")),
|
||||||
estimate_bounded_increase_(
|
|
||||||
IsNotDisabled(*key_value_config,
|
|
||||||
"WebRTC-Bwe-EstimateBoundedIncrease")),
|
|
||||||
initial_backoff_interval_("initial_backoff_interval"),
|
initial_backoff_interval_("initial_backoff_interval"),
|
||||||
link_capacity_fix_("link_capacity_fix") {
|
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
|
// E.g
|
||||||
// WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/
|
// WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/
|
||||||
ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_},
|
ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_},
|
||||||
@ -272,27 +273,34 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input,
|
|||||||
|
|
||||||
ChangeState(input, at_time);
|
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_) {
|
switch (rate_control_state_) {
|
||||||
case RateControlState::kRcHold:
|
case RateControlState::kRcHold:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RateControlState::kRcIncrease:
|
case RateControlState::kRcIncrease: {
|
||||||
if (estimated_throughput > link_capacity_.UpperBound())
|
if (estimated_throughput > link_capacity_.UpperBound())
|
||||||
link_capacity_.Reset();
|
link_capacity_.Reset();
|
||||||
|
|
||||||
// Do not increase the delay based estimate in alr since the estimator
|
// We limit the new bitrate based on the troughput to avoid unlimited
|
||||||
// will not be able to get transport feedback necessary to detect if
|
// bitrate increases. We allow a bit more lag at very low rates to not too
|
||||||
// the new estimate is correct.
|
// easily get stuck if the encoder produces uneven outputs.
|
||||||
// If we have previously increased above the limit (for instance due to
|
DataRate increase_limit =
|
||||||
// probing), we don't allow further changes.
|
1.5 * estimated_throughput + DataRate::KilobitsPerSec(10);
|
||||||
if (current_bitrate_ < troughput_based_limit &&
|
if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ &&
|
||||||
!(send_side_ && in_alr_ && no_bitrate_increase_in_alr_)) {
|
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();
|
DataRate increased_bitrate = DataRate::MinusInfinity();
|
||||||
if (link_capacity_.has_estimate()) {
|
if (link_capacity_.has_estimate()) {
|
||||||
// The link_capacity estimate is reset if the measured throughput
|
// The link_capacity estimate is reset if the measured throughput
|
||||||
@ -309,11 +317,11 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input,
|
|||||||
at_time, time_last_bitrate_change_, current_bitrate_);
|
at_time, time_last_bitrate_change_, current_bitrate_);
|
||||||
increased_bitrate = current_bitrate_ + multiplicative_increase;
|
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;
|
time_last_bitrate_change_ = at_time;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case RateControlState::kRcDecrease: {
|
case RateControlState::kRcDecrease: {
|
||||||
DataRate decreased_bitrate = DataRate::PlusInfinity();
|
DataRate decreased_bitrate = DataRate::PlusInfinity();
|
||||||
@ -368,8 +376,10 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const {
|
DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const {
|
||||||
if (estimate_bounded_increase_ && network_estimate_) {
|
if (!disable_estimate_bounded_increase_ && network_estimate_ &&
|
||||||
DataRate upper_bound = network_estimate_->link_capacity_upper;
|
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::min(new_bitrate, upper_bound);
|
||||||
}
|
}
|
||||||
new_bitrate = std::max(new_bitrate, min_configured_bitrate_);
|
new_bitrate = std::max(new_bitrate, min_configured_bitrate_);
|
||||||
|
|||||||
@ -107,9 +107,12 @@ class AimdRateControl {
|
|||||||
// Use estimated link capacity lower bound if it is higher than the
|
// Use estimated link capacity lower bound if it is higher than the
|
||||||
// acknowledged rate when backing off due to overuse.
|
// acknowledged rate when backing off due to overuse.
|
||||||
const bool estimate_bounded_backoff_;
|
const bool estimate_bounded_backoff_;
|
||||||
// Use estimated link capacity upper bound as upper limit for increasing
|
// If false, uses estimated link capacity upper bound *
|
||||||
// bitrate over the acknowledged rate.
|
// `estimate_bounded_increase_ratio_` as upper limit for the estimate.
|
||||||
const bool estimate_bounded_increase_;
|
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_;
|
absl::optional<DataRate> last_decrease_;
|
||||||
FieldTrialOptional<TimeDelta> initial_backoff_interval_;
|
FieldTrialOptional<TimeDelta> initial_backoff_interval_;
|
||||||
FieldTrialFlag link_capacity_fix_;
|
FieldTrialFlag link_capacity_fix_;
|
||||||
|
|||||||
@ -274,4 +274,72 @@ TEST(AimdRateControlTest, EstimateIncreaseWhileNotInAlr) {
|
|||||||
kInitialBitrateBps);
|
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
|
} // namespace webrtc
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user