blob: e8d9d21050f21d1b931999b758979b95ec953bcb [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 +020041constexpr int kInitialRateWindowMs = 500;
42constexpr int kRateWindowMs = 150;
43
terelius5a388362016-12-09 05:50:01 -080044// Parameters for linear least squares fit of regression line to noisy data.
lliuu029f7cc2017-03-31 14:17:42 -070045constexpr size_t kDefaultTrendlineWindowSize = 15;
tereliusafaef8b2016-11-17 03:48:18 -080046constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
47constexpr double kDefaultTrendlineThresholdGain = 4.0;
48
lliuu029f7cc2017-03-31 14:17:42 -070049// Parameters for Theil-Sen robust fitting of line to noisy data.
50constexpr size_t kDefaultMedianSlopeWindowSize = 20;
51constexpr double kDefaultMedianSlopeThresholdGain = 4.0;
52
stefane3a55672017-02-13 09:08:22 -080053constexpr int kMaxConsecutiveFailedLookups = 5;
54
lliuu029f7cc2017-03-31 14:17:42 -070055const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate";
56const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter";
57const char kBweMedianSlopeFilterExperiment[] = "WebRTC-BweMedianSlopeFilter";
58
59bool BitrateEstimateExperimentIsEnabled() {
60 return webrtc::field_trial::IsEnabled(kBitrateEstimateExperiment);
61}
62
63bool TrendlineFilterExperimentIsEnabled() {
64 std::string experiment_string =
65 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
66 // The experiment is enabled iff the field trial string begins with "Enabled".
67 return experiment_string.find("Enabled") == 0;
68}
69
70bool MedianSlopeFilterExperimentIsEnabled() {
71 std::string experiment_string =
72 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
73 // The experiment is enabled iff the field trial string begins with "Enabled".
74 return experiment_string.find("Enabled") == 0;
75}
76
77bool ReadTrendlineFilterExperimentParameters(size_t* window_size,
78 double* smoothing_coef,
79 double* threshold_gain) {
80 RTC_DCHECK(TrendlineFilterExperimentIsEnabled());
81 RTC_DCHECK(!MedianSlopeFilterExperimentIsEnabled());
82 RTC_DCHECK(window_size != nullptr);
83 RTC_DCHECK(smoothing_coef != nullptr);
84 RTC_DCHECK(threshold_gain != nullptr);
85 std::string experiment_string =
86 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
87 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf,%lf",
88 window_size, smoothing_coef, threshold_gain);
89 if (parsed_values == 3) {
90 RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
91 RTC_CHECK(0 <= *smoothing_coef && *smoothing_coef <= 1)
92 << "Coefficient needs to be between 0 and 1 for weighted average.";
93 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
94 return true;
95 }
96 LOG(LS_WARNING) << "Failed to parse parameters for BweTrendlineFilter "
97 "experiment from field trial string. Using default.";
98 *window_size = kDefaultTrendlineWindowSize;
99 *smoothing_coef = kDefaultTrendlineSmoothingCoeff;
100 *threshold_gain = kDefaultTrendlineThresholdGain;
101 return false;
102}
103
104bool ReadMedianSlopeFilterExperimentParameters(size_t* window_size,
105 double* threshold_gain) {
106 RTC_DCHECK(!TrendlineFilterExperimentIsEnabled());
107 RTC_DCHECK(MedianSlopeFilterExperimentIsEnabled());
108 RTC_DCHECK(window_size != nullptr);
109 RTC_DCHECK(threshold_gain != nullptr);
110 std::string experiment_string =
111 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
112 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf",
113 window_size, threshold_gain);
114 if (parsed_values == 2) {
115 RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
116 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
117 return true;
118 }
119 LOG(LS_WARNING) << "Failed to parse parameters for BweMedianSlopeFilter "
120 "experiment from field trial string. Using default.";
121 *window_size = kDefaultMedianSlopeWindowSize;
122 *threshold_gain = kDefaultMedianSlopeThresholdGain;
123 return false;
124}
elad.alonec304f92017-03-08 05:03:53 -0800125
126class PacketFeedbackComparator {
127 public:
128 inline bool operator()(const webrtc::PacketFeedback& lhs,
129 const webrtc::PacketFeedback& rhs) {
130 if (lhs.arrival_time_ms != rhs.arrival_time_ms)
131 return lhs.arrival_time_ms < rhs.arrival_time_ms;
132 if (lhs.send_time_ms != rhs.send_time_ms)
133 return lhs.send_time_ms < rhs.send_time_ms;
134 return lhs.sequence_number < rhs.sequence_number;
135 }
136};
137
138void SortPacketFeedbackVector(const std::vector<webrtc::PacketFeedback>& input,
139 std::vector<webrtc::PacketFeedback>* output) {
140 auto pred = [](const webrtc::PacketFeedback& packet_feedback) {
141 return packet_feedback.arrival_time_ms !=
142 webrtc::PacketFeedback::kNotReceived;
143 };
144 std::copy_if(input.begin(), input.end(), std::back_inserter(*output), pred);
145 std::sort(output->begin(), output->end(), PacketFeedbackComparator());
146}
philipel863a8262016-06-17 09:21:34 -0700147} // namespace
148
149namespace webrtc {
tereliusafaef8b2016-11-17 03:48:18 -0800150
Stefan Holmer492ee282016-10-27 17:19:20 +0200151DelayBasedBwe::BitrateEstimator::BitrateEstimator()
152 : sum_(0),
153 current_win_ms_(0),
154 prev_time_ms_(-1),
155 bitrate_estimate_(-1.0f),
lliuu029f7cc2017-03-31 14:17:42 -0700156 bitrate_estimate_var_(50.0f),
157 old_estimator_(kBitrateWindowMs, 8000),
158 in_experiment_(BitrateEstimateExperimentIsEnabled()) {}
Stefan Holmer492ee282016-10-27 17:19:20 +0200159
160void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) {
lliuu029f7cc2017-03-31 14:17:42 -0700161 if (!in_experiment_) {
162 old_estimator_.Update(bytes, now_ms);
163 rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms);
164 bitrate_estimate_ = -1.0f;
165 if (rate)
166 bitrate_estimate_ = *rate / 1000.0f;
167 return;
168 }
Stefan Holmer492ee282016-10-27 17:19:20 +0200169 int rate_window_ms = kRateWindowMs;
170 // We use a larger window at the beginning to get a more stable sample that
171 // we can use to initialize the estimate.
172 if (bitrate_estimate_ < 0.f)
173 rate_window_ms = kInitialRateWindowMs;
174 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms);
175 if (bitrate_sample < 0.0f)
176 return;
177 if (bitrate_estimate_ < 0.0f) {
178 // This is the very first sample we get. Use it to initialize the estimate.
179 bitrate_estimate_ = bitrate_sample;
180 return;
181 }
182 // Define the sample uncertainty as a function of how far away it is from the
183 // current estimate.
184 float sample_uncertainty =
185 10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_;
186 float sample_var = sample_uncertainty * sample_uncertainty;
187 // Update a bayesian estimate of the rate, weighting it lower if the sample
188 // uncertainty is large.
189 // The bitrate estimate uncertainty is increased with each update to model
190 // that the bitrate changes over time.
191 float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f;
192 bitrate_estimate_ = (sample_var * bitrate_estimate_ +
193 pred_bitrate_estimate_var * bitrate_sample) /
194 (sample_var + pred_bitrate_estimate_var);
195 bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var /
196 (sample_var + pred_bitrate_estimate_var);
197}
198
199float DelayBasedBwe::BitrateEstimator::UpdateWindow(int64_t now_ms,
200 int bytes,
201 int rate_window_ms) {
202 // Reset if time moves backwards.
203 if (now_ms < prev_time_ms_) {
204 prev_time_ms_ = -1;
205 sum_ = 0;
206 current_win_ms_ = 0;
207 }
208 if (prev_time_ms_ >= 0) {
209 current_win_ms_ += now_ms - prev_time_ms_;
210 // Reset if nothing has been received for more than a full window.
211 if (now_ms - prev_time_ms_ > rate_window_ms) {
212 sum_ = 0;
213 current_win_ms_ %= rate_window_ms;
214 }
215 }
216 prev_time_ms_ = now_ms;
217 float bitrate_sample = -1.0f;
218 if (current_win_ms_ >= rate_window_ms) {
219 bitrate_sample = 8.0f * sum_ / static_cast<float>(rate_window_ms);
220 current_win_ms_ -= rate_window_ms;
221 sum_ = 0;
222 }
223 sum_ += bytes;
224 return bitrate_sample;
225}
226
227rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const {
228 if (bitrate_estimate_ < 0.f)
229 return rtc::Optional<uint32_t>();
230 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000);
231}
philipel863a8262016-06-17 09:21:34 -0700232
elad.alon61ce37e2017-03-09 07:09:31 -0800233DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock)
lliuu029f7cc2017-03-31 14:17:42 -0700234 : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()),
235 in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()),
236 event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -0800237 clock_(clock),
philipel863a8262016-06-17 09:21:34 -0700238 inter_arrival_(),
lliuu029f7cc2017-03-31 14:17:42 -0700239 kalman_estimator_(),
tereliusafaef8b2016-11-17 03:48:18 -0800240 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -0800241 detector_(),
Stefan Holmer492ee282016-10-27 17:19:20 +0200242 receiver_incoming_bitrate_(),
philipel863a8262016-06-17 09:21:34 -0700243 last_update_ms_(-1),
philipel7522a282016-08-16 10:59:36 +0200244 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -0800245 uma_recorded_(false),
philipelf4238f92017-03-28 04:18:02 -0700246 probe_bitrate_estimator_(event_log),
tereliusafaef8b2016-11-17 03:48:18 -0800247 trendline_window_size_(kDefaultTrendlineWindowSize),
248 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
249 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius5a388362016-12-09 05:50:01 -0800250 probing_interval_estimator_(&rate_control_),
lliuu029f7cc2017-03-31 14:17:42 -0700251 median_slope_window_size_(kDefaultMedianSlopeWindowSize),
252 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -0800253 consecutive_delayed_feedbacks_(0),
254 last_logged_bitrate_(0),
255 last_logged_state_(kBwNormal) {
lliuu029f7cc2017-03-31 14:17:42 -0700256 if (in_trendline_experiment_) {
257 ReadTrendlineFilterExperimentParameters(&trendline_window_size_,
258 &trendline_smoothing_coeff_,
259 &trendline_threshold_gain_);
260 LOG(LS_INFO) << "Trendline filter experiment enabled with parameters "
261 << trendline_window_size_ << ',' << trendline_smoothing_coeff_
262 << ',' << trendline_threshold_gain_;
263 }
264 if (in_median_slope_experiment_) {
265 ReadMedianSlopeFilterExperimentParameters(&median_slope_window_size_,
266 &median_slope_threshold_gain_);
267 LOG(LS_INFO) << "Median-slope filter experiment enabled with parameters "
268 << median_slope_window_size_ << ','
269 << median_slope_threshold_gain_;
270 }
271 if (!in_trendline_experiment_ && !in_median_slope_experiment_) {
272 LOG(LS_INFO) << "No overuse experiment enabled. Using Kalman filter.";
273 }
terelius5a388362016-12-09 05:50:01 -0800274
philipel863a8262016-06-17 09:21:34 -0700275 network_thread_.DetachFromThread();
276}
277
Stefan Holmer280de9e2016-09-30 10:06:51 +0200278DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
elad.alonf9490002017-03-06 05:32:21 -0800279 const std::vector<PacketFeedback>& packet_feedback_vector) {
philipel863a8262016-06-17 09:21:34 -0700280 RTC_DCHECK(network_thread_.CalledOnValidThread());
stefandd200542017-03-17 06:19:11 -0700281 RTC_DCHECK(!packet_feedback_vector.empty());
elad.alonec304f92017-03-08 05:03:53 -0800282
283 std::vector<PacketFeedback> sorted_packet_feedback_vector;
284 SortPacketFeedbackVector(packet_feedback_vector,
285 &sorted_packet_feedback_vector);
286
stefan64636dd2016-08-03 00:29:03 -0700287 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700288 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
289 BweNames::kSendSideTransportSeqNum,
290 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700291 uma_recorded_ = true;
292 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200293 Result aggregated_result;
stefane3a55672017-02-13 09:08:22 -0800294 bool delayed_feedback = true;
elad.alonec304f92017-03-08 05:03:53 -0800295 for (const auto& packet_feedback : sorted_packet_feedback_vector) {
elad.alonf9490002017-03-06 05:32:21 -0800296 if (packet_feedback.send_time_ms < 0)
stefane3a55672017-02-13 09:08:22 -0800297 continue;
298 delayed_feedback = false;
elad.alonf9490002017-03-06 05:32:21 -0800299 Result result = IncomingPacketFeedback(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200300 if (result.updated)
301 aggregated_result = result;
philipel863a8262016-06-17 09:21:34 -0700302 }
stefane3a55672017-02-13 09:08:22 -0800303 if (delayed_feedback) {
304 ++consecutive_delayed_feedbacks_;
305 } else {
306 consecutive_delayed_feedbacks_ = 0;
307 }
308 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
elad.alonec304f92017-03-08 05:03:53 -0800309 aggregated_result = OnLongFeedbackDelay(
310 sorted_packet_feedback_vector.back().arrival_time_ms);
stefane3a55672017-02-13 09:08:22 -0800311 consecutive_delayed_feedbacks_ = 0;
312 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200313 return aggregated_result;
philipel863a8262016-06-17 09:21:34 -0700314}
315
stefane3a55672017-02-13 09:08:22 -0800316DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
317 int64_t arrival_time_ms) {
318 // Estimate should always be valid since a start bitrate always is set in the
319 // Call constructor. An alternative would be to return an empty Result here,
320 // or to estimate the throughput based on the feedback we received.
321 RTC_DCHECK(rate_control_.ValidEstimate());
322 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
323 arrival_time_ms);
324 Result result;
325 result.updated = true;
326 result.probe = false;
327 result.target_bitrate_bps = rate_control_.LatestEstimate();
328 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
329 << result.target_bitrate_bps;
330 return result;
331}
332
elad.alonf9490002017-03-06 05:32:21 -0800333DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedback(
334 const PacketFeedback& packet_feedback) {
stefan5e12d362016-07-11 01:44:02 -0700335 int64_t now_ms = clock_->TimeInMilliseconds();
philipel863a8262016-06-17 09:21:34 -0700336
elad.alonf9490002017-03-06 05:32:21 -0800337 receiver_incoming_bitrate_.Update(packet_feedback.arrival_time_ms,
338 packet_feedback.payload_size);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200339 Result result;
340 // Reset if the stream has timed out.
341 if (last_seen_packet_ms_ == -1 ||
342 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
343 inter_arrival_.reset(
344 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
345 kTimestampToMs, true));
lliuu029f7cc2017-03-31 14:17:42 -0700346 kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
tereliusafaef8b2016-11-17 03:48:18 -0800347 trendline_estimator_.reset(new TrendlineEstimator(
348 trendline_window_size_, trendline_smoothing_coeff_,
349 trendline_threshold_gain_));
lliuu029f7cc2017-03-31 14:17:42 -0700350 median_slope_estimator_.reset(new MedianSlopeEstimator(
351 median_slope_window_size_, median_slope_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200352 }
353 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700354
Stefan Holmer280de9e2016-09-30 10:06:51 +0200355 uint32_t send_time_24bits =
356 static_cast<uint32_t>(
elad.alonf9490002017-03-06 05:32:21 -0800357 ((static_cast<uint64_t>(packet_feedback.send_time_ms)
358 << kAbsSendTimeFraction) +
Stefan Holmer280de9e2016-09-30 10:06:51 +0200359 500) /
360 1000) &
361 0x00FFFFFF;
362 // Shift up send time to use the full 32 bits that inter_arrival works with,
363 // so wrapping works properly.
364 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700365
Stefan Holmer280de9e2016-09-30 10:06:51 +0200366 uint32_t ts_delta = 0;
367 int64_t t_delta = 0;
368 int size_delta = 0;
elad.alonf9490002017-03-06 05:32:21 -0800369 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms,
370 now_ms, packet_feedback.payload_size,
371 &ts_delta, &t_delta, &size_delta)) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200372 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
lliuu029f7cc2017-03-31 14:17:42 -0700373 if (in_trendline_experiment_) {
374 trendline_estimator_->Update(t_delta, ts_delta_ms,
375 packet_feedback.arrival_time_ms);
376 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
377 trendline_estimator_->num_of_deltas(),
378 packet_feedback.arrival_time_ms);
379 } else if (in_median_slope_experiment_) {
380 median_slope_estimator_->Update(t_delta, ts_delta_ms,
381 packet_feedback.arrival_time_ms);
382 detector_.Detect(median_slope_estimator_->trendline_slope(), ts_delta_ms,
383 median_slope_estimator_->num_of_deltas(),
384 packet_feedback.arrival_time_ms);
385 } else {
386 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta,
387 detector_.State(),
388 packet_feedback.arrival_time_ms);
389 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms,
390 kalman_estimator_->num_of_deltas(),
391 packet_feedback.arrival_time_ms);
392 }
stefan5ec85fb2016-09-29 04:19:38 -0700393 }
394
Stefan Holmer280de9e2016-09-30 10:06:51 +0200395 int probing_bps = 0;
elad.alonf9490002017-03-06 05:32:21 -0800396 if (packet_feedback.pacing_info.probe_cluster_id !=
397 PacedPacketInfo::kNotAProbe) {
398 probing_bps =
399 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200400 }
Stefan Holmer492ee282016-10-27 17:19:20 +0200401 rtc::Optional<uint32_t> acked_bitrate_bps =
402 receiver_incoming_bitrate_.bitrate_bps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200403 // Currently overusing the bandwidth.
404 if (detector_.State() == kBwOverusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200405 if (acked_bitrate_bps &&
406 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
407 result.updated =
elad.alonf9490002017-03-06 05:32:21 -0800408 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms,
409 acked_bitrate_bps, &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200410 }
411 } else if (probing_bps > 0) {
412 // No overuse, but probing measured a bitrate.
elad.alonf9490002017-03-06 05:32:21 -0800413 rate_control_.SetEstimate(probing_bps, packet_feedback.arrival_time_ms);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200414 result.probe = true;
Stefan Holmer492ee282016-10-27 17:19:20 +0200415 result.updated =
elad.alonf9490002017-03-06 05:32:21 -0800416 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms,
417 acked_bitrate_bps, &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200418 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200419 if (!result.updated &&
420 (last_update_ms_ == -1 ||
terelius6ed592d2016-10-18 05:55:30 -0700421 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200422 result.updated =
elad.alonf9490002017-03-06 05:32:21 -0800423 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms,
424 acked_bitrate_bps, &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200425 }
terelius5a388362016-12-09 05:50:01 -0800426 if (result.updated) {
stefan5ec85fb2016-09-29 04:19:38 -0700427 last_update_ms_ = now_ms;
terelius5a388362016-12-09 05:50:01 -0800428 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
429 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800430 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
431 detector_.State() != last_logged_state_)) {
terelius424e6cf2017-02-20 05:14:41 -0800432 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800433 detector_.State());
434 last_logged_bitrate_ = result.target_bitrate_bps;
435 last_logged_state_ = detector_.State();
436 }
terelius5a388362016-12-09 05:50:01 -0800437 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200438
439 return result;
philipel863a8262016-06-17 09:21:34 -0700440}
441
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700442bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
443 int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200444 rtc::Optional<uint32_t> acked_bitrate_bps,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700445 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800446 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
447 // removed. In the meantime, we set it to zero.
448 const RateControlInput input(detector_.State(), acked_bitrate_bps, 0);
terelius6ed592d2016-10-18 05:55:30 -0700449 rate_control_.Update(&input, now_ms);
450 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms);
451 return rate_control_.ValidEstimate();
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700452}
453
philipel863a8262016-06-17 09:21:34 -0700454void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700455 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700456}
457
philipel863a8262016-06-17 09:21:34 -0700458bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
459 uint32_t* bitrate_bps) const {
460 // Currently accessed from both the process thread (see
461 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
462 // Call::GetStats()). Should in the future only be accessed from a single
463 // thread.
464 RTC_DCHECK(ssrcs);
465 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700466 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700467 return false;
philipel7522a282016-08-16 10:59:36 +0200468
469 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700470 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700471 return true;
472}
473
stefan5a2c5062017-01-27 06:43:18 -0800474void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
475 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
476 rate_control_.SetStartBitrate(start_bitrate_bps);
477}
478
philipel863a8262016-06-17 09:21:34 -0700479void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
480 // Called from both the configuration thread and the network thread. Shouldn't
481 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700482 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700483}
minyue78b4d562016-11-30 04:47:39 -0800484
485int64_t DelayBasedBwe::GetProbingIntervalMs() const {
486 return probing_interval_estimator_.GetIntervalMs();
487}
philipel863a8262016-06-17 09:21:34 -0700488} // namespace webrtc