Chromium Code Reviews| Index: webrtc/modules/congestion_controller/delay_based_bwe.cc |
| diff --git a/webrtc/modules/congestion_controller/delay_based_bwe.cc b/webrtc/modules/congestion_controller/delay_based_bwe.cc |
| index 55d29fb430ebdb0eb4c8a8d50f7359bbfedb4afa..bd218e5f750684ad499ad8e6cf08ec24b7af371f 100644 |
| --- a/webrtc/modules/congestion_controller/delay_based_bwe.cc |
| +++ b/webrtc/modules/congestion_controller/delay_based_bwe.cc |
| @@ -35,16 +35,71 @@ constexpr double kTimestampToMs = |
| // This ssrc is used to fulfill the current API but will be removed |
| // after the API has been changed. |
| constexpr uint32_t kFixedSsrc = 0; |
| +constexpr int kRateWindowMs = 250; |
| + |
| } // namespace |
| namespace webrtc { |
| +DelayBasedBwe::RateEstimator::RateEstimator() |
| + : sum_(0), |
| + count_(0), |
| + bitrate_estimate_(300.0f), |
| + bitrate_estimate_std_(2000.0f) {} |
| + |
| +void DelayBasedBwe::RateEstimator::Update(int64_t now_ms, int bytes) { |
| + UpdateWindow(now_ms, bytes); |
| + RTC_DCHECK_GE(sum_, 0); |
| + RTC_DCHECK_GE(count_, 0); |
| + float bitrate_sample = 8.0f * sum_ / static_cast<float>(kRateWindowMs); |
| + // Define the sample uncertainty as a function of how far away it is from the |
| + // current estimate, and how many payloads it based on. |
|
terelius
2016/10/21 10:15:52
nit: it is based on
stefan-webrtc
2016/10/24 10:55:14
Done.
|
| + float sample_uncertainty = |
|
terelius
2016/10/21 10:15:52
This essentially means that we make smaller change
stefan-webrtc
2016/10/24 10:55:14
Yes, maybe. I'm worried that the window would have
terelius
2016/10/24 11:20:38
Maybe it is difficult to do what I suggested since
|
| + std::max(5 * (5 - count_), 1) * (bitrate_estimate_ - bitrate_sample); |
| + float sample_var = std::max(sample_uncertainty * sample_uncertainty, 1.0f); |
| + // Update a bayesian estimate of the rate, weighting it lower if the sample |
| + // uncertainty is large. |
| + // The bitrate estimate uncertainty is increased with each update to model |
| + // the possibility that the bitrate can change over time. |
| + // TODO(holmer): Consider increasing the uncertainty every N milliseconds |
| + // instead of every update. |
| + float bitrate_estimate_std = bitrate_estimate_std_ + 25.0f; |
| + float bitrate_estimate_var = bitrate_estimate_std * bitrate_estimate_std; |
| + float denom = 1.0f / sample_var + 1.0f / bitrate_estimate_var; |
| + bitrate_estimate_std_ = sqrt(1.0f / denom); |
| + bitrate_estimate_ = |
|
terelius
2016/10/21 10:15:52
I believe that the reason we are slow to recover f
stefan-webrtc
2016/10/24 10:55:14
Good point. The problem would occur if for instanc
|
| + (bitrate_estimate_ / bitrate_estimate_var + bitrate_sample / sample_var) * |
| + bitrate_estimate_std_ * bitrate_estimate_std_; |
|
terelius
2016/10/21 10:15:52
This update could alternatively be written as
est
stefan-webrtc
2016/10/24 10:55:14
Do you prefer that?
terelius
2016/10/24 11:20:38
I think I'd prefer
estimate = (sample_var * estima
stefan-webrtc
2016/10/25 11:04:33
Yes, the sums to 1 is a nice thing to show clearly
|
| +} |
| + |
| +void DelayBasedBwe::RateEstimator::UpdateWindow(int64_t now_ms, int bytes) { |
| + // Reset if time moves backwards. |
| + if (!payloads_.empty() && payloads_.back().first > now_ms) { |
| + payloads_.clear(); |
| + sum_ = 0; |
| + } |
| + payloads_.push_back(std::make_pair(now_ms, bytes)); |
| + sum_ += bytes; |
| + ++count_; |
| + while (!payloads_.empty()) { |
| + auto oldest = payloads_.front(); |
| + if (oldest.first > now_ms - kRateWindowMs) |
| + break; |
| + sum_ -= oldest.second; |
| + payloads_.pop_front(); |
| + --count_; |
| + } |
| +} |
| + |
| +int DelayBasedBwe::RateEstimator::bitrate_estimate() const { |
| + return bitrate_estimate_ * 1000; |
|
terelius
2016/10/21 10:15:52
Why multiply by 1000?
stefan-webrtc
2016/10/24 10:55:14
I wanted the returned value to be bits/s. Should p
terelius
2016/10/24 11:20:38
Oh, right. It would have been bits/ms otherwise.
|
| +} |
| DelayBasedBwe::DelayBasedBwe(Clock* clock) |
| : clock_(clock), |
| inter_arrival_(), |
| estimator_(), |
| detector_(OverUseDetectorOptions()), |
| - receiver_incoming_bitrate_(kBitrateWindowMs, 8000), |
| + receiver_incoming_bitrate_(), |
| last_update_ms_(-1), |
| last_seen_packet_ms_(-1), |
| uma_recorded_(false) { |
| @@ -73,7 +128,7 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo( |
| const PacketInfo& info) { |
| int64_t now_ms = clock_->TimeInMilliseconds(); |
| - receiver_incoming_bitrate_.Update(info.payload_size, info.arrival_time_ms); |
| + receiver_incoming_bitrate_.Update(info.arrival_time_ms, info.payload_size); |
| Result result; |
| // Reset if the stream has timed out. |
| if (last_seen_packet_ms_ == -1 || |
| @@ -113,29 +168,28 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo( |
| probing_bps = probe_bitrate_estimator_.HandleProbeAndEstimateBitrate(info); |
| } |
| + int acked_bitrate_bps = receiver_incoming_bitrate_.bitrate_estimate(); |
| // Currently overusing the bandwidth. |
| if (detector_.State() == kBwOverusing) { |
| - rtc::Optional<uint32_t> incoming_rate = |
| - receiver_incoming_bitrate_.Rate(info.arrival_time_ms); |
| - if (incoming_rate && |
| - rate_control_.TimeToReduceFurther(now_ms, *incoming_rate)) { |
| - result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, |
| - &result.target_bitrate_bps); |
| + if (rate_control_.TimeToReduceFurther(now_ms, acked_bitrate_bps)) { |
| + result.updated = |
| + UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
| + &result.target_bitrate_bps); |
| } |
| } else if (probing_bps > 0) { |
| // No overuse, but probing measured a bitrate. |
| rate_control_.SetEstimate(probing_bps, info.arrival_time_ms); |
| result.probe = true; |
| - result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, |
| - &result.target_bitrate_bps); |
| + result.updated = |
| + UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
| + &result.target_bitrate_bps); |
| } |
| - rtc::Optional<uint32_t> incoming_rate = |
| - receiver_incoming_bitrate_.Rate(info.arrival_time_ms); |
| if (!result.updated && |
| (last_update_ms_ == -1 || |
| now_ms - last_update_ms_ > rate_control_.GetFeedbackInterval())) { |
| - result.updated = UpdateEstimate(info.arrival_time_ms, now_ms, |
| - &result.target_bitrate_bps); |
| + result.updated = |
| + UpdateEstimate(info.arrival_time_ms, now_ms, acked_bitrate_bps, |
| + &result.target_bitrate_bps); |
| } |
| if (result.updated) |
| last_update_ms_ = now_ms; |
| @@ -145,12 +199,12 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketInfo( |
| bool DelayBasedBwe::UpdateEstimate(int64_t arrival_time_ms, |
| int64_t now_ms, |
| + int acked_bitrate_bps, |
| uint32_t* target_bitrate_bps) { |
| - // The first overuse should immediately trigger a new estimate. |
| - // We also have to update the estimate immediately if we are overusing |
| - // and the target bitrate is too high compared to what we are receiving. |
| + if (acked_bitrate_bps <= 0) |
| + return false; |
| const RateControlInput input(detector_.State(), |
| - receiver_incoming_bitrate_.Rate(arrival_time_ms), |
| + rtc::Optional<uint32_t>(acked_bitrate_bps), |
| estimator_->var_noise()); |
| rate_control_.Update(&input, now_ms); |
| *target_bitrate_bps = rate_control_.UpdateBandwidthEstimate(now_ms); |