OLD | NEW |
| (Empty) |
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/mimd_rate_control.h" | |
12 | |
13 #include <algorithm> | |
14 #include <cassert> | |
15 #include <cmath> | |
16 #include <cstring> | |
17 | |
18 namespace webrtc { | |
19 | |
20 const int64_t kDefaultRttMs = 200; | |
21 const int64_t kLogIntervalMs = 1000; | |
22 | |
23 MimdRateControl::MimdRateControl(uint32_t min_bitrate_bps) | |
24 : min_configured_bit_rate_(min_bitrate_bps), | |
25 max_configured_bit_rate_(30000000), | |
26 current_bit_rate_(max_configured_bit_rate_), | |
27 max_hold_rate_(0), | |
28 avg_max_bit_rate_(-1.0f), | |
29 var_max_bit_rate_(0.4f), | |
30 rate_control_state_(kRcHold), | |
31 came_from_state_(kRcDecrease), | |
32 rate_control_region_(kRcMaxUnknown), | |
33 last_bit_rate_change_(-1), | |
34 current_input_(kBwNormal, 0, 1.0), | |
35 updated_(false), | |
36 time_first_incoming_estimate_(-1), | |
37 initialized_bit_rate_(false), | |
38 avg_change_period_(1000.0f), | |
39 last_change_ms_(-1), | |
40 beta_(0.9f), | |
41 rtt_(kDefaultRttMs), | |
42 time_of_last_log_(-1) | |
43 { | |
44 } | |
45 | |
46 RateControlType MimdRateControl::GetControlType() const { | |
47 return kMimdControl; | |
48 } | |
49 | |
50 uint32_t MimdRateControl::GetMinBitrate() const { | |
51 return min_configured_bit_rate_; | |
52 } | |
53 | |
54 bool MimdRateControl::ValidEstimate() const { | |
55 return initialized_bit_rate_; | |
56 } | |
57 | |
58 int64_t MimdRateControl::GetFeedbackInterval() const { | |
59 return kMaxFeedbackIntervalMs; | |
60 } | |
61 | |
62 bool MimdRateControl::TimeToReduceFurther(int64_t time_now, | |
63 uint32_t incoming_bitrate_bps) const { | |
64 const int64_t bitrate_reduction_interval = | |
65 std::max<int64_t>(std::min<int64_t>(rtt_, 200), 10); | |
66 if (time_now - last_bit_rate_change_ >= bitrate_reduction_interval) { | |
67 return true; | |
68 } | |
69 if (ValidEstimate()) { | |
70 const int threshold = static_cast<int>(1.05 * incoming_bitrate_bps); | |
71 const int bitrate_difference = LatestEstimate() - incoming_bitrate_bps; | |
72 return bitrate_difference > threshold; | |
73 } | |
74 return false; | |
75 } | |
76 | |
77 uint32_t MimdRateControl::LatestEstimate() const { | |
78 return current_bit_rate_; | |
79 } | |
80 | |
81 uint32_t MimdRateControl::UpdateBandwidthEstimate(int64_t now_ms) { | |
82 current_bit_rate_ = ChangeBitRate(current_bit_rate_, | |
83 current_input_._incomingBitRate, | |
84 current_input_._noiseVar, | |
85 now_ms); | |
86 if (now_ms - time_of_last_log_ > kLogIntervalMs) { | |
87 time_of_last_log_ = now_ms; | |
88 } | |
89 return current_bit_rate_; | |
90 } | |
91 | |
92 void MimdRateControl::SetRtt(int64_t rtt) { | |
93 rtt_ = rtt; | |
94 } | |
95 | |
96 RateControlRegion MimdRateControl::Update(const RateControlInput* input, | |
97 int64_t now_ms) { | |
98 assert(input); | |
99 | |
100 // Set the initial bit rate value to what we're receiving the first half | |
101 // second. | |
102 if (!initialized_bit_rate_) { | |
103 if (time_first_incoming_estimate_ < 0) { | |
104 if (input->_incomingBitRate > 0) { | |
105 time_first_incoming_estimate_ = now_ms; | |
106 } | |
107 } else if (now_ms - time_first_incoming_estimate_ > 500 && | |
108 input->_incomingBitRate > 0) { | |
109 current_bit_rate_ = input->_incomingBitRate; | |
110 initialized_bit_rate_ = true; | |
111 } | |
112 } | |
113 | |
114 if (updated_ && current_input_._bwState == kBwOverusing) { | |
115 // Only update delay factor and incoming bit rate. We always want to react | |
116 // on an over-use. | |
117 current_input_._noiseVar = input->_noiseVar; | |
118 current_input_._incomingBitRate = input->_incomingBitRate; | |
119 return rate_control_region_; | |
120 } | |
121 updated_ = true; | |
122 current_input_ = *input; | |
123 return rate_control_region_; | |
124 } | |
125 | |
126 void MimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) { | |
127 } | |
128 | |
129 uint32_t MimdRateControl::ChangeBitRate(uint32_t current_bit_rate, | |
130 uint32_t incoming_bit_rate, | |
131 double noise_var, | |
132 int64_t now_ms) { | |
133 if (!updated_) { | |
134 return current_bit_rate_; | |
135 } | |
136 updated_ = false; | |
137 UpdateChangePeriod(now_ms); | |
138 ChangeState(current_input_, now_ms); | |
139 // calculated here because it's used in multiple places | |
140 const float incoming_bit_rate_kbps = incoming_bit_rate / 1000.0f; | |
141 // Calculate the max bit rate std dev given the normalized | |
142 // variance and the current incoming bit rate. | |
143 const float std_max_bit_rate = sqrt(var_max_bit_rate_ * avg_max_bit_rate_); | |
144 bool recovery = false; | |
145 switch (rate_control_state_) { | |
146 case kRcHold: { | |
147 max_hold_rate_ = std::max(max_hold_rate_, incoming_bit_rate); | |
148 break; | |
149 } | |
150 case kRcIncrease: { | |
151 if (avg_max_bit_rate_ >= 0) { | |
152 if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 3 * std_max_bit_rate) { | |
153 ChangeRegion(kRcMaxUnknown); | |
154 avg_max_bit_rate_ = -1.0; | |
155 } else if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 2.5 * | |
156 std_max_bit_rate) { | |
157 ChangeRegion(kRcAboveMax); | |
158 } | |
159 } | |
160 const int64_t response_time = | |
161 static_cast<int64_t>(avg_change_period_ + 0.5f) + rtt_ + 300; | |
162 double alpha = RateIncreaseFactor(now_ms, last_bit_rate_change_, | |
163 response_time, noise_var); | |
164 | |
165 current_bit_rate = static_cast<uint32_t>(current_bit_rate * alpha) + 1000; | |
166 if (max_hold_rate_ > 0 && beta_ * max_hold_rate_ > current_bit_rate) { | |
167 current_bit_rate = static_cast<uint32_t>(beta_ * max_hold_rate_); | |
168 avg_max_bit_rate_ = beta_ * max_hold_rate_ / 1000.0f; | |
169 ChangeRegion(kRcNearMax); | |
170 recovery = true; | |
171 } | |
172 max_hold_rate_ = 0; | |
173 last_bit_rate_change_ = now_ms; | |
174 break; | |
175 } | |
176 case kRcDecrease: { | |
177 if (incoming_bit_rate < min_configured_bit_rate_) { | |
178 current_bit_rate = min_configured_bit_rate_; | |
179 } else { | |
180 // Set bit rate to something slightly lower than max | |
181 // to get rid of any self-induced delay. | |
182 current_bit_rate = static_cast<uint32_t>(beta_ * incoming_bit_rate + | |
183 0.5); | |
184 if (current_bit_rate > current_bit_rate_) { | |
185 // Avoid increasing the rate when over-using. | |
186 if (rate_control_region_ != kRcMaxUnknown) { | |
187 current_bit_rate = static_cast<uint32_t>(beta_ * avg_max_bit_rate_ * | |
188 1000 + 0.5f); | |
189 } | |
190 current_bit_rate = std::min(current_bit_rate, current_bit_rate_); | |
191 } | |
192 ChangeRegion(kRcNearMax); | |
193 | |
194 if (incoming_bit_rate_kbps < avg_max_bit_rate_ - 3 * std_max_bit_rate) { | |
195 avg_max_bit_rate_ = -1.0f; | |
196 } | |
197 | |
198 UpdateMaxBitRateEstimate(incoming_bit_rate_kbps); | |
199 } | |
200 // Stay on hold until the pipes are cleared. | |
201 ChangeState(kRcHold); | |
202 last_bit_rate_change_ = now_ms; | |
203 break; | |
204 } | |
205 default: | |
206 assert(false); | |
207 } | |
208 if (!recovery && (incoming_bit_rate > 100000 || current_bit_rate > 150000) && | |
209 current_bit_rate > 1.5 * incoming_bit_rate) { | |
210 // Allow changing the bit rate if we are operating at very low rates | |
211 // Don't change the bit rate if the send side is too far off | |
212 current_bit_rate = current_bit_rate_; | |
213 last_bit_rate_change_ = now_ms; | |
214 } | |
215 return current_bit_rate; | |
216 } | |
217 | |
218 double MimdRateControl::RateIncreaseFactor(int64_t now_ms, | |
219 int64_t last_ms, | |
220 int64_t reaction_time_ms, | |
221 double noise_var) const { | |
222 // alpha = 1.02 + B ./ (1 + exp(b*(tr - (c1*s2 + c2)))) | |
223 // Parameters | |
224 const double B = 0.0407; | |
225 const double b = 0.0025; | |
226 const double c1 = -6700.0 / (33 * 33); | |
227 const double c2 = 800.0; | |
228 const double d = 0.85; | |
229 | |
230 double alpha = 1.005 + B / (1 + exp( b * (d * reaction_time_ms - | |
231 (c1 * noise_var + c2)))); | |
232 | |
233 if (alpha < 1.005) { | |
234 alpha = 1.005; | |
235 } else if (alpha > 1.3) { | |
236 alpha = 1.3; | |
237 } | |
238 | |
239 if (last_ms > -1) { | |
240 alpha = pow(alpha, (now_ms - last_ms) / 1000.0); | |
241 } | |
242 | |
243 if (rate_control_region_ == kRcNearMax) { | |
244 // We're close to our previous maximum. Try to stabilize the | |
245 // bit rate in this region, by increasing in smaller steps. | |
246 alpha = alpha - (alpha - 1.0) / 2.0; | |
247 } else if (rate_control_region_ == kRcMaxUnknown) { | |
248 alpha = alpha + (alpha - 1.0) * 2.0; | |
249 } | |
250 | |
251 return alpha; | |
252 } | |
253 | |
254 void MimdRateControl::UpdateChangePeriod(int64_t now_ms) { | |
255 int64_t change_period = 0; | |
256 if (last_change_ms_ > -1) { | |
257 change_period = now_ms - last_change_ms_; | |
258 } | |
259 last_change_ms_ = now_ms; | |
260 avg_change_period_ = 0.9f * avg_change_period_ + 0.1f * change_period; | |
261 } | |
262 | |
263 void MimdRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) { | |
264 const float alpha = 0.05f; | |
265 if (avg_max_bit_rate_ == -1.0f) { | |
266 avg_max_bit_rate_ = incoming_bit_rate_kbps; | |
267 } else { | |
268 avg_max_bit_rate_ = (1 - alpha) * avg_max_bit_rate_ + | |
269 alpha * incoming_bit_rate_kbps; | |
270 } | |
271 // Estimate the max bit rate variance and normalize the variance | |
272 // with the average max bit rate. | |
273 const float norm = std::max(avg_max_bit_rate_, 1.0f); | |
274 var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ + | |
275 alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) * | |
276 (avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm; | |
277 // 0.4 ~= 14 kbit/s at 500 kbit/s | |
278 if (var_max_bit_rate_ < 0.4f) { | |
279 var_max_bit_rate_ = 0.4f; | |
280 } | |
281 // 2.5f ~= 35 kbit/s at 500 kbit/s | |
282 if (var_max_bit_rate_ > 2.5f) { | |
283 var_max_bit_rate_ = 2.5f; | |
284 } | |
285 } | |
286 | |
287 void MimdRateControl::ChangeState(const RateControlInput& input, | |
288 int64_t now_ms) { | |
289 switch (current_input_._bwState) { | |
290 case kBwNormal: | |
291 if (rate_control_state_ == kRcHold) { | |
292 last_bit_rate_change_ = now_ms; | |
293 ChangeState(kRcIncrease); | |
294 } | |
295 break; | |
296 case kBwOverusing: | |
297 if (rate_control_state_ != kRcDecrease) { | |
298 ChangeState(kRcDecrease); | |
299 } | |
300 break; | |
301 case kBwUnderusing: | |
302 ChangeState(kRcHold); | |
303 break; | |
304 default: | |
305 assert(false); | |
306 } | |
307 } | |
308 | |
309 void MimdRateControl::ChangeRegion(RateControlRegion region) { | |
310 rate_control_region_ = region; | |
311 switch (rate_control_region_) { | |
312 case kRcAboveMax: | |
313 case kRcMaxUnknown: | |
314 beta_ = 0.9f; | |
315 break; | |
316 case kRcNearMax: | |
317 beta_ = 0.95f; | |
318 break; | |
319 default: | |
320 assert(false); | |
321 } | |
322 } | |
323 | |
324 void MimdRateControl::ChangeState(RateControlState new_state) { | |
325 came_from_state_ = rate_control_state_; | |
326 rate_control_state_ = new_state; | |
327 } | |
328 } // namespace webrtc | |
OLD | NEW |