OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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/bitrate_controller/send_side_bandwidth_estimation.h" | 11 #include "webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <cmath> | 14 #include <cmath> |
15 #include <string> | |
15 | 16 |
16 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
17 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
18 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | 19 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
19 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" | 20 #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" |
20 #include "webrtc/system_wrappers/include/field_trial.h" | 21 #include "webrtc/system_wrappers/include/field_trial.h" |
21 #include "webrtc/system_wrappers/include/metrics.h" | 22 #include "webrtc/system_wrappers/include/metrics.h" |
22 | 23 |
23 namespace webrtc { | 24 namespace webrtc { |
24 namespace { | 25 namespace { |
25 const int64_t kBweIncreaseIntervalMs = 1000; | 26 const int64_t kBweIncreaseIntervalMs = 1000; |
26 const int64_t kBweDecreaseIntervalMs = 300; | 27 const int64_t kBweDecreaseIntervalMs = 300; |
27 const int64_t kStartPhaseMs = 2000; | 28 const int64_t kStartPhaseMs = 2000; |
28 const int64_t kBweConverganceTimeMs = 20000; | 29 const int64_t kBweConverganceTimeMs = 20000; |
29 const int kLimitNumPackets = 20; | 30 const int kLimitNumPackets = 20; |
30 const int kDefaultMaxBitrateBps = 1000000000; | 31 const int kDefaultMaxBitrateBps = 1000000000; |
31 const int64_t kLowBitrateLogPeriodMs = 10000; | 32 const int64_t kLowBitrateLogPeriodMs = 10000; |
32 const int64_t kRtcEventLogPeriodMs = 5000; | 33 const int64_t kRtcEventLogPeriodMs = 5000; |
33 // Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals. | 34 // Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals. |
34 const int64_t kFeedbackIntervalMs = 1500; | 35 const int64_t kFeedbackIntervalMs = 1500; |
35 const int64_t kFeedbackTimeoutIntervals = 3; | 36 const int64_t kFeedbackTimeoutIntervals = 3; |
36 const int64_t kTimeoutIntervalMs = 1000; | 37 const int64_t kTimeoutIntervalMs = 1000; |
37 | 38 |
39 const float kDefaultLowLossThreshold = 0.02f; | |
40 const float kDefaultHighLossThreshold = 0.1f; | |
41 const int kDefaultBitrateThresholdKbps = 0; | |
42 | |
38 struct UmaRampUpMetric { | 43 struct UmaRampUpMetric { |
39 const char* metric_name; | 44 const char* metric_name; |
40 int bitrate_kbps; | 45 int bitrate_kbps; |
41 }; | 46 }; |
42 | 47 |
43 const UmaRampUpMetric kUmaRampupMetrics[] = { | 48 const UmaRampUpMetric kUmaRampupMetrics[] = { |
44 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500}, | 49 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500}, |
45 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000}, | 50 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000}, |
46 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}}; | 51 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}}; |
47 const size_t kNumUmaRampupMetrics = | 52 const size_t kNumUmaRampupMetrics = |
48 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]); | 53 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]); |
49 | 54 |
55 const char kBweLosExperiment[] = "WebRTC-BweLossExperiment"; | |
56 | |
57 bool BweLossExperimentIsEnabled() { | |
58 std::string experiment_string = | |
59 webrtc::field_trial::FindFullName(kBweLosExperiment); | |
60 // The experiment is enabled iff the field trial string begins with "Enabled". | |
61 return experiment_string.find("Enabled") == 0; | |
62 } | |
63 | |
64 bool ReadBweLossExperimentParameters(float* low_loss_threshold, | |
65 float* high_loss_threshold, | |
66 uint32_t* bitrate_threshold_kbps) { | |
67 RTC_DCHECK(low_loss_threshold); | |
68 RTC_DCHECK(high_loss_threshold); | |
69 RTC_DCHECK(bitrate_threshold_kbps); | |
70 std::string experiment_string = | |
71 webrtc::field_trial::FindFullName(kBweLosExperiment); | |
72 int parsed_values = | |
73 sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold, | |
74 high_loss_threshold, bitrate_threshold_kbps); | |
75 if (parsed_values == 3) { | |
76 RTC_CHECK_GT(*low_loss_threshold, 0.0f) | |
77 << "Loss threshold must be greater than 0."; | |
78 RTC_CHECK_LE(*low_loss_threshold, 1.0f) | |
79 << "Loss threshold must be less than or equal to 1."; | |
80 RTC_CHECK_GT(*high_loss_threshold, 0.0f) | |
81 << "Loss threshold must be greater than 0."; | |
82 RTC_CHECK_LE(*high_loss_threshold, 1.0f) | |
83 << "Loss threshold must be less than or equal to 1."; | |
84 RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold) | |
85 << "The low loss threshold must be less than or equal to the high loss " | |
86 "threshold."; | |
87 RTC_CHECK_GE(*bitrate_threshold_kbps, 0) | |
terelius
2017/03/31 08:24:33
I'd like to also check that bitrate_threshold_kbps
stefan-webrtc
2017/03/31 13:51:05
Done.
| |
88 << "Bitrate threshold can't be negative."; | |
89 return true; | |
90 } | |
91 LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment " | |
92 "experiment from field trial string. Using default."; | |
93 *low_loss_threshold = kDefaultLowLossThreshold; | |
94 *high_loss_threshold = kDefaultHighLossThreshold; | |
95 *bitrate_threshold_kbps = kDefaultBitrateThresholdKbps; | |
96 return false; | |
97 } | |
50 } // namespace | 98 } // namespace |
51 | 99 |
52 SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) | 100 SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log) |
53 : lost_packets_since_last_loss_update_Q8_(0), | 101 : lost_packets_since_last_loss_update_Q8_(0), |
54 expected_packets_since_last_loss_update_(0), | 102 expected_packets_since_last_loss_update_(0), |
55 bitrate_(0), | 103 bitrate_(0), |
56 min_bitrate_configured_(congestion_controller::GetMinBitrateBps()), | 104 min_bitrate_configured_(congestion_controller::GetMinBitrateBps()), |
57 max_bitrate_configured_(kDefaultMaxBitrateBps), | 105 max_bitrate_configured_(kDefaultMaxBitrateBps), |
58 last_low_bitrate_log_ms_(-1), | 106 last_low_bitrate_log_ms_(-1), |
59 has_decreased_since_last_fraction_loss_(false), | 107 has_decreased_since_last_fraction_loss_(false), |
60 last_feedback_ms_(-1), | 108 last_feedback_ms_(-1), |
61 last_packet_report_ms_(-1), | 109 last_packet_report_ms_(-1), |
62 last_timeout_ms_(-1), | 110 last_timeout_ms_(-1), |
63 last_fraction_loss_(0), | 111 last_fraction_loss_(0), |
64 last_logged_fraction_loss_(0), | 112 last_logged_fraction_loss_(0), |
65 last_round_trip_time_ms_(0), | 113 last_round_trip_time_ms_(0), |
66 bwe_incoming_(0), | 114 bwe_incoming_(0), |
67 delay_based_bitrate_bps_(0), | 115 delay_based_bitrate_bps_(0), |
68 time_last_decrease_ms_(0), | 116 time_last_decrease_ms_(0), |
69 first_report_time_ms_(-1), | 117 first_report_time_ms_(-1), |
70 initially_lost_packets_(0), | 118 initially_lost_packets_(0), |
71 bitrate_at_2_seconds_kbps_(0), | 119 bitrate_at_2_seconds_kbps_(0), |
72 uma_update_state_(kNoUpdate), | 120 uma_update_state_(kNoUpdate), |
73 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false), | 121 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false), |
74 event_log_(event_log), | 122 event_log_(event_log), |
75 last_rtc_event_log_ms_(-1), | 123 last_rtc_event_log_ms_(-1), |
76 in_timeout_experiment_( | 124 in_timeout_experiment_( |
77 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")) { | 125 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")), |
126 low_loss_threshold_(kDefaultLowLossThreshold), | |
127 high_loss_threshold_(kDefaultHighLossThreshold), | |
128 bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) { | |
78 RTC_DCHECK(event_log); | 129 RTC_DCHECK(event_log); |
130 if (BweLossExperimentIsEnabled()) { | |
131 uint32_t bitrate_threshold_kbps; | |
132 if (ReadBweLossExperimentParameters(&low_loss_threshold_, | |
133 &high_loss_threshold_, | |
134 &bitrate_threshold_kbps)) { | |
135 LOG(LS_INFO) << "Enabled BweLossExperiment with parameters " | |
136 << low_loss_threshold_ << ", " << high_loss_threshold_ | |
137 << ", " << bitrate_threshold_kbps; | |
138 bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000; | |
139 } | |
140 } | |
79 } | 141 } |
80 | 142 |
81 SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} | 143 SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} |
82 | 144 |
83 void SendSideBandwidthEstimation::SetBitrates(int send_bitrate, | 145 void SendSideBandwidthEstimation::SetBitrates(int send_bitrate, |
84 int min_bitrate, | 146 int min_bitrate, |
85 int max_bitrate) { | 147 int max_bitrate) { |
86 if (send_bitrate > 0) | 148 if (send_bitrate > 0) |
87 SetSendBitrate(send_bitrate); | 149 SetSendBitrate(send_bitrate); |
88 SetMinMaxBitrate(min_bitrate, max_bitrate); | 150 SetMinMaxBitrate(min_bitrate, max_bitrate); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 } | 284 } |
223 UpdateMinHistory(now_ms); | 285 UpdateMinHistory(now_ms); |
224 if (last_packet_report_ms_ == -1) { | 286 if (last_packet_report_ms_ == -1) { |
225 // No feedback received. | 287 // No feedback received. |
226 bitrate_ = CapBitrateToThresholds(now_ms, bitrate_); | 288 bitrate_ = CapBitrateToThresholds(now_ms, bitrate_); |
227 return; | 289 return; |
228 } | 290 } |
229 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_; | 291 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_; |
230 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_; | 292 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_; |
231 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) { | 293 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) { |
232 if (last_fraction_loss_ <= 5) { | 294 // We only care about loss above a given bitrate threshold. |
295 float loss = last_fraction_loss_ / 256.0f; | |
296 // We only make decisions based on loss when the bitrate is above a | |
297 // threshold. This is a crude way of handling loss which is uncorrelated | |
298 // to congestion. | |
299 if (bitrate_ < bitrate_threshold_bps_ || loss <= low_loss_threshold_) { | |
233 // Loss < 2%: Increase rate by 8% of the min bitrate in the last | 300 // Loss < 2%: Increase rate by 8% of the min bitrate in the last |
234 // kBweIncreaseIntervalMs. | 301 // kBweIncreaseIntervalMs. |
235 // Note that by remembering the bitrate over the last second one can | 302 // Note that by remembering the bitrate over the last second one can |
236 // rampup up one second faster than if only allowed to start ramping | 303 // rampup up one second faster than if only allowed to start ramping |
237 // at 8% per second rate now. E.g.: | 304 // at 8% per second rate now. E.g.: |
238 // If sending a constant 100kbps it can rampup immediatly to 108kbps | 305 // If sending a constant 100kbps it can rampup immediatly to 108kbps |
239 // whenever a receiver report is received with lower packet loss. | 306 // whenever a receiver report is received with lower packet loss. |
240 // If instead one would do: bitrate_ *= 1.08^(delta time), it would | 307 // If instead one would do: bitrate_ *= 1.08^(delta time), it would |
241 // take over one second since the lower packet loss to achieve | 308 // take over one second since the lower packet loss to achieve |
242 // 108kbps. | 309 // 108kbps. |
243 bitrate_ = static_cast<uint32_t>( | 310 bitrate_ = static_cast<uint32_t>( |
244 min_bitrate_history_.front().second * 1.08 + 0.5); | 311 min_bitrate_history_.front().second * 1.08 + 0.5); |
245 | 312 |
246 // Add 1 kbps extra, just to make sure that we do not get stuck | 313 // Add 1 kbps extra, just to make sure that we do not get stuck |
247 // (gives a little extra increase at low rates, negligible at higher | 314 // (gives a little extra increase at low rates, negligible at higher |
248 // rates). | 315 // rates). |
249 bitrate_ += 1000; | 316 bitrate_ += 1000; |
250 } else if (last_fraction_loss_ <= 26) { | 317 } else if (bitrate_ > bitrate_threshold_bps_) { |
251 // Loss between 2% - 10%: Do nothing. | 318 if (loss <= high_loss_threshold_) { |
252 } else { | 319 // Loss between 2% - 10%: Do nothing. |
253 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs | 320 } else { |
254 // + rtt. | 321 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs |
255 if (!has_decreased_since_last_fraction_loss_ && | 322 // + rtt. |
256 (now_ms - time_last_decrease_ms_) >= | 323 if (!has_decreased_since_last_fraction_loss_ && |
257 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) { | 324 (now_ms - time_last_decrease_ms_) >= |
258 time_last_decrease_ms_ = now_ms; | 325 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) { |
326 time_last_decrease_ms_ = now_ms; | |
259 | 327 |
260 // Reduce rate: | 328 // Reduce rate: |
261 // newRate = rate * (1 - 0.5*lossRate); | 329 // newRate = rate * (1 - 0.5*lossRate); |
262 // where packetLoss = 256*lossRate; | 330 // where packetLoss = 256*lossRate; |
263 bitrate_ = static_cast<uint32_t>( | 331 bitrate_ = static_cast<uint32_t>( |
264 (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / | 332 (bitrate_ * static_cast<double>(512 - last_fraction_loss_)) / |
265 512.0); | 333 512.0); |
266 has_decreased_since_last_fraction_loss_ = true; | 334 has_decreased_since_last_fraction_loss_ = true; |
335 } | |
267 } | 336 } |
268 } | 337 } |
269 } else if (time_since_feedback_ms > | 338 } else if (time_since_feedback_ms > |
270 kFeedbackTimeoutIntervals * kFeedbackIntervalMs && | 339 kFeedbackTimeoutIntervals * kFeedbackIntervalMs && |
271 (last_timeout_ms_ == -1 || | 340 (last_timeout_ms_ == -1 || |
272 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) { | 341 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) { |
273 if (in_timeout_experiment_) { | 342 if (in_timeout_experiment_) { |
274 LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms | 343 LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms |
275 << " ms), reducing bitrate."; | 344 << " ms), reducing bitrate."; |
276 bitrate_ *= 0.8; | 345 bitrate_ *= 0.8; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate / 1000 | 405 LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate / 1000 |
337 << " kbps is below configured min bitrate " | 406 << " kbps is below configured min bitrate " |
338 << min_bitrate_configured_ / 1000 << " kbps."; | 407 << min_bitrate_configured_ / 1000 << " kbps."; |
339 last_low_bitrate_log_ms_ = now_ms; | 408 last_low_bitrate_log_ms_ = now_ms; |
340 } | 409 } |
341 bitrate = min_bitrate_configured_; | 410 bitrate = min_bitrate_configured_; |
342 } | 411 } |
343 return bitrate; | 412 return bitrate; |
344 } | 413 } |
345 } // namespace webrtc | 414 } // namespace webrtc |
OLD | NEW |