blob: 147f2432b21b7100f5c2b3a138c97fe6db060152 [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
17#include "webrtc/base/checks.h"
18#include "webrtc/base/constructormagic.h"
19#include "webrtc/base/logging.h"
20#include "webrtc/base/thread_annotations.h"
terelius0baf55d2017-02-17 03:38:28 -080021#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
Irfan Sheriffb2540bb2016-09-12 12:28:54 -070022#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
philipel863a8262016-06-17 09:21:34 -070023#include "webrtc/modules/pacing/paced_sender.h"
24#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
terelius5a388362016-12-09 05:50:01 -080025#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.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 network_thread_.DetachFromThread();
78}
79
nisse76e62b02017-05-31 02:24:52 -070080DelayBasedBwe::~DelayBasedBwe() {}
81
Stefan Holmer280de9e2016-09-30 10:06:51 +020082DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
tschumim3fae6282017-06-11 23:57:17 -070083 const std::vector<PacketFeedback>& packet_feedback_vector,
84 rtc::Optional<uint32_t> acked_bitrate_bps) {
85 RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(),
86 packet_feedback_vector.end(),
87 PacketFeedbackComparator()));
philipel863a8262016-06-17 09:21:34 -070088 RTC_DCHECK(network_thread_.CalledOnValidThread());
elad.alonec304f92017-03-08 05:03:53 -080089
stefan80fba252017-04-18 06:45:12 -070090 // TOOD(holmer): An empty feedback vector here likely means that
91 // all acks were too late and that the send time history had
92 // timed out. We should reduce the rate when this occurs.
tschumim3fae6282017-06-11 23:57:17 -070093 if (packet_feedback_vector.empty()) {
stefan80fba252017-04-18 06:45:12 -070094 LOG(LS_WARNING) << "Very late feedback received.";
95 return DelayBasedBwe::Result();
96 }
elad.alonec304f92017-03-08 05:03:53 -080097
stefan64636dd2016-08-03 00:29:03 -070098 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -070099 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
100 BweNames::kSendSideTransportSeqNum,
101 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700102 uma_recorded_ = true;
103 }
michaelt8490f8a2017-04-20 10:10:10 -0700104 bool overusing = false;
stefane3a55672017-02-13 09:08:22 -0800105 bool delayed_feedback = true;
tschumim3fae6282017-06-11 23:57:17 -0700106 for (const auto& packet_feedback : packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800107 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800108 continue;
109 delayed_feedback = false;
michaelt8490f8a2017-04-20 10:10:10 -0700110 IncomingPacketFeedback(packet_feedback);
tereliusbf2c0492017-05-02 01:04:26 -0700111 if (!in_sparse_update_experiment_)
112 overusing |= (detector_.State() == BandwidthUsage::kBwOverusing);
philipel863a8262016-06-17 09:21:34 -0700113 }
tereliusbf2c0492017-05-02 01:04:26 -0700114 if (in_sparse_update_experiment_)
115 overusing = (detector_.State() == BandwidthUsage::kBwOverusing);
stefane3a55672017-02-13 09:08:22 -0800116 if (delayed_feedback) {
117 ++consecutive_delayed_feedbacks_;
michaelt8490f8a2017-04-20 10:10:10 -0700118 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
119 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700120 return OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
michaelt8490f8a2017-04-20 10:10:10 -0700121 }
stefane3a55672017-02-13 09:08:22 -0800122 } else {
123 consecutive_delayed_feedbacks_ = 0;
tschumim3fae6282017-06-11 23:57:17 -0700124 return MaybeUpdateEstimate(overusing, acked_bitrate_bps);
stefane3a55672017-02-13 09:08:22 -0800125 }
michaelt8490f8a2017-04-20 10:10:10 -0700126 return Result();
philipel863a8262016-06-17 09:21:34 -0700127}
128
stefane3a55672017-02-13 09:08:22 -0800129DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
130 int64_t arrival_time_ms) {
131 // Estimate should always be valid since a start bitrate always is set in the
132 // Call constructor. An alternative would be to return an empty Result here,
133 // or to estimate the throughput based on the feedback we received.
134 RTC_DCHECK(rate_control_.ValidEstimate());
135 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
136 arrival_time_ms);
137 Result result;
138 result.updated = true;
139 result.probe = false;
140 result.target_bitrate_bps = rate_control_.LatestEstimate();
141 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
142 << result.target_bitrate_bps;
143 return result;
144}
145
michaelt8490f8a2017-04-20 10:10:10 -0700146void DelayBasedBwe::IncomingPacketFeedback(
elad.alonf9490002017-03-06 05:32:21 -0800147 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700148 int64_t now_ms = clock_->TimeInMilliseconds();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200149 // Reset if the stream has timed out.
150 if (last_seen_packet_ms_ == -1 ||
151 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
152 inter_arrival_.reset(
153 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
154 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800155 trendline_estimator_.reset(new TrendlineEstimator(
156 trendline_window_size_, trendline_smoothing_coeff_,
157 trendline_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200158 }
159 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700160
Stefan Holmer280de9e2016-09-30 10:06:51 +0200161 uint32_t send_time_24bits =
162 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800163 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
164 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200165 500) /
166 1000) &
167 0x00FFFFFF;
168 // Shift up send time to use the full 32 bits that inter_arrival works with,
169 // so wrapping works properly.
170 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700171
Stefan Holmer280de9e2016-09-30 10:06:51 +0200172 uint32_t ts_delta = 0;
173 int64_t t_delta = 0;
174 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800175 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
176 now_ms, packet_feedback.payload_size,
177 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200178 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
stefan76d9c9c2017-04-01 06:51:09 -0700179 trendline_estimator_->Update(t_delta, ts_delta_ms,
180 packet_feedback.arrival_time_ms);
181 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
182 trendline_estimator_->num_of_deltas(),
183 packet_feedback.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700184 }
elad.alonf9490002017-03-06 05:32:21 -0800185 if (packet_feedback.pacing_info.probe_cluster_id !=
186 PacedPacketInfo::kNotAProbe) {
michaelt8490f8a2017-04-20 10:10:10 -0700187 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200188 }
michaelt8490f8a2017-04-20 10:10:10 -0700189}
190
tschumim3fae6282017-06-11 23:57:17 -0700191DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
192 bool overusing,
193 rtc::Optional<uint32_t> acked_bitrate_bps) {
michaelt8490f8a2017-04-20 10:10:10 -0700194 Result result;
195 int64_t now_ms = clock_->TimeInMilliseconds();
196
michaelt8490f8a2017-04-20 10:10:10 -0700197 rtc::Optional<int> probe_bitrate_bps =
198 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200199 // Currently overusing the bandwidth.
michaelt8490f8a2017-04-20 10:10:10 -0700200 if (overusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200201 if (acked_bitrate_bps &&
202 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
michaelt8490f8a2017-04-20 10:10:10 -0700203 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
204 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200205 }
michaelt8490f8a2017-04-20 10:10:10 -0700206 } else {
207 if (probe_bitrate_bps) {
208 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms);
209 result.probe = true;
210 }
211 result.updated = UpdateEstimate(now_ms, acked_bitrate_bps, overusing,
212 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200213 }
terelius5a388362016-12-09 05:50:01 -0800214 if (result.updated) {
terelius5a388362016-12-09 05:50:01 -0800215 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
216 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800217 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
218 detector_.State() != last_logged_state_)) {
terelius424e6cf2017-02-20 05:14:41 -0800219 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800220 detector_.State());
221 last_logged_bitrate_ = result.target_bitrate_bps;
222 last_logged_state_ = detector_.State();
223 }
terelius5a388362016-12-09 05:50:01 -0800224 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200225 return result;
philipel863a8262016-06-17 09:21:34 -0700226}
227
michaelt8490f8a2017-04-20 10:10:10 -0700228bool DelayBasedBwe::UpdateEstimate(int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200229 rtc::Optional<uint32_t> acked_bitrate_bps,
michaelt8490f8a2017-04-20 10:10:10 -0700230 bool overusing,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700231 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800232 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
233 // removed. In the meantime, we set it to zero.
michaelt8490f8a2017-04-20 10:10:10 -0700234 const RateControlInput input(
235 overusing ? BandwidthUsage::kBwOverusing : detector_.State(),
236 acked_bitrate_bps, 0);
tereliusd1b0e0e2017-04-03 02:27:08 -0700237 *target_bitrate_bps = rate_control_.Update(&input, now_ms);
terelius6ed592d2016-10-18 05:55:30 -0700238 return rate_control_.ValidEstimate();
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700239}
240
philipel863a8262016-06-17 09:21:34 -0700241void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700242 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700243}
244
philipel863a8262016-06-17 09:21:34 -0700245bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
246 uint32_t* bitrate_bps) const {
247 // Currently accessed from both the process thread (see
248 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
249 // Call::GetStats()). Should in the future only be accessed from a single
250 // thread.
251 RTC_DCHECK(ssrcs);
252 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700253 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700254 return false;
philipel7522a282016-08-16 10:59:36 +0200255
256 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700257 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700258 return true;
259}
260
stefan5a2c5062017-01-27 06:43:18 -0800261void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
262 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
263 rate_control_.SetStartBitrate(start_bitrate_bps);
264}
265
philipel863a8262016-06-17 09:21:34 -0700266void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
267 // Called from both the configuration thread and the network thread. Shouldn't
268 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700269 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700270}
minyue78b4d562016-11-30 04:47:39 -0800271
terelius67370452017-04-19 09:15:04 -0700272int64_t DelayBasedBwe::GetExpectedBwePeriodMs() const {
273 return rate_control_.GetExpectedBandwidthPeriodMs();
minyue78b4d562016-11-30 04:47:39 -0800274}
philipel863a8262016-06-17 09:21:34 -0700275} // namespace webrtc