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", ":alr_detector",
":delay_based_bwe", ":delay_based_bwe",
":estimators", ":estimators",
":loss_based_bwe_v2",
":probe_controller", ":probe_controller",
":pushback_controller", ":pushback_controller",
":send_side_bwe", ":send_side_bwe",

View File

@ -27,6 +27,7 @@
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/rtc_event_remote_estimate.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/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/congestion_controller/goog_cc/probe_controller.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.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) { bool IsNotDisabled(const FieldTrialsView* config, absl::string_view key) {
return !absl::StartsWith(config->Lookup(key), "Disabled"); 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 } // namespace
GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config,
@ -614,10 +628,6 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
uint8_t fraction_loss = bandwidth_estimation_->fraction_loss(); uint8_t fraction_loss = bandwidth_estimation_->fraction_loss();
TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time(); TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time();
DataRate loss_based_target_rate = bandwidth_estimation_->target_rate(); 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; DataRate pushback_target_rate = loss_based_target_rate;
BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(),
@ -680,7 +690,9 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
update->target_rate = target_rate_msg; update->target_rate = target_rate_msg;
auto probes = probe_controller_->SetEstimatedBitrate( 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(), update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
probes.begin(), probes.end()); probes.begin(), probes.end());
update->pacer_config = GetPacingRates(at_time); update->pacer_config = GetPacingRates(at_time);

View File

@ -271,13 +271,14 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate( std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
DataRate bitrate, DataRate bitrate,
bool bwe_limited_due_to_packet_loss, BandwidthLimitedCause bandwidth_limited_cause,
Timestamp at_time) { 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) { config_.limit_probe_target_rate_to_loss_bwe) {
state_ = State::kProbingComplete; state_ = State::kProbingComplete;
} }
bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss;
if (bitrate < kBitrateDropThreshold * estimated_bitrate_) { if (bitrate < kBitrateDropThreshold * estimated_bitrate_) {
time_of_last_large_drop_ = at_time; time_of_last_large_drop_ = at_time;
bitrate_before_last_large_drop_ = estimated_bitrate_; 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_ && if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ &&
!estimate.link_capacity_upper.IsZero() && !estimate.link_capacity_upper.IsZero() &&
(estimated_bitrate_ > estimate.link_capacity_upper || (estimated_bitrate_ > estimate.link_capacity_upper ||
bwe_limited_due_to_packet_loss_) && bandwidth_limited_cause_ ==
BandwidthLimitedCause::kLossLimitedBweDecreasing) &&
estimate.link_capacity_upper <= estimate.link_capacity_upper <=
config_.network_state_estimate_drop_down_rate * config_.network_state_estimate_drop_down_rate *
network_estimate_->link_capacity_upper) { network_estimate_->link_capacity_upper) {
@ -390,7 +392,6 @@ void ProbeController::SetNetworkStateEstimate(
void ProbeController::Reset(Timestamp at_time) { void ProbeController::Reset(Timestamp at_time) {
network_available_ = true; network_available_ = true;
bwe_limited_due_to_packet_loss_ = false;
state_ = State::kInit; state_ = State::kInit;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
time_last_probing_initiated_ = Timestamp::Zero(); time_last_probing_initiated_ = Timestamp::Zero();
@ -406,6 +407,7 @@ void ProbeController::Reset(Timestamp at_time) {
bitrate_before_last_large_drop_ = DataRate::Zero(); bitrate_before_last_large_drop_ = DataRate::Zero();
max_total_allocated_bitrate_ = DataRate::Zero(); max_total_allocated_bitrate_ = DataRate::Zero();
send_probe_on_next_process_interval_ = false; send_probe_on_next_process_interval_ = false;
bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited;
} }
bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { 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) || if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) ||
TimeForNetworkStateProbe(at_time)) { TimeForNetworkStateProbe(at_time)) {
return InitiateProbing( DataRate suggested_probe = estimated_bitrate_ * config_.alr_probe_scale;
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true); 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>(); return std::vector<ProbeClusterConfig>();
} }
@ -466,7 +472,8 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
} }
DataRate max_probe_bitrate = max_bitrate_; 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) { config_.limit_probe_target_rate_to_loss_bwe) {
max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_); 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; 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 // This class controls initiation of probing to estimate initial channel
// capacity. There is also support for probing during a session when max // capacity. There is also support for probing during a session when max
// bitrate is adjusted by an application. // bitrate is adjusted by an application.
@ -108,7 +117,7 @@ class ProbeController {
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> SetEstimatedBitrate( ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> SetEstimatedBitrate(
DataRate bitrate, DataRate bitrate,
bool bwe_limited_due_to_packet_loss, BandwidthLimitedCause bandwidth_limited_cause,
Timestamp at_time); Timestamp at_time);
void EnablePeriodicAlrProbing(bool enable); void EnablePeriodicAlrProbing(bool enable);
@ -150,7 +159,6 @@ class ProbeController {
bool TimeForNetworkStateProbe(Timestamp at_time) const; bool TimeForNetworkStateProbe(Timestamp at_time) const;
bool network_available_; bool network_available_;
bool bwe_limited_due_to_packet_loss_;
State state_; State state_;
DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity(); Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity();
@ -175,7 +183,8 @@ class ProbeController {
RtcEventLog* event_log_; RtcEventLog* event_log_;
int32_t next_probe_cluster_id_ = 1; int32_t next_probe_cluster_id_ = 1;
BandwidthLimitedCause bandwidth_limited_cause_ =
BandwidthLimitedCause::kDelayBasedLimited;
ProbeControllerConfig config_; ProbeControllerConfig config_;
}; };

View File

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