blob: 9e9118b8eeaf236a134799c408d2bddb1eb7d130 [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>
Stefan Holmer9c79ed92017-03-31 15:53:27 +020015#include <limits>
16#include <string>
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000017
Elad Alon4a87e1c2017-10-03 16:11:34 +020018#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "logging/rtc_event_log/rtc_event_log.h"
20#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020023#include "rtc_base/ptr_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "system_wrappers/include/field_trial.h"
25#include "system_wrappers/include/metrics.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000026
27namespace webrtc {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000028namespace {
Stefan Holmere5904162015-03-26 11:11:06 +010029const int64_t kBweIncreaseIntervalMs = 1000;
30const int64_t kBweDecreaseIntervalMs = 300;
31const int64_t kStartPhaseMs = 2000;
32const int64_t kBweConverganceTimeMs = 20000;
33const int kLimitNumPackets = 20;
Stefan Holmere5904162015-03-26 11:11:06 +010034const int kDefaultMaxBitrateBps = 1000000000;
stefanb6b0b922015-09-04 03:04:56 -070035const int64_t kLowBitrateLogPeriodMs = 10000;
stefan3821ff82016-09-04 05:07:26 -070036const int64_t kRtcEventLogPeriodMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020037// Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
stefan5cb19822017-06-16 07:47:00 -070038const int64_t kFeedbackIntervalMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020039const int64_t kFeedbackTimeoutIntervals = 3;
40const int64_t kTimeoutIntervalMs = 1000;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000041
Stefan Holmer9c79ed92017-03-31 15:53:27 +020042const float kDefaultLowLossThreshold = 0.02f;
43const float kDefaultHighLossThreshold = 0.1f;
44const int kDefaultBitrateThresholdKbps = 0;
45
stefan@webrtc.org474e36e2015-01-19 15:44:47 +000046struct UmaRampUpMetric {
47 const char* metric_name;
48 int bitrate_kbps;
49};
50
51const UmaRampUpMetric kUmaRampupMetrics[] = {
52 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
53 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
54 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
55const size_t kNumUmaRampupMetrics =
56 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
57
Stefan Holmer9c79ed92017-03-31 15:53:27 +020058const char kBweLosExperiment[] = "WebRTC-BweLossExperiment";
59
60bool 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 experiment_string.find("Enabled") == 0;
65}
66
67bool 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 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 = kDefaultBitrateThresholdKbps;
102 return false;
103}
jbauchf91e6d02016-01-24 23:05:21 -0800104} // namespace
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000105
ivoc14d5dbe2016-07-04 07:06:55 -0700106SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
pbosb7edb882015-10-22 08:52:20 -0700107 : lost_packets_since_last_loss_update_Q8_(0),
108 expected_packets_since_last_loss_update_(0),
philipel1b965312017-04-18 06:55:32 -0700109 current_bitrate_bps_(0),
michaeltf082c2a2016-11-07 04:17:14 -0800110 min_bitrate_configured_(congestion_controller::GetMinBitrateBps()),
Stefan Holmere5904162015-03-26 11:11:06 +0100111 max_bitrate_configured_(kDefaultMaxBitrateBps),
stefanb6b0b922015-09-04 03:04:56 -0700112 last_low_bitrate_log_ms_(-1),
pbosb7edb882015-10-22 08:52:20 -0700113 has_decreased_since_last_fraction_loss_(false),
Stefan Holmer52200d02016-09-20 14:14:23 +0200114 last_feedback_ms_(-1),
115 last_packet_report_ms_(-1),
116 last_timeout_ms_(-1),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000117 last_fraction_loss_(0),
stefan3821ff82016-09-04 05:07:26 -0700118 last_logged_fraction_loss_(0),
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000119 last_round_trip_time_ms_(0),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000120 bwe_incoming_(0),
stefan32f81542016-01-20 07:13:58 -0800121 delay_based_bitrate_bps_(0),
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000122 time_last_decrease_ms_(0),
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000123 first_report_time_ms_(-1),
124 initially_lost_packets_(0),
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000125 bitrate_at_2_seconds_kbps_(0),
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000126 uma_update_state_(kNoUpdate),
terelius006d93d2015-11-05 12:02:15 -0800127 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
stefan3821ff82016-09-04 05:07:26 -0700128 event_log_(event_log),
Stefan Holmer52200d02016-09-20 14:14:23 +0200129 last_rtc_event_log_ms_(-1),
sprangc1b57a12017-02-28 08:50:47 -0800130 in_timeout_experiment_(
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200131 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
132 low_loss_threshold_(kDefaultLowLossThreshold),
133 high_loss_threshold_(kDefaultHighLossThreshold),
134 bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) {
ivoc14d5dbe2016-07-04 07:06:55 -0700135 RTC_DCHECK(event_log);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200136 if (BweLossExperimentIsEnabled()) {
137 uint32_t bitrate_threshold_kbps;
138 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
139 &high_loss_threshold_,
140 &bitrate_threshold_kbps)) {
141 LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
142 << low_loss_threshold_ << ", " << high_loss_threshold_
143 << ", " << bitrate_threshold_kbps;
144 bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000;
145 }
146 }
ivoc14d5dbe2016-07-04 07:06:55 -0700147}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000148
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000149SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000150
philipelc6957c72016-04-28 15:52:49 +0200151void SendSideBandwidthEstimation::SetBitrates(int send_bitrate,
152 int min_bitrate,
153 int max_bitrate) {
philipel1b965312017-04-18 06:55:32 -0700154 SetMinMaxBitrate(min_bitrate, max_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200155 if (send_bitrate > 0)
156 SetSendBitrate(send_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200157}
158
Stefan Holmere5904162015-03-26 11:11:06 +0100159void SendSideBandwidthEstimation::SetSendBitrate(int bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700160 RTC_DCHECK_GT(bitrate, 0);
Bjorn Terelius29cb0e72017-11-08 14:41:12 +0100161 delay_based_bitrate_bps_ = 0; // Reset to avoid being capped by the estimate.
philipel1b965312017-04-18 06:55:32 -0700162 CapBitrateToThresholds(Clock::GetRealTimeClock()->TimeInMilliseconds(),
163 bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000164 // Clear last sent bitrate history so the new value can be used directly
165 // and not capped.
166 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000167}
168
Stefan Holmere5904162015-03-26 11:11:06 +0100169void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
170 int max_bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700171 RTC_DCHECK_GE(min_bitrate, 0);
michaeltf082c2a2016-11-07 04:17:14 -0800172 min_bitrate_configured_ =
173 std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
Stefan Holmere5904162015-03-26 11:11:06 +0100174 if (max_bitrate > 0) {
175 max_bitrate_configured_ =
176 std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
177 } else {
178 max_bitrate_configured_ = kDefaultMaxBitrateBps;
179 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000180}
181
Stefan Holmere5904162015-03-26 11:11:06 +0100182int SendSideBandwidthEstimation::GetMinBitrate() const {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000183 return min_bitrate_configured_;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000184}
185
Stefan Holmere5904162015-03-26 11:11:06 +0100186void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000187 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000188 int64_t* rtt) const {
philipel1b965312017-04-18 06:55:32 -0700189 *bitrate = current_bitrate_bps_;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000190 *loss = last_fraction_loss_;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000191 *rtt = last_round_trip_time_ms_;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000192}
193
stefanb6b0b922015-09-04 03:04:56 -0700194void SendSideBandwidthEstimation::UpdateReceiverEstimate(
195 int64_t now_ms, uint32_t bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000196 bwe_incoming_ = bandwidth;
philipel1b965312017-04-18 06:55:32 -0700197 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000198}
199
stefan32f81542016-01-20 07:13:58 -0800200void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
201 int64_t now_ms,
202 uint32_t bitrate_bps) {
203 delay_based_bitrate_bps_ = bitrate_bps;
philipel1b965312017-04-18 06:55:32 -0700204 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
stefan32f81542016-01-20 07:13:58 -0800205}
206
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000207void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000208 int64_t rtt,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000209 int number_of_packets,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000210 int64_t now_ms) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200211 last_feedback_ms_ = now_ms;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000212 if (first_report_time_ms_ == -1)
213 first_report_time_ms_ = now_ms;
214
stefan889d9652017-07-05 03:03:02 -0700215 // Update RTT if we were able to compute an RTT based on this RTCP.
216 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
217 if (rtt > 0)
218 last_round_trip_time_ms_ = rtt;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000219
220 // Check sequence number diff and weight loss report
221 if (number_of_packets > 0) {
222 // Calculate number of lost packets.
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000223 const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000224 // Accumulate reports.
pbosb7edb882015-10-22 08:52:20 -0700225 lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
226 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000227
pbosb7edb882015-10-22 08:52:20 -0700228 // Don't generate a loss rate until it can be based on enough packets.
229 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000230 return;
pbosb7edb882015-10-22 08:52:20 -0700231
232 has_decreased_since_last_fraction_loss_ = false;
233 last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ /
234 expected_packets_since_last_loss_update_;
235
236 // Reset accumulators.
237 lost_packets_since_last_loss_update_Q8_ = 0;
238 expected_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200239 last_packet_report_ms_ = now_ms;
240 UpdateEstimate(now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000241 }
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000242 UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000243}
244
245void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000246 int64_t rtt,
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000247 int lost_packets) {
philipel1b965312017-04-18 06:55:32 -0700248 int bitrate_kbps = static_cast<int>((current_bitrate_bps_ + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000249 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
250 if (!rampup_uma_stats_updated_[i] &&
251 bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700252 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
253 now_ms - first_report_time_ms_);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000254 rampup_uma_stats_updated_[i] = true;
255 }
256 }
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000257 if (IsInStartPhase(now_ms)) {
258 initially_lost_packets_ += lost_packets;
259 } else if (uma_update_state_ == kNoUpdate) {
260 uma_update_state_ = kFirstDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000261 bitrate_at_2_seconds_kbps_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700262 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
263 initially_lost_packets_, 0, 100, 50);
264 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt), 0,
265 2000, 50);
266 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
267 bitrate_at_2_seconds_kbps_, 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000268 } else if (uma_update_state_ == kFirstDone &&
269 now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
270 uma_update_state_ = kDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000271 int bitrate_diff_kbps =
272 std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700273 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
274 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000275 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000276}
277
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000278void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
philipel1b965312017-04-18 06:55:32 -0700279 uint32_t new_bitrate = current_bitrate_bps_;
stefanfa156692016-01-21 08:55:03 -0800280 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
281 // we haven't had any packet loss reported, to allow startup bitrate probing.
282 if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
philipel1b965312017-04-18 06:55:32 -0700283 new_bitrate = std::max(bwe_incoming_, new_bitrate);
284 new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
285
286 if (new_bitrate != current_bitrate_bps_) {
stefanfa156692016-01-21 08:55:03 -0800287 min_bitrate_history_.clear();
philipel1b965312017-04-18 06:55:32 -0700288 min_bitrate_history_.push_back(
289 std::make_pair(now_ms, current_bitrate_bps_));
290 CapBitrateToThresholds(now_ms, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800291 return;
292 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000293 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000294 UpdateMinHistory(now_ms);
Stefan Holmer52200d02016-09-20 14:14:23 +0200295 if (last_packet_report_ms_ == -1) {
296 // No feedback received.
philipel1b965312017-04-18 06:55:32 -0700297 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200298 return;
299 }
300 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
301 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
302 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200303 // We only care about loss above a given bitrate threshold.
304 float loss = last_fraction_loss_ / 256.0f;
305 // We only make decisions based on loss when the bitrate is above a
306 // threshold. This is a crude way of handling loss which is uncorrelated
307 // to congestion.
philipel1b965312017-04-18 06:55:32 -0700308 if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
309 loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000310 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
311 // kBweIncreaseIntervalMs.
312 // Note that by remembering the bitrate over the last second one can
313 // rampup up one second faster than if only allowed to start ramping
314 // at 8% per second rate now. E.g.:
315 // If sending a constant 100kbps it can rampup immediatly to 108kbps
316 // whenever a receiver report is received with lower packet loss.
philipel1b965312017-04-18 06:55:32 -0700317 // If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
318 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200319 // 108kbps.
philipel1b965312017-04-18 06:55:32 -0700320 new_bitrate = static_cast<uint32_t>(
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000321 min_bitrate_history_.front().second * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000322
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000323 // Add 1 kbps extra, just to make sure that we do not get stuck
324 // (gives a little extra increase at low rates, negligible at higher
325 // rates).
philipel1b965312017-04-18 06:55:32 -0700326 new_bitrate += 1000;
327 } else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200328 if (loss <= high_loss_threshold_) {
329 // Loss between 2% - 10%: Do nothing.
330 } else {
331 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
332 // + rtt.
333 if (!has_decreased_since_last_fraction_loss_ &&
334 (now_ms - time_last_decrease_ms_) >=
335 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
336 time_last_decrease_ms_ = now_ms;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000337
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200338 // Reduce rate:
339 // newRate = rate * (1 - 0.5*lossRate);
340 // where packetLoss = 256*lossRate;
philipel1b965312017-04-18 06:55:32 -0700341 new_bitrate = static_cast<uint32_t>(
342 (current_bitrate_bps_ *
343 static_cast<double>(512 - last_fraction_loss_)) /
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200344 512.0);
345 has_decreased_since_last_fraction_loss_ = true;
346 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000347 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000348 }
Stefan Holmer52200d02016-09-20 14:14:23 +0200349 } else if (time_since_feedback_ms >
350 kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
351 (last_timeout_ms_ == -1 ||
352 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
353 if (in_timeout_experiment_) {
354 LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
355 << " ms), reducing bitrate.";
philipel1b965312017-04-18 06:55:32 -0700356 new_bitrate *= 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200357 // Reset accumulators since we've already acted on missing feedback and
358 // shouldn't to act again on these old lost packets.
359 lost_packets_since_last_loss_update_Q8_ = 0;
360 expected_packets_since_last_loss_update_ = 0;
361 last_timeout_ms_ = now_ms;
362 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000363 }
philipel1b965312017-04-18 06:55:32 -0700364
365 CapBitrateToThresholds(now_ms, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000366}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000367
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000368bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
369 return first_report_time_ms_ == -1 ||
370 now_ms - first_report_time_ms_ < kStartPhaseMs;
371}
372
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000373void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000374 // Remove old data points from history.
375 // Since history precision is in ms, add one so it is able to increase
376 // bitrate if it is off by as little as 0.5ms.
377 while (!min_bitrate_history_.empty() &&
378 now_ms - min_bitrate_history_.front().first + 1 >
379 kBweIncreaseIntervalMs) {
380 min_bitrate_history_.pop_front();
381 }
382
383 // Typical minimum sliding-window algorithm: Pop values higher than current
384 // bitrate before pushing it.
385 while (!min_bitrate_history_.empty() &&
philipel1b965312017-04-18 06:55:32 -0700386 current_bitrate_bps_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000387 min_bitrate_history_.pop_back();
388 }
389
philipel1b965312017-04-18 06:55:32 -0700390 min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000391}
392
philipel1b965312017-04-18 06:55:32 -0700393void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,
394 uint32_t bitrate_bps) {
395 if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {
396 bitrate_bps = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000397 }
philipel1b965312017-04-18 06:55:32 -0700398 if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {
399 bitrate_bps = delay_based_bitrate_bps_;
stefan32f81542016-01-20 07:13:58 -0800400 }
philipel1b965312017-04-18 06:55:32 -0700401 if (bitrate_bps > max_bitrate_configured_) {
402 bitrate_bps = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000403 }
philipel1b965312017-04-18 06:55:32 -0700404 if (bitrate_bps < min_bitrate_configured_) {
stefanb6b0b922015-09-04 03:04:56 -0700405 if (last_low_bitrate_log_ms_ == -1 ||
406 now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
philipel1b965312017-04-18 06:55:32 -0700407 LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate_bps / 1000
stefanb6b0b922015-09-04 03:04:56 -0700408 << " kbps is below configured min bitrate "
409 << min_bitrate_configured_ / 1000 << " kbps.";
410 last_low_bitrate_log_ms_ = now_ms;
411 }
philipel1b965312017-04-18 06:55:32 -0700412 bitrate_bps = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000413 }
philipel1b965312017-04-18 06:55:32 -0700414
415 if (bitrate_bps != current_bitrate_bps_ ||
416 last_fraction_loss_ != last_logged_fraction_loss_ ||
417 now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200418 event_log_->Log(rtc::MakeUnique<RtcEventBweUpdateLossBased>(
419 bitrate_bps, last_fraction_loss_,
420 expected_packets_since_last_loss_update_));
philipel1b965312017-04-18 06:55:32 -0700421 last_logged_fraction_loss_ = last_fraction_loss_;
422 last_rtc_event_log_ms_ = now_ms;
423 }
424 current_bitrate_bps_ = bitrate_bps;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000425}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000426} // namespace webrtc