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 |
(...skipping 24 matching lines...) Expand all Loading... |
35 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; | 35 kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; |
36 constexpr double kTimestampToMs = | 36 constexpr double kTimestampToMs = |
37 1000.0 / static_cast<double>(1 << kInterArrivalShift); | 37 1000.0 / static_cast<double>(1 << kInterArrivalShift); |
38 // This ssrc is used to fulfill the current API but will be removed | 38 // This ssrc is used to fulfill the current API but will be removed |
39 // after the API has been changed. | 39 // after the API has been changed. |
40 constexpr uint32_t kFixedSsrc = 0; | 40 constexpr uint32_t kFixedSsrc = 0; |
41 constexpr int kInitialRateWindowMs = 500; | 41 constexpr int kInitialRateWindowMs = 500; |
42 constexpr int kRateWindowMs = 150; | 42 constexpr int kRateWindowMs = 150; |
43 | 43 |
44 // Parameters for linear least squares fit of regression line to noisy data. | 44 // Parameters for linear least squares fit of regression line to noisy data. |
45 constexpr size_t kDefaultTrendlineWindowSize = 15; | 45 constexpr size_t kDefaultTrendlineWindowSize = 20; |
46 constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; | 46 constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; |
47 constexpr double kDefaultTrendlineThresholdGain = 4.0; | 47 constexpr double kDefaultTrendlineThresholdGain = 4.0; |
48 | 48 |
49 // Parameters for Theil-Sen robust fitting of line to noisy data. | 49 // Parameters for Theil-Sen robust fitting of line to noisy data. |
50 constexpr size_t kDefaultMedianSlopeWindowSize = 20; | 50 constexpr size_t kDefaultMedianSlopeWindowSize = 20; |
51 constexpr double kDefaultMedianSlopeThresholdGain = 4.0; | 51 constexpr double kDefaultMedianSlopeThresholdGain = 4.0; |
52 | 52 |
53 constexpr int kMaxConsecutiveFailedLookups = 5; | 53 constexpr int kMaxConsecutiveFailedLookups = 5; |
54 | 54 |
55 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate"; | 55 const char kBitrateEstimateExperiment[] = "WebRTC-ImprovedBitrateEstimate"; |
56 const char kBweTrendlineFilterExperiment[] = "WebRTC-BweTrendlineFilter"; | |
57 const char kBweMedianSlopeFilterExperiment[] = "WebRTC-BweMedianSlopeFilter"; | 56 const char kBweMedianSlopeFilterExperiment[] = "WebRTC-BweMedianSlopeFilter"; |
58 | 57 |
59 bool BitrateEstimateExperimentIsEnabled() { | 58 bool BitrateEstimateExperimentIsEnabled() { |
60 return webrtc::field_trial::IsEnabled(kBitrateEstimateExperiment); | 59 return webrtc::field_trial::IsEnabled(kBitrateEstimateExperiment); |
61 } | 60 } |
62 | 61 |
63 bool 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 | |
70 bool MedianSlopeFilterExperimentIsEnabled() { | 62 bool MedianSlopeFilterExperimentIsEnabled() { |
71 std::string experiment_string = | 63 std::string experiment_string = |
72 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment); | 64 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment); |
73 // The experiment is enabled iff the field trial string begins with "Enabled". | 65 // The experiment is enabled iff the field trial string begins with "Enabled". |
74 return experiment_string.find("Enabled") == 0; | 66 return experiment_string.find("Enabled") == 0; |
75 } | 67 } |
76 | 68 |
77 bool 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 | |
104 bool ReadMedianSlopeFilterExperimentParameters(size_t* window_size, | 69 bool ReadMedianSlopeFilterExperimentParameters(size_t* window_size, |
105 double* threshold_gain) { | 70 double* threshold_gain) { |
106 RTC_DCHECK(!TrendlineFilterExperimentIsEnabled()); | |
107 RTC_DCHECK(MedianSlopeFilterExperimentIsEnabled()); | 71 RTC_DCHECK(MedianSlopeFilterExperimentIsEnabled()); |
108 RTC_DCHECK(window_size != nullptr); | 72 RTC_DCHECK(window_size != nullptr); |
109 RTC_DCHECK(threshold_gain != nullptr); | 73 RTC_DCHECK(threshold_gain != nullptr); |
110 std::string experiment_string = | 74 std::string experiment_string = |
111 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment); | 75 webrtc::field_trial::FindFullName(kBweMedianSlopeFilterExperiment); |
112 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf", | 76 int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%zu,%lf", |
113 window_size, threshold_gain); | 77 window_size, threshold_gain); |
114 if (parsed_values == 2) { | 78 if (parsed_values == 2) { |
115 RTC_CHECK_GT(*window_size, 1) << "Need at least 2 points to fit a line."; | 79 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."; | 80 RTC_CHECK_GT(*threshold_gain, 0) << "Threshold gain needs to be positive."; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 return bitrate_sample; | 188 return bitrate_sample; |
225 } | 189 } |
226 | 190 |
227 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const { | 191 rtc::Optional<uint32_t> DelayBasedBwe::BitrateEstimator::bitrate_bps() const { |
228 if (bitrate_estimate_ < 0.f) | 192 if (bitrate_estimate_ < 0.f) |
229 return rtc::Optional<uint32_t>(); | 193 return rtc::Optional<uint32_t>(); |
230 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); | 194 return rtc::Optional<uint32_t>(bitrate_estimate_ * 1000); |
231 } | 195 } |
232 | 196 |
233 DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock) | 197 DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock) |
234 : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()), | 198 : in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()), |
235 in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()), | |
236 event_log_(event_log), | 199 event_log_(event_log), |
237 clock_(clock), | 200 clock_(clock), |
238 inter_arrival_(), | 201 inter_arrival_(), |
239 kalman_estimator_(), | |
240 trendline_estimator_(), | 202 trendline_estimator_(), |
241 detector_(), | 203 detector_(), |
242 receiver_incoming_bitrate_(), | 204 receiver_incoming_bitrate_(), |
243 last_update_ms_(-1), | 205 last_update_ms_(-1), |
244 last_seen_packet_ms_(-1), | 206 last_seen_packet_ms_(-1), |
245 uma_recorded_(false), | 207 uma_recorded_(false), |
246 trendline_window_size_(kDefaultTrendlineWindowSize), | 208 trendline_window_size_(kDefaultTrendlineWindowSize), |
247 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff), | 209 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff), |
248 trendline_threshold_gain_(kDefaultTrendlineThresholdGain), | 210 trendline_threshold_gain_(kDefaultTrendlineThresholdGain), |
249 probing_interval_estimator_(&rate_control_), | 211 probing_interval_estimator_(&rate_control_), |
250 median_slope_window_size_(kDefaultMedianSlopeWindowSize), | 212 median_slope_window_size_(kDefaultMedianSlopeWindowSize), |
251 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain), | 213 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain), |
252 consecutive_delayed_feedbacks_(0), | 214 consecutive_delayed_feedbacks_(0), |
253 last_logged_bitrate_(0), | 215 last_logged_bitrate_(0), |
254 last_logged_state_(kBwNormal) { | 216 last_logged_state_(kBwNormal) { |
255 if (in_trendline_experiment_) { | |
256 ReadTrendlineFilterExperimentParameters(&trendline_window_size_, | |
257 &trendline_smoothing_coeff_, | |
258 &trendline_threshold_gain_); | |
259 LOG(LS_INFO) << "Trendline filter experiment enabled with parameters " | |
260 << trendline_window_size_ << ',' << trendline_smoothing_coeff_ | |
261 << ',' << trendline_threshold_gain_; | |
262 } | |
263 if (in_median_slope_experiment_) { | 217 if (in_median_slope_experiment_) { |
264 ReadMedianSlopeFilterExperimentParameters(&median_slope_window_size_, | 218 ReadMedianSlopeFilterExperimentParameters(&median_slope_window_size_, |
265 &median_slope_threshold_gain_); | 219 &median_slope_threshold_gain_); |
266 LOG(LS_INFO) << "Median-slope filter experiment enabled with parameters " | 220 LOG(LS_INFO) << "Median-slope filter experiment enabled with parameters " |
267 << median_slope_window_size_ << ',' | 221 << median_slope_window_size_ << ',' |
268 << median_slope_threshold_gain_; | 222 << median_slope_threshold_gain_; |
269 } | 223 } else { |
270 if (!in_trendline_experiment_ && !in_median_slope_experiment_) { | 224 LOG(LS_INFO) << "No overuse experiment enabled. Using Trendline filter."; |
271 LOG(LS_INFO) << "No overuse experiment enabled. Using Kalman filter."; | |
272 } | 225 } |
273 | 226 |
274 network_thread_.DetachFromThread(); | 227 network_thread_.DetachFromThread(); |
275 } | 228 } |
276 | 229 |
277 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( | 230 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( |
278 const std::vector<PacketFeedback>& packet_feedback_vector) { | 231 const std::vector<PacketFeedback>& packet_feedback_vector) { |
279 RTC_DCHECK(network_thread_.CalledOnValidThread()); | 232 RTC_DCHECK(network_thread_.CalledOnValidThread()); |
280 RTC_DCHECK(!packet_feedback_vector.empty()); | 233 RTC_DCHECK(!packet_feedback_vector.empty()); |
281 | 234 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 | 288 |
336 receiver_incoming_bitrate_.Update(packet_feedback.arrival_time_ms, | 289 receiver_incoming_bitrate_.Update(packet_feedback.arrival_time_ms, |
337 packet_feedback.payload_size); | 290 packet_feedback.payload_size); |
338 Result result; | 291 Result result; |
339 // Reset if the stream has timed out. | 292 // Reset if the stream has timed out. |
340 if (last_seen_packet_ms_ == -1 || | 293 if (last_seen_packet_ms_ == -1 || |
341 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { | 294 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { |
342 inter_arrival_.reset( | 295 inter_arrival_.reset( |
343 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, | 296 new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, |
344 kTimestampToMs, true)); | 297 kTimestampToMs, true)); |
345 kalman_estimator_.reset(new OveruseEstimator(OverUseDetectorOptions())); | |
346 trendline_estimator_.reset(new TrendlineEstimator( | 298 trendline_estimator_.reset(new TrendlineEstimator( |
347 trendline_window_size_, trendline_smoothing_coeff_, | 299 trendline_window_size_, trendline_smoothing_coeff_, |
348 trendline_threshold_gain_)); | 300 trendline_threshold_gain_)); |
349 median_slope_estimator_.reset(new MedianSlopeEstimator( | 301 median_slope_estimator_.reset(new MedianSlopeEstimator( |
350 median_slope_window_size_, median_slope_threshold_gain_)); | 302 median_slope_window_size_, median_slope_threshold_gain_)); |
351 } | 303 } |
352 last_seen_packet_ms_ = now_ms; | 304 last_seen_packet_ms_ = now_ms; |
353 | 305 |
354 uint32_t send_time_24bits = | 306 uint32_t send_time_24bits = |
355 static_cast<uint32_t>( | 307 static_cast<uint32_t>( |
356 ((static_cast<uint64_t>(packet_feedback.send_time_ms) | 308 ((static_cast<uint64_t>(packet_feedback.send_time_ms) |
357 << kAbsSendTimeFraction) + | 309 << kAbsSendTimeFraction) + |
358 500) / | 310 500) / |
359 1000) & | 311 1000) & |
360 0x00FFFFFF; | 312 0x00FFFFFF; |
361 // Shift up send time to use the full 32 bits that inter_arrival works with, | 313 // Shift up send time to use the full 32 bits that inter_arrival works with, |
362 // so wrapping works properly. | 314 // so wrapping works properly. |
363 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; | 315 uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; |
364 | 316 |
365 uint32_t ts_delta = 0; | 317 uint32_t ts_delta = 0; |
366 int64_t t_delta = 0; | 318 int64_t t_delta = 0; |
367 int size_delta = 0; | 319 int size_delta = 0; |
368 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms, | 320 if (inter_arrival_->ComputeDeltas(timestamp, packet_feedback.arrival_time_ms, |
369 now_ms, packet_feedback.payload_size, | 321 now_ms, packet_feedback.payload_size, |
370 &ts_delta, &t_delta, &size_delta)) { | 322 &ts_delta, &t_delta, &size_delta)) { |
371 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); | 323 double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); |
372 if (in_trendline_experiment_) { | 324 if (in_median_slope_experiment_) { |
373 trendline_estimator_->Update(t_delta, ts_delta_ms, | |
374 packet_feedback.arrival_time_ms); | |
375 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms, | |
376 trendline_estimator_->num_of_deltas(), | |
377 packet_feedback.arrival_time_ms); | |
378 } else if (in_median_slope_experiment_) { | |
379 median_slope_estimator_->Update(t_delta, ts_delta_ms, | 325 median_slope_estimator_->Update(t_delta, ts_delta_ms, |
380 packet_feedback.arrival_time_ms); | 326 packet_feedback.arrival_time_ms); |
381 detector_.Detect(median_slope_estimator_->trendline_slope(), ts_delta_ms, | 327 detector_.Detect(median_slope_estimator_->trendline_slope(), ts_delta_ms, |
382 median_slope_estimator_->num_of_deltas(), | 328 median_slope_estimator_->num_of_deltas(), |
383 packet_feedback.arrival_time_ms); | 329 packet_feedback.arrival_time_ms); |
384 } else { | 330 } else { |
385 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta, | 331 trendline_estimator_->Update(t_delta, ts_delta_ms, |
386 detector_.State(), | 332 packet_feedback.arrival_time_ms); |
387 packet_feedback.arrival_time_ms); | 333 detector_.Detect(trendline_estimator_->trendline_slope(), ts_delta_ms, |
388 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms, | 334 trendline_estimator_->num_of_deltas(), |
389 kalman_estimator_->num_of_deltas(), | |
390 packet_feedback.arrival_time_ms); | 335 packet_feedback.arrival_time_ms); |
391 } | 336 } |
392 } | 337 } |
393 | 338 |
394 int probing_bps = 0; | 339 int probing_bps = 0; |
395 if (packet_feedback.pacing_info.probe_cluster_id != | 340 if (packet_feedback.pacing_info.probe_cluster_id != |
396 PacedPacketInfo::kNotAProbe) { | 341 PacedPacketInfo::kNotAProbe) { |
397 probing_bps = | 342 probing_bps = |
398 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback); | 343 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback); |
399 } | 344 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { | 423 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { |
479 // Called from both the configuration thread and the network thread. Shouldn't | 424 // Called from both the configuration thread and the network thread. Shouldn't |
480 // be called from the network thread in the future. | 425 // be called from the network thread in the future. |
481 rate_control_.SetMinBitrate(min_bitrate_bps); | 426 rate_control_.SetMinBitrate(min_bitrate_bps); |
482 } | 427 } |
483 | 428 |
484 int64_t DelayBasedBwe::GetProbingIntervalMs() const { | 429 int64_t DelayBasedBwe::GetProbingIntervalMs() const { |
485 return probing_interval_estimator_.GetIntervalMs(); | 430 return probing_interval_estimator_.GetIntervalMs(); |
486 } | 431 } |
487 } // namespace webrtc | 432 } // namespace webrtc |
OLD | NEW |