From 5f0099596439a34a7534bf5557423db1f622989f Mon Sep 17 00:00:00 2001 From: Sebastian Jansson Date: Mon, 19 Nov 2018 18:02:20 +0100 Subject: [PATCH] Using unit classes in AimdRateControl. Bug: webrtc:9718 Change-Id: I1efed4e55c9d1ccec3c32ed012cb3cd82d7f4ee8 Reviewed-on: https://webrtc-review.googlesource.com/c/110788 Commit-Queue: Sebastian Jansson Reviewed-by: Christoffer Rodbro Cr-Commit-Position: refs/heads/master@{#25705} --- .../goog_cc/delay_based_bwe.cc | 33 +- modules/remote_bitrate_estimator/BUILD.gn | 1 + .../aimd_rate_control.cc | 282 +++++++++--------- .../aimd_rate_control.h | 69 +++-- .../aimd_rate_control_unittest.cc | 109 +++---- .../remote_bitrate_estimator/bwe_defines.cc | 4 +- .../include/bwe_defines.h | 4 +- .../remote_bitrate_estimator_abs_send_time.cc | 34 ++- .../remote_bitrate_estimator_single_stream.cc | 27 +- ...itrate_estimator_single_stream_unittest.cc | 2 +- 10 files changed, 298 insertions(+), 267 deletions(-) diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 60f52a17f4..7a1ee117bd 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -175,12 +175,11 @@ DelayBasedBwe::Result DelayBasedBwe::OnLongFeedbackDelay( // Call constructor. An alternative would be to return an empty Result here, // or to estimate the throughput based on the feedback we received. RTC_DCHECK(rate_control_.ValidEstimate()); - rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, - arrival_time.ms()); + rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, arrival_time); Result result; result.updated = true; result.probe = false; - result.target_bitrate = DataRate::bps(rate_control_.LatestEstimate()); + result.target_bitrate = rate_control_.LatestEstimate(); RTC_LOG(LS_WARNING) << "Long feedback delay detected, reducing BWE to " << ToString(result.target_bitrate); return result; @@ -239,27 +238,26 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( // Currently overusing the bandwidth. if (delay_detector_->State() == BandwidthUsage::kBwOverusing) { if (acked_bitrate && - rate_control_.TimeToReduceFurther(at_time.ms(), acked_bitrate->bps())) { + rate_control_.TimeToReduceFurther(at_time, *acked_bitrate)) { result.updated = UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); } else if (!acked_bitrate && rate_control_.ValidEstimate() && - rate_control_.InitialTimeToReduceFurther(at_time.ms())) { + rate_control_.InitialTimeToReduceFurther(at_time)) { // Overusing before we have a measured acknowledged bitrate. Reduce send // rate by 50% every 200 ms. // TODO(tschumim): Improve this and/or the acknowledged bitrate estimator // so that we (almost) always have a bitrate estimate. - rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, - at_time.ms()); + rate_control_.SetEstimate(rate_control_.LatestEstimate() / 2, at_time); result.updated = true; result.probe = false; - result.target_bitrate = DataRate::bps(rate_control_.LatestEstimate()); + result.target_bitrate = rate_control_.LatestEstimate(); } } else { if (probe_bitrate) { result.probe = true; result.updated = true; result.target_bitrate = *probe_bitrate; - rate_control_.SetEstimate(probe_bitrate->bps(), at_time.ms()); + rate_control_.SetEstimate(*probe_bitrate, at_time); } else { result.updated = UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); @@ -287,16 +285,13 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( bool DelayBasedBwe::UpdateEstimate(Timestamp at_time, absl::optional acked_bitrate, DataRate* target_rate) { - absl::optional acked_bitrate_bps; - if (acked_bitrate) - acked_bitrate_bps = acked_bitrate->bps(); - const RateControlInput input(delay_detector_->State(), acked_bitrate_bps); - *target_rate = DataRate::bps(rate_control_.Update(&input, at_time.ms())); + const RateControlInput input(delay_detector_->State(), acked_bitrate); + *target_rate = rate_control_.Update(&input, at_time); return rate_control_.ValidEstimate(); } void DelayBasedBwe::OnRttUpdate(TimeDelta avg_rtt) { - rate_control_.SetRtt(avg_rtt.ms()); + rate_control_.SetRtt(avg_rtt); } bool DelayBasedBwe::LatestEstimate(std::vector* ssrcs, @@ -311,23 +306,23 @@ bool DelayBasedBwe::LatestEstimate(std::vector* ssrcs, return false; *ssrcs = {kFixedSsrc}; - *bitrate = DataRate::bps(rate_control_.LatestEstimate()); + *bitrate = rate_control_.LatestEstimate(); return true; } void DelayBasedBwe::SetStartBitrate(DataRate start_bitrate) { RTC_LOG(LS_INFO) << "BWE Setting start bitrate to: " << ToString(start_bitrate); - rate_control_.SetStartBitrate(start_bitrate.bps()); + rate_control_.SetStartBitrate(start_bitrate); } void DelayBasedBwe::SetMinBitrate(DataRate min_bitrate) { // Called from both the configuration thread and the network thread. Shouldn't // be called from the network thread in the future. - rate_control_.SetMinBitrate(min_bitrate.bps()); + rate_control_.SetMinBitrate(min_bitrate); } TimeDelta DelayBasedBwe::GetExpectedBwePeriod() const { - return TimeDelta::ms(rate_control_.GetExpectedBandwidthPeriodMs()); + return rate_control_.GetExpectedBandwidthPeriod(); } } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn index f21c6d89e4..f6991ea69d 100644 --- a/modules/remote_bitrate_estimator/BUILD.gn +++ b/modules/remote_bitrate_estimator/BUILD.gn @@ -42,6 +42,7 @@ rtc_static_library("remote_bitrate_estimator") { deps = [ "../..:webrtc_common", "../../api/units:data_rate", + "../../api/units:timestamp", "../../modules:module_api", "../../modules:module_api_public", "../../modules/rtp_rtcp:rtp_rtcp_format", diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.cc b/modules/remote_bitrate_estimator/aimd_rate_control.cc index a992e7f064..4c917765ac 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -26,10 +26,9 @@ namespace webrtc { -static const int64_t kDefaultRttMs = 200; -static const int64_t kMaxFeedbackIntervalMs = 1000; -static const float kDefaultBackoffFactor = 0.85f; -static const int64_t kDefaultInitialBackOffIntervalMs = 200; +constexpr TimeDelta kDefaultRtt = TimeDelta::Millis<200>(); +constexpr float kDefaultBackoffFactor = 0.85f; +constexpr TimeDelta kDefaultInitialBackOffInterval = TimeDelta::Millis<200>(); const char kBweBackOffFactorExperiment[] = "WebRTC-BweBackOffFactor"; const char kBweInitialBackOffIntervalExperiment[] = @@ -55,7 +54,7 @@ float ReadBackoffFactor() { return kDefaultBackoffFactor; } -int64_t ReadInitialBackoffIntervalMs() { +TimeDelta ReadInitialBackoffInterval() { std::string experiment_string = webrtc::field_trial::FindFullName(kBweInitialBackOffIntervalExperiment); int64_t backoff_interval; @@ -63,7 +62,7 @@ int64_t ReadInitialBackoffIntervalMs() { sscanf(experiment_string.c_str(), "Enabled-%" SCNd64, &backoff_interval); if (parsed_values == 1) { if (10 <= backoff_interval && backoff_interval <= 200) { - return backoff_interval; + return TimeDelta::ms(backoff_interval); } RTC_LOG(WARNING) << "Initial back-off interval must be between 10 and 200 ms."; @@ -71,188 +70,193 @@ int64_t ReadInitialBackoffIntervalMs() { RTC_LOG(LS_WARNING) << "Failed to parse parameters for " << kBweInitialBackOffIntervalExperiment << " experiment. Using default."; - return kDefaultInitialBackOffIntervalMs; + return kDefaultInitialBackOffInterval; } AimdRateControl::AimdRateControl() - : min_configured_bitrate_bps_(congestion_controller::GetMinBitrateBps()), - max_configured_bitrate_bps_(30000000), - current_bitrate_bps_(max_configured_bitrate_bps_), - latest_estimated_throughput_bps_(current_bitrate_bps_), + : min_configured_bitrate_(congestion_controller::GetMinBitrate()), + max_configured_bitrate_(DataRate::kbps(30000)), + current_bitrate_(max_configured_bitrate_), + latest_estimated_throughput_(current_bitrate_), avg_max_bitrate_kbps_(-1.0f), var_max_bitrate_kbps_(0.4f), rate_control_state_(kRcHold), rate_control_region_(kRcMaxUnknown), - time_last_bitrate_change_(-1), - time_last_bitrate_decrease_(-1), - time_first_throughput_estimate_(-1), + time_last_bitrate_change_(Timestamp::MinusInfinity()), + time_last_bitrate_decrease_(Timestamp::MinusInfinity()), + time_first_throughput_estimate_(Timestamp::MinusInfinity()), bitrate_is_initialized_(false), beta_(webrtc::field_trial::IsEnabled(kBweBackOffFactorExperiment) ? ReadBackoffFactor() : kDefaultBackoffFactor), - rtt_(kDefaultRttMs), + rtt_(kDefaultRtt), in_experiment_(!AdaptiveThresholdExperimentIsDisabled()), smoothing_experiment_( webrtc::field_trial::IsEnabled("WebRTC-Audio-BandwidthSmoothing")), in_initial_backoff_interval_experiment_( webrtc::field_trial::IsEnabled(kBweInitialBackOffIntervalExperiment)), - initial_backoff_interval_ms_(kDefaultInitialBackOffIntervalMs) { + initial_backoff_interval_(kDefaultInitialBackOffInterval) { if (in_initial_backoff_interval_experiment_) { - initial_backoff_interval_ms_ = ReadInitialBackoffIntervalMs(); + initial_backoff_interval_ = ReadInitialBackoffInterval(); RTC_LOG(LS_INFO) << "Using aimd rate control with initial back-off interval" - << " " << initial_backoff_interval_ms_ << " ms."; + << " " << ToString(initial_backoff_interval_) << "."; } RTC_LOG(LS_INFO) << "Using aimd rate control with back off factor " << beta_; } AimdRateControl::~AimdRateControl() {} -void AimdRateControl::SetStartBitrate(int start_bitrate_bps) { - current_bitrate_bps_ = start_bitrate_bps; - latest_estimated_throughput_bps_ = current_bitrate_bps_; +void AimdRateControl::SetStartBitrate(DataRate start_bitrate) { + current_bitrate_ = start_bitrate; + latest_estimated_throughput_ = current_bitrate_; bitrate_is_initialized_ = true; } -void AimdRateControl::SetMinBitrate(int min_bitrate_bps) { - min_configured_bitrate_bps_ = min_bitrate_bps; - current_bitrate_bps_ = std::max(min_bitrate_bps, current_bitrate_bps_); +void AimdRateControl::SetMinBitrate(DataRate min_bitrate) { + min_configured_bitrate_ = min_bitrate; + current_bitrate_ = std::max(min_bitrate, current_bitrate_); } bool AimdRateControl::ValidEstimate() const { return bitrate_is_initialized_; } -int64_t AimdRateControl::GetFeedbackInterval() const { +TimeDelta AimdRateControl::GetFeedbackInterval() const { // Estimate how often we can send RTCP if we allocate up to 5% of bandwidth // to feedback. - static const int kRtcpSize = 80; - const int64_t interval = static_cast( - kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5); - const int64_t kMinFeedbackIntervalMs = 200; - return rtc::SafeClamp(interval, kMinFeedbackIntervalMs, - kMaxFeedbackIntervalMs); + const DataSize kRtcpSize = DataSize::bytes(80); + const DataRate rtcp_bitrate = current_bitrate_ * 0.05; + const TimeDelta interval = kRtcpSize / rtcp_bitrate; + const TimeDelta kMinFeedbackInterval = TimeDelta::ms(200); + const TimeDelta kMaxFeedbackInterval = TimeDelta::ms(1000); + return interval.Clamped(kMinFeedbackInterval, kMaxFeedbackInterval); } -bool AimdRateControl::TimeToReduceFurther( - int64_t now_ms, - uint32_t estimated_throughput_bps) const { - const int64_t bitrate_reduction_interval = - std::max(std::min(rtt_, 200), 10); - if (now_ms - time_last_bitrate_change_ >= bitrate_reduction_interval) { +bool AimdRateControl::TimeToReduceFurther(Timestamp at_time, + DataRate estimated_throughput) const { + const TimeDelta bitrate_reduction_interval = + rtt_.Clamped(TimeDelta::ms(10), TimeDelta::ms(200)); + if (at_time - time_last_bitrate_change_ >= bitrate_reduction_interval) { return true; } if (ValidEstimate()) { // TODO(terelius/holmer): Investigate consequences of increasing // the threshold to 0.95 * LatestEstimate(). - const uint32_t threshold = static_cast(0.5 * LatestEstimate()); - return estimated_throughput_bps < threshold; + const DataRate threshold = 0.5 * LatestEstimate(); + return estimated_throughput < threshold; } return false; } -bool AimdRateControl::InitialTimeToReduceFurther(int64_t now_ms) const { +bool AimdRateControl::InitialTimeToReduceFurther(Timestamp at_time) const { if (!in_initial_backoff_interval_experiment_) { return ValidEstimate() && - TimeToReduceFurther(now_ms, LatestEstimate() / 2 - 1); + TimeToReduceFurther(at_time, + LatestEstimate() / 2 - DataRate::bps(1)); } // TODO(terelius): We could use the RTT (clamped to suitable limits) instead // of a fixed bitrate_reduction_interval. - if (time_last_bitrate_decrease_ == -1 || - now_ms - time_last_bitrate_decrease_ >= initial_backoff_interval_ms_) { + if (time_last_bitrate_decrease_.IsInfinite() || + at_time - time_last_bitrate_decrease_ >= initial_backoff_interval_) { return true; } return false; } -uint32_t AimdRateControl::LatestEstimate() const { - return current_bitrate_bps_; +DataRate AimdRateControl::LatestEstimate() const { + return current_bitrate_; } -void AimdRateControl::SetRtt(int64_t rtt) { +void AimdRateControl::SetRtt(TimeDelta rtt) { rtt_ = rtt; } -uint32_t AimdRateControl::Update(const RateControlInput* input, - int64_t now_ms) { +DataRate AimdRateControl::Update(const RateControlInput* input, + Timestamp at_time) { RTC_CHECK(input); // Set the initial bit rate value to what we're receiving the first half // second. // TODO(bugs.webrtc.org/9379): The comment above doesn't match to the code. if (!bitrate_is_initialized_) { - const int64_t kInitializationTimeMs = 5000; - RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTimeMs); - if (time_first_throughput_estimate_ < 0) { - if (input->estimated_throughput_bps) - time_first_throughput_estimate_ = now_ms; - } else if (now_ms - time_first_throughput_estimate_ > - kInitializationTimeMs && - input->estimated_throughput_bps) { - current_bitrate_bps_ = *input->estimated_throughput_bps; + const TimeDelta kInitializationTime = TimeDelta::seconds(5); + RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTime.ms()); + if (time_first_throughput_estimate_.IsInfinite()) { + if (input->estimated_throughput) + time_first_throughput_estimate_ = at_time; + } else if (at_time - time_first_throughput_estimate_ > + kInitializationTime && + input->estimated_throughput) { + current_bitrate_ = *input->estimated_throughput; bitrate_is_initialized_ = true; } } - current_bitrate_bps_ = ChangeBitrate(current_bitrate_bps_, *input, now_ms); - return current_bitrate_bps_; + current_bitrate_ = ChangeBitrate(current_bitrate_, *input, at_time); + return current_bitrate_; } -void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) { +void AimdRateControl::SetEstimate(DataRate bitrate, Timestamp at_time) { bitrate_is_initialized_ = true; - uint32_t prev_bitrate_bps = current_bitrate_bps_; - current_bitrate_bps_ = ClampBitrate(bitrate_bps, bitrate_bps); - time_last_bitrate_change_ = now_ms; - if (current_bitrate_bps_ < prev_bitrate_bps) { - time_last_bitrate_decrease_ = now_ms; + DataRate prev_bitrate = current_bitrate_; + current_bitrate_ = ClampBitrate(bitrate, bitrate); + time_last_bitrate_change_ = at_time; + if (current_bitrate_ < prev_bitrate) { + time_last_bitrate_decrease_ = at_time; } } -int AimdRateControl::GetNearMaxIncreaseRateBps() const { - RTC_DCHECK_GT(current_bitrate_bps_, 0); - double bits_per_frame = static_cast(current_bitrate_bps_) / 30.0; - double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0)); - double avg_packet_size_bits = bits_per_frame / packets_per_frame; +double AimdRateControl::GetNearMaxIncreaseRateBpsPerSecond() const { + RTC_DCHECK(!current_bitrate_.IsZero()); + const TimeDelta kFrameInterval = TimeDelta::seconds(1) / 30; + DataSize frame_size = current_bitrate_ * kFrameInterval; + const DataSize kPacketSize = DataSize::bytes(1200); + double packets_per_frame = std::ceil(frame_size / kPacketSize); + DataSize avg_packet_size = frame_size / packets_per_frame; // Approximate the over-use estimator delay to 100 ms. - const int64_t response_time = in_experiment_ ? (rtt_ + 100) * 2 : rtt_ + 100; - constexpr double kMinIncreaseRateBps = 4000; - return static_cast(std::max( - kMinIncreaseRateBps, (avg_packet_size_bits * 1000) / response_time)); + TimeDelta response_time = rtt_ + TimeDelta::ms(100); + if (in_experiment_) + response_time = response_time * 2; + double increase_rate_bps_per_second = + (avg_packet_size / response_time).bps(); + double kMinIncreaseRateBpsPerSecond = 4000; + return std::max(kMinIncreaseRateBpsPerSecond, increase_rate_bps_per_second); } -int AimdRateControl::GetExpectedBandwidthPeriodMs() const { - const int kMinPeriodMs = smoothing_experiment_ ? 500 : 2000; - constexpr int kDefaultPeriodMs = 3000; - constexpr int kMaxPeriodMs = 50000; +TimeDelta AimdRateControl::GetExpectedBandwidthPeriod() const { + const TimeDelta kMinPeriod = + smoothing_experiment_ ? TimeDelta::ms(500) : TimeDelta::seconds(2); + const TimeDelta kDefaultPeriod = TimeDelta::seconds(3); + const TimeDelta kMaxPeriod = TimeDelta::seconds(50); - int increase_rate = GetNearMaxIncreaseRateBps(); + double increase_rate_bps_per_second = GetNearMaxIncreaseRateBpsPerSecond(); if (!last_decrease_) - return smoothing_experiment_ ? kMinPeriodMs : kDefaultPeriodMs; - - return std::min(kMaxPeriodMs, - std::max(1000 * static_cast(*last_decrease_) / - increase_rate, - kMinPeriodMs)); + return smoothing_experiment_ ? kMinPeriod : kDefaultPeriod; + double time_to_recover_decrease_seconds = + last_decrease_->bps() / increase_rate_bps_per_second; + TimeDelta period = TimeDelta::seconds(time_to_recover_decrease_seconds); + return period.Clamped(kMinPeriod, kMaxPeriod); } -uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps, +DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, const RateControlInput& input, - int64_t now_ms) { - uint32_t estimated_throughput_bps = - input.estimated_throughput_bps.value_or(latest_estimated_throughput_bps_); - if (input.estimated_throughput_bps) - latest_estimated_throughput_bps_ = *input.estimated_throughput_bps; + Timestamp at_time) { + DataRate estimated_throughput = + input.estimated_throughput.value_or(latest_estimated_throughput_); + if (input.estimated_throughput) + latest_estimated_throughput_ = *input.estimated_throughput; // An over-use should always trigger us to reduce the bitrate, even though // we have not yet established our first estimate. By acting on the over-use, // we will end up with a valid estimate. if (!bitrate_is_initialized_ && input.bw_state != BandwidthUsage::kBwOverusing) - return current_bitrate_bps_; + return current_bitrate_; - ChangeState(input, now_ms); + ChangeState(input, at_time); // Calculated here because it's used in multiple places. - const float estimated_throughput_kbps = estimated_throughput_bps / 1000.0f; + const float estimated_throughput_kbps = estimated_throughput.kbps(); // Calculate the max bit rate std dev given the normalized // variance and the current throughput bitrate. const float std_max_bit_rate = @@ -270,45 +274,41 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps, avg_max_bitrate_kbps_ = -1.0; } if (rate_control_region_ == kRcNearMax) { - uint32_t additive_increase_bps = - AdditiveRateIncrease(now_ms, time_last_bitrate_change_); - new_bitrate_bps += additive_increase_bps; + DataRate additive_increase = + AdditiveRateIncrease(at_time, time_last_bitrate_change_); + new_bitrate += additive_increase; } else { - uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease( - now_ms, time_last_bitrate_change_, new_bitrate_bps); - new_bitrate_bps += multiplicative_increase_bps; + DataRate multiplicative_increase = MultiplicativeRateIncrease( + at_time, time_last_bitrate_change_, new_bitrate); + new_bitrate += multiplicative_increase; } - time_last_bitrate_change_ = now_ms; + time_last_bitrate_change_ = at_time; break; case kRcDecrease: // Set bit rate to something slightly lower than max // to get rid of any self-induced delay. - new_bitrate_bps = - static_cast(beta_ * estimated_throughput_bps + 0.5); - if (new_bitrate_bps > current_bitrate_bps_) { + new_bitrate = estimated_throughput * beta_; + if (new_bitrate > current_bitrate_) { // Avoid increasing the rate when over-using. if (rate_control_region_ != kRcMaxUnknown) { - new_bitrate_bps = static_cast( - beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f); + new_bitrate = DataRate::kbps(beta_ * avg_max_bitrate_kbps_); } - new_bitrate_bps = std::min(new_bitrate_bps, current_bitrate_bps_); + new_bitrate = std::min(new_bitrate, current_bitrate_); } rate_control_region_ = kRcNearMax; - if (bitrate_is_initialized_ && - estimated_throughput_bps < current_bitrate_bps_) { + if (bitrate_is_initialized_ && estimated_throughput < current_bitrate_) { constexpr float kDegradationFactor = 0.9f; if (smoothing_experiment_ && - new_bitrate_bps < - kDegradationFactor * beta_ * current_bitrate_bps_) { + new_bitrate < kDegradationFactor * beta_ * current_bitrate_) { // If bitrate decreases more than a normal back off after overuse, it // indicates a real network degradation. We do not let such a decrease // to determine the bandwidth estimation period. last_decrease_ = absl::nullopt; } else { - last_decrease_ = current_bitrate_bps_ - new_bitrate_bps; + last_decrease_ = current_bitrate_ - new_bitrate; } } if (estimated_throughput_kbps < @@ -320,51 +320,49 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps, UpdateMaxThroughputEstimate(estimated_throughput_kbps); // Stay on hold until the pipes are cleared. rate_control_state_ = kRcHold; - time_last_bitrate_change_ = now_ms; - time_last_bitrate_decrease_ = now_ms; + time_last_bitrate_change_ = at_time; + time_last_bitrate_decrease_ = at_time; break; default: assert(false); } - return ClampBitrate(new_bitrate_bps, estimated_throughput_bps); + return ClampBitrate(new_bitrate, estimated_throughput); } -uint32_t AimdRateControl::ClampBitrate( - uint32_t new_bitrate_bps, - uint32_t estimated_throughput_bps) const { +DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate, + DataRate estimated_throughput) const { // Don't change the bit rate if the send side is too far off. // We allow a bit more lag at very low rates to not too easily get stuck if // the encoder produces uneven outputs. - const uint32_t max_bitrate_bps = - static_cast(1.5f * estimated_throughput_bps) + 10000; - if (new_bitrate_bps > current_bitrate_bps_ && - new_bitrate_bps > max_bitrate_bps) { - new_bitrate_bps = std::max(current_bitrate_bps_, max_bitrate_bps); + const DataRate max_bitrate = 1.5 * estimated_throughput + DataRate::kbps(10); + if (new_bitrate > current_bitrate_ && new_bitrate > max_bitrate) { + new_bitrate = std::max(current_bitrate_, max_bitrate); } - new_bitrate_bps = std::max(new_bitrate_bps, min_configured_bitrate_bps_); - return new_bitrate_bps; + new_bitrate = std::max(new_bitrate, min_configured_bitrate_); + return new_bitrate; } -uint32_t AimdRateControl::MultiplicativeRateIncrease( - int64_t now_ms, - int64_t last_ms, - uint32_t current_bitrate_bps) const { +DataRate AimdRateControl::MultiplicativeRateIncrease( + Timestamp at_time, + Timestamp last_time, + DataRate current_bitrate) const { double alpha = 1.08; - if (last_ms > -1) { - auto time_since_last_update_ms = - rtc::SafeMin(now_ms - last_ms, 1000); - alpha = pow(alpha, time_since_last_update_ms / 1000.0); + if (last_time.IsFinite()) { + auto time_since_last_update = at_time - last_time; + alpha = pow(alpha, std::min(time_since_last_update.seconds(), 1.0)); } - uint32_t multiplicative_increase_bps = - std::max(current_bitrate_bps * (alpha - 1.0), 1000.0); - return multiplicative_increase_bps; + DataRate multiplicative_increase = + std::max(current_bitrate * (alpha - 1.0), DataRate::bps(1000)); + return multiplicative_increase; } -uint32_t AimdRateControl::AdditiveRateIncrease(int64_t now_ms, - int64_t last_ms) const { - return static_cast((now_ms - last_ms) * - GetNearMaxIncreaseRateBps() / 1000); +DataRate AimdRateControl::AdditiveRateIncrease(Timestamp at_time, + Timestamp last_time) const { + double time_period_seconds = (at_time - last_time).seconds(); + double data_rate_increase_bps = + GetNearMaxIncreaseRateBpsPerSecond() * time_period_seconds; + return DataRate::bps(data_rate_increase_bps); } void AimdRateControl::UpdateMaxThroughputEstimate( @@ -394,11 +392,11 @@ void AimdRateControl::UpdateMaxThroughputEstimate( } void AimdRateControl::ChangeState(const RateControlInput& input, - int64_t now_ms) { + Timestamp at_time) { switch (input.bw_state) { case BandwidthUsage::kBwNormal: if (rate_control_state_ == kRcHold) { - time_last_bitrate_change_ = now_ms; + time_last_bitrate_change_ = at_time; rate_control_state_ = kRcIncrease; } break; diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.h b/modules/remote_bitrate_estimator/aimd_rate_control.h index 24b853501b..47afce6987 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -16,6 +16,9 @@ #include "absl/types/optional.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" +#include "api/units/data_rate.h" +#include "api/units/timestamp.h" + namespace webrtc { // A rate control implementation based on additive increases of @@ -32,28 +35,28 @@ class AimdRateControl { // either if it has been explicitly set via SetStartBitrate/SetEstimate, or if // we have measured a throughput. bool ValidEstimate() const; - void SetStartBitrate(int start_bitrate_bps); - void SetMinBitrate(int min_bitrate_bps); - int64_t GetFeedbackInterval() const; + void SetStartBitrate(DataRate start_bitrate); + void SetMinBitrate(DataRate min_bitrate); + TimeDelta GetFeedbackInterval() const; // Returns true if the bitrate estimate hasn't been changed for more than // an RTT, or if the estimated_throughput is less than half of the current // estimate. Should be used to decide if we should reduce the rate further // when over-using. - bool TimeToReduceFurther(int64_t now_ms, - uint32_t estimated_throughput_bps) const; + bool TimeToReduceFurther(Timestamp at_time, + DataRate estimated_throughput) const; // As above. To be used if overusing before we have measured a throughput. - bool InitialTimeToReduceFurther(int64_t now_ms) const; + bool InitialTimeToReduceFurther(Timestamp at_time) const; - uint32_t LatestEstimate() const; - void SetRtt(int64_t rtt); - uint32_t Update(const RateControlInput* input, int64_t now_ms); - void SetEstimate(int bitrate_bps, int64_t now_ms); + DataRate LatestEstimate() const; + void SetRtt(TimeDelta rtt); + DataRate Update(const RateControlInput* input, Timestamp at_time); + void SetEstimate(DataRate bitrate, Timestamp at_time); // Returns the increase rate when used bandwidth is near the link capacity. - int GetNearMaxIncreaseRateBps() const; + double GetNearMaxIncreaseRateBpsPerSecond() const; // Returns the expected time between overuse signals (assuming steady state). - int GetExpectedBandwidthPeriodMs() const; + TimeDelta GetExpectedBandwidthPeriod() const; private: friend class GoogCcStatePrinter; @@ -64,41 +67,41 @@ class AimdRateControl { // in the "decrease" state the bitrate will be decreased to slightly below the // current throughput. When in the "hold" state the bitrate will be kept // constant to allow built up queues to drain. - uint32_t ChangeBitrate(uint32_t current_bitrate, + DataRate ChangeBitrate(DataRate current_bitrate, const RateControlInput& input, - int64_t now_ms); - // Clamps new_bitrate_bps to within the configured min bitrate and a linear + Timestamp at_time); + // Clamps new_bitrate to within the configured min bitrate and a linear // function of the throughput, so that the new bitrate can't grow too // large compared to the bitrate actually being received by the other end. - uint32_t ClampBitrate(uint32_t new_bitrate_bps, - uint32_t estimated_throughput_bps) const; - uint32_t MultiplicativeRateIncrease(int64_t now_ms, - int64_t last_ms, - uint32_t current_bitrate_bps) const; - uint32_t AdditiveRateIncrease(int64_t now_ms, int64_t last_ms) const; - void UpdateChangePeriod(int64_t now_ms); + DataRate ClampBitrate(DataRate new_bitrate, + DataRate estimated_throughput) const; + DataRate MultiplicativeRateIncrease(Timestamp at_time, + Timestamp last_ms, + DataRate current_bitrate) const; + DataRate AdditiveRateIncrease(Timestamp at_time, Timestamp last_time) const; + void UpdateChangePeriod(Timestamp at_time); void UpdateMaxThroughputEstimate(float estimated_throughput_kbps); - void ChangeState(const RateControlInput& input, int64_t now_ms); + void ChangeState(const RateControlInput& input, Timestamp at_time); - uint32_t min_configured_bitrate_bps_; - uint32_t max_configured_bitrate_bps_; - uint32_t current_bitrate_bps_; - uint32_t latest_estimated_throughput_bps_; + DataRate min_configured_bitrate_; + DataRate max_configured_bitrate_; + DataRate current_bitrate_; + DataRate latest_estimated_throughput_; float avg_max_bitrate_kbps_; float var_max_bitrate_kbps_; RateControlState rate_control_state_; RateControlRegion rate_control_region_; - int64_t time_last_bitrate_change_; - int64_t time_last_bitrate_decrease_; - int64_t time_first_throughput_estimate_; + Timestamp time_last_bitrate_change_; + Timestamp time_last_bitrate_decrease_; + Timestamp time_first_throughput_estimate_; bool bitrate_is_initialized_; float beta_; - int64_t rtt_; + TimeDelta rtt_; const bool in_experiment_; const bool smoothing_experiment_; const bool in_initial_backoff_interval_experiment_; - int64_t initial_backoff_interval_ms_; - absl::optional last_decrease_; + TimeDelta initial_backoff_interval_; + absl::optional last_decrease_; }; } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc index 5cde7cedaf..4bec9e8ff5 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc +++ b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc @@ -40,13 +40,26 @@ AimdRateControlStates CreateAimdRateControlStates() { states.simulated_clock.reset(new SimulatedClock(kClockInitialTime)); return states; } - +absl::optional OptionalRateFromOptionalBps( + absl::optional bitrate_bps) { + if (bitrate_bps) { + return DataRate::bps(*bitrate_bps); + } else { + return absl::nullopt; + } +} void UpdateRateControl(const AimdRateControlStates& states, const BandwidthUsage& bandwidth_usage, absl::optional throughput_estimate, int64_t now_ms) { - RateControlInput input(bandwidth_usage, throughput_estimate); - states.aimd_rate_control->Update(&input, now_ms); + RateControlInput input(bandwidth_usage, + OptionalRateFromOptionalBps(throughput_estimate)); + states.aimd_rate_control->Update(&input, Timestamp::ms(now_ms)); +} +void SetEstimate(const AimdRateControlStates& states, int bitrate_bps) { + states.aimd_rate_control->SetEstimate( + DataRate::bps(bitrate_bps), + Timestamp::ms(states.simulated_clock->TimeInMilliseconds())); } } // namespace @@ -54,40 +67,40 @@ void UpdateRateControl(const AimdRateControlStates& states, TEST(AimdRateControlTest, MinNearMaxIncreaseRateOnLowBandwith) { auto states = CreateAimdRateControlStates(); constexpr int kBitrate = 30000; - states.aimd_rate_control->SetEstimate( - kBitrate, states.simulated_clock->TimeInMilliseconds()); - EXPECT_EQ(4000, states.aimd_rate_control->GetNearMaxIncreaseRateBps()); + SetEstimate(states, kBitrate); + EXPECT_EQ(4000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); } TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn90kbpsAnd200msRtt) { auto states = CreateAimdRateControlStates(); constexpr int kBitrate = 90000; - states.aimd_rate_control->SetEstimate( - kBitrate, states.simulated_clock->TimeInMilliseconds()); - EXPECT_EQ(5000, states.aimd_rate_control->GetNearMaxIncreaseRateBps()); + SetEstimate(states, kBitrate); + EXPECT_EQ(5000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); } TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt) { auto states = CreateAimdRateControlStates(); constexpr int kBitrate = 60000; - states.aimd_rate_control->SetEstimate( - kBitrate, states.simulated_clock->TimeInMilliseconds()); - states.aimd_rate_control->SetRtt(100); - EXPECT_EQ(5000, states.aimd_rate_control->GetNearMaxIncreaseRateBps()); + SetEstimate(states, kBitrate); + states.aimd_rate_control->SetRtt(TimeDelta::ms(100)); + EXPECT_EQ(5000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); } TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) { // Smoothing experiment disabled auto states = CreateAimdRateControlStates(); constexpr int kBitrate = 300000; - states.aimd_rate_control->SetEstimate( - kBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kBitrate); UpdateRateControl(states, BandwidthUsage::kBwOverusing, kBitrate, states.simulated_clock->TimeInMilliseconds()); - EXPECT_NEAR(14000, states.aimd_rate_control->GetNearMaxIncreaseRateBps(), + EXPECT_NEAR(14000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond(), 1000); EXPECT_EQ(kDefaultPeriodMsNoSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriodSmoothingExp) { @@ -95,21 +108,20 @@ TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriodSmoothingExp) { test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial); auto states = CreateAimdRateControlStates(); constexpr int kBitrate = 300000; - states.aimd_rate_control->SetEstimate( - kBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kBitrate); UpdateRateControl(states, BandwidthUsage::kBwOverusing, kBitrate, states.simulated_clock->TimeInMilliseconds()); - EXPECT_NEAR(14000, states.aimd_rate_control->GetNearMaxIncreaseRateBps(), + EXPECT_NEAR(14000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond(), 1000); EXPECT_EQ(kMinBwePeriodMsSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, BweLimitedByAckedBitrate) { auto states = CreateAimdRateControlStates(); constexpr int kAckedBitrate = 10000; - states.aimd_rate_control->SetEstimate( - kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kAckedBitrate); while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime < 20000) { UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate, @@ -118,14 +130,13 @@ TEST(AimdRateControlTest, BweLimitedByAckedBitrate) { } ASSERT_TRUE(states.aimd_rate_control->ValidEstimate()); EXPECT_EQ(static_cast(1.5 * kAckedBitrate + 10000), - states.aimd_rate_control->LatestEstimate()); + states.aimd_rate_control->LatestEstimate().bps()); } TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) { auto states = CreateAimdRateControlStates(); constexpr int kAckedBitrate = 100000; - states.aimd_rate_control->SetEstimate( - kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kAckedBitrate); while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime < 20000) { UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate, @@ -135,10 +146,10 @@ TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) { ASSERT_TRUE(states.aimd_rate_control->ValidEstimate()); // If the acked bitrate decreases the BWE shouldn't be reduced to 1.5x // what's being acked, but also shouldn't get to increase more. - uint32_t prev_estimate = states.aimd_rate_control->LatestEstimate(); + uint32_t prev_estimate = states.aimd_rate_control->LatestEstimate().bps(); UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate / 2, states.simulated_clock->TimeInMilliseconds()); - uint32_t new_estimate = states.aimd_rate_control->LatestEstimate(); + uint32_t new_estimate = states.aimd_rate_control->LatestEstimate().bps(); EXPECT_NEAR(new_estimate, static_cast(1.5 * kAckedBitrate + 10000), 2000); EXPECT_EQ(new_estimate, prev_estimate); @@ -147,35 +158,34 @@ TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) { TEST(AimdRateControlTest, DefaultPeriodUntilFirstOveruse) { // Smoothing experiment disabled auto states = CreateAimdRateControlStates(); - states.aimd_rate_control->SetStartBitrate(300000); + states.aimd_rate_control->SetStartBitrate(DataRate::kbps(300)); EXPECT_EQ(kDefaultPeriodMsNoSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); states.simulated_clock->AdvanceTimeMilliseconds(100); UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000, states.simulated_clock->TimeInMilliseconds()); EXPECT_NE(kDefaultPeriodMsNoSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, MinPeriodUntilFirstOveruseSmoothingExp) { // Smoothing experiment enabled test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial); auto states = CreateAimdRateControlStates(); - states.aimd_rate_control->SetStartBitrate(300000); + states.aimd_rate_control->SetStartBitrate(DataRate::kbps(300)); EXPECT_EQ(kMinBwePeriodMsSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); states.simulated_clock->AdvanceTimeMilliseconds(100); UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000, states.simulated_clock->TimeInMilliseconds()); EXPECT_NE(kMinBwePeriodMsSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease) { auto states = CreateAimdRateControlStates(); constexpr int kInitialBitrate = 110000; - states.aimd_rate_control->SetEstimate( - kInitialBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kInitialBitrate); states.simulated_clock->AdvanceTimeMilliseconds(100); // Make the bitrate drop by 20 kbps to get to 90 kbps. // The rate increase at 90 kbps should be 5 kbps, so the period should be 4 s. @@ -183,8 +193,9 @@ TEST(AimdRateControlTest, ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease) { (kInitialBitrate - 20000) / kFractionAfterOveruse; UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); - EXPECT_EQ(5000, states.aimd_rate_control->GetNearMaxIncreaseRateBps()); - EXPECT_EQ(4000, states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + EXPECT_EQ(5000, + states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); + EXPECT_EQ(4000, states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, MinPeriodAfterLargeBitrateDecreaseSmoothingExp) { @@ -192,8 +203,7 @@ TEST(AimdRateControlTest, MinPeriodAfterLargeBitrateDecreaseSmoothingExp) { test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial); auto states = CreateAimdRateControlStates(); constexpr int kInitialBitrate = 110000; - states.aimd_rate_control->SetEstimate( - kInitialBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kInitialBitrate); states.simulated_clock->AdvanceTimeMilliseconds(100); // Make such a large drop in bitrate that should be treated as network // degradation. @@ -201,20 +211,19 @@ TEST(AimdRateControlTest, MinPeriodAfterLargeBitrateDecreaseSmoothingExp) { UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); EXPECT_EQ(kMinBwePeriodMsSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) { auto states = CreateAimdRateControlStates(); constexpr int kInitialBitrate = 10000; - states.aimd_rate_control->SetEstimate( - kInitialBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kInitialBitrate); states.simulated_clock->AdvanceTimeMilliseconds(100); // Make a small (1.5 kbps) bitrate drop to 8.5 kbps. UpdateRateControl(states, BandwidthUsage::kBwOverusing, kInitialBitrate - 1, states.simulated_clock->TimeInMilliseconds()); EXPECT_EQ(kMinBwePeriodMsNoSmoothingExp, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxSmoothingExp) { @@ -222,29 +231,27 @@ TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxSmoothingExp) { test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial); auto states = CreateAimdRateControlStates(); constexpr int kInitialBitrate = 50000000; - states.aimd_rate_control->SetEstimate( - kInitialBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kInitialBitrate); states.simulated_clock->AdvanceTimeMilliseconds(100); // Make a large (10 Mbps) bitrate drop to 10 kbps. constexpr int kAckedBitrate = 40000000 / kFractionAfterOveruse; UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); EXPECT_EQ(kMaxBwePeriodMs, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxNoSmoothingExp) { auto states = CreateAimdRateControlStates(); constexpr int kInitialBitrate = 10010000; - states.aimd_rate_control->SetEstimate( - kInitialBitrate, states.simulated_clock->TimeInMilliseconds()); + SetEstimate(states, kInitialBitrate); states.simulated_clock->AdvanceTimeMilliseconds(100); // Make a large (10 Mbps) bitrate drop to 10 kbps. constexpr int kAckedBitrate = 10000 / kFractionAfterOveruse; UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, states.simulated_clock->TimeInMilliseconds()); EXPECT_EQ(kMaxBwePeriodMs, - states.aimd_rate_control->GetExpectedBandwidthPeriodMs()); + states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); } TEST(AimdRateControlTest, SendingRateBoundedWhenThroughputNotEstimated) { @@ -265,7 +272,7 @@ TEST(AimdRateControlTest, SendingRateBoundedWhenThroughputNotEstimated) { states.simulated_clock->TimeInMilliseconds()); states.simulated_clock->AdvanceTimeMilliseconds(100); } - EXPECT_LE(states.aimd_rate_control->LatestEstimate(), + EXPECT_LE(states.aimd_rate_control->LatestEstimate().bps(), kInitialBitrateBps * 1.5 + 10000); } diff --git a/modules/remote_bitrate_estimator/bwe_defines.cc b/modules/remote_bitrate_estimator/bwe_defines.cc index 6cbe468348..91f3cd4050 100644 --- a/modules/remote_bitrate_estimator/bwe_defines.cc +++ b/modules/remote_bitrate_estimator/bwe_defines.cc @@ -34,8 +34,8 @@ DataRate GetMinBitrate() { RateControlInput::RateControlInput( BandwidthUsage bw_state, - const absl::optional& estimated_throughput_bps) - : bw_state(bw_state), estimated_throughput_bps(estimated_throughput_bps) {} + const absl::optional& estimated_throughput) + : bw_state(bw_state), estimated_throughput(estimated_throughput) {} RateControlInput::~RateControlInput() = default; diff --git a/modules/remote_bitrate_estimator/include/bwe_defines.h b/modules/remote_bitrate_estimator/include/bwe_defines.h index 209850716c..f6ba06ce73 100644 --- a/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -51,11 +51,11 @@ enum RateControlRegion { kRcNearMax, kRcAboveMax, kRcMaxUnknown }; struct RateControlInput { RateControlInput(BandwidthUsage bw_state, - const absl::optional& estimated_throughput_bps); + const absl::optional& estimated_throughput); ~RateControlInput(); BandwidthUsage bw_state; - absl::optional estimated_throughput_bps; + absl::optional estimated_throughput; }; } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc index a7cfe4c90a..1ad35c7bf0 100644 --- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc +++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc @@ -22,6 +22,16 @@ #include "system_wrappers/include/metrics.h" namespace webrtc { +namespace { +absl::optional OptionalRateFromOptionalBps( + absl::optional bitrate_bps) { + if (bitrate_bps) { + return DataRate::bps(*bitrate_bps); + } else { + return absl::nullopt; + } +} +} // namespace enum { kTimestampGroupLengthMs = 5, @@ -188,7 +198,8 @@ RemoteBitrateEstimatorAbsSendTime::ProcessClusters(int64_t now_ms) { << " bps. Mean send delta: " << best_it->send_mean_ms << " ms, mean recv delta: " << best_it->recv_mean_ms << " ms, num probes: " << best_it->count; - remote_rate_.SetEstimate(probe_bitrate_bps, now_ms); + remote_rate_.SetEstimate(DataRate::bps(probe_bitrate_bps), + Timestamp::ms(now_ms)); return ProbeResult::kBitrateUpdated; } } @@ -205,7 +216,7 @@ bool RemoteBitrateEstimatorAbsSendTime::IsBitrateImproving( bool initial_probe = !remote_rate_.ValidEstimate() && new_bitrate_bps > 0; bool bitrate_above_estimate = remote_rate_.ValidEstimate() && - new_bitrate_bps > static_cast(remote_rate_.LatestEstimate()); + new_bitrate_bps > remote_rate_.LatestEstimate().bps(); return initial_probe || bitrate_above_estimate; } @@ -316,13 +327,14 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo( // Check if it's time for a periodic update or if we should update because // of an over-use. if (last_update_ms_ == -1 || - now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval()) { + now_ms - last_update_ms_ > remote_rate_.GetFeedbackInterval().ms()) { update_estimate = true; } else if (detector_.State() == BandwidthUsage::kBwOverusing) { absl::optional incoming_rate = incoming_bitrate_.Rate(arrival_time_ms); if (incoming_rate && - remote_rate_.TimeToReduceFurther(now_ms, *incoming_rate)) { + remote_rate_.TimeToReduceFurther(Timestamp::ms(now_ms), + DataRate::bps(*incoming_rate))) { update_estimate = true; } } @@ -332,9 +344,11 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo( // 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. - const RateControlInput input(detector_.State(), - incoming_bitrate_.Rate(arrival_time_ms)); - target_bitrate_bps = remote_rate_.Update(&input, now_ms); + const RateControlInput input( + detector_.State(), + OptionalRateFromOptionalBps(incoming_bitrate_.Rate(arrival_time_ms))); + target_bitrate_bps = + remote_rate_.Update(&input, Timestamp::ms(now_ms)).bps(); update_estimate = remote_rate_.ValidEstimate(); ssrcs = Keys(ssrcs_); } @@ -374,7 +388,7 @@ void RemoteBitrateEstimatorAbsSendTime::TimeoutStreams(int64_t now_ms) { void RemoteBitrateEstimatorAbsSendTime::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { rtc::CritScope lock(&crit_); - remote_rate_.SetRtt(avg_rtt_ms); + remote_rate_.SetRtt(TimeDelta::ms(avg_rtt_ms)); } void RemoteBitrateEstimatorAbsSendTime::RemoveStream(uint32_t ssrc) { @@ -399,7 +413,7 @@ bool RemoteBitrateEstimatorAbsSendTime::LatestEstimate( if (ssrcs_.empty()) { *bitrate_bps = 0; } else { - *bitrate_bps = remote_rate_.LatestEstimate(); + *bitrate_bps = remote_rate_.LatestEstimate().bps(); } return true; } @@ -408,6 +422,6 @@ void RemoteBitrateEstimatorAbsSendTime::SetMinBitrate(int min_bitrate_bps) { // Called from both the configuration thread and the network thread. Shouldn't // be called from the network thread in the future. rtc::CritScope lock(&crit_); - remote_rate_.SetMinBitrate(min_bitrate_bps); + remote_rate_.SetMinBitrate(DataRate::bps(min_bitrate_bps)); } } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc index 1f0de47d05..a267051944 100644 --- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc +++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc @@ -27,6 +27,16 @@ #include "system_wrappers/include/metrics.h" namespace webrtc { +namespace { +absl::optional OptionalRateFromOptionalBps( + absl::optional bitrate_bps) { + if (bitrate_bps) { + return DataRate::bps(*bitrate_bps); + } else { + return absl::nullopt; + } +} +} // namespace enum { kTimestampGroupLengthMs = 5 }; static const double kTimestampToMs = 1.0 / 90.0; @@ -133,7 +143,8 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket( incoming_bitrate_.Rate(now_ms); if (incoming_bitrate_bps && (prior_state != BandwidthUsage::kBwOverusing || - GetRemoteRate()->TimeToReduceFurther(now_ms, *incoming_bitrate_bps))) { + GetRemoteRate()->TimeToReduceFurther( + Timestamp::ms(now_ms), DataRate::bps(*incoming_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. @@ -187,10 +198,12 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) { } AimdRateControl* remote_rate = GetRemoteRate(); - const RateControlInput input(bw_state, incoming_bitrate_.Rate(now_ms)); - uint32_t target_bitrate = remote_rate->Update(&input, now_ms); + const RateControlInput input( + bw_state, OptionalRateFromOptionalBps(incoming_bitrate_.Rate(now_ms))); + uint32_t target_bitrate = + remote_rate->Update(&input, Timestamp::ms(now_ms)).bps(); if (remote_rate->ValidEstimate()) { - process_interval_ms_ = remote_rate->GetFeedbackInterval(); + process_interval_ms_ = remote_rate->GetFeedbackInterval().ms(); RTC_DCHECK_GT(process_interval_ms_, 0); std::vector ssrcs; GetSsrcs(&ssrcs); @@ -202,7 +215,7 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) { void RemoteBitrateEstimatorSingleStream::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) { rtc::CritScope cs(&crit_sect_); - GetRemoteRate()->SetRtt(avg_rtt_ms); + GetRemoteRate()->SetRtt(TimeDelta::ms(avg_rtt_ms)); } void RemoteBitrateEstimatorSingleStream::RemoveStream(unsigned int ssrc) { @@ -226,7 +239,7 @@ bool RemoteBitrateEstimatorSingleStream::LatestEstimate( if (ssrcs->empty()) *bitrate_bps = 0; else - *bitrate_bps = remote_rate_->LatestEstimate(); + *bitrate_bps = remote_rate_->LatestEstimate().bps(); return true; } @@ -249,7 +262,7 @@ AimdRateControl* RemoteBitrateEstimatorSingleStream::GetRemoteRate() { void RemoteBitrateEstimatorSingleStream::SetMinBitrate(int min_bitrate_bps) { rtc::CritScope cs(&crit_sect_); - remote_rate_->SetMinBitrate(min_bitrate_bps); + remote_rate_->SetMinBitrate(DataRate::bps(min_bitrate_bps)); } } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc index 120db13c7f..2a4ef06473 100644 --- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc +++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream_unittest.cc @@ -55,7 +55,7 @@ TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThreeStreamsWrap) { } TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropThirteenStreamsWrap) { - CapacityDropTestHelper(13, true, 733, 0); + CapacityDropTestHelper(13, true, 567, 0); } TEST_F(RemoteBitrateEstimatorSingleTest, CapacityDropNineteenStreamsWrap) {