Skip to content

Commit

Permalink
Sync with latest Loss v2 changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugene Voityuk committed Nov 17, 2022
1 parent a43e06e commit f498894
Show file tree
Hide file tree
Showing 10 changed files with 368 additions and 197 deletions.
5 changes: 5 additions & 0 deletions worker/deps/libwebrtc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ The file `libwebrtc/mediasoup_helpers.h` includes some utilities to plug mediaso
The file `worker/deps/libwebrtc/deps/abseil-cpp/abseil-cpp/absl/synchronization/internal/graphcycles.cc` has `#include <limits>` added to it to fix CI builds with Clang.

The file `meson.build` is written for using with Meson build system.

Updated and synced with:

* libwebrtc branch: main
* libwebrtc commit: 17887eb04a84e426b604d4c084898c3147c7d810
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 @@ -132,8 +136,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()) {
RTC_LOG(LS_WARNING)
Expand All @@ -147,18 +152,22 @@ DataRate LossBasedBweV2::GetBandwidthEstimate(
RTC_LOG(LS_WARNING) << "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;
}

if (delay_based_limit.IsFinite()) {
return std::min({current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound(), delay_based_limit});
if (IsValid(delay_based_estimate_)) {
result.bandwidth_estimate =
std::min({current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound(), delay_based_estimate_});
} else {
return std::min(current_estimate_.loss_limited_bandwidth,
GetInstantUpperBound());
result.bandwidth_estimate = std::min(
current_estimate_.loss_limited_bandwidth, GetInstantUpperBound());
}
return result;
}

void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) {
Expand All @@ -179,24 +188,45 @@ 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 {
/* RTC_LOG(LS_WARNING) << "The min bitrate must be finite: "
/*RTC_LOG(LS_WARNING) << "The min bitrate must be finite: "
<< ToString(min_bitrate);*/
}

if (IsValid(max_bitrate)) {
max_bitrate_ = max_bitrate;
} else {
/* RTC_LOG(LS_WARNING) << "The max bitrate must be finite: "
<< ToString(max_bitrate);*/
}
}

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()) {
/* RTC_LOG(LS_WARNING)
<< "The estimator must be enabled before it can be used.";*/
return;
}
SetProbeBitrate(probe_bitrate);
if (packet_results.empty()) {
/* RTC_LOG(LS_VERBOSE)
<< "The estimate cannot be updated without any loss statistics.";*/
Expand All @@ -215,7 +245,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 @@ -239,34 +269,75 @@ 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)) {
current_state_ = LossBasedState::kIncreasing;
} else if (IsValid(delay_based_estimate_) &&
best_candidate.loss_limited_bandwidth < delay_based_estimate_) {
current_state_ = LossBasedState::kDecreasing;
} else if (IsValid(delay_based_estimate_) &&
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 @@ -337,6 +408,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 @@ -369,9 +444,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 @@ -431,6 +508,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 @@ -662,33 +742,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 @@ -704,8 +776,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 @@ -723,16 +795,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 @@ -880,11 +952,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 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) {
instant_limit = config_->instant_upper_bound_bandwidth_balance /
Expand All @@ -900,6 +972,12 @@ void LossBasedBweV2::CalculateInstantUpperBound() {
}
}

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;
}

Expand Down Expand Up @@ -1015,4 +1093,8 @@ bool LossBasedBweV2::PushBackObservation(
return true;
}

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

} // namespace webrtc

0 comments on commit f498894

Please sign in to comment.