Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/webrtc/modules/remote_bitrate_estimator/remote_rate_control.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 12.2 KB
Line 
1/*
2 *  Copyright (c) 2012 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/remote_rate_control.h"
12
13#include <assert.h>
14#include <math.h>
15#include <string.h>
16
17#include <algorithm>
18
19#include "webrtc/system_wrappers/interface/trace.h"
20
21namespace webrtc {
22
23const unsigned int kDefaultRttMs = 200;
24
25RemoteRateControl::RemoteRateControl()
26    : min_configured_bit_rate_(30000),
27    max_configured_bit_rate_(30000000),
28    current_bit_rate_(max_configured_bit_rate_),
29    max_hold_rate_(0),
30    avg_max_bit_rate_(-1.0f),
31    var_max_bit_rate_(0.4f),
32    rate_control_state_(kRcHold),
33    came_from_state_(kRcDecrease),
34    rate_control_region_(kRcMaxUnknown),
35    last_bit_rate_change_(-1),
36    current_input_(kBwNormal, 0, 1.0),
37    updated_(false),
38    time_first_incoming_estimate_(-1),
39    initialized_bit_rate_(false),
40    avg_change_period_(1000.0f),
41    last_change_ms_(-1),
42    beta_(0.9f),
43    rtt_(kDefaultRttMs)
44{
45}
46
47void RemoteRateControl::Reset() {
48  *this = RemoteRateControl();
49  came_from_state_ = kRcHold;
50}
51
52bool RemoteRateControl::ValidEstimate() const {
53  return initialized_bit_rate_;
54}
55
56bool RemoteRateControl::TimeToReduceFurther(int64_t time_now,
57    unsigned int incoming_bitrate) const {
58  const int bitrate_reduction_interval = std::max(std::min(rtt_, 200u), 10u);
59  if (time_now - last_bit_rate_change_ >= bitrate_reduction_interval) {
60    return true;
61  }
62  if (ValidEstimate()) {
63    const int threshold = static_cast<int>(1.05 * incoming_bitrate);
64    const int bitrate_difference = LatestEstimate() - incoming_bitrate;
65    return bitrate_difference > threshold;
66  }
67  return false;
68}
69
70int32_t RemoteRateControl::SetConfiguredBitRates(uint32_t min_bit_rate_bps,
71                                                 uint32_t max_bit_rate_bps) {
72  if (min_bit_rate_bps > max_bit_rate_bps) {
73    return -1;
74  }
75  min_configured_bit_rate_ = min_bit_rate_bps;
76  max_configured_bit_rate_ = max_bit_rate_bps;
77  current_bit_rate_ = std::min(std::max(min_bit_rate_bps, current_bit_rate_),
78                               max_bit_rate_bps);
79  return 0;
80}
81
82uint32_t RemoteRateControl::LatestEstimate() const {
83  return current_bit_rate_;
84}
85
86uint32_t RemoteRateControl::UpdateBandwidthEstimate(int64_t now_ms) {
87  current_bit_rate_ = ChangeBitRate(current_bit_rate_,
88                                    current_input_._incomingBitRate,
89                                    current_input_._noiseVar,
90                                    now_ms);
91  return current_bit_rate_;
92}
93
94void RemoteRateControl::SetRtt(unsigned int rtt) {
95  rtt_ = rtt;
96}
97
98RateControlRegion RemoteRateControl::Update(const RateControlInput* input,
99                                            int64_t now_ms) {
100  assert(input);
101
102  // Set the initial bit rate value to what we're receiving the first half
103  // second.
104  if (!initialized_bit_rate_) {
105    if (time_first_incoming_estimate_ < 0) {
106      if (input->_incomingBitRate > 0) {
107        time_first_incoming_estimate_ = now_ms;
108      }
109    } else if (now_ms - time_first_incoming_estimate_ > 500 &&
110               input->_incomingBitRate > 0) {
111      current_bit_rate_ = input->_incomingBitRate;
112      initialized_bit_rate_ = true;
113    }
114  }
115
116  if (updated_ && current_input_._bwState == kBwOverusing) {
117    // Only update delay factor and incoming bit rate. We always want to react
118    // on an over-use.
119    current_input_._noiseVar = input->_noiseVar;
120    current_input_._incomingBitRate = input->_incomingBitRate;
121    return rate_control_region_;
122  }
123  updated_ = true;
124  current_input_ = *input;
125  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Incoming rate = %u kbps",
126               input->_incomingBitRate/1000);
127  return rate_control_region_;
128}
129
130uint32_t RemoteRateControl::ChangeBitRate(uint32_t current_bit_rate,
131                                          uint32_t incoming_bit_rate,
132                                          double noise_var,
133                                          int64_t now_ms) {
134  if (!updated_) {
135    return current_bit_rate_;
136  }
137  updated_ = false;
138  UpdateChangePeriod(now_ms);
139  ChangeState(current_input_, now_ms);
140  // calculated here because it's used in multiple places
141  const float incoming_bit_rate_kbps = incoming_bit_rate / 1000.0f;
142  // Calculate the max bit rate std dev given the normalized
143  // variance and the current incoming bit rate.
144  const float std_max_bit_rate = sqrt(var_max_bit_rate_ * avg_max_bit_rate_);
145  bool recovery = false;
146  switch (rate_control_state_) {
147    case kRcHold: {
148      max_hold_rate_ = std::max(max_hold_rate_, incoming_bit_rate);
149      break;
150    }
151    case kRcIncrease: {
152      if (avg_max_bit_rate_ >= 0) {
153        if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 3 * std_max_bit_rate) {
154          ChangeRegion(kRcMaxUnknown);
155          avg_max_bit_rate_ = -1.0;
156        } else if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 2.5 *
157                   std_max_bit_rate) {
158          ChangeRegion(kRcAboveMax);
159        }
160      }
161      WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
162                   "BWE: Response time: %f + %i + 10*33\n",
163                   avg_change_period_, rtt_);
164      const uint32_t response_time = static_cast<uint32_t>(avg_change_period_ +
165          0.5f) + rtt_ + 300;
166      double alpha = RateIncreaseFactor(now_ms, last_bit_rate_change_,
167                                        response_time, noise_var);
168
169      WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
170          "BWE: avg_change_period_ = %f ms; RTT = %u ms", avg_change_period_,
171          rtt_);
172
173      current_bit_rate = static_cast<uint32_t>(current_bit_rate * alpha) + 1000;
174      if (max_hold_rate_ > 0 && beta_ * max_hold_rate_ > current_bit_rate) {
175        current_bit_rate = static_cast<uint32_t>(beta_ * max_hold_rate_);
176        avg_max_bit_rate_ = beta_ * max_hold_rate_ / 1000.0f;
177        ChangeRegion(kRcNearMax);
178        recovery = true;
179      }
180      max_hold_rate_ = 0;
181      WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
182          "BWE: Increase rate to current_bit_rate = %u kbps",
183          current_bit_rate / 1000);
184      last_bit_rate_change_ = now_ms;
185      break;
186    }
187    case kRcDecrease: {
188      if (incoming_bit_rate < min_configured_bit_rate_) {
189        current_bit_rate = min_configured_bit_rate_;
190      } else {
191        // Set bit rate to something slightly lower than max
192        // to get rid of any self-induced delay.
193        current_bit_rate = static_cast<uint32_t>(beta_ * incoming_bit_rate +
194            0.5);
195        if (current_bit_rate > current_bit_rate_) {
196          // Avoid increasing the rate when over-using.
197          if (rate_control_region_ != kRcMaxUnknown) {
198            current_bit_rate = static_cast<uint32_t>(beta_ * avg_max_bit_rate_ *
199                1000 + 0.5f);
200          }
201          current_bit_rate = std::min(current_bit_rate, current_bit_rate_);
202        }
203        ChangeRegion(kRcNearMax);
204
205        if (incoming_bit_rate_kbps < avg_max_bit_rate_ - 3 * std_max_bit_rate) {
206          avg_max_bit_rate_ = -1.0f;
207        }
208
209        UpdateMaxBitRateEstimate(incoming_bit_rate_kbps);
210
211        WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
212            "BWE: Decrease rate to current_bit_rate = %u kbps",
213            current_bit_rate / 1000);
214      }
215      // Stay on hold until the pipes are cleared.
216      ChangeState(kRcHold);
217      last_bit_rate_change_ = now_ms;
218      break;
219    }
220    default:
221      assert(false);
222  }
223  if (!recovery && (incoming_bit_rate > 100000 || current_bit_rate > 150000) &&
224      current_bit_rate > 1.5 * incoming_bit_rate) {
225    // Allow changing the bit rate if we are operating at very low rates
226    // Don't change the bit rate if the send side is too far off
227    current_bit_rate = current_bit_rate_;
228    last_bit_rate_change_ = now_ms;
229  }
230  return current_bit_rate;
231}
232
233double RemoteRateControl::RateIncreaseFactor(int64_t now_ms,
234                                             int64_t last_ms,
235                                             uint32_t reaction_time_ms,
236                                             double noise_var) const {
237  // alpha = 1.02 + B ./ (1 + exp(b*(tr - (c1*s2 + c2))))
238  // Parameters
239  const double B = 0.0407;
240  const double b = 0.0025;
241  const double c1 = -6700.0 / (33 * 33);
242  const double c2 = 800.0;
243  const double d = 0.85;
244
245  double alpha = 1.005 + B / (1 + exp( b * (d * reaction_time_ms -
246      (c1 * noise_var + c2))));
247
248  if (alpha < 1.005) {
249    alpha = 1.005;
250  } else if (alpha > 1.3) {
251    alpha = 1.3;
252  }
253
254  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: alpha = %f", alpha);
255
256  if (last_ms > -1) {
257    alpha = pow(alpha, (now_ms - last_ms) / 1000.0);
258  }
259
260  if (rate_control_region_ == kRcNearMax) {
261    // We're close to our previous maximum. Try to stabilize the
262    // bit rate in this region, by increasing in smaller steps.
263    alpha = alpha - (alpha - 1.0) / 2.0;
264  } else if (rate_control_region_ == kRcMaxUnknown) {
265    alpha = alpha + (alpha - 1.0) * 2.0;
266  }
267
268  return alpha;
269}
270
271void RemoteRateControl::UpdateChangePeriod(int64_t now_ms) {
272  int64_t change_period = 0;
273  if (last_change_ms_ > -1) {
274    change_period = now_ms - last_change_ms_;
275  }
276  last_change_ms_ = now_ms;
277  avg_change_period_ = 0.9f * avg_change_period_ + 0.1f * change_period;
278}
279
280void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) {
281  const float alpha = 0.05f;
282  if (avg_max_bit_rate_ == -1.0f) {
283    avg_max_bit_rate_ = incoming_bit_rate_kbps;
284  } else {
285    avg_max_bit_rate_ = (1 - alpha) * avg_max_bit_rate_ +
286        alpha * incoming_bit_rate_kbps;
287  }
288  // Estimate the max bit rate variance and normalize the variance
289  // with the average max bit rate.
290  const float norm = std::max(avg_max_bit_rate_, 1.0f);
291  var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ +
292      alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) *
293          (avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm;
294  // 0.4 ~= 14 kbit/s at 500 kbit/s
295  if (var_max_bit_rate_ < 0.4f) {
296    var_max_bit_rate_ = 0.4f;
297  }
298  // 2.5f ~= 35 kbit/s at 500 kbit/s
299  if (var_max_bit_rate_ > 2.5f) {
300    var_max_bit_rate_ = 2.5f;
301  }
302}
303
304void RemoteRateControl::ChangeState(const RateControlInput& input,
305                                    int64_t now_ms) {
306  switch (current_input_._bwState) {
307    case kBwNormal:
308      if (rate_control_state_ == kRcHold) {
309        last_bit_rate_change_ = now_ms;
310        ChangeState(kRcIncrease);
311      }
312      break;
313    case kBwOverusing:
314      if (rate_control_state_ != kRcDecrease) {
315        ChangeState(kRcDecrease);
316      }
317      break;
318    case kBwUnderusing:
319      ChangeState(kRcHold);
320      break;
321    default:
322      assert(false);
323  }
324}
325
326void RemoteRateControl::ChangeRegion(RateControlRegion region) {
327  rate_control_region_ = region;
328  switch (rate_control_region_) {
329    case kRcAboveMax:
330    case kRcMaxUnknown:
331      beta_ = 0.9f;
332      break;
333    case kRcNearMax:
334      beta_ = 0.95f;
335      break;
336    default:
337      assert(false);
338  }
339}
340
341void RemoteRateControl::ChangeState(RateControlState new_state) {
342  came_from_state_ = rate_control_state_;
343  rate_control_state_ = new_state;
344  char state1[15];
345  char state2[15];
346  char state3[15];
347  StateStr(came_from_state_, state1);
348  StateStr(rate_control_state_, state2);
349  StateStr(current_input_._bwState, state3);
350  WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
351               "\t%s => %s due to %s\n", state1, state2, state3);
352}
353
354void RemoteRateControl::StateStr(RateControlState state, char* str) {
355  switch (state) {
356    case kRcDecrease:
357      strncpy(str, "DECREASE", 9);
358      break;
359    case kRcHold:
360      strncpy(str, "HOLD", 5);
361      break;
362    case kRcIncrease:
363      strncpy(str, "INCREASE", 9);
364      break;
365    default:
366      assert(false);
367  }
368}
369
370void RemoteRateControl::StateStr(BandwidthUsage state, char* str) {
371  switch (state) {
372    case kBwNormal:
373      strncpy(str, "NORMAL", 7);
374      break;
375    case kBwOverusing:
376      strncpy(str, "OVER USING", 11);
377      break;
378    case kBwUnderusing:
379      strncpy(str, "UNDER USING", 12);
380      break;
381    default:
382      assert(false);
383  }
384}
385}  // namespace webrtc
Note: See TracBrowser for help on using the repository browser.