blob: 2ef4463e9147337393f0ad6c3dc0c2cc204a01e1 [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
terelius3376c842017-07-31 04:23:25 -070060DelayBasedBwe::Result::Result()
61 : updated(false),
62 probe(false),
63 target_bitrate_bps(0),
64 recovered_from_overuse(false) {}
65
66DelayBasedBwe::Result::Result(bool probe, uint32_t target_bitrate_bps)
67 : updated(true),
68 probe(probe),
69 target_bitrate_bps(target_bitrate_bps),
70 recovered_from_overuse(false) {}
71
72DelayBasedBwe::Result::~Result() {}
73
elad.alon61ce37e2017-03-09 07:09:31 -080074DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
stefan76d9c9c2017-04-01 06:51:09 -070075 : event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -080076 clock_(clock),
philipel863a8262016-06-17 09:21:34 -070077 inter_arrival_(),
tereliusafaef8b2016-11-17 03:48:18 -080078 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -080079 detector_(),
philipel7522a282016-08-16 10:59:36 +020080 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -080081 uma_recorded_(false),
philipelf4238f92017-03-28 04:18:02 -070082 probe_bitrate_estimator_(event_log),
tereliusafaef8b2016-11-17 03:48:18 -080083 trendline_window_size_(kDefaultTrendlineWindowSize),
84 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
85 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -080086 consecutive_delayed_feedbacks_(0),
87 last_logged_bitrate_(0),
tereliusbf2c0492017-05-02 01:04:26 -070088 last_logged_state_(BandwidthUsage::kBwNormal),
89 in_sparse_update_experiment_(BweSparseUpdateExperimentIsEnabled()) {
stefan76d9c9c2017-04-01 06:51:09 -070090 LOG(LS_INFO) << "Using Trendline filter for delay change estimation.";
philipel863a8262016-06-17 09:21:34 -070091}
92
nisse76e62b02017-05-31 02:24:52 -070093DelayBasedBwe::~DelayBasedBwe() {}
94
Stefan Holmer280de9e2016-09-30 10:06:51 +020095DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
tschumim3fae6282017-06-11 23:57:17 -070096 const std::vector<PacketFeedback>& packet_feedback_vector,
97 rtc::Optional<uint32_t> acked_bitrate_bps) {
98 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
99 packet_feedback_vector.end(),
100 PacketFeedbackComparator()));
erikvargabf5a2fc2017-06-16 05:02:05 -0700101 RTC_DCHECK_RUNS_SERIALIZED(&network_race_);
elad.alonec304f92017-03-08 05:03:53 -0800102
stefan80fba252017-04-18 06:45:12 -0700103 // TOOD(holmer): An empty feedback vector here likely means that
104 // all acks were too late and that the send time history had
105 // timed out. We should reduce the rate when this occurs.
tschumim3fae6282017-06-11 23:57:17 -0700106 if (packet_feedback_vector.empty()) {
stefan80fba252017-04-18 06:45:12 -0700107 LOG(LS_WARNING) << "Very late feedback received.";
108 return DelayBasedBwe::Result();
109 }
elad.alonec304f92017-03-08 05:03:53 -0800110
stefan64636dd2016-08-03 00:29:03 -0700111 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700112 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
113 BweNames::kSendSideTransportSeqNum,
114 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700115 uma_recorded_ = true;
116 }
michaelt8490f8a2017-04-20 10:10:10 -0700117 bool overusing = false;
stefane3a55672017-02-13 09:08:22 -0800118 bool delayed_feedback = true;
terelius3376c842017-07-31 04:23:25 -0700119 bool recovered_from_overuse = false;
120 BandwidthUsage prev_detector_state = detector_.State();
tschumim3fae6282017-06-11 23:57:17 -0700121 for (const auto& packet_feedback : packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800122 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800123 continue;
124 delayed_feedback = false;
michaelt8490f8a2017-04-20 10:10:10 -0700125 IncomingPacketFeedback(packet_feedback);
tereliusbf2c0492017-05-02 01:04:26 -0700126 if (!in_sparse_update_experiment_)
127 overusing |= (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700128 if (prev_detector_state == BandwidthUsage::kBwUnderusing &&
129 detector_.State() == BandwidthUsage::kBwNormal) {
130 recovered_from_overuse = true;
131 }
132 prev_detector_state = detector_.State();
philipel863a8262016-06-17 09:21:34 -0700133 }
tereliusbf2c0492017-05-02 01:04:26 -0700134 if (in_sparse_update_experiment_)
135 overusing = (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700136
stefane3a55672017-02-13 09:08:22 -0800137 if (delayed_feedback) {
138 ++consecutive_delayed_feedbacks_;
michaelt8490f8a2017-04-20 10:10:10 -0700139 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
140 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700141 return OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
michaelt8490f8a2017-04-20 10:10:10 -0700142 }
stefane3a55672017-02-13 09:08:22 -0800143 } else {
144 consecutive_delayed_feedbacks_ = 0;
terelius3376c842017-07-31 04:23:25 -0700145 return MaybeUpdateEstimate(overusing, acked_bitrate_bps,
146 recovered_from_overuse);
stefane3a55672017-02-13 09:08:22 -0800147 }
michaelt8490f8a2017-04-20 10:10:10 -0700148 return Result();
philipel863a8262016-06-17 09:21:34 -0700149}
150
stefane3a55672017-02-13 09:08:22 -0800151DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
152 int64_t arrival_time_ms) {
153 // Estimate should always be valid since a start bitrate always is set in the
154 // Call constructor. An alternative would be to return an empty Result here,
155 // or to estimate the throughput based on the feedback we received.
156 RTC_DCHECK(rate_control_.ValidEstimate());
157 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
158 arrival_time_ms);
159 Result result;
160 result.updated = true;
161 result.probe = false;
162 result.target_bitrate_bps = rate_control_.LatestEstimate();
163 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
164 << result.target_bitrate_bps;
165 return result;
166}
167
michaelt8490f8a2017-04-20 10:10:10 -0700168void DelayBasedBwe::IncomingPacketFeedback(
elad.alonf9490002017-03-06 05:32:21 -0800169 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700170 int64_t now_ms = clock_->TimeInMilliseconds();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200171 // Reset if the stream has timed out.
172 if (last_seen_packet_ms_ == -1 ||
173 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
174 inter_arrival_.reset(
175 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
176 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800177 trendline_estimator_.reset(new TrendlineEstimator(
178 trendline_window_size_, trendline_smoothing_coeff_,
179 trendline_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200180 }
181 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700182
Stefan Holmer280de9e2016-09-30 10:06:51 +0200183 uint32_t send_time_24bits =
184 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800185 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
186 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200187 500) /
188 1000) &
189 0x00FFFFFF;
190 // Shift up send time to use the full 32 bits that inter_arrival works with,
191 // so wrapping works properly.
192 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700193
Stefan Holmer280de9e2016-09-30 10:06:51 +0200194 uint32_t ts_delta = 0;
195 int64_t t_delta = 0;
196 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800197 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
198 now_ms, packet_feedback.payload_size,
199 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200200 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
stefan76d9c9c2017-04-01 06:51:09 -0700201 trendline_estimator_->Update(t_delta, ts_delta_ms,
202 packet_feedback.arrival_time_ms);
203 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
204 trendline_estimator_->num_of_deltas(),
205 packet_feedback.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700206 }
elad.alonf9490002017-03-06 05:32:21 -0800207 if (packet_feedback.pacing_info.probe_cluster_id !=
208 PacedPacketInfo::kNotAProbe) {
michaelt8490f8a2017-04-20 10:10:10 -0700209 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200210 }
michaelt8490f8a2017-04-20 10:10:10 -0700211}
212
tschumim3fae6282017-06-11 23:57:17 -0700213DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
214 bool overusing,
terelius3376c842017-07-31 04:23:25 -0700215 rtc::Optional<uint32_t> acked_bitrate_bps,
216 bool recovered_from_overuse) {
michaelt8490f8a2017-04-20 10:10:10 -0700217 Result result;
218 int64_t now_ms = clock_->TimeInMilliseconds();
219
michaelt8490f8a2017-04-20 10:10:10 -0700220 rtc::Optional<int> probe_bitrate_bps =
221 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200222 // Currently overusing the bandwidth.
michaelt8490f8a2017-04-20 10:10:10 -0700223 if (overusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200224 if (acked_bitrate_bps &&
225 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
michaelt8490f8a2017-04-20 10:10:10 -0700226 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
227 &result.target_bitrate_bps);
tereliusa9521e22017-07-04 04:52:58 -0700228 } else if (!acked_bitrate_bps && rate_control_.ValidEstimate() &&
229 rate_control_.TimeToReduceFurther(
230 now_ms, rate_control_.LatestEstimate() / 2 - 1)) {
231 // Overusing before we have a measured acknowledged bitrate. We check
232 // TimeToReduceFurther (with a fake acknowledged bitrate) to avoid
233 // reducing too often.
234 // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator
235 // so that we (almost) always have a bitrate estimate.
236 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, now_ms);
237 result.updated = true;
238 result.probe = false;
239 result.target_bitrate_bps = rate_control_.LatestEstimate();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200240 }
michaelt8490f8a2017-04-20 10:10:10 -0700241 } else {
242 if (probe_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700243 result.probe = true;
terelius37647302017-06-27 07:50:31 -0700244 result.updated = true;
245 result.target_bitrate_bps = *probe_bitrate_bps;
246 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms);
247 } else {
248 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
249 &result.target_bitrate_bps);
terelius3376c842017-07-31 04:23:25 -0700250 result.recovered_from_overuse = recovered_from_overuse;
michaelt8490f8a2017-04-20 10:10:10 -0700251 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200252 }
terelius5a388362016-12-09 05:50:01 -0800253 if (result.updated) {
terelius5a388362016-12-09 05:50:01 -0800254 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
255 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800256 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
257 detector_.State() != last_logged_state_)) {
terelius424e6cf2017-02-20 05:14:41 -0800258 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800259 detector_.State());
260 last_logged_bitrate_ = result.target_bitrate_bps;
261 last_logged_state_ = detector_.State();
262 }
terelius5a388362016-12-09 05:50:01 -0800263 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200264 return result;
philipel863a8262016-06-17 09:21:34 -0700265}
266
michaelt8490f8a2017-04-20 10:10:10 -0700267bool DelayBasedBwe::UpdateEstimate(int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200268 rtc::Optional<uint32_t> acked_bitrate_bps,
michaelt8490f8a2017-04-20 10:10:10 -0700269 bool overusing,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700270 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800271 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
272 // removed. In the meantime, we set it to zero.
michaelt8490f8a2017-04-20 10:10:10 -0700273 const RateControlInput input(
274 overusing ? BandwidthUsage::kBwOverusing : detector_.State(),
275 acked_bitrate_bps, 0);
terelius37647302017-06-27 07:50:31 -0700276 uint32_t prev_target_bitrate_bps = rate_control_.LatestEstimate();
tereliusd1b0e0e2017-04-03 02:27:08 -0700277 *target_bitrate_bps = rate_control_.Update(&input, now_ms);
terelius37647302017-06-27 07:50:31 -0700278 return rate_control_.ValidEstimate() &&
279 prev_target_bitrate_bps != *target_bitrate_bps;
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700280}
281
philipel863a8262016-06-17 09:21:34 -0700282void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700283 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700284}
285
philipel863a8262016-06-17 09:21:34 -0700286bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
287 uint32_t* bitrate_bps) const {
288 // Currently accessed from both the process thread (see
289 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
290 // Call::GetStats()). Should in the future only be accessed from a single
291 // thread.
292 RTC_DCHECK(ssrcs);
293 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700294 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700295 return false;
philipel7522a282016-08-16 10:59:36 +0200296
297 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700298 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700299 return true;
300}
301
stefan5a2c5062017-01-27 06:43:18 -0800302void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
303 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
304 rate_control_.SetStartBitrate(start_bitrate_bps);
305}
306
philipel863a8262016-06-17 09:21:34 -0700307void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
308 // Called from both the configuration thread and the network thread. Shouldn't
309 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700310 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700311}
minyue78b4d562016-11-30 04:47:39 -0800312
terelius67370452017-04-19 09:15:04 -0700313int64_t DelayBasedBwe::GetExpectedBwePeriodMs() const {
314 return rate_control_.GetExpectedBandwidthPeriodMs();
minyue78b4d562016-11-30 04:47:39 -0800315}
philipel863a8262016-06-17 09:21:34 -0700316} // namespace webrtc