OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |