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