Skip to content

Commit

Permalink
Backport latest changes from libwebrtc.
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugene Voityuk committed Dec 5, 2022
1 parent 252d568 commit 0c7eef0
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 370 deletions.
2 changes: 0 additions & 2 deletions worker/deps/libwebrtc/libwebrtc.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.cc',
'libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc',
'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc',
'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc',
'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc',
'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc',
'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc',
Expand Down Expand Up @@ -110,7 +109,6 @@
'libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h',
'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h',
'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.h',
'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h',
'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h',
'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h',
'libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ bool IsValid(DataRate datarate) {
return datarate.IsFinite();
}

bool IsValid(absl::optional<DataRate> datarate) {
return datarate.has_value() && IsValid(datarate.value());
}

bool IsValid(Timestamp timestamp) {
return timestamp.IsFinite();
}
Expand Down Expand Up @@ -148,8 +152,9 @@ bool LossBasedBweV2::IsReady() const {
num_observations_ > 0;
}

DataRate LossBasedBweV2::GetBandwidthEstimate(
DataRate delay_based_limit) const {
LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const {
Result result;
result.state = current_state_;
if (!IsReady()) {
if (!IsEnabled()) {
MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used.");
Expand All @@ -161,8 +166,10 @@ DataRate LossBasedBweV2::GetBandwidthEstimate(
MS_WARN_TAG(bwe, "The estimator must receive enough loss statistics before it can be used.");
}
}
return IsValid(delay_based_limit) ? delay_based_limit
: DataRate::PlusInfinity();
result.bandwidth_estimate = IsValid(delay_based_estimate_)
? delay_based_estimate_
: DataRate::PlusInfinity();
return result;
}

auto instant_limit = GetInstantUpperBound();
Expand All @@ -171,13 +178,15 @@ DataRate LossBasedBweV2::GetBandwidthEstimate(
current_estimate_.loss_limited_bandwidth.bps(),
delay_based_limit.IsFinite() ? delay_based_limit.bps() : 0,
instant_limit.IsFinite() ? instant_limit.bps() : 0);
if (delay_based_limit.IsFinite()) {
return std::min({current_estimate_.loss_limited_bandwidth,
instant_limit, delay_based_limit});
} else {
return std::min(current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound());
}
if (IsValid(delay_based_estimate_)) {
result.bandwidth_estimate =
std::min({current_estimate_.loss_limited_bandwidth,
instant_limit, delay_based_estimate_});
} else {
result.bandwidth_estimate = std::min(
current_estimate_.loss_limited_bandwidth, instant_limit);
}
return result;
}

void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) {
Expand All @@ -196,18 +205,37 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) {
}
}

void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) {
void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate,
DataRate max_bitrate) {
if (IsValid(min_bitrate)) {
min_bitrate_ = min_bitrate;
} else {
MS_WARN_TAG(bwe, "The min bitrate must be finite: %" PRIi64 "", min_bitrate.bps());
}

if (IsValid(max_bitrate)) {
max_bitrate_ = max_bitrate;
} else {
MS_WARN_TAG(bwe, "The max bitrate must be finite: %" PRIi64 "", max_bitrate.bps());
}
}

void LossBasedBweV2::SetProbeBitrate(absl::optional<DataRate> probe_bitrate) {
if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) {
if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) {
probe_bitrate_ = probe_bitrate.value();
}
}
}

