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

Side by Side Diff: webrtc/modules/congestion_controller/probe_controller.cc

Issue 2986563002: Add probing to recover faster from large bitrate drops. (Closed)
Patch Set: Move drop detection to ProbeController. Created 3 years, 4 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
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 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/congestion_controller/probe_controller.h" 11 #include "webrtc/modules/congestion_controller/probe_controller.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <initializer_list> 14 #include <initializer_list>
15 15
16 #include "webrtc/rtc_base/logging.h" 16 #include "webrtc/rtc_base/logging.h"
17 #include "webrtc/rtc_base/safe_conversions.h" 17 #include "webrtc/rtc_base/safe_conversions.h"
18 #include "webrtc/system_wrappers/include/field_trial.h"
18 #include "webrtc/system_wrappers/include/metrics.h" 19 #include "webrtc/system_wrappers/include/metrics.h"
19 20
20 namespace webrtc { 21 namespace webrtc {
21 22
22 namespace { 23 namespace {
23 // Maximum waiting time from the time of initiating probing to getting 24 // Maximum waiting time from the time of initiating probing to getting
24 // the measured results back. 25 // the measured results back.
25 constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000; 26 constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000;
26 27
27 // Value of |min_bitrate_to_probe_further_bps_| that indicates 28 // Value of |min_bitrate_to_probe_further_bps_| that indicates
28 // further probing is disabled. 29 // further probing is disabled.
29 constexpr int kExponentialProbingDisabled = 0; 30 constexpr int kExponentialProbingDisabled = 0;
30 31
31 // Default probing bitrate limit. Applied only when the application didn't 32 // Default probing bitrate limit. Applied only when the application didn't
32 // specify max bitrate. 33 // specify max bitrate.
33 constexpr int64_t kDefaultMaxProbingBitrateBps = 5000000; 34 constexpr int64_t kDefaultMaxProbingBitrateBps = 5000000;
34 35
35 // This is a limit on how often probing can be done when there is a BW
36 // drop detected in ALR.
37 constexpr int64_t kAlrProbingIntervalMinMs = 5000;
38
39 // Interval between probes when ALR periodic probing is enabled. 36 // Interval between probes when ALR periodic probing is enabled.
40 constexpr int64_t kAlrPeriodicProbingIntervalMs = 5000; 37 constexpr int64_t kAlrPeriodicProbingIntervalMs = 5000;
41 38
42 // Minimum probe bitrate percentage to probe further for repeated probes, 39 // Minimum probe bitrate percentage to probe further for repeated probes,
43 // relative to the previous probe. For example, if 1Mbps probe results in 40 // relative to the previous probe. For example, if 1Mbps probe results in
44 // 80kbps, then we'll probe again at 1.6Mbps. In that case second probe won't be 41 // 80kbps, then we'll probe again at 1.6Mbps. In that case second probe won't be
45 // sent if we get 600kbps from the first one. 42 // sent if we get 600kbps from the first one.
46 constexpr int kRepeatedProbeMinPercentage = 70; 43 constexpr int kRepeatedProbeMinPercentage = 70;
47 44
45 // If the bitrate drops to a factor |kBitrateDropThreshold| or lower
46 // and we recover within |kBitrateDropTimeoutMs|, then we'll send
47 // a probe at a fraction |kProbeFractionAfterDrop| of the original bitrate.
48 constexpr double kBitrateDropThreshold = 0.66;
49 constexpr int kBitrateDropTimeoutMs = 5000;
50 constexpr double kProbeFractionAfterDrop = 0.85;
51
52 // Timeout for probing after leaving ALR. If the bitrate drops significantly,
53 // (as determined by the delay based estimator) and we leave ALR, then we will
54 // send a probe if we recover within |kLeftAlrTimeoutMs| ms.
55 constexpr int kAlrEndedTimeoutMs = 3000;
56
57 // The expected uncertainty of probe result (as a fraction of the target probe
58 // This is a limit on how often probing can be done when there is a BW
59 // drop detected in ALR.
60 constexpr int64_t kMinTimeBetweenAlrProbesMs = 5000;
61
62 // bitrate). Used to avoid probing if the probe bitrate is close to our current
63 // estimate.
64 constexpr double kProbeUncertainty = 0.05;
65
66 // Use probing to recover faster after large bitrate estimate drops.
67 constexpr char kBweRapidRecoveryExperiment[] =
68 "WebRTC-BweRapidRecoveryExperiment";
69
48 } // namespace 70 } // namespace
49 71
50 ProbeController::ProbeController(PacedSender* pacer, const Clock* clock) 72 ProbeController::ProbeController(PacedSender* pacer, const Clock* clock)
51 : pacer_(pacer), clock_(clock), enable_periodic_alr_probing_(false) { 73 : pacer_(pacer), clock_(clock), enable_periodic_alr_probing_(false) {
52 Reset(); 74 Reset();
75 in_rapid_recovery_experiment_ = webrtc::field_trial::FindFullName(
76 kBweRapidRecoveryExperiment) == "Enabled";
53 } 77 }
54 78
55 void ProbeController::SetBitrates(int64_t min_bitrate_bps, 79 void ProbeController::SetBitrates(int64_t min_bitrate_bps,
56 int64_t start_bitrate_bps, 80 int64_t start_bitrate_bps,
57 int64_t max_bitrate_bps) { 81 int64_t max_bitrate_bps) {
58 rtc::CritScope cs(&critsect_); 82 rtc::CritScope cs(&critsect_);
59 83
60 if (start_bitrate_bps > 0) { 84 if (start_bitrate_bps > 0) {
61 start_bitrate_bps_ = start_bitrate_bps; 85 start_bitrate_bps_ = start_bitrate_bps;
62 estimated_bitrate_bps_ = start_bitrate_bps; 86 estimated_bitrate_bps_ = start_bitrate_bps;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 << " Minimum to probe further: " 163 << " Minimum to probe further: "
140 << min_bitrate_to_probe_further_bps_; 164 << min_bitrate_to_probe_further_bps_;
141 165
142 if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled && 166 if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled &&
143 bitrate_bps > min_bitrate_to_probe_further_bps_) { 167 bitrate_bps > min_bitrate_to_probe_further_bps_) {
144 // Double the probing bitrate. 168 // Double the probing bitrate.
145 InitiateProbing(now_ms, {2 * bitrate_bps}, true); 169 InitiateProbing(now_ms, {2 * bitrate_bps}, true);
146 } 170 }
147 } 171 }
148 172
149 // Detect a drop in estimated BW when operating in ALR and not already 173 if (bitrate_bps < kBitrateDropThreshold * estimated_bitrate_bps_) {
150 // probing. The current response is to initiate a single probe session at the 174 time_of_last_large_drop_ms_ = now_ms;
151 // previous bitrate and immediately use the reported bitrate as the new 175 bitrate_before_last_large_drop_bps_ = estimated_bitrate_bps_;
152 // bitrate.
153 //
154 // If the probe session fails, the assumption is that this drop was a
155 // real one from a competing flow or something else on the network and
156 // it ramps up from bitrate_bps.
157 if (state_ == State::kProbingComplete &&
158 pacer_->GetApplicationLimitedRegionStartTime() &&
159 bitrate_bps < 2 * estimated_bitrate_bps_ / 3 &&
160 (now_ms - last_alr_probing_time_) > kAlrProbingIntervalMinMs) {
161 LOG(LS_INFO) << "Detected big BW drop in ALR, start probe.";
162 // Track how often we probe in response to BW drop in ALR.
163 RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.AlrProbingIntervalInS",
164 (now_ms - last_alr_probing_time_) / 1000);
165 InitiateProbing(now_ms, {estimated_bitrate_bps_}, false);
166 last_alr_probing_time_ = now_ms;
167
168 // TODO(isheriff): May want to track when we did ALR probing in order
169 // to reset |last_alr_probing_time_| if we validate that it was a
170 // drop due to exogenous event.
171 } 176 }
172 177
173 estimated_bitrate_bps_ = bitrate_bps; 178 estimated_bitrate_bps_ = bitrate_bps;
174 } 179 }
175 180
176 void ProbeController::EnablePeriodicAlrProbing(bool enable) { 181 void ProbeController::EnablePeriodicAlrProbing(bool enable) {
177 rtc::CritScope cs(&critsect_); 182 rtc::CritScope cs(&critsect_);
178 enable_periodic_alr_probing_ = enable; 183 enable_periodic_alr_probing_ = enable;
179 } 184 }
180 185
186 void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) {
187 rtc::CritScope cs(&critsect_);
188 alr_end_time_ms_.emplace(alr_end_time_ms);
189 }
190
191 void ProbeController::RequestProbe() {
192 int64_t now_ms = clock_->TimeInMilliseconds();
193 rtc::CritScope cs(&critsect_);
194 // Called once we have returned to normal state after a large drop in
195 // estimated bandwidth. The current response is to initiate a single probe
196 // session (if not already probing) at the previous bitrate.
197 //
198 // If the probe session fails, the assumption is that this drop was a
199 // real one from a competing flow or a network change.
200 bool in_alr = pacer_->GetApplicationLimitedRegionStartTime().has_value();
201 bool alr_ended_recently =
202 (alr_end_time_ms_.has_value() &&
203 now_ms - alr_end_time_ms_.value() < kAlrEndedTimeoutMs);
204 if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) {
205 if (state_ == State::kProbingComplete) {
206 uint32_t suggested_probe_bps =
207 kProbeFractionAfterDrop * bitrate_before_last_large_drop_bps_;
208 uint32_t min_expected_probe_result_bps =
209 (1 - kProbeUncertainty) * suggested_probe_bps;
210 int64_t time_since_drop_ms = now_ms - time_of_last_large_drop_ms_;
211 int64_t time_since_probe_ms = now_ms - last_bwe_drop_probing_time_ms_;
212 if (min_expected_probe_result_bps > estimated_bitrate_bps_ &&
213 time_since_drop_ms < kBitrateDropTimeoutMs &&
214 time_since_probe_ms > kMinTimeBetweenAlrProbesMs) {
215 LOG(LS_INFO) << "Detected big bandwidth drop, start probing.";
216 // Track how often we probe in response to bandwidth drop in ALR.
217 RTC_HISTOGRAM_COUNTS_10000(
218 "WebRTC.BWE.BweDropProbingIntervalInS",
219 (now_ms - last_bwe_drop_probing_time_ms_) / 1000);
220 InitiateProbing(now_ms, {suggested_probe_bps}, false);
221 last_bwe_drop_probing_time_ms_ = now_ms;
222 }
223 }
224 }
225 }
226
181 void ProbeController::Reset() { 227 void ProbeController::Reset() {
182 rtc::CritScope cs(&critsect_); 228 rtc::CritScope cs(&critsect_);
183 network_state_ = kNetworkUp; 229 network_state_ = kNetworkUp;
184 state_ = State::kInit; 230 state_ = State::kInit;
185 min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; 231 min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
186 time_last_probing_initiated_ms_ = 0; 232 time_last_probing_initiated_ms_ = 0;
187 estimated_bitrate_bps_ = 0; 233 estimated_bitrate_bps_ = 0;
188 start_bitrate_bps_ = 0; 234 start_bitrate_bps_ = 0;
189 max_bitrate_bps_ = 0; 235 max_bitrate_bps_ = 0;
190 last_alr_probing_time_ = clock_->TimeInMilliseconds(); 236 int64_t now_ms = clock_->TimeInMilliseconds();
237 last_bwe_drop_probing_time_ms_ = now_ms;
238 alr_end_time_ms_.reset();
191 mid_call_probing_waiting_for_result_ = false; 239 mid_call_probing_waiting_for_result_ = false;
240 time_of_last_large_drop_ms_ = now_ms;
241 bitrate_before_last_large_drop_bps_ = 0;
192 } 242 }
193 243
194 void ProbeController::Process() { 244 void ProbeController::Process() {
195 rtc::CritScope cs(&critsect_); 245 rtc::CritScope cs(&critsect_);
196 246
197 int64_t now_ms = clock_->TimeInMilliseconds(); 247 int64_t now_ms = clock_->TimeInMilliseconds();
198 248
199 if (now_ms - time_last_probing_initiated_ms_ > 249 if (now_ms - time_last_probing_initiated_ms_ >
200 kMaxWaitingTimeForProbingResultMs) { 250 kMaxWaitingTimeForProbingResultMs) {
201 mid_call_probing_waiting_for_result_ = false; 251 mid_call_probing_waiting_for_result_ = false;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 state_ = State::kWaitingForProbingResult; 292 state_ = State::kWaitingForProbingResult;
243 min_bitrate_to_probe_further_bps_ = 293 min_bitrate_to_probe_further_bps_ =
244 (*(bitrates_to_probe.end() - 1)) * kRepeatedProbeMinPercentage / 100; 294 (*(bitrates_to_probe.end() - 1)) * kRepeatedProbeMinPercentage / 100;
245 } else { 295 } else {
246 state_ = State::kProbingComplete; 296 state_ = State::kProbingComplete;
247 min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; 297 min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled;
248 } 298 }
249 } 299 }
250 300
251 } // namespace webrtc 301 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698