Update loss based bwe - probe integration.
Instead of use probe_bitrate as the bandwidth estimate, the change uses probe bitrate as the bandwidth limit. The experiment is not started, so it does not affect production. Bug: webrtc:12707 Change-Id: Iefd8cdfe87983057489e551816bf5d4cb38f7c9f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/296040 Commit-Queue: Diep Bui <diepbp@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39603}
This commit is contained in:
parent
dc90a9c583
commit
980c6bc09f
@ -209,9 +209,8 @@ void LossBasedBweV2::SetMinMaxBitrate(DataRate min_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();
|
||||
}
|
||||
probe_bitrate_ = probe_bitrate.value();
|
||||
last_probe_timestamp_ = last_send_time_most_recent_observation_;
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +228,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
<< "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.";
|
||||
@ -240,6 +239,8 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
return;
|
||||
}
|
||||
|
||||
SetProbeBitrate(probe_bitrate);
|
||||
|
||||
if (!IsValid(current_estimate_.loss_limited_bandwidth)) {
|
||||
RTC_LOG(LS_VERBOSE)
|
||||
<< "The estimator must be initialized before it can be used.";
|
||||
@ -300,24 +301,27 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
|
||||
: 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Use probe bitrate as the estimate limit when probes are requested.
|
||||
if (config_->probe_integration_enabled && IsValid(probe_bitrate_) &&
|
||||
IsRequestingProbe()) {
|
||||
if (last_probe_timestamp_ + config_->probe_expiration >=
|
||||
last_send_time_most_recent_observation_) {
|
||||
best_candidate.loss_limited_bandwidth =
|
||||
std::min(probe_bitrate_, best_candidate.loss_limited_bandwidth);
|
||||
}
|
||||
}
|
||||
|
||||
current_estimate_ = best_candidate;
|
||||
|
||||
if (IsBandwidthLimitedDueToLoss() &&
|
||||
@ -412,6 +416,8 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
"SlopeOfBweHighLossFunc", 1000);
|
||||
FieldTrialParameter<bool> probe_integration_enabled("ProbeIntegrationEnabled",
|
||||
false);
|
||||
FieldTrialParameter<TimeDelta> probe_expiration("ProbeExpiration",
|
||||
TimeDelta::Seconds(10));
|
||||
FieldTrialParameter<bool> bound_by_upper_link_capacity_when_loss_limited(
|
||||
"BoundByUpperLinkCapacityWhenLossLimited", true);
|
||||
FieldTrialParameter<bool> not_use_acked_rate_in_alr("NotUseAckedRateInAlr",
|
||||
@ -449,6 +455,7 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
&use_acked_bitrate_only_when_overusing,
|
||||
¬_increase_if_inherent_loss_less_than_average_loss,
|
||||
&probe_integration_enabled,
|
||||
&probe_expiration,
|
||||
&high_loss_rate_threshold,
|
||||
&bandwidth_cap_at_high_loss_rate,
|
||||
&slope_of_bwe_high_loss_func,
|
||||
@ -514,6 +521,7 @@ absl::optional<LossBasedBweV2::Config> LossBasedBweV2::CreateConfig(
|
||||
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->probe_expiration = probe_expiration.Get();
|
||||
config->bound_by_upper_link_capacity_when_loss_limited =
|
||||
bound_by_upper_link_capacity_when_loss_limited.Get();
|
||||
config->not_use_acked_rate_in_alr = not_use_acked_rate_in_alr.Get();
|
||||
@ -1084,4 +1092,8 @@ bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const {
|
||||
return current_state_ != LossBasedState::kDelayBasedEstimate;
|
||||
}
|
||||
|
||||
bool LossBasedBweV2::IsRequestingProbe() const {
|
||||
return current_state_ == LossBasedState::kIncreasing;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -40,6 +40,8 @@ class LossBasedBweV2 {
|
||||
struct Result {
|
||||
~Result() = default;
|
||||
DataRate bandwidth_estimate = DataRate::Zero();
|
||||
// State is used by goog_cc, which later sends probe requests to probe
|
||||
// controller if state is kIncreasing.
|
||||
LossBasedState state = LossBasedState::kDelayBasedEstimate;
|
||||
};
|
||||
// Creates a disabled `LossBasedBweV2` if the
|
||||
@ -112,6 +114,7 @@ class LossBasedBweV2 {
|
||||
DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity();
|
||||
double slope_of_bwe_high_loss_func = 1000.0;
|
||||
bool probe_integration_enabled = false;
|
||||
TimeDelta probe_expiration = TimeDelta::Zero();
|
||||
bool bound_by_upper_link_capacity_when_loss_limited = false;
|
||||
bool not_use_acked_rate_in_alr = false;
|
||||
};
|
||||
@ -177,6 +180,7 @@ class LossBasedBweV2 {
|
||||
const ChannelParameters& best_candidate);
|
||||
bool IsBandwidthLimitedDueToLoss() const;
|
||||
void SetProbeBitrate(absl::optional<DataRate> probe_bitrate);
|
||||
bool IsRequestingProbe() const;
|
||||
|
||||
absl::optional<DataRate> acknowledged_bitrate_;
|
||||
absl::optional<Config> config_;
|
||||
@ -198,6 +202,7 @@ class LossBasedBweV2 {
|
||||
DataRate probe_bitrate_ = DataRate::PlusInfinity();
|
||||
DataRate delay_based_estimate_ = DataRate::PlusInfinity();
|
||||
DataRate upper_link_capacity_ = DataRate::PlusInfinity();
|
||||
Timestamp last_probe_timestamp_ = Timestamp::MinusInfinity();
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -1148,13 +1148,13 @@ TEST_P(LossBasedBweV2Test,
|
||||
DataRate::KilobitsPerSec(600));
|
||||
}
|
||||
|
||||
TEST_P(LossBasedBweV2Test, UseProbeResultWhenRecoveringFromLoss) {
|
||||
TEST_P(LossBasedBweV2Test, LimitByProbeResultWhenRecoveringFromLoss) {
|
||||
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,"
|
||||
"InstantUpperBoundBwBalance:10000kbps,DelayedIncreaseWindow:100s,"
|
||||
"DelayBasedCandidate:true,MaxIncreaseFactor:1.3,"
|
||||
"BwRampupUpperBoundFactor:2.0,ProbeIntegrationEnabled:true/");
|
||||
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
|
||||
DataRate delay_based_estimate = DataRate::KilobitsPerSec(5000);
|
||||
@ -1172,7 +1172,7 @@ TEST_P(LossBasedBweV2Test, UseProbeResultWhenRecoveringFromLoss) {
|
||||
/*probe_estimate=*/absl::nullopt,
|
||||
/*upper_link_capacity=*/DataRate::PlusInfinity(), /*in_alr=*/false);
|
||||
|
||||
// Network recovers after loss.
|
||||
// Network recovers after loss
|
||||
DataRate probe_estimate = DataRate::KilobitsPerSec(300);
|
||||
std::vector<PacketResult> enough_feedback_2 =
|
||||
CreatePacketResultsWithReceivedPackets(
|
||||
@ -1183,9 +1183,82 @@ TEST_P(LossBasedBweV2Test, UseProbeResultWhenRecoveringFromLoss) {
|
||||
probe_estimate, /*upper_link_capacity=*/DataRate::PlusInfinity(),
|
||||
/*in_alr=*/false);
|
||||
|
||||
for (int i = 2; i < 5; ++i) {
|
||||
enough_feedback_2 = CreatePacketResultsWithReceivedPackets(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound * i);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
|
||||
/*probe_estimate=*/absl::nullopt,
|
||||
/*upper_link_capacity=*/DataRate::PlusInfinity(),
|
||||
/*in_alr=*/false);
|
||||
LossBasedBweV2::Result result_after_recovery =
|
||||
loss_based_bandwidth_estimator.GetLossBasedResult();
|
||||
EXPECT_LE(result_after_recovery.bandwidth_estimate, probe_estimate);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(LossBasedBweV2Test, NotLimitByProbeResultWhenProbeResultIsExpired) {
|
||||
ExplicitKeyValueConfig key_value_config(
|
||||
"WebRTC-Bwe-LossBasedBweV2/"
|
||||
"Enabled:true,CandidateFactors:1.2|1|0.5,AckedRateCandidate:true,"
|
||||
"ObservationWindowSize:2,ObservationDurationLowerBound:200ms,"
|
||||
"InstantUpperBoundBwBalance:10000kbps,DelayedIncreaseWindow:100s,"
|
||||
"DelayBasedCandidate:true,MaxIncreaseFactor:1.3,"
|
||||
"BwRampupUpperBoundFactor:2.0,ProbeIntegrationEnabled:true,"
|
||||
"ProbeExpiration:10s/");
|
||||
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,
|
||||
/*upper_link_capacity=*/DataRate::PlusInfinity(), /*in_alr=*/false);
|
||||
|
||||
// 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, /*upper_link_capacity=*/DataRate::PlusInfinity(),
|
||||
/*in_alr=*/false);
|
||||
|
||||
for (int i = 2; i < 5; ++i) {
|
||||
enough_feedback_2 = CreatePacketResultsWithReceivedPackets(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound * i);
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_2, delay_based_estimate, BandwidthUsage::kBwNormal,
|
||||
/*probe_estimate=*/absl::nullopt,
|
||||
/*upper_link_capacity=*/DataRate::PlusInfinity(),
|
||||
/*in_alr=*/false);
|
||||
}
|
||||
|
||||
std::vector<PacketResult> enough_feedback_3 =
|
||||
CreatePacketResultsWithReceivedPackets(
|
||||
/*first_packet_timestamp=*/Timestamp::Zero() +
|
||||
kObservationDurationLowerBound + TimeDelta::Seconds(11));
|
||||
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
|
||||
enough_feedback_3, delay_based_estimate, BandwidthUsage::kBwNormal,
|
||||
/*probe_estimate=*/absl::nullopt,
|
||||
/*upper_link_capacity=*/DataRate::PlusInfinity(),
|
||||
/*in_alr=*/false);
|
||||
|
||||
// Probe result is expired after 10s.
|
||||
LossBasedBweV2::Result result_after_recovery =
|
||||
loss_based_bandwidth_estimator.GetLossBasedResult();
|
||||
EXPECT_EQ(result_after_recovery.bandwidth_estimate, probe_estimate);
|
||||
EXPECT_GT(result_after_recovery.bandwidth_estimate, probe_estimate);
|
||||
}
|
||||
|
||||
// If BoundByUpperLinkCapacityWhenLossLimited is enabled, the estimate is
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user