blob: af6af76ae77a34b31300ff0f4ffbb950f2fdceb4 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/congestion_controller/delay_based_bwe.h"
philipel863a8262016-06-17 09:21:34 -070012
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
Elad Alon4a87e1c2017-10-03 16:11:34 +020017#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "logging/rtc_event_log/rtc_event_log.h"
19#include "modules/pacing/paced_sender.h"
20#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
21#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/constructormagic.h"
24#include "rtc_base/logging.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020025#include "rtc_base/ptr_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "rtc_base/thread_annotations.h"
27#include "system_wrappers/include/field_trial.h"
28#include "system_wrappers/include/metrics.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020029#include "typedefs.h" // NOLINT(build/include)
philipel863a8262016-06-17 09:21:34 -070030
31namespace {
philipel7522a282016-08-16 10:59:36 +020032constexpr int kTimestampGroupLengthMs = 5;
33constexpr int kAbsSendTimeFraction = 18;
34constexpr int kAbsSendTimeInterArrivalUpshift = 8;
35constexpr int kInterArrivalShift =
36 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
37constexpr double kTimestampToMs =
philipel863a8262016-06-17 09:21:34 -070038 1000.0 / static_cast<double>(1 << kInterArrivalShift);
philipel7522a282016-08-16 10:59:36 +020039// This ssrc is used to fulfill the current API but will be removed
40// after the API has been changed.
41constexpr uint32_t kFixedSsrc = 0;
Stefan Holmer492ee282016-10-27 17:19:20 +020042
terelius5a388362016-12-09 05:50:01 -080043// Parameters for linear least squares fit of regression line to noisy data.
stefan76d9c9c2017-04-01 06:51:09 -070044constexpr size_t kDefaultTrendlineWindowSize = 20;
tereliusafaef8b2016-11-17 03:48:18 -080045constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
46constexpr double kDefaultTrendlineThresholdGain = 4.0;
47
stefane3a55672017-02-13 09:08:22 -080048constexpr int kMaxConsecutiveFailedLookups = 5;
49
tereliusbf2c0492017-05-02 01:04:26 -070050const char kBweSparseUpdateExperiment[] = "WebRTC-BweSparseUpdateExperiment";
Stefan Holmerea00e482017-10-06 08:43:34 +020051const char kBweWindowSizeInPacketsExperiment[] =
52 "WebRTC-BweWindowSizeInPackets";
tereliusbf2c0492017-05-02 01:04:26 -070053
Stefan Holmerea00e482017-10-06 08:43:34 +020054size_t ReadTrendlineFilterWindowSize() {
tereliusbf2c0492017-05-02 01:04:26 -070055 std::string experiment_string =
Stefan Holmerea00e482017-10-06 08:43:34 +020056 webrtc::field_trial::FindFullName(kBweWindowSizeInPacketsExperiment);
57 size_t window_size;
58 int parsed_values =
59 sscanf(experiment_string.c_str(), "Enabled-%zu", &window_size);
60 if (parsed_values == 1) {
61 if (window_size > 1)
62 return window_size;
63 LOG(WARNING) << "Window size must be greater than 1.";
64 }
65 LOG(LS_WARNING) << "Failed to parse parameters for BweTrendlineFilter "
66 "experiment from field trial string. Using default.";
67 return kDefaultTrendlineWindowSize;
tereliusbf2c0492017-05-02 01:04:26 -070068}
philipel863a8262016-06-17 09:21:34 -070069} // namespace
70
71namespace webrtc {
tereliusafaef8b2016-11-17 03:48:18 -080072
terelius3376c842017-07-31 04:23:25 -070073DelayBasedBwe::Result::Result()
74 : updated(false),
75 probe(false),
76 target_bitrate_bps(0),
77 recovered_from_overuse(false) {}
78
79DelayBasedBwe::Result::Result(bool probe, uint32_t target_bitrate_bps)
80 : updated(true),
81 probe(probe),
82 target_bitrate_bps(target_bitrate_bps),
83 recovered_from_overuse(false) {}
84
85DelayBasedBwe::Result::~Result() {}
86
elad.alon61ce37e2017-03-09 07:09:31 -080087DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
stefan76d9c9c2017-04-01 06:51:09 -070088 : event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -080089 clock_(clock),
philipel863a8262016-06-17 09:21:34 -070090 inter_arrival_(),
tereliusafaef8b2016-11-17 03:48:18 -080091 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -080092 detector_(),
philipel7522a282016-08-16 10:59:36 +020093 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -080094 uma_recorded_(false),
philipelf4238f92017-03-28 04:18:02 -070095 probe_bitrate_estimator_(event_log),
Stefan Holmerea00e482017-10-06 08:43:34 +020096 trendline_window_size_(
97 webrtc::field_trial::IsEnabled(kBweWindowSizeInPacketsExperiment)
98 ? ReadTrendlineFilterWindowSize()
99 : kDefaultTrendlineWindowSize),
tereliusafaef8b2016-11-17 03:48:18 -0800100 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
101 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -0800102 consecutive_delayed_feedbacks_(0),
philipel8e560762017-10-02 14:00:13 +0200103 prev_bitrate_(0),
104 prev_state_(BandwidthUsage::kBwNormal),
Stefan Holmerea00e482017-10-06 08:43:34 +0200105 in_sparse_update_experiment_(
106 webrtc::field_trial::IsEnabled(kBweSparseUpdateExperiment)) {
107 LOG(LS_INFO)
108 << "Using Trendline filter for delay change estimation with window size "
109 << trendline_window_size_;
philipel863a8262016-06-17 09:21:34 -0700110}
111
nisse76e62b02017-05-31 02:24:52 -0700112DelayBasedBwe::~DelayBasedBwe() {}
113
Stefan Holmer280de9e2016-09-30 10:06:51 +0200114DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
tschumim3fae6282017-06-11 23:57:17 -0700115 const std::vector<PacketFeedback>& packet_feedback_vector,
116 rtc::Optional<uint32_t> acked_bitrate_bps) {
117 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
118 packet_feedback_vector.end(),
119 PacketFeedbackComparator()));
erikvargabf5a2fc2017-06-16 05:02:05 -0700120 RTC_DCHECK_RUNS_SERIALIZED(&network_race_);
elad.alonec304f92017-03-08 05:03:53 -0800121
stefan80fba252017-04-18 06:45:12 -0700122 // TOOD(holmer): An empty feedback vector here likely means that
123 // all acks were too late and that the send time history had
124 // timed out. We should reduce the rate when this occurs.
tschumim3fae6282017-06-11 23:57:17 -0700125 if (packet_feedback_vector.empty()) {
stefan80fba252017-04-18 06:45:12 -0700126 LOG(LS_WARNING) << "Very late feedback received.";
127 return DelayBasedBwe::Result();
128 }
elad.alonec304f92017-03-08 05:03:53 -0800129
stefan64636dd2016-08-03 00:29:03 -0700130 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700131 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
132 BweNames::kSendSideTransportSeqNum,
133 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700134 uma_recorded_ = true;
135 }
michaelt8490f8a2017-04-20 10:10:10 -0700136 bool overusing = false;
stefane3a55672017-02-13 09:08:22 -0800137 bool delayed_feedback = true;
terelius3376c842017-07-31 04:23:25 -0700138 bool recovered_from_overuse = false;
139 BandwidthUsage prev_detector_state = detector_.State();
tschumim3fae6282017-06-11 23:57:17 -0700140 for (const auto& packet_feedback : packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800141 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800142 continue;
143 delayed_feedback = false;
michaelt8490f8a2017-04-20 10:10:10 -0700144 IncomingPacketFeedback(packet_feedback);
tereliusbf2c0492017-05-02 01:04:26 -0700145 if (!in_sparse_update_experiment_)
146 overusing |= (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700147 if (prev_detector_state == BandwidthUsage::kBwUnderusing &&
148 detector_.State() == BandwidthUsage::kBwNormal) {
149 recovered_from_overuse = true;
150 }
151 prev_detector_state = detector_.State();
philipel863a8262016-06-17 09:21:34 -0700152 }
tereliusbf2c0492017-05-02 01:04:26 -0700153 if (in_sparse_update_experiment_)
154 overusing = (detector_.State() == BandwidthUsage::kBwOverusing);
terelius3376c842017-07-31 04:23:25 -0700155
stefane3a55672017-02-13 09:08:22 -0800156 if (delayed_feedback) {
157 ++consecutive_delayed_feedbacks_;
michaelt8490f8a2017-04-20 10:10:10 -0700158 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
159 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700160 return OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
michaelt8490f8a2017-04-20 10:10:10 -0700161 }
stefane3a55672017-02-13 09:08:22 -0800162 } else {
163 consecutive_delayed_feedbacks_ = 0;
terelius3376c842017-07-31 04:23:25 -0700164 return MaybeUpdateEstimate(overusing, acked_bitrate_bps,
165 recovered_from_overuse);
stefane3a55672017-02-13 09:08:22 -0800166 }
michaelt8490f8a2017-04-20 10:10:10 -0700167 return Result();
philipel863a8262016-06-17 09:21:34 -0700168}
169
stefane3a55672017-02-13 09:08:22 -0800170DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
171 int64_t arrival_time_ms) {
172 // Estimate should always be valid since a start bitrate always is set in the
173 // Call constructor. An alternative would be to return an empty Result here,
174 // or to estimate the throughput based on the feedback we received.
175 RTC_DCHECK(rate_control_.ValidEstimate());
176 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
177 arrival_time_ms);
178 Result result;
179 result.updated = true;
180 result.probe = false;
181 result.target_bitrate_bps = rate_control_.LatestEstimate();
182 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
183 << result.target_bitrate_bps;
184 return result;
185}
186
michaelt8490f8a2017-04-20 10:10:10 -0700187void DelayBasedBwe::IncomingPacketFeedback(
elad.alonf9490002017-03-06 05:32:21 -0800188 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700189 int64_t now_ms = clock_->TimeInMilliseconds();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200190 // Reset if the stream has timed out.
191 if (last_seen_packet_ms_ == -1 ||
192 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
193 inter_arrival_.reset(
194 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
195 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800196 trendline_estimator_.reset(new TrendlineEstimator(
197 trendline_window_size_, trendline_smoothing_coeff_,
198 trendline_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200199 }
200 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700201
Stefan Holmer280de9e2016-09-30 10:06:51 +0200202 uint32_t send_time_24bits =
203 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800204 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
205 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200206 500) /
207 1000) &
208 0x00FFFFFF;
209 // Shift up send time to use the full 32 bits that inter_arrival works with,
210 // so wrapping works properly.
211 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700212
Stefan Holmer280de9e2016-09-30 10:06:51 +0200213 uint32_t ts_delta = 0;
214 int64_t t_delta = 0;
215 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800216 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
217 now_ms, packet_feedback.payload_size,
218 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200219 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
stefan76d9c9c2017-04-01 06:51:09 -0700220 trendline_estimator_->Update(t_delta, ts_delta_ms,
221 packet_feedback.arrival_time_ms);
222 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
223 trendline_estimator_->num_of_deltas(),
224 packet_feedback.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700225 }
elad.alonf9490002017-03-06 05:32:21 -0800226 if (packet_feedback.pacing_info.probe_cluster_id !=
227 PacedPacketInfo::kNotAProbe) {
michaelt8490f8a2017-04-20 10:10:10 -0700228 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200229 }
michaelt8490f8a2017-04-20 10:10:10 -0700230}
231
tschumim3fae6282017-06-11 23:57:17 -0700232DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
233 bool overusing,
terelius3376c842017-07-31 04:23:25 -0700234 rtc::Optional<uint32_t> acked_bitrate_bps,
235 bool recovered_from_overuse) {
michaelt8490f8a2017-04-20 10:10:10 -0700236 Result result;
237 int64_t now_ms = clock_->TimeInMilliseconds();
238
michaelt8490f8a2017-04-20 10:10:10 -0700239 rtc::Optional<int> probe_bitrate_bps =
240 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200241 // Currently overusing the bandwidth.
michaelt8490f8a2017-04-20 10:10:10 -0700242 if (overusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200243 if (acked_bitrate_bps &&
244 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
michaelt8490f8a2017-04-20 10:10:10 -0700245 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
246 &result.target_bitrate_bps);
tereliusa9521e22017-07-04 04:52:58 -0700247 } else if (!acked_bitrate_bps && rate_control_.ValidEstimate() &&
248 rate_control_.TimeToReduceFurther(
249 now_ms, rate_control_.LatestEstimate() / 2 - 1)) {
250 // Overusing before we have a measured acknowledged bitrate. We check
251 // TimeToReduceFurther (with a fake acknowledged bitrate) to avoid
252 // reducing too often.
253 // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator
254 // so that we (almost) always have a bitrate estimate.
255 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, now_ms);
256 result.updated = true;
257 result.probe = false;
258 result.target_bitrate_bps = rate_control_.LatestEstimate();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200259 }
michaelt8490f8a2017-04-20 10:10:10 -0700260 } else {
261 if (probe_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700262 result.probe = true;
terelius37647302017-06-27 07:50:31 -0700263 result.updated = true;
264 result.target_bitrate_bps = *probe_bitrate_bps;
265 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms);
266 } else {
267 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
268 &result.target_bitrate_bps);
terelius3376c842017-07-31 04:23:25 -0700269 result.recovered_from_overuse = recovered_from_overuse;
michaelt8490f8a2017-04-20 10:10:10 -0700270 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200271 }
philipel8e560762017-10-02 14:00:13 +0200272 if ((result.updated && prev_bitrate_ != result.target_bitrate_bps) ||
273 detector_.State() != prev_state_) {
274 uint32_t bitrate_bps =
275 result.updated ? result.target_bitrate_bps : prev_bitrate_;
276
277 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms, bitrate_bps);
278
Elad Alon4a87e1c2017-10-03 16:11:34 +0200279 if (event_log_) {
280 event_log_->Log(rtc::MakeUnique<RtcEventBweUpdateDelayBased>(
281 bitrate_bps, detector_.State()));
282 }
philipel8e560762017-10-02 14:00:13 +0200283
284 prev_bitrate_ = bitrate_bps;
285 prev_state_ = detector_.State();
terelius5a388362016-12-09 05:50:01 -0800286 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200287 return result;
philipel863a8262016-06-17 09:21:34 -0700288}
289
michaelt8490f8a2017-04-20 10:10:10 -0700290bool DelayBasedBwe::UpdateEstimate(int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200291 rtc::Optional<uint32_t> acked_bitrate_bps,
michaelt8490f8a2017-04-20 10:10:10 -0700292 bool overusing,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700293 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800294 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
295 // removed. In the meantime, we set it to zero.
michaelt8490f8a2017-04-20 10:10:10 -0700296 const RateControlInput input(
297 overusing ? BandwidthUsage::kBwOverusing : detector_.State(),
298 acked_bitrate_bps, 0);
terelius37647302017-06-27 07:50:31 -0700299 uint32_t prev_target_bitrate_bps = rate_control_.LatestEstimate();
tereliusd1b0e0e2017-04-03 02:27:08 -0700300 *target_bitrate_bps = rate_control_.Update(&input, now_ms);
terelius37647302017-06-27 07:50:31 -0700301 return rate_control_.ValidEstimate() &&
302 prev_target_bitrate_bps != *target_bitrate_bps;
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700303}
304
philipel863a8262016-06-17 09:21:34 -0700305void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700306 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700307}
308
philipel863a8262016-06-17 09:21:34 -0700309bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
310 uint32_t* bitrate_bps) const {
311 // Currently accessed from both the process thread (see
312 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
313 // Call::GetStats()). Should in the future only be accessed from a single
314 // thread.
315 RTC_DCHECK(ssrcs);
316 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700317 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700318 return false;
philipel7522a282016-08-16 10:59:36 +0200319
320 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700321 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700322 return true;
323}
324
stefan5a2c5062017-01-27 06:43:18 -0800325void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
326 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
327 rate_control_.SetStartBitrate(start_bitrate_bps);
328}
329
philipel863a8262016-06-17 09:21:34 -0700330void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
331 // Called from both the configuration thread and the network thread. Shouldn't
332 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700333 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700334}
minyue78b4d562016-11-30 04:47:39 -0800335
terelius67370452017-04-19 09:15:04 -0700336int64_t DelayBasedBwe::GetExpectedBwePeriodMs() const {
337 return rate_control_.GetExpectedBandwidthPeriodMs();
minyue78b4d562016-11-30 04:47:39 -0800338}
philipel863a8262016-06-17 09:21:34 -0700339} // namespace webrtc