Add flag to reset LossBased BWE best candidate to instant upper bound
Bug: webrtc:12707
Change-Id: I4583e131ab9c5d81188191b23ebc227b4662bd7c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/329121
Reviewed-by: Diep Bui <diepbp@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41274}
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
index 614ae5b..898fdae 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
@@ -316,33 +316,27 @@
}
}
- current_best_estimate_ = best_candidate;
- UpdateResult();
-
- if (IsInLossLimitedState() &&
- (recovering_after_loss_timestamp_.IsInfinite() ||
- recovering_after_loss_timestamp_ + config_->delayed_increase_window <
- last_send_time_most_recent_observation_)) {
- bandwidth_limit_in_current_window_ =
- std::max(kCongestionControllerMinBitrate,
- current_best_estimate_.loss_limited_bandwidth *
- config_->max_increase_factor);
- recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_;
- }
-}
-
-void LossBasedBweV2::UpdateResult() {
DataRate bounded_bandwidth_estimate = DataRate::PlusInfinity();
if (IsValid(delay_based_estimate_)) {
bounded_bandwidth_estimate =
std::max(GetInstantLowerBound(),
- std::min({current_best_estimate_.loss_limited_bandwidth,
+ std::min({best_candidate.loss_limited_bandwidth,
GetInstantUpperBound(), delay_based_estimate_}));
} else {
- bounded_bandwidth_estimate =
- std::max(GetInstantLowerBound(),
- std::min(current_best_estimate_.loss_limited_bandwidth,
- GetInstantUpperBound()));
+ bounded_bandwidth_estimate = std::max(
+ GetInstantLowerBound(), std::min(best_candidate.loss_limited_bandwidth,
+ GetInstantUpperBound()));
+ }
+ if (config_->bound_best_candidate &&
+ bounded_bandwidth_estimate < best_candidate.loss_limited_bandwidth) {
+ RTC_LOG(LS_INFO) << "Resetting loss based BWE to "
+ << bounded_bandwidth_estimate.kbps()
+ << "due to loss. Avg loss rate: "
+ << GetAverageReportedLossRatio();
+ current_best_estimate_.loss_limited_bandwidth = bounded_bandwidth_estimate;
+ current_best_estimate_.inherent_loss = 0;
+ } else {
+ current_best_estimate_ = best_candidate;
}
if (loss_based_result_.state == LossBasedState::kDecreasing &&
@@ -399,6 +393,17 @@
loss_based_result_.state = LossBasedState::kDelayBasedEstimate;
}
loss_based_result_.bandwidth_estimate = bounded_bandwidth_estimate;
+
+ if (IsInLossLimitedState() &&
+ (recovering_after_loss_timestamp_.IsInfinite() ||
+ recovering_after_loss_timestamp_ + config_->delayed_increase_window <
+ last_send_time_most_recent_observation_)) {
+ bandwidth_limit_in_current_window_ =
+ std::max(kCongestionControllerMinBitrate,
+ current_best_estimate_.loss_limited_bandwidth *
+ config_->max_increase_factor);
+ recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_;
+ }
}
bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited(
@@ -483,6 +488,7 @@
FieldTrialParameter<bool> use_byte_loss_rate("UseByteLossRate", false);
FieldTrialParameter<TimeDelta> padding_duration("PaddingDuration",
TimeDelta::Zero());
+ FieldTrialParameter<bool> bound_best_candidate("BoundBestCandidate", false);
if (key_value_config) {
ParseFieldTrial({&enabled,
&bandwidth_rampup_upper_bound_factor,
@@ -521,7 +527,8 @@
&lower_bound_by_acked_rate_factor,
&hold_duration_factor,
&use_byte_loss_rate,
- &padding_duration},
+ &padding_duration,
+ &bound_best_candidate},
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
}
@@ -586,7 +593,7 @@
config->hold_duration_factor = hold_duration_factor.Get();
config->use_byte_loss_rate = use_byte_loss_rate.Get();
config->padding_duration = padding_duration.Get();
-
+ config->bound_best_candidate = bound_best_candidate.Get();
return config;
}
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
index 850ce8e..9afbb11 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
@@ -123,6 +123,7 @@
double hold_duration_factor = 0.0;
bool use_byte_loss_rate = false;
TimeDelta padding_duration = TimeDelta::Zero();
+ bool bound_best_candidate = false;
};
struct Derivatives {
@@ -188,7 +189,6 @@
// Returns false if no observation was created.
bool PushBackObservation(rtc::ArrayView<const PacketResult> packet_results);
- void UpdateResult();
bool IsEstimateIncreasingWhenLossLimited(DataRate old_estimate,
DataRate new_estimate);
bool IsInLossLimitedState() const;
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
index 2399108..84c889a 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
@@ -1383,6 +1383,42 @@
LossBasedState::kIncreaseUsingPadding);
}
+TEST_F(LossBasedBweV2Test, BestCandidateResetsToUpperBoundInFieldTrial) {
+ ExplicitKeyValueConfig key_value_config(
+ ShortObservationConfig("PaddingDuration:1000ms,BoundBestCandidate:true"));
+ LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
+ loss_based_bandwidth_estimator.SetBandwidthEstimate(
+ DataRate::KilobitsPerSec(2500));
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWith50pPacketLossRate(
+ /*first_packet_timestamp=*/Timestamp::Zero()),
+ /*delay_based_estimate=*/DataRate::PlusInfinity(),
+ /*in_alr=*/true);
+ LossBasedBweV2::Result result_after_loss =
+ loss_based_bandwidth_estimator.GetLossBasedResult();
+ ASSERT_EQ(result_after_loss.state, LossBasedState::kDecreasing);
+
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWithReceivedPackets(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ kObservationDurationLowerBound),
+ /*delay_based_estimate=*/DataRate::PlusInfinity(),
+ /*in_alr=*/true);
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ CreatePacketResultsWithReceivedPackets(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ 2 * kObservationDurationLowerBound),
+ /*delay_based_estimate=*/DataRate::PlusInfinity(),
+ /*in_alr=*/true);
+ // After a BWE decrease due to large loss, BWE is expected to ramp up slowly
+ // and follow the acked bitrate.
+ EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state,
+ LossBasedState::kIncreaseUsingPadding);
+ EXPECT_NEAR(loss_based_bandwidth_estimator.GetLossBasedResult()
+ .bandwidth_estimate.kbps(),
+ result_after_loss.bandwidth_estimate.kbps(), 100);
+}
+
TEST_F(LossBasedBweV2Test, DecreaseToAckedCandidateIfPaddingInAlr) {
ExplicitKeyValueConfig key_value_config(ShortObservationConfig(
"PaddingDuration:1000ms,"