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:
Sebastian Jansson
2018-08-02 16:27:28 +02:00
committed by Commit Bot
parent dc6e68b4a7
commit da2ec40590
8 changed files with 283 additions and 263 deletions

View File

@ -135,6 +135,7 @@ rtc_source_set("probe_controller") {
"../../../logging:rtc_event_pacing", "../../../logging:rtc_event_pacing",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:rtc_base_approved", "../../../rtc_base:rtc_base_approved",
"../../../rtc_base/system:unused",
"../../../system_wrappers:field_trial_api", "../../../system_wrappers:field_trial_api",
"../../../system_wrappers:metrics_api", "../../../system_wrappers:metrics_api",
"//third_party/abseil-cpp/absl/types:optional", "//third_party/abseil-cpp/absl/types:optional",

View File

@ -122,16 +122,18 @@ GoogCcNetworkController::GoogCcNetworkController(RtcEventLog* event_log,
delay_based_bwe_(new DelayBasedBwe(event_log_)), delay_based_bwe_(new DelayBasedBwe(event_log_)),
acknowledged_bitrate_estimator_( acknowledged_bitrate_estimator_(
absl::make_unique<AcknowledgedBitrateEstimator>()), absl::make_unique<AcknowledgedBitrateEstimator>()),
initial_config_(config),
last_bandwidth_(config.starting_bandwidth), last_bandwidth_(config.starting_bandwidth),
pacing_factor_(kDefaultPaceMultiplier), pacing_factor_(config.stream_based_config.pacing_factor.value_or(
min_pacing_rate_(DataRate::Zero()), kDefaultPaceMultiplier)),
max_padding_rate_(DataRate::Zero()), 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()), max_total_allocated_bitrate_(DataRate::Zero()),
in_cwnd_experiment_(CwndExperimentEnabled()), in_cwnd_experiment_(CwndExperimentEnabled()),
accepted_queue_ms_(kDefaultAcceptedQueueMs) { accepted_queue_ms_(kDefaultAcceptedQueueMs) {
delay_based_bwe_->SetMinBitrate(congestion_controller::GetMinBitrateBps()); delay_based_bwe_->SetMinBitrate(congestion_controller::GetMinBitrateBps());
UpdateBitrateConstraints(config.constraints, config.starting_bandwidth);
OnStreamsConfig(config.stream_based_config);
if (in_cwnd_experiment_ && if (in_cwnd_experiment_ &&
!ReadCwndExperimentParameter(&accepted_queue_ms_)) { !ReadCwndExperimentParameter(&accepted_queue_ms_)) {
RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment " RTC_LOG(LS_WARNING) << "Failed to parse parameters for CwndExperiment "
@ -144,8 +146,9 @@ GoogCcNetworkController::~GoogCcNetworkController() {}
NetworkControlUpdate GoogCcNetworkController::OnNetworkAvailability( NetworkControlUpdate GoogCcNetworkController::OnNetworkAvailability(
NetworkAvailability msg) { NetworkAvailability msg) {
probe_controller_->OnNetworkAvailability(msg); NetworkControlUpdate update;
return NetworkControlUpdate(); update.probe_cluster_configs = probe_controller_->OnNetworkAvailability(msg);
return update;
} }
NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange( NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
@ -166,24 +169,46 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange(
delay_based_bwe_->SetMinBitrate(min_bitrate_bps); delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
probe_controller_->Reset(msg.at_time.ms()); probe_controller_->Reset(msg.at_time.ms());
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, NetworkControlUpdate update;
max_bitrate_bps, msg.at_time.ms()); update.probe_cluster_configs = probe_controller_->SetBitrates(
min_bitrate_bps, start_bitrate_bps, max_bitrate_bps, msg.at_time.ms());
return MaybeTriggerOnNetworkChanged(msg.at_time); MaybeTriggerOnNetworkChanged(&update, msg.at_time);
return update;
} }
NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( NetworkControlUpdate GoogCcNetworkController::OnProcessInterval(
ProcessInterval msg) { 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()); bandwidth_estimation_->UpdateEstimate(msg.at_time.ms());
absl::optional<int64_t> start_time_ms = absl::optional<int64_t> start_time_ms =
alr_detector_->GetApplicationLimitedRegionStartTime(); alr_detector_->GetApplicationLimitedRegionStartTime();
probe_controller_->SetAlrStartTimeMs(start_time_ms); probe_controller_->SetAlrStartTimeMs(start_time_ms);
probe_controller_->Process(msg.at_time.ms());
NetworkControlUpdate update = MaybeTriggerOnNetworkChanged(msg.at_time); auto probes = probe_controller_->Process(msg.at_time.ms());
for (const ProbeClusterConfig& config : update.probe_cluster_configs.insert(update.probe_cluster_configs.end(),
probe_controller_->GetAndResetPendingProbes()) { probes.begin(), probes.end());
update.probe_cluster_configs.push_back(config);
} MaybeTriggerOnNetworkChanged(&update, msg.at_time);
return update; return update;
} }
@ -216,11 +241,13 @@ NetworkControlUpdate GoogCcNetworkController::OnSentPacket(
NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
StreamsConfig msg) { StreamsConfig msg) {
NetworkControlUpdate update;
probe_controller_->EnablePeriodicAlrProbing(msg.requests_alr_probing); probe_controller_->EnablePeriodicAlrProbing(msg.requests_alr_probing);
if (msg.max_total_allocated_bitrate && if (msg.max_total_allocated_bitrate &&
*msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) { *msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) {
probe_controller_->OnMaxTotalAllocatedBitrate( update.probe_cluster_configs =
msg.max_total_allocated_bitrate->bps(), msg.at_time.ms()); probe_controller_->OnMaxTotalAllocatedBitrate(
msg.max_total_allocated_bitrate->bps(), msg.at_time.ms());
max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate; max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate;
} }
bool pacing_changed = false; bool pacing_changed = false;
@ -236,19 +263,22 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig(
max_padding_rate_ = *msg.max_padding_rate; max_padding_rate_ = *msg.max_padding_rate;
pacing_changed = true; pacing_changed = true;
} }
NetworkControlUpdate update;
if (pacing_changed) if (pacing_changed)
update.pacer_config = UpdatePacingRates(msg.at_time); update.pacer_config = GetPacingRates(msg.at_time);
return update; return update;
} }
NetworkControlUpdate GoogCcNetworkController::OnTargetRateConstraints( NetworkControlUpdate GoogCcNetworkController::OnTargetRateConstraints(
TargetRateConstraints constraints) { TargetRateConstraints constraints) {
UpdateBitrateConstraints(constraints, absl::nullopt); NetworkControlUpdate update;
return MaybeTriggerOnNetworkChanged(constraints.at_time); 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, TargetRateConstraints constraints,
absl::optional<DataRate> starting_rate) { absl::optional<DataRate> starting_rate) {
int64_t min_bitrate_bps = GetBpsOrDefault(constraints.min_data_rate, 0); 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); ClampBitrates(&start_bitrate_bps, &min_bitrate_bps, &max_bitrate_bps);
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, std::vector<ProbeClusterConfig> probes(probe_controller_->SetBitrates(
max_bitrate_bps, constraints.at_time.ms()); min_bitrate_bps, start_bitrate_bps, max_bitrate_bps,
constraints.at_time.ms()));
bandwidth_estimation_->SetBitrates(start_bitrate_bps, min_bitrate_bps, bandwidth_estimation_->SetBitrates(start_bitrate_bps, min_bitrate_bps,
max_bitrate_bps); max_bitrate_bps);
if (start_bitrate_bps > 0) if (start_bitrate_bps > 0)
delay_based_bwe_->SetStartBitrate(start_bitrate_bps); delay_based_bwe_->SetStartBitrate(start_bitrate_bps);
delay_based_bwe_->SetMinBitrate(min_bitrate_bps); delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
return probes;
} }
NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport( NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport(
@ -326,11 +358,13 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback(
bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time.ms(), bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time.ms(),
result.target_bitrate_bps); result.target_bitrate_bps);
// Update the estimate in the ProbeController, in case we want to probe. // 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) { if (result.recovered_from_overuse) {
probe_controller_->SetAlrStartTimeMs(alr_start_time); 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(); update.congestion_window = MaybeUpdateCongestionWindow();
return update; return update;
@ -351,7 +385,7 @@ NetworkControlUpdate GoogCcNetworkController::GetNetworkState(
TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs()); TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs());
update.target_rate->at_time = at_time; update.target_rate->at_time = at_time;
update.target_rate->target_rate = bandwidth; update.target_rate->target_rate = bandwidth;
update.pacer_config = UpdatePacingRates(at_time); update.pacer_config = GetPacingRates(at_time);
update.congestion_window = current_data_window_; update.congestion_window = current_data_window_;
return update; return update;
} }
@ -381,7 +415,8 @@ GoogCcNetworkController::MaybeUpdateCongestionWindow() {
return data_window; return data_window;
} }
NetworkControlUpdate GoogCcNetworkController::MaybeTriggerOnNetworkChanged( void GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
NetworkControlUpdate* update,
Timestamp at_time) { Timestamp at_time) {
int32_t estimated_bitrate_bps; int32_t estimated_bitrate_bps;
uint8_t fraction_loss; uint8_t fraction_loss;
@ -390,19 +425,33 @@ NetworkControlUpdate GoogCcNetworkController::MaybeTriggerOnNetworkChanged(
bool estimate_changed = GetNetworkParameters( bool estimate_changed = GetNetworkParameters(
&estimated_bitrate_bps, &fraction_loss, &rtt_ms, at_time); &estimated_bitrate_bps, &fraction_loss, &rtt_ms, at_time);
if (estimate_changed) { if (estimate_changed) {
alr_detector_->SetEstimatedBitrate(estimated_bitrate_bps);
DataRate bandwidth = DataRate::bps(estimated_bitrate_bps);
last_bandwidth_ = bandwidth;
TimeDelta bwe_period = TimeDelta bwe_period =
TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs()); TimeDelta::ms(delay_based_bwe_->GetExpectedBwePeriodMs());
NetworkEstimate new_estimate; TargetTransferRate target_rate;
new_estimate.at_time = at_time; target_rate.at_time = at_time;
new_estimate.round_trip_time = TimeDelta::ms(rtt_ms); // Set the target rate to the full estimated bandwidth since the estimation
new_estimate.bandwidth = DataRate::bps(estimated_bitrate_bps); // for legacy reasons includes target rate constraints.
new_estimate.loss_rate_ratio = fraction_loss / 255.0f; target_rate.target_rate = bandwidth;
new_estimate.bwe_period = bwe_period;
last_bandwidth_ = new_estimate.bandwidth; target_rate.network_estimate.at_time = at_time;
return OnNetworkEstimate(new_estimate); 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( bool GoogCcNetworkController::GetNetworkParameters(
@ -434,26 +483,7 @@ bool GoogCcNetworkController::GetNetworkParameters(
return estimate_changed; return estimate_changed;
} }
NetworkControlUpdate GoogCcNetworkController::OnNetworkEstimate( PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const {
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 {
DataRate pacing_rate = DataRate pacing_rate =
std::max(min_pacing_rate_, last_bandwidth_) * pacing_factor_; std::max(min_pacing_rate_, last_bandwidth_) * pacing_factor_;
DataRate padding_rate = std::min(max_padding_rate_, last_bandwidth_); DataRate padding_rate = std::min(max_padding_rate_, last_bandwidth_);

View File

@ -52,16 +52,17 @@ class GoogCcNetworkController : public NetworkControllerInterface {
NetworkControlUpdate GetNetworkState(Timestamp at_time) const; NetworkControlUpdate GetNetworkState(Timestamp at_time) const;
private: private:
void UpdateBitrateConstraints(TargetRateConstraints constraints, std::vector<ProbeClusterConfig> UpdateBitrateConstraints(
absl::optional<DataRate> starting_rate); TargetRateConstraints constraints,
absl::optional<DataRate> starting_rate);
absl::optional<DataSize> MaybeUpdateCongestionWindow(); absl::optional<DataSize> MaybeUpdateCongestionWindow();
NetworkControlUpdate MaybeTriggerOnNetworkChanged(Timestamp at_time); void MaybeTriggerOnNetworkChanged(NetworkControlUpdate* update,
Timestamp at_time);
bool GetNetworkParameters(int32_t* estimated_bitrate_bps, bool GetNetworkParameters(int32_t* estimated_bitrate_bps,
uint8_t* fraction_loss, uint8_t* fraction_loss,
int64_t* rtt_ms, int64_t* rtt_ms,
Timestamp at_time); Timestamp at_time);
NetworkControlUpdate OnNetworkEstimate(NetworkEstimate msg); PacerConfig GetPacingRates(Timestamp at_time) const;
PacerConfig UpdatePacingRates(Timestamp at_time) const;
RtcEventLog* const event_log_; RtcEventLog* const event_log_;
@ -72,6 +73,8 @@ class GoogCcNetworkController : public NetworkControllerInterface {
std::unique_ptr<DelayBasedBwe> delay_based_bwe_; std::unique_ptr<DelayBasedBwe> delay_based_bwe_;
std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator_; std::unique_ptr<AcknowledgedBitrateEstimator> acknowledged_bitrate_estimator_;
absl::optional<NetworkControllerConfig> initial_config_;
std::deque<int64_t> feedback_rtts_; std::deque<int64_t> feedback_rtts_;
absl::optional<int64_t> min_feedback_rtt_ms_; absl::optional<int64_t> min_feedback_rtt_ms_;

View File

@ -83,10 +83,11 @@ ProbeController::ProbeController() : enable_periodic_alr_probing_(false) {
ProbeController::~ProbeController() {} ProbeController::~ProbeController() {}
void ProbeController::SetBitrates(int64_t min_bitrate_bps, std::vector<ProbeClusterConfig> ProbeController::SetBitrates(
int64_t start_bitrate_bps, int64_t min_bitrate_bps,
int64_t max_bitrate_bps, int64_t start_bitrate_bps,
int64_t at_time_ms) { int64_t max_bitrate_bps,
int64_t at_time_ms) {
if (start_bitrate_bps > 0) { if (start_bitrate_bps > 0) {
start_bitrate_bps_ = start_bitrate_bps; start_bitrate_bps_ = start_bitrate_bps;
estimated_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_) { switch (state_) {
case State::kInit: case State::kInit:
if (network_available_) if (network_available_)
InitiateExponentialProbing(at_time_ms); return InitiateExponentialProbing(at_time_ms);
break; break;
case State::kWaitingForProbingResult: case State::kWaitingForProbingResult:
@ -125,13 +126,14 @@ void ProbeController::SetBitrates(int64_t min_bitrate_bps,
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated", RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated",
max_bitrate_bps_ / 1000); max_bitrate_bps_ / 1000);
InitiateProbing(at_time_ms, {max_bitrate_bps}, false); return InitiateProbing(at_time_ms, {max_bitrate_bps}, false);
} }
break; break;
} }
return std::vector<ProbeClusterConfig>();
} }
void ProbeController::OnMaxTotalAllocatedBitrate( std::vector<ProbeClusterConfig> ProbeController::OnMaxTotalAllocatedBitrate(
int64_t max_total_allocated_bitrate, int64_t max_total_allocated_bitrate,
int64_t at_time_ms) { int64_t at_time_ms) {
// TODO(philipel): Should |max_total_allocated_bitrate| be used as a limit for // 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_) && (max_bitrate_bps_ <= 0 || estimated_bitrate_bps_ < max_bitrate_bps_) &&
estimated_bitrate_bps_ < max_total_allocated_bitrate) { estimated_bitrate_bps_ < max_total_allocated_bitrate) {
max_total_allocated_bitrate_ = 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; network_available_ = msg.network_available;
if (!network_available_ && state_ == State::kWaitingForProbingResult) { 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) 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(network_available_);
RTC_DCHECK(state_ == State::kInit); RTC_DCHECK(state_ == State::kInit);
RTC_DCHECK_GT(start_bitrate_bps_, 0); RTC_DCHECK_GT(start_bitrate_bps_, 0);
// When probing at 1.8 Mbps ( 6x 300), this represents a threshold of // When probing at 1.8 Mbps ( 6x 300), this represents a threshold of
// 1.2 Mbps to continue probing. // 1.2 Mbps to continue probing.
InitiateProbing(at_time_ms, {3 * start_bitrate_bps_, 6 * start_bitrate_bps_}, return InitiateProbing(
true); at_time_ms, {3 * start_bitrate_bps_, 6 * start_bitrate_bps_}, true);
} }
void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps, std::vector<ProbeClusterConfig> ProbeController::SetEstimatedBitrate(
int64_t at_time_ms) { int64_t bitrate_bps,
int64_t at_time_ms) {
int64_t now_ms = at_time_ms; int64_t now_ms = at_time_ms;
if (mid_call_probing_waiting_for_result_ && if (mid_call_probing_waiting_for_result_ &&
@ -181,7 +188,7 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
bitrate_bps / 1000); bitrate_bps / 1000);
mid_call_probing_waiting_for_result_ = false; mid_call_probing_waiting_for_result_ = false;
} }
std::vector<ProbeClusterConfig> pending_probes;
if (state_ == State::kWaitingForProbingResult) { if (state_ == State::kWaitingForProbingResult) {
// Continue probing if probing results indicate channel has greater // Continue probing if probing results indicate channel has greater
// capacity. // capacity.
@ -192,7 +199,7 @@ void ProbeController::SetEstimatedBitrate(int64_t bitrate_bps,
if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled && if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
bitrate_bps > min_bitrate_to_probe_further_bps_) { bitrate_bps > min_bitrate_to_probe_further_bps_) {
// Double the probing bitrate. // 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; estimated_bitrate_bps_ = bitrate_bps;
return pending_probes;
} }
void ProbeController::EnablePeriodicAlrProbing(bool enable) { 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); 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 // Called once we have returned to normal state after a large drop in
// estimated bandwidth. The current response is to initiate a single probe // estimated bandwidth. The current response is to initiate a single probe
// session (if not already probing) at the previous bitrate. // 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( RTC_HISTOGRAM_COUNTS_10000(
"WebRTC.BWE.BweDropProbingIntervalInS", "WebRTC.BWE.BweDropProbingIntervalInS",
(at_time_ms - last_bwe_drop_probing_time_ms_) / 1000); (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; last_bwe_drop_probing_time_ms_ = at_time_ms;
} }
} }
} }
return std::vector<ProbeClusterConfig>();
} }
void ProbeController::Reset(int64_t at_time_ms) { 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; 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; int64_t now_ms = at_time_ms;
if (now_ms - time_last_probing_initiated_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_) if (enable_periodic_alr_probing_ && state_ == State::kProbingComplete) {
return; // Probe bandwidth periodically when in ALR state.
if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) {
// Probe bandwidth periodically when in ALR state. int64_t next_probe_time_ms =
if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) { std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) +
int64_t next_probe_time_ms = kAlrPeriodicProbingIntervalMs;
std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) + if (now_ms >= next_probe_time_ms) {
kAlrPeriodicProbingIntervalMs; return InitiateProbing(now_ms, {estimated_bitrate_bps_ * 2}, true);
if (now_ms >= next_probe_time_ms) { }
InitiateProbing(now_ms, {estimated_bitrate_bps_ * 2}, true);
} }
} }
return std::vector<ProbeClusterConfig>();
} }
std::vector<ProbeClusterConfig> ProbeController::GetAndResetPendingProbes() { std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
if (pending_probes_.empty())
return std::vector<ProbeClusterConfig>();
std::vector<ProbeClusterConfig> pending_probes;
pending_probes_.swap(pending_probes);
return pending_probes;
}
void ProbeController::InitiateProbing(
int64_t now_ms, int64_t now_ms,
std::initializer_list<int64_t> bitrates_to_probe, std::initializer_list<int64_t> bitrates_to_probe,
bool probe_further) { bool probe_further) {
std::vector<ProbeClusterConfig> pending_probes;
for (int64_t bitrate : bitrates_to_probe) { for (int64_t bitrate : bitrates_to_probe) {
RTC_DCHECK_GT(bitrate, 0); RTC_DCHECK_GT(bitrate, 0);
int64_t max_probe_bitrate_bps = 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_data_rate = DataRate::bps(rtc::dchecked_cast<int>(bitrate));
config.target_duration = TimeDelta::ms(kMinProbeDurationMs); config.target_duration = TimeDelta::ms(kMinProbeDurationMs);
config.target_probe_count = kMinProbePacketsSent; config.target_probe_count = kMinProbePacketsSent;
pending_probes_.push_back(config); pending_probes.push_back(config);
} }
time_last_probing_initiated_ms_ = now_ms; time_last_probing_initiated_ms_ = now_ms;
if (probe_further) { if (probe_further) {
@ -332,6 +335,7 @@ void ProbeController::InitiateProbing(
state_ = State::kProbingComplete; state_ = State::kProbingComplete;
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
} }
return pending_probes;
} }
} // namespace webrtc } // namespace webrtc

