blob: d3bce593f36fa3402963cb11e4ba0e91a3e9f938 [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
Elad Alon4a87e1c2017-10-03 16:11:34 +020019#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "logging/rtc_event_log/rtc_event_log.h"
21#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020024#include "rtc_base/ptr_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#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 Janssonea86bb72018-02-14 16:53:38 +0000108 : lost_packets_since_last_loss_update_Q8_(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),
terelius006d93d2015-11-05 12:02:15 -0800128 rampup_uma_stats_updated_(kNumUmaRampupMetrics, false),
stefan3821ff82016-09-04 05:07:26 -0700129 event_log_(event_log),
Stefan Holmer52200d02016-09-20 14:14:23 +0200130 last_rtc_event_log_ms_(-1),
sprangc1b57a12017-02-28 08:50:47 -0800131 in_timeout_experiment_(
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200132 webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")),
133 low_loss_threshold_(kDefaultLowLossThreshold),
134 high_loss_threshold_(kDefaultHighLossThreshold),
135 bitrate_threshold_bps_(1000 * kDefaultBitrateThresholdKbps) {
ivoc14d5dbe2016-07-04 07:06:55 -0700136 RTC_DCHECK(event_log);
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200137 if (BweLossExperimentIsEnabled()) {
138 uint32_t bitrate_threshold_kbps;
139 if (ReadBweLossExperimentParameters(&low_loss_threshold_,
140 &high_loss_threshold_,
141 &bitrate_threshold_kbps)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100142 RTC_LOG(LS_INFO) << "Enabled BweLossExperiment with parameters "
143 << low_loss_threshold_ << ", " << high_loss_threshold_
144 << ", " << bitrate_threshold_kbps;
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200145 bitrate_threshold_bps_ = bitrate_threshold_kbps * 1000;
146 }
147 }
ivoc14d5dbe2016-07-04 07:06:55 -0700148}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000149
andresp@webrtc.org16b75c22014-03-21 14:00:51 +0000150SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000151
philipelc6957c72016-04-28 15:52:49 +0200152void SendSideBandwidthEstimation::SetBitrates(int send_bitrate,
153 int min_bitrate,
154 int max_bitrate) {
philipel1b965312017-04-18 06:55:32 -0700155 SetMinMaxBitrate(min_bitrate, max_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200156 if (send_bitrate > 0)
157 SetSendBitrate(send_bitrate);
philipelc6957c72016-04-28 15:52:49 +0200158}
159
Stefan Holmere5904162015-03-26 11:11:06 +0100160void SendSideBandwidthEstimation::SetSendBitrate(int bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700161 RTC_DCHECK_GT(bitrate, 0);
Bjorn Terelius29cb0e72017-11-08 14:41:12 +0100162 delay_based_bitrate_bps_ = 0; // Reset to avoid being capped by the estimate.
philipel1b965312017-04-18 06:55:32 -0700163 CapBitrateToThresholds(Clock::GetRealTimeClock()->TimeInMilliseconds(),
164 bitrate);
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000165 // Clear last sent bitrate history so the new value can be used directly
166 // and not capped.
167 min_bitrate_history_.clear();
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000168}
169
Stefan Holmere5904162015-03-26 11:11:06 +0100170void SendSideBandwidthEstimation::SetMinMaxBitrate(int min_bitrate,
171 int max_bitrate) {
henrikg91d6ede2015-09-17 00:24:34 -0700172 RTC_DCHECK_GE(min_bitrate, 0);
michaeltf082c2a2016-11-07 04:17:14 -0800173 min_bitrate_configured_ =
174 std::max(min_bitrate, congestion_controller::GetMinBitrateBps());
Stefan Holmere5904162015-03-26 11:11:06 +0100175 if (max_bitrate > 0) {
176 max_bitrate_configured_ =
177 std::max<uint32_t>(min_bitrate_configured_, max_bitrate);
178 } else {
179 max_bitrate_configured_ = kDefaultMaxBitrateBps;
180 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000181}
182
Stefan Holmere5904162015-03-26 11:11:06 +0100183int SendSideBandwidthEstimation::GetMinBitrate() const {
stefan@webrtc.org792f1a12015-03-04 12:24:26 +0000184 return min_bitrate_configured_;
henrik.lundin@webrtc.org845862f2014-03-06 07:19:28 +0000185}
186
Stefan Holmere5904162015-03-26 11:11:06 +0100187void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000188 uint8_t* loss,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000189 int64_t* rtt) const {
philipel1b965312017-04-18 06:55:32 -0700190 *bitrate = current_bitrate_bps_;
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000191 *loss = last_fraction_loss_;
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000192 *rtt = last_round_trip_time_ms_;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000193}
194
stefanb6b0b922015-09-04 03:04:56 -0700195void SendSideBandwidthEstimation::UpdateReceiverEstimate(
196 int64_t now_ms, uint32_t bandwidth) {
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000197 bwe_incoming_ = bandwidth;
philipel1b965312017-04-18 06:55:32 -0700198 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000199}
200
stefan32f81542016-01-20 07:13:58 -0800201void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(
202 int64_t now_ms,
203 uint32_t bitrate_bps) {
204 delay_based_bitrate_bps_ = bitrate_bps;
philipel1b965312017-04-18 06:55:32 -0700205 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
stefan32f81542016-01-20 07:13:58 -0800206}
207
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000208void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000209 int64_t rtt,
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000210 int number_of_packets,
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000211 int64_t now_ms) {
Stefan Holmer52200d02016-09-20 14:14:23 +0200212 last_feedback_ms_ = now_ms;
stefan@webrtc.org83d48042014-11-10 13:55:16 +0000213 if (first_report_time_ms_ == -1)
214 first_report_time_ms_ = now_ms;
215
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000216 // Update RTT if we were able to compute an RTT based on this RTCP.
217 // FlexFEC doesn't send RTCP SR, which means we won't be able to compute RTT.
218 if (rtt > 0)
219 last_round_trip_time_ms_ = rtt;
220
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000221 // Check sequence number diff and weight loss report
222 if (number_of_packets > 0) {
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000223 // Calculate number of lost packets.
224 const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000225 // Accumulate reports.
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000226 lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
pbosb7edb882015-10-22 08:52:20 -0700227 expected_packets_since_last_loss_update_ += number_of_packets;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000228
pbosb7edb882015-10-22 08:52:20 -0700229 // Don't generate a loss rate until it can be based on enough packets.
230 if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000231 return;
pbosb7edb882015-10-22 08:52:20 -0700232
233 has_decreased_since_last_fraction_loss_ = false;
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000234 last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ /
235 expected_packets_since_last_loss_update_;
pbosb7edb882015-10-22 08:52:20 -0700236
237 // Reset accumulators.
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000238 lost_packets_since_last_loss_update_Q8_ = 0;
pbosb7edb882015-10-22 08:52:20 -0700239 expected_packets_since_last_loss_update_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200240 last_packet_report_ms_ = now_ms;
241 UpdateEstimate(now_ms);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000242 }
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000243 UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000244}
245
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000246void SendSideBandwidthEstimation::UpdateUmaStats(int64_t now_ms,
247 int64_t rtt,
248 int lost_packets) {
philipel1b965312017-04-18 06:55:32 -0700249 int bitrate_kbps = static_cast<int>((current_bitrate_bps_ + 500) / 1000);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000250 for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) {
251 if (!rampup_uma_stats_updated_[i] &&
252 bitrate_kbps >= kUmaRampupMetrics[i].bitrate_kbps) {
asapersson1d02d3e2016-09-09 22:40:25 -0700253 RTC_HISTOGRAMS_COUNTS_100000(i, kUmaRampupMetrics[i].metric_name,
254 now_ms - first_report_time_ms_);
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000255 rampup_uma_stats_updated_[i] = true;
256 }
257 }
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000258 if (IsInStartPhase(now_ms)) {
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000259 initially_lost_packets_ += lost_packets;
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000260 } else if (uma_update_state_ == kNoUpdate) {
261 uma_update_state_ = kFirstDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000262 bitrate_at_2_seconds_kbps_ = bitrate_kbps;
asapersson1d02d3e2016-09-09 22:40:25 -0700263 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitiallyLostPackets",
264 initially_lost_packets_, 0, 100, 50);
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000265 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialRtt", static_cast<int>(rtt), 0,
266 2000, 50);
asapersson1d02d3e2016-09-09 22:40:25 -0700267 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialBandwidthEstimate",
268 bitrate_at_2_seconds_kbps_, 0, 2000, 50);
stefan@webrtc.orgdb262472014-11-04 19:32:10 +0000269 } else if (uma_update_state_ == kFirstDone &&
270 now_ms - first_report_time_ms_ >= kBweConverganceTimeMs) {
271 uma_update_state_ = kDone;
stefan@webrtc.org474e36e2015-01-19 15:44:47 +0000272 int bitrate_diff_kbps =
273 std::max(bitrate_at_2_seconds_kbps_ - bitrate_kbps, 0);
asapersson1d02d3e2016-09-09 22:40:25 -0700274 RTC_HISTOGRAM_COUNTS("WebRTC.BWE.InitialVsConvergedDiff", bitrate_diff_kbps,
275 0, 2000, 50);
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000276 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000277}
278
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000279void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {
philipel1b965312017-04-18 06:55:32 -0700280 uint32_t new_bitrate = current_bitrate_bps_;
stefanfa156692016-01-21 08:55:03 -0800281 // We trust the REMB and/or delay-based estimate during the first 2 seconds if
282 // we haven't had any packet loss reported, to allow startup bitrate probing.
283 if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {
philipel1b965312017-04-18 06:55:32 -0700284 new_bitrate = std::max(bwe_incoming_, new_bitrate);
285 new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);
286
287 if (new_bitrate != current_bitrate_bps_) {
stefanfa156692016-01-21 08:55:03 -0800288 min_bitrate_history_.clear();
philipel1b965312017-04-18 06:55:32 -0700289 min_bitrate_history_.push_back(
290 std::make_pair(now_ms, current_bitrate_bps_));
291 CapBitrateToThresholds(now_ms, new_bitrate);
stefanfa156692016-01-21 08:55:03 -0800292 return;
293 }
stefan@webrtc.org82462aa2014-10-23 11:57:05 +0000294 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000295 UpdateMinHistory(now_ms);
Stefan Holmer52200d02016-09-20 14:14:23 +0200296 if (last_packet_report_ms_ == -1) {
297 // No feedback received.
philipel1b965312017-04-18 06:55:32 -0700298 CapBitrateToThresholds(now_ms, current_bitrate_bps_);
Stefan Holmer52200d02016-09-20 14:14:23 +0200299 return;
300 }
301 int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;
302 int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;
303 if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200304 // We only care about loss above a given bitrate threshold.
305 float loss = last_fraction_loss_ / 256.0f;
306 // We only make decisions based on loss when the bitrate is above a
307 // threshold. This is a crude way of handling loss which is uncorrelated
308 // to congestion.
philipel1b965312017-04-18 06:55:32 -0700309 if (current_bitrate_bps_ < bitrate_threshold_bps_ ||
310 loss <= low_loss_threshold_) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000311 // Loss < 2%: Increase rate by 8% of the min bitrate in the last
312 // kBweIncreaseIntervalMs.
313 // Note that by remembering the bitrate over the last second one can
314 // rampup up one second faster than if only allowed to start ramping
315 // at 8% per second rate now. E.g.:
316 // If sending a constant 100kbps it can rampup immediatly to 108kbps
317 // whenever a receiver report is received with lower packet loss.
philipel1b965312017-04-18 06:55:32 -0700318 // If instead one would do: current_bitrate_bps_ *= 1.08^(delta time),
319 // it would take over one second since the lower packet loss to achieve
Stefan Holmer52200d02016-09-20 14:14:23 +0200320 // 108kbps.
philipel1b965312017-04-18 06:55:32 -0700321 new_bitrate = static_cast<uint32_t>(
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000322 min_bitrate_history_.front().second * 1.08 + 0.5);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000323
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000324 // Add 1 kbps extra, just to make sure that we do not get stuck
325 // (gives a little extra increase at low rates, negligible at higher
326 // rates).
philipel1b965312017-04-18 06:55:32 -0700327 new_bitrate += 1000;
328 } else if (current_bitrate_bps_ > bitrate_threshold_bps_) {
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200329 if (loss <= high_loss_threshold_) {
330 // Loss between 2% - 10%: Do nothing.
331 } else {
332 // Loss > 10%: Limit the rate decreases to once a kBweDecreaseIntervalMs
333 // + rtt.
334 if (!has_decreased_since_last_fraction_loss_ &&
335 (now_ms - time_last_decrease_ms_) >=
336 (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {
337 time_last_decrease_ms_ = now_ms;
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000338
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200339 // Reduce rate:
340 // newRate = rate * (1 - 0.5*lossRate);
341 // where packetLoss = 256*lossRate;
philipel1b965312017-04-18 06:55:32 -0700342 new_bitrate = static_cast<uint32_t>(
343 (current_bitrate_bps_ *
344 static_cast<double>(512 - last_fraction_loss_)) /
Stefan Holmer9c79ed92017-03-31 15:53:27 +0200345 512.0);
346 has_decreased_since_last_fraction_loss_ = true;
347 }
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000348 }
andresp@webrtc.org07bc7342014-03-21 16:51:01 +0000349 }
Stefan Holmer52200d02016-09-20 14:14:23 +0200350 } else if (time_since_feedback_ms >
351 kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&
352 (last_timeout_ms_ == -1 ||
353 now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {
354 if (in_timeout_experiment_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100355 RTC_LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms
356 << " ms), reducing bitrate.";
philipel1b965312017-04-18 06:55:32 -0700357 new_bitrate *= 0.8;
Stefan Holmer52200d02016-09-20 14:14:23 +0200358 // Reset accumulators since we've already acted on missing feedback and
359 // shouldn't to act again on these old lost packets.
Sebastian Janssonea86bb72018-02-14 16:53:38 +0000360 lost_packets_since_last_loss_update_Q8_ = 0;
Stefan Holmer52200d02016-09-20 14:14:23 +0200361 expected_packets_since_last_loss_update_ = 0;
362 last_timeout_ms_ = now_ms;
363 }
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000364 }
philipel1b965312017-04-18 06:55:32 -0700365
366 CapBitrateToThresholds(now_ms, new_bitrate);
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000367}
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000368
stefan@webrtc.org548b2282014-11-03 14:42:43 +0000369bool SendSideBandwidthEstimation::IsInStartPhase(int64_t now_ms) const {
370 return first_report_time_ms_ == -1 ||
371 now_ms - first_report_time_ms_ < kStartPhaseMs;
372}
373
stefan@webrtc.orgedeea912014-12-08 19:46:23 +0000374void SendSideBandwidthEstimation::UpdateMinHistory(int64_t now_ms) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000375 // Remove old data points from history.
376 // Since history precision is in ms, add one so it is able to increase
377 // bitrate if it is off by as little as 0.5ms.
378 while (!min_bitrate_history_.empty() &&
379 now_ms - min_bitrate_history_.front().first + 1 >
380 kBweIncreaseIntervalMs) {
381 min_bitrate_history_.pop_front();
382 }
383
384 // Typical minimum sliding-window algorithm: Pop values higher than current
385 // bitrate before pushing it.
386 while (!min_bitrate_history_.empty() &&
philipel1b965312017-04-18 06:55:32 -0700387 current_bitrate_bps_ <= min_bitrate_history_.back().second) {
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000388 min_bitrate_history_.pop_back();
389 }
390
philipel1b965312017-04-18 06:55:32 -0700391 min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));
andresp@webrtc.org44caf012014-03-26 21:00:21 +0000392}
393
philipel1b965312017-04-18 06:55:32 -0700394void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,
395 uint32_t bitrate_bps) {
396 if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {
397 bitrate_bps = bwe_incoming_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000398 }
philipel1b965312017-04-18 06:55:32 -0700399 if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {
400 bitrate_bps = delay_based_bitrate_bps_;
stefan32f81542016-01-20 07:13:58 -0800401 }
philipel1b965312017-04-18 06:55:32 -0700402 if (bitrate_bps > max_bitrate_configured_) {
403 bitrate_bps = max_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000404 }
philipel1b965312017-04-18 06:55:32 -0700405 if (bitrate_bps < min_bitrate_configured_) {
stefanb6b0b922015-09-04 03:04:56 -0700406 if (last_low_bitrate_log_ms_ == -1 ||
407 now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100408 RTC_LOG(LS_WARNING) << "Estimated available bandwidth "
409 << bitrate_bps / 1000
410 << " kbps is below configured min bitrate "
411 << min_bitrate_configured_ / 1000 << " kbps.";
stefanb6b0b922015-09-04 03:04:56 -0700412 last_low_bitrate_log_ms_ = now_ms;
413 }
philipel1b965312017-04-18 06:55:32 -0700414 bitrate_bps = min_bitrate_configured_;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000415 }
philipel1b965312017-04-18 06:55:32 -0700416
417 if (bitrate_bps != current_bitrate_bps_ ||
418 last_fraction_loss_ != last_logged_fraction_loss_ ||
419 now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200420 event_log_->Log(rtc::MakeUnique<RtcEventBweUpdateLossBased>(
421 bitrate_bps, last_fraction_loss_,
422 expected_packets_since_last_loss_update_));
philipel1b965312017-04-18 06:55:32 -0700423 last_logged_fraction_loss_ = last_fraction_loss_;
424 last_rtc_event_log_ms_ = now_ms;
425 }
426 current_bitrate_bps_ = bitrate_bps;
andresp@webrtc.org4e69f782014-03-17 17:07:48 +0000427}
pwestin@webrtc.org1cd11622012-04-19 12:13:52 +0000428} // namespace webrtc