void LossBasedBweV2::UpdateBandwidthEstimate(
std::vector<PacketResult> packet_results,
DataRate delay_based_estimate,
BandwidthUsage delay_detector_state) {
BandwidthUsage delay_detector_state,
absl::optional<DataRate> probe_bitrate,
DataRate upper_link_capacity) {
delay_based_estimate_ = delay_based_estimate;
upper_link_capacity_ = upper_link_capacity;
if (!IsEnabled()) {
MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used.");
return;
Expand All @@ -228,7 +256,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate(

ChannelParameters best_candidate = current_estimate_;
double objective_max = std::numeric_limits<double>::lowest();
for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) {
for (ChannelParameters candidate : GetCandidates()) {
NewtonsMethodUpdate(candidate);

const double candidate_objective = GetObjective(candidate);
Expand All @@ -252,34 +280,74 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
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`
// ago, and
// 3. The best candidate is greater than bandwidth_limit_in_current_window.
if (limited_due_to_loss_candidate_ &&
recovering_after_loss_timestamp_.IsFinite() &&
recovering_after_loss_timestamp_ + config_->delayed_increase_window >
last_send_time_most_recent_observation_ &&
best_candidate.loss_limited_bandwidth >
bandwidth_limit_in_current_window_) {
best_candidate.loss_limited_bandwidth = bandwidth_limit_in_current_window_;
}
limited_due_to_loss_candidate_ =
delay_based_estimate.IsFinite() &&
best_candidate.loss_limited_bandwidth < delay_based_estimate;

if (limited_due_to_loss_candidate_ &&
if (IsBandwidthLimitedDueToLoss()) {
// Bound the estimate increase if:
// 1. The estimate has been increased for less than
// `delayed_increase_window` ago, and
// 2. The best candidate is greater than bandwidth_limit_in_current_window.
if (recovering_after_loss_timestamp_.IsFinite() &&
recovering_after_loss_timestamp_ + config_->delayed_increase_window >
last_send_time_most_recent_observation_ &&
best_candidate.loss_limited_bandwidth >
bandwidth_limit_in_current_window_) {
best_candidate.loss_limited_bandwidth =
bandwidth_limit_in_current_window_;
}

bool increasing_when_loss_limited =
IsEstimateIncreasingWhenLossLimited(best_candidate);
// Bound the best candidate by the acked bitrate unless there is a recent
// probe result.
if (increasing_when_loss_limited && !IsValid(probe_bitrate_) &&
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_);
}

// Use probe bitrate as the estimate as probe bitrate is trusted to be
// correct. After being used, the probe bitrate is reset.
if (config_->probe_integration_enabled && IsValid(probe_bitrate_)) {
best_candidate.loss_limited_bandwidth =
std::min(probe_bitrate_, best_candidate.loss_limited_bandwidth);
probe_bitrate_ = DataRate::MinusInfinity();
}
}

if (IsEstimateIncreasingWhenLossLimited(best_candidate) &&
best_candidate.loss_limited_bandwidth < delay_based_estimate) {
current_state_ = LossBasedState::kIncreasing;
} else if (best_candidate.loss_limited_bandwidth < delay_based_estimate_) {
current_state_ = LossBasedState::kDecreasing;
} else if (best_candidate.loss_limited_bandwidth >= delay_based_estimate_) {
current_state_ = LossBasedState::kDelayBasedEstimate;
}
current_estimate_ = best_candidate;

if (IsBandwidthLimitedDueToLoss() &&
(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,
best_candidate.loss_limited_bandwidth * config_->max_increase_factor);
bandwidth_limit_in_current_window_ =
std::max(kCongestionControllerMinBitrate,
current_estimate_.loss_limited_bandwidth *
config_->max_increase_factor);
recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_;
}
}

current_estimate_ = best_candidate;
bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited(
const ChannelParameters& best_candidate) {
return (current_estimate_.loss_limited_bandwidth <
best_candidate.loss_limited_bandwidth ||
(current_estimate_.loss_limited_bandwidth ==
best_candidate.loss_limited_bandwidth &&
current_state_ == LossBasedState::kIncreasing)) &&
IsBandwidthLimitedDueToLoss();
}

// Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a
Expand Down Expand Up @@ -350,6 +418,10 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
"BandwidthCapAtHighLossRate", DataRate::kbps(500.0));
FieldTrialParameter<double> slope_of_bwe_high_loss_func(
"SlopeOfBweHighLossFunc", 1000);
FieldTrialParameter<bool> probe_integration_enabled("ProbeIntegrationEnabled",
false);
FieldTrialParameter<bool> bound_by_upper_link_capacity_when_loss_limited(
"BoundByUpperLinkCapacityWhenLossLimited", true);
if (key_value_config) {
ParseFieldTrial({&enabled,
&bandwidth_rampup_upper_bound_factor,
Expand Down Expand Up @@ -382,9 +454,11 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
&delayed_increase_window,
&use_acked_bitrate_only_when_overusing,
&not_increase_if_inherent_loss_less_than_average_loss,
&probe_integration_enabled,
&high_loss_rate_threshold,
&bandwidth_cap_at_high_loss_rate,
&slope_of_bwe_high_loss_func},
&slope_of_bwe_high_loss_func,
&bound_by_upper_link_capacity_when_loss_limited},
key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2"));
}

Expand Down Expand Up @@ -444,6 +518,9 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
config->bandwidth_cap_at_high_loss_rate =
bandwidth_cap_at_high_loss_rate.Get();
config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get();
config->probe_integration_enabled = probe_integration_enabled.Get();
config->bound_by_upper_link_capacity_when_loss_limited =
bound_by_upper_link_capacity_when_loss_limited.Get();


std::string candidate_factors_str;
Expand Down Expand Up @@ -677,33 +754,25 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const {
return num_lost_packets / num_packets;
}

DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound(
DataRate delay_based_estimate) const {
DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity();
if (limited_due_to_loss_candidate_) {
DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const {
DataRate candidate_bandwidth_upper_bound = max_bitrate_;
if (IsBandwidthLimitedDueToLoss() &&
IsValid(bandwidth_limit_in_current_window_)) {
candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_;
}

if (config_->trendline_integration_enabled) {
candidate_bandwidth_upper_bound =
std::min(GetInstantUpperBound(), candidate_bandwidth_upper_bound);
if (IsValid(delay_based_estimate)) {
if (IsValid(delay_based_estimate_)) {
candidate_bandwidth_upper_bound =
std::min(delay_based_estimate, candidate_bandwidth_upper_bound);
std::min(delay_based_estimate_, candidate_bandwidth_upper_bound);
}
}

if (!acknowledged_bitrate_.has_value())
return candidate_bandwidth_upper_bound;

candidate_bandwidth_upper_bound =
IsValid(candidate_bandwidth_upper_bound)
? std::min(candidate_bandwidth_upper_bound,
config_->bandwidth_rampup_upper_bound_factor *
(*acknowledged_bitrate_))
: config_->bandwidth_rampup_upper_bound_factor *
(*acknowledged_bitrate_);

if (config_->rampup_acceleration_max_factor > 0.0) {
const TimeDelta time_since_bandwidth_reduced = std::min(
config_->rampup_acceleration_maxout_time,
Expand All @@ -719,8 +788,8 @@ DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound(
return candidate_bandwidth_upper_bound;
}

std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates(
DataRate delay_based_estimate) const {
std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates()
const {
std::vector<DataRate> bandwidths;
bool can_increase_bitrate = TrendlineEsimateAllowBitrateIncrease();
for (double candidate_factor : config_->candidate_factors) {
Expand All @@ -738,16 +807,16 @@ std::vector<LossBasedBweV2::ChannelParameters> LossBasedBweV2::GetCandidates(
config_->bandwidth_backoff_lower_bound_factor);
}

if (IsValid(delay_based_estimate) &&
if (IsValid(delay_based_estimate_) &&
config_->append_delay_based_estimate_candidate) {
if (can_increase_bitrate &&
delay_based_estimate > current_estimate_.loss_limited_bandwidth) {
bandwidths.push_back(delay_based_estimate);
delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) {
bandwidths.push_back(delay_based_estimate_);
}
}

const DataRate candidate_bandwidth_upper_bound =
GetCandidateBandwidthUpperBound(delay_based_estimate);
GetCandidateBandwidthUpperBound();

std::vector<ChannelParameters> candidates;
candidates.resize(bandwidths.size());
Expand Down Expand Up @@ -895,11 +964,11 @@ DataRate LossBasedBweV2::GetSendingRate(
}

DataRate LossBasedBweV2::GetInstantUpperBound() const {
return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity());
return cached_instant_upper_bound_.value_or(max_bitrate_);
}

void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) {
DataRate instant_limit = DataRate::PlusInfinity();
DataRate instant_limit = max_bitrate_;
const double average_reported_loss_ratio = GetAverageReportedLossRatio();

if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) {
Expand Down Expand Up @@ -934,7 +1003,13 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) {
}
}

cached_instant_upper_bound_ = instant_limit;
if (IsBandwidthLimitedDueToLoss()) {
if (IsValid(upper_link_capacity_) &&
config_->bound_by_upper_link_capacity_when_loss_limited) {
instant_limit = std::min(instant_limit, upper_link_capacity_);
}
}
cached_instant_upper_bound_ = instant_limit;
}

void LossBasedBweV2::CalculateTemporalWeights() {
Expand Down Expand Up @@ -1022,7 +1097,6 @@ bool LossBasedBweV2::PushBackObservation(
const Timestamp last_send_time = packet_results_summary.last_send_time;
const TimeDelta observation_duration =
last_send_time - last_send_time_most_recent_observation_;

// Too small to be meaningful.
if (observation_duration <= TimeDelta::Zero() ||
(observation_duration < config_->observation_duration_lower_bound &&
Expand Down Expand Up @@ -1065,4 +1139,8 @@ bool LossBasedBweV2::PushBackObservation(
return true;
}

bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const {
return current_state_ != LossBasedState::kDelayBasedEstimate;
}

} // namespace webrtc
Loading

0 comments on commit 0c7eef0

Please sign in to comment.