blob: 48eea3cd73ff688a816807dace968ddfd1f872ec [file] [log] [blame]
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/bitrate_controller/send_side_bandwidth_estimation.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000012
jbauchf91e6d02016-01-24 23:05:21 -080013#include <algorithm>
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000014#include <cmath>
Piotr Tworek5e4833c2017-12-12 12:09:31 +010015#include <cstdio>
Stefan Holmer9c79ed92017-03-31 15:53:27 +020016#include <limits>
17#include <string>
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000018
Karl Wiberg918f50c2018-07-05 11:40:33 +020019#include "absl/memory/memory.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020020#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "logging/rtc_event_log/rtc_event_log.h"
22#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/logging.h"
25#include "system_wrappers/include/field_trial.h"
26#include "system_wrappers/include/metrics.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000027
28namespace webrtc {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000029namespace {
Stefan Holmere5904162015-03-26 11:11:06 +010030const int64_t kBweIncreaseIntervalMs = 1000;
31const int64_t kBweDecreaseIntervalMs = 300;
32const int64_t kStartPhaseMs = 2000;
33const int64_t kBweConverganceTimeMs = 20000;
34const int kLimitNumPackets = 20;
Stefan Holmere5904162015-03-26 11:11:06 +010035const int kDefaultMaxBitrateBps = 1000000000;
stefanb6b0b922015-09-04 03:04:56 -070036const int64_t kLowBitrateLogPeriodMs = 10000;
stefan3821ff82016-09-04 05:07:26 -070037const int64_t kRtcEventLogPeriodMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020038// Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
stefan5cb19822017-06-16 07:47:00 -070039const int64_t kFeedbackIntervalMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020040const int64_t kFeedbackTimeoutIntervals = 3;
41const int64_t kTimeoutIntervalMs = 1000;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000042
Stefan Holmer9c79ed92017-03-31 15:53:27 +020043const float kDefaultLowLossThreshold = 0.02f;
44const float kDefaultHighLossThreshold = 0.1f;
45const int kDefaultBitrateThresholdKbps = 0;
46
stefan@webrtc.org474e36e2015-01-19 15:44:47 +000047struct UmaRampUpMetric {
48 const char* metric_name;
49 int bitrate_kbps;
50};
51
52const UmaRampUpMetric kUmaRampupMetrics[] = {
53 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
54 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
55 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
56const size_t kNumUmaRampupMetrics =
57 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
58
Stefan Holmer9c79ed92017-03-31 15:53:27 +020059const char kBweLosExperiment[] = "WebRTC-BweLossExperiment";
60
61bool BweLossExperimentIsEnabled() {
62 std::string experiment_string =
63 webrtc::field_trial::FindFullName(kBweLosExperiment);
64 // The experiment is enabled iff the field trial string begins with "Enabled".
65 return experiment_string.find("Enabled") == 0;
66}
67
68bool ReadBweLossExperimentParameters(float* low_loss_threshold,
69 float* high_loss_threshold,
70 uint32_t* bitrate_threshold_kbps) {
71 RTC_DCHECK(low_loss_threshold);
72 RTC_DCHECK(high_loss_threshold);
73 RTC_DCHECK(bitrate_threshold_kbps);
74 std::string experiment_string =
75 webrtc::field_trial::FindFullName(kBweLosExperiment);
76 int parsed_values =
77 sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold,
78 high_loss_threshold, bitrate_threshold_kbps);
79 if (parsed_values == 3) {
80 RTC_CHECK_GT(*low_loss_threshold, 0.0f)
81 << "Loss threshold must be greater than 0.";
82 RTC_CHECK_LE(*low_loss_threshold, 1.0f)
83 << "Loss threshold must be less than or equal to 1.";
84 RTC_CHECK_GT(*high_loss_threshold, 0.0f)
85 << "Loss threshold must be greater than 0.";
86 RTC_CHECK_LE(*high_loss_threshold, 1.0f)
87 << "Loss threshold must be less than or equal to 1.";
88 RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold)
89 << "The low loss threshold must be less than or equal to the high loss "
90 "threshold.";
91 RTC_CHECK_GE(*bitrate_threshold_kbps, 0)
92 << "Bitrate threshold can't be negative.";
93 RTC_CHECK_LT(*bitrate_threshold_kbps,
94 std::numeric_limits<int>::max() / 1000)
95 << "Bitrate must be smaller enough to avoid overflows.";
96 return true;
97 }
Mirko Bonadei675513b2017-11-09 11:09:25 +010098 RTC_LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment "
99 "experiment from field trial string. Using default.";
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200100 *low_loss_threshold = kDefaultLowLossThreshold;
101 *high_loss_threshold = kDefaultHighLossThreshold;
102 *bitrate_threshold_kbps = kDefaultBitrateThresholdKbps;
103 return false;
104}
jbauchf91e6d02016-01-24 23:05:21 -0800105} // namespace
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000106
ivoc14d5dbe2016-07-04 07:06:55 -0700107SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100108 : lost_packets_since_last_loss_update_(0),
pbosb7edb882015-10-22 08:52:20 -0700109 expected_packets_since_last_loss_update_(0),
philipel1b965312017-04-18 06:55:32 -0700110 current_bitrate_bps_(0),
michaeltf082c2a2016-11-07 04:17:14 -0800111 min_bitrate_configured_(congestion_controller::GetMinBitrateBps()),
Stefan Holmere5904162015-03-26 11:11:06 +0100112 max_bitrate_configured_(kDefaultMaxBitrateBps),
stefanb6b0b922015-09-04 03:04:56 -0700113 last_low_bitrate_log_ms_(-1),
pbosb7edb882015-10-22 08:52:20 -0700114 has_decreased_since_last_fraction_loss_(false),
Stefan Holmer52200d02016-09-20 14:14:23 +0200115 last_feedback_ms_(-1),
116 last_packet_report_ms_(-1),
117 last_timeout_ms_(-1),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000118 last_fraction_loss_(0),
stefan3821ff82016-09-04 05:07:26 -0700119 last_logged_fraction_loss_(0),
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000120 last_round_trip_time_ms_(0),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000121 bwe_incoming_(0),
stefan32f81542016-01-20 07:13:58 -0800122 delay_based_bitrate_bps_(0),
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000123 time_last_decrease_ms_(0),
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000124 first_report_time_ms_(-1),
125 initially_lost_packets_(0),
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000126 bitrate_at_2_seconds_kbps_(0),
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000127 uma_update_state_(kNoUpdate),
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100128 uma_rtt_state_(kNoUpdate),
terelius006d93d2015-11-05 12:02:15 -0800129 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
stefan3821ff82016-09-04 05:07:26 -0700130 event_log_(event_log),
Stefan Holmer52200d02016-09-20 14:14:23 +0200131 last_rtc_event_log_ms_(-1),
sprangc1b57a12017-02-28 08:50:47 -0800132 in_timeout_experiment_(
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200133 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
134 low_loss_threshold_(kDefaultLowLossThreshold),
135 high_loss_threshold_(kDefaultHighLossThreshold),
136 bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) {
ivoc14d5dbe2016-07-04 07:06:55 -0700137 RTC_DCHECK(event_log);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200138 if (BweLossExperimentIsEnabled()) {
139 uint32_t bitrate_threshold_kbps;
140 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
141 &high_loss_threshold_,
142 &bitrate_threshold_kbps)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100143 RTC_LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
144 << low_loss_threshold_ << ", " << high_loss_threshold_
145 << ", " << bitrate_threshold_kbps;
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200146 bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000;
147 }
148 }
ivoc14d5dbe2016-07-04 07:06:55 -0700149}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000150
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000151SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000152
philipelc6957c72016-04-28 15:52:49 +0200153void SendSideBandwidthEstimation::SetBitrates(int send_bitrate,
154 int min_bitrate,
155 int max_bitrate) {
philipel1b965312017-04-18 06:55:32 -0700156 SetMinMaxBitrate(min_bitrate, max_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200157 if (send_bitrate > 0)
158 SetSendBitrate(send_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200159}
160
Stefan Holmere5904162015-03-26 11:11:06 +0100161void SendSideBandwidthEstimation::SetSendBitrate(int bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700162 RTC_DCHECK_GT(bitrate, 0);
Bjorn Terelius29cb0e72017-11-08 14:41:12 +0100163 delay_based_bitrate_bps_ = 0; // Reset to avoid being capped by the estimate.
philipel1b965312017-04-18 06:55:32 -0700164 CapBitrateToThresholds(Clock::GetRealTimeClock()->TimeInMilliseconds(),
165 bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000166 // Clear last sent bitrate history so the new value can be used directly
167 // and not capped.
168 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000169}
170
Stefan Holmere5904162015-03-26 11:11:06 +0100171void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
172 int max_bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700173 RTC_DCHECK_GE(min_bitrate, 0);
michaeltf082c2a2016-11-07 04:17:14 -0800174 min_bitrate_configured_ =
175 std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
Stefan Holmere5904162015-03-26 11:11:06 +0100176 if (max_bitrate > 0) {
177 max_bitrate_configured_ =
178 std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
179 } else {
180 max_bitrate_configured_ = kDefaultMaxBitrateBps;
181 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000182}
183
Stefan Holmere5904162015-03-26 11:11:06 +0100184int SendSideBandwidthEstimation::GetMinBitrate() const {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000185 return min_bitrate_configured_;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000186}
187
Stefan Holmere5904162015-03-26 11:11:06 +0100188void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000189 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000190 int64_t* rtt) const {
philipel1b965312017-04-18 06:55:32 -0700191 *bitrate = current_bitrate_bps_;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000192 *loss = last_fraction_loss_;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000193 *rtt = last_round_trip_time_ms_;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000194}
195
Yves Gerey665174f2018-06-19 15:03:05 +0200196void SendSideBandwidthEstimation::UpdateReceiverEstimate(int64_t now_ms,
197 uint32_t bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000198 bwe_incoming_ = bandwidth;
philipel1b965312017-04-18 06:55:32 -0700199 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000200}
201
stefan32f81542016-01-20 07:13:58 -0800202void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
203 int64_t now_ms,
204 uint32_t bitrate_bps) {
205 delay_based_bitrate_bps_ = bitrate_bps;
philipel1b965312017-04-18 06:55:32 -0700206 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
stefan32f81542016-01-20 07:13:58 -0800207}
208
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000209void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100210 int64_t rtt_ms,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000211 int number_of_packets,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000212 int64_t now_ms) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100213 const int kRoundingConstant = 128;
214 int packets_lost = (static_cast<int>(fraction_loss) * number_of_packets +
215 kRoundingConstant) >>
216 8;
217 UpdatePacketsLost(packets_lost, number_of_packets, now_ms);
218 UpdateRtt(rtt_ms, now_ms);
219}
220
221void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost,
222 int number_of_packets,
223 int64_t now_ms) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200224 last_feedback_ms_ = now_ms;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000225 if (first_report_time_ms_ == -1)
226 first_report_time_ms_ = now_ms;
227
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000228 // Check sequence number diff and weight loss report
229 if (number_of_packets > 0) {
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000230 // Accumulate reports.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100231 lost_packets_since_last_loss_update_ += packets_lost;
pbosb7edb882015-10-22 08:52:20 -0700232 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000233
pbosb7edb882015-10-22 08:52:20 -0700234 // Don't generate a loss rate until it can be based on enough packets.
235 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000236 return;
pbosb7edb882015-10-22 08:52:20 -0700237
238 has_decreased_since_last_fraction_loss_ = false;
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100239 int64_t lost_q8 = lost_packets_since_last_loss_update_ << 8;
240 int64_t expected = expected_packets_since_last_loss_update_;
241 last_fraction_loss_ = std::min<int>(lost_q8 / expected, 255);
pbosb7edb882015-10-22 08:52:20 -0700242
243 // Reset accumulators.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100244
245 lost_packets_since_last_loss_update_ = 0;
pbosb7edb882015-10-22 08:52:20 -0700246 expected_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200247 last_packet_report_ms_ = now_ms;
248 UpdateEstimate(now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000249 }
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100250 UpdateUmaStatsPacketsLost(now_ms, packets_lost);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000251}
252
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100253void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(int64_t now_ms,
254 int packets_lost) {
philipel1b965312017-04-18 06:55:32 -0700255 int bitrate_kbps = static_cast<int>((current_bitrate_bps_ + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000256 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
257 if (!rampup_uma_stats_updated_[i] &&
258 bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700259 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
260 now_ms - first_report_time_ms_);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000261 rampup_uma_stats_updated_[i] = true;
262 }
263 }
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000264 if (IsInStartPhase(now_ms)) {
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100265 initially_lost_packets_ += packets_lost;
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000266 } else if (uma_update_state_ == kNoUpdate) {
267 uma_update_state_ = kFirstDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000268 bitrate_at_2_seconds_kbps_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700269 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
270 initially_lost_packets_, 0, 100, 50);
asapersson1d02d3e2016-09-09 22:40:25 -0700271 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
272 bitrate_at_2_seconds_kbps_, 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000273 } else if (uma_update_state_ == kFirstDone &&
274 now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
275 uma_update_state_ = kDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000276 int bitrate_diff_kbps =
277 std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700278 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
279 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000280 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000281}
282
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100283void SendSideBandwidthEstimation::UpdateRtt(int64_t rtt_ms, int64_t now_ms) {
284 // Update RTT if we were able to compute an RTT based on this RTCP.
285 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
286 if (rtt_ms > 0)
287 last_round_trip_time_ms_ = rtt_ms;
288
289 if (!IsInStartPhase(now_ms) && uma_rtt_state_ == kNoUpdate) {
290 uma_rtt_state_ = kDone;
291 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt_ms), 0,
292 2000, 50);
293 }
294}
295
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000296void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
philipel1b965312017-04-18 06:55:32 -0700297 uint32_t new_bitrate = current_bitrate_bps_;
stefanfa156692016-01-21 08:55:03 -0800298 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
299 // we haven't had any packet loss reported, to allow startup bitrate probing.
300 if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
philipel1b965312017-04-18 06:55:32 -0700301 new_bitrate = std::max(bwe_incoming_, new_bitrate);
302 new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
303
304 if (new_bitrate != current_bitrate_bps_) {
stefanfa156692016-01-21 08:55:03 -0800305 min_bitrate_history_.clear();
philipel1b965312017-04-18 06:55:32 -0700306 min_bitrate_history_.push_back(
307 std::make_pair(now_ms, current_bitrate_bps_));
308 CapBitrateToThresholds(now_ms, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800309 return;
310 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000311 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000312 UpdateMinHistory(now_ms);
Stefan Holmer52200d02016-09-20 14:14:23 +0200313 if (last_packet_report_ms_ == -1) {
314 // No feedback received.
philipel1b965312017-04-18 06:55:32 -0700315 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200316 return;
317 }
318 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
319 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
320 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200321 // We only care about loss above a given bitrate threshold.
322 float loss = last_fraction_loss_ / 256.0f;
323 // We only make decisions based on loss when the bitrate is above a
324 // threshold. This is a crude way of handling loss which is uncorrelated
325 // to congestion.
philipel1b965312017-04-18 06:55:32 -0700326 if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
327 loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000328 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
329 // kBweIncreaseIntervalMs.
330 // Note that by remembering the bitrate over the last second one can
331 // rampup up one second faster than if only allowed to start ramping
332 // at 8% per second rate now. E.g.:
333 // If sending a constant 100kbps it can rampup immediatly to 108kbps
334 // whenever a receiver report is received with lower packet loss.
philipel1b965312017-04-18 06:55:32 -0700335 // If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
336 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200337 // 108kbps.
philipel1b965312017-04-18 06:55:32 -0700338 new_bitrate = static_cast<uint32_t>(
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000339 min_bitrate_history_.front().second * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000340
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000341 // Add 1 kbps extra, just to make sure that we do not get stuck
342 // (gives a little extra increase at low rates, negligible at higher
343 // rates).
philipel1b965312017-04-18 06:55:32 -0700344 new_bitrate += 1000;
345 } else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200346 if (loss <= high_loss_threshold_) {
347 // Loss between 2% - 10%: Do nothing.
348 } else {
349 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
350 // + rtt.
351 if (!has_decreased_since_last_fraction_loss_ &&
352 (now_ms - time_last_decrease_ms_) >=
353 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
354 time_last_decrease_ms_ = now_ms;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000355
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200356 // Reduce rate:
357 // newRate = rate * (1 - 0.5*lossRate);
358 // where packetLoss = 256*lossRate;
philipel1b965312017-04-18 06:55:32 -0700359 new_bitrate = static_cast<uint32_t>(
360 (current_bitrate_bps_ *
361 static_cast<double>(512 - last_fraction_loss_)) /
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200362 512.0);
363 has_decreased_since_last_fraction_loss_ = true;
364 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000365 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000366 }
Stefan Holmer52200d02016-09-20 14:14:23 +0200367 } else if (time_since_feedback_ms >
368 kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
369 (last_timeout_ms_ == -1 ||
370 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
371 if (in_timeout_experiment_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100372 RTC_LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
373 << " ms), reducing bitrate.";
philipel1b965312017-04-18 06:55:32 -0700374 new_bitrate *= 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200375 // Reset accumulators since we've already acted on missing feedback and
376 // shouldn't to act again on these old lost packets.
Sebastian Jansson439f0bc2018-02-20 10:46:39 +0100377 lost_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200378 expected_packets_since_last_loss_update_ = 0;
379 last_timeout_ms_ = now_ms;
380 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000381 }
philipel1b965312017-04-18 06:55:32 -0700382
383 CapBitrateToThresholds(now_ms, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000384}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000385
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000386bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
387 return first_report_time_ms_ == -1 ||
388 now_ms - first_report_time_ms_ < kStartPhaseMs;
389}
390
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000391void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000392 // Remove old data points from history.
393 // Since history precision is in ms, add one so it is able to increase
394 // bitrate if it is off by as little as 0.5ms.
395 while (!min_bitrate_history_.empty() &&
396 now_ms - min_bitrate_history_.front().first + 1 >
397 kBweIncreaseIntervalMs) {
398 min_bitrate_history_.pop_front();
399 }
400
401 // Typical minimum sliding-window algorithm: Pop values higher than current
402 // bitrate before pushing it.
403 while (!min_bitrate_history_.empty() &&
philipel1b965312017-04-18 06:55:32 -0700404 current_bitrate_bps_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000405 min_bitrate_history_.pop_back();
406 }
407
philipel1b965312017-04-18 06:55:32 -0700408 min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000409}
410
philipel1b965312017-04-18 06:55:32 -0700411void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,
412 uint32_t bitrate_bps) {
413 if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {
414 bitrate_bps = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000415 }
philipel1b965312017-04-18 06:55:32 -0700416 if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {
417 bitrate_bps = delay_based_bitrate_bps_;
stefan32f81542016-01-20 07:13:58 -0800418 }
philipel1b965312017-04-18 06:55:32 -0700419 if (bitrate_bps > max_bitrate_configured_) {
420 bitrate_bps = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000421 }
philipel1b965312017-04-18 06:55:32 -0700422 if (bitrate_bps < min_bitrate_configured_) {
stefanb6b0b922015-09-04 03:04:56 -0700423 if (last_low_bitrate_log_ms_ == -1 ||
424 now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100425 RTC_LOG(LS_WARNING) << "Estimated available bandwidth "
426 << bitrate_bps / 1000
427 << " kbps is below configured min bitrate "
428 << min_bitrate_configured_ / 1000 << " kbps.";
stefanb6b0b922015-09-04 03:04:56 -0700429 last_low_bitrate_log_ms_ = now_ms;
430 }
philipel1b965312017-04-18 06:55:32 -0700431 bitrate_bps = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000432 }
philipel1b965312017-04-18 06:55:32 -0700433
434 if (bitrate_bps != current_bitrate_bps_ ||
435 last_fraction_loss_ != last_logged_fraction_loss_ ||
436 now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200437 event_log_->Log(absl::make_unique<RtcEventBweUpdateLossBased>(
Elad Alon4a87e1c2017-10-03 16:11:34 +0200438 bitrate_bps, last_fraction_loss_,
439 expected_packets_since_last_loss_update_));
philipel1b965312017-04-18 06:55:32 -0700440 last_logged_fraction_loss_ = last_fraction_loss_;
441 last_rtc_event_log_ms_ = now_ms;
442 }
443 current_bitrate_bps_ = bitrate_bps;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000444}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000445} // namespace webrtc