Probing integration in loss based bwe 2.
- Loss based bwe has 3 states: increasing (increasing when loss limited), decreasing (decreasing when loss limited), or delay based bwe (the same as delay based estimate).
- When bandwidth is loss limited and decreasing, and probe result is available, GetLossBasedResult = min(estimate, probe result).
- When bandwidth is loss limited and increasing, and the estimate is bounded by acked bitrate * a factor.
- When bandwidth is loss limited and probe result is available, use probe bitrate as the current estimate, and reset probe bitrate.
Bug: webrtc:12707
Change-Id: I53cb82aa16397941c0cfaf1035116f775bdce72b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/277400
Commit-Queue: Diep Bui <diepbp@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38382}
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
index fcb77fa..9cc9da2 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
@@ -549,8 +549,8 @@
bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time,
result.target_bitrate);
}
- bandwidth_estimation_->UpdateLossBasedEstimator(report,
- result.delay_detector_state);
+ bandwidth_estimation_->UpdateLossBasedEstimator(
+ report, result.delay_detector_state, probe_bitrate);
if (result.updated) {
// Update the estimate in the ProbeController, in case we want to probe.
MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
index e671bd2..7c54218 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc
@@ -42,6 +42,10 @@
return datarate.IsFinite();
}
+bool IsValid(absl::optional<DataRate> datarate) {
+ return datarate.has_value() && IsValid(datarate.value());
+}
+
bool IsValid(Timestamp timestamp) {
return timestamp.IsFinite();
}
@@ -134,8 +138,10 @@
num_observations_ > 0;
}
-DataRate LossBasedBweV2::GetBandwidthEstimate(
+LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult(
DataRate delay_based_limit) const {
+ Result result;
+ result.state = current_state_;
if (!IsReady()) {
if (!IsEnabled()) {
RTC_LOG(LS_WARNING)
@@ -150,17 +156,21 @@
"statistics before it can be used.";
}
}
- return IsValid(delay_based_limit) ? delay_based_limit
- : DataRate::PlusInfinity();
+ result.bandwidth_estimate = IsValid(delay_based_limit)
+ ? delay_based_limit
+ : 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_limit)) {
+ result.bandwidth_estimate =
+ std::min({current_estimate_.loss_limited_bandwidth,
+ GetInstantUpperBound(), delay_based_limit});
} 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) {
@@ -190,15 +200,25 @@
}
}
+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(
rtc::ArrayView<const PacketResult> packet_results,
DataRate delay_based_estimate,
- BandwidthUsage delay_detector_state) {
+ BandwidthUsage delay_detector_state,
+ absl::optional<DataRate> probe_bitrate) {
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.";
@@ -241,34 +261,75 @@
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 (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_;
+ }
- if (limited_due_to_loss_candidate_ &&
+ 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
@@ -339,6 +400,8 @@
"BandwidthCapAtHighLossRate", DataRate::KilobitsPerSec(500.0));
FieldTrialParameter<double> slope_of_bwe_high_loss_func(
"SlopeOfBweHighLossFunc", 1000);
+ FieldTrialParameter<bool> probe_integration_enabled("ProbeIntegrationEnabled",
+ false);
if (key_value_config) {
ParseFieldTrial({&enabled,
&bandwidth_rampup_upper_bound_factor,
@@ -371,6 +434,7 @@
&delayed_increase_window,
&use_acked_bitrate_only_when_overusing,
¬_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},
@@ -433,6 +497,8 @@
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();
+
return config;
}
@@ -645,7 +711,7 @@
DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound(
DataRate delay_based_estimate) const {
DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity();
- if (limited_due_to_loss_candidate_) {
+ if (IsBandwidthLimitedDueToLoss()) {
candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_;
}
@@ -661,14 +727,6 @@
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,
@@ -995,4 +1053,8 @@
return true;
}
+bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const {
+ return current_state_ != LossBasedState::kDelayBasedEstimate;
+}
+
} // namespace webrtc
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
index 88cae01..6d3b409 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h
@@ -27,8 +27,21 @@
namespace webrtc {
+// State of the loss based estimate, which can be either increasing/decreasing
+// when network is loss limited, or equal to the delay based estimate.
+enum class LossBasedState {
+ kIncreasing = 0,
+ kDecreasing = 1,
+ kDelayBasedEstimate = 2
+};
+
class LossBasedBweV2 {
public:
+ struct Result {
+ ~Result() = default;
+ DataRate bandwidth_estimate = DataRate::Zero();
+ LossBasedState state = LossBasedState::kDelayBasedEstimate;
+ };
// Creates a disabled `LossBasedBweV2` if the
// `key_value_config` is not valid.
explicit LossBasedBweV2(const FieldTrialsView* key_value_config);
@@ -44,7 +57,7 @@
bool IsReady() const;
// Returns `DataRate::PlusInfinity` if no BWE can be calculated.
- DataRate GetBandwidthEstimate(DataRate delay_based_limit) const;
+ Result GetLossBasedResult(DataRate delay_based_limit) const;
void SetAcknowledgedBitrate(DataRate acknowledged_bitrate);
void SetBandwidthEstimate(DataRate bandwidth_estimate);
@@ -52,7 +65,8 @@
void UpdateBandwidthEstimate(
rtc::ArrayView<const PacketResult> packet_results,
DataRate delay_based_estimate,
- BandwidthUsage delay_detector_state);
+ BandwidthUsage delay_detector_state,
+ absl::optional<DataRate> probe_bitrate);
private:
struct ChannelParameters {
@@ -95,6 +109,7 @@
double high_loss_rate_threshold = 1.0;
DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity();
double slope_of_bwe_high_loss_func = 1000.0;
+ bool probe_integration_enabled = false;
};
struct Derivatives {
@@ -155,6 +170,10 @@
const std::vector<PacketResult>& packet_feedbacks,
Timestamp at_time);
void UpdateDelayDetector(BandwidthUsage delay_detector_state);
+ bool IsEstimateIncreasingWhenLossLimited(
+ const ChannelParameters& best_candidate);
+ bool IsBandwidthLimitedDueToLoss() const;
+ void SetProbeBitrate(absl::optional<DataRate> probe_bitrate);
absl::optional<DataRate> acknowledged_bitrate_;
absl::optional<Config> config_;
@@ -170,8 +189,9 @@
std::deque<BandwidthUsage> delay_detector_states_;
Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity();
DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity();
- bool limited_due_to_loss_candidate_ = false;
DataRate min_bitrate_ = DataRate::KilobitsPerSec(1);
+ LossBasedState current_state_ = LossBasedState::kDelayBasedEstimate;
+ DataRate probe_bitrate_ = DataRate::PlusInfinity();
};
} // namespace webrtc
diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
index 0e039fd..10b408a 100644
--- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
+++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc
@@ -202,8 +202,10 @@
/*trendline_integration_enabled=*/GetParam()));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
- EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::KilobitsPerSec(100)),
+ EXPECT_EQ(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::KilobitsPerSec(100))
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(100));
}
@@ -214,8 +216,10 @@
/*trendline_integration_enabled=*/GetParam()));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
- EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::KilobitsPerSec(100)),
+ EXPECT_EQ(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::KilobitsPerSec(100))
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(100));
}
@@ -233,13 +237,14 @@
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
EXPECT_TRUE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator
- .GetBandwidthEstimate(/*delay_based_limit=*/DataRate::PlusInfinity())
- .IsFinite());
+ .GetLossBasedResult(/*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate.IsFinite());
}
TEST_P(LossBasedBweV2Test, NoBandwidthEstimateGivenNoInitialization) {
@@ -252,13 +257,14 @@
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator
- .GetBandwidthEstimate(/*delay_based_limit=*/DataRate::PlusInfinity())
- .IsPlusInfinity());
+ .GetLossBasedResult(/*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate.IsPlusInfinity());
}
TEST_P(LossBasedBweV2Test, NoBandwidthEstimateGivenNotEnoughFeedback) {
@@ -286,17 +292,18 @@
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator
- .GetBandwidthEstimate(/*delay_based_limit=*/DataRate::PlusInfinity())
- .IsPlusInfinity());
+ .GetLossBasedResult(/*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate.IsPlusInfinity());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- not_enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ not_enough_feedback, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator
- .GetBandwidthEstimate(/*delay_based_limit=*/DataRate::PlusInfinity())
- .IsPlusInfinity());
+ .GetLossBasedResult(/*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate.IsPlusInfinity());
}
TEST_P(LossBasedBweV2Test,
@@ -317,24 +324,32 @@
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
- EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_NE(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
- EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_EQ(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
- EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_NE(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
}
@@ -359,30 +374,42 @@
loss_based_bandwidth_estimator_2.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
- EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_EQ(loss_based_bandwidth_estimator_1
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(660));
loss_based_bandwidth_estimator_1.SetAcknowledgedBitrate(
- DataRate::KilobitsPerSec(600));
+ DataRate::KilobitsPerSec(900));
- EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_EQ(loss_based_bandwidth_estimator_1
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(660));
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
- EXPECT_NE(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
- loss_based_bandwidth_estimator_2.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()));
+ EXPECT_NE(loss_based_bandwidth_estimator_1
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
+ loss_based_bandwidth_estimator_2
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate);
}
TEST_P(LossBasedBweV2Test,
@@ -400,10 +427,12 @@
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_no_received_packets, DataRate::PlusInfinity(),
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
- EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_EQ(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(100));
}
@@ -429,14 +458,19 @@
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_1, DataRate::PlusInfinity(),
- BandwidthUsage::kBwUnderusing);
- EXPECT_LE(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ BandwidthUsage::kBwUnderusing, /*probe_estimate=*/absl::nullopt);
+ EXPECT_LE(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- EXPECT_LE(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ EXPECT_LE(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
}
@@ -461,18 +495,24 @@
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// If the delay based estimate is infinity, then loss based estimate increases
// and not bounded by delay based estimate.
- EXPECT_GT(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_GT(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// If the delay based estimate is not infinity, then loss based estimate is
// bounded by delay based estimate.
- EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::KilobitsPerSec(500)),
+ EXPECT_EQ(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::KilobitsPerSec(500))
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(500));
}
@@ -500,16 +540,18 @@
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(acked_bitrate);
// Update estimate when network is overusing, and 50% loss rate.
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(),
- BandwidthUsage::kBwOverusing);
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwOverusing,
+ /*probe_estimate=*/absl::nullopt);
// Update estimate again when network is continuously overusing, and 100%
// loss rate.
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(),
- BandwidthUsage::kBwOverusing);
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwOverusing,
+ /*probe_estimate=*/absl::nullopt);
// The estimate bitrate now is backed off based on acked bitrate.
- EXPECT_LE(loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity()),
+ EXPECT_LE(loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate,
acked_bitrate);
}
@@ -529,15 +571,21 @@
DataRate::KilobitsPerSec(300));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_1 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_1 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
// Use the same feedback and check if the estimate is unchanged.
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_2 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_2 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
EXPECT_EQ(estimate_2, estimate_1);
}
@@ -560,14 +608,20 @@
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_1 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_1 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_2 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_2 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
EXPECT_EQ(estimate_2, estimate_1);
}
@@ -590,15 +644,20 @@
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_1 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_1 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_2, DataRate::PlusInfinity(),
- BandwidthUsage::kBwUnderusing);
- DataRate estimate_2 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ BandwidthUsage::kBwUnderusing, /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_2 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
EXPECT_LE(estimate_2, estimate_1);
}
@@ -628,15 +687,20 @@
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(300));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal);
- DataRate estimate_1 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_1, DataRate::PlusInfinity(), BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_1 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, DataRate::PlusInfinity(),
- BandwidthUsage::kBwOverusing);
- DataRate estimate_2 = loss_based_bandwidth_estimator.GetBandwidthEstimate(
- /*delay_based_limit=*/DataRate::PlusInfinity());
+ enough_feedback_2, DataRate::PlusInfinity(), BandwidthUsage::kBwOverusing,
+ /*probe_estimate=*/absl::nullopt);
+ DataRate estimate_2 = loss_based_bandwidth_estimator
+ .GetLossBasedResult(
+ /*delay_based_limit=*/DataRate::PlusInfinity())
+ .bandwidth_estimate;
EXPECT_LT(estimate_2, estimate_1);
}
@@ -658,28 +722,75 @@
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
delay_based_estimate);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
delay_based_estimate);
}
-// After loss based bwe backs off, the next estimate is capped by
-// MaxIncreaseFactor * current estimate.
TEST_P(LossBasedBweV2Test,
IncreaseByMaxIncreaseFactorAfterLossBasedBweBacksOff) {
+ ExplicitKeyValueConfig key_value_config(
+ "WebRTC-Bwe-LossBasedBweV2/"
+ "Enabled:true,CandidateFactors:1.2|1|0.5,AckedRateCandidate:true,"
+ "ObservationWindowSize:2,ObservationDurationLowerBound:200ms,"
+ "InstantUpperBoundBwBalance:10000kbps,"
+ "DelayBasedCandidate:true,MaxIncreaseFactor:1.5,BwRampupUpperBoundFactor:"
+ "2.0/");
+ LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
+ DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
+ DataRate acked_rate = DataRate::KilobitsPerSec(300);
+ loss_based_bandwidth_estimator.SetBandwidthEstimate(
+ DataRate::KilobitsPerSec(600));
+ loss_based_bandwidth_estimator.SetAcknowledgedBitrate(acked_rate);
+
+ // Create some loss to create the loss limited scenario.
std::vector<PacketResult> enough_feedback_1 =
- CreatePacketResultsWithReceivedPackets(
+ CreatePacketResultsWith100pLossRate(
/*first_packet_timestamp=*/Timestamp::Zero());
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+ LossBasedBweV2::Result result_at_loss =
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate);
+
+ // Network recovers after loss.
std::vector<PacketResult> enough_feedback_2 =
CreatePacketResultsWithReceivedPackets(
/*first_packet_timestamp=*/Timestamp::Zero() +
kObservationDurationLowerBound);
+ loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
+ DataRate::KilobitsPerSec(600));
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+
+ LossBasedBweV2::Result result_after_recovery =
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate);
+ EXPECT_EQ(result_after_recovery.bandwidth_estimate,
+ result_at_loss.bandwidth_estimate * 1.5);
+}
+
+// After loss based bwe backs off, the next estimate is capped by
+// a factor of acked bitrate.
+TEST_P(LossBasedBweV2Test,
+ IncreaseByFactorOfAckedBitrateAfterLossBasedBweBacksOff) {
+ std::vector<PacketResult> enough_feedback_1 =
+ CreatePacketResultsWith100pLossRate(
+ /*first_packet_timestamp=*/Timestamp::Zero());
+ std::vector<PacketResult> enough_feedback_2 =
+ CreatePacketResultsWith10pLossRate(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ kObservationDurationLowerBound);
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true,
/*trendline_integration_enabled=*/GetParam()));
@@ -691,22 +802,22 @@
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(300));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal);
- DataRate estimate_1 =
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate);
- // Increase the acknowledged bitrate to make sure that the estimate is not
- // capped too low.
- loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
- DataRate::KilobitsPerSec(5000));
- loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
- // The estimate is capped by current_estimate * kMaxIncreaseFactor because it
- // recently backed off.
+ // Change the acked bitrate to make sure that the estimate is bounded by a
+ // factor of acked bitrate.
+ DataRate acked_bitrate = DataRate::KilobitsPerSec(50);
+ loss_based_bandwidth_estimator.SetAcknowledgedBitrate(acked_bitrate);
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+
+ // The estimate is capped by acked_bitrate * BwRampupUpperBoundFactor.
DataRate estimate_2 =
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate);
- EXPECT_EQ(estimate_2, estimate_1 * kMaxIncreaseFactor);
- EXPECT_LE(estimate_2, delay_based_estimate);
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate;
+ EXPECT_EQ(estimate_2, acked_bitrate * 1.2);
}
// After loss based bwe backs off, the estimate is bounded during the delayed
@@ -735,25 +846,30 @@
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(300));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// Increase the acknowledged bitrate to make sure that the estimate is not
// capped too low.
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(5000));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// The estimate is capped by current_estimate * kMaxIncreaseFactor because
// it recently backed off.
DataRate estimate_2 =
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate);
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate;
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_3, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_3, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// The latest estimate is the same as the previous estimate since the sent
// packets were sent within the DelayedIncreaseWindow.
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
estimate_2);
}
@@ -781,24 +897,29 @@
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(300));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// Increase the acknowledged bitrate to make sure that the estimate is not
// capped too low.
loss_based_bandwidth_estimator.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(5000));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// The estimate is capped by current_estimate * kMaxIncreaseFactor because it
// recently backed off.
DataRate estimate_2 =
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate);
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate;
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
- enough_feedback_3, delay_based_estimate, BandwidthUsage::kBwNormal);
+ enough_feedback_3, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
// The estimate can continue increasing after the DelayedIncreaseWindow.
EXPECT_GE(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
estimate_2);
}
@@ -821,7 +942,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_10p_loss_2 =
CreatePacketResultsWith10pLossRate(
@@ -829,11 +950,12 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// Do not increase the bitrate because inherent loss is less than average loss
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
}
@@ -858,7 +980,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_10p_loss_2 =
CreatePacketResultsWith10pLossRate(
@@ -866,12 +988,13 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// Because LossThresholdOfHighBandwidthPreference is 20%, the average loss is
// 10%, bandwidth estimate should increase.
EXPECT_GT(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
}
@@ -896,7 +1019,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_10p_loss_2 =
CreatePacketResultsWith10pLossRate(
@@ -904,15 +1027,54 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// Because LossThresholdOfHighBandwidthPreference is 5%, the average loss is
// 10%, bandwidth estimate should decrease.
EXPECT_LT(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(600));
}
+TEST_P(LossBasedBweV2Test, UseProbeResultWhenRecoveringFromLoss) {
+ ExplicitKeyValueConfig key_value_config(
+ "WebRTC-Bwe-LossBasedBweV2/"
+ "Enabled:true,CandidateFactors:1.2|1|0.5,AckedRateCandidate:true,"
+ "ObservationWindowSize:2,ObservationDurationLowerBound:200ms,"
+ "InstantUpperBoundBwBalance:10000kbps,"
+ "DelayBasedCandidate:true,MaxIncreaseFactor:1000,"
+ "BwRampupUpperBoundFactor:2.0,ProbeIntegrationEnabled:true/");
+ LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
+ DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
+ DataRate acked_rate = DataRate::KilobitsPerSec(300);
+ loss_based_bandwidth_estimator.SetBandwidthEstimate(
+ DataRate::KilobitsPerSec(600));
+ loss_based_bandwidth_estimator.SetAcknowledgedBitrate(acked_rate);
+
+ // Create some loss to create the loss limited scenario.
+ std::vector<PacketResult> enough_feedback_1 =
+ CreatePacketResultsWith100pLossRate(
+ /*first_packet_timestamp=*/Timestamp::Zero());
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ enough_feedback_1, delay_based_estimate, BandwidthUsage::kBwNormal,
+ /*probe_estimate=*/absl::nullopt);
+
+ // Network recovers after loss.
+ DataRate probe_estimate = DataRate::KilobitsPerSec(300);
+ std::vector<PacketResult> enough_feedback_2 =
+ CreatePacketResultsWithReceivedPackets(
+ /*first_packet_timestamp=*/Timestamp::Zero() +
+ kObservationDurationLowerBound);
+ loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
+ enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
+ probe_estimate);
+
+ LossBasedBweV2::Result result_after_recovery =
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate);
+ EXPECT_EQ(result_after_recovery.bandwidth_estimate, probe_estimate);
+}
+
TEST_P(LossBasedBweV2Test,
StricterBoundUsingHighLossRateThresholdAt10pLossRate) {
ExplicitKeyValueConfig key_value_config(
@@ -934,7 +1096,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_10p_loss_2 =
CreatePacketResultsWith10pLossRate(
@@ -942,12 +1104,13 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_10p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// At 10% loss rate and high loss rate threshold to be 10%, cap the estimate
// to be 500 * 1000-0.1 = 400kbps.
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(400));
}
@@ -972,7 +1135,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_50p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_50p_loss_2 =
CreatePacketResultsWith50pLossRate(
@@ -980,12 +1143,13 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_50p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// At 50% loss rate and high loss rate threshold to be 30%, cap the estimate
// to be the min bitrate.
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(10));
}
@@ -1010,7 +1174,7 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_100p_loss_2 =
CreatePacketResultsWith100pLossRate(
@@ -1018,12 +1182,13 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// At 100% loss rate and high loss rate threshold to be 30%, cap the estimate
// to be the min bitrate.
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(10));
}
@@ -1047,12 +1212,13 @@
/*first_packet_timestamp=*/Timestamp::Zero());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_100p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// Make sure that the estimate is set to min bitrate because of 100% loss
// rate.
EXPECT_EQ(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(10));
// Create some feedbacks with 0 loss rate to simulate network recovering.
@@ -1062,7 +1228,7 @@
kObservationDurationLowerBound);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_0p_loss_1, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
std::vector<PacketResult> enough_feedback_0p_loss_2 =
CreatePacketResultsWithReceivedPackets(
@@ -1070,11 +1236,12 @@
kObservationDurationLowerBound * 2);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_0p_loss_2, delay_based_estimate,
- BandwidthUsage::kBwNormal);
+ BandwidthUsage::kBwNormal, /*probe_estimate=*/absl::nullopt);
// The estimate increases as network recovers.
EXPECT_GT(
- loss_based_bandwidth_estimator.GetBandwidthEstimate(delay_based_estimate),
+ loss_based_bandwidth_estimator.GetLossBasedResult(delay_based_estimate)
+ .bandwidth_estimate,
DataRate::KilobitsPerSec(10));
}
diff --git a/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc b/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
index 12a7d41..0a88e3d 100644
--- a/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
+++ b/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.cc
@@ -229,6 +229,7 @@
bitrate_threshold_(kDefaultBitrateThreshold),
loss_based_bandwidth_estimator_v1_(key_value_config),
loss_based_bandwidth_estimator_v2_(key_value_config),
+ loss_based_state_(LossBasedState::kDelayBasedEstimate),
disable_receiver_limit_caps_only_("Disabled") {
RTC_DCHECK(event_log);
if (BweLossExperimentIsEnabled()) {
@@ -320,6 +321,10 @@
return std::max(min_bitrate_configured_, target);
}
+LossBasedState SendSideBandwidthEstimation::loss_based_state() const {
+ return loss_based_state_;
+}
+
DataRate SendSideBandwidthEstimation::delay_based_limit() const {
return delay_based_limit_;
}
@@ -364,14 +369,16 @@
void SendSideBandwidthEstimation::UpdateLossBasedEstimator(
const TransportPacketsFeedback& report,
- BandwidthUsage delay_detector_state) {
+ BandwidthUsage delay_detector_state,
+ absl::optional<DataRate> probe_bitrate) {
if (LossBasedBandwidthEstimatorV1Enabled()) {
loss_based_bandwidth_estimator_v1_.UpdateLossStatistics(
report.packet_feedbacks, report.feedback_time);
}
if (LossBasedBandwidthEstimatorV2Enabled()) {
loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate(
- report.packet_feedbacks, delay_based_limit_, delay_detector_state);
+ report.packet_feedbacks, delay_based_limit_, delay_detector_state,
+ probe_bitrate);
UpdateEstimate(report.feedback_time);
}
}
@@ -519,10 +526,11 @@
}
if (LossBasedBandwidthEstimatorV2ReadyForUse()) {
- DataRate new_bitrate =
- loss_based_bandwidth_estimator_v2_.GetBandwidthEstimate(
+ LossBasedBweV2::Result result =
+ loss_based_bandwidth_estimator_v2_.GetLossBasedResult(
delay_based_limit_);
- UpdateTargetBitrate(new_bitrate, at_time);
+ loss_based_state_ = result.state;
+ UpdateTargetBitrate(result.bandwidth_estimate, at_time);
return;
}
diff --git a/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h b/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
index 4b60689..fc8b750 100644
--- a/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
+++ b/modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h
@@ -85,6 +85,7 @@
void OnRouteChange();
DataRate target_rate() const;
+ LossBasedState loss_based_state() const;
DataRate delay_based_limit() const;
uint8_t fraction_loss() const { return last_fraction_loss_; }
TimeDelta round_trip_time() const { return last_round_trip_time_; }
@@ -119,7 +120,8 @@
void SetAcknowledgedRate(absl::optional<DataRate> acknowledged_rate,
Timestamp at_time);
void UpdateLossBasedEstimator(const TransportPacketsFeedback& report,
- BandwidthUsage delay_detector_state);
+ BandwidthUsage delay_detector_state,
+ absl::optional<DataRate> probe_bitrate);
private:
friend class GoogCcStatePrinter;
@@ -201,6 +203,7 @@
DataRate bitrate_threshold_;
LossBasedBandwidthEstimation loss_based_bandwidth_estimator_v1_;
LossBasedBweV2 loss_based_bandwidth_estimator_v2_;
+ LossBasedState loss_based_state_;
FieldTrialFlag disable_receiver_limit_caps_only_;
};
} // namespace webrtc