blob: c50f0d4b45e8fd1c9bd071f3f68082e30cc9647a [file] [log] [blame]
philipel863a8262016-06-17 09:21:34 -07001/*
2 * Copyright (c) 2016 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
11#include "webrtc/modules/congestion_controller/delay_based_bwe.h"
12
philipel863a8262016-06-17 09:21:34 -070013#include <algorithm>
Stefan Holmer492ee282016-10-27 17:19:20 +020014#include <cmath>
tereliusafaef8b2016-11-17 03:48:18 -080015#include <string>
philipel863a8262016-06-17 09:21:34 -070016
terelius0baf55d2017-02-17 03:38:28 -080017#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
Irfan Sheriffb2540bb2016-09-12 12:28:54 -070018#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
philipel863a8262016-06-17 09:21:34 -070019#include "webrtc/modules/pacing/paced_sender.h"
20#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
terelius5a388362016-12-09 05:50:01 -080021#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020022#include "webrtc/rtc_base/checks.h"
23#include "webrtc/rtc_base/constructormagic.h"
24#include "webrtc/rtc_base/logging.h"
25#include "webrtc/rtc_base/thread_annotations.h"
Stefan Holmer492ee282016-10-27 17:19:20 +020026#include "webrtc/system_wrappers/include/field_trial.h"
stefan64636dd2016-08-03 00:29:03 -070027#include "webrtc/system_wrappers/include/metrics.h"
philipel863a8262016-06-17 09:21:34 -070028#include "webrtc/typedefs.h"
29
30namespace {
philipel7522a282016-08-16 10:59:36 +020031constexpr int kTimestampGroupLengthMs = 5;
32constexpr int kAbsSendTimeFraction = 18;
33constexpr int kAbsSendTimeInterArrivalUpshift = 8;
34constexpr int kInterArrivalShift =
35 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
36constexpr double kTimestampToMs =
philipel863a8262016-06-17 09:21:34 -070037 1000.0 / static_cast<double>(1 << kInterArrivalShift);
philipel7522a282016-08-16 10:59:36 +020038// This ssrc is used to fulfill the current API but will be removed
39// after the API has been changed.
40constexpr uint32_t kFixedSsrc = 0;
Stefan Holmer492ee282016-10-27 17:19:20 +020041
terelius5a388362016-12-09 05:50:01 -080042// Parameters for linear least squares fit of regression line to noisy data.
stefan76d9c9c2017-04-01 06:51:09 -070043constexpr size_t kDefaultTrendlineWindowSize = 20;
tereliusafaef8b2016-11-17 03:48:18 -080044constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
45constexpr double kDefaultTrendlineThresholdGain = 4.0;
46
stefane3a55672017-02-13 09:08:22 -080047constexpr int kMaxConsecutiveFailedLookups = 5;
48
tereliusbf2c0492017-05-02 01:04:26 -070049const char kBweSparseUpdateExperiment[] = "WebRTC-BweSparseUpdateExperiment";
50
51bool BweSparseUpdateExperimentIsEnabled() {
52 std::string experiment_string =
53 webrtc::field_trial::FindFullName(kBweSparseUpdateExperiment);
54 return experiment_string == "Enabled";
55}
philipel863a8262016-06-17 09:21:34 -070056} // namespace
57
58namespace webrtc {
tereliusafaef8b2016-11-17 03:48:18 -080059
elad.alon61ce37e2017-03-09 07:09:31 -080060DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
stefan76d9c9c2017-04-01 06:51:09 -070061 : event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -080062 clock_(clock),
philipel863a8262016-06-17 09:21:34 -070063 inter_arrival_(),
tereliusafaef8b2016-11-17 03:48:18 -080064 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -080065 detector_(),
philipel7522a282016-08-16 10:59:36 +020066 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -080067 uma_recorded_(false),
philipelf4238f92017-03-28 04:18:02 -070068 probe_bitrate_estimator_(event_log),
tereliusafaef8b2016-11-17 03:48:18 -080069 trendline_window_size_(kDefaultTrendlineWindowSize),
70 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
71 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -080072 consecutive_delayed_feedbacks_(0),
73 last_logged_bitrate_(0),
tereliusbf2c0492017-05-02 01:04:26 -070074 last_logged_state_(BandwidthUsage::kBwNormal),
75 in_sparse_update_experiment_(BweSparseUpdateExperimentIsEnabled()) {
stefan76d9c9c2017-04-01 06:51:09 -070076 LOG(LS_INFO) << "Using Trendline filter for delay change estimation.";
philipel863a8262016-06-17 09:21:34 -070077}
78
nisse76e62b02017-05-31 02:24:52 -070079DelayBasedBwe::~DelayBasedBwe() {}
80
Stefan Holmer280de9e2016-09-30 10:06:51 +020081DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
tschumim3fae6282017-06-11 23:57:17 -070082 const std::vector<PacketFeedback>& packet_feedback_vector,
83 rtc::Optional<uint32_t> acked_bitrate_bps) {
84 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
85 packet_feedback_vector.end(),
86 PacketFeedbackComparator()));
erikvargabf5a2fc2017-06-16 05:02:05 -070087 RTC_DCHECK_RUNS_SERIALIZED(&network_race_);
elad.alonec304f92017-03-08 05:03:53 -080088
stefan80fba252017-04-18 06:45:12 -070089 // TOOD(holmer): An empty feedback vector here likely means that
90 // all acks were too late and that the send time history had
91 // timed out. We should reduce the rate when this occurs.
tschumim3fae6282017-06-11 23:57:17 -070092 if (packet_feedback_vector.empty()) {
stefan80fba252017-04-18 06:45:12 -070093 LOG(LS_WARNING) << "Very late feedback received.";
94 return DelayBasedBwe::Result();
95 }
elad.alonec304f92017-03-08 05:03:53 -080096
stefan64636dd2016-08-03 00:29:03 -070097 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -070098 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
99 BweNames::kSendSideTransportSeqNum,
100 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700101 uma_recorded_ = true;
102 }
michaelt8490f8a2017-04-20 10:10:10 -0700103 bool overusing = false;
stefane3a55672017-02-13 09:08:22 -0800104 bool delayed_feedback = true;
tschumim3fae6282017-06-11 23:57:17 -0700105 for (const auto& packet_feedback : packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800106 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800107 continue;
108 delayed_feedback = false;
michaelt8490f8a2017-04-20 10:10:10 -0700109 IncomingPacketFeedback(packet_feedback);
tereliusbf2c0492017-05-02 01:04:26 -0700110 if (!in_sparse_update_experiment_)
111 overusing |= (detector_.State() == BandwidthUsage::kBwOverusing);
philipel863a8262016-06-17 09:21:34 -0700112 }
tereliusbf2c0492017-05-02 01:04:26 -0700113 if (in_sparse_update_experiment_)
114 overusing = (detector_.State() == BandwidthUsage::kBwOverusing);
stefane3a55672017-02-13 09:08:22 -0800115 if (delayed_feedback) {
116 ++consecutive_delayed_feedbacks_;
michaelt8490f8a2017-04-20 10:10:10 -0700117 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
118 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700119 return OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
michaelt8490f8a2017-04-20 10:10:10 -0700120 }
stefane3a55672017-02-13 09:08:22 -0800121 } else {
122 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700123 return MaybeUpdateEstimate(overusing, acked_bitrate_bps);
stefane3a55672017-02-13 09:08:22 -0800124 }
michaelt8490f8a2017-04-20 10:10:10 -0700125 return Result();
philipel863a8262016-06-17 09:21:34 -0700126}
127
stefane3a55672017-02-13 09:08:22 -0800128DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
129 int64_t arrival_time_ms) {
130 // Estimate should always be valid since a start bitrate always is set in the
131 // Call constructor. An alternative would be to return an empty Result here,
132 // or to estimate the throughput based on the feedback we received.
133 RTC_DCHECK(rate_control_.ValidEstimate());
134 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
135 arrival_time_ms);
136 Result result;
137 result.updated = true;
138 result.probe = false;
139 result.target_bitrate_bps = rate_control_.LatestEstimate();
140 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
141 << result.target_bitrate_bps;
142 return result;
143}
144
michaelt8490f8a2017-04-20 10:10:10 -0700145void DelayBasedBwe::IncomingPacketFeedback(
elad.alonf9490002017-03-06 05:32:21 -0800146 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700147 int64_t now_ms = clock_->TimeInMilliseconds();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200148 // Reset if the stream has timed out.
149 if (last_seen_packet_ms_ == -1 ||
150 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
151 inter_arrival_.reset(
152 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
153 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800154 trendline_estimator_.reset(new TrendlineEstimator(
155 trendline_window_size_, trendline_smoothing_coeff_,
156 trendline_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200157 }
158 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700159
Stefan Holmer280de9e2016-09-30 10:06:51 +0200160 uint32_t send_time_24bits =
161 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800162 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
163 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200164 500) /
165 1000) &
166 0x00FFFFFF;
167 // Shift up send time to use the full 32 bits that inter_arrival works with,
168 // so wrapping works properly.
169 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700170
Stefan Holmer280de9e2016-09-30 10:06:51 +0200171 uint32_t ts_delta = 0;
172 int64_t t_delta = 0;
173 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800174 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
175 now_ms, packet_feedback.payload_size,
176 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200177 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
stefan76d9c9c2017-04-01 06:51:09 -0700178 trendline_estimator_->Update(t_delta, ts_delta_ms,
179 packet_feedback.arrival_time_ms);
180 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
181 trendline_estimator_->num_of_deltas(),
182 packet_feedback.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700183 }
elad.alonf9490002017-03-06 05:32:21 -0800184 if (packet_feedback.pacing_info.probe_cluster_id !=
185 PacedPacketInfo::kNotAProbe) {
michaelt8490f8a2017-04-20 10:10:10 -0700186 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200187 }
michaelt8490f8a2017-04-20 10:10:10 -0700188}
189
tschumim3fae6282017-06-11 23:57:17 -0700190DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
191 bool overusing,
192 rtc::Optional<uint32_t> acked_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700193 Result result;
194 int64_t now_ms = clock_->TimeInMilliseconds();
195
michaelt8490f8a2017-04-20 10:10:10 -0700196 rtc::Optional<int> probe_bitrate_bps =
197 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200198 // Currently overusing the bandwidth.
michaelt8490f8a2017-04-20 10:10:10 -0700199 if (overusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200200 if (acked_bitrate_bps &&
201 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
michaelt8490f8a2017-04-20 10:10:10 -0700202 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
203 &result.target_bitrate_bps);
tereliusa9521e22017-07-04 04:52:58 -0700204 } else if (!acked_bitrate_bps && rate_control_.ValidEstimate() &&
205 rate_control_.TimeToReduceFurther(
206 now_ms, rate_control_.LatestEstimate() / 2 - 1)) {
207 // Overusing before we have a measured acknowledged bitrate. We check
208 // TimeToReduceFurther (with a fake acknowledged bitrate) to avoid
209 // reducing too often.
210 // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator
211 // so that we (almost) always have a bitrate estimate.
212 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, now_ms);
213 result.updated = true;
214 result.probe = false;
215 result.target_bitrate_bps = rate_control_.LatestEstimate();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200216 }
michaelt8490f8a2017-04-20 10:10:10 -0700217 } else {
218 if (probe_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700219 result.probe = true;
terelius37647302017-06-27 07:50:31 -0700220 result.updated = true;
221 result.target_bitrate_bps = *probe_bitrate_bps;
222 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms);
223 } else {
224 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
225 &result.target_bitrate_bps);
michaelt8490f8a2017-04-20 10:10:10 -0700226 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200227 }
terelius5a388362016-12-09 05:50:01 -0800228 if (result.updated) {
terelius5a388362016-12-09 05:50:01 -0800229 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
230 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800231 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
232 detector_.State() != last_logged_state_)) {
terelius424e6cf2017-02-20 05:14:41 -0800233 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800234 detector_.State());
235 last_logged_bitrate_ = result.target_bitrate_bps;
236 last_logged_state_ = detector_.State();
237 }
terelius5a388362016-12-09 05:50:01 -0800238 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200239 return result;
philipel863a8262016-06-17 09:21:34 -0700240}
241
michaelt8490f8a2017-04-20 10:10:10 -0700242bool DelayBasedBwe::UpdateEstimate(int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200243 rtc::Optional<uint32_t> acked_bitrate_bps,
michaelt8490f8a2017-04-20 10:10:10 -0700244 bool overusing,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700245 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800246 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
247 // removed. In the meantime, we set it to zero.
michaelt8490f8a2017-04-20 10:10:10 -0700248 const RateControlInput input(
249 overusing ? BandwidthUsage::kBwOverusing : detector_.State(),
250 acked_bitrate_bps, 0);
terelius37647302017-06-27 07:50:31 -0700251 uint32_t prev_target_bitrate_bps = rate_control_.LatestEstimate();
tereliusd1b0e0e2017-04-03 02:27:08 -0700252 *target_bitrate_bps = rate_control_.Update(&input, now_ms);
terelius37647302017-06-27 07:50:31 -0700253 return rate_control_.ValidEstimate() &&
254 prev_target_bitrate_bps != *target_bitrate_bps;
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700255}
256
philipel863a8262016-06-17 09:21:34 -0700257void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700258 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700259}
260
philipel863a8262016-06-17 09:21:34 -0700261bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
262 uint32_t* bitrate_bps) const {
263 // Currently accessed from both the process thread (see
264 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
265 // Call::GetStats()). Should in the future only be accessed from a single
266 // thread.
267 RTC_DCHECK(ssrcs);
268 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700269 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700270 return false;
philipel7522a282016-08-16 10:59:36 +0200271
272 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700273 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700274 return true;
275}
276
stefan5a2c5062017-01-27 06:43:18 -0800277void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
278 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
279 rate_control_.SetStartBitrate(start_bitrate_bps);
280}
281
philipel863a8262016-06-17 09:21:34 -0700282void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
283 // Called from both the configuration thread and the network thread. Shouldn't
284 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700285 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700286}
minyue78b4d562016-11-30 04:47:39 -0800287
terelius67370452017-04-19 09:15:04 -0700288int64_t DelayBasedBwe::GetExpectedBwePeriodMs() const {
289 return rate_control_.GetExpectedBandwidthPeriodMs();
minyue78b4d562016-11-30 04:47:39 -0800290}
philipel863a8262016-06-17 09:21:34 -0700291} // namespace webrtc