Tweaks for LossBasedBweV2.
Caches the TCP fairness limit to avoid redundant calculation. Adds option to append the delay based estimate as a candidate. Makes the appending of acknowledged bitrate as a candidate optional. Adds a log-bandwidth bias term. (submit on behalf of crodbro) Bug: webrtc:12707 Change-Id: Ic4b0f58e6f0bc3b117fe78a2321a07db65afd9dd Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/228163 Commit-Queue: Ying Wang <yinwa@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34687}
This commit is contained in:

committed by
WebRTC LUCI CQ

parent
913cfa76ec
commit
1fde34f703
@ -178,7 +178,8 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) {
|
||||
}
|
||||
|
||||
void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
rtc::ArrayView<const PacketResult> packet_results) {
|
||||
rtc::ArrayView<const PacketResult> packet_results,
|
||||
DataRate delay_based_estimate) {
|
||||
if (!IsEnabled()) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "The estimator must be enabled before it can be used.";
|
||||
@ -202,7 +203,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
|
||||
ChannelParameters best_candidate = current_estimate_;
|
||||
double objective_max = std::numeric_limits<double>::lowest();
|
||||
for (ChannelParameters candidate : GetCandidates()) {
|
||||
for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) {
|
||||
NewtonsMethodUpdate(candidate);
|
||||
|
||||
const double candidate_objective = GetObjective(candidate);
|
||||
@ -226,6 +227,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
{1.05, 1.0, 0.95});
|
||||
FieldTrialParameter<double> higher_bandwidth_bias_factor("HigherBwBiasFactor",
|
||||
0.00001);
|
||||
FieldTrialParameter<double> higher_log_bandwidth_bias_factor(
|
||||
"HigherLogBwBiasFactor", 0.001);
|
||||
FieldTrialParameter<double> inherent_loss_lower_bound(
|
||||
"InherentLossLowerBound", 1.0e-3);
|
||||
FieldTrialParameter<DataRate> inherent_loss_upper_bound_bandwidth_balance(
|
||||
@ -236,6 +239,10 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
"InitialInherentLossEstimate", 0.01);
|
||||
FieldTrialParameter<int> newton_iterations("NewtonIterations", 1);
|
||||
FieldTrialParameter<double> newton_step_size("NewtonStepSize", 0.5);
|
||||
FieldTrialParameter<bool> append_acknowledged_rate_candidate(
|
||||
"AckedRateCandidate", true);
|
||||
FieldTrialParameter<bool> append_delay_based_estimate_candidate(
|
||||
"DelayBasedCandidate", false);
|
||||
FieldTrialParameter<TimeDelta> observation_duration_lower_bound(
|
||||
"ObservationDurationLowerBound", TimeDelta::Seconds(1));
|
||||
FieldTrialParameter<int> observation_window_size("ObservationWindowSize", 20);
|
||||
@ -251,17 +258,27 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
0.99);
|
||||
|
||||
if (key_value_config) {
|
||||
ParseFieldTrial(
|
||||
{&enabled, &bandwidth_rampup_upper_bound_factor, &candidate_factors,
|
||||
&higher_bandwidth_bias_factor, &inherent_loss_lower_bound,
|
||||
&inherent_loss_upper_bound_bandwidth_balance,
|
||||
&inherent_loss_upper_bound_offset, &initial_inherent_loss_estimate,
|
||||
&newton_iterations, &newton_step_size,
|
||||
&observation_duration_lower_bound, &observation_window_size,
|
||||
&sending_rate_smoothing_factor, &tcp_fairness_temporal_weight_factor,
|
||||
&tcp_fairness_upper_bound_bandwidth_balance,
|
||||
&tcp_fairness_upper_bound_loss_offset, &temporal_weight_factor},
|
||||
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
|
||||
ParseFieldTrial({&enabled,
|
||||
&bandwidth_rampup_upper_bound_factor,
|
||||
&candidate_factors,
|
||||
&higher_bandwidth_bias_factor,
|
||||
&higher_log_bandwidth_bias_factor,
|
||||
&inherent_loss_lower_bound,
|
||||
&inherent_loss_upper_bound_bandwidth_balance,
|
||||
&inherent_loss_upper_bound_offset,
|
||||
&initial_inherent_loss_estimate,
|
||||
&newton_iterations,
|
||||
&newton_step_size,
|
||||
&append_acknowledged_rate_candidate,
|
||||
&append_delay_based_estimate_candidate,
|
||||
&observation_duration_lower_bound,
|
||||
&observation_window_size,
|
||||
&sending_rate_smoothing_factor,
|
||||
&tcp_fairness_temporal_weight_factor,
|
||||
&tcp_fairness_upper_bound_bandwidth_balance,
|
||||
&tcp_fairness_upper_bound_loss_offset,
|
||||
&temporal_weight_factor},
|
||||
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
|
||||
}
|
||||
|
||||
absl::optional<Config> config;
|
||||
@ -273,6 +290,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
bandwidth_rampup_upper_bound_factor.Get();
|
||||
config->candidate_factors = candidate_factors.Get();
|
||||
config->higher_bandwidth_bias_factor = higher_bandwidth_bias_factor.Get();
|
||||
config->higher_log_bandwidth_bias_factor =
|
||||
higher_log_bandwidth_bias_factor.Get();
|
||||
config->inherent_loss_lower_bound = inherent_loss_lower_bound.Get();
|
||||
config->inherent_loss_upper_bound_bandwidth_balance =
|
||||
inherent_loss_upper_bound_bandwidth_balance.Get();
|
||||
@ -281,6 +300,10 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
config->initial_inherent_loss_estimate = initial_inherent_loss_estimate.Get();
|
||||
config->newton_iterations = newton_iterations.Get();
|
||||
config->newton_step_size = newton_step_size.Get();
|
||||
config->append_acknowledged_rate_candidate =
|
||||
append_acknowledged_rate_candidate.Get();
|
||||
config->append_delay_based_estimate_candidate =
|
||||
append_delay_based_estimate_candidate.Get();
|
||||
config->observation_duration_lower_bound =
|
||||
observation_duration_lower_bound.Get();
|
||||
config->observation_window_size = observation_window_size.Get();
|
||||
@ -427,19 +450,23 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const {
|
||||
return static_cast<double>(num_lost_packets) / num_packets;
|
||||
}
|
||||
|
||||
std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates()
|
||||
const {
|
||||
std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates(
|
||||
DataRate delay_based_estimate) const {
|
||||
std::vector<DataRate> bandwidths;
|
||||
for (double candidate_factor : config_->candidate_factors) {
|
||||
bandwidths.emplace_back(candidate_factor *
|
||||
current_estimate_.loss_limited_bandwidth);
|
||||
bandwidths.push_back(candidate_factor *
|
||||
current_estimate_.loss_limited_bandwidth);
|
||||
}
|
||||
|
||||
if (acknowledged_bitrate_.has_value()) {
|
||||
bandwidths.emplace_back(*acknowledged_bitrate_);
|
||||
if (acknowledged_bitrate_.has_value() &&
|
||||
config_->append_acknowledged_rate_candidate) {
|
||||
bandwidths.push_back(*acknowledged_bitrate_);
|
||||
}
|
||||
|
||||
// TODO(crodbro): Consider adding the delay based estimate as a candidate.
|
||||
if (IsValid(delay_based_estimate) &&
|
||||
config_->append_delay_based_estimate_candidate) {
|
||||
bandwidths.push_back(delay_based_estimate);
|
||||
}
|
||||
|
||||
const DataRate candidate_bandwidth_upper_bound =
|
||||
acknowledged_bitrate_.has_value()
|
||||
@ -516,10 +543,22 @@ double LossBasedBweV2::GetInherentLossUpperBound(DataRate bandwidth) const {
|
||||
return std::min(inherent_loss_upper_bound, 1.0);
|
||||
}
|
||||
|
||||
double LossBasedBweV2::GetHighBandwidthBias(DataRate bandwidth) const {
|
||||
if (IsValid(bandwidth)) {
|
||||
return config_->higher_bandwidth_bias_factor * bandwidth.kbps() +
|
||||
config_->higher_log_bandwidth_bias_factor *
|
||||
std::log(1.0 + bandwidth.kbps());
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double LossBasedBweV2::GetObjective(
|
||||
const ChannelParameters& channel_parameters) const {
|
||||
double objective = 0.0;
|
||||
|
||||
const double high_bandwidth_bias =
|
||||
GetHighBandwidthBias(channel_parameters.loss_limited_bandwidth);
|
||||
|
||||
for (const Observation& observation : observations_) {
|
||||
if (!observation.IsInitialized()) {
|
||||
continue;
|
||||
@ -537,9 +576,7 @@ double LossBasedBweV2::GetObjective(
|
||||
((observation.num_lost_packets * std::log(loss_probability)) +
|
||||
(observation.num_received_packets * std::log(1.0 - loss_probability)));
|
||||
objective +=
|
||||
temporal_weight * (config_->higher_bandwidth_bias_factor *
|
||||
channel_parameters.loss_limited_bandwidth.kbps() *
|
||||
observation.num_packets);
|
||||
temporal_weight * high_bandwidth_bias * observation.num_packets;
|
||||
}
|
||||
|
||||
return objective;
|
||||
@ -565,18 +602,19 @@ DataRate LossBasedBweV2::GetSendingRate(
|
||||
}
|
||||
|
||||
DataRate LossBasedBweV2::GetTcpFairnessBandwidthUpperBound() const {
|
||||
if (num_observations_ <= 0) {
|
||||
return DataRate::PlusInfinity();
|
||||
}
|
||||
return cached_tcp_fairness_limit_.value_or(DataRate::PlusInfinity());
|
||||
}
|
||||
|
||||
void LossBasedBweV2::CalculateTcpFairnessBandwidthUpperBound() {
|
||||
DataRate tcp_fairness_limit = DataRate::PlusInfinity();
|
||||
const double average_reported_loss_ratio = GetAverageReportedLossRatio();
|
||||
if (average_reported_loss_ratio <=
|
||||
if (average_reported_loss_ratio >
|
||||
config_->tcp_fairness_upper_bound_loss_offset) {
|
||||
return DataRate::PlusInfinity();
|
||||
tcp_fairness_limit = config_->tcp_fairness_upper_bound_bandwidth_balance /
|
||||
(average_reported_loss_ratio -
|
||||
config_->tcp_fairness_upper_bound_loss_offset);
|
||||
}
|
||||
return config_->tcp_fairness_upper_bound_bandwidth_balance /
|
||||
(average_reported_loss_ratio -
|
||||
config_->tcp_fairness_upper_bound_loss_offset);
|
||||
cached_tcp_fairness_limit_ = tcp_fairness_limit;
|
||||
}
|
||||
|
||||
void LossBasedBweV2::CalculateTemporalWeights() {
|
||||
@ -646,6 +684,7 @@ bool LossBasedBweV2::PushBackObservation(
|
||||
|
||||
partial_observation_ = PartialObservation();
|
||||
|
||||
CalculateTcpFairnessBandwidthUpperBound();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,8 @@ class LossBasedBweV2 {
|
||||
void SetBandwidthEstimate(DataRate bandwidth_estimate);
|
||||
|
||||
void UpdateBandwidthEstimate(
|
||||
rtc::ArrayView<const PacketResult> packet_results);
|
||||
rtc::ArrayView<const PacketResult> packet_results,
|
||||
DataRate delay_based_estimate);
|
||||
|
||||
private:
|
||||
struct ChannelParameters {
|
||||
@ -60,6 +61,7 @@ class LossBasedBweV2 {
|
||||
double bandwidth_rampup_upper_bound_factor = 0.0;
|
||||
std::vector<double> candidate_factors;
|
||||
double higher_bandwidth_bias_factor = 0.0;
|
||||
double higher_log_bandwidth_bias_factor = 0.0;
|
||||
double inherent_loss_lower_bound = 0.0;
|
||||
DataRate inherent_loss_upper_bound_bandwidth_balance =
|
||||
DataRate::MinusInfinity();
|
||||
@ -67,6 +69,8 @@ class LossBasedBweV2 {
|
||||
double initial_inherent_loss_estimate = 0.0;
|
||||
int newton_iterations = 0;
|
||||
double newton_step_size = 0.0;
|
||||
bool append_acknowledged_rate_candidate = true;
|
||||
bool append_delay_based_estimate_candidate = false;
|
||||
TimeDelta observation_duration_lower_bound = TimeDelta::Zero();
|
||||
int observation_window_size = 0;
|
||||
double sending_rate_smoothing_factor = 0.0;
|
||||
@ -104,14 +108,17 @@ class LossBasedBweV2 {
|
||||
|
||||
// Returns `0.0` if not enough loss statistics have been received.
|
||||
double GetAverageReportedLossRatio() const;
|
||||
std::vector<ChannelParameters> GetCandidates() const;
|
||||
std::vector<ChannelParameters> GetCandidates(
|
||||
DataRate delay_based_estimate) const;
|
||||
Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const;
|
||||
double GetFeasibleInherentLoss(
|
||||
const ChannelParameters& channel_parameters) const;
|
||||
double GetInherentLossUpperBound(DataRate bandwidth) const;
|
||||
double GetHighBandwidthBias(DataRate bandwidth) const;
|
||||
double GetObjective(const ChannelParameters& channel_parameters) const;
|
||||
DataRate GetSendingRate(DataRate instantaneous_sending_rate) const;
|
||||
DataRate GetTcpFairnessBandwidthUpperBound() const;
|
||||
void CalculateTcpFairnessBandwidthUpperBound();
|
||||
|
||||
void CalculateTemporalWeights();
|
||||
void NewtonsMethodUpdate(ChannelParameters& channel_parameters) const;
|
||||
@ -126,6 +133,7 @@ class LossBasedBweV2 {
|
||||
std::vector<Observation> observations_;
|
||||
PartialObservation partial_observation_;
|
||||
Timestamp last_send_time_most_recent_observation_ = Timestamp::PlusInfinity();
|
||||
absl::optional<DataRate> cached_tcp_fairness_limit_;
|
||||
std::vector<double> tcp_fairness_temporal_weights_;
|
||||
std::vector<double> temporal_weights_;
|
||||
};
|
||||
|
@ -105,7 +105,8 @@ TEST(LossBasedBweV2Test, BandwidthEstimateGivenInitializationAndThenFeedback) {
|
||||
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_TRUE(loss_based_bandwidth_estimator.IsReady());
|
||||
EXPECT_TRUE(loss_based_bandwidth_estimator.GetBandwidthEstimate().IsFinite());
|
||||
@ -127,7 +128,8 @@ TEST(LossBasedBweV2Test, NoBandwidthEstimateGivenNoInitialization) {
|
||||
Config(/*enabled=*/true, /*valid=*/true));
|
||||
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
|
||||
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
|
||||
EXPECT_TRUE(
|
||||
@ -159,7 +161,8 @@ TEST(LossBasedBweV2Test, NoBandwidthEstimateGivenNotEnoughFeedback) {
|
||||
EXPECT_TRUE(
|
||||
loss_based_bandwidth_estimator.GetBandwidthEstimate().IsPlusInfinity());
|
||||
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(not_enough_feedback);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
not_enough_feedback, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
|
||||
EXPECT_TRUE(
|
||||
@ -196,7 +199,8 @@ TEST(LossBasedBweV2Test,
|
||||
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback_1);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_1, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
@ -207,7 +211,8 @@ TEST(LossBasedBweV2Test,
|
||||
EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(enough_feedback_2);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_2, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(600));
|
||||
@ -246,8 +251,10 @@ TEST(LossBasedBweV2Test,
|
||||
DataRate::KilobitsPerSec(600));
|
||||
loss_based_bandwidth_estimator_2.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(enough_feedback_1);
|
||||
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(enough_feedback_1);
|
||||
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
|
||||
enough_feedback_1, DataRate::PlusInfinity());
|
||||
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
|
||||
enough_feedback_1, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(660));
|
||||
@ -258,8 +265,10 @@ TEST(LossBasedBweV2Test,
|
||||
EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(660));
|
||||
|
||||
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(enough_feedback_2);
|
||||
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(enough_feedback_2);
|
||||
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
|
||||
enough_feedback_2, DataRate::PlusInfinity());
|
||||
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
|
||||
enough_feedback_2, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_NE(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
|
||||
loss_based_bandwidth_estimator_2.GetBandwidthEstimate());
|
||||
@ -288,7 +297,7 @@ TEST(LossBasedBweV2Test,
|
||||
loss_based_bandwidth_estimator.SetBandwidthEstimate(
|
||||
DataRate::KilobitsPerSec(600));
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_no_received_packets);
|
||||
enough_feedback_no_received_packets, DataRate::PlusInfinity());
|
||||
|
||||
EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
|
||||
DataRate::KilobitsPerSec(100));
|
||||
|
@ -364,7 +364,7 @@ void SendSideBandwidthEstimation::IncomingPacketFeedbackVector(
|
||||
}
|
||||
if (LossBasedBandwidthEstimatorV2Enabled()) {
|
||||
loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate(
|
||||
report.packet_feedbacks);
|
||||
report.packet_feedbacks, delay_based_limit_);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user