https://codereview.webrtc.org/2504023002 broke exponential probing. After that change ProbeController stops exponential probes prematurely: it goes to kProbingComplete state if SetEstimatedBitrate() is called with bitrate lower than min_bitrate_to_probe_further_bps_, which always happens with the first pair of probes. As result it wasn't sending repeated probes as it should. This change fixes that issue by moving probe expieration logic to ProbeContoller::Process(). This also ensures that the controller goes to kProbingComplete state as soon as probing timeout expired, without waiting for the next SetEstimatedBitrate() call. BUG=669421 Review-Url: https://codereview.webrtc.org/2546613003 Cr-Commit-Position: refs/heads/master@{#15392}
227 lines
8.0 KiB
C++
227 lines
8.0 KiB
C++
/*
|
|
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/modules/congestion_controller/probe_controller.h"
|
|
|
|
#include <algorithm>
|
|
#include <initializer_list>
|
|
|
|
#include "webrtc/base/logging.h"
|
|
#include "webrtc/system_wrappers/include/metrics.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
// Number of deltas between probes per cluster. On the very first cluster,
|
|
// we will need kProbeDeltasPerCluster + 1 probes, but on a cluster following
|
|
// another, we need kProbeDeltasPerCluster probes.
|
|
constexpr int kProbeDeltasPerCluster = 5;
|
|
|
|
// Maximum waiting time from the time of initiating probing to getting
|
|
// the measured results back.
|
|
constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000;
|
|
|
|
// Value of |min_bitrate_to_probe_further_bps_| that indicates
|
|
// further probing is disabled.
|
|
constexpr int kExponentialProbingDisabled = 0;
|
|
|
|
// Default probing bitrate limit. Applied only when the application didn't
|
|
// specify max bitrate.
|
|
constexpr int kDefaultMaxProbingBitrateBps = 5000000;
|
|
|
|
// This is a limit on how often probing can be done when there is a BW
|
|
// drop detected in ALR.
|
|
constexpr int64_t kAlrProbingIntervalMinMs = 5000;
|
|
|
|
// Interval between probes when ALR periodic probing is enabled.
|
|
constexpr int64_t kAlrPeriodicProbingIntervalMs = 5000;
|
|
|
|
// Minimum probe bitrate percentage to probe further for repeated probes.
|
|
constexpr int kRepeatedProbeMinPercentage = 125;
|
|
|
|
} // namespace
|
|
|
|
ProbeController::ProbeController(PacedSender* pacer, Clock* clock)
|
|
: pacer_(pacer),
|
|
clock_(clock),
|
|
network_state_(kNetworkUp),
|
|
state_(State::kInit),
|
|
min_bitrate_to_probe_further_bps_(kExponentialProbingDisabled),
|
|
time_last_probing_initiated_ms_(0),
|
|
estimated_bitrate_bps_(0),
|
|
start_bitrate_bps_(0),
|
|
max_bitrate_bps_(0),
|
|
last_alr_probing_time_(clock_->TimeInMilliseconds()),
|
|
enable_periodic_alr_probing_(false) {}
|
|
|
|
void ProbeController::SetBitrates(int min_bitrate_bps,
|
|
int start_bitrate_bps,
|
|
int max_bitrate_bps) {
|
|
rtc::CritScope cs(&critsect_);
|
|
|
|
if (start_bitrate_bps > 0) {
|
|
start_bitrate_bps_ = start_bitrate_bps;
|
|
} else if (start_bitrate_bps_ == 0) {
|
|
start_bitrate_bps_ = min_bitrate_bps;
|
|
}
|
|
|
|
int old_max_bitrate_bps = max_bitrate_bps_;
|
|
max_bitrate_bps_ = max_bitrate_bps;
|
|
|
|
switch (state_) {
|
|
case State::kInit:
|
|
if (network_state_ == kNetworkUp)
|
|
InitiateExponentialProbing();
|
|
break;
|
|
|
|
case State::kWaitingForProbingResult:
|
|
break;
|
|
|
|
case State::kProbingComplete:
|
|
// Initiate probing when |max_bitrate_| was increased mid-call.
|
|
if (estimated_bitrate_bps_ != 0 &&
|
|
estimated_bitrate_bps_ < old_max_bitrate_bps &&
|
|
max_bitrate_bps_ > old_max_bitrate_bps) {
|
|
InitiateProbing(clock_->TimeInMilliseconds(), {max_bitrate_bps},
|
|
kExponentialProbingDisabled);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ProbeController::OnNetworkStateChanged(NetworkState network_state) {
|
|
rtc::CritScope cs(&critsect_);
|
|
network_state_ = network_state;
|
|
if (network_state_ == kNetworkUp && state_ == State::kInit)
|
|
InitiateExponentialProbing();
|
|
}
|
|
|
|
void ProbeController::InitiateExponentialProbing() {
|
|
RTC_DCHECK(network_state_ == kNetworkUp);
|
|
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(clock_->TimeInMilliseconds(),
|
|
{3 * start_bitrate_bps_, 6 * start_bitrate_bps_},
|
|
4 * start_bitrate_bps_);
|
|
}
|
|
|
|
void ProbeController::SetEstimatedBitrate(int bitrate_bps) {
|
|
rtc::CritScope cs(&critsect_);
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
|
if (state_ == State::kWaitingForProbingResult) {
|
|
// Continue probing if probing results indicate channel has greater
|
|
// capacity.
|
|
LOG(LS_INFO) << "Measured bitrate: " << bitrate_bps
|
|
<< " Minimum to probe further: "
|
|
<< min_bitrate_to_probe_further_bps_;
|
|
if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
|
|
bitrate_bps > min_bitrate_to_probe_further_bps_) {
|
|
// Double the probing bitrate and expect a minimum of 25% gain to
|
|
// continue probing.
|
|
InitiateProbing(now_ms, {2 * bitrate_bps},
|
|
bitrate_bps * kRepeatedProbeMinPercentage / 100);
|
|
}
|
|
}
|
|
|
|
// Detect a drop in estimated BW when operating in ALR and not already
|
|
// probing. The current response is to initiate a single probe session at the
|
|
// previous bitrate and immediately use the reported bitrate as the new
|
|
// bitrate.
|
|
//
|
|
// If the probe session fails, the assumption is that this drop was a
|
|
// real one from a competing flow or something else on the network and
|
|
// it ramps up from bitrate_bps.
|
|
if (state_ == State::kProbingComplete &&
|
|
pacer_->GetApplicationLimitedRegionStartTime() &&
|
|
bitrate_bps < estimated_bitrate_bps_ / 2 &&
|
|
(now_ms - last_alr_probing_time_) > kAlrProbingIntervalMinMs) {
|
|
LOG(LS_INFO) << "Detected big BW drop in ALR, start probe.";
|
|
// Track how often we probe in response to BW drop in ALR.
|
|
RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.AlrProbingIntervalInS",
|
|
(now_ms - last_alr_probing_time_) / 1000);
|
|
InitiateProbing(now_ms, {estimated_bitrate_bps_},
|
|
kExponentialProbingDisabled);
|
|
last_alr_probing_time_ = now_ms;
|
|
|
|
// TODO(isheriff): May want to track when we did ALR probing in order
|
|
// to reset |last_alr_probing_time_| if we validate that it was a
|
|
// drop due to exogenous event.
|
|
}
|
|
|
|
estimated_bitrate_bps_ = bitrate_bps;
|
|
}
|
|
|
|
void ProbeController::EnablePeriodicAlrProbing(bool enable) {
|
|
rtc::CritScope cs(&critsect_);
|
|
enable_periodic_alr_probing_ = enable;
|
|
}
|
|
|
|
void ProbeController::Process() {
|
|
rtc::CritScope cs(&critsect_);
|
|
|
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
|
|
|
if (state_ == State::kWaitingForProbingResult &&
|
|
(now_ms - time_last_probing_initiated_ms_) >
|
|
kMaxWaitingTimeForProbingResultMs) {
|
|
LOG(LS_INFO) << "kWaitingForProbingResult: timeout";
|
|
state_ = State::kProbingComplete;
|
|
min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
|
|
}
|
|
|
|
if (state_ != State::kProbingComplete || !enable_periodic_alr_probing_)
|
|
return;
|
|
|
|
// Probe bandwidth periodically when in ALR state.
|
|
rtc::Optional<int64_t> alr_start_time =
|
|
pacer_->GetApplicationLimitedRegionStartTime();
|
|
if (alr_start_time) {
|
|
int64_t next_probe_time_ms =
|
|
std::max(*alr_start_time, time_last_probing_initiated_ms_) +
|
|
kAlrPeriodicProbingIntervalMs;
|
|
if (now_ms >= next_probe_time_ms) {
|
|
InitiateProbing(
|
|
now_ms, {estimated_bitrate_bps_ * 2},
|
|
estimated_bitrate_bps_ * kRepeatedProbeMinPercentage / 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProbeController::InitiateProbing(
|
|
int64_t now_ms,
|
|
std::initializer_list<int> bitrates_to_probe,
|
|
int min_bitrate_to_probe_further_bps) {
|
|
bool first_cluster = true;
|
|
for (int bitrate : bitrates_to_probe) {
|
|
int max_probe_bitrate_bps =
|
|
max_bitrate_bps_ > 0 ? max_bitrate_bps_ : kDefaultMaxProbingBitrateBps;
|
|
bitrate = std::min(bitrate, max_probe_bitrate_bps);
|
|
if (first_cluster) {
|
|
pacer_->CreateProbeCluster(bitrate, kProbeDeltasPerCluster + 1);
|
|
first_cluster = false;
|
|
} else {
|
|
pacer_->CreateProbeCluster(bitrate, kProbeDeltasPerCluster);
|
|
}
|
|
}
|
|
min_bitrate_to_probe_further_bps_ = min_bitrate_to_probe_further_bps;
|
|
time_last_probing_initiated_ms_ = now_ms;
|
|
if (min_bitrate_to_probe_further_bps == kExponentialProbingDisabled)
|
|
state_ = State::kProbingComplete;
|
|
else
|
|
state_ = State::kWaitingForProbingResult;
|
|
}
|
|
|
|
} // namespace webrtc
|