• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
11 #include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h"
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <cmath>
16 
17 #include "webrtc/base/checks.h"
18 
19 #include "webrtc/modules/remote_bitrate_estimator/overuse_detector.h"
20 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
21 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
22 
23 namespace webrtc {
24 
25 static const int64_t kDefaultRttMs = 200;
26 static const int64_t kLogIntervalMs = 1000;
27 static const double kWithinIncomingBitrateHysteresis = 1.05;
28 static const int64_t kMaxFeedbackIntervalMs = 1000;
29 
AimdRateControl()30 AimdRateControl::AimdRateControl()
31     : min_configured_bitrate_bps_(
32           RemoteBitrateEstimator::kDefaultMinBitrateBps),
33       max_configured_bitrate_bps_(30000000),
34       current_bitrate_bps_(max_configured_bitrate_bps_),
35       avg_max_bitrate_kbps_(-1.0f),
36       var_max_bitrate_kbps_(0.4f),
37       rate_control_state_(kRcHold),
38       rate_control_region_(kRcMaxUnknown),
39       time_last_bitrate_change_(-1),
40       current_input_(kBwNormal, 0, 1.0),
41       updated_(false),
42       time_first_incoming_estimate_(-1),
43       bitrate_is_initialized_(false),
44       beta_(0.85f),
45       rtt_(kDefaultRttMs),
46       time_of_last_log_(-1),
47       in_experiment_(AdaptiveThresholdExperimentIsEnabled()) {}
48 
SetMinBitrate(int min_bitrate_bps)49 void AimdRateControl::SetMinBitrate(int min_bitrate_bps) {
50   min_configured_bitrate_bps_ = min_bitrate_bps;
51   current_bitrate_bps_ = std::max<int>(min_bitrate_bps, current_bitrate_bps_);
52 }
53 
ValidEstimate() const54 bool AimdRateControl::ValidEstimate() const {
55   return bitrate_is_initialized_;
56 }
57 
GetFeedbackInterval() const58 int64_t AimdRateControl::GetFeedbackInterval() const {
59   // Estimate how often we can send RTCP if we allocate up to 5% of bandwidth
60   // to feedback.
61   static const int kRtcpSize = 80;
62   int64_t interval = static_cast<int64_t>(
63       kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5);
64   const int64_t kMinFeedbackIntervalMs = 200;
65   return std::min(std::max(interval, kMinFeedbackIntervalMs),
66                   kMaxFeedbackIntervalMs);
67 }
68 
TimeToReduceFurther(int64_t time_now,uint32_t incoming_bitrate_bps) const69 bool AimdRateControl::TimeToReduceFurther(int64_t time_now,
70                                           uint32_t incoming_bitrate_bps) const {
71   const int64_t bitrate_reduction_interval =
72       std::max<int64_t>(std::min<int64_t>(rtt_, 200), 10);
73   if (time_now - time_last_bitrate_change_ >= bitrate_reduction_interval) {
74     return true;
75   }
76   if (ValidEstimate()) {
77     const int threshold = static_cast<int>(kWithinIncomingBitrateHysteresis *
78                                            incoming_bitrate_bps);
79     const int bitrate_difference = LatestEstimate() - incoming_bitrate_bps;
80     return bitrate_difference > threshold;
81   }
82   return false;
83 }
84 
LatestEstimate() const85 uint32_t AimdRateControl::LatestEstimate() const {
86   return current_bitrate_bps_;
87 }
88 
UpdateBandwidthEstimate(int64_t now_ms)89 uint32_t AimdRateControl::UpdateBandwidthEstimate(int64_t now_ms) {
90   current_bitrate_bps_ = ChangeBitrate(current_bitrate_bps_,
91                                        current_input_.incoming_bitrate, now_ms);
92   if (now_ms - time_of_last_log_ > kLogIntervalMs) {
93     time_of_last_log_ = now_ms;
94   }
95   return current_bitrate_bps_;
96 }
97 
SetRtt(int64_t rtt)98 void AimdRateControl::SetRtt(int64_t rtt) {
99   rtt_ = rtt;
100 }
101 
Update(const RateControlInput * input,int64_t now_ms)102 void AimdRateControl::Update(const RateControlInput* input, int64_t now_ms) {
103   assert(input);
104 
105   // Set the initial bit rate value to what we're receiving the first half
106   // second.
107   if (!bitrate_is_initialized_) {
108     const int64_t kInitializationTimeMs = 5000;
109     RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTimeMs);
110     if (time_first_incoming_estimate_ < 0) {
111       if (input->incoming_bitrate > 0) {
112         time_first_incoming_estimate_ = now_ms;
113       }
114     } else if (now_ms - time_first_incoming_estimate_ > kInitializationTimeMs &&
115                input->incoming_bitrate > 0) {
116       current_bitrate_bps_ = input->incoming_bitrate;
117       bitrate_is_initialized_ = true;
118     }
119   }
120 
121   if (updated_ && current_input_.bw_state == kBwOverusing) {
122     // Only update delay factor and incoming bit rate. We always want to react
123     // on an over-use.
124     current_input_.noise_var = input->noise_var;
125     current_input_.incoming_bitrate = input->incoming_bitrate;
126   } else {
127     updated_ = true;
128     current_input_ = *input;
129   }
130 }
131 
SetEstimate(int bitrate_bps,int64_t now_ms)132 void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) {
133   updated_ = true;
134   bitrate_is_initialized_ = true;
135   current_bitrate_bps_ = ChangeBitrate(bitrate_bps, bitrate_bps, now_ms);
136 }
137 
ChangeBitrate(uint32_t current_bitrate_bps,uint32_t incoming_bitrate_bps,int64_t now_ms)138 uint32_t AimdRateControl::ChangeBitrate(uint32_t current_bitrate_bps,
139                                         uint32_t incoming_bitrate_bps,
140                                         int64_t now_ms) {
141   if (!updated_) {
142     return current_bitrate_bps_;
143   }
144   // An over-use should always trigger us to reduce the bitrate, even though
145   // we have not yet established our first estimate. By acting on the over-use,
146   // we will end up with a valid estimate.
147   if (!bitrate_is_initialized_ && current_input_.bw_state != kBwOverusing)
148     return current_bitrate_bps_;
149   updated_ = false;
150   ChangeState(current_input_, now_ms);
151   // Calculated here because it's used in multiple places.
152   const float incoming_bitrate_kbps = incoming_bitrate_bps / 1000.0f;
153   // Calculate the max bit rate std dev given the normalized
154   // variance and the current incoming bit rate.
155   const float std_max_bit_rate = sqrt(var_max_bitrate_kbps_ *
156                                       avg_max_bitrate_kbps_);
157   switch (rate_control_state_) {
158     case kRcHold:
159       break;
160 
161     case kRcIncrease:
162       if (avg_max_bitrate_kbps_ >= 0 &&
163           incoming_bitrate_kbps >
164               avg_max_bitrate_kbps_ + 3 * std_max_bit_rate) {
165         ChangeRegion(kRcMaxUnknown);
166         avg_max_bitrate_kbps_ = -1.0;
167       }
168       if (rate_control_region_ == kRcNearMax) {
169         // Approximate the over-use estimator delay to 100 ms.
170         const int64_t response_time = rtt_ + 100;
171         uint32_t additive_increase_bps = AdditiveRateIncrease(
172             now_ms, time_last_bitrate_change_, response_time);
173         current_bitrate_bps += additive_increase_bps;
174 
175       } else {
176         uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease(
177             now_ms, time_last_bitrate_change_, current_bitrate_bps);
178         current_bitrate_bps += multiplicative_increase_bps;
179       }
180 
181       time_last_bitrate_change_ = now_ms;
182       break;
183 
184     case kRcDecrease:
185       bitrate_is_initialized_ = true;
186       if (incoming_bitrate_bps < min_configured_bitrate_bps_) {
187         current_bitrate_bps = min_configured_bitrate_bps_;
188       } else {
189         // Set bit rate to something slightly lower than max
190         // to get rid of any self-induced delay.
191         current_bitrate_bps = static_cast<uint32_t>(beta_ *
192                                                     incoming_bitrate_bps + 0.5);
193         if (current_bitrate_bps > current_bitrate_bps_) {
194           // Avoid increasing the rate when over-using.
195           if (rate_control_region_ != kRcMaxUnknown) {
196             current_bitrate_bps = static_cast<uint32_t>(
197                 beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f);
198           }
199           current_bitrate_bps = std::min(current_bitrate_bps,
200                                          current_bitrate_bps_);
201         }
202         ChangeRegion(kRcNearMax);
203 
204         if (incoming_bitrate_kbps < avg_max_bitrate_kbps_ -
205             3 * std_max_bit_rate) {
206           avg_max_bitrate_kbps_ = -1.0f;
207         }
208 
209         UpdateMaxBitRateEstimate(incoming_bitrate_kbps);
210       }
211       // Stay on hold until the pipes are cleared.
212       ChangeState(kRcHold);
213       time_last_bitrate_change_ = now_ms;
214       break;
215 
216     default:
217       assert(false);
218   }
219   if ((incoming_bitrate_bps > 100000 || current_bitrate_bps > 150000) &&
220       current_bitrate_bps > 1.5 * incoming_bitrate_bps) {
221     // Allow changing the bit rate if we are operating at very low rates
222     // Don't change the bit rate if the send side is too far off
223     current_bitrate_bps = current_bitrate_bps_;
224     time_last_bitrate_change_ = now_ms;
225   }
226   return current_bitrate_bps;
227 }
228 
MultiplicativeRateIncrease(int64_t now_ms,int64_t last_ms,uint32_t current_bitrate_bps) const229 uint32_t AimdRateControl::MultiplicativeRateIncrease(
230     int64_t now_ms, int64_t last_ms, uint32_t current_bitrate_bps) const {
231   double alpha = 1.08;
232   if (last_ms > -1) {
233     int time_since_last_update_ms = std::min(static_cast<int>(now_ms - last_ms),
234                                              1000);
235     alpha = pow(alpha,  time_since_last_update_ms / 1000.0);
236   }
237   uint32_t multiplicative_increase_bps = std::max(
238       current_bitrate_bps * (alpha - 1.0), 1000.0);
239   return multiplicative_increase_bps;
240 }
241 
AdditiveRateIncrease(int64_t now_ms,int64_t last_ms,int64_t response_time_ms) const242 uint32_t AimdRateControl::AdditiveRateIncrease(
243     int64_t now_ms, int64_t last_ms, int64_t response_time_ms) const {
244   assert(response_time_ms > 0);
245   double beta = 0.0;
246   if (last_ms > 0) {
247     beta = std::min((now_ms - last_ms) / static_cast<double>(response_time_ms),
248                     1.0);
249     if (in_experiment_)
250       beta /= 2.0;
251   }
252   double bits_per_frame = static_cast<double>(current_bitrate_bps_) / 30.0;
253   double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0));
254   double avg_packet_size_bits = bits_per_frame / packets_per_frame;
255   uint32_t additive_increase_bps = std::max(
256       1000.0, beta * avg_packet_size_bits);
257   return additive_increase_bps;
258 }
259 
UpdateMaxBitRateEstimate(float incoming_bitrate_kbps)260 void AimdRateControl::UpdateMaxBitRateEstimate(float incoming_bitrate_kbps) {
261   const float alpha = 0.05f;
262   if (avg_max_bitrate_kbps_ == -1.0f) {
263     avg_max_bitrate_kbps_ = incoming_bitrate_kbps;
264   } else {
265     avg_max_bitrate_kbps_ = (1 - alpha) * avg_max_bitrate_kbps_ +
266         alpha * incoming_bitrate_kbps;
267   }
268   // Estimate the max bit rate variance and normalize the variance
269   // with the average max bit rate.
270   const float norm = std::max(avg_max_bitrate_kbps_, 1.0f);
271   var_max_bitrate_kbps_ = (1 - alpha) * var_max_bitrate_kbps_ +
272       alpha * (avg_max_bitrate_kbps_ - incoming_bitrate_kbps) *
273           (avg_max_bitrate_kbps_ - incoming_bitrate_kbps) / norm;
274   // 0.4 ~= 14 kbit/s at 500 kbit/s
275   if (var_max_bitrate_kbps_ < 0.4f) {
276     var_max_bitrate_kbps_ = 0.4f;
277   }
278   // 2.5f ~= 35 kbit/s at 500 kbit/s
279   if (var_max_bitrate_kbps_ > 2.5f) {
280     var_max_bitrate_kbps_ = 2.5f;
281   }
282 }
283 
ChangeState(const RateControlInput & input,int64_t now_ms)284 void AimdRateControl::ChangeState(const RateControlInput& input,
285                                   int64_t now_ms) {
286   switch (current_input_.bw_state) {
287     case kBwNormal:
288       if (rate_control_state_ == kRcHold) {
289         time_last_bitrate_change_ = now_ms;
290         ChangeState(kRcIncrease);
291       }
292       break;
293     case kBwOverusing:
294       if (rate_control_state_ != kRcDecrease) {
295         ChangeState(kRcDecrease);
296       }
297       break;
298     case kBwUnderusing:
299       ChangeState(kRcHold);
300       break;
301     default:
302       assert(false);
303   }
304 }
305 
ChangeRegion(RateControlRegion region)306 void AimdRateControl::ChangeRegion(RateControlRegion region) {
307   rate_control_region_ = region;
308 }
309 
ChangeState(RateControlState new_state)310 void AimdRateControl::ChangeState(RateControlState new_state) {
311   rate_control_state_ = new_state;
312 }
313 }  // namespace webrtc
314