Replace int with Timestamp and DataRate in ProbeController

Replace most instances. SetAlrStartTime is set as is should be cleaned up together with the callsite.

Bug: webrtc:14404
Change-Id: I8ec532828ef665afbf08f0943465a429ab40baa1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/273300
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37932}
This commit is contained in:
Per Kjellander 2022-08-29 15:22:15 +02:00 committed by WebRTC LUCI CQ
parent 590a965a9f
commit d6e9749942
5 changed files with 416 additions and 417 deletions

View File

@ -262,6 +262,7 @@ rtc_library("probe_controller") {
"../../../api/rtc_event_log",
"../../../api/transport:network_control",
"../../../api/units:data_rate",
"../../../api/units:data_size",
"../../../api/units:time_delta",
"../../../api/units:timestamp",
"../../../logging:rtc_event_bwe",

View File

@ -24,6 +24,7 @@
#include "absl/strings/match.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#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/probe_controller.h"
@ -51,15 +52,6 @@ constexpr float kDefaultPaceMultiplier = 2.5f;
// below the current throughput estimate to drain the network queues.
constexpr double kProbeDropThroughputFraction = 0.85;
int64_t GetBpsOrDefault(const absl::optional<DataRate>& rate,
int64_t fallback_bps) {
if (rate && rate->IsFinite()) {
return rate->bps();
} else {
return fallback_bps;
}
}
bool IsEnabled(const FieldTrialsView* config, absl::string_view key) {
return absl::StartsWith(config->Lookup(key), "Enabled");
}
@ -173,7 +165,7 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_,
network_state_predictor_.get()));
bandwidth_estimation_->OnRouteChange();
probe_controller_->Reset(msg.at_time.ms());
probe_controller_->Reset(msg.at_time);
NetworkControlUpdate update;
update.probe_cluster_configs = ResetConstraints(msg.constraints);
MaybeTriggerOnNetworkChanged(&update, msg.at_time);
@ -196,7 +188,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
initial_config_->stream_based_config.max_total_allocated_bitrate;
if (total_bitrate) {
auto probes = probe_controller_->OnMaxTotalAllocatedBitrate(
total_bitrate->bps(), msg.at_time.ms());
*total_bitrate, msg.at_time);
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
probes.begin(), probes.end());
@ -213,7 +205,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
alr_detector_->GetApplicationLimitedRegionStartTime();
probe_controller_->SetAlrStartTimeMs(start_time_ms);
auto probes = probe_controller_->Process(msg.at_time.ms());
auto probes = probe_controller_->Process(msg.at_time);
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
probes.begin(), probes.end());
@ -299,9 +291,9 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
if (rate_control_settings_.TriggerProbeOnMaxAllocatedBitrateChange()) {
update.probe_cluster_configs =
probe_controller_->OnMaxTotalAllocatedBitrate(
msg.max_total_allocated_bitrate->bps(), msg.at_time.ms());
*msg.max_total_allocated_bitrate, msg.at_time);
} else {
probe_controller_->SetMaxBitrate(msg.max_total_allocated_bitrate->bps());
probe_controller_->SetMaxBitrate(*msg.max_total_allocated_bitrate);
}
max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate;
}
@ -373,8 +365,8 @@ std::vector<ProbeClusterConfig> GoogCcNetworkController::ResetConstraints(
delay_based_bwe_->SetMinBitrate(min_data_rate_);
return probe_controller_->SetBitrates(
min_data_rate_.bps(), GetBpsOrDefault(starting_rate_, -1),
max_data_rate_.bps_or(-1), new_constraints.at_time.ms());
min_data_rate_, starting_rate_.value_or(DataRate::Zero()), max_data_rate_,
new_constraints.at_time);
}
NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
@ -564,7 +556,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
if (recovered_from_overuse) {
probe_controller_->SetAlrStartTimeMs(alr_start_time);
auto probes = probe_controller_->RequestProbe(report.feedback_time.ms());
auto probes = probe_controller_->RequestProbe(report.feedback_time);
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
probes.begin(), probes.end());
}
@ -682,8 +674,7 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
update->target_rate = target_rate_msg;
auto probes = probe_controller_->SetEstimatedBitrate(
loss_based_target_rate.bps(), bwe_limited_due_to_packet_loss,
at_time.ms());
loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time);
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
probes.begin(), probes.end());
update->pacer_config = GetPacingRates(at_time);

View File

