Ensure LossBased BWE do not decrease due to acked bitrate

Ensure acked bitrate is not used for lower loss based estimate if
estimate improve.

Ensure LossBasedBweV2 is in state DelayBased if reached max rate.

Bug: webrtc:12707
Change-Id: I20230b99e0c2b530570e2f2de8ea88179f795c50
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/324140
Reviewed-by: Diep Bui <diepbp@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40977}
This commit is contained in:
Per K 2023-10-20 11:10:29 +02:00 committed by WebRTC LUCI CQ
parent 79d1e9eb9c
commit af7b785f02
2 changed files with 95 additions and 28 deletions

View File

@ -282,12 +282,10 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
// Bound the best candidate by the acked bitrate.
if (increasing_when_loss_limited && IsValid(acknowledged_bitrate_)) {
best_candidate.loss_limited_bandwidth =
IsValid(best_candidate.loss_limited_bandwidth)
? std::min(best_candidate.loss_limited_bandwidth,
config_->bandwidth_rampup_upper_bound_factor *
(*acknowledged_bitrate_))
: config_->bandwidth_rampup_upper_bound_factor *
(*acknowledged_bitrate_);
std::max(current_best_estimate_.loss_limited_bandwidth,
std::min(best_candidate.loss_limited_bandwidth,
config_->bandwidth_rampup_upper_bound_factor *
(*acknowledged_bitrate_)));
}
}
@ -323,11 +321,13 @@ void LossBasedBweV2::UpdateResult() {
if (IsEstimateIncreasingWhenLossLimited(
/*old_estimate=*/loss_based_result_.bandwidth_estimate,
/*new_estimate=*/bounded_bandwidth_estimate) &&
bounded_bandwidth_estimate < delay_based_estimate_) {
bounded_bandwidth_estimate < delay_based_estimate_ &&
bounded_bandwidth_estimate < max_bitrate_) {
loss_based_result_.state = LossBasedState::kIncreasing;
} else if (bounded_bandwidth_estimate < delay_based_estimate_) {
} else if (bounded_bandwidth_estimate < delay_based_estimate_ &&
bounded_bandwidth_estimate < max_bitrate_) {
loss_based_result_.state = LossBasedState::kDecreasing;
} else if (bounded_bandwidth_estimate >= delay_based_estimate_) {
} else {
loss_based_result_.state = LossBasedState::kDelayBasedEstimate;
}
loss_based_result_.bandwidth_estimate = bounded_bandwidth_estimate;

View File

@ -711,7 +711,7 @@ TEST_F(LossBasedBweV2Test,
}
TEST_F(LossBasedBweV2Test,
LossBasedStateIsNotDelayBasedEstimateIfDelayBasedEsimtateInfinite) {
LossBasedStateIsNotDelayBasedEstimateIfDelayBasedEstimateInfinite) {
ExplicitKeyValueConfig key_value_config(
ShortObservationConfig("CandidateFactors:100|1|0.5,"
"InstantUpperBoundBwBalance:10000kbps,"
@ -750,17 +750,14 @@ TEST_F(LossBasedBweV2Test,
// a factor of acked bitrate.
TEST_F(LossBasedBweV2Test,
IncreaseByFactorOfAckedBitrateAfterLossBasedBweBacksOff) {
ExplicitKeyValueConfig key_value_config(
ShortObservationConfig("LossThresholdOfHighBandwidthPreference:0.99,"
"BwRampupUpperBoundFactor:1.2,"
"InherentLossUpperBoundOffset:0.9"));
ExplicitKeyValueConfig key_value_config(ShortObservationConfig(
"LossThresholdOfHighBandwidthPreference:0.99,"
"BwRampupUpperBoundFactor:1.2,"
// Set InstantUpperBoundBwBalance high to disable InstantUpperBound cap.
"InstantUpperBoundBwBalance:10000kbps,"));
std::vector<PacketResult> enough_feedback_1 =
CreatePacketResultsWith100pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero());
std::vector<PacketResult> enough_feedback_2 =
CreatePacketResultsWith10pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero() +
kObservationDurationLowerBound);
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
@ -771,19 +768,42 @@ TEST_F(LossBasedBweV2Test,
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback_1,
delay_based_estimate,
/*in_alr=*/false);
ASSERT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
LossBasedState::kDecreasing);
LossBasedBweV2::Result result =
loss_based_bandwidth_estimator.GetLossBasedResult();
DataRate estimate_1 = result.bandwidth_estimate;
ASSERT_LT(estimate_1.kbps(), 600);
// Change the acked bitrate to make sure that the estimate is bounded by a
// factor of acked bitrate.
DataRate acked_bitrate = DataRate::KilobitsPerSec(50);
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(acked_bitrate);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback_2,
delay_based_estimate,
/*in_alr=*/false);
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(estimate_1 * 0.9);
int feedback_count = 1;
while (feedback_count < 5 && result.state != LossBasedState::kIncreasing) {
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
CreatePacketResultsWithReceivedPackets(
/*first_packet_timestamp=*/Timestamp::Zero() +
feedback_count++ * kObservationDurationLowerBound),
delay_based_estimate,
/*in_alr=*/false);
result = loss_based_bandwidth_estimator.GetLossBasedResult();
}
ASSERT_EQ(result.state, LossBasedState::kIncreasing);
// The estimate is capped by acked_bitrate * BwRampupUpperBoundFactor.
DataRate estimate_2 =
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate;
EXPECT_EQ(estimate_2, acked_bitrate * 1.2);
EXPECT_EQ(result.bandwidth_estimate, estimate_1 * 0.9 * 1.2);
// But if acked bitrate decrease, BWE does not decrease when there is no
// loss.
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(estimate_1 * 0.9);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
CreatePacketResultsWithReceivedPackets(
/*first_packet_timestamp=*/Timestamp::Zero() +
feedback_count++ * kObservationDurationLowerBound),
delay_based_estimate,
/*in_alr=*/false);
EXPECT_EQ(
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate,
result.bandwidth_estimate);
}
// After loss based bwe backs off, the estimate is bounded during the delayed
@ -1368,5 +1388,52 @@ TEST_F(LossBasedBweV2Test, HasIncreaseStateBecauseOfLowerBound) {
LossBasedState::kIncreasing);
}
TEST_F(LossBasedBweV2Test, HasDelayBasedStateIfLossBasedBweIsMax) {
ExplicitKeyValueConfig key_value_config(ShortObservationConfig(""));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetMinMaxBitrate(
/*min_bitrate=*/DataRate::KilobitsPerSec(10),
/*max_bitrate=*/DataRate::KilobitsPerSec(1000));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
/*feedback = */ CreatePacketResultsWithReceivedPackets(
/*first_packet_timestamp=*/Timestamp::Zero()),
/*delay_based_estimate=*/DataRate::KilobitsPerSec(2000),
/*in_alr=*/false);
EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
LossBasedState::kDelayBasedEstimate);
EXPECT_EQ(
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate,
DataRate::KilobitsPerSec(1000));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
/*feedback=*/CreatePacketResultsWith50pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero() +
kObservationDurationLowerBound),
/*delay_based_estimate=*/DataRate::KilobitsPerSec(2000),
/*in_alr=*/false);
LossBasedBweV2::Result result =
loss_based_bandwidth_estimator.GetLossBasedResult();
ASSERT_EQ(result.state, LossBasedState::kDecreasing);
ASSERT_LT(result.bandwidth_estimate, DataRate::KilobitsPerSec(1000));
// Eventually the estimator recovers to delay based state.
int feedback_count = 2;
while (feedback_count < 5 &&
result.state != LossBasedState::kDelayBasedEstimate) {
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
/*feedback = */ CreatePacketResultsWithReceivedPackets(
/*first_packet_timestamp=*/Timestamp::Zero() +
feedback_count++ * kObservationDurationLowerBound),
/*delay_based_estimate=*/DataRate::KilobitsPerSec(2000),
/*in_alr=*/false);
result = loss_based_bandwidth_estimator.GetLossBasedResult();
}
EXPECT_EQ(result.state, LossBasedState::kDelayBasedEstimate);
EXPECT_EQ(
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate,
DataRate::KilobitsPerSec(1000));
}
} // namespace
} // namespace webrtc