Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: webrtc/modules/congestion_controller/delay_based_bwe.cc

Issue 2489323002: Add a new overuse estimator for the delay based BWE behind experiment. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/congestion_controller/delay_based_bwe.h" 11 #include "webrtc/modules/congestion_controller/delay_based_bwe.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <cmath> 14 #include <cmath>
15 #include <string>
15 16
16 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
17 #include "webrtc/base/constructormagic.h" 18 #include "webrtc/base/constructormagic.h"
18 #include "webrtc/base/logging.h" 19 #include "webrtc/base/logging.h"
19 #include "webrtc/base/thread_annotations.h" 20 #include "webrtc/base/thread_annotations.h"
20 #include "webrtc/modules/congestion_controller/include/congestion_controller.h" 21 #include "webrtc/modules/congestion_controller/include/congestion_controller.h"
21 #include "webrtc/modules/pacing/paced_sender.h" 22 #include "webrtc/modules/pacing/paced_sender.h"
22 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat or.h" 23 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat or.h"
23 #include "webrtc/system_wrappers/include/field_trial.h" 24 #include "webrtc/system_wrappers/include/field_trial.h"
24 #include "webrtc/system_wrappers/include/metrics.h" 25 #include "webrtc/system_wrappers/include/metrics.h"
25 #include "webrtc/typedefs.h" 26 #include "webrtc/typedefs.h"
26 27
27 namespace { 28 namespace {
28 constexpr int kTimestampGroupLengthMs = 5; 29 constexpr int kTimestampGroupLengthMs = 5;
29 constexpr int kAbsSendTimeFraction = 18; 30 constexpr int kAbsSendTimeFraction = 18;
30 constexpr int kAbsSendTimeInterArrivalUpshift = 8; 31 constexpr int kAbsSendTimeInterArrivalUpshift = 8;
31 constexpr int kInterArrivalShift = 32 constexpr int kInterArrivalShift =
32 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; 33 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift;
33 constexpr double kTimestampToMs = 34 constexpr double kTimestampToMs =
34 1000.0 / static_cast<double>(1 << kInterArrivalShift); 35 1000.0 / static_cast<double>(1 << kInterArrivalShift);
35 // This ssrc is used to fulfill the current API but will be removed 36 // This ssrc is used to fulfill the current API but will be removed
36 // after the API has been changed. 37 // after the API has been changed.
37 constexpr uint32_t kFixedSsrc = 0; 38 constexpr uint32_t kFixedSsrc = 0;
38 constexpr int kInitialRateWindowMs = 500; 39 constexpr int kInitialRateWindowMs = 500;
39 constexpr int kRateWindowMs = 150; 40 constexpr int kRateWindowMs = 150;
40 41
42 constexpr size_t kDefaultTrendlineWindowSize = 20;
43 constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
44 constexpr double kDefaultTrendlineThresholdGain = 4.0;
45
41 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate"; 46 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate";
47 const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter";
42 48
43 bool BitrateEstimateExperimentIsEnabled() { 49 bool BitrateEstimateExperimentIsEnabled() {
44 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) == 50 return webrtc::field_trial::FindFullName(kBitrateEstimateExperiment) ==
45 "Enabled"; 51 "Enabled";
46 } 52 }
53
54 bool TrendlineFilterExperimentIsEnabled() {
55 std::string experiment_string =
56 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
57 // The experiment is enabled iff the field trial string begins with "Enabled".
58 return experiment_string.find("Enabled") == 0;
59 }
60
61 bool ReadTrendlineFilterExperimentParameters(size_t* window_points,
62 double* smoothing_coef,
63 double* threshold_gain) {
64 RTC_DCHECK(TrendlineFilterExperimentIsEnabled());
65 std::string experiment_string =
66 webrtc::field_trial::FindFullName(kBweTrendlineFilterExperiment);
67 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf,%lf",
68 window_points, smoothing_coef, threshold_gain);
69 if (parsed_values == 3) {
70 if (2 <= *window_points && 0 <= *smoothing_coef && *smoothing_coef <= 1 &&
stefan-webrtc 2016/11/13 13:09:53 I personally prefer having variables first and con
terelius 2016/11/14 13:21:39 In general I agree, but for the smoothing_coef I w
stefan-webrtc 2016/11/14 13:30:58 Sounds good for smoothing_coef, but the other two
terelius 2016/11/15 17:35:46 The if statement is redundant if we CHECK anyway.
stefan-webrtc 2016/11/16 15:11:20 Acknowledged.
71 0 <= *threshold_gain)
72 return true;
73 if (*window_points < 2)
74 LOG(LS_ERROR) << "Needs at least 2 points to fit a trend line.";
stefan-webrtc 2016/11/13 13:09:53 Should we perhaps DCHECK on all broken configurati
terelius 2016/11/14 13:21:39 It would not give us any alert if we misconfigure
stefan-webrtc 2016/11/14 13:30:58 Yes, then I think we should CHECK as it would be b
terelius 2016/11/15 17:35:46 Done.
75 if (*smoothing_coef < 0 || 1 < *smoothing_coef)
76 LOG(LS_ERROR)
77 << "Coefficient needs to be between 0 and 1 for weighted average.";
78 if (*threshold_gain < 0)
79 LOG(LS_ERROR) << "Threshold gain needs to be positive.";
80 }
81 LOG(LS_ERROR) << "Failed to parse parameters for BweTrendlineFilter "
82 "experiment from field trial string.";
83 *window_points = kDefaultTrendlineWindowSize;
84 *smoothing_coef = kDefaultTrendlineSmoothingCoeff;
85 *threshold_gain = kDefaultTrendlineThresholdGain;
86 return false;
87 }
88
47 } // namespace 89 } // namespace
48 90
49 namespace webrtc { 91 namespace webrtc {
92
50 DelayBasedBwe::BitrateEstimator::BitrateEstimator() 93 DelayBasedBwe::BitrateEstimator::BitrateEstimator()
51 : sum_(0), 94 : sum_(0),
52 current_win_ms_(0), 95 current_win_ms_(0),
53 prev_time_ms_(-1), 96 prev_time_ms_(-1),
54 bitrate_estimate_(-1.0f), 97 bitrate_estimate_(-1.0f),
55 bitrate_estimate_var_(50.0f), 98 bitrate_estimate_var_(50.0f),
56 old_estimator_(kBitrateWindowMs, 8000), 99 old_estimator_(kBitrateWindowMs, 8000),
57 in_experiment_(BitrateEstimateExperimentIsEnabled()) {} 100 in_experiment_(BitrateEstimateExperimentIsEnabled()) {}
58 101
59 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) { 102 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 168
126 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const { 169 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const {
127 if (bitrate_estimate_ < 0.f) 170 if (bitrate_estimate_ < 0.f)
128 return rtc::Optional<uint32_t>(); 171 return rtc::Optional<uint32_t>();
129 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); 172 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000);
130 } 173 }
131 174
132 DelayBasedBwe::DelayBasedBwe(Clock* clock) 175 DelayBasedBwe::DelayBasedBwe(Clock* clock)
133 : clock_(clock), 176 : clock_(clock),
134 inter_arrival_(), 177 inter_arrival_(),
135 estimator_(), 178 kalman_estimator_(),
179 trendline_estimator_(),
136 detector_(OverUseDetectorOptions()), 180 detector_(OverUseDetectorOptions()),
137 receiver_incoming_bitrate_(), 181 receiver_incoming_bitrate_(),
138 last_update_ms_(-1), 182 last_update_ms_(-1),
139 last_seen_packet_ms_(-1), 183 last_seen_packet_ms_(-1),
140 uma_recorded_(false) { 184 uma_recorded_(false),
185 trendline_window_size_(kDefaultTrendlineWindowSize),
186 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff),
187 trendline_threshold_gain_(kDefaultTrendlineThresholdGain),
188 in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()) {
189 if (in_trendline_experiment_) {
190 ReadTrendlineFilterExperimentParameters(&trendline_window_size_,
191 &trendline_smoothing_coeff_,
192 &trendline_threshold_gain_);
193 }
141 network_thread_.DetachFromThread(); 194 network_thread_.DetachFromThread();
142 } 195 }
143 196
144 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( 197 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector(
145 const std::vector<PacketInfo>& packet_feedback_vector) { 198 const std::vector<PacketInfo>& packet_feedback_vector) {
146 RTC_DCHECK(network_thread_.CalledOnValidThread()); 199 RTC_DCHECK(network_thread_.CalledOnValidThread());
147 if (!uma_recorded_) { 200 if (!uma_recorded_) {
148 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, 201 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram,
149 BweNames::kSendSideTransportSeqNum, 202 BweNames::kSendSideTransportSeqNum,
150 BweNames::kBweNamesMax); 203 BweNames::kBweNamesMax);
(...skipping 13 matching lines...) Expand all
164 int64_t now_ms = clock_->TimeInMilliseconds(); 217 int64_t now_ms = clock_->TimeInMilliseconds();
165 218
166 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size); 219 receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size);
167 Result result; 220 Result result;
168 // Reset if the stream has timed out. 221 // Reset if the stream has timed out.
169 if (last_seen_packet_ms_ == -1 || 222 if (last_seen_packet_ms_ == -1 ||
170 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { 223 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) {
171 inter_arrival_.reset( 224 inter_arrival_.reset(
172 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, 225 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
173 kTimestampToMs, true)); 226 kTimestampToMs, true));
174 estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); 227 kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions()));
228 trendline_estimator_.reset(new TrendlineEstimator(
229 trendline_window_size_, trendline_smoothing_coeff_,
230 trendline_threshold_gain_));
175 } 231 }
176 last_seen_packet_ms_ = now_ms; 232 last_seen_packet_ms_ = now_ms;
177 233
178 uint32_t send_time_24bits = 234 uint32_t send_time_24bits =
179 static_cast<uint32_t>( 235 static_cast<uint32_t>(
180 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) + 236 ((static_cast<uint64_t>(info.send_time_ms) << kAbsSendTimeFraction) +
181 500) / 237 500) /
182 1000) & 238 1000) &
183 0x00FFFFFF; 239 0x00FFFFFF;
184 // Shift up send time to use the full 32 bits that inter_arrival works with, 240 // Shift up send time to use the full 32 bits that inter_arrival works with,
185 // so wrapping works properly. 241 // so wrapping works properly.
186 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; 242 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
187 243
188 uint32_t ts_delta = 0; 244 uint32_t ts_delta = 0;
189 int64_t t_delta = 0; 245 int64_t t_delta = 0;
190 int size_delta = 0; 246 int size_delta = 0;
191 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms, 247 if (inter_arrival_->ComputeDeltas(timestamp, info.arrival_time_ms, now_ms,
192 info.payload_size, &ts_delta, &t_delta, 248 info.payload_size, &ts_delta, &t_delta,
193 &size_delta)) { 249 &size_delta)) {
194 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); 250 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
195 estimator_->Update(t_delta, ts_delta_ms, size_delta, detector_.State(), 251 if (in_trendline_experiment_) {
252 trendline_estimator_->Update(t_delta, ts_delta_ms, info.arrival_time_ms);
253 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms,
254 trendline_estimator_->num_of_deltas(),
196 info.arrival_time_ms); 255 info.arrival_time_ms);
197 detector_.Detect(estimator_->offset(), ts_delta_ms, 256
198 estimator_->num_of_deltas(), info.arrival_time_ms); 257 } else {
258 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta,
259 detector_.State(), info.arrival_time_ms);
260 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms,
261 kalman_estimator_->num_of_deltas(),
262 info.arrival_time_ms);
263 }
199 } 264 }
200 265
201 int probing_bps = 0; 266 int probing_bps = 0;
202 if (info.probe_cluster_id != PacketInfo::kNotAProbe) { 267 if (info.probe_cluster_id != PacketInfo::kNotAProbe) {
203 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); 268 probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info);
204 } 269 }
205 rtc::Optional<uint32_t> acked_bitrate_bps = 270 rtc::Optional<uint32_t> acked_bitrate_bps =
206 receiver_incoming_bitrate_.bitrate_bps(); 271 receiver_incoming_bitrate_.bitrate_bps();
207 // Currently overusing the bandwidth. 272 // Currently overusing the bandwidth.
208 if (detector_.State() == kBwOverusing) { 273 if (detector_.State() == kBwOverusing) {
(...skipping 21 matching lines...) Expand all
230 if (result.updated) 295 if (result.updated)
231 last_update_ms_ = now_ms; 296 last_update_ms_ = now_ms;
232 297
233 return result; 298 return result;
234 } 299 }
235 300
236 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, 301 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms,
237 int64_t now_ms, 302 int64_t now_ms,
238 rtc::Optional<uint32_t> acked_bitrate_bps, 303 rtc::Optional<uint32_t> acked_bitrate_bps,
239 uint32_t* target_bitrate_bps) { 304 uint32_t* target_bitrate_bps) {
240 const RateControlInput input(detector_.State(), acked_bitrate_bps, 305 // TODO(terelius): RateControlInput::noise_var is deprecated and will be
241 estimator_->var_noise()); 306 // removed. In the meantime, we set it to zero.
307 const RateControlInput input(detector_.State(), acked_bitrate_bps, 0);
242 rate_control_.Update(&input, now_ms); 308 rate_control_.Update(&input, now_ms);
243 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); 309 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms);
244 return rate_control_.ValidEstimate(); 310 return rate_control_.ValidEstimate();
245 } 311 }
246 312
247 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { 313 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
248 rate_control_.SetRtt(avg_rtt_ms); 314 rate_control_.SetRtt(avg_rtt_ms);
249 } 315 }
250 316
251 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, 317 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs,
(...skipping 11 matching lines...) Expand all
263 *bitrate_bps = rate_control_.LatestEstimate(); 329 *bitrate_bps = rate_control_.LatestEstimate();
264 return true; 330 return true;
265 } 331 }
266 332
267 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { 333 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) {
268 // Called from both the configuration thread and the network thread. Shouldn't 334 // Called from both the configuration thread and the network thread. Shouldn't
269 // be called from the network thread in the future. 335 // be called from the network thread in the future.
270 rate_control_.SetMinBitrate(min_bitrate_bps); 336 rate_control_.SetMinBitrate(min_bitrate_bps);
271 } 337 }
272 } // namespace webrtc 338 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698