Probe when network is loss limited.

Trigger probes next process intervals if the loss based current state is either increasing or decreasing. 0/ first probe at the loss based estimate. 1/ if increasing: allow further probing. 2/ if decreasing: not allow further probing.


Bug: webrtc:12707
Change-Id: I4e99edcbe4e2c315e8498ffb7fb2e589cdb4e666
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/279041
Commit-Queue: Diep Bui <diepbp@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38395}
This commit is contained in:
Diep Bui
2022-10-13 15:52:14 +00:00
committed by WebRTC LUCI CQ
parent 2b5923c3d0
commit aa71259b06
5 changed files with 303 additions and 99 deletions

View File

@ -27,6 +27,7 @@ rtc_library("goog_cc") {
":alr_detector",
":delay_based_bwe",
":estimators",
":loss_based_bwe_v2",
":probe_controller",
":pushback_controller",
":send_side_bwe",

View File

@ -27,6 +27,7 @@
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
#include "modules/congestion_controller/goog_cc/alr_detector.h"
#include "modules/congestion_controller/goog_cc/loss_based_bwe_v2.h"
#include "modules/congestion_controller/goog_cc/probe_controller.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
@ -59,6 +60,19 @@ bool IsEnabled(const FieldTrialsView* config, absl::string_view key) {
bool IsNotDisabled(const FieldTrialsView* config, absl::string_view key) {
return !absl::StartsWith(config->Lookup(key), "Disabled");
}
BandwidthLimitedCause GetBandwidthLimitedCause(
LossBasedState loss_based_state) {
switch (loss_based_state) {
case LossBasedState::kDecreasing:
return BandwidthLimitedCause::kLossLimitedBweDecreasing;
case LossBasedState::kIncreasing:
return BandwidthLimitedCause::kLossLimitedBweIncreasing;
default:
return BandwidthLimitedCause::kDelayBasedLimited;
}
}
} // namespace
GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config,
@ -614,10 +628,6 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
uint8_t fraction_loss = bandwidth_estimation_->fraction_loss();
TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time();
DataRate loss_based_target_rate = bandwidth_estimation_->target_rate();
bool bwe_limited_due_to_packet_loss =
loss_based_target_rate.IsFinite() &&
bandwidth_estimation_->delay_based_limit().IsFinite() &&
loss_based_target_rate < bandwidth_estimation_->delay_based_limit();
DataRate pushback_target_rate = loss_based_target_rate;
BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(),
@ -680,7 +690,9 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
update->target_rate = target_rate_msg;
auto probes = probe_controller_->SetEstimatedBitrate(
loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time);
loss_based_target_rate,
GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()),
at_time);
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
probes.begin(), probes.end());
update->pacer_config = GetPacingRates(at_time);

View File