View File

@ -19,6 +19,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/transport/network_control.h" #include "api/transport/network_control.h"
#include "rtc_base/constructormagic.h" #include "rtc_base/constructormagic.h"
#include "rtc_base/system/unused.h"
namespace webrtc { namespace webrtc {
@ -32,34 +33,39 @@ class ProbeController {
ProbeController(); ProbeController();
~ProbeController(); ~ProbeController();
void SetBitrates(int64_t min_bitrate_bps, RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> SetBitrates(
int64_t start_bitrate_bps, int64_t min_bitrate_bps,
int64_t max_bitrate_bps, int64_t start_bitrate_bps,
int64_t at_time_ms); int64_t max_bitrate_bps,
int64_t at_time_ms);
// The total bitrate, as opposed to the max bitrate, is the sum of the // The total bitrate, as opposed to the max bitrate, is the sum of the
// configured bitrates for all active streams. // configured bitrates for all active streams.
void OnMaxTotalAllocatedBitrate(int64_t max_total_allocated_bitrate, RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig>
int64_t at_time_ms); 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 EnablePeriodicAlrProbing(bool enable);
void SetAlrStartTimeMs(absl::optional<int64_t> alr_start_time); void SetAlrStartTimeMs(absl::optional<int64_t> alr_start_time);
void SetAlrEndedTimeMs(int64_t alr_end_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 // Resets the ProbeController to a state equivalent to as if it was just
// created EXCEPT for |enable_periodic_alr_probing_|. // created EXCEPT for |enable_periodic_alr_probing_|.
void Reset(int64_t at_time_ms); void Reset(int64_t at_time_ms);
void Process(int64_t at_time_ms); RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> Process(
int64_t at_time_ms);
std::vector<ProbeClusterConfig> GetAndResetPendingProbes();
private: private:
enum class State { enum class State {
@ -71,10 +77,12 @@ class ProbeController {
kProbingComplete, kProbingComplete,
}; };
void InitiateExponentialProbing(int64_t at_time_ms); RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig>
void InitiateProbing(int64_t now_ms, InitiateExponentialProbing(int64_t at_time_ms);
std::initializer_list<int64_t> bitrates_to_probe, RTC_WARN_UNUSED_RESULT std::vector<ProbeClusterConfig> InitiateProbing(
bool probe_further); int64_t now_ms,
std::initializer_list<int64_t> bitrates_to_probe,
bool probe_further);
bool network_available_; bool network_available_;
State state_; State state_;
@ -97,8 +105,6 @@ class ProbeController {
int64_t mid_call_probing_bitrate_bps_; int64_t mid_call_probing_bitrate_bps_;
int64_t mid_call_probing_succcess_threshold_; int64_t mid_call_probing_succcess_threshold_;
std::vector<ProbeClusterConfig> pending_probes_;
RTC_DISALLOW_COPY_AND_ASSIGN(ProbeController); RTC_DISALLOW_COPY_AND_ASSIGN(ProbeController);
}; };

View File

@ -47,11 +47,11 @@ class ProbeControllerTest : public ::testing::Test {
} }
~ProbeControllerTest() override {} ~ProbeControllerTest() override {}
void SetNetworkAvailable(bool available) { std::vector<ProbeClusterConfig> SetNetworkAvailable(bool available) {
NetworkAvailability msg; NetworkAvailability msg;
msg.at_time = Timestamp::ms(NowMs()); msg.at_time = Timestamp::ms(NowMs());
msg.network_available = available; msg.network_available = available;
probe_controller_->OnNetworkAvailability(msg); return probe_controller_->OnNetworkAvailability(msg);
} }
int64_t NowMs() { return clock_.TimeInMilliseconds(); } int64_t NowMs() { return clock_.TimeInMilliseconds(); }
@ -61,183 +61,165 @@ class ProbeControllerTest : public ::testing::Test {
}; };
TEST_F(ProbeControllerTest, InitiatesProbingAtStart) { TEST_F(ProbeControllerTest, InitiatesProbingAtStart) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u); EXPECT_GE(probes.size(), 2u);
} }
TEST_F(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) { TEST_F(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
SetNetworkAvailable(false); SetNetworkAvailable(false);
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
SetNetworkAvailable(true); probes = SetNetworkAvailable(true);
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u); EXPECT_GE(probes.size(), 2u);
} }
TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) { TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
// Long enough to time out exponential probing. // Long enough to time out exponential probing.
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs()); probes = probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps + 100, NowMs());
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
kMaxBitrateBps + 100, NowMs());
EXPECT_EQ(
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
kMaxBitrateBps + 100);
} }
TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) { TEST_F(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncreaseAtMaxBitrate) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
// Long enough to time out exponential probing. // Long enough to time out exponential probing.
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs()); probes = probe_controller_->SetEstimatedBitrate(kStartBitrateBps, NowMs());
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(kMaxBitrateBps, NowMs());
probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
probe_controller_->SetEstimatedBitrate(kMaxBitrateBps, NowMs()); kMaxBitrateBps + 100, NowMs());
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, EXPECT_EQ(probes[0].target_data_rate.bps(), kMaxBitrateBps + 100);
kMaxBitrateBps + 100, NowMs());
EXPECT_EQ(
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
kMaxBitrateBps + 100);
} }
TEST_F(ProbeControllerTest, TestExponentialProbing) { TEST_F(ProbeControllerTest, TestExponentialProbing) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->GetAndResetPendingProbes();
// Repeated probe should only be sent when estimated bitrate climbs above // Repeated probe should only be sent when estimated bitrate climbs above
// 0.7 * 6 * kStartBitrateBps = 1260. // 0.7 * 6 * kStartBitrateBps = 1260.
probe_controller_->SetEstimatedBitrate(1000, NowMs()); probes = probe_controller_->SetEstimatedBitrate(1000, NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
probe_controller_->SetEstimatedBitrate(1800, NowMs()); probes = probe_controller_->SetEstimatedBitrate(1800, NowMs());
EXPECT_EQ( EXPECT_EQ(probes[0].target_data_rate.bps(), 2 * 1800);
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
2 * 1800);
} }
TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) { TEST_F(ProbeControllerTest, TestExponentialProbingTimeout) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->GetAndResetPendingProbes();
// Advance far enough to cause a time out in waiting for probing result. // Advance far enough to cause a time out in waiting for probing result.
clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs); clock_.AdvanceTimeMilliseconds(kExponentialProbingTimeoutMs);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(1800, NowMs()); probes = probe_controller_->SetEstimatedBitrate(1800, NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
} }
TEST_F(ProbeControllerTest, RequestProbeInAlr) { TEST_F(ProbeControllerTest, RequestProbeInAlr) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_GE(probes.size(), 2u);
EXPECT_GE(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds()); probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds());
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(250, NowMs()); probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
probe_controller_->RequestProbe(NowMs()); probes = probe_controller_->RequestProbe(NowMs());
std::vector<ProbeClusterConfig> probes =
probe_controller_->GetAndResetPendingProbes();
EXPECT_EQ(probes.size(), 1u); EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500); EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
} }
TEST_F(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) { TEST_F(ProbeControllerTest, RequestProbeWhenAlrEndedRecently) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
probe_controller_->SetAlrStartTimeMs(absl::nullopt); probe_controller_->SetAlrStartTimeMs(absl::nullopt);
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(250, NowMs()); probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds()); probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds());
clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs - 1); 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.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500); EXPECT_EQ(probes[0].target_data_rate.bps(), 0.85 * 500);
} }
TEST_F(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) { TEST_F(ProbeControllerTest, RequestProbeWhenAlrNotEndedRecently) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
probe_controller_->SetAlrStartTimeMs(absl::nullopt); probe_controller_->SetAlrStartTimeMs(absl::nullopt);
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(250, NowMs()); probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds()); probe_controller_->SetAlrEndedTimeMs(clock_.TimeInMilliseconds());
clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs + 1); clock_.AdvanceTimeMilliseconds(kAlrEndedTimeoutMs + 1);
probe_controller_->RequestProbe(NowMs()); probes = probe_controller_->RequestProbe(NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
} }
TEST_F(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) { TEST_F(ProbeControllerTest, RequestProbeWhenBweDropNotRecent) {
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds()); probe_controller_->SetAlrStartTimeMs(clock_.TimeInMilliseconds());
clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1); clock_.AdvanceTimeMilliseconds(kAlrProbeInterval + 1);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(250, NowMs()); probes = probe_controller_->SetEstimatedBitrate(250, NowMs());
clock_.AdvanceTimeMilliseconds(kBitrateDropTimeoutMs + 1); clock_.AdvanceTimeMilliseconds(kBitrateDropTimeoutMs + 1);
probe_controller_->RequestProbe(NowMs()); probes = probe_controller_->RequestProbe(NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
} }
TEST_F(ProbeControllerTest, PeriodicProbing) { TEST_F(ProbeControllerTest, PeriodicProbing) {
probe_controller_->EnablePeriodicAlrProbing(true); probe_controller_->EnablePeriodicAlrProbing(true);
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_EQ(probes.size(), 2u);
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
int64_t start_time = clock_.TimeInMilliseconds(); int64_t start_time = clock_.TimeInMilliseconds();
// Expect the controller to send a new probe after 5s has passed. // Expect the controller to send a new probe after 5s has passed.
probe_controller_->SetAlrStartTimeMs(start_time); probe_controller_->SetAlrStartTimeMs(start_time);
clock_.AdvanceTimeMilliseconds(5000); clock_.AdvanceTimeMilliseconds(5000);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs());
std::vector<ProbeClusterConfig> probes =
probe_controller_->GetAndResetPendingProbes();
EXPECT_EQ(probes.size(), 1u); EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probes[0].target_data_rate.bps(), 1000); 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. // The following probe should be sent at 10s into ALR.
probe_controller_->SetAlrStartTimeMs(start_time); probe_controller_->SetAlrStartTimeMs(start_time);
clock_.AdvanceTimeMilliseconds(4000); clock_.AdvanceTimeMilliseconds(4000);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); EXPECT_EQ(probes.size(), 0u);
probe_controller_->SetAlrStartTimeMs(start_time); probe_controller_->SetAlrStartTimeMs(start_time);
clock_.AdvanceTimeMilliseconds(1000); clock_.AdvanceTimeMilliseconds(1000);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
probe_controller_->SetEstimatedBitrate(500, NowMs()); EXPECT_EQ(probes.size(), 1u);
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 1u); probes = probe_controller_->SetEstimatedBitrate(500, NowMs());
EXPECT_EQ(probes.size(), 0u);
} }
TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) { TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) {
@ -246,42 +228,39 @@ TEST_F(ProbeControllerTest, PeriodicProbingAfterReset) {
probe_controller_->SetAlrStartTimeMs(alr_start_time); probe_controller_->SetAlrStartTimeMs(alr_start_time);
probe_controller_->EnablePeriodicAlrProbing(true); probe_controller_->EnablePeriodicAlrProbing(true);
probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps, auto probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
probe_controller_->Reset(NowMs()); probe_controller_->Reset(NowMs());
clock_.AdvanceTimeMilliseconds(10000); clock_.AdvanceTimeMilliseconds(10000);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); // 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, probes = probe_controller_->SetBitrates(kMinBitrateBps, kStartBitrateBps,
kMaxBitrateBps, NowMs()); kMaxBitrateBps, NowMs());
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 2u); EXPECT_EQ(probes.size(), 2u);
// Make sure we use |kStartBitrateBps| as the estimated bitrate // Make sure we use |kStartBitrateBps| as the estimated bitrate
// until SetEstimatedBitrate is called with an updated estimate. // until SetEstimatedBitrate is called with an updated estimate.
clock_.AdvanceTimeMilliseconds(10000); clock_.AdvanceTimeMilliseconds(10000);
probe_controller_->Process(NowMs()); probes = probe_controller_->Process(NowMs());
EXPECT_EQ( EXPECT_EQ(probes[0].target_data_rate.bps(), kStartBitrateBps * 2);
probe_controller_->GetAndResetPendingProbes()[0].target_data_rate.bps(),
kStartBitrateBps * 2);
} }
TEST_F(ProbeControllerTest, TestExponentialProbingOverflow) { TEST_F(ProbeControllerTest, TestExponentialProbingOverflow) {
const int64_t kMbpsMultiplier = 1000000; const int64_t kMbpsMultiplier = 1000000;
probe_controller_->SetBitrates(kMinBitrateBps, 10 * kMbpsMultiplier, auto probes = probe_controller_->SetBitrates(
100 * kMbpsMultiplier, NowMs()); kMinBitrateBps, 10 * kMbpsMultiplier, 100 * kMbpsMultiplier, NowMs());
probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier, NowMs());
// Verify that probe bitrate is capped at the specified max bitrate. // Verify that probe bitrate is capped at the specified max bitrate.
EXPECT_EQ( probes =
probe_controller_->GetAndResetPendingProbes()[2].target_data_rate.bps(), probe_controller_->SetEstimatedBitrate(60 * kMbpsMultiplier, NowMs());
100 * kMbpsMultiplier); EXPECT_EQ(probes[0].target_data_rate.bps(), 100 * kMbpsMultiplier);
// Verify that repeated probes aren't sent. // Verify that repeated probes aren't sent.
probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier, NowMs()); probes =
EXPECT_EQ(probe_controller_->GetAndResetPendingProbes().size(), 0u); probe_controller_->SetEstimatedBitrate(100 * kMbpsMultiplier, NowMs());
EXPECT_EQ(probes.size(), 0u);
} }
} // namespace test } // namespace test

