blob: 8db2a6102a6a74877178f1d3cedbfc450f5b2445 [file] [log] [blame]
pbos@webrtc.org9f79fe62014-12-04 15:34:061/*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "modules/remote_bitrate_estimator/aimd_rate_control.h"
pbos@webrtc.org9f79fe62014-12-04 15:34:0612
Bjorn Terelius0c7ec802018-07-18 12:59:5613#include <inttypes.h>
14
pbos@webrtc.org9f79fe62014-12-04 15:34:0615#include <algorithm>
16#include <cassert>
17#include <cmath>
Piotr Tworek5e4833c2017-12-12 11:09:3118#include <cstdio>
Stefan Holmerea00e482017-10-06 06:43:3419#include <string>
pbos@webrtc.org9f79fe62014-12-04 15:34:0620
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
22#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
Stefan Holmerea00e482017-10-06 06:43:3423#include "modules/remote_bitrate_estimator/overuse_detector.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
Bjorn Terelius0c7ec802018-07-18 12:59:5625#include "rtc_base/checks.h"
Stefan Holmerea00e482017-10-06 06:43:3426#include "rtc_base/logging.h"
Bjorn Terelius0c7ec802018-07-18 12:59:5627#include "rtc_base/numerics/safe_minmax.h"
Stefan Holmerea00e482017-10-06 06:43:3428#include "system_wrappers/include/field_trial.h"
pbos@webrtc.org9f79fe62014-12-04 15:34:0629
30namespace webrtc {
31
Per Kjellanderdd3eae52018-05-18 07:12:1532static const int64_t kDefaultRttMs = 200;
33static const int64_t kMaxFeedbackIntervalMs = 1000;
34static const float kDefaultBackoffFactor = 0.85f;
Bjorn Terelius0c7ec802018-07-18 12:59:5635static const int64_t kDefaultInitialBackOffIntervalMs = 200;
Stefan Holmerea00e482017-10-06 06:43:3436
37const char kBweBackOffFactorExperiment[] = "WebRTC-BweBackOffFactor";
Bjorn Terelius0c7ec802018-07-18 12:59:5638const char kBweInitialBackOffIntervalExperiment[] =
39 "WebRTC-BweInitialBackOffInterval";
Stefan Holmerea00e482017-10-06 06:43:3440
Bjorn Terelius95de63b2018-05-16 18:18:2141float ReadBackoffFactor() {
Stefan Holmerea00e482017-10-06 06:43:3442 std::string experiment_string =
43 webrtc::field_trial::FindFullName(kBweBackOffFactorExperiment);
44 float backoff_factor;
45 int parsed_values =
46 sscanf(experiment_string.c_str(), "Enabled-%f", &backoff_factor);
47 if (parsed_values == 1) {
Stefan Holmer92cacec2017-10-10 07:07:2548 if (backoff_factor >= 1.0f) {
Mirko Bonadei675513b2017-11-09 10:09:2549 RTC_LOG(WARNING) << "Back-off factor must be less than 1.";
Stefan Holmer92cacec2017-10-10 07:07:2550 } else if (backoff_factor <= 0.0f) {
Mirko Bonadei675513b2017-11-09 10:09:2551 RTC_LOG(WARNING) << "Back-off factor must be greater than 0.";
Stefan Holmerea00e482017-10-06 06:43:3452 } else {
53 return backoff_factor;
54 }
55 }
Mirko Bonadei675513b2017-11-09 10:09:2556 RTC_LOG(LS_WARNING) << "Failed to parse parameters for AimdRateControl "
57 "experiment from field trial string. Using default.";
Stefan Holmerea00e482017-10-06 06:43:3458 return kDefaultBackoffFactor;
59}
pbos@webrtc.org9f79fe62014-12-04 15:34:0660
Bjorn Terelius0c7ec802018-07-18 12:59:5661int64_t ReadInitialBackoffIntervalMs() {
62 std::string experiment_string =
63 webrtc::field_trial::FindFullName(kBweInitialBackOffIntervalExperiment);
64 int64_t backoff_interval;
65 int parsed_values =
66 sscanf(experiment_string.c_str(), "Enabled-%" SCNd64, &backoff_interval);
67 if (parsed_values == 1) {
68 if (10 <= backoff_interval && backoff_interval <= 200) {
69 return backoff_interval;
70 }
71 RTC_LOG(WARNING)
72 << "Initial back-off interval must be between 10 and 200 ms.";
73 }
74 RTC_LOG(LS_WARNING) << "Failed to parse parameters for "
75 << kBweInitialBackOffIntervalExperiment
76 << " experiment. Using default.";
77 return kDefaultInitialBackOffIntervalMs;
78}
79
stefan4fbd1452015-09-28 10:57:1480AimdRateControl::AimdRateControl()
michaeltf082c2aa2016-11-07 12:17:1481 : min_configured_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
Per Kjellanderdd3eae52018-05-18 07:12:1582 max_configured_bitrate_bps_(30000000),
83 current_bitrate_bps_(max_configured_bitrate_bps_),
Bjorn Terelius43d0b982018-06-28 14:38:0584 latest_estimated_throughput_bps_(current_bitrate_bps_),
pbos@webrtc.org9f79fe62014-12-04 15:34:0685 avg_max_bitrate_kbps_(-1.0f),
86 var_max_bitrate_kbps_(0.4f),
87 rate_control_state_(kRcHold),
pbos@webrtc.org9f79fe62014-12-04 15:34:0688 rate_control_region_(kRcMaxUnknown),
89 time_last_bitrate_change_(-1),
Bjorn Terelius0c7ec802018-07-18 12:59:5690 time_last_bitrate_decrease_(-1),
Bjorn Terelius43d0b982018-06-28 14:38:0591 time_first_throughput_estimate_(-1),
pbos@webrtc.org9f79fe62014-12-04 15:34:0692 bitrate_is_initialized_(false),
Stefan Holmerea00e482017-10-06 06:43:3493 beta_(webrtc::field_trial::IsEnabled(kBweBackOffFactorExperiment)
Bjorn Terelius95de63b2018-05-16 18:18:2194 ? ReadBackoffFactor()
Stefan Holmerea00e482017-10-06 06:43:3495 : kDefaultBackoffFactor),
pbos@webrtc.org9f79fe62014-12-04 15:34:0696 rtt_(kDefaultRttMs),
Ivo Creusen46ca2872017-10-09 10:28:3997 in_experiment_(!AdaptiveThresholdExperimentIsDisabled()),
98 smoothing_experiment_(
Bjorn Terelius0c7ec802018-07-18 12:59:5699 webrtc::field_trial::IsEnabled("WebRTC-Audio-BandwidthSmoothing")),
100 in_initial_backoff_interval_experiment_(
101 webrtc::field_trial::IsEnabled(kBweInitialBackOffIntervalExperiment)),
102 initial_backoff_interval_ms_(kDefaultInitialBackOffIntervalMs) {
103 if (in_initial_backoff_interval_experiment_) {
104 initial_backoff_interval_ms_ = ReadInitialBackoffIntervalMs();
105 RTC_LOG(LS_INFO) << "Using aimd rate control with initial back-off interval"
106 << " " << initial_backoff_interval_ms_ << " ms.";
107 }
Mirko Bonadei675513b2017-11-09 10:09:25108 RTC_LOG(LS_INFO) << "Using aimd rate control with back off factor " << beta_;
Stefan Holmerea00e482017-10-06 06:43:34109}
pbos@webrtc.org9f79fe62014-12-04 15:34:06110
stefan5a2c5062017-01-27 14:43:18111AimdRateControl::~AimdRateControl() {}
112
113void AimdRateControl::SetStartBitrate(int start_bitrate_bps) {
Per Kjellanderdd3eae52018-05-18 07:12:15114 current_bitrate_bps_ = start_bitrate_bps;
Bjorn Terelius43d0b982018-06-28 14:38:05115 latest_estimated_throughput_bps_ = current_bitrate_bps_;
Per Kjellanderdd3eae52018-05-18 07:12:15116 bitrate_is_initialized_ = true;
stefan5a2c5062017-01-27 14:43:18117}
118
Per Kjellanderdd3eae52018-05-18 07:12:15119void AimdRateControl::SetMinBitrate(int min_bitrate_bps) {
120 min_configured_bitrate_bps_ = min_bitrate_bps;
121 current_bitrate_bps_ = std::max<int>(min_bitrate_bps, current_bitrate_bps_);
pbos@webrtc.org9f79fe62014-12-04 15:34:06122}
123
124bool AimdRateControl::ValidEstimate() const {
125 return bitrate_is_initialized_;
126}
127
pkasting@chromium.org0b1534c2014-12-15 22:09:40128int64_t AimdRateControl::GetFeedbackInterval() const {
pbos@webrtc.org9f79fe62014-12-04 15:34:06129 // Estimate how often we can send RTCP if we allocate up to 5% of bandwidth
130 // to feedback.
pkasting@chromium.org0b1534c2014-12-15 22:09:40131 static const int kRtcpSize = 80;
kwiberg07038562017-06-12 18:40:47132 const int64_t interval = static_cast<int64_t>(
pkasting@chromium.org0b1534c2014-12-15 22:09:40133 kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5);
Per Kjellanderdd3eae52018-05-18 07:12:15134 const int64_t kMinFeedbackIntervalMs = 200;
kwiberg07038562017-06-12 18:40:47135 return rtc::SafeClamp(interval, kMinFeedbackIntervalMs,
136 kMaxFeedbackIntervalMs);
pbos@webrtc.org9f79fe62014-12-04 15:34:06137}
138
Bjorn Terelius43d0b982018-06-28 14:38:05139bool AimdRateControl::TimeToReduceFurther(
Bjorn Terelius0c7ec802018-07-18 12:59:56140 int64_t now_ms,
Bjorn Terelius43d0b982018-06-28 14:38:05141 uint32_t estimated_throughput_bps) const {
pkasting@chromium.org16825b12015-01-12 21:51:21142 const int64_t bitrate_reduction_interval =
143 std::max<int64_t>(std::min<int64_t>(rtt_, 200), 10);
Bjorn Terelius0c7ec802018-07-18 12:59:56144 if (now_ms - time_last_bitrate_change_ >= bitrate_reduction_interval) {
pbos@webrtc.org9f79fe62014-12-04 15:34:06145 return true;
146 }
147 if (ValidEstimate()) {
howtoflydf28e472016-12-02 11:27:08148 // TODO(terelius/holmer): Investigate consequences of increasing
149 // the threshold to 0.95 * LatestEstimate().
Yves Gerey665174f2018-06-19 13:03:05150 const uint32_t threshold = static_cast<uint32_t>(0.5 * LatestEstimate());
Bjorn Terelius43d0b982018-06-28 14:38:05151 return estimated_throughput_bps < threshold;
pbos@webrtc.org9f79fe62014-12-04 15:34:06152 }
153 return false;
154}
155
Bjorn Terelius0c7ec802018-07-18 12:59:56156bool AimdRateControl::InitialTimeToReduceFurther(int64_t now_ms) const {
157 if (!in_initial_backoff_interval_experiment_) {
158 return ValidEstimate() &&
159 TimeToReduceFurther(now_ms, LatestEstimate() / 2 - 1);
160 }
161 // TODO(terelius): We could use the RTT (clamped to suitable limits) instead
162 // of a fixed bitrate_reduction_interval.
163 if (time_last_bitrate_decrease_ == -1 ||
164 now_ms - time_last_bitrate_decrease_ >= initial_backoff_interval_ms_) {
165 return true;
166 }
167 return false;
168}
169
pbos@webrtc.org9f79fe62014-12-04 15:34:06170uint32_t AimdRateControl::LatestEstimate() const {
171 return current_bitrate_bps_;
172}
173
pkasting@chromium.org16825b12015-01-12 21:51:21174void AimdRateControl::SetRtt(int64_t rtt) {
pbos@webrtc.org9f79fe62014-12-04 15:34:06175 rtt_ = rtt;
176}
177
tereliusd1b0e0e2017-04-03 09:27:08178uint32_t AimdRateControl::Update(const RateControlInput* input,
179 int64_t now_ms) {
Erik Språng51e60302016-06-10 20:13:21180 RTC_CHECK(input);
pbos@webrtc.org9f79fe62014-12-04 15:34:06181
182 // Set the initial bit rate value to what we're receiving the first half
183 // second.
Anastasia Koloskova6d191802018-06-11 09:44:29184 // TODO(bugs.webrtc.org/9379): The comment above doesn't match to the code.
pbos@webrtc.org9f79fe62014-12-04 15:34:06185 if (!bitrate_is_initialized_) {
Stefan Holmer11324b92015-07-09 15:27:48186 const int64_t kInitializationTimeMs = 5000;
henrikg91d6ede2015-09-17 07:24:34187 RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTimeMs);
Bjorn Terelius43d0b982018-06-28 14:38:05188 if (time_first_throughput_estimate_ < 0) {
189 if (input->estimated_throughput_bps)
190 time_first_throughput_estimate_ = now_ms;
191 } else if (now_ms - time_first_throughput_estimate_ >
192 kInitializationTimeMs &&
193 input->estimated_throughput_bps) {
194 current_bitrate_bps_ = *input->estimated_throughput_bps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06195 bitrate_is_initialized_ = true;
196 }
197 }
198
tereliusd1b0e0e2017-04-03 09:27:08199 current_bitrate_bps_ = ChangeBitrate(current_bitrate_bps_, *input, now_ms);
200 return current_bitrate_bps_;
pbos@webrtc.org9f79fe62014-12-04 15:34:06201}
202
203void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) {
pbos@webrtc.org9f79fe62014-12-04 15:34:06204 bitrate_is_initialized_ = true;
Bjorn Terelius0c7ec802018-07-18 12:59:56205 uint32_t prev_bitrate_bps = current_bitrate_bps_;
stefane3a55672017-02-13 17:08:22206 current_bitrate_bps_ = ClampBitrate(bitrate_bps, bitrate_bps);
207 time_last_bitrate_change_ = now_ms;
Bjorn Terelius0c7ec802018-07-18 12:59:56208 if (current_bitrate_bps_ < prev_bitrate_bps) {
209 time_last_bitrate_decrease_ = now_ms;
210 }
pbos@webrtc.org9f79fe62014-12-04 15:34:06211}
212
michaelt4a4b3cf2016-11-17 09:18:43213int AimdRateControl::GetNearMaxIncreaseRateBps() const {
214 RTC_DCHECK_GT(current_bitrate_bps_, 0);
215 double bits_per_frame = static_cast<double>(current_bitrate_bps_) / 30.0;
216 double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0));
217 double avg_packet_size_bits = bits_per_frame / packets_per_frame;
terelius67370452017-04-19 16:15:04218
michaelt4a4b3cf2016-11-17 09:18:43219 // Approximate the over-use estimator delay to 100 ms.
220 const int64_t response_time = in_experiment_ ? (rtt_ + 100) * 2 : rtt_ + 100;
michaelt4a4b3cf2016-11-17 09:18:43221 constexpr double kMinIncreaseRateBps = 4000;
222 return static_cast<int>(std::max(
223 kMinIncreaseRateBps, (avg_packet_size_bits * 1000) / response_time));
224}
225
terelius67370452017-04-19 16:15:04226int AimdRateControl::GetExpectedBandwidthPeriodMs() const {
Ivo Creusen46ca2872017-10-09 10:28:39227 const int kMinPeriodMs = smoothing_experiment_ ? 500 : 2000;
alexnarestb335e312017-09-19 19:00:32228 constexpr int kDefaultPeriodMs = 3000;
minyue93e45222017-05-18 21:32:41229 constexpr int kMaxPeriodMs = 50000;
terelius67370452017-04-19 16:15:04230
231 int increase_rate = GetNearMaxIncreaseRateBps();
232 if (!last_decrease_)
Ivo Creusen46ca2872017-10-09 10:28:39233 return smoothing_experiment_ ? kMinPeriodMs : kDefaultPeriodMs;
terelius67370452017-04-19 16:15:04234
Per Kjellanderdd3eae52018-05-18 07:12:15235 return std::min(kMaxPeriodMs,
236 std::max<int>(1000 * static_cast<int64_t>(*last_decrease_) /
237 increase_rate,
238 kMinPeriodMs));
michaelt4a4b3cf2016-11-17 09:18:43239}
240
stefane3a55672017-02-13 17:08:22241uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
tereliusd1b0e0e2017-04-03 09:27:08242 const RateControlInput& input,
pbos@webrtc.org9f79fe62014-12-04 15:34:06243 int64_t now_ms) {
Bjorn Terelius43d0b982018-06-28 14:38:05244 uint32_t estimated_throughput_bps =
245 input.estimated_throughput_bps.value_or(latest_estimated_throughput_bps_);
246 if (input.estimated_throughput_bps)
247 latest_estimated_throughput_bps_ = *input.estimated_throughput_bps;
tereliusd1b0e0e2017-04-03 09:27:08248
Stefan Holmer11324b92015-07-09 15:27:48249 // An over-use should always trigger us to reduce the bitrate, even though
250 // we have not yet established our first estimate. By acting on the over-use,
251 // we will end up with a valid estimate.
michaelt97653702017-04-11 07:49:44252 if (!bitrate_is_initialized_ &&
253 input.bw_state != BandwidthUsage::kBwOverusing)
Stefan Holmer11324b92015-07-09 15:27:48254 return current_bitrate_bps_;
tereliusd1b0e0e2017-04-03 09:27:08255
256 ChangeState(input, now_ms);
pbos@webrtc.org9f79fe62014-12-04 15:34:06257 // Calculated here because it's used in multiple places.
Bjorn Terelius43d0b982018-06-28 14:38:05258 const float estimated_throughput_kbps = estimated_throughput_bps / 1000.0f;
pbos@webrtc.org9f79fe62014-12-04 15:34:06259 // Calculate the max bit rate std dev given the normalized
Bjorn Terelius43d0b982018-06-28 14:38:05260 // variance and the current throughput bitrate.
Yves Gerey665174f2018-06-19 13:03:05261 const float std_max_bit_rate =
262 sqrt(var_max_bitrate_kbps_ * avg_max_bitrate_kbps_);
pbos@webrtc.org9f79fe62014-12-04 15:34:06263 switch (rate_control_state_) {
stefanc62642c2015-07-07 11:20:34264 case kRcHold:
pbos@webrtc.org9f79fe62014-12-04 15:34:06265 break;
stefanc62642c2015-07-07 11:20:34266
267 case kRcIncrease:
268 if (avg_max_bitrate_kbps_ >= 0 &&
Bjorn Terelius43d0b982018-06-28 14:38:05269 estimated_throughput_kbps >
stefanc62642c2015-07-07 11:20:34270 avg_max_bitrate_kbps_ + 3 * std_max_bit_rate) {
271 ChangeRegion(kRcMaxUnknown);
272 avg_max_bitrate_kbps_ = -1.0;
pbos@webrtc.org9f79fe62014-12-04 15:34:06273 }
274 if (rate_control_region_ == kRcNearMax) {
michaelt4a4b3cf2016-11-17 09:18:43275 uint32_t additive_increase_bps =
276 AdditiveRateIncrease(now_ms, time_last_bitrate_change_);
stefane3a55672017-02-13 17:08:22277 new_bitrate_bps += additive_increase_bps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06278 } else {
279 uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease(
stefane3a55672017-02-13 17:08:22280 now_ms, time_last_bitrate_change_, new_bitrate_bps);
281 new_bitrate_bps += multiplicative_increase_bps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06282 }
283
pbos@webrtc.org9f79fe62014-12-04 15:34:06284 time_last_bitrate_change_ = now_ms;
285 break;
stefanc62642c2015-07-07 11:20:34286
287 case kRcDecrease:
stefane3a55672017-02-13 17:08:22288 // Set bit rate to something slightly lower than max
289 // to get rid of any self-induced delay.
290 new_bitrate_bps =
Bjorn Terelius43d0b982018-06-28 14:38:05291 static_cast<uint32_t>(beta_ * estimated_throughput_bps + 0.5);
stefane3a55672017-02-13 17:08:22292 if (new_bitrate_bps > current_bitrate_bps_) {
293 // Avoid increasing the rate when over-using.
294 if (rate_control_region_ != kRcMaxUnknown) {
295 new_bitrate_bps = static_cast<uint32_t>(
296 beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f);
pbos@webrtc.org9f79fe62014-12-04 15:34:06297 }
stefane3a55672017-02-13 17:08:22298 new_bitrate_bps = std::min(new_bitrate_bps, current_bitrate_bps_);
pbos@webrtc.org9f79fe62014-12-04 15:34:06299 }
stefane3a55672017-02-13 17:08:22300 ChangeRegion(kRcNearMax);
301
terelius67370452017-04-19 16:15:04302 if (bitrate_is_initialized_ &&
Bjorn Terelius43d0b982018-06-28 14:38:05303 estimated_throughput_bps < current_bitrate_bps_) {
Ivo Creusen46ca2872017-10-09 10:28:39304 constexpr float kDegradationFactor = 0.9f;
305 if (smoothing_experiment_ &&
306 new_bitrate_bps <
307 kDegradationFactor * beta_ * current_bitrate_bps_) {
308 // If bitrate decreases more than a normal back off after overuse, it
309 // indicates a real network degradation. We do not let such a decrease
310 // to determine the bandwidth estimation period.
Danil Chapovalov0040b662018-06-18 08:48:16311 last_decrease_ = absl::nullopt;
Ivo Creusen46ca2872017-10-09 10:28:39312 } else {
Oskar Sundbom18f26d12017-11-16 09:52:14313 last_decrease_ = current_bitrate_bps_ - new_bitrate_bps;
Ivo Creusen46ca2872017-10-09 10:28:39314 }
stefane3a55672017-02-13 17:08:22315 }
Bjorn Terelius43d0b982018-06-28 14:38:05316 if (estimated_throughput_kbps <
stefane3a55672017-02-13 17:08:22317 avg_max_bitrate_kbps_ - 3 * std_max_bit_rate) {
318 avg_max_bitrate_kbps_ = -1.0f;
319 }
320
terelius67370452017-04-19 16:15:04321 bitrate_is_initialized_ = true;
Bjorn Terelius43d0b982018-06-28 14:38:05322 UpdateMaxThroughputEstimate(estimated_throughput_kbps);
pbos@webrtc.org9f79fe62014-12-04 15:34:06323 // Stay on hold until the pipes are cleared.
tereliusd1b0e0e2017-04-03 09:27:08324 rate_control_state_ = kRcHold;
pbos@webrtc.org9f79fe62014-12-04 15:34:06325 time_last_bitrate_change_ = now_ms;
Bjorn Terelius0c7ec802018-07-18 12:59:56326 time_last_bitrate_decrease_ = now_ms;
pbos@webrtc.org9f79fe62014-12-04 15:34:06327 break;
stefanc62642c2015-07-07 11:20:34328
pbos@webrtc.org9f79fe62014-12-04 15:34:06329 default:
330 assert(false);
331 }
Bjorn Terelius43d0b982018-06-28 14:38:05332 return ClampBitrate(new_bitrate_bps, estimated_throughput_bps);
stefane3a55672017-02-13 17:08:22333}
334
Bjorn Terelius43d0b982018-06-28 14:38:05335uint32_t AimdRateControl::ClampBitrate(
336 uint32_t new_bitrate_bps,
337 uint32_t estimated_throughput_bps) const {
stefandb752f92016-12-05 16:23:40338 // Don't change the bit rate if the send side is too far off.
339 // We allow a bit more lag at very low rates to not too easily get stuck if
340 // the encoder produces uneven outputs.
341 const uint32_t max_bitrate_bps =
Bjorn Terelius43d0b982018-06-28 14:38:05342 static_cast<uint32_t>(1.5f * estimated_throughput_bps) + 10000;
stefane3a55672017-02-13 17:08:22343 if (new_bitrate_bps > current_bitrate_bps_ &&
344 new_bitrate_bps > max_bitrate_bps) {
345 new_bitrate_bps = std::max(current_bitrate_bps_, max_bitrate_bps);
pbos@webrtc.org9f79fe62014-12-04 15:34:06346 }
stefane3a55672017-02-13 17:08:22347 new_bitrate_bps = std::max(new_bitrate_bps, min_configured_bitrate_bps_);
348 return new_bitrate_bps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06349}
350
351uint32_t AimdRateControl::MultiplicativeRateIncrease(
Yves Gerey665174f2018-06-19 13:03:05352 int64_t now_ms,
353 int64_t last_ms,
354 uint32_t current_bitrate_bps) const {
pbos@webrtc.org9f79fe62014-12-04 15:34:06355 double alpha = 1.08;
356 if (last_ms > -1) {
kwiberg7885d3f2017-04-25 19:35:07357 auto time_since_last_update_ms =
358 rtc::SafeMin<int64_t>(now_ms - last_ms, 1000);
Yves Gerey665174f2018-06-19 13:03:05359 alpha = pow(alpha, time_since_last_update_ms / 1000.0);
pbos@webrtc.org9f79fe62014-12-04 15:34:06360 }
Yves Gerey665174f2018-06-19 13:03:05361 uint32_t multiplicative_increase_bps =
362 std::max(current_bitrate_bps * (alpha - 1.0), 1000.0);
pbos@webrtc.org9f79fe62014-12-04 15:34:06363 return multiplicative_increase_bps;
364}
365
michaelt4a4b3cf2016-11-17 09:18:43366uint32_t AimdRateControl::AdditiveRateIncrease(int64_t now_ms,
367 int64_t last_ms) const {
368 return static_cast<uint32_t>((now_ms - last_ms) *
369 GetNearMaxIncreaseRateBps() / 1000);
pbos@webrtc.org9f79fe62014-12-04 15:34:06370}
371
Bjorn Terelius43d0b982018-06-28 14:38:05372void AimdRateControl::UpdateMaxThroughputEstimate(
373 float estimated_throughput_kbps) {
pbos@webrtc.org9f79fe62014-12-04 15:34:06374 const float alpha = 0.05f;
375 if (avg_max_bitrate_kbps_ == -1.0f) {
Bjorn Terelius43d0b982018-06-28 14:38:05376 avg_max_bitrate_kbps_ = estimated_throughput_kbps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06377 } else {
Yves Gerey665174f2018-06-19 13:03:05378 avg_max_bitrate_kbps_ =
Bjorn Terelius43d0b982018-06-28 14:38:05379 (1 - alpha) * avg_max_bitrate_kbps_ + alpha * estimated_throughput_kbps;
pbos@webrtc.org9f79fe62014-12-04 15:34:06380 }
381 // Estimate the max bit rate variance and normalize the variance
382 // with the average max bit rate.
383 const float norm = std::max(avg_max_bitrate_kbps_, 1.0f);
Yves Gerey665174f2018-06-19 13:03:05384 var_max_bitrate_kbps_ =
385 (1 - alpha) * var_max_bitrate_kbps_ +
Bjorn Terelius43d0b982018-06-28 14:38:05386 alpha * (avg_max_bitrate_kbps_ - estimated_throughput_kbps) *
387 (avg_max_bitrate_kbps_ - estimated_throughput_kbps) / norm;
pbos@webrtc.org9f79fe62014-12-04 15:34:06388 // 0.4 ~= 14 kbit/s at 500 kbit/s
389 if (var_max_bitrate_kbps_ < 0.4f) {
390 var_max_bitrate_kbps_ = 0.4f;
391 }
392 // 2.5f ~= 35 kbit/s at 500 kbit/s
393 if (var_max_bitrate_kbps_ > 2.5f) {
394 var_max_bitrate_kbps_ = 2.5f;
395 }
396}
397
398void AimdRateControl::ChangeState(const RateControlInput& input,
399 int64_t now_ms) {
tereliusd1b0e0e2017-04-03 09:27:08400 switch (input.bw_state) {
michaelt97653702017-04-11 07:49:44401 case BandwidthUsage::kBwNormal:
pbos@webrtc.org9f79fe62014-12-04 15:34:06402 if (rate_control_state_ == kRcHold) {
403 time_last_bitrate_change_ = now_ms;
tereliusd1b0e0e2017-04-03 09:27:08404 rate_control_state_ = kRcIncrease;
pbos@webrtc.org9f79fe62014-12-04 15:34:06405 }
406 break;
michaelt97653702017-04-11 07:49:44407 case BandwidthUsage::kBwOverusing:
pbos@webrtc.org9f79fe62014-12-04 15:34:06408 if (rate_control_state_ != kRcDecrease) {
tereliusd1b0e0e2017-04-03 09:27:08409 rate_control_state_ = kRcDecrease;
pbos@webrtc.org9f79fe62014-12-04 15:34:06410 }
411 break;
michaelt97653702017-04-11 07:49:44412 case BandwidthUsage::kBwUnderusing:
tereliusd1b0e0e2017-04-03 09:27:08413 rate_control_state_ = kRcHold;
pbos@webrtc.org9f79fe62014-12-04 15:34:06414 break;
415 default:
416 assert(false);
417 }
418}
419
420void AimdRateControl::ChangeRegion(RateControlRegion region) {
421 rate_control_region_ = region;
pbos@webrtc.org9f79fe62014-12-04 15:34:06422}
423
pbos@webrtc.org9f79fe62014-12-04 15:34:06424} // namespace webrtc