blob: b89daab7d1b950036d6cecee2a6fa3b2f567bce7 [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.
tereliusafaef8b2016-11-17 03:48:18 -080045constexpr size_t kDefaultTrendlineWindowSize = 15;
46constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
47constexpr double kDefaultTrendlineThresholdGain = 4.0;
48
terelius5a388362016-12-09 05:50:01 -080049// 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
Stefan Holmer492ee282016-10-27 17:19:20 +020055const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate";
tereliusafaef8b2016-11-17 03:48:18 -080056const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter";
terelius5a388362016-12-09 05:50:01 -080057const char kBweMedianSlopeFilterExperiment[] = "WebRTC-BweMedianSlopeFilter";
Stefan Holmer492ee282016-10-27 17:19:20 +020058
59bool BitrateEstimateExperimentIsEnabled() {
60 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) ==
61 "Enabled";
62}
tereliusafaef8b2016-11-17 03:48:18 -080063
64bool TrendlineFilterExperimentIsEnabled() {
65 std::string experiment_string =
66 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
67 // The experiment is enabled iff the field trial string begins with "Enabled".
68 return experiment_string.find("Enabled") == 0;
69}
70
terelius5a388362016-12-09 05:50:01 -080071bool MedianSlopeFilterExperimentIsEnabled() {
72 std::string experiment_string =
73 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
74 // The experiment is enabled iff the field trial string begins with "Enabled".
75 return experiment_string.find("Enabled") == 0;
76}
77
78bool ReadTrendlineFilterExperimentParameters(size_t* window_size,
tereliusafaef8b2016-11-17 03:48:18 -080079 double* smoothing_coef,
80 double* threshold_gain) {
81 RTC_DCHECK(TrendlineFilterExperimentIsEnabled());
terelius5a388362016-12-09 05:50:01 -080082 RTC_DCHECK(!MedianSlopeFilterExperimentIsEnabled());
83 RTC_DCHECK(window_size != nullptr);
84 RTC_DCHECK(smoothing_coef != nullptr);
85 RTC_DCHECK(threshold_gain != nullptr);
tereliusafaef8b2016-11-17 03:48:18 -080086 std::string experiment_string =
87 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
88 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf,%lf",
terelius5a388362016-12-09 05:50:01 -080089 window_size, smoothing_coef, threshold_gain);
tereliusafaef8b2016-11-17 03:48:18 -080090 if (parsed_values == 3) {
terelius5a388362016-12-09 05:50:01 -080091 RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
tereliusafaef8b2016-11-17 03:48:18 -080092 RTC_CHECK(0 <= *smoothing_coef && *smoothing_coef <= 1)
93 << "Coefficient needs to be between 0 and 1 for weighted average.";
94 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
95 return true;
96 }
97 LOG(LS_WARNING) << "Failed to parse parameters for BweTrendlineFilter "
98 "experiment from field trial string. Using default.";
terelius5a388362016-12-09 05:50:01 -080099 *window_size = kDefaultTrendlineWindowSize;
tereliusafaef8b2016-11-17 03:48:18 -0800100 *smoothing_coef = kDefaultTrendlineSmoothingCoeff;
101 *threshold_gain = kDefaultTrendlineThresholdGain;
102 return false;
103}
104
terelius5a388362016-12-09 05:50:01 -0800105bool ReadMedianSlopeFilterExperimentParameters(size_t* window_size,
106 double* threshold_gain) {
107 RTC_DCHECK(!TrendlineFilterExperimentIsEnabled());
108 RTC_DCHECK(MedianSlopeFilterExperimentIsEnabled());
109 RTC_DCHECK(window_size != nullptr);
110 RTC_DCHECK(threshold_gain != nullptr);
111 std::string experiment_string =
112 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment);
113 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf",
114 window_size, threshold_gain);
115 if (parsed_values == 2) {
116 RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line.";
117 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive.";
118 return true;
119 }
120 LOG(LS_WARNING) << "Failed to parse parameters for BweMedianSlopeFilter "
121 "experiment from field trial string. Using default.";
122 *window_size = kDefaultMedianSlopeWindowSize;
123 *threshold_gain = kDefaultMedianSlopeThresholdGain;
124 return false;
125}
philipel863a8262016-06-17 09:21:34 -0700126} // namespace
127
128namespace webrtc {
tereliusafaef8b2016-11-17 03:48:18 -0800129
Stefan Holmer492ee282016-10-27 17:19:20 +0200130DelayBasedBwe::BitrateEstimator::BitrateEstimator()
131 : sum_(0),
132 current_win_ms_(0),
133 prev_time_ms_(-1),
134 bitrate_estimate_(-1.0f),
135 bitrate_estimate_var_(50.0f),
136 old_estimator_(kBitrateWindowMs, 8000),
137 in_experiment_(BitrateEstimateExperimentIsEnabled()) {}
138
139void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) {
140 if (!in_experiment_) {
141 old_estimator_.Update(bytes, now_ms);
142 rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms);
143 bitrate_estimate_ = -1.0f;
144 if (rate)
145 bitrate_estimate_ = *rate / 1000.0f;
146 return;
147 }
148 int rate_window_ms = kRateWindowMs;
149 // We use a larger window at the beginning to get a more stable sample that
150 // we can use to initialize the estimate.
151 if (bitrate_estimate_ < 0.f)
152 rate_window_ms = kInitialRateWindowMs;
153 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms);
154 if (bitrate_sample < 0.0f)
155 return;
156 if (bitrate_estimate_ < 0.0f) {
157 // This is the very first sample we get. Use it to initialize the estimate.
158 bitrate_estimate_ = bitrate_sample;
159 return;
160 }
161 // Define the sample uncertainty as a function of how far away it is from the
162 // current estimate.
163 float sample_uncertainty =
164 10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_;
165 float sample_var = sample_uncertainty * sample_uncertainty;
166 // Update a bayesian estimate of the rate, weighting it lower if the sample
167 // uncertainty is large.
168 // The bitrate estimate uncertainty is increased with each update to model
169 // that the bitrate changes over time.
170 float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f;
171 bitrate_estimate_ = (sample_var * bitrate_estimate_ +
172 pred_bitrate_estimate_var * bitrate_sample) /
173 (sample_var + pred_bitrate_estimate_var);
174 bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var /
175 (sample_var + pred_bitrate_estimate_var);
176}
177
178float DelayBasedBwe::BitrateEstimator::UpdateWindow(int64_t now_ms,
179 int bytes,
180 int rate_window_ms) {
181 // Reset if time moves backwards.
182 if (now_ms < prev_time_ms_) {
183 prev_time_ms_ = -1;
184 sum_ = 0;
185 current_win_ms_ = 0;
186 }
187 if (prev_time_ms_ >= 0) {
188 current_win_ms_ += now_ms - prev_time_ms_;
189 // Reset if nothing has been received for more than a full window.
190 if (now_ms - prev_time_ms_ > rate_window_ms) {
191 sum_ = 0;
192 current_win_ms_ %= rate_window_ms;
193 }
194 }
195 prev_time_ms_ = now_ms;
196 float bitrate_sample = -1.0f;
197 if (current_win_ms_ >= rate_window_ms) {
198 bitrate_sample = 8.0f * sum_ / static_cast<float>(rate_window_ms);
199 current_win_ms_ -= rate_window_ms;
200 sum_ = 0;
201 }
202 sum_ += bytes;
203 return bitrate_sample;
204}
205
206rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const {
207 if (bitrate_estimate_ < 0.f)
208 return rtc::Optional<uint32_t>();
209 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000);
210}
philipel863a8262016-06-17 09:21:34 -0700211
terelius0baf55d2017-02-17 03:38:28 -0800212DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, Clock* clock)
terelius5a388362016-12-09 05:50:01 -0800213 : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()),
214 in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()),
terelius0baf55d2017-02-17 03:38:28 -0800215 event_log_(event_log),
terelius5a388362016-12-09 05:50:01 -0800216 clock_(clock),
philipel863a8262016-06-17 09:21:34 -0700217 inter_arrival_(),
tereliusafaef8b2016-11-17 03:48:18 -0800218 kalman_estimator_(),
219 trendline_estimator_(),
terelius84f83f82016-12-27 10:43:01 -0800220 detector_(),
Stefan Holmer492ee282016-10-27 17:19:20 +0200221 receiver_incoming_bitrate_(),
philipel863a8262016-06-17 09:21:34 -0700222 last_update_ms_(-1),
philipel7522a282016-08-16 10:59:36 +0200223 last_seen_packet_ms_(-1),
tereliusafaef8b2016-11-17 03:48:18 -0800224 uma_recorded_(false),
225 trendline_window_size_(kDefaultTrendlineWindowSize),
226 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
227 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
terelius5a388362016-12-09 05:50:01 -0800228 probing_interval_estimator_(&rate_control_),
229 median_slope_window_size_(kDefaultMedianSlopeWindowSize),
stefane3a55672017-02-13 09:08:22 -0800230 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain),
terelius0baf55d2017-02-17 03:38:28 -0800231 consecutive_delayed_feedbacks_(0),
232 last_logged_bitrate_(0),
233 last_logged_state_(kBwNormal) {
tereliusafaef8b2016-11-17 03:48:18 -0800234 if (in_trendline_experiment_) {
235 ReadTrendlineFilterExperimentParameters(&trendline_window_size_,
236 &trendline_smoothing_coeff_,
237 &trendline_threshold_gain_);
tereliused1850a2017-02-08 08:45:20 -0800238 LOG(LS_INFO) << "Trendline filter experiment enabled with parameters "
239 << trendline_window_size_ << ',' << trendline_smoothing_coeff_
240 << ',' << trendline_threshold_gain_;
tereliusafaef8b2016-11-17 03:48:18 -0800241 }
terelius5a388362016-12-09 05:50:01 -0800242 if (in_median_slope_experiment_) {
terelius804ab6f2017-01-17 03:30:05 -0800243 ReadMedianSlopeFilterExperimentParameters(&median_slope_window_size_,
244 &median_slope_threshold_gain_);
tereliused1850a2017-02-08 08:45:20 -0800245 LOG(LS_INFO) << "Median-slope filter experiment enabled with parameters "
246 << median_slope_window_size_ << ','
247 << median_slope_threshold_gain_;
248 }
249 if (!in_trendline_experiment_ && !in_median_slope_experiment_) {
250 LOG(LS_INFO) << "No overuse experiment enabled. Using Kalman filter.";
terelius5a388362016-12-09 05:50:01 -0800251 }
252
philipel863a8262016-06-17 09:21:34 -0700253 network_thread_.DetachFromThread();
254}
255
Stefan Holmer280de9e2016-09-30 10:06:51 +0200256DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
philipel863a8262016-06-17 09:21:34 -0700257 const std::vector<PacketInfo>& packet_feedback_vector) {
258 RTC_DCHECK(network_thread_.CalledOnValidThread());
stefan64636dd2016-08-03 00:29:03 -0700259 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700260 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
261 BweNames::kSendSideTransportSeqNum,
262 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700263 uma_recorded_ = true;
264 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200265 Result aggregated_result;
stefane3a55672017-02-13 09:08:22 -0800266 bool delayed_feedback = true;
philipel863a8262016-06-17 09:21:34 -0700267 for (const auto& packet_info : packet_feedback_vector) {
stefane3a55672017-02-13 09:08:22 -0800268 if (packet_info.send_time_ms < 0)
269 continue;
270 delayed_feedback = false;
Stefan Holmer280de9e2016-09-30 10:06:51 +0200271 Result result = IncomingPacketInfo(packet_info);
272 if (result.updated)
273 aggregated_result = result;
philipel863a8262016-06-17 09:21:34 -0700274 }
stefane3a55672017-02-13 09:08:22 -0800275 if (delayed_feedback) {
276 ++consecutive_delayed_feedbacks_;
277 } else {
278 consecutive_delayed_feedbacks_ = 0;
279 }
280 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) {
281 aggregated_result =
282 OnLongFeedbackDelay(packet_feedback_vector.back().arrival_time_ms);
283 consecutive_delayed_feedbacks_ = 0;
284 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200285 return aggregated_result;
philipel863a8262016-06-17 09:21:34 -0700286}
287
stefane3a55672017-02-13 09:08:22 -0800288DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay(
289 int64_t arrival_time_ms) {
290 // Estimate should always be valid since a start bitrate always is set in the
291 // Call constructor. An alternative would be to return an empty Result here,
292 // or to estimate the throughput based on the feedback we received.
293 RTC_DCHECK(rate_control_.ValidEstimate());
294 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2,
295 arrival_time_ms);
296 Result result;
297 result.updated = true;
298 result.probe = false;
299 result.target_bitrate_bps = rate_control_.LatestEstimate();
300 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to "
301 << result.target_bitrate_bps;
302 return result;
303}
304
Stefan Holmer280de9e2016-09-30 10:06:51 +0200305DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo(
306 const PacketInfo& info) {
stefan5e12d362016-07-11 01:44:02 -0700307 int64_t now_ms = clock_->TimeInMilliseconds();
philipel863a8262016-06-17 09:21:34 -0700308
Stefan Holmer492ee282016-10-27 17:19:20 +0200309 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200310 Result result;
311 // Reset if the stream has timed out.
312 if (last_seen_packet_ms_ == -1 ||
313 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
314 inter_arrival_.reset(
315 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
316 kTimestampToMs, true));
tereliusafaef8b2016-11-17 03:48:18 -0800317 kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
318 trendline_estimator_.reset(new TrendlineEstimator(
319 trendline_window_size_, trendline_smoothing_coeff_,
320 trendline_threshold_gain_));
terelius5a388362016-12-09 05:50:01 -0800321 median_slope_estimator_.reset(new MedianSlopeEstimator(
322 median_slope_window_size_, median_slope_threshold_gain_));
Stefan Holmer280de9e2016-09-30 10:06:51 +0200323 }
324 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700325
Stefan Holmer280de9e2016-09-30 10:06:51 +0200326 uint32_t send_time_24bits =
327 static_cast<uint32_t>(
328 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) +
329 500) /
330 1000) &
331 0x00FFFFFF;
332 // Shift up send time to use the full 32 bits that inter_arrival works with,
333 // so wrapping works properly.
334 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700335
Stefan Holmer280de9e2016-09-30 10:06:51 +0200336 uint32_t ts_delta = 0;
337 int64_t t_delta = 0;
338 int size_delta = 0;
339 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms,
340 info.payload_size, &ts_delta, &t_delta,
341 &size_delta)) {
342 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
tereliusafaef8b2016-11-17 03:48:18 -0800343 if (in_trendline_experiment_) {
344 trendline_estimator_->Update(t_delta, ts_delta_ms, info.arrival_time_ms);
345 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
346 trendline_estimator_->num_of_deltas(),
Stefan Holmer280de9e2016-09-30 10:06:51 +0200347 info.arrival_time_ms);
terelius5a388362016-12-09 05:50:01 -0800348 } else if (in_median_slope_experiment_) {
349 median_slope_estimator_->Update(t_delta, ts_delta_ms,
350 info.arrival_time_ms);
351 detector_.Detect(median_slope_estimator_->trendline_slope(), ts_delta_ms,
352 median_slope_estimator_->num_of_deltas(),
353 info.arrival_time_ms);
tereliusafaef8b2016-11-17 03:48:18 -0800354 } else {
355 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta,
356 detector_.State(), info.arrival_time_ms);
357 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms,
358 kalman_estimator_->num_of_deltas(),
359 info.arrival_time_ms);
360 }
stefan5ec85fb2016-09-29 04:19:38 -0700361 }
362
Stefan Holmer280de9e2016-09-30 10:06:51 +0200363 int probing_bps = 0;
364 if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
365 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
366 }
Stefan Holmer492ee282016-10-27 17:19:20 +0200367 rtc::Optional<uint32_t> acked_bitrate_bps =
368 receiver_incoming_bitrate_.bitrate_bps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200369 // Currently overusing the bandwidth.
370 if (detector_.State() == kBwOverusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200371 if (acked_bitrate_bps &&
372 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
373 result.updated =
374 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
375 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200376 }
377 } else if (probing_bps > 0) {
378 // No overuse, but probing measured a bitrate.
terelius6ed592d2016-10-18 05:55:30 -0700379 rate_control_.SetEstimate(probing_bps, info.arrival_time_ms);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200380 result.probe = true;
Stefan Holmer492ee282016-10-27 17:19:20 +0200381 result.updated =
382 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
383 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200384 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200385 if (!result.updated &&
386 (last_update_ms_ == -1 ||
terelius6ed592d2016-10-18 05:55:30 -0700387 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200388 result.updated =
389 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
390 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200391 }
terelius5a388362016-12-09 05:50:01 -0800392 if (result.updated) {
stefan5ec85fb2016-09-29 04:19:38 -0700393 last_update_ms_ = now_ms;
terelius5a388362016-12-09 05:50:01 -0800394 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms,
395 result.target_bitrate_bps);
terelius0baf55d2017-02-17 03:38:28 -0800396 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ ||
397 detector_.State() != last_logged_state_)) {
398 event_log_->LogBwePacketDelayEvent(result.target_bitrate_bps,
399 detector_.State());
400 last_logged_bitrate_ = result.target_bitrate_bps;
401 last_logged_state_ = detector_.State();
402 }
terelius5a388362016-12-09 05:50:01 -0800403 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200404
405 return result;
philipel863a8262016-06-17 09:21:34 -0700406}
407
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700408bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
409 int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200410 rtc::Optional<uint32_t> acked_bitrate_bps,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700411 uint32_t* target_bitrate_bps) {
tereliusafaef8b2016-11-17 03:48:18 -0800412 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
413 // removed. In the meantime, we set it to zero.
414 const RateControlInput input(detector_.State(), acked_bitrate_bps, 0);
terelius6ed592d2016-10-18 05:55:30 -0700415 rate_control_.Update(&input, now_ms);
416 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms);
417 return rate_control_.ValidEstimate();
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700418}
419
philipel863a8262016-06-17 09:21:34 -0700420void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700421 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700422}
423
philipel863a8262016-06-17 09:21:34 -0700424bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
425 uint32_t* bitrate_bps) const {
426 // Currently accessed from both the process thread (see
427 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
428 // Call::GetStats()). Should in the future only be accessed from a single
429 // thread.
430 RTC_DCHECK(ssrcs);
431 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700432 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700433 return false;
philipel7522a282016-08-16 10:59:36 +0200434
435 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700436 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700437 return true;
438}
439
stefan5a2c5062017-01-27 06:43:18 -0800440void DelayBasedBwe::SetStartBitrate(int start_bitrate_bps) {
441 LOG(LS_WARNING) << "BWE Setting start bitrate to: " << start_bitrate_bps;
442 rate_control_.SetStartBitrate(start_bitrate_bps);
443}
444
philipel863a8262016-06-17 09:21:34 -0700445void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
446 // Called from both the configuration thread and the network thread. Shouldn't
447 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700448 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700449}
minyue78b4d562016-11-30 04:47:39 -0800450
451int64_t DelayBasedBwe::GetProbingIntervalMs() const {
452 return probing_interval_estimator_.GetIntervalMs();
453}
philipel863a8262016-06-17 09:21:34 -0700454} // namespace webrtc