• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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