blob: 6def9ba48059c791a4abe4f930ab7c1797e89971 [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
pbos@webrtc.org2e10b8e2013-07-16 12:54:53 +000011#include "webrtc/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
skvladcc91d282016-10-03 18:31:22 -070018#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
michaeltf082c2a2016-11-07 04:17:14 -080019#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020020#include "webrtc/rtc_base/checks.h"
21#include "webrtc/rtc_base/logging.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010022#include "webrtc/system_wrappers/include/field_trial.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010023#include "webrtc/system_wrappers/include/metrics.h"
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +000024
25namespace webrtc {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000026namespace {
Stefan Holmere5904162015-03-26 11:11:06 +010027const int64_t kBweIncreaseIntervalMs = 1000;
28const int64_t kBweDecreaseIntervalMs = 300;
29const int64_t kStartPhaseMs = 2000;
30const int64_t kBweConverganceTimeMs = 20000;
31const int kLimitNumPackets = 20;
Stefan Holmere5904162015-03-26 11:11:06 +010032const int kDefaultMaxBitrateBps = 1000000000;
stefanb6b0b922015-09-04 03:04:56 -070033const int64_t kLowBitrateLogPeriodMs = 10000;
stefan3821ff82016-09-04 05:07:26 -070034const int64_t kRtcEventLogPeriodMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020035// Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals.
stefan5cb19822017-06-16 07:47:00 -070036const int64_t kFeedbackIntervalMs = 5000;
Stefan Holmer52200d02016-09-20 14:14:23 +020037const int64_t kFeedbackTimeoutIntervals = 3;
38const int64_t kTimeoutIntervalMs = 1000;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +000039
Stefan Holmer9c79ed92017-03-31 15:53:27 +020040const float kDefaultLowLossThreshold = 0.02f;
41const float kDefaultHighLossThreshold = 0.1f;
42const int kDefaultBitrateThresholdKbps = 0;
43
stefan@webrtc.org474e36e2015-01-19 15:44:47 +000044struct UmaRampUpMetric {
45 const char* metric_name;
46 int bitrate_kbps;
47};
48
49const UmaRampUpMetric kUmaRampupMetrics[] = {
50 {"WebRTC.BWE.RampUpTimeTo500kbpsInMs", 500},
51 {"WebRTC.BWE.RampUpTimeTo1000kbpsInMs", 1000},
52 {"WebRTC.BWE.RampUpTimeTo2000kbpsInMs", 2000}};
53const size_t kNumUmaRampupMetrics =
54 sizeof(kUmaRampupMetrics) / sizeof(kUmaRampupMetrics[0]);
55
Stefan Holmer9c79ed92017-03-31 15:53:27 +020056const char kBweLosExperiment[] = "WebRTC-BweLossExperiment";
57
58bool BweLossExperimentIsEnabled() {
59 std::string experiment_string =
60 webrtc::field_trial::FindFullName(kBweLosExperiment);
61 // The experiment is enabled iff the field trial string begins with "Enabled".
62 return experiment_string.find("Enabled") == 0;
63}
64
65bool ReadBweLossExperimentParameters(float* low_loss_threshold,
66 float* high_loss_threshold,
67 uint32_t* bitrate_threshold_kbps) {
68 RTC_DCHECK(low_loss_threshold);
69 RTC_DCHECK(high_loss_threshold);
70 RTC_DCHECK(bitrate_threshold_kbps);
71 std::string experiment_string =
72 webrtc::field_trial::FindFullName(kBweLosExperiment);
73 int parsed_values =
74 sscanf(experiment_string.c_str(), "Enabled-%f,%f,%u", low_loss_threshold,
75 high_loss_threshold, bitrate_threshold_kbps);
76 if (parsed_values == 3) {
77 RTC_CHECK_GT(*low_loss_threshold, 0.0f)
78 << "Loss threshold must be greater than 0.";
79 RTC_CHECK_LE(*low_loss_threshold, 1.0f)
80 << "Loss threshold must be less than or equal to 1.";
81 RTC_CHECK_GT(*high_loss_threshold, 0.0f)
82 << "Loss threshold must be greater than 0.";
83 RTC_CHECK_LE(*high_loss_threshold, 1.0f)
84 << "Loss threshold must be less than or equal to 1.";
85 RTC_CHECK_LE(*low_loss_threshold, *high_loss_threshold)
86 << "The low loss threshold must be less than or equal to the high loss "
87 "threshold.";
88 RTC_CHECK_GE(*bitrate_threshold_kbps, 0)
89 << "Bitrate threshold can't be negative.";
90 RTC_CHECK_LT(*bitrate_threshold_kbps,
91 std::numeric_limits<int>::max() / 1000)
92 << "Bitrate must be smaller enough to avoid overflows.";
93 return true;
94 }
95 LOG(LS_WARNING) << "Failed to parse parameters for BweLossExperiment "
96 "experiment from field trial string. Using default.";
97 *low_loss_threshold = kDefaultLowLossThreshold;
98 *high_loss_threshold = kDefaultHighLossThreshold;
99 *bitrate_threshold_kbps = kDefaultBitrateThresholdKbps;
100 return false;
101}
jbauchf91e6d02016-01-24 23:05:21 -0800102} // namespace
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000103
ivoc14d5dbe2016-07-04 07:06:55 -0700104SendSideBandwidthEstimation::SendSideBandwidthEstimation(RtcEventLog* event_log)
pbosb7edb882015-10-22 08:52:20 -0700105 : lost_packets_since_last_loss_update_Q8_(0),
106 expected_packets_since_last_loss_update_(0),
philipel1b965312017-04-18 06:55:32 -0700107 current_bitrate_bps_(0),
michaeltf082c2a2016-11-07 04:17:14 -0800108 min_bitrate_configured_(congestion_controller::GetMinBitrateBps()),
Stefan Holmere5904162015-03-26 11:11:06 +0100109 max_bitrate_configured_(kDefaultMaxBitrateBps),
stefanb6b0b922015-09-04 03:04:56 -0700110 last_low_bitrate_log_ms_(-1),
pbosb7edb882015-10-22 08:52:20 -0700111 has_decreased_since_last_fraction_loss_(false),
Stefan Holmer52200d02016-09-20 14:14:23 +0200112 last_feedback_ms_(-1),
113 last_packet_report_ms_(-1),
114 last_timeout_ms_(-1),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000115 last_fraction_loss_(0),
stefan3821ff82016-09-04 05:07:26 -0700116 last_logged_fraction_loss_(0),
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000117 last_round_trip_time_ms_(0),
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000118 bwe_incoming_(0),
stefan32f81542016-01-20 07:13:58 -0800119 delay_based_bitrate_bps_(0),
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000120 time_last_decrease_ms_(0),
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000121 first_report_time_ms_(-1),
122 initially_lost_packets_(0),
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000123 bitrate_at_2_seconds_kbps_(0),
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000124 uma_update_state_(kNoUpdate),
terelius006d93d2015-11-05 12:02:15 -0800125 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
stefan3821ff82016-09-04 05:07:26 -0700126 event_log_(event_log),
Stefan Holmer52200d02016-09-20 14:14:23 +0200127 last_rtc_event_log_ms_(-1),
sprangc1b57a12017-02-28 08:50:47 -0800128 in_timeout_experiment_(
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200129 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
130 low_loss_threshold_(kDefaultLowLossThreshold),
131 high_loss_threshold_(kDefaultHighLossThreshold),
132 bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) {
ivoc14d5dbe2016-07-04 07:06:55 -0700133 RTC_DCHECK(event_log);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200134 if (BweLossExperimentIsEnabled()) {
135 uint32_t bitrate_threshold_kbps;
136 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
137 &high_loss_threshold_,
138 &bitrate_threshold_kbps)) {
139 LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
140 << low_loss_threshold_ << ", " << high_loss_threshold_
141 << ", " << bitrate_threshold_kbps;
142 bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000;
143 }
144 }
ivoc14d5dbe2016-07-04 07:06:55 -0700145}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000146
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000147SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000148
philipelc6957c72016-04-28 15:52:49 +0200149void SendSideBandwidthEstimation::SetBitrates(int send_bitrate,
150 int min_bitrate,
151 int max_bitrate) {
philipel1b965312017-04-18 06:55:32 -0700152 SetMinMaxBitrate(min_bitrate, max_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200153 if (send_bitrate > 0)
154 SetSendBitrate(send_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200155}
156
Stefan Holmere5904162015-03-26 11:11:06 +0100157void SendSideBandwidthEstimation::SetSendBitrate(int bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700158 RTC_DCHECK_GT(bitrate, 0);
philipel1b965312017-04-18 06:55:32 -0700159 CapBitrateToThresholds(Clock::GetRealTimeClock()->TimeInMilliseconds(),
160 bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000161 // Clear last sent bitrate history so the new value can be used directly
162 // and not capped.
163 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000164}
165
Stefan Holmere5904162015-03-26 11:11:06 +0100166void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
167 int max_bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700168 RTC_DCHECK_GE(min_bitrate, 0);
michaeltf082c2a2016-11-07 04:17:14 -0800169 min_bitrate_configured_ =
170 std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
Stefan Holmere5904162015-03-26 11:11:06 +0100171 if (max_bitrate > 0) {
172 max_bitrate_configured_ =
173 std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
174 } else {
175 max_bitrate_configured_ = kDefaultMaxBitrateBps;
176 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000177}
178
Stefan Holmere5904162015-03-26 11:11:06 +0100179int SendSideBandwidthEstimation::GetMinBitrate() const {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000180 return min_bitrate_configured_;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000181}
182
Stefan Holmere5904162015-03-26 11:11:06 +0100183void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000184 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000185 int64_t* rtt) const {
philipel1b965312017-04-18 06:55:32 -0700186 *bitrate = current_bitrate_bps_;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000187 *loss = last_fraction_loss_;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000188 *rtt = last_round_trip_time_ms_;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000189}
190
stefanb6b0b922015-09-04 03:04:56 -0700191void SendSideBandwidthEstimation::UpdateReceiverEstimate(
192 int64_t now_ms, uint32_t bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000193 bwe_incoming_ = bandwidth;
philipel1b965312017-04-18 06:55:32 -0700194 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000195}
196
stefan32f81542016-01-20 07:13:58 -0800197void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
198 int64_t now_ms,
199 uint32_t bitrate_bps) {
200 delay_based_bitrate_bps_ = bitrate_bps;
philipel1b965312017-04-18 06:55:32 -0700201 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
stefan32f81542016-01-20 07:13:58 -0800202}
203
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000204void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000205 int64_t rtt,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000206 int number_of_packets,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000207 int64_t now_ms) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200208 last_feedback_ms_ = now_ms;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000209 if (first_report_time_ms_ == -1)
210 first_report_time_ms_ = now_ms;
211
stefan889d9652017-07-05 03:03:02 -0700212 // Update RTT if we were able to compute an RTT based on this RTCP.
213 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
214 if (rtt > 0)
215 last_round_trip_time_ms_ = rtt;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000216
217 // Check sequence number diff and weight loss report
218 if (number_of_packets > 0) {
219 // Calculate number of lost packets.
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000220 const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000221 // Accumulate reports.
pbosb7edb882015-10-22 08:52:20 -0700222 lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
223 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000224
pbosb7edb882015-10-22 08:52:20 -0700225 // Don't generate a loss rate until it can be based on enough packets.
226 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000227 return;
pbosb7edb882015-10-22 08:52:20 -0700228
229 has_decreased_since_last_fraction_loss_ = false;
230 last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ /
231 expected_packets_since_last_loss_update_;
232
233 // Reset accumulators.
234 lost_packets_since_last_loss_update_Q8_ = 0;
235 expected_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200236 last_packet_report_ms_ = now_ms;
237 UpdateEstimate(now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000238 }
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000239 UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000240}
241
242void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000243 int64_t rtt,
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000244 int lost_packets) {
philipel1b965312017-04-18 06:55:32 -0700245 int bitrate_kbps = static_cast<int>((current_bitrate_bps_ + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000246 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
247 if (!rampup_uma_stats_updated_[i] &&
248 bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700249 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
250 now_ms - first_report_time_ms_);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000251 rampup_uma_stats_updated_[i] = true;
252 }
253 }
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000254 if (IsInStartPhase(now_ms)) {
255 initially_lost_packets_ += lost_packets;
256 } else if (uma_update_state_ == kNoUpdate) {
257 uma_update_state_ = kFirstDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000258 bitrate_at_2_seconds_kbps_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700259 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
260 initially_lost_packets_, 0, 100, 50);
261 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt), 0,
262 2000, 50);
263 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
264 bitrate_at_2_seconds_kbps_, 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000265 } else if (uma_update_state_ == kFirstDone &&
266 now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
267 uma_update_state_ = kDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000268 int bitrate_diff_kbps =
269 std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700270 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
271 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000272 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000273}
274
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000275void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
philipel1b965312017-04-18 06:55:32 -0700276 uint32_t new_bitrate = current_bitrate_bps_;
stefanfa156692016-01-21 08:55:03 -0800277 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
278 // we haven't had any packet loss reported, to allow startup bitrate probing.
279 if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
philipel1b965312017-04-18 06:55:32 -0700280 new_bitrate = std::max(bwe_incoming_, new_bitrate);
281 new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
282
283 if (new_bitrate != current_bitrate_bps_) {
stefanfa156692016-01-21 08:55:03 -0800284 min_bitrate_history_.clear();
philipel1b965312017-04-18 06:55:32 -0700285 min_bitrate_history_.push_back(
286 std::make_pair(now_ms, current_bitrate_bps_));
287 CapBitrateToThresholds(now_ms, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800288 return;
289 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000290 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000291 UpdateMinHistory(now_ms);
Stefan Holmer52200d02016-09-20 14:14:23 +0200292 if (last_packet_report_ms_ == -1) {
293 // No feedback received.
philipel1b965312017-04-18 06:55:32 -0700294 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200295 return;
296 }
297 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
298 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
299 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200300 // We only care about loss above a given bitrate threshold.
301 float loss = last_fraction_loss_ / 256.0f;
302 // We only make decisions based on loss when the bitrate is above a
303 // threshold. This is a crude way of handling loss which is uncorrelated
304 // to congestion.
philipel1b965312017-04-18 06:55:32 -0700305 if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
306 loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000307 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
308 // kBweIncreaseIntervalMs.
309 // Note that by remembering the bitrate over the last second one can
310 // rampup up one second faster than if only allowed to start ramping
311 // at 8% per second rate now. E.g.:
312 // If sending a constant 100kbps it can rampup immediatly to 108kbps
313 // whenever a receiver report is received with lower packet loss.
philipel1b965312017-04-18 06:55:32 -0700314 // If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
315 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200316 // 108kbps.
philipel1b965312017-04-18 06:55:32 -0700317 new_bitrate = static_cast<uint32_t>(
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000318 min_bitrate_history_.front().second * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000319
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000320 // Add 1 kbps extra, just to make sure that we do not get stuck
321 // (gives a little extra increase at low rates, negligible at higher
322 // rates).
philipel1b965312017-04-18 06:55:32 -0700323 new_bitrate += 1000;
324 } else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200325 if (loss <= high_loss_threshold_) {
326 // Loss between 2% - 10%: Do nothing.
327 } else {
328 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
329 // + rtt.
330 if (!has_decreased_since_last_fraction_loss_ &&
331 (now_ms - time_last_decrease_ms_) >=
332 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
333 time_last_decrease_ms_ = now_ms;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000334
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200335 // Reduce rate:
336 // newRate = rate * (1 - 0.5*lossRate);
337 // where packetLoss = 256*lossRate;
philipel1b965312017-04-18 06:55:32 -0700338 new_bitrate = static_cast<uint32_t>(
339 (current_bitrate_bps_ *
340 static_cast<double>(512 - last_fraction_loss_)) /
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200341 512.0);
342 has_decreased_since_last_fraction_loss_ = true;
343 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000344 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000345 }
Stefan Holmer52200d02016-09-20 14:14:23 +0200346 } else if (time_since_feedback_ms >
347 kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
348 (last_timeout_ms_ == -1 ||
349 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
350 if (in_timeout_experiment_) {
351 LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
352 << " ms), reducing bitrate.";
philipel1b965312017-04-18 06:55:32 -0700353 new_bitrate *= 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200354 // Reset accumulators since we've already acted on missing feedback and
355 // shouldn't to act again on these old lost packets.
356 lost_packets_since_last_loss_update_Q8_ = 0;
357 expected_packets_since_last_loss_update_ = 0;
358 last_timeout_ms_ = now_ms;
359 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000360 }
philipel1b965312017-04-18 06:55:32 -0700361
362 CapBitrateToThresholds(now_ms, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000363}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000364
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000365bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
366 return first_report_time_ms_ == -1 ||
367 now_ms - first_report_time_ms_ < kStartPhaseMs;
368}
369
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000370void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000371 // Remove old data points from history.
372 // Since history precision is in ms, add one so it is able to increase
373 // bitrate if it is off by as little as 0.5ms.
374 while (!min_bitrate_history_.empty() &&
375 now_ms - min_bitrate_history_.front().first + 1 >
376 kBweIncreaseIntervalMs) {
377 min_bitrate_history_.pop_front();
378 }
379
380 // Typical minimum sliding-window algorithm: Pop values higher than current
381 // bitrate before pushing it.
382 while (!min_bitrate_history_.empty() &&
philipel1b965312017-04-18 06:55:32 -0700383 current_bitrate_bps_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000384 min_bitrate_history_.pop_back();
385 }
386
philipel1b965312017-04-18 06:55:32 -0700387 min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000388}
389
philipel1b965312017-04-18 06:55:32 -0700390void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,
391 uint32_t bitrate_bps) {
392 if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {
393 bitrate_bps = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000394 }
philipel1b965312017-04-18 06:55:32 -0700395 if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {
396 bitrate_bps = delay_based_bitrate_bps_;
stefan32f81542016-01-20 07:13:58 -0800397 }
philipel1b965312017-04-18 06:55:32 -0700398 if (bitrate_bps > max_bitrate_configured_) {
399 bitrate_bps = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000400 }
philipel1b965312017-04-18 06:55:32 -0700401 if (bitrate_bps < min_bitrate_configured_) {
stefanb6b0b922015-09-04 03:04:56 -0700402 if (last_low_bitrate_log_ms_ == -1 ||
403 now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
philipel1b965312017-04-18 06:55:32 -0700404 LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate_bps / 1000
stefanb6b0b922015-09-04 03:04:56 -0700405 << " kbps is below configured min bitrate "
406 << min_bitrate_configured_ / 1000 << " kbps.";
407 last_low_bitrate_log_ms_ = now_ms;
408 }
philipel1b965312017-04-18 06:55:32 -0700409 bitrate_bps = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000410 }
philipel1b965312017-04-18 06:55:32 -0700411
412 if (bitrate_bps != current_bitrate_bps_ ||
413 last_fraction_loss_ != last_logged_fraction_loss_ ||
414 now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
415 event_log_->LogLossBasedBweUpdate(bitrate_bps, last_fraction_loss_,
416 expected_packets_since_last_loss_update_);
417 last_logged_fraction_loss_ = last_fraction_loss_;
418 last_rtc_event_log_ms_ = now_ms;
419 }
420 current_bitrate_bps_ = bitrate_bps;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000421}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000422} // namespace webrtc