View File

@ -132,7 +132,8 @@ class SendSideCongestionController
uint8_t fraction_loss, uint8_t fraction_loss,
int64_t rtt); int64_t rtt);
void LimitOutstandingBytes(size_t num_outstanding_bytes); 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_; const Clock* const clock_;
rtc::CriticalSection observer_lock_; rtc::CriticalSection observer_lock_;
Observer* observer_ RTC_GUARDED_BY(observer_lock_); Observer* observer_ RTC_GUARDED_BY(observer_lock_);

View File

@ -200,10 +200,9 @@ void SendSideCongestionController::SetBweBitrates(int min_bitrate_bps,
{ {
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->SetBitrates(min_bitrate_bps, start_bitrate_bps, SendProbes(probe_controller_->SetBitrates(
max_bitrate_bps, min_bitrate_bps, start_bitrate_bps, max_bitrate_bps,
clock_->TimeInMilliseconds()); clock_->TimeInMilliseconds()));
SendPendingProbes();
} }
{ {
@ -223,9 +222,8 @@ void SendSideCongestionController::SetAllocatedSendBitrateLimits(
pacer_->SetSendBitrateLimits(min_send_bitrate_bps, max_padding_bitrate_bps); pacer_->SetSendBitrateLimits(min_send_bitrate_bps, max_padding_bitrate_bps);
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->OnMaxTotalAllocatedBitrate(max_total_bitrate_bps, SendProbes(probe_controller_->OnMaxTotalAllocatedBitrate(
clock_->TimeInMilliseconds()); max_total_bitrate_bps, clock_->TimeInMilliseconds()));
SendPendingProbes();
} }
// TODO(holmer): Split this up and use SetBweBitrates in combination with // TODO(holmer): Split this up and use SetBweBitrates in combination with
@ -255,10 +253,9 @@ void SendSideCongestionController::OnNetworkRouteChanged(
{ {
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->Reset(clock_->TimeInMilliseconds()); probe_controller_->Reset(clock_->TimeInMilliseconds());
probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps, SendProbes(probe_controller_->SetBitrates(min_bitrate_bps, bitrate_bps,
max_bitrate_bps, max_bitrate_bps,
clock_->TimeInMilliseconds()); clock_->TimeInMilliseconds()));
SendPendingProbes();
} }
MaybeTriggerOnNetworkChanged(); MaybeTriggerOnNetworkChanged();
@ -321,8 +318,7 @@ void SendSideCongestionController::SignalNetworkState(NetworkState state) {
NetworkAvailability msg; NetworkAvailability msg;
msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds()); msg.at_time = Timestamp::ms(clock_->TimeInMilliseconds());
msg.network_available = state == kNetworkUp; msg.network_available = state == kNetworkUp;
probe_controller_->OnNetworkAvailability(msg); SendProbes(probe_controller_->OnNetworkAvailability(msg));
SendPendingProbes();
} }
MaybeTriggerOnNetworkChanged(); MaybeTriggerOnNetworkChanged();
} }
@ -355,8 +351,9 @@ int64_t SendSideCongestionController::TimeUntilNextProcess() {
return bitrate_controller_->TimeUntilNextProcess(); return bitrate_controller_->TimeUntilNextProcess();
} }
void SendSideCongestionController::SendPendingProbes() { void SendSideCongestionController::SendProbes(
for (auto probe_config : probe_controller_->GetAndResetPendingProbes()) { std::vector<ProbeClusterConfig> probe_configs) {
for (auto probe_config : probe_configs) {
pacer_->CreateProbeCluster(probe_config.target_data_rate.bps()); pacer_->CreateProbeCluster(probe_config.target_data_rate.bps());
} }
} }
@ -382,8 +379,7 @@ void SendSideCongestionController::Process() {
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->SetAlrStartTimeMs( probe_controller_->SetAlrStartTimeMs(
pacer_->GetApplicationLimitedRegionStartTime()); pacer_->GetApplicationLimitedRegionStartTime());
probe_controller_->Process(clock_->TimeInMilliseconds()); SendProbes(probe_controller_->Process(clock_->TimeInMilliseconds()));
SendPendingProbes();
} }
MaybeTriggerOnNetworkChanged(); MaybeTriggerOnNetworkChanged();
} }
@ -437,7 +433,7 @@ void SendSideCongestionController::OnTransportFeedback(
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->SetAlrStartTimeMs( probe_controller_->SetAlrStartTimeMs(
pacer_->GetApplicationLimitedRegionStartTime()); pacer_->GetApplicationLimitedRegionStartTime());
probe_controller_->RequestProbe(clock_->TimeInMilliseconds()); SendProbes(probe_controller_->RequestProbe(clock_->TimeInMilliseconds()));
} }
if (in_cwnd_experiment_) { if (in_cwnd_experiment_) {
LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes()); LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes());
@ -501,8 +497,8 @@ void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {
pacer_->SetEstimatedBitrate(bitrate_bps); pacer_->SetEstimatedBitrate(bitrate_bps);
{ {
rtc::CritScope cs(&probe_lock_); rtc::CritScope cs(&probe_lock_);
probe_controller_->SetEstimatedBitrate(bitrate_bps, SendProbes(probe_controller_->SetEstimatedBitrate(
clock_->TimeInMilliseconds()); bitrate_bps, clock_->TimeInMilliseconds()));
} }
retransmission_rate_limiter_->SetMaxRate(bitrate_bps); retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
} }