blob: dd59b8a81bea71507294182edfbbdc1ffe4d68e3 [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"
philipel863a8262016-06-17 09:21:34 -070018#include "webrtc/modules/pacing/paced_sender.h"
19#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
terelius5a388362016-12-09 05:50:01 -080020#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020021#include "webrtc/rtc_base/checks.h"
22#include "webrtc/rtc_base/constructormagic.h"
23#include "webrtc/rtc_base/logging.h"
24#include "webrtc/rtc_base/thread_annotations.h"
Stefan Holmer492ee282016-10-27 17:19:20 +020025#include "webrtc/system_wrappers/include/field_trial.h"
stefan64636dd2016-08-03 00:29:03 -070026#include "webrtc/system_wrappers/include/metrics.h"
philipel863a8262016-06-17 09:21:34 -070027#include "webrtc/typedefs.h"
28
29namespace {
philipel7522a282016-08-16 10:59:36 +020030constexpr int kTimestampGroupLengthMs = 5;
31constexpr int kAbsSendTimeFraction = 18;
32constexpr int kAbsSendTimeInterArrivalUpshift = 8;
33constexpr int kInterArrivalShift =
34 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
35constexpr double kTimestampToMs =
philipel863a8262016-06-17 09:21:34 -070036 1000.0 / static_cast<double>(1 << kInterArrivalShift);
philipel7522a282016-08-16 10:59:36 +020037// This ssrc is used to fulfill the current API but will be removed
38// after the API has been changed.
39constexpr uint32_t kFixedSsrc = 0;
Stefan Holmer492ee282016-10-27 17:19:20 +020040
terelius5a388362016-12-09 05:50:01 -080041// Parameters for linear least squares fit of regression line to noisy data.
stefan76d9c9c2017-04-01 06:51:09 -070042constexpr size_t kDefaultTrendlineWindowSize = 20;
tereliusafaef8b2016-11-17 03:48:18 -080043constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
44constexpr double kDefaultTrendlineThresholdGain = 4.0;
45
stefane3a55672017-02-13 09:08:22 -080046constexpr int kMaxConsecutiveFailedLookups = 5;
47
tereliusbf2c0492017-05-02 01:04:26 -070048const char kBweSparseUpdateExperiment[] = "WebRTC-BweSparseUpdateExperiment";
49
50bool BweSparseUpdateExperimentIsEnabled() {
51 std::string experiment_string =
52 webrtc::field_trial::FindFullName(kBweSparseUpdateExperiment);
53 return experiment_string == "Enabled";
54}
philipel863a8262016-06-17 09:21:34 -070055} // namespace
56
57namespace webrtc {
tereliusafaef8b2016-11-17 03:48:18 -080058
terelius3376c842017-07-31 04:23:25 -070059DelayBasedBwe::Result::Result()
60 : updated(false),
61 probe(false),
62 target_bitrate_bps(0),
63 recovered_from_overuse(false) {}
64
65DelayBasedBwe::Result::Result(bool probe, uint32_t target_bitrate_bps)
66 : updated(true),
67 probe(probe),
68 target_bitrate_bps(target_bitrate_bps),
69 recovered_from_overuse(false) {}
70
71DelayBasedBwe::Result::~Result() {}
72
elad.alon61ce37e2017-03-09 07:09:31 -080073DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
stefan76d9c9c2017-04-01 06:51:09 -070074 : event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -080075 clock_(clock),
philipel863a8262016-06-17 09:21:34 -070076 inter_arrival_(),
tereliusafaef8b2016-11-17 03:48:18 -080077 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -080078 detector_(),
philipel7522a282016-08-16 10:59:36 +020079 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -080080 uma_recorded_(false),
philipelf4238f92017-03-28 04:18:02 -070081 probe_bitrate_estimator_(event_log),
tereliusafaef8b2016-11-17 03:48:18 -080082 trendline_window_size_(kDefaultTrendlineWindowSize),
83 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
84 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -080085 consecutive_delayed_feedbacks_(0),
86 last_logged_bitrate_(0),
tereliusbf2c0492017-05-02 01:04:26 -070087 last_logged_state_(BandwidthUsage::kBwNormal),
88 in_sparse_update_experiment_(BweSparseUpdateExperimentIsEnabled()) {
stefan76d9c9c2017-04-01 06:51:09 -070089 LOG(LS_INFO) << "Using Trendline filter for delay change estimation.";
philipel863a8262016-06-17 09:21:34 -070090}
91
nisse76e62b02017-05-31 02:24:52 -070092DelayBasedBwe::~DelayBasedBwe() {}
93
Stefan Holmer280de9e2016-09-30 10:06:51 +020094DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
tschumim3fae6282017-06-11 23:57:17 -070095 const std::vector<PacketFeedback>& packet_feedback_vector,
96 rtc::Optional<uint32_t> acked_bitrate_bps) {
97 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
98 packet_feedback_vector.end(),
99 PacketFeedbackComparator()));
erikvargabf5a2fc2017-06-16 05:02:05 -0700100 RTC_DCHECK_RUNS_SERIALIZED(&network_race_);
elad.alonec304f92017-03-08 05:03:53 -0800101
stefan80fba252017-04-18 06:45:12 -0700102 // TOOD(holmer): An empty feedback vector here likely means that
103 // all acks were too late and that the send time history had
104 // timed out. We should reduce the rate when this occurs.
tschumim3fae6282017-06-11 23:57:17 -0700105 if (packet_feedback_vector.empty()) {
stefan80fba252017-04-18 06:45:12 -0700106 LOG(LS_WARNING) << "Very late feedback received.";
107 return DelayBasedBwe::Result();
108 }
elad.alonec304f92017-03-08 05:03:53 -0800109
stefan64636dd2016-08-03 00:29:03 -0700110 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700111 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
112 BweNames::kSendSideTransportSeqNum,
113 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700114 uma_recorded_ = true;
115 }
michaelt8490f8a2017-04-20 10:10:10 -0700116 bool overusing = false;
stefane3a55672017-02-13 09:08:22 -0800117 bool delayed_feedback = true;
terelius3376c842017-07-31 04:23:25 -0700118 bool recovered_from_overuse = false;
119 BandwidthUsage prev_detector_state = detector_.State();
tschumim3fae6282017-06-11 23:57:17 -0700120 for (const auto& packet_feedback : packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800121 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800122 continue;
123 delayed_feedback = false;
michaelt8490f8a2017-04-20 10:10:10 -0700124 IncomingPacketFeedback(packet_feedback);
tereliusbf2c0492017-05-02 01:04:26 -0700125 if (!in_sparse_update_experiment_)
126 overusing |= (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700127 if (prev_detector_state == BandwidthUsage::kBwUnderusing &&
128 detector_.State() == BandwidthUsage::kBwNormal) {
129 recovered_from_overuse = true;
130 }
131 prev_detector_state = detector_.State();
philipel863a8262016-06-17 09:21:34 -0700132 }
tereliusbf2c0492017-05-02 01:04:26 -0700133 if (in_sparse_update_experiment_)
134 overusing = (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700135
stefane3a55672017-02-13 09:08:22 -0800136 if (delayed_feedback) {
137 ++consecutive_delayed_feedbacks_;
michaelt8490f8a2017-04-20 10:10:10 -0700138 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
139 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700140 return OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
michaelt8490f8a2017-04-20 10:10:10 -0700141 }
stefane3a55672017-02-13 09:08:22 -0800142 } else {
143 consecutive_delayed_feedbacks_ = 0;
terelius3376c842017-07-31 04:23:25 -0700144 return MaybeUpdateEstimate(overusing, acked_bitrate_bps,
145 recovered_from_overuse);
stefane3a55672017-02-13 09:08:22 -0800146 }
michaelt8490f8a2017-04-20 10:10:10 -0700147 return Result();
philipel863a8262016-06-17 09:21:34 -0700148}
149
stefane3a55672017-02-13 09:08:22 -0800150DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
151 int64_t arrival_time_ms) {
152 // Estimate should always be valid since a start bitrate always is set in the
153 // Call constructor. An alternative would be to return an empty Result here,
154 // or to estimate the throughput based on the feedback we received.
155 RTC_DCHECK(rate_control_.ValidEstimate());
156 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
157 arrival_time_ms);
158 Result result;
159 result.updated = true;
160 result.probe = false;
161 result.target_bitrate_bps = rate_control_.LatestEstimate();
162 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
163 << result.target_bitrate_bps;
164 return result;
165}
166
michaelt8490f8a2017-04-20 10:10:10 -0700167void DelayBasedBwe::IncomingPacketFeedback(
elad.alonf9490002017-03-06 05:32:21 -0800168 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700169 int64_t now_ms = clock_->TimeInMilliseconds();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200170 // Reset if the stream has timed out.
171 if (last_seen_packet_ms_ == -1 ||
172 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
173 inter_arrival_.reset(
174 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
175 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800176 trendline_estimator_.reset(new TrendlineEstimator(
177 trendline_window_size_, trendline_smoothing_coeff_,
178 trendline_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200179 }
180 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700181
Stefan Holmer280de9e2016-09-30 10:06:51 +0200182 uint32_t send_time_24bits =
183 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800184 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
185 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200186 500) /
187 1000) &
188 0x00FFFFFF;
189 // Shift up send time to use the full 32 bits that inter_arrival works with,
190 // so wrapping works properly.
191 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700192
Stefan Holmer280de9e2016-09-30 10:06:51 +0200193 uint32_t ts_delta = 0;
194 int64_t t_delta = 0;
195 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800196 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
197 now_ms, packet_feedback.payload_size,
198 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200199 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
stefan76d9c9c2017-04-01 06:51:09 -0700200 trendline_estimator_->Update(t_delta, ts_delta_ms,
201 packet_feedback.arrival_time_ms);
202 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
203 trendline_estimator_->num_of_deltas(),
204 packet_feedback.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700205 }
elad.alonf9490002017-03-06 05:32:21 -0800206 if (packet_feedback.pacing_info.probe_cluster_id !=
207 PacedPacketInfo::kNotAProbe) {
michaelt8490f8a2017-04-20 10:10:10 -0700208 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200209 }
michaelt8490f8a2017-04-20 10:10:10 -0700210}
211
tschumim3fae6282017-06-11 23:57:17 -0700212DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
213 bool overusing,
terelius3376c842017-07-31 04:23:25 -0700214 rtc::Optional<uint32_t> acked_bitrate_bps,
215 bool recovered_from_overuse) {
michaelt8490f8a2017-04-20 10:10:10 -0700216 Result result;
217 int64_t now_ms = clock_->TimeInMilliseconds();
218
michaelt8490f8a2017-04-20 10:10:10 -0700219 rtc::Optional<int> probe_bitrate_bps =
220 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200221 // Currently overusing the bandwidth.
michaelt8490f8a2017-04-20 10:10:10 -0700222 if (overusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200223 if (acked_bitrate_bps &&
224 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
michaelt8490f8a2017-04-20 10:10:10 -0700225 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
226 &result.target_bitrate_bps);
tereliusa9521e22017-07-04 04:52:58 -0700227 } else if (!acked_bitrate_bps && rate_control_.ValidEstimate() &&
228 rate_control_.TimeToReduceFurther(
229 now_ms, rate_control_.LatestEstimate() / 2 - 1)) {
230 // Overusing before we have a measured acknowledged bitrate. We check
231 // TimeToReduceFurther (with a fake acknowledged bitrate) to avoid
232 // reducing too often.
233 // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator
234 // so that we (almost) always have a bitrate estimate.
235 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, now_ms);
236 result.updated = true;
237 result.probe = false;
238 result.target_bitrate_bps = rate_control_.LatestEstimate();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200239 }
michaelt8490f8a2017-04-20 10:10:10 -0700240 } else {
241 if (probe_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700242 result.probe = true;
terelius37647302017-06-27 07:50:31 -0700243 result.updated = true;
244 result.target_bitrate_bps = *probe_bitrate_bps;
245 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms);
246 } else {
247 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
248 &result.target_bitrate_bps);
terelius3376c842017-07-31 04:23:25 -0700249 result.recovered_from_overuse = recovered_from_overuse;
michaelt8490f8a2017-04-20 10:10:10 -0700250 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200251 }
terelius5a388362016-12-09 05:50:01 -0800252 if (result.updated) {
terelius5a388362016-12-09 05:50:01 -0800253 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
254 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800255 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
256 detector_.State() != last_logged_state_)) {
terelius424e6cf2017-02-20 05:14:41 -0800257 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800258 detector_.State());
259 last_logged_bitrate_ = result.target_bitrate_bps;
260 last_logged_state_ = detector_.State();
261 }
terelius5a388362016-12-09 05:50:01 -0800262 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200263 return result;
philipel863a8262016-06-17 09:21:34 -0700264}
265
michaelt8490f8a2017-04-20 10:10:10 -0700266bool DelayBasedBwe::UpdateEstimate(int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200267 rtc::Optional<uint32_t> acked_bitrate_bps,
michaelt8490f8a2017-04-20 10:10:10 -0700268 bool overusing,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700269 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800270 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
271 // removed. In the meantime, we set it to zero.
michaelt8490f8a2017-04-20 10:10:10 -0700272 const RateControlInput input(
273 overusing ? BandwidthUsage::kBwOverusing : detector_.State(),
274 acked_bitrate_bps, 0);
terelius37647302017-06-27 07:50:31 -0700275 uint32_t prev_target_bitrate_bps = rate_control_.LatestEstimate();
tereliusd1b0e0e2017-04-03 02:27:08 -0700276 *target_bitrate_bps = rate_control_.Update(&input, now_ms);
terelius37647302017-06-27 07:50:31 -0700277 return rate_control_.ValidEstimate() &&
278 prev_target_bitrate_bps != *target_bitrate_bps;
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700279}
280
philipel863a8262016-06-17 09:21:34 -0700281void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700282 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700283}
284
philipel863a8262016-06-17 09:21:34 -0700285bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
286 uint32_t* bitrate_bps) const {
287 // Currently accessed from both the process thread (see
288 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
289 // Call::GetStats()). Should in the future only be accessed from a single
290 // thread.
291 RTC_DCHECK(ssrcs);
292 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700293 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700294 return false;
philipel7522a282016-08-16 10:59:36 +0200295
296 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700297 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700298 return true;
299}
300
stefan5a2c5062017-01-27 06:43:18 -0800301void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
302 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
303 rate_control_.SetStartBitrate(start_bitrate_bps);
304}
305
philipel863a8262016-06-17 09:21:34 -0700306void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
307 // Called from both the configuration thread and the network thread. Shouldn't
308 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700309 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700310}
minyue78b4d562016-11-30 04:47:39 -0800311
terelius67370452017-04-19 09:15:04 -0700312int64_t DelayBasedBwe::GetExpectedBwePeriodMs() const {
313 return rate_control_.GetExpectedBandwidthPeriodMs();
minyue78b4d562016-11-30 04:47:39 -0800314}
philipel863a8262016-06-17 09:21:34 -0700315} // namespace webrtc