blob: af27505268b736a9bf81c5ab912acf477ded65c6 [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>
philipel863a8262016-06-17 09:21:34 -070015
16#include "webrtc/base/checks.h"
17#include "webrtc/base/constructormagic.h"
18#include "webrtc/base/logging.h"
19#include "webrtc/base/thread_annotations.h"
Irfan Sheriffb2540bb2016-09-12 12:28:54 -070020#include "webrtc/modules/congestion_controller/include/congestion_controller.h"
philipel863a8262016-06-17 09:21:34 -070021#include "webrtc/modules/pacing/paced_sender.h"
22#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
Stefan Holmer492ee282016-10-27 17:19:20 +020023#include "webrtc/system_wrappers/include/field_trial.h"
stefan64636dd2016-08-03 00:29:03 -070024#include "webrtc/system_wrappers/include/metrics.h"
philipel863a8262016-06-17 09:21:34 -070025#include "webrtc/typedefs.h"
26
27namespace {
philipel7522a282016-08-16 10:59:36 +020028constexpr int kTimestampGroupLengthMs = 5;
29constexpr int kAbsSendTimeFraction = 18;
30constexpr int kAbsSendTimeInterArrivalUpshift = 8;
31constexpr int kInterArrivalShift =
32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
33constexpr double kTimestampToMs =
philipel863a8262016-06-17 09:21:34 -070034 1000.0 / static_cast<double>(1 << kInterArrivalShift);
philipel7522a282016-08-16 10:59:36 +020035// This ssrc is used to fulfill the current API but will be removed
36// after the API has been changed.
37constexpr uint32_t kFixedSsrc = 0;
Stefan Holmer492ee282016-10-27 17:19:20 +020038constexpr int kInitialRateWindowMs = 500;
39constexpr int kRateWindowMs = 150;
40
41const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate";
42
43bool BitrateEstimateExperimentIsEnabled() {
44 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) ==
45 "Enabled";
46}
philipel863a8262016-06-17 09:21:34 -070047} // namespace
48
49namespace webrtc {
Stefan Holmer492ee282016-10-27 17:19:20 +020050DelayBasedBwe::BitrateEstimator::BitrateEstimator()
51 : sum_(0),
52 current_win_ms_(0),
53 prev_time_ms_(-1),
54 bitrate_estimate_(-1.0f),
55 bitrate_estimate_var_(50.0f),
56 old_estimator_(kBitrateWindowMs, 8000),
57 in_experiment_(BitrateEstimateExperimentIsEnabled()) {}
58
59void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) {
60 if (!in_experiment_) {
61 old_estimator_.Update(bytes, now_ms);
62 rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms);
63 bitrate_estimate_ = -1.0f;
64 if (rate)
65 bitrate_estimate_ = *rate / 1000.0f;
66 return;
67 }
68 int rate_window_ms = kRateWindowMs;
69 // We use a larger window at the beginning to get a more stable sample that
70 // we can use to initialize the estimate.
71 if (bitrate_estimate_ < 0.f)
72 rate_window_ms = kInitialRateWindowMs;
73 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms);
74 if (bitrate_sample < 0.0f)
75 return;
76 if (bitrate_estimate_ < 0.0f) {
77 // This is the very first sample we get. Use it to initialize the estimate.
78 bitrate_estimate_ = bitrate_sample;
79 return;
80 }
81 // Define the sample uncertainty as a function of how far away it is from the
82 // current estimate.
83 float sample_uncertainty =
84 10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_;
85 float sample_var = sample_uncertainty * sample_uncertainty;
86 // Update a bayesian estimate of the rate, weighting it lower if the sample
87 // uncertainty is large.
88 // The bitrate estimate uncertainty is increased with each update to model
89 // that the bitrate changes over time.
90 float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f;
91 bitrate_estimate_ = (sample_var * bitrate_estimate_ +
92 pred_bitrate_estimate_var * bitrate_sample) /
93 (sample_var + pred_bitrate_estimate_var);
94 bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var /
95 (sample_var + pred_bitrate_estimate_var);
96}
97
98float DelayBasedBwe::BitrateEstimator::UpdateWindow(int64_t now_ms,
99 int bytes,
100 int rate_window_ms) {
101 // Reset if time moves backwards.
102 if (now_ms < prev_time_ms_) {
103 prev_time_ms_ = -1;
104 sum_ = 0;
105 current_win_ms_ = 0;
106 }
107 if (prev_time_ms_ >= 0) {
108 current_win_ms_ += now_ms - prev_time_ms_;
109 // Reset if nothing has been received for more than a full window.
110 if (now_ms - prev_time_ms_ > rate_window_ms) {
111 sum_ = 0;
112 current_win_ms_ %= rate_window_ms;
113 }
114 }
115 prev_time_ms_ = now_ms;
116 float bitrate_sample = -1.0f;
117 if (current_win_ms_ >= rate_window_ms) {
118 bitrate_sample = 8.0f * sum_ / static_cast<float>(rate_window_ms);
119 current_win_ms_ -= rate_window_ms;
120 sum_ = 0;
121 }
122 sum_ += bytes;
123 return bitrate_sample;
124}
125
126rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const {
127 if (bitrate_estimate_ < 0.f)
128 return rtc::Optional<uint32_t>();
129 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000);
130}
philipel863a8262016-06-17 09:21:34 -0700131
Stefan Holmer280de9e2016-09-30 10:06:51 +0200132DelayBasedBwe::DelayBasedBwe(Clock* clock)
stefan5e12d362016-07-11 01:44:02 -0700133 : clock_(clock),
philipel863a8262016-06-17 09:21:34 -0700134 inter_arrival_(),
135 estimator_(),
136 detector_(OverUseDetectorOptions()),
Stefan Holmer492ee282016-10-27 17:19:20 +0200137 receiver_incoming_bitrate_(),
philipel863a8262016-06-17 09:21:34 -0700138 last_update_ms_(-1),
philipel7522a282016-08-16 10:59:36 +0200139 last_seen_packet_ms_(-1),
stefan64636dd2016-08-03 00:29:03 -0700140 uma_recorded_(false) {
philipel863a8262016-06-17 09:21:34 -0700141 network_thread_.DetachFromThread();
142}
143
Stefan Holmer280de9e2016-09-30 10:06:51 +0200144DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
philipel863a8262016-06-17 09:21:34 -0700145 const std::vector<PacketInfo>& packet_feedback_vector) {
146 RTC_DCHECK(network_thread_.CalledOnValidThread());
stefan64636dd2016-08-03 00:29:03 -0700147 if (!uma_recorded_) {
asapersson1d02d3e2016-09-09 22:40:25 -0700148 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
149 BweNames::kSendSideTransportSeqNum,
150 BweNames::kBweNamesMax);
stefan64636dd2016-08-03 00:29:03 -0700151 uma_recorded_ = true;
152 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200153 Result aggregated_result;
philipel863a8262016-06-17 09:21:34 -0700154 for (const auto& packet_info : packet_feedback_vector) {
Stefan Holmer280de9e2016-09-30 10:06:51 +0200155 Result result = IncomingPacketInfo(packet_info);
156 if (result.updated)
157 aggregated_result = result;
philipel863a8262016-06-17 09:21:34 -0700158 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200159 return aggregated_result;
philipel863a8262016-06-17 09:21:34 -0700160}
161
Stefan Holmer280de9e2016-09-30 10:06:51 +0200162DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo(
163 const PacketInfo& info) {
stefan5e12d362016-07-11 01:44:02 -0700164 int64_t now_ms = clock_->TimeInMilliseconds();
philipel863a8262016-06-17 09:21:34 -0700165
Stefan Holmer492ee282016-10-27 17:19:20 +0200166 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200167 Result result;
168 // Reset if the stream has timed out.
169 if (last_seen_packet_ms_ == -1 ||
170 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
171 inter_arrival_.reset(
172 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
173 kTimestampToMs, true));
174 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
175 }
176 last_seen_packet_ms_ = now_ms;
philipel863a8262016-06-17 09:21:34 -0700177
Stefan Holmer280de9e2016-09-30 10:06:51 +0200178 uint32_t send_time_24bits =
179 static_cast<uint32_t>(
180 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) +
181 500) /
182 1000) &
183 0x00FFFFFF;
184 // Shift up send time to use the full 32 bits that inter_arrival works with,
185 // so wrapping works properly.
186 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
stefanfd0d4262016-09-29 02:44:31 -0700187
Stefan Holmer280de9e2016-09-30 10:06:51 +0200188 uint32_t ts_delta = 0;
189 int64_t t_delta = 0;
190 int size_delta = 0;
191 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms,
192 info.payload_size, &ts_delta, &t_delta,
193 &size_delta)) {
194 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
195 estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State(),
196 info.arrival_time_ms);
197 detector_.Detect(estimator_->offset(), ts_delta_ms,
198 estimator_->num_of_deltas(), info.arrival_time_ms);
stefan5ec85fb2016-09-29 04:19:38 -0700199 }
200
Stefan Holmer280de9e2016-09-30 10:06:51 +0200201 int probing_bps = 0;
202 if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
203 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
204 }
Stefan Holmer492ee282016-10-27 17:19:20 +0200205 rtc::Optional<uint32_t> acked_bitrate_bps =
206 receiver_incoming_bitrate_.bitrate_bps();
Stefan Holmer280de9e2016-09-30 10:06:51 +0200207 // Currently overusing the bandwidth.
208 if (detector_.State() == kBwOverusing) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200209 if (acked_bitrate_bps &&
210 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) {
211 result.updated =
212 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
213 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200214 }
215 } else if (probing_bps > 0) {
216 // No overuse, but probing measured a bitrate.
terelius6ed592d2016-10-18 05:55:30 -0700217 rate_control_.SetEstimate(probing_bps, info.arrival_time_ms);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200218 result.probe = true;
Stefan Holmer492ee282016-10-27 17:19:20 +0200219 result.updated =
220 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
221 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200222 }
Stefan Holmer280de9e2016-09-30 10:06:51 +0200223 if (!result.updated &&
224 (last_update_ms_ == -1 ||
terelius6ed592d2016-10-18 05:55:30 -0700225 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200226 result.updated =
227 UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps,
228 &result.target_bitrate_bps);
Stefan Holmer280de9e2016-09-30 10:06:51 +0200229 }
230 if (result.updated)
stefan5ec85fb2016-09-29 04:19:38 -0700231 last_update_ms_ = now_ms;
Stefan Holmer280de9e2016-09-30 10:06:51 +0200232
233 return result;
philipel863a8262016-06-17 09:21:34 -0700234}
235
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700236bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
237 int64_t now_ms,
Stefan Holmer492ee282016-10-27 17:19:20 +0200238 rtc::Optional<uint32_t> acked_bitrate_bps,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700239 uint32_t* target_bitrate_bps) {
Stefan Holmer492ee282016-10-27 17:19:20 +0200240 const RateControlInput input(detector_.State(), acked_bitrate_bps,
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700241 estimator_->var_noise());
terelius6ed592d2016-10-18 05:55:30 -0700242 rate_control_.Update(&input, now_ms);
243 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms);
244 return rate_control_.ValidEstimate();
Irfan Sheriffb2540bb2016-09-12 12:28:54 -0700245}
246
philipel863a8262016-06-17 09:21:34 -0700247void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
terelius6ed592d2016-10-18 05:55:30 -0700248 rate_control_.SetRtt(avg_rtt_ms);
philipel863a8262016-06-17 09:21:34 -0700249}
250
philipel863a8262016-06-17 09:21:34 -0700251bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
252 uint32_t* bitrate_bps) const {
253 // Currently accessed from both the process thread (see
254 // ModuleRtpRtcpImpl::Process()) and the configuration thread (see
255 // Call::GetStats()). Should in the future only be accessed from a single
256 // thread.
257 RTC_DCHECK(ssrcs);
258 RTC_DCHECK(bitrate_bps);
terelius6ed592d2016-10-18 05:55:30 -0700259 if (!rate_control_.ValidEstimate())
philipel863a8262016-06-17 09:21:34 -0700260 return false;
philipel7522a282016-08-16 10:59:36 +0200261
262 *ssrcs = {kFixedSsrc};
terelius6ed592d2016-10-18 05:55:30 -0700263 *bitrate_bps = rate_control_.LatestEstimate();
philipel863a8262016-06-17 09:21:34 -0700264 return true;
265}
266
267void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
268 // Called from both the configuration thread and the network thread. Shouldn't
269 // be called from the network thread in the future.
terelius6ed592d2016-10-18 05:55:30 -0700270 rate_control_.SetMinBitrate(min_bitrate_bps);
philipel863a8262016-06-17 09:21:34 -0700271}
272} // namespace webrtc