 Chromium Code Reviews
 Chromium Code Reviews Issue 1151603008:
  Make the BWE threshold adaptive.  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master
    
  
    Issue 1151603008:
  Make the BWE threshold adaptive.  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 
| 3 * | 3 * | 
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found | 
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may | 
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. | 
| 9 */ | 9 */ | 
| 10 | 10 | 
| 11 #include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h" | 11 #include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h" | 
| 12 | 12 | 
| 13 #include <algorithm> | 13 #include <algorithm> | 
| 14 #include <cassert> | 14 #include <cassert> | 
| 15 #include <cmath> | 15 #include <cmath> | 
| 16 | 16 | 
| 17 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" | 17 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" | 
| 18 | 18 | 
| 19 namespace webrtc { | 19 namespace webrtc { | 
| 20 | 20 | 
| 21 static const int64_t kDefaultRttMs = 200; | 21 static const int64_t kDefaultRttMs = 200; | 
| 22 static const int64_t kLogIntervalMs = 1000; | 22 static const int64_t kLogIntervalMs = 1000; | 
| 23 static const double kWithinIncomingBitrateHysteresis = 1.05; | 23 static const double kWithinIncomingBitrateHysteresis = 1.05; | 
| 24 | 24 | 
| 25 AimdRateControl::AimdRateControl(uint32_t min_bitrate_bps) | 25 AimdRateControl::AimdRateControl(uint32_t min_bitrate_bps) | 
| 26 : min_configured_bitrate_bps_(min_bitrate_bps), | 26 : min_configured_bitrate_bps_(min_bitrate_bps), | 
| 27 max_configured_bitrate_bps_(30000000), | 27 max_configured_bitrate_bps_(30000000), | 
| 28 current_bitrate_bps_(max_configured_bitrate_bps_), | 28 current_bitrate_bps_(max_configured_bitrate_bps_), | 
| 29 max_hold_rate_bps_(0), | |
| 30 avg_max_bitrate_kbps_(-1.0f), | 29 avg_max_bitrate_kbps_(-1.0f), | 
| 31 var_max_bitrate_kbps_(0.4f), | 30 var_max_bitrate_kbps_(0.4f), | 
| 32 rate_control_state_(kRcHold), | 31 rate_control_state_(kRcHold), | 
| 33 came_from_state_(kRcDecrease), | |
| 34 rate_control_region_(kRcMaxUnknown), | 32 rate_control_region_(kRcMaxUnknown), | 
| 35 time_last_bitrate_change_(-1), | 33 time_last_bitrate_change_(-1), | 
| 36 current_input_(kBwNormal, 0, 1.0), | 34 current_input_(kBwNormal, 0, 1.0), | 
| 37 updated_(false), | 35 updated_(false), | 
| 38 time_first_incoming_estimate_(-1), | 36 time_first_incoming_estimate_(-1), | 
| 39 bitrate_is_initialized_(false), | 37 bitrate_is_initialized_(false), | 
| 40 beta_(0.9f), | 38 beta_(0.85f), | 
| 41 rtt_(kDefaultRttMs), | 39 rtt_(kDefaultRttMs), | 
| 42 time_of_last_log_(-1) {} | 40 time_of_last_log_(-1) { | 
| 41 } | |
| 43 | 42 | 
| 44 RateControlType AimdRateControl::GetControlType() const { | 43 RateControlType AimdRateControl::GetControlType() const { | 
| 45 return kAimdControl; | 44 return kAimdControl; | 
| 46 } | 45 } | 
| 47 | 46 | 
| 48 uint32_t AimdRateControl::GetMinBitrate() const { | 47 uint32_t AimdRateControl::GetMinBitrate() const { | 
| 49 return min_configured_bitrate_bps_; | 48 return min_configured_bitrate_bps_; | 
| 50 } | 49 } | 
| 51 | 50 | 
| 52 bool AimdRateControl::ValidEstimate() const { | 51 bool AimdRateControl::ValidEstimate() const { | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 if (now_ms - time_of_last_log_ > kLogIntervalMs) { | 90 if (now_ms - time_of_last_log_ > kLogIntervalMs) { | 
| 92 time_of_last_log_ = now_ms; | 91 time_of_last_log_ = now_ms; | 
| 93 } | 92 } | 
| 94 return current_bitrate_bps_; | 93 return current_bitrate_bps_; | 
| 95 } | 94 } | 
| 96 | 95 | 
| 97 void AimdRateControl::SetRtt(int64_t rtt) { | 96 void AimdRateControl::SetRtt(int64_t rtt) { | 
| 98 rtt_ = rtt; | 97 rtt_ = rtt; | 
| 99 } | 98 } | 
| 100 | 99 | 
| 101 RateControlRegion AimdRateControl::Update(const RateControlInput* input, | 100 void AimdRateControl::Update(const RateControlInput* input, int64_t now_ms) { | 
| 102 int64_t now_ms) { | |
| 103 assert(input); | 101 assert(input); | 
| 104 | 102 | 
| 105 // Set the initial bit rate value to what we're receiving the first half | 103 // Set the initial bit rate value to what we're receiving the first half | 
| 106 // second. | 104 // second. | 
| 107 if (!bitrate_is_initialized_) { | 105 if (!bitrate_is_initialized_) { | 
| 108 if (time_first_incoming_estimate_ < 0) { | 106 if (time_first_incoming_estimate_ < 0) { | 
| 109 if (input->_incomingBitRate > 0) { | 107 if (input->_incomingBitRate > 0) { | 
| 110 time_first_incoming_estimate_ = now_ms; | 108 time_first_incoming_estimate_ = now_ms; | 
| 111 } | 109 } | 
| 112 } else if (now_ms - time_first_incoming_estimate_ > 500 && | 110 } else if (now_ms - time_first_incoming_estimate_ > 500 && | 
| 113 input->_incomingBitRate > 0) { | 111 input->_incomingBitRate > 0) { | 
| 114 current_bitrate_bps_ = input->_incomingBitRate; | 112 current_bitrate_bps_ = input->_incomingBitRate; | 
| 115 bitrate_is_initialized_ = true; | 113 bitrate_is_initialized_ = true; | 
| 116 } | 114 } | 
| 117 } | 115 } | 
| 118 | 116 | 
| 119 if (updated_ && current_input_._bwState == kBwOverusing) { | 117 if (updated_ && current_input_._bwState == kBwOverusing) { | 
| 120 // Only update delay factor and incoming bit rate. We always want to react | 118 // Only update delay factor and incoming bit rate. We always want to react | 
| 121 // on an over-use. | 119 // on an over-use. | 
| 122 current_input_._noiseVar = input->_noiseVar; | 120 current_input_._noiseVar = input->_noiseVar; | 
| 123 current_input_._incomingBitRate = input->_incomingBitRate; | 121 current_input_._incomingBitRate = input->_incomingBitRate; | 
| 124 } else { | 122 } else { | 
| 125 updated_ = true; | 123 updated_ = true; | 
| 126 current_input_ = *input; | 124 current_input_ = *input; | 
| 127 } | 125 } | 
| 128 return rate_control_region_; | |
| 129 } | 126 } | 
| 130 | 127 | 
| 131 void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) { | 128 void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) { | 
| 132 updated_ = true; | 129 updated_ = true; | 
| 133 bitrate_is_initialized_ = true; | 130 bitrate_is_initialized_ = true; | 
| 134 current_bitrate_bps_ = ChangeBitrate(bitrate_bps, bitrate_bps, now_ms); | 131 current_bitrate_bps_ = ChangeBitrate(bitrate_bps, bitrate_bps, now_ms); | 
| 135 } | 132 } | 
| 136 | 133 | 
| 137 uint32_t AimdRateControl::ChangeBitrate(uint32_t current_bitrate_bps, | 134 uint32_t AimdRateControl::ChangeBitrate(uint32_t current_bitrate_bps, | 
| 138 uint32_t incoming_bitrate_bps, | 135 uint32_t incoming_bitrate_bps, | 
| 139 int64_t now_ms) { | 136 int64_t now_ms) { | 
| 140 if (!updated_) { | 137 if (!updated_) { | 
| 141 return current_bitrate_bps_; | 138 return current_bitrate_bps_; | 
| 142 } | 139 } | 
| 143 updated_ = false; | 140 updated_ = false; | 
| 144 ChangeState(current_input_, now_ms); | 141 ChangeState(current_input_, now_ms); | 
| 145 // Calculated here because it's used in multiple places. | 142 // Calculated here because it's used in multiple places. | 
| 146 const float incoming_bitrate_kbps = incoming_bitrate_bps / 1000.0f; | 143 const float incoming_bitrate_kbps = incoming_bitrate_bps / 1000.0f; | 
| 147 // Calculate the max bit rate std dev given the normalized | 144 // Calculate the max bit rate std dev given the normalized | 
| 148 // variance and the current incoming bit rate. | 145 // variance and the current incoming bit rate. | 
| 149 const float std_max_bit_rate = sqrt(var_max_bitrate_kbps_ * | 146 const float std_max_bit_rate = sqrt(var_max_bitrate_kbps_ * | 
| 150 avg_max_bitrate_kbps_); | 147 avg_max_bitrate_kbps_); | 
| 151 bool fast_recovery_after_hold = false; | |
| 152 switch (rate_control_state_) { | 148 switch (rate_control_state_) { | 
| 153 case kRcHold: { | 149 case kRcHold: | 
| 154 max_hold_rate_bps_ = std::max(max_hold_rate_bps_, incoming_bitrate_bps); | |
| 155 break; | 150 break; | 
| 156 } | 151 | 
| 157 case kRcIncrease: { | 152 case kRcIncrease: | 
| 158 if (avg_max_bitrate_kbps_ >= 0) { | 153 if (avg_max_bitrate_kbps_ >= 0 && | 
| 159 if (incoming_bitrate_kbps > avg_max_bitrate_kbps_ + | 154 incoming_bitrate_kbps > avg_max_bitrate_kbps_ + | 
| 160 3 * std_max_bit_rate) { | 155 3 * std_max_bit_rate) { | 
| 161 ChangeRegion(kRcMaxUnknown); | 156 ChangeRegion(kRcMaxUnknown); | 
| 162 avg_max_bitrate_kbps_ = -1.0; | 157 avg_max_bitrate_kbps_ = -1.0; | 
| 163 } else if (incoming_bitrate_kbps > avg_max_bitrate_kbps_ + | |
| 164 2.5 * std_max_bit_rate) { | |
| 165 ChangeRegion(kRcAboveMax); | |
| 166 } | |
| 167 } | 158 } | 
| 
mflodman
2015/07/03 08:29:55
Why was the kRcAboveMax removed?
 
Gaetano Carlucci
2015/07/03 10:54:28
kRcNearMax, kRcAboveMax and kRcMaxUnknown were int
 
stefan-webrtc
2015/07/03 13:45:10
We decided to simplify back-off and have the back-
 | |
| 168 if (rate_control_region_ == kRcNearMax) { | 159 if (rate_control_region_ == kRcNearMax) { | 
| 169 // Approximate the over-use estimator delay to 100 ms. | 160 // Approximate the over-use estimator delay to 100 ms. | 
| 170 const int64_t response_time = rtt_ + 100; | 161 const int64_t response_time = rtt_ + 100; | 
| 171 uint32_t additive_increase_bps = AdditiveRateIncrease( | 162 uint32_t additive_increase_bps = AdditiveRateIncrease( | 
| 172 now_ms, time_last_bitrate_change_, response_time); | 163 now_ms, time_last_bitrate_change_, response_time); | 
| 173 current_bitrate_bps += additive_increase_bps; | 164 current_bitrate_bps += additive_increase_bps; | 
| 174 | 165 | 
| 175 } else { | 166 } else { | 
| 176 uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease( | 167 uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease( | 
| 177 now_ms, time_last_bitrate_change_, current_bitrate_bps); | 168 now_ms, time_last_bitrate_change_, current_bitrate_bps); | 
| 178 current_bitrate_bps += multiplicative_increase_bps; | 169 current_bitrate_bps += multiplicative_increase_bps; | 
| 179 } | 170 } | 
| 180 | 171 | 
| 181 if (max_hold_rate_bps_ > 0 && | |
| 182 beta_ * max_hold_rate_bps_ > current_bitrate_bps) { | |
| 183 current_bitrate_bps = static_cast<uint32_t>(beta_ * max_hold_rate_bps_); | |
| 184 avg_max_bitrate_kbps_ = beta_ * max_hold_rate_bps_ / 1000.0f; | |
| 185 ChangeRegion(kRcNearMax); | |
| 186 fast_recovery_after_hold = true; | |
| 187 } | |
| 188 max_hold_rate_bps_ = 0; | |
| 189 time_last_bitrate_change_ = now_ms; | 172 time_last_bitrate_change_ = now_ms; | 
| 190 break; | 173 break; | 
| 191 } | 174 | 
| 192 case kRcDecrease: { | 175 case kRcDecrease: | 
| 193 if (incoming_bitrate_bps < min_configured_bitrate_bps_) { | 176 if (incoming_bitrate_bps < min_configured_bitrate_bps_) { | 
| 194 current_bitrate_bps = min_configured_bitrate_bps_; | 177 current_bitrate_bps = min_configured_bitrate_bps_; | 
| 195 } else { | 178 } else { | 
| 196 // Set bit rate to something slightly lower than max | 179 // Set bit rate to something slightly lower than max | 
| 197 // to get rid of any self-induced delay. | 180 // to get rid of any self-induced delay. | 
| 198 current_bitrate_bps = static_cast<uint32_t>(beta_ * | 181 current_bitrate_bps = static_cast<uint32_t>(beta_ * | 
| 199 incoming_bitrate_bps + 0.5); | 182 incoming_bitrate_bps + 0.5); | 
| 200 if (current_bitrate_bps > current_bitrate_bps_) { | 183 if (current_bitrate_bps > current_bitrate_bps_) { | 
| 201 // Avoid increasing the rate when over-using. | 184 // Avoid increasing the rate when over-using. | 
| 202 if (rate_control_region_ != kRcMaxUnknown) { | 185 if (rate_control_region_ != kRcMaxUnknown) { | 
| 203 current_bitrate_bps = static_cast<uint32_t>( | 186 current_bitrate_bps = static_cast<uint32_t>( | 
| 204 beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f); | 187 beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f); | 
| 205 } | 188 } | 
| 206 current_bitrate_bps = std::min(current_bitrate_bps, | 189 current_bitrate_bps = std::min(current_bitrate_bps, | 
| 207 current_bitrate_bps_); | 190 current_bitrate_bps_); | 
| 208 } | 191 } | 
| 209 ChangeRegion(kRcNearMax); | 192 ChangeRegion(kRcNearMax); | 
| 210 | 193 | 
| 211 if (incoming_bitrate_kbps < avg_max_bitrate_kbps_ - | 194 if (incoming_bitrate_kbps < avg_max_bitrate_kbps_ - | 
| 212 3 * std_max_bit_rate) { | 195 3 * std_max_bit_rate) { | 
| 213 avg_max_bitrate_kbps_ = -1.0f; | 196 avg_max_bitrate_kbps_ = -1.0f; | 
| 214 } | 197 } | 
| 215 | 198 | 
| 216 UpdateMaxBitRateEstimate(incoming_bitrate_kbps); | 199 UpdateMaxBitRateEstimate(incoming_bitrate_kbps); | 
| 217 } | 200 } | 
| 218 // Stay on hold until the pipes are cleared. | 201 // Stay on hold until the pipes are cleared. | 
| 219 ChangeState(kRcHold); | 202 ChangeState(kRcHold); | 
| 220 time_last_bitrate_change_ = now_ms; | 203 time_last_bitrate_change_ = now_ms; | 
| 221 break; | 204 break; | 
| 222 } | 205 | 
| 223 default: | 206 default: | 
| 224 assert(false); | 207 assert(false); | 
| 225 } | 208 } | 
| 226 if (!fast_recovery_after_hold && (incoming_bitrate_bps > 100000 || | 209 if ((incoming_bitrate_bps > 100000 || current_bitrate_bps > 150000) && | 
| 227 current_bitrate_bps > 150000) && | |
| 228 current_bitrate_bps > 1.5 * incoming_bitrate_bps) { | 210 current_bitrate_bps > 1.5 * incoming_bitrate_bps) { | 
| 229 // Allow changing the bit rate if we are operating at very low rates | 211 // Allow changing the bit rate if we are operating at very low rates | 
| 230 // Don't change the bit rate if the send side is too far off | 212 // Don't change the bit rate if the send side is too far off | 
| 231 current_bitrate_bps = current_bitrate_bps_; | 213 current_bitrate_bps = current_bitrate_bps_; | 
| 232 time_last_bitrate_change_ = now_ms; | 214 time_last_bitrate_change_ = now_ms; | 
| 233 } | 215 } | 
| 234 return current_bitrate_bps; | 216 return current_bitrate_bps; | 
| 235 } | 217 } | 
| 236 | 218 | 
| 237 uint32_t AimdRateControl::MultiplicativeRateIncrease( | 219 uint32_t AimdRateControl::MultiplicativeRateIncrease( | 
| 238 int64_t now_ms, int64_t last_ms, uint32_t current_bitrate_bps) const { | 220 int64_t now_ms, int64_t last_ms, uint32_t current_bitrate_bps) const { | 
| 239 double alpha = 1.08; | 221 double alpha = 1.08; | 
| 240 if (last_ms > -1) { | 222 if (last_ms > -1) { | 
| 241 int time_since_last_update_ms = std::min(static_cast<int>(now_ms - last_ms), | 223 int time_since_last_update_ms = std::min(static_cast<int>(now_ms - last_ms), | 
| 242 1000); | 224 1000); | 
| 243 alpha = pow(alpha, time_since_last_update_ms / 1000.0); | 225 alpha = pow(alpha, time_since_last_update_ms / 1000.0); | 
| 244 } | 226 } | 
| 245 uint32_t multiplicative_increase_bps = std::max( | 227 uint32_t multiplicative_increase_bps = std::max( | 
| 246 current_bitrate_bps * (alpha - 1.0), 1000.0); | 228 current_bitrate_bps * (alpha - 1.0), 1000.0); | 
| 247 return multiplicative_increase_bps; | 229 return multiplicative_increase_bps; | 
| 248 } | 230 } | 
| 249 | 231 | 
| 250 uint32_t AimdRateControl::AdditiveRateIncrease( | 232 uint32_t AimdRateControl::AdditiveRateIncrease( | 
| 251 int64_t now_ms, int64_t last_ms, int64_t response_time_ms) const { | 233 int64_t now_ms, int64_t last_ms, int64_t response_time_ms) const { | 
| 252 assert(response_time_ms > 0); | 234 assert(response_time_ms > 0); | 
| 253 double beta = 0.0; | 235 double beta = 0.0; | 
| 254 if (last_ms > 0) { | 236 if (last_ms > 0) { | 
| 255 beta = std::min((now_ms - last_ms) / | 237 beta = 0.5 * | 
| 256 static_cast<double>(response_time_ms), 1.0); | 238 std::min((now_ms - last_ms) / static_cast<double>(response_time_ms), | 
| 239 1.0); | |
| 257 } | 240 } | 
| 258 double bits_per_frame = static_cast<double>(current_bitrate_bps_) / 30.0; | 241 double bits_per_frame = static_cast<double>(current_bitrate_bps_) / 30.0; | 
| 259 double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0)); | 242 double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0)); | 
| 260 double avg_packet_size_bits = bits_per_frame / packets_per_frame; | 243 double avg_packet_size_bits = bits_per_frame / packets_per_frame; | 
| 261 uint32_t additive_increase_bps = std::max( | 244 uint32_t additive_increase_bps = std::max( | 
| 262 1000.0, beta * avg_packet_size_bits); | 245 1000.0, beta * avg_packet_size_bits); | 
| 263 return additive_increase_bps; | 246 return additive_increase_bps; | 
| 264 } | 247 } | 
| 265 | 248 | 
| 266 void AimdRateControl::UpdateMaxBitRateEstimate(float incoming_bitrate_kbps) { | 249 void AimdRateControl::UpdateMaxBitRateEstimate(float incoming_bitrate_kbps) { | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 case kBwUnderusing: | 287 case kBwUnderusing: | 
| 305 ChangeState(kRcHold); | 288 ChangeState(kRcHold); | 
| 306 break; | 289 break; | 
| 307 default: | 290 default: | 
| 308 assert(false); | 291 assert(false); | 
| 309 } | 292 } | 
| 310 } | 293 } | 
| 311 | 294 | 
| 312 void AimdRateControl::ChangeRegion(RateControlRegion region) { | 295 void AimdRateControl::ChangeRegion(RateControlRegion region) { | 
| 313 rate_control_region_ = region; | 296 rate_control_region_ = region; | 
| 314 switch (rate_control_region_) { | |
| 315 case kRcAboveMax: | |
| 316 case kRcMaxUnknown: | |
| 317 beta_ = 0.9f; | |
| 318 break; | |
| 319 case kRcNearMax: | |
| 320 beta_ = 0.95f; | |
| 321 break; | |
| 322 default: | |
| 323 assert(false); | |
| 324 } | |
| 325 } | 297 } | 
| 326 | 298 | 
| 327 void AimdRateControl::ChangeState(RateControlState new_state) { | 299 void AimdRateControl::ChangeState(RateControlState new_state) { | 
| 328 came_from_state_ = rate_control_state_; | |
| 329 rate_control_state_ = new_state; | 300 rate_control_state_ = new_state; | 
| 330 } | 301 } | 
| 331 } // namespace webrtc | 302 } // namespace webrtc | 
| OLD | NEW |