Update loss based bwe 2 to handle low bandwidth networks and no delay signal.
1. Add loss threshold for high bandwidth preference. If the average loss ratio is less than the threshold, then the model prefers higher bandwidth candidates. Otherwise, it prefers lower bandwidth candidates. Before, it always prefers higher bandwidth candidate. The default value is 0.99, means it always prefers high bandwidth candidates. 2. Only increase the estimate if the inherent loss (random loss) is equal to/greater than the average loss. If the inherent loss is less than the average loss, then it is oversending, thus should not increase the estimate. Bug: webrtc:12707 Change-Id: I37eb536679ca29e017a4a47703b417efd4d103ca Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/269101 Commit-Queue: Diep Bui <diepbp@webrtc.org> Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37608}
This commit is contained in:
parent
82c29716c0
commit
5edefa87f7
@ -12,6 +12,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
@ -221,6 +222,16 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
last_time_estimate_reduced_ = last_send_time_most_recent_observation_;
|
||||
}
|
||||
|
||||
// Do not increase the estimate if the average loss is greater than current
|
||||
// inherent loss.
|
||||
if (GetAverageReportedLossRatio() > best_candidate.inherent_loss &&
|
||||
config_->not_increase_if_inherent_loss_less_than_average_loss &&
|
||||
current_estimate_.loss_limited_bandwidth <
|
||||
best_candidate.loss_limited_bandwidth) {
|
||||
best_candidate.loss_limited_bandwidth =
|
||||
current_estimate_.loss_limited_bandwidth;
|
||||
}
|
||||
|
||||
// Bound the estimate increase if:
|
||||
// 1. The estimate is limited due to loss, and
|
||||
// 2. The estimate has been increased for less than `delayed_increase_window`
|
||||
@ -270,6 +281,10 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
"HigherLogBwBiasFactor", 0.001);
|
||||
FieldTrialParameter<double> inherent_loss_lower_bound(
|
||||
"InherentLossLowerBound", 1.0e-3);
|
||||
FieldTrialParameter<double> loss_threshold_of_high_bandwidth_preference(
|
||||
"LossThresholdOfHighBandwidthPreference", 0.99);
|
||||
FieldTrialParameter<double> bandwidth_preference_smoothing_factor(
|
||||
"BandwidthPreferenceSmoothingFactor", 0.002);
|
||||
FieldTrialParameter<DataRate> inherent_loss_upper_bound_bandwidth_balance(
|
||||
"InherentLossUpperBoundBwBalance", DataRate::KilobitsPerSec(15.0));
|
||||
FieldTrialParameter<double> inherent_loss_upper_bound_offset(
|
||||
@ -306,6 +321,9 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
"DelayedIncreaseWindow", TimeDelta::Millis(300));
|
||||
FieldTrialParameter<bool> use_acked_bitrate_only_when_overusing(
|
||||
"UseAckedBitrateOnlyWhenOverusing", false);
|
||||
FieldTrialParameter<bool>
|
||||
not_increase_if_inherent_loss_less_than_average_loss(
|
||||
"NotIncreaseIfInherentLossLessThanAverageLoss", false);
|
||||
|
||||
if (key_value_config) {
|
||||
ParseFieldTrial({&enabled,
|
||||
@ -316,6 +334,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
&higher_bandwidth_bias_factor,
|
||||
&higher_log_bandwidth_bias_factor,
|
||||
&inherent_loss_lower_bound,
|
||||
&loss_threshold_of_high_bandwidth_preference,
|
||||
&bandwidth_preference_smoothing_factor,
|
||||
&inherent_loss_upper_bound_bandwidth_balance,
|
||||
&inherent_loss_upper_bound_offset,
|
||||
&initial_inherent_loss_estimate,
|
||||
@ -335,7 +355,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
&trendline_observations_window_size,
|
||||
&max_increase_factor,
|
||||
&delayed_increase_window,
|
||||
&use_acked_bitrate_only_when_overusing},
|
||||
&use_acked_bitrate_only_when_overusing,
|
||||
¬_increase_if_inherent_loss_less_than_average_loss},
|
||||
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
|
||||
}
|
||||
|
||||
@ -354,6 +375,10 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
config->higher_log_bandwidth_bias_factor =
|
||||
higher_log_bandwidth_bias_factor.Get();
|
||||
config->inherent_loss_lower_bound = inherent_loss_lower_bound.Get();
|
||||
config->loss_threshold_of_high_bandwidth_preference =
|
||||
loss_threshold_of_high_bandwidth_preference.Get();
|
||||
config->bandwidth_preference_smoothing_factor =
|
||||
bandwidth_preference_smoothing_factor.Get();
|
||||
config->inherent_loss_upper_bound_bandwidth_balance =
|
||||
inherent_loss_upper_bound_bandwidth_balance.Get();
|
||||
config->inherent_loss_upper_bound_offset =
|
||||
@ -385,6 +410,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
config->delayed_increase_window = delayed_increase_window.Get();
|
||||
config->use_acked_bitrate_only_when_overusing =
|
||||
use_acked_bitrate_only_when_overusing.Get();
|
||||
config->not_increase_if_inherent_loss_less_than_average_loss =
|
||||
not_increase_if_inherent_loss_less_than_average_loss.Get();
|
||||
return config;
|
||||
}
|
||||
|
||||
@ -447,6 +474,20 @@ bool LossBasedBweV2::IsConfigValid() const {
|
||||
<< config_->inherent_loss_lower_bound;
|
||||
valid = false;
|
||||
}
|
||||
if (config_->loss_threshold_of_high_bandwidth_preference < 0.0 ||
|
||||
config_->loss_threshold_of_high_bandwidth_preference >= 1.0) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "The loss threshold of high bandwidth preference must be in [0, 1): "
|
||||
<< config_->loss_threshold_of_high_bandwidth_preference;
|
||||
valid = false;
|
||||
}
|
||||
if (config_->bandwidth_preference_smoothing_factor <= 0.0 ||
|
||||
config_->bandwidth_preference_smoothing_factor > 1.0) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "The bandwidth preference smoothing factor must be in (0, 1]: "
|
||||
<< config_->bandwidth_preference_smoothing_factor;
|
||||
valid = false;
|
||||
}
|
||||
if (config_->inherent_loss_upper_bound_bandwidth_balance <=
|
||||
DataRate::Zero()) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
@ -720,10 +761,23 @@ double LossBasedBweV2::GetInherentLossUpperBound(DataRate bandwidth) const {
|
||||
return std::min(inherent_loss_upper_bound, 1.0);
|
||||
}
|
||||
|
||||
double LossBasedBweV2::AdjustBiasFactor(double loss_rate,
|
||||
double bias_factor) const {
|
||||
return bias_factor *
|
||||
(config_->loss_threshold_of_high_bandwidth_preference - loss_rate) /
|
||||
(config_->bandwidth_preference_smoothing_factor +
|
||||
std::abs(config_->loss_threshold_of_high_bandwidth_preference -
|
||||
loss_rate));
|
||||
}
|
||||
|
||||
double LossBasedBweV2::GetHighBandwidthBias(DataRate bandwidth) const {
|
||||
if (IsValid(bandwidth)) {
|
||||
return config_->higher_bandwidth_bias_factor * bandwidth.kbps() +
|
||||
config_->higher_log_bandwidth_bias_factor *
|
||||
const double average_reported_loss_ratio = GetAverageReportedLossRatio();
|
||||
return AdjustBiasFactor(average_reported_loss_ratio,
|
||||
config_->higher_bandwidth_bias_factor) *
|
||||
bandwidth.kbps() +
|
||||
AdjustBiasFactor(average_reported_loss_ratio,
|
||||
config_->higher_log_bandwidth_bias_factor) *
|
||||
std::log(1.0 + bandwidth.kbps());
|
||||
}
|
||||
return 0.0;
|
||||
|
||||
@ -68,6 +68,8 @@ class LossBasedBweV2 {
|
||||
double higher_bandwidth_bias_factor = 0.0;
|
||||
double higher_log_bandwidth_bias_factor = 0.0;
|
||||
double inherent_loss_lower_bound = 0.0;
|
||||
double loss_threshold_of_high_bandwidth_preference = 0.0;
|
||||
double bandwidth_preference_smoothing_factor = 0.0;
|
||||
DataRate inherent_loss_upper_bound_bandwidth_balance =
|
||||
DataRate::MinusInfinity();
|
||||
double inherent_loss_upper_bound_offset = 0.0;
|
||||
@ -89,6 +91,7 @@ class LossBasedBweV2 {
|
||||
double max_increase_factor = 0.0;
|
||||
TimeDelta delayed_increase_window = TimeDelta::Zero();
|
||||
bool use_acked_bitrate_only_when_overusing = false;
|
||||
bool not_increase_if_inherent_loss_less_than_average_loss = false;
|
||||
};
|
||||
|
||||
struct Derivatives {
|
||||
@ -125,6 +128,7 @@ class LossBasedBweV2 {
|
||||
double GetFeasibleInherentLoss(
|
||||
const ChannelParameters& channel_parameters) const;
|
||||
double GetInherentLossUpperBound(DataRate bandwidth) const;
|
||||
double AdjustBiasFactor(double loss_rate, double bias_factor) const;
|
||||
double GetHighBandwidthBias(DataRate bandwidth) const;
|
||||
double GetObjective(const ChannelParameters& channel_parameters) const;
|
||||
DataRate GetSendingRate(DataRate instantaneous_sending_rate) const;
|
||||
|
||||
@ -100,6 +100,23 @@ class LossBasedBweV2Test : public ::testing::TestWithParam<bool> {
|
||||
return enough_feedback;
|
||||
}
|
||||
|
||||
std::vector<PacketResult> CreatePacketResultsWith10pLossRate(
|
||||
Timestamp first_packet_timestamp) {
|
||||
std::vector<PacketResult> enough_feedback(10);
|
||||
enough_feedback[0].sent_packet.size = DataSize::Bytes(15'000);
|
||||
for (unsigned i = 0; i < enough_feedback.size(); ++i) {
|
||||
enough_feedback[i].sent_packet.size = DataSize::Bytes(15'000);
|
||||
enough_feedback[i].sent_packet.send_time =
|
||||
first_packet_timestamp +
|
||||
static_cast<int>(i) * kObservationDurationLowerBound;
|
||||
enough_feedback[i].receive_time =
|
||||
first_packet_timestamp +
|
||||
static_cast<int>(i + 1) * kObservationDurationLowerBound;
|
||||
}
|
||||
enough_feedback[9].receive_time = Timestamp::PlusInfinity();
|
||||
return enough_feedback;
|
||||
}
|
||||
|
||||
std::vector<PacketResult> CreatePacketResultsWith50pLossRate(
|
||||
Timestamp first_packet_timestamp) {
|
||||
std::vector<PacketResult> enough_feedback(2);
|
||||
@ -785,6 +802,117 @@ TEST_P(LossBasedBweV2Test, KeepIncreasingEstimateAfterDelayedIncreaseWindow) {
|
||||
estimate_2);
|
||||
}
|
||||
|
||||
TEST_P(LossBasedBweV2Test, NotIncreaseIfInherentLossLessThanAverageLoss) {
|
||||
ExplicitKeyValueConfig key_value_config(
|
||||
"WebRTC-Bwe-LossBasedBweV2/"
|
||||
"Enabled:true,CandidateFactors:1.2,AckedRateCandidate:false,"
|
||||
"ObservationWindowSize:2,"
|
||||
"DelayBasedCandidate:true,InstantUpperBoundBwBalance:100kbps,"
|
||||
"ObservationDurationLowerBound:200ms,"
|
||||
"NotIncreaseIfInherentLossLessThanAverageLoss:true/");
|
||||
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
|
||||
DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
|
||||
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_1 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero());
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_1, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_2 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_2, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
// Do not increase the bitrate because inherent loss is less than average loss
|
||||
EXPECT_EQ(
|
||||
loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
}
|
||||
|
||||
TEST_P(LossBasedBweV2Test,
|
||||
SelectHighBandwidthCandidateIfLossRateIsLessThanThreshold) {
|
||||
ExplicitKeyValueConfig key_value_config(
|
||||
"WebRTC-Bwe-LossBasedBweV2/"
|
||||
"Enabled:true,CandidateFactors:1.2|0.8,AckedRateCandidate:false,"
|
||||
"ObservationWindowSize:2,"
|
||||
"DelayBasedCandidate:true,InstantUpperBoundBwBalance:100kbps,"
|
||||
"ObservationDurationLowerBound:200ms,HigherBwBiasFactor:1000,"
|
||||
"HigherLogBwBiasFactor:1000,LossThresholdOfHighBandwidthPreference:0."
|
||||
"20/");
|
||||
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
|
||||
DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
|
||||
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_1 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero());
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_1, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_2 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_2, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
// Because LossThresholdOfHighBandwidthPreference is 20%, the average loss is
|
||||
// 10%, bandwidth estimate should increase.
|
||||
EXPECT_GT(
|
||||
loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
}
|
||||
|
||||
TEST_P(LossBasedBweV2Test,
|
||||
SelectLowBandwidthCandidateIfLossRateIsIsHigherThanThreshold) {
|
||||
ExplicitKeyValueConfig key_value_config(
|
||||
"WebRTC-Bwe-LossBasedBweV2/"
|
||||
"Enabled:true,CandidateFactors:1.2|0.8,AckedRateCandidate:false,"
|
||||
"ObservationWindowSize:2,"
|
||||
"DelayBasedCandidate:true,InstantUpperBoundBwBalance:100kbps,"
|
||||
"ObservationDurationLowerBound:200ms,HigherBwBiasFactor:1000,"
|
||||
"HigherLogBwBiasFactor:1000,LossThresholdOfHighBandwidthPreference:0."
|
||||
"05/");
|
||||
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
|
||||
DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
|
||||
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_1 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero());
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_1, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
std::vector<PacketResult> enough_feedback_10p_loss_2 =
|
||||
CreatePacketResultsWith10pLossRate(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_10p_loss_2, delay_based_estimate,
|
||||
BandwidthUsage::kBwNormal);
|
||||
|
||||
// Because LossThresholdOfHighBandwidthPreference is 5%, the average loss is
|
||||
// 10%, bandwidth estimate should decrease.
|
||||
EXPECT_LT(
|
||||
loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(LossBasedBweV2Tests,
|
||||
LossBasedBweV2Test,
|
||||
::testing::Bool());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user