1 /*
2 * Copyright (c) 2012 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 "modules/congestion_controller/goog_cc/send_side_bandwidth_estimation.h"
12
13 #include <algorithm>
14 #include <cstdio>
15 #include <limits>
16 #include <memory>
17 #include <string>
18
19 #include "absl/strings/match.h"
20 #include "api/field_trials_view.h"
21 #include "api/network_state_predictor.h"
22 #include "api/rtc_event_log/rtc_event.h"
23 #include "api/rtc_event_log/rtc_event_log.h"
24 #include "api/units/data_rate.h"
25 #include "api/units/time_delta.h"
26 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
27 #include "modules/congestion_controller/goog_cc/loss_based_bwe_v2.h"
28 #include "modules/remote_bitrate_estimator/include/bwe_defines.h"
29 #include "rtc_base/checks.h"
30 #include "rtc_base/logging.h"
31 #include "system_wrappers/include/field_trial.h"
32 #include "system_wrappers/include/metrics.h"
33
34 namespace webrtc {
35 namespace {
36 constexpr TimeDelta kBweIncreaseInterval = TimeDelta::Millis(1000);
37 constexpr TimeDelta kBweDecreaseInterval = TimeDelta::Millis(300);
38 constexpr TimeDelta kStartPhase = TimeDelta::Millis(2000);
39 constexpr TimeDelta kBweConverganceTime = TimeDelta::Millis(20000);
40 constexpr int kLimitNumPackets = 20;
41 constexpr DataRate kDefaultMaxBitrate = DataRate::BitsPerSec(1000000000);
42 constexpr TimeDelta kLowBitrateLogPeriod = TimeDelta::Millis(10000);
43 constexpr TimeDelta kRtcEventLogPeriod = TimeDelta::Millis(5000);
44 // Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
45 constexpr TimeDelta kMaxRtcpFeedbackInterval = TimeDelta::Millis(5000);
46
47 constexpr float kDefaultLowLossThreshold = 0.02f;
48 constexpr float kDefaultHighLossThreshold = 0.1f;
49 constexpr DataRate kDefaultBitrateThreshold = DataRate::Zero();
50
51 struct UmaRampUpMetric {
52 const char* metric_name;
53 int bitrate_kbps;
54 };
55
56 const UmaRampUpMetric kUmaRampupMetrics[] = {
57 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
58 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
59 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
60 const size_t kNumUmaRampupMetrics =
61 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
62
63 const char kBweLosExperiment[] = "WebRTC-BweLossExperiment";
64
BweLossExperimentIsEnabled()65 bool BweLossExperimentIsEnabled() {
66 std::string experiment_string =
67 webrtc::field_trial::FindFullName(kBweLosExperiment);
68 // The experiment is enabled iff the field trial string begins with "Enabled".
69 return absl::StartsWith(experiment_string, "Enabled");
70 }
71
ReadBweLossExperimentParameters(float * low_loss_threshold,float * high_loss_threshold,uint32_t * bitrate_threshold_kbps)72 bool ReadBweLossExperimentParameters(float* low_loss_threshold,
73 float* high_loss_threshold,
74 uint32_t* bitrate_threshold_kbps) {
75 RTC_DCHECK(low_loss_threshold);
76 RTC_DCHECK(high_loss_threshold);
77 RTC_DCHECK(bitrate_threshold_kbps);
78 std::string experiment_string =
79 webrtc::field_trial::FindFullName(kBweLosExperiment);
80 int parsed_values =
81 sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold,
82 high_loss_threshold, bitrate_threshold_kbps);
83 if (parsed_values == 3) {
84 RTC_CHECK_GT(*low_loss_threshold, 0.0f)
85 << "Loss threshold must be greater than 0.";
86 RTC_CHECK_LE(*low_loss_threshold, 1.0f)
87 << "Loss threshold must be less than or equal to 1.";
88 RTC_CHECK_GT(*high_loss_threshold, 0.0f)
89 << "Loss threshold must be greater than 0.";
90 RTC_CHECK_LE(*high_loss_threshold, 1.0f)
91 << "Loss threshold must be less than or equal to 1.";
92 RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold)
93 << "The low loss threshold must be less than or equal to the high loss "
94 "threshold.";
95 RTC_CHECK_GE(*bitrate_threshold_kbps, 0)
96 << "Bitrate threshold can't be negative.";
97 RTC_CHECK_LT(*bitrate_threshold_kbps,
98 std::numeric_limits<int>::max() / 1000)
99 << "Bitrate must be smaller enough to avoid overflows.";
100 return true;
101 }
102 RTC_LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment "
103 "experiment from field trial string. Using default.";
104 *low_loss_threshold = kDefaultLowLossThreshold;
105 *high_loss_threshold = kDefaultHighLossThreshold;
106 *bitrate_threshold_kbps = kDefaultBitrateThreshold.kbps();
107 return false;
108 }
109 } // namespace
110
LinkCapacityTracker()111 LinkCapacityTracker::LinkCapacityTracker()
112 : tracking_rate("rate", TimeDelta::Seconds(10)) {
113 ParseFieldTrial({&tracking_rate},
114 field_trial::FindFullName("WebRTC-Bwe-LinkCapacity"));
115 }
116
~LinkCapacityTracker()117 LinkCapacityTracker::~LinkCapacityTracker() {}
118
UpdateDelayBasedEstimate(Timestamp at_time,DataRate delay_based_bitrate)119 void LinkCapacityTracker::UpdateDelayBasedEstimate(
120 Timestamp at_time,
121 DataRate delay_based_bitrate) {
122 if (delay_based_bitrate < last_delay_based_estimate_) {
123 capacity_estimate_bps_ =
124 std::min(capacity_estimate_bps_, delay_based_bitrate.bps<double>());
125 last_link_capacity_update_ = at_time;
126 }
127 last_delay_based_estimate_ = delay_based_bitrate;
128 }
129
OnStartingRate(DataRate start_rate)130 void LinkCapacityTracker::OnStartingRate(DataRate start_rate) {
131 if (last_link_capacity_update_.IsInfinite())
132 capacity_estimate_bps_ = start_rate.bps<double>();
133 }
134
OnRateUpdate(absl::optional<DataRate> acknowledged,DataRate target,Timestamp at_time)135 void LinkCapacityTracker::OnRateUpdate(absl::optional<DataRate> acknowledged,
136 DataRate target,
137 Timestamp at_time) {
138 if (!acknowledged)
139 return;
140 DataRate acknowledged_target = std::min(*acknowledged, target);
141 if (acknowledged_target.bps() > capacity_estimate_bps_) {
142 TimeDelta delta = at_time - last_link_capacity_update_;
143 double alpha = delta.IsFinite() ? exp(-(delta / tracking_rate.Get())) : 0;
144 capacity_estimate_bps_ = alpha * capacity_estimate_bps_ +
145 (1 - alpha) * acknowledged_target.bps<double>();
146 }
147 last_link_capacity_update_ = at_time;
148 }
149
OnRttBackoff(DataRate backoff_rate,Timestamp at_time)150 void LinkCapacityTracker::OnRttBackoff(DataRate backoff_rate,
151 Timestamp at_time) {
152 capacity_estimate_bps_ =
153 std::min(capacity_estimate_bps_, backoff_rate.bps<double>());
154 last_link_capacity_update_ = at_time;
155 }
156
estimate() const157 DataRate LinkCapacityTracker::estimate() const {
158 return DataRate::BitsPerSec(capacity_estimate_bps_);
159 }
160
RttBasedBackoff(const FieldTrialsView * key_value_config)161 RttBasedBackoff::RttBasedBackoff(const FieldTrialsView* key_value_config)
162 : disabled_("Disabled"),
163 configured_limit_("limit", TimeDelta::Seconds(3)),
164 drop_fraction_("fraction", 0.8),
165 drop_interval_("interval", TimeDelta::Seconds(1)),
166 bandwidth_floor_("floor", DataRate::KilobitsPerSec(5)),
167 rtt_limit_(TimeDelta::PlusInfinity()),
168 // By initializing this to plus infinity, we make sure that we never
169 // trigger rtt backoff unless packet feedback is enabled.
170 last_propagation_rtt_update_(Timestamp::PlusInfinity()),
171 last_propagation_rtt_(TimeDelta::Zero()),
172 last_packet_sent_(Timestamp::MinusInfinity()) {
173 ParseFieldTrial({&disabled_, &configured_limit_, &drop_fraction_,
174 &drop_interval_, &bandwidth_floor_},
175 key_value_config->Lookup("WebRTC-Bwe-MaxRttLimit"));
176 if (!disabled_) {
177 rtt_limit_ = configured_limit_.Get();
178 }
179 }
180
UpdatePropagationRtt(Timestamp at_time,TimeDelta propagation_rtt)181 void RttBasedBackoff::UpdatePropagationRtt(Timestamp at_time,
182 TimeDelta propagation_rtt) {
183 last_propagation_rtt_update_ = at_time;
184 last_propagation_rtt_ = propagation_rtt;
185 }
186
CorrectedRtt(Timestamp at_time) const187 TimeDelta RttBasedBackoff::CorrectedRtt(Timestamp at_time) const {
188 TimeDelta time_since_rtt = at_time - last_propagation_rtt_update_;
189 TimeDelta timeout_correction = time_since_rtt;
190 // Avoid timeout when no packets are being sent.
191 TimeDelta time_since_packet_sent = at_time - last_packet_sent_;
192 timeout_correction =
193 std::max(time_since_rtt - time_since_packet_sent, TimeDelta::Zero());
194 return timeout_correction + last_propagation_rtt_;
195 }
196
197 RttBasedBackoff::~RttBasedBackoff() = default;
198
SendSideBandwidthEstimation(const FieldTrialsView * key_value_config,RtcEventLog * event_log)199 SendSideBandwidthEstimation::SendSideBandwidthEstimation(
200 const FieldTrialsView* key_value_config,
201 RtcEventLog* event_log)
202 : rtt_backoff_(key_value_config),
203 lost_packets_since_last_loss_update_(0),
204 expected_packets_since_last_loss_update_(0),
205 current_target_(DataRate::Zero()),
206 last_logged_target_(DataRate::Zero()),
207 min_bitrate_configured_(kCongestionControllerMinBitrate),
208 max_bitrate_configured_(kDefaultMaxBitrate),
209 last_low_bitrate_log_(Timestamp::MinusInfinity()),
210 has_decreased_since_last_fraction_loss_(false),
211 last_loss_feedback_(Timestamp::MinusInfinity()),
212 last_loss_packet_report_(Timestamp::MinusInfinity()),
213 last_fraction_loss_(0),
214 last_logged_fraction_loss_(0),
215 last_round_trip_time_(TimeDelta::Zero()),
216 receiver_limit_(DataRate::PlusInfinity()),
217 delay_based_limit_(DataRate::PlusInfinity()),
218 time_last_decrease_(Timestamp::MinusInfinity()),
219 first_report_time_(Timestamp::MinusInfinity()),
220 initially_lost_packets_(0),
221 bitrate_at_2_seconds_(DataRate::Zero()),
222 uma_update_state_(kNoUpdate),
223 uma_rtt_state_(kNoUpdate),
224 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
225 event_log_(event_log),
226 last_rtc_event_log_(Timestamp::MinusInfinity()),
227 low_loss_threshold_(kDefaultLowLossThreshold),
228 high_loss_threshold_(kDefaultHighLossThreshold),
229 bitrate_threshold_(kDefaultBitrateThreshold),
230 loss_based_bandwidth_estimator_v1_(key_value_config),
231 loss_based_bandwidth_estimator_v2_(key_value_config),
232 loss_based_state_(LossBasedState::kDelayBasedEstimate),
233 disable_receiver_limit_caps_only_("Disabled") {
234 RTC_DCHECK(event_log);
235 if (BweLossExperimentIsEnabled()) {
236 uint32_t bitrate_threshold_kbps;
237 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
238 &high_loss_threshold_,
239 &bitrate_threshold_kbps)) {
240 RTC_LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
241 << low_loss_threshold_ << ", " << high_loss_threshold_
242 << ", " << bitrate_threshold_kbps;
243 bitrate_threshold_ = DataRate::KilobitsPerSec(bitrate_threshold_kbps);
244 }
245 }
246 ParseFieldTrial({&disable_receiver_limit_caps_only_},
247 key_value_config->Lookup("WebRTC-Bwe-ReceiverLimitCapsOnly"));
248 if (LossBasedBandwidthEstimatorV2Enabled()) {
249 loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate(
250 min_bitrate_configured_, max_bitrate_configured_);
251 }
252 }
253
~SendSideBandwidthEstimation()254 SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
255
OnRouteChange()256 void SendSideBandwidthEstimation::OnRouteChange() {
257 lost_packets_since_last_loss_update_ = 0;
258 expected_packets_since_last_loss_update_ = 0;
259 current_target_ = DataRate::Zero();
260 min_bitrate_configured_ = kCongestionControllerMinBitrate;
261 max_bitrate_configured_ = kDefaultMaxBitrate;
262 last_low_bitrate_log_ = Timestamp::MinusInfinity();
263 has_decreased_since_last_fraction_loss_ = false;
264 last_loss_feedback_ = Timestamp::MinusInfinity();
265 last_loss_packet_report_ = Timestamp::MinusInfinity();
266 last_fraction_loss_ = 0;
267 last_logged_fraction_loss_ = 0;
268 last_round_trip_time_ = TimeDelta::Zero();
269 receiver_limit_ = DataRate::PlusInfinity();
270 delay_based_limit_ = DataRate::PlusInfinity();
271 time_last_decrease_ = Timestamp::MinusInfinity();
272 first_report_time_ = Timestamp::MinusInfinity();
273 initially_lost_packets_ = 0;
274 bitrate_at_2_seconds_ = DataRate::Zero();
275 uma_update_state_ = kNoUpdate;
276 uma_rtt_state_ = kNoUpdate;
277 last_rtc_event_log_ = Timestamp::MinusInfinity();
278 }
279
SetBitrates(absl::optional<DataRate> send_bitrate,DataRate min_bitrate,DataRate max_bitrate,Timestamp at_time)280 void SendSideBandwidthEstimation::SetBitrates(
281 absl::optional<DataRate> send_bitrate,
282 DataRate min_bitrate,
283 DataRate max_bitrate,
284 Timestamp at_time) {
285 SetMinMaxBitrate(min_bitrate, max_bitrate);
286 if (send_bitrate) {
287 link_capacity_.OnStartingRate(*send_bitrate);
288 SetSendBitrate(*send_bitrate, at_time);
289 }
290 }
291
SetSendBitrate(DataRate bitrate,Timestamp at_time)292 void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate,
293 Timestamp at_time) {
294 RTC_DCHECK_GT(bitrate, DataRate::Zero());
295 // Reset to avoid being capped by the estimate.
296 delay_based_limit_ = DataRate::PlusInfinity();
297 UpdateTargetBitrate(bitrate, at_time);
298 // Clear last sent bitrate history so the new value can be used directly
299 // and not capped.
300 min_bitrate_history_.clear();
301 }
302
SetMinMaxBitrate(DataRate min_bitrate,DataRate max_bitrate)303 void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate,
304 DataRate max_bitrate) {
305 min_bitrate_configured_ =
306 std::max(min_bitrate, kCongestionControllerMinBitrate);
307 if (max_bitrate > DataRate::Zero() && max_bitrate.IsFinite()) {
308 max_bitrate_configured_ = std::max(min_bitrate_configured_, max_bitrate);
309 } else {
310 max_bitrate_configured_ = kDefaultMaxBitrate;
311 }
312 loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate(min_bitrate_configured_,
313 max_bitrate_configured_);
314 }
315
GetMinBitrate() const316 int SendSideBandwidthEstimation::GetMinBitrate() const {
317 return min_bitrate_configured_.bps<int>();
318 }
319
target_rate() const320 DataRate SendSideBandwidthEstimation::target_rate() const {
321 DataRate target = current_target_;
322 if (!disable_receiver_limit_caps_only_)
323 target = std::min(target, receiver_limit_);
324 return std::max(min_bitrate_configured_, target);
325 }
326
loss_based_state() const327 LossBasedState SendSideBandwidthEstimation::loss_based_state() const {
328 return loss_based_state_;
329 }
330
GetEstimatedLinkCapacity() const331 DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const {
332 return link_capacity_.estimate();
333 }
334
UpdateReceiverEstimate(Timestamp at_time,DataRate bandwidth)335 void SendSideBandwidthEstimation::UpdateReceiverEstimate(Timestamp at_time,
336 DataRate bandwidth) {
337 // TODO(srte): Ensure caller passes PlusInfinity, not zero, to represent no
338 // limitation.
339 receiver_limit_ = bandwidth.IsZero() ? DataRate::PlusInfinity() : bandwidth;
340 ApplyTargetLimits(at_time);
341 }
342
UpdateDelayBasedEstimate(Timestamp at_time,DataRate bitrate)343 void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(Timestamp at_time,
344 DataRate bitrate) {
345 link_capacity_.UpdateDelayBasedEstimate(at_time, bitrate);
346 // TODO(srte): Ensure caller passes PlusInfinity, not zero, to represent no
347 // limitation.
348 delay_based_limit_ = bitrate.IsZero() ? DataRate::PlusInfinity() : bitrate;
349 ApplyTargetLimits(at_time);
350 }
351
SetAcknowledgedRate(absl::optional<DataRate> acknowledged_rate,Timestamp at_time)352 void SendSideBandwidthEstimation::SetAcknowledgedRate(
353 absl::optional<DataRate> acknowledged_rate,
354 Timestamp at_time) {
355 acknowledged_rate_ = acknowledged_rate;
356 if (!acknowledged_rate.has_value()) {
357 return;
358 }
359 if (LossBasedBandwidthEstimatorV1Enabled()) {
360 loss_based_bandwidth_estimator_v1_.UpdateAcknowledgedBitrate(
361 *acknowledged_rate, at_time);
362 }
363 if (LossBasedBandwidthEstimatorV2Enabled()) {
364 loss_based_bandwidth_estimator_v2_.SetAcknowledgedBitrate(
365 *acknowledged_rate);
366 }
367 }
368
UpdateLossBasedEstimator(const TransportPacketsFeedback & report,BandwidthUsage delay_detector_state,absl::optional<DataRate> probe_bitrate,DataRate upper_link_capacity)369 void SendSideBandwidthEstimation::UpdateLossBasedEstimator(
370 const TransportPacketsFeedback& report,
371 BandwidthUsage delay_detector_state,
372 absl::optional<DataRate> probe_bitrate,
373 DataRate upper_link_capacity) {
374 if (LossBasedBandwidthEstimatorV1Enabled()) {
375 loss_based_bandwidth_estimator_v1_.UpdateLossStatistics(
376 report.packet_feedbacks, report.feedback_time);
377 }
378 if (LossBasedBandwidthEstimatorV2Enabled()) {
379 loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate(
380 report.packet_feedbacks, delay_based_limit_, delay_detector_state,
381 probe_bitrate, upper_link_capacity);
382 UpdateEstimate(report.feedback_time);
383 }
384 }
385
UpdatePacketsLost(int64_t packets_lost,int64_t number_of_packets,Timestamp at_time)386 void SendSideBandwidthEstimation::UpdatePacketsLost(int64_t packets_lost,
387 int64_t number_of_packets,
388 Timestamp at_time) {
389 last_loss_feedback_ = at_time;
390 if (first_report_time_.IsInfinite())
391 first_report_time_ = at_time;
392
393 // Check sequence number diff and weight loss report
394 if (number_of_packets > 0) {
395 int64_t expected =
396 expected_packets_since_last_loss_update_ + number_of_packets;
397
398 // Don't generate a loss rate until it can be based on enough packets.
399 if (expected < kLimitNumPackets) {
400 // Accumulate reports.
401 expected_packets_since_last_loss_update_ = expected;
402 lost_packets_since_last_loss_update_ += packets_lost;
403 return;
404 }
405
406 has_decreased_since_last_fraction_loss_ = false;
407 int64_t lost_q8 =
408 std::max<int64_t>(lost_packets_since_last_loss_update_ + packets_lost,
409 0)
410 << 8;
411 last_fraction_loss_ = std::min<int>(lost_q8 / expected, 255);
412
413 // Reset accumulators.
414 lost_packets_since_last_loss_update_ = 0;
415 expected_packets_since_last_loss_update_ = 0;
416 last_loss_packet_report_ = at_time;
417 UpdateEstimate(at_time);
418 }
419
420 UpdateUmaStatsPacketsLost(at_time, packets_lost);
421 }
422
UpdateUmaStatsPacketsLost(Timestamp at_time,int packets_lost)423 void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(Timestamp at_time,
424 int packets_lost) {
425 DataRate bitrate_kbps =
426 DataRate::KilobitsPerSec((current_target_.bps() + 500) / 1000);
427 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
428 if (!rampup_uma_stats_updated_[i] &&
429 bitrate_kbps.kbps() >= kUmaRampupMetrics[i].bitrate_kbps) {
430 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
431 (at_time - first_report_time_).ms());
432 rampup_uma_stats_updated_[i] = true;
433 }
434 }
435 if (IsInStartPhase(at_time)) {
436 initially_lost_packets_ += packets_lost;
437 } else if (uma_update_state_ == kNoUpdate) {
438 uma_update_state_ = kFirstDone;
439 bitrate_at_2_seconds_ = bitrate_kbps;
440 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
441 initially_lost_packets_, 0, 100, 50);
442 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
443 bitrate_at_2_seconds_.kbps(), 0, 2000, 50);
444 } else if (uma_update_state_ == kFirstDone &&
445 at_time - first_report_time_ >= kBweConverganceTime) {
446 uma_update_state_ = kDone;
447 int bitrate_diff_kbps = std::max(
448 bitrate_at_2_seconds_.kbps<int>() - bitrate_kbps.kbps<int>(), 0);
449 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
450 0, 2000, 50);
451 }
452 }
453
UpdateRtt(TimeDelta rtt,Timestamp at_time)454 void SendSideBandwidthEstimation::UpdateRtt(TimeDelta rtt, Timestamp at_time) {
455 // Update RTT if we were able to compute an RTT based on this RTCP.
456 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
457 if (rtt > TimeDelta::Zero())
458 last_round_trip_time_ = rtt;
459
460 if (!IsInStartPhase(at_time) && uma_rtt_state_ == kNoUpdate) {
461 uma_rtt_state_ = kDone;
462 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", rtt.ms<int>(), 0, 2000, 50);
463 }
464 }
465
UpdateEstimate(Timestamp at_time)466 void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
467 if (rtt_backoff_.CorrectedRtt(at_time) > rtt_backoff_.rtt_limit_) {
468 if (at_time - time_last_decrease_ >= rtt_backoff_.drop_interval_ &&
469 current_target_ > rtt_backoff_.bandwidth_floor_) {
470 time_last_decrease_ = at_time;
471 DataRate new_bitrate =
472 std::max(current_target_ * rtt_backoff_.drop_fraction_,
473 rtt_backoff_.bandwidth_floor_.Get());
474 link_capacity_.OnRttBackoff(new_bitrate, at_time);
475 UpdateTargetBitrate(new_bitrate, at_time);
476 return;
477 }
478 // TODO(srte): This is likely redundant in most cases.
479 ApplyTargetLimits(at_time);
480 return;
481 }
482
483 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
484 // we haven't had any packet loss reported, to allow startup bitrate probing.
485 if (last_fraction_loss_ == 0 && IsInStartPhase(at_time)) {
486 DataRate new_bitrate = current_target_;
487 // TODO(srte): We should not allow the new_bitrate to be larger than the
488 // receiver limit here.
489 if (receiver_limit_.IsFinite())
490 new_bitrate = std::max(receiver_limit_, new_bitrate);
491 if (delay_based_limit_.IsFinite())
492 new_bitrate = std::max(delay_based_limit_, new_bitrate);
493 if (LossBasedBandwidthEstimatorV1Enabled()) {
494 loss_based_bandwidth_estimator_v1_.Initialize(new_bitrate);
495 }
496 if (LossBasedBandwidthEstimatorV2Enabled()) {
497 loss_based_bandwidth_estimator_v2_.SetBandwidthEstimate(new_bitrate);
498 }
499
500 if (new_bitrate != current_target_) {
501 min_bitrate_history_.clear();
502 if (LossBasedBandwidthEstimatorV1Enabled()) {
503 min_bitrate_history_.push_back(std::make_pair(at_time, new_bitrate));
504 } else {
505 min_bitrate_history_.push_back(
506 std::make_pair(at_time, current_target_));
507 }
508 UpdateTargetBitrate(new_bitrate, at_time);
509 return;
510 }
511 }
512 UpdateMinHistory(at_time);
513 if (last_loss_packet_report_.IsInfinite()) {
514 // No feedback received.
515 // TODO(srte): This is likely redundant in most cases.
516 ApplyTargetLimits(at_time);
517 return;
518 }
519
520 if (LossBasedBandwidthEstimatorV1ReadyForUse()) {
521 DataRate new_bitrate = loss_based_bandwidth_estimator_v1_.Update(
522 at_time, min_bitrate_history_.front().second, delay_based_limit_,
523 last_round_trip_time_);
524 UpdateTargetBitrate(new_bitrate, at_time);
525 return;
526 }
527
528 if (LossBasedBandwidthEstimatorV2ReadyForUse()) {
529 LossBasedBweV2::Result result =
530 loss_based_bandwidth_estimator_v2_.GetLossBasedResult();
531 loss_based_state_ = result.state;
532 UpdateTargetBitrate(result.bandwidth_estimate, at_time);
533 return;
534 }
535
536 TimeDelta time_since_loss_packet_report = at_time - last_loss_packet_report_;
537 if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) {
538 // We only care about loss above a given bitrate threshold.
539 float loss = last_fraction_loss_ / 256.0f;
540 // We only make decisions based on loss when the bitrate is above a
541 // threshold. This is a crude way of handling loss which is uncorrelated
542 // to congestion.
543 if (current_target_ < bitrate_threshold_ || loss <= low_loss_threshold_) {
544 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
545 // kBweIncreaseInterval.
546 // Note that by remembering the bitrate over the last second one can
547 // rampup up one second faster than if only allowed to start ramping
548 // at 8% per second rate now. E.g.:
549 // If sending a constant 100kbps it can rampup immediately to 108kbps
550 // whenever a receiver report is received with lower packet loss.
551 // If instead one would do: current_bitrate_ *= 1.08^(delta time),
552 // it would take over one second since the lower packet loss to achieve
553 // 108kbps.
554 DataRate new_bitrate = DataRate::BitsPerSec(
555 min_bitrate_history_.front().second.bps() * 1.08 + 0.5);
556
557 // Add 1 kbps extra, just to make sure that we do not get stuck
558 // (gives a little extra increase at low rates, negligible at higher
559 // rates).
560 new_bitrate += DataRate::BitsPerSec(1000);
561 UpdateTargetBitrate(new_bitrate, at_time);
562 return;
563 } else if (current_target_ > bitrate_threshold_) {
564 if (loss <= high_loss_threshold_) {
565 // Loss between 2% - 10%: Do nothing.
566 } else {
567 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseInterval
568 // + rtt.
569 if (!has_decreased_since_last_fraction_loss_ &&
570 (at_time - time_last_decrease_) >=
571 (kBweDecreaseInterval + last_round_trip_time_)) {
572 time_last_decrease_ = at_time;
573
574 // Reduce rate:
575 // newRate = rate * (1 - 0.5*lossRate);
576 // where packetLoss = 256*lossRate;
577 DataRate new_bitrate = DataRate::BitsPerSec(
578 (current_target_.bps() *
579 static_cast<double>(512 - last_fraction_loss_)) /
580 512.0);
581 has_decreased_since_last_fraction_loss_ = true;
582 UpdateTargetBitrate(new_bitrate, at_time);
583 return;
584 }
585 }
586 }
587 }
588 // TODO(srte): This is likely redundant in most cases.
589 ApplyTargetLimits(at_time);
590 }
591
UpdatePropagationRtt(Timestamp at_time,TimeDelta propagation_rtt)592 void SendSideBandwidthEstimation::UpdatePropagationRtt(
593 Timestamp at_time,
594 TimeDelta propagation_rtt) {
595 rtt_backoff_.UpdatePropagationRtt(at_time, propagation_rtt);
596 }
597
OnSentPacket(const SentPacket & sent_packet)598 void SendSideBandwidthEstimation::OnSentPacket(const SentPacket& sent_packet) {
599 // Only feedback-triggering packets will be reported here.
600 rtt_backoff_.last_packet_sent_ = sent_packet.send_time;
601 }
602
IsInStartPhase(Timestamp at_time) const603 bool SendSideBandwidthEstimation::IsInStartPhase(Timestamp at_time) const {
604 return first_report_time_.IsInfinite() ||
605 at_time - first_report_time_ < kStartPhase;
606 }
607
UpdateMinHistory(Timestamp at_time)608 void SendSideBandwidthEstimation::UpdateMinHistory(Timestamp at_time) {
609 // Remove old data points from history.
610 // Since history precision is in ms, add one so it is able to increase
611 // bitrate if it is off by as little as 0.5ms.
612 while (!min_bitrate_history_.empty() &&
613 at_time - min_bitrate_history_.front().first + TimeDelta::Millis(1) >
614 kBweIncreaseInterval) {
615 min_bitrate_history_.pop_front();
616 }
617
618 // Typical minimum sliding-window algorithm: Pop values higher than current
619 // bitrate before pushing it.
620 while (!min_bitrate_history_.empty() &&
621 current_target_ <= min_bitrate_history_.back().second) {
622 min_bitrate_history_.pop_back();
623 }
624
625 min_bitrate_history_.push_back(std::make_pair(at_time, current_target_));
626 }
627
GetUpperLimit() const628 DataRate SendSideBandwidthEstimation::GetUpperLimit() const {
629 DataRate upper_limit = delay_based_limit_;
630 if (disable_receiver_limit_caps_only_)
631 upper_limit = std::min(upper_limit, receiver_limit_);
632 return std::min(upper_limit, max_bitrate_configured_);
633 }
634
MaybeLogLowBitrateWarning(DataRate bitrate,Timestamp at_time)635 void SendSideBandwidthEstimation::MaybeLogLowBitrateWarning(DataRate bitrate,
636 Timestamp at_time) {
637 if (at_time - last_low_bitrate_log_ > kLowBitrateLogPeriod) {
638 RTC_LOG(LS_WARNING) << "Estimated available bandwidth " << ToString(bitrate)
639 << " is below configured min bitrate "
640 << ToString(min_bitrate_configured_) << ".";
641 last_low_bitrate_log_ = at_time;
642 }
643 }
644
MaybeLogLossBasedEvent(Timestamp at_time)645 void SendSideBandwidthEstimation::MaybeLogLossBasedEvent(Timestamp at_time) {
646 if (current_target_ != last_logged_target_ ||
647 last_fraction_loss_ != last_logged_fraction_loss_ ||
648 at_time - last_rtc_event_log_ > kRtcEventLogPeriod) {
649 event_log_->Log(std::make_unique<RtcEventBweUpdateLossBased>(
650 current_target_.bps(), last_fraction_loss_,
651 expected_packets_since_last_loss_update_));
652 last_logged_fraction_loss_ = last_fraction_loss_;
653 last_logged_target_ = current_target_;
654 last_rtc_event_log_ = at_time;
655 }
656 }
657
UpdateTargetBitrate(DataRate new_bitrate,Timestamp at_time)658 void SendSideBandwidthEstimation::UpdateTargetBitrate(DataRate new_bitrate,
659 Timestamp at_time) {
660 new_bitrate = std::min(new_bitrate, GetUpperLimit());
661 if (new_bitrate < min_bitrate_configured_) {
662 MaybeLogLowBitrateWarning(new_bitrate, at_time);
663 new_bitrate = min_bitrate_configured_;
664 }
665 current_target_ = new_bitrate;
666 MaybeLogLossBasedEvent(at_time);
667 link_capacity_.OnRateUpdate(acknowledged_rate_, current_target_, at_time);
668 }
669
ApplyTargetLimits(Timestamp at_time)670 void SendSideBandwidthEstimation::ApplyTargetLimits(Timestamp at_time) {
671 UpdateTargetBitrate(current_target_, at_time);
672 }
673
LossBasedBandwidthEstimatorV1Enabled() const674 bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV1Enabled() const {
675 return loss_based_bandwidth_estimator_v1_.Enabled() &&
676 !LossBasedBandwidthEstimatorV2Enabled();
677 }
678
LossBasedBandwidthEstimatorV1ReadyForUse() const679 bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV1ReadyForUse()
680 const {
681 return LossBasedBandwidthEstimatorV1Enabled() &&
682 loss_based_bandwidth_estimator_v1_.InUse();
683 }
684
LossBasedBandwidthEstimatorV2Enabled() const685 bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2Enabled() const {
686 return loss_based_bandwidth_estimator_v2_.IsEnabled();
687 }
688
LossBasedBandwidthEstimatorV2ReadyForUse() const689 bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2ReadyForUse()
690 const {
691 return LossBasedBandwidthEstimatorV2Enabled() &&
692 loss_based_bandwidth_estimator_v2_.IsReady();
693 }
694
695 } // namespace webrtc
696