| 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 |