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