@ -18,6 +18,7 @@
#include "absl/strings/match.h"
#include "absl/types/optional.h"
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
@ -31,32 +32,28 @@ namespace webrtc {
namespace {
// Maximum waiting time from the time of initiating probing to getting
// the measured results back.
constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000;
// Value of `min_bitrate_to_probe_further_bps_` that indicates
// further probing is disabled.
constexpr int kExponentialProbingDisabled = 0;
constexpr TimeDelta kMaxWaitingTimeForProbingResult = TimeDelta::Seconds(1);
// Default probing bitrate limit. Applied only when the application didn't
// specify max bitrate.
constexpr int64_t kDefaultMaxProbingBitrateBps = 5000000;
constexpr DataRate kDefaultMaxProbingBitrate = DataRate::KilobitsPerSec(5000);
// If the bitrate drops to a factor `kBitrateDropThreshold` or lower
// and we recover within `kBitrateDropTimeoutMs`, then we'll send
// a probe at a fraction `kProbeFractionAfterDrop` of the original bitrate.
constexpr double kBitrateDropThreshold = 0.66;
constexpr int kBitrateDropTimeoutMs = 5000;
constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds(5);
constexpr double kProbeFractionAfterDrop = 0.85;
// Timeout for probing after leaving ALR. If the bitrate drops significantly,
// (as determined by the delay based estimator) and we leave ALR, then we will
// send a probe if we recover within `kLeftAlrTimeoutMs` ms.
constexpr int kAlrEndedTimeoutMs = 3000;
constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds(3);
// The expected uncertainty of probe result (as a fraction of the target probe
// This is a limit on how often probing can be done when there is a BW
// drop detected in ALR.
constexpr int64_t kMinTimeBetweenAlrProbesMs = 5000;
constexpr TimeDelta kMinTimeBetweenAlrProbes = TimeDelta::Seconds(5);
// bitrate). Used to avoid probing if the probe bitrate is close to our current
// estimate.
@ -73,11 +70,10 @@ void MaybeLogProbeClusterCreated(RtcEventLog* event_log,
return;
}
size_t min_bytes = static_cast<int32_t>(probe.target_data_rate.bps() *
probe.target_duration.ms() / 8000);
DataSize min_data_size = probe.target_data_rate * probe.target_duration;
event_log->Log(std::make_unique<RtcEventProbeClusterCreated>(
probe.id, probe.target_data_rate.bps(), probe.target_probe_count,
min_bytes));
min_data_size.bytes()));
}
} // namespace
@ -138,32 +134,33 @@ ProbeController::ProbeController(const FieldTrialsView* key_value_config,
"Enabled")),
event_log_(event_log),
config_(ProbeControllerConfig(key_value_config)) {
Reset(0);
Reset(Timestamp::Zero());
}
ProbeController::~ProbeController() {}
std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
int64_t min_bitrate_bps,
int64_t start_bitrate_bps,
int64_t max_bitrate_bps,
int64_t at_time_ms) {
if (start_bitrate_bps > 0) {
start_bitrate_bps_ = start_bitrate_bps;
estimated_bitrate_bps_ = start_bitrate_bps;
} else if (start_bitrate_bps_ == 0) {
start_bitrate_bps_ = min_bitrate_bps;
DataRate min_bitrate,
DataRate start_bitrate,
DataRate max_bitrate,
Timestamp at_time) {
if (start_bitrate > DataRate::Zero()) {
start_bitrate_ = start_bitrate;
estimated_bitrate_ = start_bitrate;
} else if (start_bitrate_.IsZero()) {
start_bitrate_ = min_bitrate;
}
// The reason we use the variable `old_max_bitrate_pbs` is because we
// need to set `max_bitrate_bps_` before we call InitiateProbing.
int64_t old_max_bitrate_bps = max_bitrate_bps_;
max_bitrate_bps_ = max_bitrate_bps;
// need to set `max_bitrate_` before we call InitiateProbing.
DataRate old_max_bitrate = max_bitrate_;
max_bitrate_ =
max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate;
switch (state_) {
case State::kInit:
if (network_available_)
return InitiateExponentialProbing(at_time_ms);
return InitiateExponentialProbing(at_time);
break;
case State::kWaitingForProbingResult:
@ -172,21 +169,20 @@ std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
case State::kProbingComplete:
// If the new max bitrate is higher than both the old max bitrate and the
// estimate then initiate probing.
if (estimated_bitrate_bps_ != 0 &&
old_max_bitrate_bps < max_bitrate_bps_ &&
estimated_bitrate_bps_ < max_bitrate_bps_) {
if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ &&
estimated_bitrate_ < max_bitrate_) {
// The assumption is that if we jump more than 20% in the bandwidth
// estimate or if the bandwidth estimate is within 90% of the new
// max bitrate then the probing attempt was successful.
mid_call_probing_succcess_threshold_ =
std::min(estimated_bitrate_bps_ * 1.2, max_bitrate_bps_ * 0.9);
std::min(estimated_bitrate_ * 1.2, max_bitrate_ * 0.9);
mid_call_probing_waiting_for_result_ = true;
mid_call_probing_bitrate_bps_ = max_bitrate_bps_;
mid_call_probing_bitrate_ = max_bitrate_;
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated",
max_bitrate_bps_ / 1000);
max_bitrate_.kbps());
return InitiateProbing(at_time_ms, {max_bitrate_bps_}, false);
return InitiateProbing(at_time, {max_bitrate_}, false);
}
break;
}
@ -194,37 +190,35 @@ std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
}
std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
int64_t max_total_allocated_bitrate,
int64_t at_time_ms) {
const bool in_alr = alr_start_time_ms_.has_value();
DataRate max_total_allocated_bitrate,
Timestamp at_time) {
const bool in_alr = alr_start_time_.has_value();
const bool allow_allocation_probe = in_alr;
if (state_ == State::kProbingComplete &&
max_total_allocated_bitrate != max_total_allocated_bitrate_ &&
estimated_bitrate_bps_ != 0 &&
(max_bitrate_bps_ <= 0 || estimated_bitrate_bps_ < max_bitrate_bps_) &&
estimated_bitrate_bps_ < max_total_allocated_bitrate &&
estimated_bitrate_ < max_bitrate_ &&
estimated_bitrate_ < max_total_allocated_bitrate &&
allow_allocation_probe) {
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
if (!config_.first_allocation_probe_scale)
return std::vector<ProbeClusterConfig>();
DataRate first_probe_rate =
DataRate::BitsPerSec(max_total_allocated_bitrate) *
config_.first_allocation_probe_scale.Value();
DataRate first_probe_rate = max_total_allocated_bitrate *
config_.first_allocation_probe_scale.Value();
DataRate probe_cap = config_.allocation_probe_max.Get();
first_probe_rate = std::min(first_probe_rate, probe_cap);
std::vector<int64_t> probes = {first_probe_rate.bps()};
std::vector<DataRate> probes = {first_probe_rate};
if (config_.second_allocation_probe_scale) {
DataRate second_probe_rate =
DataRate::BitsPerSec(max_total_allocated_bitrate) *
max_total_allocated_bitrate *
config_.second_allocation_probe_scale.Value();
second_probe_rate = std::min(second_probe_rate, probe_cap);
if (second_probe_rate > first_probe_rate)
probes.push_back(second_probe_rate.bps());
probes.push_back(second_probe_rate);
}
return InitiateProbing(at_time_ms, probes,
return InitiateProbing(at_time, probes,
config_.allocation_allow_further_probing.Get());
}
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
@ -237,65 +231,61 @@ std::vector<ProbeClusterConfig> ProbeController::OnNetworkAvailability(
if (!network_available_ && state_ == State::kWaitingForProbingResult) {
state_ = State::kProbingComplete;
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
}
if (network_available_ && state_ == State::kInit && start_bitrate_bps_ > 0)
return InitiateExponentialProbing(msg.at_time.ms());
if (network_available_ && state_ == State::kInit && !start_bitrate_.IsZero())
return InitiateExponentialProbing(msg.at_time);
return std::vector<ProbeClusterConfig>();
}
std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
int64_t at_time_ms) {
Timestamp at_time) {
RTC_DCHECK(network_available_);
RTC_DCHECK(state_ == State::kInit);
RTC_DCHECK_GT(start_bitrate_bps_, 0);
RTC_DCHECK_GT(start_bitrate_, DataRate::Zero());
// When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
// 1.2 Mbps to continue probing.
std::vector<int64_t> probes = {static_cast<int64_t>(
config_.first_exponential_probe_scale * start_bitrate_bps_)};
std::vector<DataRate> probes = {config_.first_exponential_probe_scale *
start_bitrate_};
if (config_.second_exponential_probe_scale) {
probes.push_back(config_.second_exponential_probe_scale.Value() *
start_bitrate_bps_);
start_bitrate_);
}
return InitiateProbing(at_time_ms, probes, true);
return InitiateProbing(at_time, probes, true);
}
std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
int64_t bitrate_bps,
DataRate bitrate,
bool bwe_limited_due_to_packet_loss,
int64_t at_time_ms) {
Timestamp at_time) {
bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss;
if (bitrate_bps < kBitrateDropThreshold * estimated_bitrate_bps_) {
time_of_last_large_drop_ms_ = at_time_ms;
bitrate_before_last_large_drop_bps_ = estimated_bitrate_bps_;
if (bitrate < kBitrateDropThreshold * estimated_bitrate_) {
time_of_last_large_drop_ = at_time;
bitrate_before_last_large_drop_ = estimated_bitrate_;
}
estimated_bitrate_bps_ = bitrate_bps;
estimated_bitrate_ = bitrate;
if (mid_call_probing_waiting_for_result_ &&
bitrate_bps >= mid_call_probing_succcess_threshold_) {
bitrate >= mid_call_probing_succcess_threshold_) {
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Success",
mid_call_probing_bitrate_bps_ / 1000);
mid_call_probing_bitrate_.kbps());
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.ProbedKbps",
bitrate_bps / 1000);
bitrate.kbps());
mid_call_probing_waiting_for_result_ = false;
}
std::vector<ProbeClusterConfig> pending_probes;
if (state_ == State::kWaitingForProbingResult) {
// Continue probing if probing results indicate channel has greater
// capacity.
RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate_bps
RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate
<< " Minimum to probe further: "
<< min_bitrate_to_probe_further_bps_;
<< min_bitrate_to_probe_further_;
if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
bitrate_bps > min_bitrate_to_probe_further_bps_) {
if (bitrate > min_bitrate_to_probe_further_) {
pending_probes = InitiateProbing(
at_time_ms,
{static_cast<int64_t>(config_.further_exponential_probe_scale *
bitrate_bps)},
true);
at_time, {config_.further_exponential_probe_scale * bitrate}, true);
}
}
@ -308,50 +298,54 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) {
void ProbeController::SetAlrStartTimeMs(
absl::optional<int64_t> alr_start_time_ms) {
alr_start_time_ms_ = alr_start_time_ms;
if (alr_start_time_ms) {
alr_start_time_ = Timestamp::Millis(*alr_start_time_ms);
} else {
alr_start_time_ = absl::nullopt;
}
}
void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) {
alr_end_time_ms_.emplace(alr_end_time_ms);
alr_end_time_.emplace(Timestamp::Millis(alr_end_time_ms));
}
std::vector<ProbeClusterConfig> ProbeController::RequestProbe(
int64_t at_time_ms) {
Timestamp at_time) {
// Called once we have returned to normal state after a large drop in
// estimated bandwidth. The current response is to initiate a single probe
// session (if not already probing) at the previous bitrate.
//
// If the probe session fails, the assumption is that this drop was a
// real one from a competing flow or a network change.
bool in_alr = alr_start_time_ms_.has_value();
bool in_alr = alr_start_time_.has_value();
bool alr_ended_recently =
(alr_end_time_ms_.has_value() &&
at_time_ms - alr_end_time_ms_.value() < kAlrEndedTimeoutMs);
(alr_end_time_.has_value() &&
at_time - alr_end_time_.value() < kAlrEndedTimeout);
if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) {
if (state_ == State::kProbingComplete) {
uint32_t suggested_probe_bps =
kProbeFractionAfterDrop * bitrate_before_last_large_drop_bps_;
uint32_t min_expected_probe_result_bps =
(1 - kProbeUncertainty) * suggested_probe_bps;
int64_t time_since_drop_ms = at_time_ms - time_of_last_large_drop_ms_;
int64_t time_since_probe_ms = at_time_ms - last_bwe_drop_probing_time_ms_;
if (min_expected_probe_result_bps > estimated_bitrate_bps_ &&
time_since_drop_ms < kBitrateDropTimeoutMs &&
time_since_probe_ms > kMinTimeBetweenAlrProbesMs) {
DataRate suggested_probe =
kProbeFractionAfterDrop * bitrate_before_last_large_drop_;
DataRate min_expected_probe_result =
(1 - kProbeUncertainty) * suggested_probe;
TimeDelta time_since_drop = at_time - time_of_last_large_drop_;
TimeDelta time_since_probe = at_time - last_bwe_drop_probing_time_;
if (min_expected_probe_result > estimated_bitrate_ &&
time_since_drop < kBitrateDropTimeout &&
time_since_probe > kMinTimeBetweenAlrProbes) {
RTC_LOG(LS_INFO) << "Detected big bandwidth drop, start probing.";
// Track how often we probe in response to bandwidth drop in ALR.
RTC_HISTOGRAM_COUNTS_10000(
"WebRTC.BWE.BweDropProbingIntervalInS",
(at_time_ms - last_bwe_drop_probing_time_ms_) / 1000);
last_bwe_drop_probing_time_ms_ = at_time_ms;
return InitiateProbing(at_time_ms, {suggested_probe_bps}, false);
(at_time - last_bwe_drop_probing_time_).seconds());
last_bwe_drop_probing_time_ = at_time;
return InitiateProbing(at_time, {suggested_probe}, false);
}
}
}
return std::vector<ProbeClusterConfig>();
}
void ProbeController::SetMaxBitrate(int64_t max_bitrate_bps) {
max_bitrate_bps_ = max_bitrate_bps;
void ProbeController::SetMaxBitrate(DataRate max_bitrate) {
max_bitrate_ = max_bitrate;
}
void ProbeController::SetNetworkStateEstimate(
@ -359,112 +353,106 @@ void ProbeController::SetNetworkStateEstimate(
network_estimate_ = estimate;
}
void ProbeController::Reset(int64_t at_time_ms) {
void ProbeController::Reset(Timestamp at_time) {
network_available_ = true;
bwe_limited_due_to_packet_loss_ = false;
state_ = State::kInit;
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
time_last_probing_initiated_ms_ = 0;
estimated_bitrate_bps_ = 0;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
time_last_probing_initiated_ = Timestamp::Zero();
estimated_bitrate_ = DataRate::Zero();
network_estimate_ = absl::nullopt;
start_bitrate_bps_ = 0;
max_bitrate_bps_ = 0;
int64_t now_ms = at_time_ms;
last_bwe_drop_probing_time_ms_ = now_ms;
alr_end_time_ms_.reset();
start_bitrate_ = DataRate::Zero();
max_bitrate_ = kDefaultMaxProbingBitrate;
Timestamp now = at_time;
last_bwe_drop_probing_time_ = now;
alr_end_time_.reset();
mid_call_probing_waiting_for_result_ = false;
time_of_last_large_drop_ms_ = now_ms;
bitrate_before_last_large_drop_bps_ = 0;
max_total_allocated_bitrate_ = 0;
time_of_last_large_drop_ = now;
bitrate_before_last_large_drop_ = DataRate::Zero();
max_total_allocated_bitrate_ = DataRate::Zero();
}
bool ProbeController::TimeForAlrProbe(int64_t at_time_ms) const {
if (enable_periodic_alr_probing_ && alr_start_time_ms_) {
int64_t next_probe_time_ms =
std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) +
config_.alr_probing_interval->ms();
return at_time_ms >= next_probe_time_ms;
bool ProbeController::TimeForAlrProbe(Timestamp at_time) const {
if (enable_periodic_alr_probing_ && alr_start_time_) {
Timestamp next_probe_time =
std::max(*alr_start_time_, time_last_probing_initiated_) +
config_.alr_probing_interval;
return at_time >= next_probe_time;
}
return false;
}
bool ProbeController::TimeForNetworkStateProbe(int64_t at_time_ms) const {
bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const {
if (config_.network_state_estimate_probing_interval->IsFinite() &&
network_estimate_ && network_estimate_->link_capacity_upper.IsFinite() &&
estimated_bitrate_bps_ < network_estimate_->link_capacity_upper.bps()) {
int64_t next_probe_time_ms =
time_last_probing_initiated_ms_ +
config_.network_state_estimate_probing_interval->ms();
return at_time_ms >= next_probe_time_ms;
estimated_bitrate_ < network_estimate_->link_capacity_upper) {
Timestamp next_probe_time = time_last_probing_initiated_ +
config_.network_state_estimate_probing_interval;
return at_time >= next_probe_time;
}
return false;
}
std::vector<ProbeClusterConfig> ProbeController::Process(int64_t at_time_ms) {
if (at_time_ms - time_last_probing_initiated_ms_ >
kMaxWaitingTimeForProbingResultMs) {
std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
if (at_time - time_last_probing_initiated_ >
kMaxWaitingTimeForProbingResult) {
mid_call_probing_waiting_for_result_ = false;
if (state_ == State::kWaitingForProbingResult) {
RTC_LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
state_ = State::kProbingComplete;
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
}
}
if (estimated_bitrate_bps_ <= 0 || state_ != State::kProbingComplete) {
if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
return {};
}
if (TimeForAlrProbe(at_time_ms) || TimeForNetworkStateProbe(at_time_ms)) {
return InitiateProbing(at_time_ms,
{static_cast<int64_t>(estimated_bitrate_bps_ *
config_.alr_probe_scale)},
true);
if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {
return InitiateProbing(
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
}
return std::vector<ProbeClusterConfig>();
}
std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
int64_t now_ms,
std::vector<int64_t> bitrates_to_probe,
Timestamp now,
std::vector<DataRate> bitrates_to_probe,
bool probe_further) {
if (bwe_limited_due_to_packet_loss_ &&
!config_.probe_if_bwe_limited_due_to_loss) {
return {};
}
int64_t max_probe_bitrate_bps =
max_bitrate_bps_ > 0 ? max_bitrate_bps_ : kDefaultMaxProbingBitrateBps;
DataRate max_probe_bitrate = max_bitrate_;
if (config_.network_state_estimate_probing_interval->IsFinite() &&
network_estimate_ &&
network_estimate_->link_capacity_upper > DataRate::Zero()) {
max_probe_bitrate_bps = std::min(
max_probe_bitrate_bps,
static_cast<int64_t>(network_estimate_->link_capacity_upper.bps() *
config_.network_state_probe_scale));
max_probe_bitrate =
std::min(max_probe_bitrate, network_estimate_->link_capacity_upper *
config_.network_state_probe_scale);
}
if (max_total_allocated_bitrate_ > 0) {
if (max_total_allocated_bitrate_ > DataRate::Zero()) {
// If a max allocated bitrate has been configured, allow probing up to 2x
// that rate. This allows some overhead to account for bursty streams,
// which otherwise would have to ramp up when the overshoot is already in
// progress.
// It also avoids minor quality reduction caused by probes often being
// received at slightly less than the target probe bitrate.
max_probe_bitrate_bps =
std::min(max_probe_bitrate_bps, max_total_allocated_bitrate_ * 2);
max_probe_bitrate =
std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2);
}
std::vector<ProbeClusterConfig> pending_probes;
for (int64_t bitrate : bitrates_to_probe) {
RTC_DCHECK_GT(bitrate, 0);
for (DataRate bitrate : bitrates_to_probe) {
RTC_DCHECK(!bitrate.IsZero());
if (bitrate > max_probe_bitrate_bps) {
bitrate = max_probe_bitrate_bps;
if (bitrate > max_probe_bitrate) {
bitrate = max_probe_bitrate;
probe_further = false;
}
ProbeClusterConfig config;
config.at_time = Timestamp::Millis(now_ms);
config.target_data_rate =
DataRate::BitsPerSec(rtc::dchecked_cast<int>(bitrate));
config.at_time = now;
config.target_data_rate = bitrate;
config.target_duration = config_.min_probe_duration;
config.target_probe_count = config_.min_probe_packets_sent;
config.id = next_probe_cluster_id_;
@ -472,14 +460,14 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
MaybeLogProbeClusterCreated(event_log_, config);
pending_probes.push_back(config);
}
time_last_probing_initiated_ms_ = now_ms;
time_last_probing_initiated_ = now;
if (probe_further) {
state_ = State::kWaitingForProbingResult;
min_bitrate_to_probe_further_bps_ =
min_bitrate_to_probe_further_ =
(*(bitrates_to_probe.end() - 1)) * config_.further_probe_threshold;
} else {
state_ = State::kProbingComplete;
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
}
return pending_probes;
}

View File

@ -23,6 +23,7 @@
#include "api/transport/network_control.h"
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/timestamp.h"
#include "rtc_base/experiments/field_trial_parser.h"
namespace webrtc {
@ -34,7 +35,7 @@ struct ProbeControllerConfig {
~ProbeControllerConfig();
// These parameters configure the initial probes. First we send one or two
// probes of sizes p1 * start_bitrate_bps_ and p2 * start_bitrate_bps_.
// probes of sizes p1 * start_bitrate_ and p2 * start_bitrate_.
// Then whenever we get a bitrate estimate of at least further_probe_threshold
// times the size of the last sent probe we'll send another one of size
// step_size times the new estimate.
@ -78,24 +79,24 @@ class ProbeController {
ProbeController& operator=(const ProbeController&) = delete;
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> SetBitrates(
int64_t min_bitrate_bps,
int64_t start_bitrate_bps,
int64_t max_bitrate_bps,
int64_t at_time_ms);
DataRate min_bitrate,
DataRate start_bitrate,
DataRate max_bitrate,
Timestamp at_time);
// The total bitrate, as opposed to the max bitrate, is the sum of the
// configured bitrates for all active streams.
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig>
OnMaxTotalAllocatedBitrate(int64_t max_total_allocated_bitrate,
int64_t at_time_ms);
OnMaxTotalAllocatedBitrate(DataRate max_total_allocated_bitrate,
Timestamp at_time);
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> OnNetworkAvailability(
NetworkAvailability msg);
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> SetEstimatedBitrate(
int64_t target_bitrate_bps,
DataRate bitrate,
bool bwe_limited_due_to_packet_loss,
int64_t at_time_ms);
Timestamp at_time);
void EnablePeriodicAlrProbing(bool enable);
@ -103,18 +104,18 @@ class ProbeController {
void SetAlrEndedTimeMs(int64_t alr_end_time);
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> RequestProbe(
int64_t at_time_ms);
Timestamp at_time);
// Sets a new maximum probing bitrate, without generating a new probe cluster.
void SetMaxBitrate(int64_t max_bitrate_bps);
void SetMaxBitrate(DataRate max_bitrate);
void SetNetworkStateEstimate(webrtc::NetworkStateEstimate estimate);
// Resets the ProbeController to a state equivalent to as if it was just
// created EXCEPT for `enable_periodic_alr_probing_`.
void Reset(int64_t at_time_ms);
void Reset(Timestamp at_time);
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> Process(
int64_t at_time_ms);
Timestamp at_time);
private:
enum class State {
@ -127,36 +128,36 @@ class ProbeController {
};
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig>
InitiateExponentialProbing(int64_t at_time_ms);
InitiateExponentialProbing(Timestamp at_time);
ABSL_MUST_USE_RESULT std::vector<ProbeClusterConfig> InitiateProbing(
int64_t now_ms,
std::vector<int64_t> bitrates_to_probe,
Timestamp now,
std::vector<DataRate> bitrates_to_probe,
bool probe_further);
bool TimeForAlrProbe(int64_t at_time_ms) const;
bool TimeForNetworkStateProbe(int64_t at_time_ms) const;
bool TimeForAlrProbe(Timestamp at_time) const;
bool TimeForNetworkStateProbe(Timestamp at_time) const;
bool network_available_;
bool bwe_limited_due_to_packet_loss_;
State state_;
int64_t min_bitrate_to_probe_further_bps_;
int64_t time_last_probing_initiated_ms_;
int64_t estimated_bitrate_bps_;
DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity();
DataRate estimated_bitrate_ = DataRate::Zero();
absl::optional<webrtc::NetworkStateEstimate> network_estimate_;
int64_t start_bitrate_bps_;
int64_t max_bitrate_bps_;
int64_t last_bwe_drop_probing_time_ms_;
absl::optional<int64_t> alr_start_time_ms_;
absl::optional<int64_t> alr_end_time_ms_;
DataRate start_bitrate_ = DataRate::Zero();
DataRate max_bitrate_ = DataRate::PlusInfinity();
Timestamp last_bwe_drop_probing_time_ = Timestamp::Zero();
absl::optional<Timestamp> alr_start_time_;
absl::optional<Timestamp> alr_end_time_;
bool enable_periodic_alr_probing_;
int64_t time_of_last_large_drop_ms_;
int64_t bitrate_before_last_large_drop_bps_;
int64_t max_total_allocated_bitrate_;
Timestamp time_of_last_large_drop_ = Timestamp::MinusInfinity();
DataRate bitrate_before_last_large_drop_ = DataRate::Zero();
DataRate max_total_allocated_bitrate_ = DataRate::Zero();
const bool in_rapid_recovery_experiment_;
// For WebRTC.BWE.MidCallProbing.* metric.
bool mid_call_probing_waiting_for_result_;
int64_t mid_call_probing_bitrate_bps_;
int64_t mid_call_probing_succcess_threshold_;
DataRate mid_call_probing_bitrate_ = DataRate::Zero();
DataRate mid_call_probing_succcess_threshold_ = DataRate::Zero();
RtcEventLog* event_log_;
int32_t next_probe_cluster_id_ = 1;

View File

@ -11,9 +11,8 @@
#include <memory>
#include "api/transport/field_trial_based_config.h"
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "rtc_base/logging.h"
@ -22,27 +21,22 @@
#include "test/gmock.h"
#include "test/gtest.h"
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Field;
using ::testing::Matcher;
using ::testing::NiceMock;
using ::testing::Return;
namespace webrtc {
namespace test {
namespace {
constexpr int kMinBitrateBps = 100;
constexpr int kStartBitrateBps = 300;
constexpr int kMaxBitrateBps = 10000;
constexpr DataRate kMinBitrate = DataRate::BitsPerSec(100);
constexpr DataRate kStartBitrate = DataRate::BitsPerSec(300);
constexpr DataRate kMaxBitrate = DataRate::BitsPerSec(10000);
constexpr int kExponentialProbingTimeoutMs = 5000;
constexpr TimeDelta kExponentialProbingTimeout = TimeDelta::Seconds(5);
constexpr int kAlrProbeInterval = 5000;
constexpr int kAlrEndedTimeoutMs = 3000;
constexpr int kBitrateDropTimeoutMs = 5000;
constexpr TimeDelta kAlrProbeInterval = TimeDelta::Seconds(5);
constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds(3);
constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds(5);
} // namespace
class ProbeControllerFixture {
@ -56,10 +50,7 @@ class ProbeControllerFixture {
}
Timestamp CurrentTime() { return clock_.CurrentTime(); }
int64_t NowMs() { return clock_.TimeInMilliseconds(); }
void AdvanceTimeMilliseconds(int64_t delta_ms) {
clock_.AdvanceTimeMilliseconds(delta_ms);
}
void AdvanceTime(TimeDelta delta) { clock_.AdvanceTime(delta); }
ExplicitKeyValueConfig field_trial_config_;
SimulatedClock clock_;
@ -71,8 +62,8 @@ TEST(ProbeControllerTest, InitiatesProbingAtStart) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_GE(probes.size(), 2u);
}
@ -81,7 +72,7 @@ TEST(ProbeControllerTest, SetsDefaultTargetDurationAndTargetProbeCount) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
kMinBitrateBps, kStartBitrateBps, kMaxBitrateBps, fixture.NowMs());
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_GE(probes.size(), 2u);
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(15));
@ -96,7 +87,7 @@ TEST(ProbeControllerTest,
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
std::vector<ProbeClusterConfig> probes = probe_controller->SetBitrates(
kMinBitrateBps, kStartBitrateBps, kMaxBitrateBps, fixture.NowMs());
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
ASSERT_GE(probes.size(), 2u);
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(123));
@ -109,8 +100,8 @@ TEST(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
fixture.CreateController();
auto probes = probe_controller->OnNetworkAvailability(
{.at_time = fixture.CurrentTime(), .network_available = false});
probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probes = probe_controller->OnNetworkAvailability(
{.at_time = fixture.CurrentTime(), .network_available = true});
@ -121,45 +112,46 @@ TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Long enough to time out exponential probing.
fixture.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrateBps, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probes = probe_controller->Process(fixture.NowMs());
probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps + 100, fixture.NowMs());
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrate.bps() + 100);
}
TEST(ProbeControllerTest, ProbesOnMaxBitrateIncreaseOnlyWhenInAlr) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrateBps - 1, kBweLimitedDuetoPacketLoss, fixture.NowMs());
kMaxBitrate - DataRate::BitsPerSec(1),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
// Wait long enough to time out exponential probing.
fixture.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
// Probe when in alr.
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
probes = probe_controller->OnMaxTotalAllocatedBitrate(kMaxBitrateBps + 1,
fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(1), fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
// Do not probe when not in alr.
probe_controller->SetAlrStartTimeMs(absl::nullopt);
probes = probe_controller->OnMaxTotalAllocatedBitrate(kMaxBitrateBps + 2,
fixture.NowMs());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
kMaxBitrate + DataRate::BitsPerSec(2), fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
}
@ -167,38 +159,42 @@ TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Long enough to time out exponential probing.
fixture.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->SetEstimatedBitrate(
kStartBitrateBps, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probes = probe_controller->Process(fixture.NowMs());
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
kMaxBitrateBps, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps + 100, fixture.NowMs());
kMaxBitrate, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate + DataRate::BitsPerSec(100),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
EXPECT_EQ(probes[0].target_data_rate,
kMaxBitrate + DataRate::BitsPerSec(100));
}
TEST(ProbeControllerTest, TestExponentialProbing) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.7 * 6 * kStartBitrateBps = 1260.
// 0.7 * 6 * kStartBitrate = 1260.
probes = probe_controller->SetEstimatedBitrate(
1000, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(1000),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probes = probe_controller->SetEstimatedBitrate(
1800, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(1800),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
}
@ -207,15 +203,15 @@ TEST(ProbeControllerTest, TestExponentialProbingTimeout) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
// Advance far enough to cause a time out in waiting for probing result.
fixture.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(kExponentialProbingTimeout);
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
1800, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(1800),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
}
@ -223,19 +219,20 @@ TEST(ProbeControllerTest, RequestProbeInAlr) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_GE(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
250, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probes = probe_controller->RequestProbe(fixture.NowMs());
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
@ -245,21 +242,22 @@ TEST(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
250, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probe_controller->SetAlrEndedTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs - 1);
probes = probe_controller->RequestProbe(fixture.NowMs());
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probe_controller->SetAlrEndedTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrEndedTimeout - TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
@ -269,21 +267,22 @@ TEST(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(absl::nullopt);
fixture.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
250, kBweLimitedDuetoPacketLoss, fixture.NowMs());
probe_controller->SetAlrEndedTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs + 1);
probes = probe_controller->RequestProbe(fixture.NowMs());
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, 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);
}
@ -291,20 +290,21 @@ TEST(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(kAlrProbeInterval + TimeDelta::Millis(1));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
250, kBweLimitedDuetoPacketLoss, fixture.NowMs());
fixture.AdvanceTimeMilliseconds(kBitrateDropTimeoutMs + 1);
probes = probe_controller->RequestProbe(fixture.NowMs());
DataRate::BitsPerSec(250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
fixture.AdvanceTime(kBitrateDropTimeout + TimeDelta::Millis(1));
probes = probe_controller->RequestProbe(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
}
@ -312,40 +312,43 @@ TEST(ProbeControllerTest, PeriodicProbing) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
int64_t start_time = fixture.NowMs();
Timestamp start_time = fixture.CurrentTime();
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(start_time);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000);
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
// The following probe should be sent at 10s into ALR.
probe_controller->SetAlrStartTimeMs(start_time);
fixture.AdvanceTimeMilliseconds(4000);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(start_time.ms());
fixture.AdvanceTime(TimeDelta::Seconds(4));
probes = probe_controller->Process(fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probe_controller->SetAlrStartTimeMs(start_time);
fixture.AdvanceTimeMilliseconds(1000);
probes = probe_controller->Process(fixture.NowMs());
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(
500, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(500),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
}
@ -353,49 +356,50 @@ TEST(ProbeControllerTest, PeriodicProbingAfterReset) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
int64_t alr_start_time = fixture.NowMs();
Timestamp alr_start_time = fixture.CurrentTime();
probe_controller->SetAlrStartTimeMs(alr_start_time);
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
probe_controller->Reset(fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probe_controller->Reset(fixture.CurrentTime());
fixture.AdvanceTimeMilliseconds(10000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(10));
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);
probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
kMaxBitrate, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
// Make sure we use `kStartBitrateBps` as the estimated bitrate
// until SetEstimatedBitrate is called with an updated estimate.
fixture.AdvanceTimeMilliseconds(10000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(10));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), kStartBitrateBps * 2);
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
}
TEST(ProbeControllerTest, TestExponentialProbingOverflow) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
const int64_t kMbpsMultiplier = 1000000;
auto probes =
probe_controller->SetBitrates(kMinBitrateBps, 10 * kMbpsMultiplier,
100 * kMbpsMultiplier, fixture.NowMs());
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
auto probes = probe_controller->SetBitrates(kMinBitrate, 10 * kMbpsMultiplier,
100 * kMbpsMultiplier,
fixture.CurrentTime());
// Verify that probe bitrate is capped at the specified max bitrate.
probes = probe_controller->SetEstimatedBitrate(
60 * kMbpsMultiplier, kBweLimitedDuetoPacketLoss, fixture.NowMs());
60 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 100 * kMbpsMultiplier);
EXPECT_EQ(probes[0].target_data_rate, 100 * kMbpsMultiplier);
// Verify that repeated probes aren't sent.
probes = probe_controller->SetEstimatedBitrate(
100 * kMbpsMultiplier, kBweLimitedDuetoPacketLoss, fixture.NowMs());
100 * kMbpsMultiplier, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
}
@ -403,40 +407,42 @@ TEST(ProbeControllerTest, TestAllocatedBitrateCap) {
ProbeControllerFixture fixture;
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
const int64_t kMbpsMultiplier = 1000000;
const int64_t kMaxBitrateBps = 100 * kMbpsMultiplier;
const DataRate kMbpsMultiplier = DataRate::KilobitsPerSec(1000);
const DataRate kMaxBitrate = 100 * kMbpsMultiplier;
auto probes = probe_controller->SetBitrates(
kMinBitrateBps, 10 * kMbpsMultiplier, kMaxBitrateBps, fixture.NowMs());
kMinBitrate, 10 * kMbpsMultiplier, kMaxBitrate, fixture.CurrentTime());
// Configure ALR for periodic probing.
probe_controller->EnablePeriodicAlrProbing(true);
int64_t alr_start_time = fixture.NowMs();
probe_controller->SetAlrStartTimeMs(alr_start_time);
Timestamp alr_start_time = fixture.CurrentTime();
probe_controller->SetAlrStartTimeMs(alr_start_time.ms());
int64_t estimated_bitrate_bps = kMaxBitrateBps / 10;
DataRate estimated_bitrate = kMaxBitrate / 10;
probes = probe_controller->SetEstimatedBitrate(
estimated_bitrate_bps, kBweLimitedDuetoPacketLoss, fixture.NowMs());
estimated_bitrate, /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
// Set a max allocated bitrate below the current estimate.
int64_t max_allocated_bps = estimated_bitrate_bps - 1 * kMbpsMultiplier;
probes = probe_controller->OnMaxTotalAllocatedBitrate(max_allocated_bps,
fixture.NowMs());
DataRate max_allocated = estimated_bitrate - 1 * kMbpsMultiplier;
probes = probe_controller->OnMaxTotalAllocatedBitrate(max_allocated,
fixture.CurrentTime());
EXPECT_TRUE(probes.empty()); // No probe since lower than current max.
// Probes such as ALR capped at 2x the max allocation limit.
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * max_allocated_bps);
EXPECT_EQ(probes[0].target_data_rate, 2 * max_allocated);
// Remove allocation limit.
EXPECT_TRUE(
probe_controller->OnMaxTotalAllocatedBitrate(0, fixture.NowMs()).empty());
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
probe_controller
->OnMaxTotalAllocatedBitrate(DataRate::Zero(), fixture.CurrentTime())
.empty());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), estimated_bitrate_bps * 2);
EXPECT_EQ(probes[0].target_data_rate, estimated_bitrate * 2);
}
TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
@ -446,10 +452,10 @@ TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
"alloc_p1:2,alloc_p2/");
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
const bool kBweLimitedDuetoPacketLoss = false;
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
5000000, fixture.NowMs());
auto probes = probe_controller->SetBitrates(kMinBitrate, kStartBitrate,
DataRate::KilobitsPerSec(5000),
fixture.CurrentTime());
EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 600);
EXPECT_EQ(probes[1].target_data_rate.bps(), 1500);
@ -457,22 +463,24 @@ TEST(ProbeControllerTest, ConfigurableProbingFieldTrial) {
// Repeated probe should only be sent when estimated bitrate climbs above
// 0.8 * 5 * kStartBitrateBps = 1200.
probes = probe_controller->SetEstimatedBitrate(
1100, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(1100),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 0u);
probes = probe_controller->SetEstimatedBitrate(
1250, kBweLimitedDuetoPacketLoss, fixture.NowMs());
DataRate::BitsPerSec(1250),
/*bwe_limited_due_to_packet_loss=*/false, fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 3 * 1250);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
probes =
probe_controller->OnMaxTotalAllocatedBitrate(200000, fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
probes = probe_controller->OnMaxTotalAllocatedBitrate(
DataRate::KilobitsPerSec(200), fixture.CurrentTime());
EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 400000);
EXPECT_EQ(probes[0].target_data_rate.bps(), 400'000);
}
TEST(ProbeControllerTest, PauseAlrProbeWhenLossBasedBweLimited) {
@ -482,27 +490,30 @@ TEST(ProbeControllerTest, PauseAlrProbeWhenLossBasedBweLimited) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss*/ true, fixture.NowMs());
fixture.AdvanceTimeMilliseconds(6000);
probes = probe_controller->Process(fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss*/ true,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
// ALR probing resumed when estimate is no longer restricted by loss based
// BWE.
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
fixture.AdvanceTimeMilliseconds(6000);
probes = probe_controller->Process(fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(6));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(!probes.empty());
}
@ -513,19 +524,21 @@ TEST(ProbeControllerTest, AlrProbeStartWhenNotLossBasedBweLimited) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/true, fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/true,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss*/ false, fixture.NowMs());
fixture.AdvanceTimeMilliseconds(1000);
probes = probe_controller->Process(fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss*/ false,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(1));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(!probes.empty());
}
@ -535,21 +548,22 @@ TEST(ProbeControllerTest, PeriodicProbeAtUpperNetworkStateEstimate) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
5000, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
DataRate::BitsPerSec(5000), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::BitsPerSec(6000);
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
}
@ -562,29 +576,32 @@ TEST(ProbeControllerTest,
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(600);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/true, fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/true,
fixture.CurrentTime());
// Expect the controller to send a new probe after 5s has passed.
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_TRUE(probes.empty());
probes = probe_controller->SetEstimatedBitrate(
500, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
DataRate::BitsPerSec(500), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
EXPECT_FALSE(probes.empty());
}
@ -594,22 +611,23 @@ TEST(ProbeControllerTest, AlrProbesLimitedByNetworkStateEstimate) {
std::unique_ptr<ProbeController> probe_controller =
fixture.CreateController();
probe_controller->EnablePeriodicAlrProbing(true);
auto probes = probe_controller->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, fixture.NowMs());
auto probes = probe_controller->SetBitrates(
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
probes = probe_controller->SetEstimatedBitrate(
6000, /*bwe_limited_due_to_packet_loss=*/false, fixture.NowMs());
probe_controller->SetAlrStartTimeMs(fixture.NowMs());
DataRate::KilobitsPerSec(6), /*bwe_limited_due_to_packet_loss=*/false,
fixture.CurrentTime());
probe_controller->SetAlrStartTimeMs(fixture.CurrentTime().ms());
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps);
EXPECT_EQ(probes[0].target_data_rate, kMaxBitrate);
NetworkStateEstimate state_estimate;
state_estimate.link_capacity_upper = DataRate::BitsPerSec(8000);
probe_controller->SetNetworkStateEstimate(state_estimate);
fixture.AdvanceTimeMilliseconds(5000);
probes = probe_controller->Process(fixture.NowMs());
fixture.AdvanceTime(TimeDelta::Seconds(5));
probes = probe_controller->Process(fixture.CurrentTime());
ASSERT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
}