blob: 02d75959a98bc15b5d32e33dbae18bbb1df58bb5 [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);
philipel1b965312017-04-18 06:55:32 -0700161 CapBitrateToThresholds(Clock::GetRealTimeClock()->TimeInMilliseconds(),
162 bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000163 // Clear last sent bitrate history so the new value can be used directly
164 // and not capped.
165 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000166}
167
Stefan Holmere5904162015-03-26 11:11:06 +0100168void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
169 int max_bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700170 RTC_DCHECK_GE(min_bitrate, 0);
michaeltf082c2a2016-11-07 04:17:14 -0800171 min_bitrate_configured_ =
172 std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
Stefan Holmere5904162015-03-26 11:11:06 +0100173 if (max_bitrate > 0) {
174 max_bitrate_configured_ =
175 std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
176 } else {
177 max_bitrate_configured_ = kDefaultMaxBitrateBps;
178 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000179}
180
Stefan Holmere5904162015-03-26 11:11:06 +0100181int SendSideBandwidthEstimation::GetMinBitrate() const {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000182 return min_bitrate_configured_;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000183}
184
Stefan Holmere5904162015-03-26 11:11:06 +0100185void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000186 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000187 int64_t* rtt) const {
philipel1b965312017-04-18 06:55:32 -0700188 *bitrate = current_bitrate_bps_;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000189 *loss = last_fraction_loss_;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000190 *rtt = last_round_trip_time_ms_;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000191}
192
stefanb6b0b922015-09-04 03:04:56 -0700193void SendSideBandwidthEstimation::UpdateReceiverEstimate(
194 int64_t now_ms, uint32_t bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000195 bwe_incoming_ = bandwidth;
philipel1b965312017-04-18 06:55:32 -0700196 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000197}
198
stefan32f81542016-01-20 07:13:58 -0800199void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
200 int64_t now_ms,
201 uint32_t bitrate_bps) {
202 delay_based_bitrate_bps_ = bitrate_bps;
philipel1b965312017-04-18 06:55:32 -0700203 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
stefan32f81542016-01-20 07:13:58 -0800204}
205
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000206void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000207 int64_t rtt,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000208 int number_of_packets,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000209 int64_t now_ms) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200210 last_feedback_ms_ = now_ms;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000211 if (first_report_time_ms_ == -1)
212 first_report_time_ms_ = now_ms;
213
stefan889d9652017-07-05 03:03:02 -0700214 // Update RTT if we were able to compute an RTT based on this RTCP.
215 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
216 if (rtt > 0)
217 last_round_trip_time_ms_ = rtt;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000218
219 // Check sequence number diff and weight loss report
220 if (number_of_packets > 0) {
221 // Calculate number of lost packets.
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000222 const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000223 // Accumulate reports.
pbosb7edb882015-10-22 08:52:20 -0700224 lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
225 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000226
pbosb7edb882015-10-22 08:52:20 -0700227 // Don't generate a loss rate until it can be based on enough packets.
228 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000229 return;
pbosb7edb882015-10-22 08:52:20 -0700230
231 has_decreased_since_last_fraction_loss_ = false;
232 last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ /
233 expected_packets_since_last_loss_update_;
234
235 // Reset accumulators.
236 lost_packets_since_last_loss_update_Q8_ = 0;
237 expected_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200238 last_packet_report_ms_ = now_ms;
239 UpdateEstimate(now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000240 }
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000241 UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000242}
243
244void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000245 int64_t rtt,
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000246 int lost_packets) {
philipel1b965312017-04-18 06:55:32 -0700247 int bitrate_kbps = static_cast<int>((current_bitrate_bps_ + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000248 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
249 if (!rampup_uma_stats_updated_[i] &&
250 bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700251 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
252 now_ms - first_report_time_ms_);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000253 rampup_uma_stats_updated_[i] = true;
254 }
255 }
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000256 if (IsInStartPhase(now_ms)) {
257 initially_lost_packets_ += lost_packets;
258 } else if (uma_update_state_ == kNoUpdate) {
259 uma_update_state_ = kFirstDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000260 bitrate_at_2_seconds_kbps_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700261 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
262 initially_lost_packets_, 0, 100, 50);
263 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt), 0,
264 2000, 50);
265 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
266 bitrate_at_2_seconds_kbps_, 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000267 } else if (uma_update_state_ == kFirstDone &&
268 now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
269 uma_update_state_ = kDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000270 int bitrate_diff_kbps =
271 std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700272 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
273 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000274 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000275}
276
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000277void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
philipel1b965312017-04-18 06:55:32 -0700278 uint32_t new_bitrate = current_bitrate_bps_;
stefanfa156692016-01-21 08:55:03 -0800279 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
280 // we haven't had any packet loss reported, to allow startup bitrate probing.
281 if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
philipel1b965312017-04-18 06:55:32 -0700282 new_bitrate = std::max(bwe_incoming_, new_bitrate);
283 new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
284
285 if (new_bitrate != current_bitrate_bps_) {
stefanfa156692016-01-21 08:55:03 -0800286 min_bitrate_history_.clear();
philipel1b965312017-04-18 06:55:32 -0700287 min_bitrate_history_.push_back(
288 std::make_pair(now_ms, current_bitrate_bps_));
289 CapBitrateToThresholds(now_ms, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800290 return;
291 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000292 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000293 UpdateMinHistory(now_ms);
Stefan Holmer52200d02016-09-20 14:14:23 +0200294 if (last_packet_report_ms_ == -1) {
295 // No feedback received.
philipel1b965312017-04-18 06:55:32 -0700296 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200297 return;
298 }
299 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
300 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
301 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200302 // We only care about loss above a given bitrate threshold.
303 float loss = last_fraction_loss_ / 256.0f;
304 // We only make decisions based on loss when the bitrate is above a
305 // threshold. This is a crude way of handling loss which is uncorrelated
306 // to congestion.
philipel1b965312017-04-18 06:55:32 -0700307 if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
308 loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000309 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
310 // kBweIncreaseIntervalMs.
311 // Note that by remembering the bitrate over the last second one can
312 // rampup up one second faster than if only allowed to start ramping
313 // at 8% per second rate now. E.g.:
314 // If sending a constant 100kbps it can rampup immediatly to 108kbps
315 // whenever a receiver report is received with lower packet loss.
philipel1b965312017-04-18 06:55:32 -0700316 // If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
317 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200318 // 108kbps.
philipel1b965312017-04-18 06:55:32 -0700319 new_bitrate = static_cast<uint32_t>(
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000320 min_bitrate_history_.front().second * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000321
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000322 // Add 1 kbps extra, just to make sure that we do not get stuck
323 // (gives a little extra increase at low rates, negligible at higher
324 // rates).
philipel1b965312017-04-18 06:55:32 -0700325 new_bitrate += 1000;
326 } else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200327 if (loss <= high_loss_threshold_) {
328 // Loss between 2% - 10%: Do nothing.
329 } else {
330 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
331 // + rtt.
332 if (!has_decreased_since_last_fraction_loss_ &&
333 (now_ms - time_last_decrease_ms_) >=
334 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
335 time_last_decrease_ms_ = now_ms;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000336
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200337 // Reduce rate:
338 // newRate = rate * (1 - 0.5*lossRate);
339 // where packetLoss = 256*lossRate;
philipel1b965312017-04-18 06:55:32 -0700340 new_bitrate = static_cast<uint32_t>(
341 (current_bitrate_bps_ *
342 static_cast<double>(512 - last_fraction_loss_)) /
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200343 512.0);
344 has_decreased_since_last_fraction_loss_ = true;
345 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000346 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000347 }
Stefan Holmer52200d02016-09-20 14:14:23 +0200348 } else if (time_since_feedback_ms >
349 kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
350 (last_timeout_ms_ == -1 ||
351 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
352 if (in_timeout_experiment_) {
353 LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
354 << " ms), reducing bitrate.";
philipel1b965312017-04-18 06:55:32 -0700355 new_bitrate *= 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200356 // Reset accumulators since we've already acted on missing feedback and
357 // shouldn't to act again on these old lost packets.
358 lost_packets_since_last_loss_update_Q8_ = 0;
359 expected_packets_since_last_loss_update_ = 0;
360 last_timeout_ms_ = now_ms;
361 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000362 }
philipel1b965312017-04-18 06:55:32 -0700363
364 CapBitrateToThresholds(now_ms, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000365}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000366
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000367bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
368 return first_report_time_ms_ == -1 ||
369 now_ms - first_report_time_ms_ < kStartPhaseMs;
370}
371
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000372void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000373 // Remove old data points from history.
374 // Since history precision is in ms, add one so it is able to increase
375 // bitrate if it is off by as little as 0.5ms.
376 while (!min_bitrate_history_.empty() &&
377 now_ms - min_bitrate_history_.front().first + 1 >
378 kBweIncreaseIntervalMs) {
379 min_bitrate_history_.pop_front();
380 }
381
382 // Typical minimum sliding-window algorithm: Pop values higher than current
383 // bitrate before pushing it.
384 while (!min_bitrate_history_.empty() &&
philipel1b965312017-04-18 06:55:32 -0700385 current_bitrate_bps_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000386 min_bitrate_history_.pop_back();
387 }
388
philipel1b965312017-04-18 06:55:32 -0700389 min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000390}
391
philipel1b965312017-04-18 06:55:32 -0700392void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,
393 uint32_t bitrate_bps) {
394 if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {
395 bitrate_bps = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000396 }
philipel1b965312017-04-18 06:55:32 -0700397 if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {
398 bitrate_bps = delay_based_bitrate_bps_;
stefan32f81542016-01-20 07:13:58 -0800399 }
philipel1b965312017-04-18 06:55:32 -0700400 if (bitrate_bps > max_bitrate_configured_) {
401 bitrate_bps = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000402 }
philipel1b965312017-04-18 06:55:32 -0700403 if (bitrate_bps < min_bitrate_configured_) {
stefanb6b0b922015-09-04 03:04:56 -0700404 if (last_low_bitrate_log_ms_ == -1 ||
405 now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
philipel1b965312017-04-18 06:55:32 -0700406 LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate_bps / 1000
stefanb6b0b922015-09-04 03:04:56 -0700407 << " kbps is below configured min bitrate "
408 << min_bitrate_configured_ / 1000 << " kbps.";
409 last_low_bitrate_log_ms_ = now_ms;
410 }
philipel1b965312017-04-18 06:55:32 -0700411 bitrate_bps = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000412 }
philipel1b965312017-04-18 06:55:32 -0700413
414 if (bitrate_bps != current_bitrate_bps_ ||
415 last_fraction_loss_ != last_logged_fraction_loss_ ||
416 now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200417 event_log_->Log(rtc::MakeUnique<RtcEventBweUpdateLossBased>(
418 bitrate_bps, last_fraction_loss_,
419 expected_packets_since_last_loss_update_));
philipel1b965312017-04-18 06:55:32 -0700420 last_logged_fraction_loss_ = last_fraction_loss_;
421 last_rtc_event_log_ms_ = now_ms;
422 }
423 current_bitrate_bps_ = bitrate_bps;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000424}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000425} // namespace webrtc