Use acked bitrate as lower bound of loss based BWE.

This cl/ makes sure that the estimate cannot go lower than a factor of acked bitrate. The current flag LowerBoundByAckedRateFactor is set to 0, means we dont use it.


Bug: webrtc:12707
Change-Id: I75d5881f0b85a374af3f7039b82c71aee97fb7b0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/323881
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Diep Bui <diepbp@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40958}
This commit is contained in:
Diep Bui 2023-10-18 07:38:18 +00:00 committed by WebRTC LUCI CQ
parent 8e18e2e085
commit 8ef094f66a
3 changed files with 94 additions and 6 deletions

View File

@ -164,11 +164,14 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const {
if (IsValid(delay_based_estimate_)) {
result.bandwidth_estimate =
std::min({current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound(), delay_based_estimate_});
std::max(GetInstantLowerBound(),
std::min({current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound(), delay_based_estimate_}));
} else {
result.bandwidth_estimate = std::min(
current_estimate_.loss_limited_bandwidth, GetInstantUpperBound());
result.bandwidth_estimate =
std::max(GetInstantLowerBound(),
std::min(current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound()));
}
return result;
}
@ -176,6 +179,7 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const {
void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) {
if (IsValid(acknowledged_bitrate)) {
acknowledged_bitrate_ = acknowledged_bitrate;
CalculateInstantLowerBound();
} else {
RTC_LOG(LS_WARNING) << "The acknowledged bitrate must be finite: "
<< ToString(acknowledged_bitrate);
@ -195,6 +199,7 @@ void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate,
DataRate max_bitrate) {
if (IsValid(min_bitrate)) {
min_bitrate_ = min_bitrate;
CalculateInstantLowerBound();
} else {
RTC_LOG(LS_WARNING) << "The min bitrate must be finite: "
<< ToString(min_bitrate);
@ -393,6 +398,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
true);
FieldTrialParameter<bool> use_in_start_phase("UseInStartPhase", false);
FieldTrialParameter<int> min_num_observations("MinNumObservations", 3);
FieldTrialParameter<double> lower_bound_by_acked_rate_factor(
"LowerBoundByAckedRateFactor", 0.0);
if (key_value_config) {
ParseFieldTrial({&enabled,
&bandwidth_rampup_upper_bound_factor,
@ -428,7 +435,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
&slope_of_bwe_high_loss_func,
&not_use_acked_rate_in_alr,
&use_in_start_phase,
&min_num_observations},
&min_num_observations,
&lower_bound_by_acked_rate_factor},
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
}
@ -488,6 +496,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
config->not_use_acked_rate_in_alr = not_use_acked_rate_in_alr.Get();
config->use_in_start_phase = use_in_start_phase.Get();
config->min_num_observations = min_num_observations.Get();
config->lower_bound_by_acked_rate_factor =
lower_bound_by_acked_rate_factor.Get();
return config;
}
@ -673,6 +683,13 @@ bool LossBasedBweV2::IsConfigValid() const {
<< config_->min_num_observations;
valid = false;
}
if (config_->lower_bound_by_acked_rate_factor < 0.0) {
RTC_LOG(LS_WARNING)
<< "The estimate lower bound by acknowledged rate factor must be "
"non-negative: "
<< config_->lower_bound_by_acked_rate_factor;
valid = false;
}
return valid;
}
@ -913,6 +930,24 @@ void LossBasedBweV2::CalculateInstantUpperBound() {
cached_instant_upper_bound_ = instant_limit;
}
DataRate LossBasedBweV2::GetInstantLowerBound() const {
return cached_instant_lower_bound_.value_or(DataRate::Zero());
}
void LossBasedBweV2::CalculateInstantLowerBound() {
DataRate instance_lower_bound = DataRate::Zero();
if (IsValid(acknowledged_bitrate_) &&
config_->lower_bound_by_acked_rate_factor > 0.0) {
instance_lower_bound = config_->lower_bound_by_acked_rate_factor *
acknowledged_bitrate_.value();
}
if (IsValid(min_bitrate_)) {
instance_lower_bound = std::max(instance_lower_bound, min_bitrate_);
}
cached_instant_lower_bound_ = instance_lower_bound;
}
void LossBasedBweV2::CalculateTemporalWeights() {
for (int i = 0; i < config_->observation_window_size; ++i) {
temporal_weights_[i] = std::pow(config_->temporal_weight_factor, i);

View File

@ -113,6 +113,7 @@ class LossBasedBweV2 {
bool not_use_acked_rate_in_alr = false;
bool use_in_start_phase = false;
int min_num_observations = 0;
double lower_bound_by_acked_rate_factor = 0.0;
};
struct Derivatives {
@ -154,6 +155,8 @@ class LossBasedBweV2 {
DataRate GetSendingRate(DataRate instantaneous_sending_rate) const;
DataRate GetInstantUpperBound() const;
void CalculateInstantUpperBound();
DataRate GetInstantLowerBound() const;
void CalculateInstantLowerBound();
void CalculateTemporalWeights();
void NewtonsMethodUpdate(ChannelParameters& channel_parameters) const;
@ -173,6 +176,7 @@ class LossBasedBweV2 {
Timestamp last_send_time_most_recent_observation_ = Timestamp::PlusInfinity();
Timestamp last_time_estimate_reduced_ = Timestamp::MinusInfinity();
absl::optional<DataRate> cached_instant_upper_bound_;
absl::optional<DataRate> cached_instant_lower_bound_;
std::vector<double> instant_upper_bound_temporal_weights_;
std::vector<double> temporal_weights_;
Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity();

View File

@ -1185,7 +1185,6 @@ TEST_F(LossBasedBweV2Test, NotBackOffToAckedRateInAlr) {
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_1, delay_based_estimate,
/*in_alr=*/true);
// Make sure that the estimate decreases but higher than acked rate.
@ -1248,5 +1247,55 @@ TEST_F(LossBasedBweV2Test, ReadyToUseInStartPhase) {
EXPECT_TRUE(loss_based_bandwidth_estimator.ReadyToUseInStartPhase());
}
TEST_F(LossBasedBweV2Test, BoundEstimateByAckedRate) {
ExplicitKeyValueConfig key_value_config(
ShortObservationConfig("LowerBoundByAckedRateFactor:1.0"));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetMinMaxBitrate(
/*min_bitrate=*/DataRate::KilobitsPerSec(10),
/*max_bitrate=*/DataRate::KilobitsPerSec(1000000));
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(500));
std::vector<PacketResult> enough_feedback_100p_loss_1 =
CreatePacketResultsWith100pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_1,
/*delay_based_estimate=*/DataRate::PlusInfinity(),
/*in_alr=*/false);
EXPECT_EQ(
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate,
DataRate::KilobitsPerSec(500));
}
TEST_F(LossBasedBweV2Test, NotBoundEstimateByAckedRate) {
ExplicitKeyValueConfig key_value_config(
ShortObservationConfig("LowerBoundByAckedRateFactor:0.0"));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetMinMaxBitrate(
/*min_bitrate=*/DataRate::KilobitsPerSec(10),
/*max_bitrate=*/DataRate::KilobitsPerSec(1000000));
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(500));
std::vector<PacketResult> enough_feedback_100p_loss_1 =
CreatePacketResultsWith100pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_1,
/*delay_based_estimate=*/DataRate::PlusInfinity(),
/*in_alr=*/false);
EXPECT_LT(
loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate,
DataRate::KilobitsPerSec(500));
}
} // namespace
} // namespace webrtc