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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 | 148 |
149 namespace webrtc { | 149 namespace webrtc { |
150 | 150 |
151 DelayBasedBwe::BitrateEstimator::BitrateEstimator() | 151 DelayBasedBwe::BitrateEstimator::BitrateEstimator() |
152 : sum_(0), | 152 : sum_(0), |
153 current_win_ms_(0), | 153 current_win_ms_(0), |
154 prev_time_ms_(-1), | 154 prev_time_ms_(-1), |
155 bitrate_estimate_(-1.0f), | 155 bitrate_estimate_(-1.0f), |
156 bitrate_estimate_var_(50.0f), | 156 bitrate_estimate_var_(50.0f), |
157 old_estimator_(kBitrateWindowMs, 8000), | 157 old_estimator_(kBitrateWindowMs, 8000), |
158 in_experiment_(BitrateEstimateExperimentIsEnabled()) {} | 158 in_experiment_(BitrateEstimateExperimentIsEnabled()), |
159 last_result_was_valid_(false) {} | |
159 | 160 |
160 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) { | 161 void DelayBasedBwe::BitrateEstimator::Update(int64_t now_ms, int bytes) { |
161 if (!in_experiment_) { | 162 if (!in_experiment_) { |
162 old_estimator_.Update(bytes, now_ms); | 163 old_estimator_.Update(bytes, now_ms); |
163 rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms); | 164 rtc::Optional<uint32_t> rate = old_estimator_.Rate(now_ms); |
164 bitrate_estimate_ = -1.0f; | 165 bitrate_estimate_ = -1.0f; |
165 if (rate) | 166 if (rate) { |
166 bitrate_estimate_ = *rate / 1000.0f; | 167 bitrate_estimate_ = *rate / 1000.0f; |
168 last_result_was_valid_ = true; | |
terelius
2017/03/29 15:14:29
I'm a little bit worried that this might reset the
michaelt
2017/04/11 11:04:33
Ok the hack is removed.
| |
169 } else if (last_result_was_valid_) { | |
170 old_estimator_.Reset(); | |
171 last_result_was_valid_ = false; | |
172 } | |
167 return; | 173 return; |
168 } | 174 } |
169 int rate_window_ms = kRateWindowMs; | 175 int rate_window_ms = kRateWindowMs; |
170 // We use a larger window at the beginning to get a more stable sample that | 176 // We use a larger window at the beginning to get a more stable sample that |
171 // we can use to initialize the estimate. | 177 // we can use to initialize the estimate. |
172 if (bitrate_estimate_ < 0.f) | 178 if (bitrate_estimate_ < 0.f) |
173 rate_window_ms = kInitialRateWindowMs; | 179 rate_window_ms = kInitialRateWindowMs; |
174 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms); | 180 float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms); |
175 if (bitrate_sample < 0.0f) | 181 if (bitrate_sample < 0.0f) |
176 return; | 182 return; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock) | 239 DelayBasedBwe::DelayBasedBwe(RtcEventLog* event_log, const Clock* clock) |
234 : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()), | 240 : in_trendline_experiment_(TrendlineFilterExperimentIsEnabled()), |
235 in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()), | 241 in_median_slope_experiment_(MedianSlopeFilterExperimentIsEnabled()), |
236 event_log_(event_log), | 242 event_log_(event_log), |
237 clock_(clock), | 243 clock_(clock), |
238 inter_arrival_(), | 244 inter_arrival_(), |
239 kalman_estimator_(), | 245 kalman_estimator_(), |
240 trendline_estimator_(), | 246 trendline_estimator_(), |
241 detector_(), | 247 detector_(), |
242 receiver_incoming_bitrate_(), | 248 receiver_incoming_bitrate_(), |
243 last_update_ms_(-1), | |
244 last_seen_packet_ms_(-1), | 249 last_seen_packet_ms_(-1), |
245 uma_recorded_(false), | 250 uma_recorded_(false), |
246 probe_bitrate_estimator_(event_log), | 251 probe_bitrate_estimator_(event_log), |
247 trendline_window_size_(kDefaultTrendlineWindowSize), | 252 trendline_window_size_(kDefaultTrendlineWindowSize), |
248 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff), | 253 trendline_smoothing_coeff_(kDefaultTrendlineSmoothingCoeff), |
249 trendline_threshold_gain_(kDefaultTrendlineThresholdGain), | 254 trendline_threshold_gain_(kDefaultTrendlineThresholdGain), |
250 probing_interval_estimator_(&rate_control_), | 255 probing_interval_estimator_(&rate_control_), |
251 median_slope_window_size_(kDefaultMedianSlopeWindowSize), | 256 median_slope_window_size_(kDefaultMedianSlopeWindowSize), |
252 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain), | 257 median_slope_threshold_gain_(kDefaultMedianSlopeThresholdGain), |
253 consecutive_delayed_feedbacks_(0), | 258 consecutive_delayed_feedbacks_(0), |
(...skipping 29 matching lines...) Expand all Loading... | |
283 std::vector<PacketFeedback> sorted_packet_feedback_vector; | 288 std::vector<PacketFeedback> sorted_packet_feedback_vector; |
284 SortPacketFeedbackVector(packet_feedback_vector, | 289 SortPacketFeedbackVector(packet_feedback_vector, |
285 &sorted_packet_feedback_vector); | 290 &sorted_packet_feedback_vector); |
286 | 291 |
287 if (!uma_recorded_) { | 292 if (!uma_recorded_) { |
288 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, | 293 RTC_HISTOGRAM_ENUMERATION(kBweTypeHistogram, |
289 BweNames::kSendSideTransportSeqNum, | 294 BweNames::kSendSideTransportSeqNum, |
290 BweNames::kBweNamesMax); | 295 BweNames::kBweNamesMax); |
291 uma_recorded_ = true; | 296 uma_recorded_ = true; |
292 } | 297 } |
293 Result aggregated_result; | 298 bool overusing = false; |
294 bool delayed_feedback = true; | 299 bool delayed_feedback = true; |
295 for (const auto& packet_feedback : sorted_packet_feedback_vector) { | 300 for (const auto& packet_feedback : sorted_packet_feedback_vector) { |
296 if (packet_feedback.send_time_ms < 0) | 301 if (packet_feedback.send_time_ms < 0) |
297 continue; | 302 continue; |
298 delayed_feedback = false; | 303 delayed_feedback = false; |
299 Result result = IncomingPacketFeedback(packet_feedback); | 304 IncomingPacketFeedback(packet_feedback); |
300 if (result.updated) | 305 overusing |= detector_.State() == kBwOverusing; |
301 aggregated_result = result; | |
302 } | 306 } |
303 if (delayed_feedback) { | 307 if (delayed_feedback) { |
304 ++consecutive_delayed_feedbacks_; | 308 ++consecutive_delayed_feedbacks_; |
305 } else { | 309 } else { |
306 consecutive_delayed_feedbacks_ = 0; | 310 consecutive_delayed_feedbacks_ = 0; |
307 } | 311 } |
308 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) { | 312 if (consecutive_delayed_feedbacks_ >= kMaxConsecutiveFailedLookups) { |
309 aggregated_result = OnLongFeedbackDelay( | 313 consecutive_delayed_feedbacks_ = 0; |
314 return OnLongFeedbackDelay( | |
310 sorted_packet_feedback_vector.back().arrival_time_ms); | 315 sorted_packet_feedback_vector.back().arrival_time_ms); |
311 consecutive_delayed_feedbacks_ = 0; | |
312 } | 316 } |
313 return aggregated_result; | 317 return MaybeUpdateEstimate(overusing); |
314 } | 318 } |
315 | 319 |
316 DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay( | 320 DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay( |
317 int64_t arrival_time_ms) { | 321 int64_t arrival_time_ms) { |
318 // Estimate should always be valid since a start bitrate always is set in the | 322 // Estimate should always be valid since a start bitrate always is set in the |
319 // Call constructor. An alternative would be to return an empty Result here, | 323 // Call constructor. An alternative would be to return an empty Result here, |
320 // or to estimate the throughput based on the feedback we received. | 324 // or to estimate the throughput based on the feedback we received. |
321 RTC_DCHECK(rate_control_.ValidEstimate()); | 325 RTC_DCHECK(rate_control_.ValidEstimate()); |
322 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, | 326 rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, |
323 arrival_time_ms); | 327 arrival_time_ms); |
324 Result result; | 328 Result result; |
325 result.updated = true; | 329 result.updated = true; |
326 result.probe = false; | 330 result.probe = false; |
327 result.target_bitrate_bps = rate_control_.LatestEstimate(); | 331 result.target_bitrate_bps = rate_control_.LatestEstimate(); |
328 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to " | 332 LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to " |
329 << result.target_bitrate_bps; | 333 << result.target_bitrate_bps; |
330 return result; | 334 return result; |
331 } | 335 } |
332 | 336 |
333 DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedback( | 337 void DelayBasedBwe::IncomingPacketFeedback( |
334 const PacketFeedback& packet_feedback) { | 338 const PacketFeedback& packet_feedback) { |
335 int64_t now_ms = clock_->TimeInMilliseconds(); | 339 int64_t now_ms = clock_->TimeInMilliseconds(); |
336 | 340 |
337 receiver_incoming_bitrate_.Update(packet_feedback.arrival_time_ms, | 341 receiver_incoming_bitrate_.Update(packet_feedback.arrival_time_ms, |
338 packet_feedback.payload_size); | 342 packet_feedback.payload_size); |
339 Result result; | 343 Result result; |
340 // Reset if the stream has timed out. | 344 // Reset if the stream has timed out. |
341 if (last_seen_packet_ms_ == -1 || | 345 if (last_seen_packet_ms_ == -1 || |
342 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { | 346 now_ms - last_seen_packet_ms_ > kStreamTimeOutMs) { |
343 inter_arrival_.reset( | 347 inter_arrival_.reset( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 packet_feedback.arrival_time_ms); | 388 packet_feedback.arrival_time_ms); |
385 } else { | 389 } else { |
386 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta, | 390 kalman_estimator_->Update(t_delta, ts_delta_ms, size_delta, |
387 detector_.State(), | 391 detector_.State(), |
388 packet_feedback.arrival_time_ms); | 392 packet_feedback.arrival_time_ms); |
389 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms, | 393 detector_.Detect(kalman_estimator_->offset(), ts_delta_ms, |
390 kalman_estimator_->num_of_deltas(), | 394 kalman_estimator_->num_of_deltas(), |
391 packet_feedback.arrival_time_ms); | 395 packet_feedback.arrival_time_ms); |
392 } | 396 } |
393 } | 397 } |
394 | |
395 int probing_bps = 0; | |
396 if (packet_feedback.pacing_info.probe_cluster_id != | 398 if (packet_feedback.pacing_info.probe_cluster_id != |
397 PacedPacketInfo::kNotAProbe) { | 399 PacedPacketInfo::kNotAProbe) { |
398 probing_bps = | 400 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback); |
399 probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(packet_feedback); | |
400 } | 401 } |
402 } | |
403 | |
404 DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(bool overusing) { | |
405 Result result; | |
401 rtc::Optional<uint32_t> acked_bitrate_bps = | 406 rtc::Optional<uint32_t> acked_bitrate_bps = |
402 receiver_incoming_bitrate_.bitrate_bps(); | 407 receiver_incoming_bitrate_.bitrate_bps(); |
408 int64_t now_ms = clock_->TimeInMilliseconds(); | |
409 rtc::Optional<int> probe_bitrate_bps = | |
410 probe_bitrate_estimator_.FetchAndResetLastEstimatedBitrateBps(); | |
403 // Currently overusing the bandwidth. | 411 // Currently overusing the bandwidth. |
404 if (detector_.State() == kBwOverusing) { | 412 if (overusing) { |
405 if (acked_bitrate_bps && | 413 if (acked_bitrate_bps && |
406 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) { | 414 rate_control_.TimeToReduceFurther(now_ms, *acked_bitrate_bps)) { |
407 result.updated = | 415 result.updated = |
408 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms, | 416 UpdateEstimate(now_ms, acked_bitrate_bps, overusing, &result); |
409 acked_bitrate_bps, &result.target_bitrate_bps); | |
410 } | 417 } |
411 } else if (probing_bps > 0) { | 418 } else { |
412 // No overuse, but probing measured a bitrate. | 419 if (probe_bitrate_bps) { |
413 rate_control_.SetEstimate(probing_bps, packet_feedback.arrival_time_ms); | 420 rate_control_.SetEstimate(*probe_bitrate_bps, now_ms); |
414 result.probe = true; | 421 result.probe = true; |
422 } | |
415 result.updated = | 423 result.updated = |
416 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms, | 424 UpdateEstimate(now_ms, acked_bitrate_bps, overusing, &result); |
417 acked_bitrate_bps, &result.target_bitrate_bps); | |
418 } | |
419 if (!result.updated && | |
420 (last_update_ms_ == -1 || | |
421 now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) { | |
422 result.updated = | |
423 UpdateEstimate(packet_feedback.arrival_time_ms, now_ms, | |
424 acked_bitrate_bps, &result.target_bitrate_bps); | |
425 } | 425 } |
426 if (result.updated) { | 426 if (result.updated) { |
427 last_update_ms_ = now_ms; | |
428 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms, | 427 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms, |
429 result.target_bitrate_bps); | 428 result.target_bitrate_bps); |
430 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ || | 429 if (event_log_ && (result.target_bitrate_bps != last_logged_bitrate_ || |
431 detector_.State() != last_logged_state_)) { | 430 detector_.State() != last_logged_state_)) { |
432 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps, | 431 event_log_->LogDelayBasedBweUpdate(result.target_bitrate_bps, |
433 detector_.State()); | 432 detector_.State()); |
434 last_logged_bitrate_ = result.target_bitrate_bps; | 433 last_logged_bitrate_ = result.target_bitrate_bps; |
435 last_logged_state_ = detector_.State(); | 434 last_logged_state_ = detector_.State(); |
436 } | 435 } |
437 } | 436 } |
438 | |
439 return result; | 437 return result; |
440 } | 438 } |
441 | 439 |
442 bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, | 440 bool DelayBasedBwe::UpdateEstimate(int64_t now_ms, |
443 int64_t now_ms, | |
444 rtc::Optional<uint32_t> acked_bitrate_bps, | 441 rtc::Optional<uint32_t> acked_bitrate_bps, |
445 uint32_t* target_bitrate_bps) { | 442 bool overusing, |
443 Result* result) { | |
446 // TODO(terelius): RateControlInput::noise_var is deprecated and will be | 444 // TODO(terelius): RateControlInput::noise_var is deprecated and will be |
447 // removed. In the meantime, we set it to zero. | 445 // removed. In the meantime, we set it to zero. |
448 const RateControlInput input(detector_.State(), acked_bitrate_bps, 0); | 446 const RateControlInput input(overusing ? kBwOverusing : detector_.State(), |
447 acked_bitrate_bps, 0); | |
449 rate_control_.Update(&input, now_ms); | 448 rate_control_.Update(&input, now_ms); |
450 *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); | 449 result->target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); |
450 BWE_TEST_LOGGING_PLOT(1, "target_bitrate_bps", now_ms, | |
451 result->target_bitrate_bps); | |
451 return rate_control_.ValidEstimate(); | 452 return rate_control_.ValidEstimate(); |
452 } | 453 } |
453 | 454 |
454 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { | 455 void DelayBasedBwe::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { |
455 rate_control_.SetRtt(avg_rtt_ms); | 456 rate_control_.SetRtt(avg_rtt_ms); |
456 } | 457 } |
457 | 458 |
458 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, | 459 bool DelayBasedBwe::LatestEstimate(std::vector<uint32_t>* ssrcs, |
459 uint32_t* bitrate_bps) const { | 460 uint32_t* bitrate_bps) const { |
460 // Currently accessed from both the process thread (see | 461 // Currently accessed from both the process thread (see |
(...skipping 18 matching lines...) Expand all Loading... | |
479 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { | 480 void DelayBasedBwe::SetMinBitrate(int min_bitrate_bps) { |
480 // Called from both the configuration thread and the network thread. Shouldn't | 481 // Called from both the configuration thread and the network thread. Shouldn't |
481 // be called from the network thread in the future. | 482 // be called from the network thread in the future. |
482 rate_control_.SetMinBitrate(min_bitrate_bps); | 483 rate_control_.SetMinBitrate(min_bitrate_bps); |
483 } | 484 } |
484 | 485 |
485 int64_t DelayBasedBwe::GetProbingIntervalMs() const { | 486 int64_t DelayBasedBwe::GetProbingIntervalMs() const { |
486 return probing_interval_estimator_.GetIntervalMs(); | 487 return probing_interval_estimator_.GetIntervalMs(); |
487 } | 488 } |
488 } // namespace webrtc | 489 } // namespace webrtc |
OLD | NEW |