Always sends probes when they are generated.
This changes makes the usage of the new probe controller reflect how the old probe controller was used. That is probes are now sent as soon as they are generated. This is to avoid regressions in performance doe to the timing of the sent probes. Bug: chromium:868776 Change-Id: I722585689258c9b01e8f1dc47249b284a05a2793 Reviewed-on: https://webrtc-review.googlesource.com/91441 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24175}
This commit is contained in:

committed by
Commit Bot

parent
dc6e68b4a7
commit
da2ec40590
@ -135,6 +135,7 @@ rtc_source_set("probe_controller") {
|
||||
"../../../logging:rtc_event_pacing",
|
||||
"../../../rtc_base:checks",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base/system:unused",
|
||||
"../../../system_wrappers:field_trial_api",
|
||||
"../../../system_wrappers:metrics_api",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
|
@ -122,16 +122,18 @@ GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
|
||||
delay_based_bwe_(new DelayBasedBwe(event_log_)),
|
||||
acknowledged_bitrate_estimator_(
|
||||
absl::make_unique<AcknowledgedBitrateEstimator>()),
|
||||
initial_config_(config),
|
||||
last_bandwidth_(config.starting_bandwidth),
|
||||
pacing_factor_(kDefaultPaceMultiplier),
|
||||
min_pacing_rate_(DataRate::Zero()),
|
||||
max_padding_rate_(DataRate::Zero()),
|
||||
pacing_factor_(config.stream_based_config.pacing_factor.value_or(
|
||||
kDefaultPaceMultiplier)),
|
||||
min_pacing_rate_(config.stream_based_config.min_pacing_rate.value_or(
|
||||
DataRate::Zero())),
|
||||
max_padding_rate_(config.stream_based_config.max_padding_rate.value_or(
|
||||
DataRate::Zero())),
|
||||
max_total_allocated_bitrate_(DataRate::Zero()),
|
||||
in_cwnd_experiment_(CwndExperimentEnabled()),
|
||||
accepted_queue_ms_(kDefaultAcceptedQueueMs) {
|
||||
delay_based_bwe_->SetMinBitrate(congestion_controller::GetMinBitrateBps());
|
||||
UpdateBitrateConstraints(config.constraints, config.starting_bandwidth);
|
||||
OnStreamsConfig(config.stream_based_config);
|
||||
if (in_cwnd_experiment_ &&
|
||||
!ReadCwndExperimentParameter(&accepted_queue_ms_)) {
|
||||
RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
|
||||
@ -144,8 +146,9 @@ GoogCcNetworkController::~GoogCcNetworkController() {}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnNetworkAvailability(
|
||||
NetworkAvailability msg) {
|
||||
probe_controller_->OnNetworkAvailability(msg);
|
||||
return NetworkControlUpdate();
|
||||
NetworkControlUpdate update;
|
||||
update.probe_cluster_configs = probe_controller_->OnNetworkAvailability(msg);
|
||||
return update;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
|
||||
@ -166,24 +169,46 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
|
||||
delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
|
||||
|
||||
probe_controller_->Reset(msg.at_time.ms());
|
||||
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
|
||||
max_bitrate_bps, msg.at_time.ms());
|
||||
|
||||
return MaybeTriggerOnNetworkChanged(msg.at_time);
|
||||
NetworkControlUpdate update;
|
||||
update.probe_cluster_configs = probe_controller_->SetBitrates(
|
||||
min_bitrate_bps, start_bitrate_bps, max_bitrate_bps, msg.at_time.ms());
|
||||
MaybeTriggerOnNetworkChanged(&update, msg.at_time);
|
||||
return update;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
|
||||
ProcessInterval msg) {
|
||||
NetworkControlUpdate update;
|
||||
if (initial_config_) {
|
||||
update.probe_cluster_configs = UpdateBitrateConstraints(
|
||||
initial_config_->constraints, initial_config_->starting_bandwidth);
|
||||
update.pacer_config = GetPacingRates(msg.at_time);
|
||||
|
||||
probe_controller_->EnablePeriodicAlrProbing(
|
||||
initial_config_->stream_based_config.requests_alr_probing);
|
||||
absl::optional<DataRate> total_bitrate =
|
||||
initial_config_->stream_based_config.max_total_allocated_bitrate;
|
||||
if (total_bitrate) {
|
||||
auto probes = probe_controller_->OnMaxTotalAllocatedBitrate(
|
||||
total_bitrate->bps(), msg.at_time.ms());
|
||||
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
|
||||
probes.begin(), probes.end());
|
||||
|
||||
max_total_allocated_bitrate_ = *total_bitrate;
|
||||
}
|
||||
initial_config_.reset();
|
||||
}
|
||||
|
||||
bandwidth_estimation_->UpdateEstimate(msg.at_time.ms());
|
||||
absl::optional<int64_t> start_time_ms =
|
||||
alr_detector_->GetApplicationLimitedRegionStartTime();
|
||||
probe_controller_->SetAlrStartTimeMs(start_time_ms);
|
||||
probe_controller_->Process(msg.at_time.ms());
|
||||
NetworkControlUpdate update = MaybeTriggerOnNetworkChanged(msg.at_time);
|
||||
for (const ProbeClusterConfig& config :
|
||||
probe_controller_->GetAndResetPendingProbes()) {
|
||||
update.probe_cluster_configs.push_back(config);
|
||||
}
|
||||
|
||||
auto probes = probe_controller_->Process(msg.at_time.ms());
|
||||
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
|
||||
probes.begin(), probes.end());
|
||||
|
||||
MaybeTriggerOnNetworkChanged(&update, msg.at_time);
|
||||
return update;
|
||||
}
|
||||
|
||||
@ -216,11 +241,13 @@ NetworkControlUpdate GoogCcNetworkController::OnSentPacket(
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
|
||||
StreamsConfig msg) {
|
||||
NetworkControlUpdate update;
|
||||
probe_controller_->EnablePeriodicAlrProbing(msg.requests_alr_probing);
|
||||
if (msg.max_total_allocated_bitrate &&
|
||||
*msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) {
|
||||
probe_controller_->OnMaxTotalAllocatedBitrate(
|
||||
msg.max_total_allocated_bitrate->bps(), msg.at_time.ms());
|
||||
update.probe_cluster_configs =
|
||||
probe_controller_->OnMaxTotalAllocatedBitrate(
|
||||
msg.max_total_allocated_bitrate->bps(), msg.at_time.ms());
|
||||
max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate;
|
||||
}
|
||||
bool pacing_changed = false;
|
||||
@ -236,19 +263,22 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
|
||||
max_padding_rate_ = *msg.max_padding_rate;
|
||||
pacing_changed = true;
|
||||
}
|
||||
NetworkControlUpdate update;
|
||||
if (pacing_changed)
|
||||
update.pacer_config = UpdatePacingRates(msg.at_time);
|
||||
update.pacer_config = GetPacingRates(msg.at_time);
|
||||
return update;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnTargetRateConstraints(
|
||||
TargetRateConstraints constraints) {
|
||||
UpdateBitrateConstraints(constraints, absl::nullopt);
|
||||
return MaybeTriggerOnNetworkChanged(constraints.at_time);
|
||||
NetworkControlUpdate update;
|
||||
update.probe_cluster_configs =
|
||||
UpdateBitrateConstraints(constraints, absl::nullopt);
|
||||
MaybeTriggerOnNetworkChanged(&update, constraints.at_time);
|
||||
return update;
|
||||
}
|
||||
|
||||
void GoogCcNetworkController::UpdateBitrateConstraints(
|
||||
std::vector<ProbeClusterConfig>
|
||||
GoogCcNetworkController::UpdateBitrateConstraints(
|
||||
TargetRateConstraints constraints,
|
||||
absl::optional<DataRate> starting_rate) {
|
||||
int64_t min_bitrate_bps = GetBpsOrDefault(constraints.min_data_rate, 0);
|
||||
@ -257,14 +287,16 @@ void GoogCcNetworkController::UpdateBitrateConstraints(
|
||||
|
||||
ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
|
||||
|
||||
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
|
||||
max_bitrate_bps, constraints.at_time.ms());
|
||||
std::vector<ProbeClusterConfig> probes(probe_controller_->SetBitrates(
|
||||
min_bitrate_bps, start_bitrate_bps, max_bitrate_bps,
|
||||
constraints.at_time.ms()));
|
||||
|
||||
bandwidth_estimation_->SetBitrates(start_bitrate_bps, min_bitrate_bps,
|
||||
max_bitrate_bps);
|
||||
if (start_bitrate_bps > 0)
|
||||
delay_based_bwe_->SetStartBitrate(start_bitrate_bps);
|
||||
delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
|
||||
return probes;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
|
||||
@ -326,11 +358,13 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
|
||||
bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time.ms(),
|
||||
result.target_bitrate_bps);
|
||||
// Update the estimate in the ProbeController, in case we want to probe.
|
||||
update = MaybeTriggerOnNetworkChanged(report.feedback_time);
|
||||
MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
|
||||
}
|
||||
if (result.recovered_from_overuse) {
|
||||
probe_controller_->SetAlrStartTimeMs(alr_start_time);
|
||||
probe_controller_->RequestProbe(report.feedback_time.ms());
|
||||
auto probes = probe_controller_->RequestProbe(report.feedback_time.ms());
|
||||
update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
|
||||
probes.begin(), probes.end());
|
||||
}
|
||||
update.congestion_window = MaybeUpdateCongestionWindow();
|
||||
return update;
|
||||
@ -351,7 +385,7 @@ NetworkControlUpdate GoogCcNetworkController::GetNetworkState(
|
||||
TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs());
|
||||
update.target_rate->at_time = at_time;
|
||||
update.target_rate->target_rate = bandwidth;
|
||||
update.pacer_config = UpdatePacingRates(at_time);
|
||||
update.pacer_config = GetPacingRates(at_time);
|
||||
update.congestion_window = current_data_window_;
|
||||
return update;
|
||||
}
|
||||
@ -381,7 +415,8 @@ GoogCcNetworkController::MaybeUpdateCongestionWindow() {
|
||||
return data_window;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
|
||||
void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
|
||||
NetworkControlUpdate* update,
|
||||
Timestamp at_time) {
|
||||
int32_t estimated_bitrate_bps;
|
||||
uint8_t fraction_loss;
|
||||
@ -390,19 +425,33 @@ NetworkControlUpdate GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
|
||||
bool estimate_changed = GetNetworkParameters(
|
||||
&estimated_bitrate_bps, &fraction_loss, &rtt_ms, at_time);
|
||||
if (estimate_changed) {
|
||||
alr_detector_->SetEstimatedBitrate(estimated_bitrate_bps);
|
||||
|
||||
DataRate bandwidth = DataRate::bps(estimated_bitrate_bps);
|
||||
last_bandwidth_ = bandwidth;
|
||||
|
||||
TimeDelta bwe_period =
|
||||
TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs());
|
||||
|
||||
NetworkEstimate new_estimate;
|
||||
new_estimate.at_time = at_time;
|
||||
new_estimate.round_trip_time = TimeDelta::ms(rtt_ms);
|
||||
new_estimate.bandwidth = DataRate::bps(estimated_bitrate_bps);
|
||||
new_estimate.loss_rate_ratio = fraction_loss / 255.0f;
|
||||
new_estimate.bwe_period = bwe_period;
|
||||
last_bandwidth_ = new_estimate.bandwidth;
|
||||
return OnNetworkEstimate(new_estimate);
|
||||
TargetTransferRate target_rate;
|
||||
target_rate.at_time = at_time;
|
||||
// Set the target rate to the full estimated bandwidth since the estimation
|
||||
// for legacy reasons includes target rate constraints.
|
||||
target_rate.target_rate = bandwidth;
|
||||
|
||||
target_rate.network_estimate.at_time = at_time;
|
||||
target_rate.network_estimate.round_trip_time = TimeDelta::ms(rtt_ms);
|
||||
target_rate.network_estimate.bandwidth = bandwidth;
|
||||
target_rate.network_estimate.loss_rate_ratio = fraction_loss / 255.0f;
|
||||
target_rate.network_estimate.bwe_period = bwe_period;
|
||||
update->target_rate = target_rate;
|
||||
|
||||
auto probes =
|
||||
probe_controller_->SetEstimatedBitrate(bandwidth.bps(), at_time.ms());
|
||||
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
|
||||
probes.begin(), probes.end());
|
||||
update->pacer_config = GetPacingRates(at_time);
|
||||
}
|
||||
return NetworkControlUpdate();
|
||||
}
|
||||
|
||||
bool GoogCcNetworkController::GetNetworkParameters(
|
||||
@ -434,26 +483,7 @@ bool GoogCcNetworkController::GetNetworkParameters(
|
||||
return estimate_changed;
|
||||
}
|
||||
|
||||
NetworkControlUpdate GoogCcNetworkController::OnNetworkEstimate(
|
||||
NetworkEstimate estimate) {
|
||||
NetworkControlUpdate update;
|
||||
update.pacer_config = UpdatePacingRates(estimate.at_time);
|
||||
alr_detector_->SetEstimatedBitrate(estimate.bandwidth.bps());
|
||||
probe_controller_->SetEstimatedBitrate(estimate.bandwidth.bps(),
|
||||
estimate.at_time.ms());
|
||||
|
||||
TargetTransferRate target_rate;
|
||||
target_rate.at_time = estimate.at_time;
|
||||
// Set the target rate to the full estimated bandwidth since the estimation
|
||||
// for legacy reasons includes target rate constraints.
|
||||
target_rate.target_rate = estimate.bandwidth;
|
||||
target_rate.network_estimate = estimate;
|
||||
update.target_rate = target_rate;
|
||||
return update;
|
||||
}
|
||||
|
||||
PacerConfig GoogCcNetworkController::UpdatePacingRates(
|
||||
Timestamp at_time) const {
|
||||
PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const {
|
||||
DataRate pacing_rate =
|
||||
std::max(min_pacing_rate_, last_bandwidth_) * pacing_factor_;
|
||||
DataRate padding_rate = std::min(max_padding_rate_, last_bandwidth_);
|
||||
|
@ -52,16 +52,17 @@ class GoogCcNetworkController : public NetworkControllerInterface {
|
||||
NetworkControlUpdate GetNetworkState(Timestamp at_time) const;
|
||||
|
||||
private:
|
||||
void UpdateBitrateConstraints(TargetRateConstraints constraints,
|
||||
absl::optional<DataRate> starting_rate);
|
||||
std::vector<ProbeClusterConfig> UpdateBitrateConstraints(
|
||||
TargetRateConstraints constraints,
|
||||
absl::optional<DataRate> starting_rate);
|
||||
absl::optional<DataSize> MaybeUpdateCongestionWindow();
|
||||
NetworkControlUpdate MaybeTriggerOnNetworkChanged(Timestamp at_time);
|
||||
void MaybeTriggerOnNetworkChanged(NetworkControlUpdate* update,
|
||||
Timestamp at_time);
|
||||
bool GetNetworkParameters(int32_t* estimated_bitrate_bps,
|
||||
uint8_t* fraction_loss,
|
||||
int64_t* rtt_ms,
|
||||
Timestamp at_time);
|
||||
NetworkControlUpdate OnNetworkEstimate(NetworkEstimate msg);
|
||||
PacerConfig UpdatePacingRates(Timestamp at_time) const;
|
||||
PacerConfig GetPacingRates(Timestamp at_time) const;
|
||||
|
||||
RtcEventLog* const event_log_;
|
||||
|
||||
@ -72,6 +73,8 @@ class GoogCcNetworkController : public NetworkControllerInterface {
|
||||
std::unique_ptr<DelayBasedBwe> delay_based_bwe_;
|
||||
std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator_;
|
||||
|
||||
absl::optional<NetworkControllerConfig> initial_config_;
|
||||
|
||||
std::deque<int64_t> feedback_rtts_;
|
||||
absl::optional<int64_t> min_feedback_rtt_ms_;
|
||||
|
||||
|
@ -83,10 +83,11 @@ ProbeController::ProbeController() : enable_periodic_alr_probing_(false) {
|
||||
|
||||
ProbeController::~ProbeController() {}
|
||||
|
||||
void ProbeController::SetBitrates(int64_t min_bitrate_bps,
|
||||
int64_t start_bitrate_bps,
|
||||
int64_t max_bitrate_bps,
|
||||
int64_t at_time_ms) {
|
||||
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;
|
||||
@ -102,7 +103,7 @@ void ProbeController::SetBitrates(int64_t min_bitrate_bps,
|
||||
switch (state_) {
|
||||
case State::kInit:
|
||||
if (network_available_)
|
||||
InitiateExponentialProbing(at_time_ms);
|
||||
return InitiateExponentialProbing(at_time_ms);
|
||||
break;
|
||||
|
||||
case State::kWaitingForProbingResult:
|
||||
@ -125,13 +126,14 @@ void ProbeController::SetBitrates(int64_t min_bitrate_bps,
|
||||
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated",
|
||||
max_bitrate_bps_ / 1000);
|
||||
|
||||
InitiateProbing(at_time_ms, {max_bitrate_bps}, false);
|
||||
return InitiateProbing(at_time_ms, {max_bitrate_bps}, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
}
|
||||
|
||||
void ProbeController::OnMaxTotalAllocatedBitrate(
|
||||
std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
|
||||
int64_t max_total_allocated_bitrate,
|
||||
int64_t at_time_ms) {
|
||||
// TODO(philipel): Should |max_total_allocated_bitrate| be used as a limit for
|
||||
@ -142,11 +144,13 @@ void ProbeController::OnMaxTotalAllocatedBitrate(
|
||||
(max_bitrate_bps_ <= 0 || estimated_bitrate_bps_ < max_bitrate_bps_) &&
|
||||
estimated_bitrate_bps_ < max_total_allocated_bitrate) {
|
||||
max_total_allocated_bitrate_ = max_total_allocated_bitrate;
|
||||
InitiateProbing(at_time_ms, {max_total_allocated_bitrate}, false);
|
||||
return InitiateProbing(at_time_ms, {max_total_allocated_bitrate}, false);
|
||||
}
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
}
|
||||
|
||||
void ProbeController::OnNetworkAvailability(NetworkAvailability msg) {
|
||||
std::vector<ProbeClusterConfig> ProbeController::OnNetworkAvailability(
|
||||
NetworkAvailability msg) {
|
||||
network_available_ = msg.network_available;
|
||||
|
||||
if (!network_available_ && state_ == State::kWaitingForProbingResult) {
|
||||
@ -155,22 +159,25 @@ void ProbeController::OnNetworkAvailability(NetworkAvailability msg) {
|
||||
}
|
||||
|
||||
if (network_available_ && state_ == State::kInit && start_bitrate_bps_ > 0)
|
||||
InitiateExponentialProbing(msg.at_time.ms());
|
||||
return InitiateExponentialProbing(msg.at_time.ms());
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
}
|
||||
|
||||
void ProbeController::InitiateExponentialProbing(int64_t at_time_ms) {
|
||||
std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
|
||||
int64_t at_time_ms) {
|
||||
RTC_DCHECK(network_available_);
|
||||
RTC_DCHECK(state_ == State::kInit);
|
||||
RTC_DCHECK_GT(start_bitrate_bps_, 0);
|
||||
|
||||
// When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
|
||||
// 1.2 Mbps to continue probing.
|
||||
InitiateProbing(at_time_ms, {3 * start_bitrate_bps_, 6 * start_bitrate_bps_},
|
||||
true);
|
||||
return InitiateProbing(
|
||||
at_time_ms, {3 * start_bitrate_bps_, 6 * start_bitrate_bps_}, true);
|
||||
}
|
||||
|
||||
void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
|
||||
int64_t at_time_ms) {
|
||||
std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
|
||||
int64_t bitrate_bps,
|
||||
int64_t at_time_ms) {
|
||||
int64_t now_ms = at_time_ms;
|
||||
|
||||
if (mid_call_probing_waiting_for_result_ &&
|
||||
@ -181,7 +188,7 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
|
||||
bitrate_bps / 1000);
|
||||
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.
|
||||
@ -192,7 +199,7 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
|
||||
if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
|
||||
bitrate_bps > min_bitrate_to_probe_further_bps_) {
|
||||
// Double the probing bitrate.
|
||||
InitiateProbing(now_ms, {2 * bitrate_bps}, true);
|
||||
pending_probes = InitiateProbing(now_ms, {2 * bitrate_bps}, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,6 +209,7 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
|
||||
}
|
||||
|
||||
estimated_bitrate_bps_ = bitrate_bps;
|
||||
return pending_probes;
|
||||
}
|
||||
|
||||
void ProbeController::EnablePeriodicAlrProbing(bool enable) {
|
||||
@ -216,7 +224,8 @@ void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) {
|
||||
alr_end_time_ms_.emplace(alr_end_time_ms);
|
||||
}
|
||||
|
||||
void ProbeController::RequestProbe(int64_t at_time_ms) {
|
||||
std::vector<ProbeClusterConfig> ProbeController::RequestProbe(
|
||||
int64_t at_time_ms) {
|
||||
// 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.
|
||||
@ -243,11 +252,12 @@ void ProbeController::RequestProbe(int64_t at_time_ms) {
|
||||
RTC_HISTOGRAM_COUNTS_10000(
|
||||
"WebRTC.BWE.BweDropProbingIntervalInS",
|
||||
(at_time_ms - last_bwe_drop_probing_time_ms_) / 1000);
|
||||
InitiateProbing(at_time_ms, {suggested_probe_bps}, false);
|
||||
return InitiateProbing(at_time_ms, {suggested_probe_bps}, false);
|
||||
last_bwe_drop_probing_time_ms_ = at_time_ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
}
|
||||
|
||||
void ProbeController::Reset(int64_t at_time_ms) {
|
||||
@ -267,7 +277,7 @@ void ProbeController::Reset(int64_t at_time_ms) {
|
||||
max_total_allocated_bitrate_ = 0;
|
||||
}
|
||||
|
||||
void ProbeController::Process(int64_t at_time_ms) {
|
||||
std::vector<ProbeClusterConfig> ProbeController::Process(int64_t at_time_ms) {
|
||||
int64_t now_ms = at_time_ms;
|
||||
|
||||
if (now_ms - time_last_probing_initiated_ms_ >
|
||||
@ -281,32 +291,25 @@ void ProbeController::Process(int64_t at_time_ms) {
|
||||
}
|
||||
}
|
||||
|
||||
if (state_ != State::kProbingComplete || !enable_periodic_alr_probing_)
|
||||
return;
|
||||
|
||||
// Probe bandwidth periodically when in ALR state.
|
||||
if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) {
|
||||
int64_t next_probe_time_ms =
|
||||
std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) +
|
||||
kAlrPeriodicProbingIntervalMs;
|
||||
if (now_ms >= next_probe_time_ms) {
|
||||
InitiateProbing(now_ms, {estimated_bitrate_bps_ * 2}, true);
|
||||
if (enable_periodic_alr_probing_ && state_ == State::kProbingComplete) {
|
||||
// Probe bandwidth periodically when in ALR state.
|
||||
if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) {
|
||||
int64_t next_probe_time_ms =
|
||||
std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) +
|
||||
kAlrPeriodicProbingIntervalMs;
|
||||
if (now_ms >= next_probe_time_ms) {
|
||||
return InitiateProbing(now_ms, {estimated_bitrate_bps_ * 2}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
}
|
||||
|
||||
std::vector<ProbeClusterConfig> ProbeController::GetAndResetPendingProbes() {
|
||||
if (pending_probes_.empty())
|
||||
return std::vector<ProbeClusterConfig>();
|
||||
std::vector<ProbeClusterConfig> pending_probes;
|
||||
pending_probes_.swap(pending_probes);
|
||||
return pending_probes;
|
||||
}
|
||||
|
||||
void ProbeController::InitiateProbing(
|
||||
std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
|
||||
int64_t now_ms,
|
||||
std::initializer_list<int64_t> bitrates_to_probe,
|
||||
bool probe_further) {
|
||||
std::vector<ProbeClusterConfig> pending_probes;
|
||||
for (int64_t bitrate : bitrates_to_probe) {
|
||||
RTC_DCHECK_GT(bitrate, 0);
|
||||
int64_t max_probe_bitrate_bps =
|
||||
@ -321,7 +324,7 @@ void ProbeController::InitiateProbing(
|
||||
config.target_data_rate = DataRate::bps(rtc::dchecked_cast<int>(bitrate));
|
||||
config.target_duration = TimeDelta::ms(kMinProbeDurationMs);
|
||||
config.target_probe_count = kMinProbePacketsSent;
|
||||
pending_probes_.push_back(config);
|
||||
pending_probes.push_back(config);
|
||||
}
|
||||
time_last_probing_initiated_ms_ = now_ms;
|
||||
if (probe_further) {
|
||||
@ -332,6 +335,7 @@ void ProbeController::InitiateProbing(
|
||||
state_ = State::kProbingComplete;
|
||||
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
|
||||
}
|
||||
return pending_probes;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/transport/network_control.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/system/unused.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -32,34 +33,39 @@ class ProbeController {
|
||||
ProbeController();
|
||||
~ProbeController();
|
||||
|
||||
void SetBitrates(int64_t min_bitrate_bps,
|
||||
int64_t start_bitrate_bps,
|
||||
int64_t max_bitrate_bps,
|
||||
int64_t at_time_ms);
|
||||
RTC_WARN_UNUSED_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);
|
||||
|
||||
// The total bitrate, as opposed to the max bitrate, is the sum of the
|
||||
// configured bitrates for all active streams.
|
||||
void OnMaxTotalAllocatedBitrate(int64_t max_total_allocated_bitrate,
|
||||
int64_t at_time_ms);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig>
|
||||
OnMaxTotalAllocatedBitrate(int64_t max_total_allocated_bitrate,
|
||||
int64_t at_time_ms);
|
||||
|
||||
void OnNetworkAvailability(NetworkAvailability msg);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> OnNetworkAvailability(
|
||||
NetworkAvailability msg);
|
||||
|
||||
void SetEstimatedBitrate(int64_t bitrate_bps, int64_t at_time_ms);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> SetEstimatedBitrate(
|
||||
int64_t bitrate_bps,
|
||||
int64_t at_time_ms);
|
||||
|
||||
void EnablePeriodicAlrProbing(bool enable);
|
||||
|
||||
void SetAlrStartTimeMs(absl::optional<int64_t> alr_start_time);
|
||||
void SetAlrEndedTimeMs(int64_t alr_end_time);
|
||||
|
||||
void RequestProbe(int64_t at_time_ms);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> RequestProbe(
|
||||
int64_t at_time_ms);
|
||||
|
||||
// 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 Process(int64_t at_time_ms);
|
||||
|
||||
std::vector<ProbeClusterConfig> GetAndResetPendingProbes();
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> Process(
|
||||
int64_t at_time_ms);
|
||||
|
||||
private:
|
||||
enum class State {
|
||||
@ -71,10 +77,12 @@ class ProbeController {
|
||||
kProbingComplete,
|
||||
};
|
||||
|
||||
void InitiateExponentialProbing(int64_t at_time_ms);
|
||||
void InitiateProbing(int64_t now_ms,
|
||||
std::initializer_list<int64_t> bitrates_to_probe,
|
||||
bool probe_further);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig>
|
||||
InitiateExponentialProbing(int64_t at_time_ms);
|
||||
RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> InitiateProbing(
|
||||
int64_t now_ms,
|
||||
std::initializer_list<int64_t> bitrates_to_probe,
|
||||
bool probe_further);
|
||||
|
||||
bool network_available_;
|
||||
State state_;
|
||||
@ -97,8 +105,6 @@ class ProbeController {
|
||||
int64_t mid_call_probing_bitrate_bps_;
|
||||
int64_t mid_call_probing_succcess_threshold_;
|
||||
|
||||
std::vector<ProbeClusterConfig> pending_probes_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ProbeController);
|
||||
};
|
||||
|
||||
|
@ -47,11 +47,11 @@ class ProbeControllerTest : public ::testing::Test {
|
||||
}
|
||||
~ProbeControllerTest() override {}
|
||||
|
||||
void SetNetworkAvailable(bool available) {
|
||||
std::vector<ProbeClusterConfig> SetNetworkAvailable(bool available) {
|
||||
NetworkAvailability msg;
|
||||
msg.at_time = Timestamp::ms(NowMs());
|
||||
msg.network_available = available;
|
||||
probe_controller_->OnNetworkAvailability(msg);
|
||||
return probe_controller_->OnNetworkAvailability(msg);
|
||||
}
|
||||
|
||||
int64_t NowMs() { return clock_.TimeInMilliseconds(); }
|
||||
@ -61,183 +61,165 @@ class ProbeControllerTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(ProbeControllerTest, InitiatesProbingAtStart) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_GE(probes.size(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
|
||||
SetNetworkAvailable(false);
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
SetNetworkAvailable(true);
|
||||
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
probes = SetNetworkAvailable(true);
|
||||
EXPECT_GE(probes.size(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
// Long enough to time out exponential probing.
|
||||
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
|
||||
probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
|
||||
probe_controller_->Process(NowMs());
|
||||
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps + 100, NowMs());
|
||||
|
||||
EXPECT_EQ(
|
||||
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
|
||||
kMaxBitrateBps + 100);
|
||||
probes = probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps + 100, NowMs());
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
// Long enough to time out exponential probing.
|
||||
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
|
||||
probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
|
||||
probe_controller_->Process(NowMs());
|
||||
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
|
||||
probe_controller_->SetEstimatedBitrate(kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps + 100, NowMs());
|
||||
EXPECT_EQ(
|
||||
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
|
||||
kMaxBitrateBps + 100);
|
||||
probes = probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(kMaxBitrateBps, NowMs());
|
||||
probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps + 100, NowMs());
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, TestExponentialProbing) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->GetAndResetPendingProbes();
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
|
||||
// Repeated probe should only be sent when estimated bitrate climbs above
|
||||
// 0.7 * 6 * kStartBitrateBps = 1260.
|
||||
probe_controller_->SetEstimatedBitrate(1000, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(1000, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
|
||||
probe_controller_->SetEstimatedBitrate(1800, NowMs());
|
||||
EXPECT_EQ(
|
||||
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
|
||||
2 * 1800);
|
||||
probes = probe_controller_->SetEstimatedBitrate(1800, NowMs());
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->GetAndResetPendingProbes();
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
// Advance far enough to cause a time out in waiting for probing result.
|
||||
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
|
||||
probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
|
||||
probe_controller_->SetEstimatedBitrate(1800, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(1800, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, RequestProbeInAlr) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_GE(probes.size(), 2u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds());
|
||||
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probe_controller_->RequestProbe(NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probes = probe_controller_->RequestProbe(NowMs());
|
||||
|
||||
std::vector<ProbeClusterConfig> probes =
|
||||
probe_controller_->GetAndResetPendingProbes();
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(absl::nullopt);
|
||||
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds());
|
||||
clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs - 1);
|
||||
probe_controller_->RequestProbe(NowMs());
|
||||
probes = probe_controller_->RequestProbe(NowMs());
|
||||
|
||||
std::vector<ProbeClusterConfig> probes =
|
||||
probe_controller_->GetAndResetPendingProbes();
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(absl::nullopt);
|
||||
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds());
|
||||
clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs + 1);
|
||||
probe_controller_->RequestProbe(NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes = probe_controller_->RequestProbe(NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds());
|
||||
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
|
||||
clock_.AdvanceTimeMilliseconds(kBitrateDropTimeoutMs + 1);
|
||||
probe_controller_->RequestProbe(NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes = probe_controller_->RequestProbe(NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, PeriodicProbing) {
|
||||
probe_controller_->EnablePeriodicAlrProbing(true);
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
int64_t start_time = clock_.TimeInMilliseconds();
|
||||
|
||||
// Expect the controller to send a new probe after 5s has passed.
|
||||
probe_controller_->SetAlrStartTimeMs(start_time);
|
||||
clock_.AdvanceTimeMilliseconds(5000);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
std::vector<ProbeClusterConfig> probes =
|
||||
probe_controller_->GetAndResetPendingProbes();
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000);
|
||||
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
|
||||
// The following probe should be sent at 10s into ALR.
|
||||
probe_controller_->SetAlrStartTimeMs(start_time);
|
||||
clock_.AdvanceTimeMilliseconds(4000);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(start_time);
|
||||
clock_.AdvanceTimeMilliseconds(1000);
|
||||
probe_controller_->Process(NowMs());
|
||||
probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 1u);
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) {
|
||||
@ -246,42 +228,39 @@ TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) {
|
||||
|
||||
probe_controller_->SetAlrStartTimeMs(alr_start_time);
|
||||
probe_controller_->EnablePeriodicAlrProbing(true);
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
probe_controller_->Reset(NowMs());
|
||||
|
||||
clock_.AdvanceTimeMilliseconds(10000);
|
||||
probe_controller_->Process(NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
// Since bitrates are not yet set, no probe is sent event though we are in ALR
|
||||
// mode.
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u);
|
||||
probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
|
||||
kMaxBitrateBps, NowMs());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
|
||||
// Make sure we use |kStartBitrateBps| as the estimated bitrate
|
||||
// until SetEstimatedBitrate is called with an updated estimate.
|
||||
clock_.AdvanceTimeMilliseconds(10000);
|
||||
probe_controller_->Process(NowMs());
|
||||
EXPECT_EQ(
|
||||
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
|
||||
kStartBitrateBps * 2);
|
||||
probes = probe_controller_->Process(NowMs());
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), kStartBitrateBps * 2);
|
||||
}
|
||||
|
||||
TEST_F(ProbeControllerTest, TestExponentialProbingOverflow) {
|
||||
const int64_t kMbpsMultiplier = 1000000;
|
||||
probe_controller_->SetBitrates(kMinBitrateBps, 10 * kMbpsMultiplier,
|
||||
100 * kMbpsMultiplier, NowMs());
|
||||
|
||||
probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier, NowMs());
|
||||
|
||||
auto probes = probe_controller_->SetBitrates(
|
||||
kMinBitrateBps, 10 * kMbpsMultiplier, 100 * kMbpsMultiplier, NowMs());
|
||||
// Verify that probe bitrate is capped at the specified max bitrate.
|
||||
EXPECT_EQ(
|
||||
probe_controller_->GetAndResetPendingProbes()[2].target_data_rate.bps(),
|
||||
100 * kMbpsMultiplier);
|
||||
|
||||
probes =
|
||||
probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier, NowMs());
|
||||
EXPECT_EQ(probes[0].target_data_rate.bps(), 100 * kMbpsMultiplier);
|
||||
// Verify that repeated probes aren't sent.
|
||||
probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier, NowMs());
|
||||
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u);
|
||||
probes =
|
||||
probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier, NowMs());
|
||||
EXPECT_EQ(probes.size(), 0u);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
@ -132,7 +132,8 @@ class SendSideCongestionController
|
||||
uint8_t fraction_loss,
|
||||
int64_t rtt);
|
||||
void LimitOutstandingBytes(size_t num_outstanding_bytes);
|
||||
void SendPendingProbes() RTC_EXCLUSIVE_LOCKS_REQUIRED(&probe_lock_);
|
||||
void SendProbes(std::vector<ProbeClusterConfig> probe_configs)
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(&probe_lock_);
|
||||
const Clock* const clock_;
|
||||
rtc::CriticalSection observer_lock_;
|
||||
Observer* observer_ RTC_GUARDED_BY(observer_lock_);
|
||||
|
@ -200,10 +200,9 @@ void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps,
|
||||
|
||||
{
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps,
|
||||
max_bitrate_bps,
|
||||
clock_->TimeInMilliseconds());
|
||||
SendPendingProbes();
|
||||
SendProbes(probe_controller_->SetBitrates(
|
||||
min_bitrate_bps, start_bitrate_bps, max_bitrate_bps,
|
||||
clock_->TimeInMilliseconds()));
|
||||
}
|
||||
|
||||
{
|
||||
@ -223,9 +222,8 @@ void SendSideCongestionController::SetAllocatedSendBitrateLimits(
|
||||
pacer_->SetSendBitrateLimits(min_send_bitrate_bps, max_padding_bitrate_bps);
|
||||
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->OnMaxTotalAllocatedBitrate(max_total_bitrate_bps,
|
||||
clock_->TimeInMilliseconds());
|
||||
SendPendingProbes();
|
||||
SendProbes(probe_controller_->OnMaxTotalAllocatedBitrate(
|
||||
max_total_bitrate_bps, clock_->TimeInMilliseconds()));
|
||||
}
|
||||
|
||||
// TODO(holmer): Split this up and use SetBweBitrates in combination with
|
||||
@ -255,10 +253,9 @@ void SendSideCongestionController::OnNetworkRouteChanged(
|
||||
{
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->Reset(clock_->TimeInMilliseconds());
|
||||
probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps,
|
||||
max_bitrate_bps,
|
||||
clock_->TimeInMilliseconds());
|
||||
SendPendingProbes();
|
||||
SendProbes(probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps,
|
||||
max_bitrate_bps,
|
||||
clock_->TimeInMilliseconds()));
|
||||
}
|
||||
|
||||
MaybeTriggerOnNetworkChanged();
|
||||
@ -321,8 +318,7 @@ void SendSideCongestionController::SignalNetworkState(NetworkState state) {
|
||||
NetworkAvailability msg;
|
||||
msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds());
|
||||
msg.network_available = state == kNetworkUp;
|
||||
probe_controller_->OnNetworkAvailability(msg);
|
||||
SendPendingProbes();
|
||||
SendProbes(probe_controller_->OnNetworkAvailability(msg));
|
||||
}
|
||||
MaybeTriggerOnNetworkChanged();
|
||||
}
|
||||
@ -355,8 +351,9 @@ int64_t SendSideCongestionController::TimeUntilNextProcess() {
|
||||
return bitrate_controller_->TimeUntilNextProcess();
|
||||
}
|
||||
|
||||
void SendSideCongestionController::SendPendingProbes() {
|
||||
for (auto probe_config : probe_controller_->GetAndResetPendingProbes()) {
|
||||
void SendSideCongestionController::SendProbes(
|
||||
std::vector<ProbeClusterConfig> probe_configs) {
|
||||
for (auto probe_config : probe_configs) {
|
||||
pacer_->CreateProbeCluster(probe_config.target_data_rate.bps());
|
||||
}
|
||||
}
|
||||
@ -382,8 +379,7 @@ void SendSideCongestionController::Process() {
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->SetAlrStartTimeMs(
|
||||
pacer_->GetApplicationLimitedRegionStartTime());
|
||||
probe_controller_->Process(clock_->TimeInMilliseconds());
|
||||
SendPendingProbes();
|
||||
SendProbes(probe_controller_->Process(clock_->TimeInMilliseconds()));
|
||||
}
|
||||
MaybeTriggerOnNetworkChanged();
|
||||
}
|
||||
@ -437,7 +433,7 @@ void SendSideCongestionController::OnTransportFeedback(
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->SetAlrStartTimeMs(
|
||||
pacer_->GetApplicationLimitedRegionStartTime());
|
||||
probe_controller_->RequestProbe(clock_->TimeInMilliseconds());
|
||||
SendProbes(probe_controller_->RequestProbe(clock_->TimeInMilliseconds()));
|
||||
}
|
||||
if (in_cwnd_experiment_) {
|
||||
LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
|
||||
@ -501,8 +497,8 @@ void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {
|
||||
pacer_->SetEstimatedBitrate(bitrate_bps);
|
||||
{
|
||||
rtc::CritScope cs(&probe_lock_);
|
||||
probe_controller_->SetEstimatedBitrate(bitrate_bps,
|
||||
clock_->TimeInMilliseconds());
|
||||
SendProbes(probe_controller_->SetEstimatedBitrate(
|
||||
bitrate_bps, clock_->TimeInMilliseconds()));
|
||||
}
|
||||
retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
|
||||
}
|
||||
|
Reference in New Issue
Block a user