Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(623)

Side by Side Diff: webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc

Issue 2786353002: Add loss-based BWE experiment which allows us to try different parameters. (Closed)
Patch Set: Comments addressed. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698