@ -271,13 +271,14 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
DataRate bitrate,
bool bwe_limited_due_to_packet_loss,
BandwidthLimitedCause bandwidth_limited_cause,
Timestamp at_time) {
if (bwe_limited_due_to_packet_loss != bwe_limited_due_to_packet_loss_ &&
bandwidth_limited_cause_ = bandwidth_limited_cause;
if (bandwidth_limited_cause_ ==
BandwidthLimitedCause::kLossLimitedBweDecreasing &&
config_.limit_probe_target_rate_to_loss_bwe) {
state_ = State::kProbingComplete;
}
bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss;
if (bitrate < kBitrateDropThreshold * estimated_bitrate_) {
time_of_last_large_drop_ = at_time;
bitrate_before_last_large_drop_ = estimated_bitrate_;
@ -378,7 +379,8 @@ void ProbeController::SetNetworkStateEstimate(
if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ &&
!estimate.link_capacity_upper.IsZero() &&
(estimated_bitrate_ > estimate.link_capacity_upper ||
bwe_limited_due_to_packet_loss_) &&
bandwidth_limited_cause_ ==
BandwidthLimitedCause::kLossLimitedBweDecreasing) &&
estimate.link_capacity_upper <=
config_.network_state_estimate_drop_down_rate *
network_estimate_->link_capacity_upper) {
@ -390,7 +392,6 @@ void ProbeController::SetNetworkStateEstimate(
void ProbeController::Reset(Timestamp at_time) {
network_available_ = true;
bwe_limited_due_to_packet_loss_ = false;
state_ = State::kInit;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
time_last_probing_initiated_ = Timestamp::Zero();
@ -406,6 +407,7 @@ void ProbeController::Reset(Timestamp at_time) {
bitrate_before_last_large_drop_ = DataRate::Zero();
max_total_allocated_bitrate_ = DataRate::Zero();
send_probe_on_next_process_interval_ = false;
bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited;
}
bool ProbeController::TimeForAlrProbe(Timestamp at_time) const {
@ -445,8 +447,12 @@ std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
}
if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) ||
TimeForNetworkStateProbe(at_time)) {
return InitiateProbing(
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
DataRate suggested_probe = estimated_bitrate_ * config_.alr_probe_scale;
if (config_.limit_probe_target_rate_to_loss_bwe &&
bandwidth_limited_cause_ != BandwidthLimitedCause::kDelayBasedLimited) {
suggested_probe = estimated_bitrate_;
}
return InitiateProbing(at_time, {suggested_probe}, true);
}
return std::vector<ProbeClusterConfig>();
}
@ -466,7 +472,8 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
}
DataRate max_probe_bitrate = max_bitrate_;
if (bwe_limited_due_to_packet_loss_ &&
if (bandwidth_limited_cause_ ==
BandwidthLimitedCause::kLossLimitedBweDecreasing &&
config_.limit_probe_target_rate_to_loss_bwe) {
max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_);
}

View File

@ -79,6 +79,15 @@ struct ProbeControllerConfig {
FieldTrialParameter<double> skip_if_estimate_larger_than_fraction_of_max;
};
// Reason that bandwidth estimate is limited. Bandwidth estimate can be limited
// by either delay based bwe, or loss based bwe when it increases/decreases the
// estimate.
enum class BandwidthLimitedCause {
kLossLimitedBweIncreasing = 0,
kLossLimitedBweDecreasing = 1,
kDelayBasedLimited = 2
};
// This class controls initiation of probing to estimate initial channel
// capacity. There is also support for probing during a session when max
// bitrate is adjusted by an application.
@ -108,7 +117,7 @@ class ProbeController {
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> SetEstimatedBitrate(
DataRate bitrate,
bool bwe_limited_due_to_packet_loss,
BandwidthLimitedCause bandwidth_limited_cause,
Timestamp at_time);
void EnablePeriodicAlrProbing(bool enable);
@ -150,7 +159,6 @@ class ProbeController {
bool TimeForNetworkStateProbe(Timestamp at_time) const;
bool network_available_;
bool bwe_limited_due_to_packet_loss_;
State state_;
DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity();
@ -175,7 +183,8 @@ class ProbeController {
RtcEventLog* event_log_;
int32_t next_probe_cluster_id_ = 1;
BandwidthLimitedCause bandwidth_limited_cause_ =
BandwidthLimitedCause::kDelayBasedLimited;
ProbeControllerConfig config_;
};

View File

@ -102,7 +102,7 @@ TEST(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
{.at_time = fixture.CurrentTime(), .network_available = false});
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
probes = probe_controller->OnNetworkAvailability(
{.at_time = fixture.CurrentTime(), .network_available = true});
EXPECT_GE(probes.size(), 2u);
@ -138,7 +138,7 @@ TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
// Long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetBitrates(
@ -156,18 +156,19 @@ TEST(ProbeControllerTest, ProbesOnMaxBitrateIncreaseOnlyWhenInAlr) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate - DataRate::BitsPerSec(1),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
BandwidthLimitedCause::kDelayBasedLimited, fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(1), fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probes.at(0).target_data_rate, kMaxBitrate);
// Do not probe when not in alr.
probe_controller->SetAlrStartTimeMs(absl::nullopt);
@ -185,11 +186,11 @@ TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
// Long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
@ -209,13 +210,13 @@ TEST(ProbeControllerTest, TestExponentialProbing) {
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.7 * 6 * kStartBitrate = 1260.
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1000),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
DataRate::BitsPerSec(1000), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1800),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
}
@ -231,9 +232,9 @@ TEST(ProbeControllerTest, TestExponentialProbingTimeout) {
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1800),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
DataRate::BitsPerSec(1800), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, RequestProbeInAlr) {
@ -244,15 +245,15 @@ TEST(ProbeControllerTest, RequestProbeInAlr) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_GE(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
@ -267,15 +268,15 @@ TEST(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrEndedTimeout - TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
@ -292,19 +293,19 @@ TEST(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrEndedTimeout + TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
@ -315,18 +316,18 @@ TEST(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
fixture.AdvanceTime(kBitrateDropTimeout + TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, PeriodicProbing) {
@ -338,8 +339,8 @@ TEST(ProbeControllerTest, PeriodicProbing) {
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
Timestamp start_time = fixture.CurrentTime();
@ -351,26 +352,26 @@ TEST(ProbeControllerTest, PeriodicProbing) {
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// The following probe should be sent at 10s into ALR.
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(4));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, PeriodicProbingAfterReset) {
@ -389,7 +390,7 @@ TEST(ProbeControllerTest, PeriodicProbingAfterReset) {
probes = probe_controller->Process(fixture.CurrentTime());
// Since bitrates are not yet set, no probe is sent event though we are in ALR
// mode.
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
@ -413,15 +414,15 @@ TEST(ProbeControllerTest, TestExponentialProbingOverflow) {
fixture.CurrentTime());
// Verify that probe bitrate is capped at the specified max bitrate.
probes = probe_controller->SetEstimatedBitrate(
60 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
60 * kMbpsMultiplier, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 100 * kMbpsMultiplier);
// Verify that repeated probes aren't sent.
probes = probe_controller->SetEstimatedBitrate(
100 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
100 * kMbpsMultiplier, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, TestAllocatedBitrateCap) {
@ -440,7 +441,7 @@ TEST(ProbeControllerTest, TestAllocatedBitrateCap) {
DataRate estimated_bitrate = kMaxBitrate / 10;
probes = probe_controller->SetEstimatedBitrate(
estimated_bitrate, /*bwe_limited_due_to_packet_loss=*/false,
estimated_bitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Set a max allocated bitrate below the current estimate.
@ -486,13 +487,13 @@ TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.8 * 5 * kStartBitrateBps = 1200.
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1100),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(1100), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(1250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
DataRate::BitsPerSec(1250), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 3 * 1250);
@ -516,7 +517,7 @@ TEST(ProbeControllerTest, LimitAlrProbeWhenLossBasedBweLimited) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
@ -525,20 +526,12 @@ TEST(ProbeControllerTest, LimitAlrProbeWhenLossBasedBweLimited) {
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss*/ true,
fixture.CurrentTime());
DataRate::BitsPerSec(500),
BandwidthLimitedCause::kLossLimitedBweDecreasing, fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, DataRate::BitsPerSec(500));
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(!probes.empty());
EXPECT_GT(probes[0].target_data_rate, DataRate::BitsPerSec(500));
}
TEST(ProbeControllerTest, PeriodicProbeAtUpperNetworkStateEstimate) {
@ -550,7 +543,7 @@ TEST(ProbeControllerTest, PeriodicProbeAtUpperNetworkStateEstimate) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(5000), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::BitsPerSec(5000), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
@ -578,7 +571,7 @@ TEST(ProbeControllerTest,
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
@ -589,20 +582,20 @@ TEST(ProbeControllerTest,
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/true,
fixture.CurrentTime());
DataRate::BitsPerSec(500),
BandwidthLimitedCause::kLossLimitedBweDecreasing, fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(!probes.empty());
ASSERT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, DataRate::BitsPerSec(500));
probes = probe_controller->SetEstimatedBitrate(
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::BitsPerSec(500), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_TRUE(!probes.empty());
ASSERT_FALSE(probes.empty());
EXPECT_GT(probes[0].target_data_rate, DataRate::BitsPerSec(500));
}
@ -615,7 +608,7 @@ TEST(ProbeControllerTest, AlrProbesLimitedByNetworkStateEstimate) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::KilobitsPerSec(6), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::KilobitsPerSec(6), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
@ -643,7 +636,7 @@ TEST(ProbeControllerTest, CanSetLongerProbeDurationAfterNetworkStateEstimate) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
DataRate::KilobitsPerSec(5), /*bwe_limited_due_to_packet_loss=*/false,
DataRate::KilobitsPerSec(5), BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
EXPECT_LT(probes[0].target_duration, TimeDelta::Millis(100));
@ -667,7 +660,7 @@ TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateIncrease) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
@ -706,7 +699,7 @@ TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDrop) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
@ -746,7 +739,7 @@ TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDropLossLimited) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
@ -761,7 +754,7 @@ TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDropLossLimited) {
// Loss limited.
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate / 3, /*bwe_limited_due_to_packet_loss=*/true,
kStartBitrate / 3, BandwidthLimitedCause::kLossLimitedBweDecreasing,
fixture.CurrentTime());
// If NetworkState decrease dramatically, expect a probe to be sent.
// But limited to loss based estimate.
@ -772,7 +765,189 @@ TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateDropLossLimited) {
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate / 3);
}
TEST(ProbeControllerTest, DontProbeFurtherWhenLossLimited) {
TEST(ProbeControllerTest,
ProbesAtEstimatedBitrateWhenInAlrIfLossBasedIncreasing) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes.at(0).target_data_rate, kStartBitrate);
}
TEST(ProbeControllerTest, ProbesFurtherWhenInAlrIfLossBasedIncreasing) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes.at(0).target_data_rate, kStartBitrate);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, 2 * kStartBitrate);
}
TEST(ProbeControllerTest, NotProbeFurtherWhenInAlrIfLossBasedDecreases) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,network_state_drop_down_rate:0.5,limit_probe_"
"target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweDecreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes.at(0).target_data_rate, kStartBitrate);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweDecreasing,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, NotProbeIfLossBasedIncreasingOutsideAlr) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->EnablePeriodicAlrProbing(true);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
TEST(ProbeControllerTest, ProbeFurtherWhenLossBasedIncreases) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 5 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
DataRate probe_target_rate = probes[0].target_data_rate;
EXPECT_LT(probe_target_rate, state_estimate.link_capacity_upper);
// Expect that more probes are sent if BWE is increasing.
probes = probe_controller->SetEstimatedBitrate(
probe_target_rate, BandwidthLimitedCause::kLossLimitedBweIncreasing,
fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, 2 * probe_target_rate);
}
TEST(ProbeControllerTest, ProbeFurtherWhenLossBasedIsSameAsDelayBasedEstimate) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_FALSE(probes.empty());
// Need to wait at least one second before process can trigger a new probe.
fixture.AdvanceTime(TimeDelta::Millis(1100));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = 5 * kStartBitrate;
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
DataRate probe_target_rate = probes[0].target_data_rate;
EXPECT_LT(probe_target_rate, state_estimate.link_capacity_upper);
// Expect that more probes are sent if BWE is the same as delay based
// estimate.
probes = probe_controller->SetEstimatedBitrate(
probe_target_rate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, 2 * probe_target_rate);
}
TEST(ProbeControllerTest, DontProbeFurtherWhenLossBasedDecreases) {
ProbeControllerFixture fixture(
"WebRTC-Bwe-ProbingConfiguration/"
"network_state_interval:5s,limit_probe_target_rate_to_loss_bwe:true/");
@ -797,8 +972,8 @@ TEST(ProbeControllerTest, DontProbeFurtherWhenLossLimited) {
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
// Expect that no more probes are sent immediately if BWE is loss limited.
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate, /*bwe_limited_due_to_packet_loss=*/true,
fixture.CurrentTime());
probes[0].target_data_rate,
BandwidthLimitedCause::kLossLimitedBweDecreasing, fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
@ -827,7 +1002,7 @@ TEST(ProbeControllerTest, ProbeFurtherWhenDelayBasedLimited) {
EXPECT_LT(probes[0].target_data_rate, state_estimate.link_capacity_upper);
// Since the probe was successfull, expect to continue probing.
probes = probe_controller->SetEstimatedBitrate(
probes[0].target_data_rate, /*bwe_limited_due_to_packet_loss=*/false,
probes[0].target_data_rate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
@ -845,7 +1020,7 @@ TEST(ProbeControllerTest, SkipAlrProbeIfEstimateLargerThanMaxProbe) {
ASSERT_FALSE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
@ -873,7 +1048,7 @@ TEST(ProbeControllerTest, SkipNetworkStateProbeIfEstimateLargerThanMaxProbe) {
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = 2 * kMaxBitrate});
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
@ -895,7 +1070,7 @@ TEST(ProbeControllerTest, SendsProbeIfNetworkStateEstimateLowerThanMaxProbe) {
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = 2 * kMaxBitrate});
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kMaxBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
@ -919,7 +1094,7 @@ TEST(ProbeControllerTest, DontSendProbeIfNetworkStateEstimateIsZero) {
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
kStartBitrate, BandwidthLimitedCause::kDelayBasedLimited,
fixture.CurrentTime());
probe_controller->SetNetworkStateEstimate(
{.link_capacity_upper = kStartBitrate});