From e1d7b23915c87cf52d70ef0f53680bc613ddfa90 Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Tue, 17 Jul 2018 16:01:25 +0200 Subject: [PATCH] Implement congestion window direct pushback to encoders. (Without TaskQueue) Bug: None Change-Id: I3c6da916ce5f4a32ff47bfb0894b00f11fbf7823 Reviewed-on: https://webrtc-review.googlesource.com/86605 Commit-Queue: Ying Wang Reviewed-by: Sebastian Jansson Reviewed-by: Christoffer Rodbro Cr-Commit-Position: refs/heads/master@{#24008} --- modules/congestion_controller/BUILD.gn | 5 + .../congestion_window_pushback_controller.cc | 93 +++++++++++++++++++ .../congestion_window_pushback_controller.h | 43 +++++++++ ...ion_window_pushback_controller_unittest.cc | 65 +++++++++++++ .../include/send_side_congestion_controller.h | 4 + .../rtp/send_side_congestion_controller.cc | 81 ++++++---------- .../send_side_congestion_controller.cc | 69 ++++++++++---- 7 files changed, 288 insertions(+), 72 deletions(-) create mode 100644 modules/congestion_controller/congestion_window_pushback_controller.cc create mode 100644 modules/congestion_controller/congestion_window_pushback_controller.h create mode 100644 modules/congestion_controller/congestion_window_pushback_controller_unittest.cc diff --git a/modules/congestion_controller/BUILD.gn b/modules/congestion_controller/BUILD.gn index 175730deb8..27a7369322 100644 --- a/modules/congestion_controller/BUILD.gn +++ b/modules/congestion_controller/BUILD.gn @@ -20,6 +20,8 @@ rtc_static_library("congestion_controller") { visibility = [ "*" ] configs += [ ":bwe_test_logging" ] sources = [ + "congestion_window_pushback_controller.cc", + "congestion_window_pushback_controller.h", "include/network_changed_observer.h", "include/receive_side_congestion_controller.h", "include/send_side_congestion_controller.h", @@ -37,7 +39,9 @@ rtc_static_library("congestion_controller") { ":transport_feedback", "..:module_api", "../..:webrtc_common", + "../../api/transport:network_control", "../../rtc_base:checks", + "../../rtc_base:ptr_util", "../../rtc_base:rate_limiter", "../../system_wrappers", "../../system_wrappers:field_trial_api", @@ -95,6 +99,7 @@ if (rtc_include_tests) { testonly = true sources = [ + "congestion_window_pushback_controller_unittest.cc", "receive_side_congestion_controller_unittest.cc", "send_side_congestion_controller_unittest.cc", "transport_feedback_adapter_unittest.cc", diff --git a/modules/congestion_controller/congestion_window_pushback_controller.cc b/modules/congestion_controller/congestion_window_pushback_controller.cc new file mode 100644 index 0000000000..daa51bddd3 --- /dev/null +++ b/modules/congestion_controller/congestion_window_pushback_controller.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include +#include + +#include "modules/congestion_controller/congestion_window_pushback_controller.h" +#include "system_wrappers/include/field_trial.h" + +namespace webrtc { + +// When CongestionWindowPushback is enabled, the pacer is oblivious to +// the congestion window. The relation between outstanding data and +// the congestion window affects encoder allocations directly. +// This experiment is build on top of congestion window experiment. +const char kCongestionPushbackExperiment[] = "WebRTC-CongestionWindowPushback"; +const uint32_t kDefaultMinPushbackTargetBitrateBps = 30000; + +bool ReadCongestionWindowPushbackExperimentParameter( + uint32_t* min_pushback_target_bitrate_bps) { + RTC_DCHECK(min_pushback_target_bitrate_bps); + std::string experiment_string = + webrtc::field_trial::FindFullName(kCongestionPushbackExperiment); + int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%" PRIu32, + min_pushback_target_bitrate_bps); + if (parsed_values == 1) { + RTC_CHECK_GE(*min_pushback_target_bitrate_bps, 0) + << "Min pushback target bitrate must be greater than or equal to 0."; + return true; + } + return false; +} + +CongestionWindowPushbackController::CongestionWindowPushbackController() { + if (!ReadCongestionWindowPushbackExperimentParameter( + &min_pushback_target_bitrate_bps_)) { + min_pushback_target_bitrate_bps_ = kDefaultMinPushbackTargetBitrateBps; + } +} + +void CongestionWindowPushbackController::UpdateOutstandingData( + size_t outstanding_bytes) { + outstanding_bytes_ = outstanding_bytes; +} + +void CongestionWindowPushbackController::UpdateMaxOutstandingData( + size_t max_outstanding_bytes) { + DataSize data_window = DataSize::bytes(max_outstanding_bytes); + if (current_data_window_) { + data_window = (data_window + current_data_window_.value()) / 2; + } + current_data_window_ = data_window; +} + +void CongestionWindowPushbackController::SetDataWindow(DataSize data_window) { + current_data_window_ = data_window; +} + +uint32_t CongestionWindowPushbackController::UpdateTargetBitrate( + uint32_t bitrate_bps) { + if (!current_data_window_ || current_data_window_->IsZero()) + return bitrate_bps; + double fill_ratio = + outstanding_bytes_ / static_cast(current_data_window_->bytes()); + if (fill_ratio > 1.5) { + encoding_rate_ratio_ *= 0.9; + } else if (fill_ratio > 1) { + encoding_rate_ratio_ *= 0.95; + } else if (fill_ratio < 0.1) { + encoding_rate_ratio_ = 1.0; + } else { + encoding_rate_ratio_ *= 1.05; + encoding_rate_ratio_ = std::min(encoding_rate_ratio_, 1.0); + } + uint32_t adjusted_target_bitrate_bps = + static_cast(bitrate_bps * encoding_rate_ratio_); + + // Do not adjust below the minimum pushback bitrate but do obey if the + // original estimate is below it. + bitrate_bps = adjusted_target_bitrate_bps < min_pushback_target_bitrate_bps_ + ? std::min(bitrate_bps, min_pushback_target_bitrate_bps_) + : adjusted_target_bitrate_bps; + return bitrate_bps; +} + +} // namespace webrtc diff --git a/modules/congestion_controller/congestion_window_pushback_controller.h b/modules/congestion_controller/congestion_window_pushback_controller.h new file mode 100644 index 0000000000..f608590583 --- /dev/null +++ b/modules/congestion_controller/congestion_window_pushback_controller.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef MODULES_CONGESTION_CONTROLLER_CONGESTION_WINDOW_PUSHBACK_CONTROLLER_H_ +#define MODULES_CONGESTION_CONTROLLER_CONGESTION_WINDOW_PUSHBACK_CONTROLLER_H_ + +#include "api/transport/network_types.h" +#include "common_types.h" // NOLINT(build/include) +#include "rtc_base/criticalsection.h" +#include "rtc_base/format_macros.h" + +namespace webrtc { + +// This class enables pushback from congestion window directly to video encoder. +// When the congestion window is filling up, the video encoder target bitrate +// will be reduced accordingly to accommodate the network changes. To avoid +// pausing video too frequently, a minimum encoder target bitrate threshold is +// used to prevent video pause due to a full congestion window. +class CongestionWindowPushbackController { + public: + CongestionWindowPushbackController(); + void UpdateOutstandingData(size_t outstanding_bytes); + void UpdateMaxOutstandingData(size_t max_outstanding_bytes); + uint32_t UpdateTargetBitrate(uint32_t bitrate_bps); + void SetDataWindow(DataSize data_window); + + private: + absl::optional current_data_window_; + size_t outstanding_bytes_ = 0; + uint32_t min_pushback_target_bitrate_bps_; + double encoding_rate_ratio_ = 1.0; +}; + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_CONGESTION_WINDOW_PUSHBACK_CONTROLLER_H_ diff --git a/modules/congestion_controller/congestion_window_pushback_controller_unittest.cc b/modules/congestion_controller/congestion_window_pushback_controller_unittest.cc new file mode 100644 index 0000000000..d9d6a79d62 --- /dev/null +++ b/modules/congestion_controller/congestion_window_pushback_controller_unittest.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "modules/congestion_controller/congestion_window_pushback_controller.h" +#include "test/gmock.h" +#include "test/gtest.h" + +using testing::_; + +namespace webrtc { +namespace test { + +class CongestionWindowPushbackControllerTest : public ::testing::Test { + protected: + CongestionWindowPushbackController cwnd_controller_; +}; + +TEST_F(CongestionWindowPushbackControllerTest, FullCongestionWindow) { + cwnd_controller_.UpdateOutstandingData(100000); + cwnd_controller_.UpdateMaxOutstandingData(50000); + + uint32_t bitrate_bps = 80000; + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(72000u, bitrate_bps); + + cwnd_controller_.UpdateMaxOutstandingData(50000); + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(static_cast(72000 * 0.9 * 0.9), bitrate_bps); +} + +TEST_F(CongestionWindowPushbackControllerTest, NormalCongestionWindow) { + cwnd_controller_.UpdateOutstandingData(100000); + cwnd_controller_.SetDataWindow(DataSize::bytes(200000)); + + uint32_t bitrate_bps = 80000; + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(80000u, bitrate_bps); + + cwnd_controller_.UpdateMaxOutstandingData(20000); + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(80000u, bitrate_bps); +} + +TEST_F(CongestionWindowPushbackControllerTest, LowBitrate) { + cwnd_controller_.UpdateOutstandingData(100000); + cwnd_controller_.SetDataWindow(DataSize::bytes(50000)); + + uint32_t bitrate_bps = 35000; + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(static_cast(35000 * 0.9), bitrate_bps); + + cwnd_controller_.UpdateMaxOutstandingData(20000); + bitrate_bps = cwnd_controller_.UpdateTargetBitrate(bitrate_bps); + EXPECT_EQ(30000u, bitrate_bps); +} + +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/include/send_side_congestion_controller.h b/modules/congestion_controller/include/send_side_congestion_controller.h index 7e5022eda0..f4270eadcc 100644 --- a/modules/congestion_controller/include/send_side_congestion_controller.h +++ b/modules/congestion_controller/include/send_side_congestion_controller.h @@ -39,6 +39,7 @@ class AcknowledgedBitrateEstimator; class ProbeController; class RateLimiter; class RtcEventLog; +class CongestionWindowPushbackController; class SendSideCongestionController : public SendSideCongestionControllerInterface { @@ -169,6 +170,9 @@ class SendSideCongestionController bool pacer_pushback_experiment_ = false; float encoding_rate_ = 1.0; + const std::unique_ptr + congestion_window_pushback_controller_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendSideCongestionController); }; diff --git a/modules/congestion_controller/rtp/send_side_congestion_controller.cc b/modules/congestion_controller/rtp/send_side_congestion_controller.cc index 40b4356147..5205940de1 100644 --- a/modules/congestion_controller/rtp/send_side_congestion_controller.cc +++ b/modules/congestion_controller/rtp/send_side_congestion_controller.cc @@ -16,6 +16,7 @@ #include #include "absl/memory/memory.h" #include "api/transport/network_types.h" +#include "modules/congestion_controller/congestion_window_pushback_controller.h" #include "modules/congestion_controller/goog_cc/include/goog_cc_factory.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/bind.h" @@ -38,6 +39,8 @@ namespace webrtc_cc { namespace { using send_side_cc_internal::PeriodicTask; +const char kCwndExperiment[] = "WebRTC-CwndExperiment"; + // When CongestionWindowPushback is enabled, the pacer is oblivious to // the congestion window. The relation between outstanding data and // the congestion window affects encoder allocations directly. @@ -47,22 +50,6 @@ const char kCongestionPushbackExperiment[] = "WebRTC-CongestionWindowPushback"; // the congestion window and/or data spikes reduces encoder allocations. const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment"; const int64_t PacerQueueUpdateIntervalMs = 25; -const uint32_t kDefaultMinPushbackTargetBitrateBps = 30000; - -bool ReadCongestionWindowPushbackExperimentParameter( - uint32_t* min_pushback_target_bitrate_bps) { - RTC_DCHECK(min_pushback_target_bitrate_bps); - std::string experiment_string = - webrtc::field_trial::FindFullName(kCongestionPushbackExperiment); - int parsed_values = sscanf(experiment_string.c_str(), "Enabled-%" PRIu32, - min_pushback_target_bitrate_bps); - if (parsed_values == 1) { - RTC_CHECK_GE(*min_pushback_target_bitrate_bps, 0) - << "Min pushback target bitrate must be greater than or equal to 0."; - return true; - } - return false; -} bool IsPacerPushbackExperimentEnabled() { return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment) || @@ -71,8 +58,16 @@ bool IsPacerPushbackExperimentEnabled() { webrtc::runtime_enabled_features::kDualStreamModeFeatureName)); } -bool IsCongestionWindowExperimentEnabled() { - return webrtc::field_trial::IsEnabled(kCongestionPushbackExperiment); +bool IsCongestionWindowPushbackExperimentEnabled() { + return webrtc::field_trial::IsEnabled(kCongestionPushbackExperiment) && + webrtc::field_trial::IsEnabled(kCwndExperiment); +} + +std::unique_ptr +MaybeInitalizeCongestionWindowPushbackController() { + return IsCongestionWindowPushbackExperimentEnabled() + ? absl::make_unique() + : nullptr; } void SortPacketFeedbackVector(std::vector* input) { @@ -200,17 +195,16 @@ class ControlHandler { PacerController* pacer_controller_; absl::optional current_target_rate_msg_; - absl::optional congestion_window_; - DataSize outstanding_data_ = DataSize::Zero(); bool network_available_ = true; int64_t last_reported_target_bitrate_bps_ = 0; uint8_t last_reported_fraction_loss_ = 0; int64_t last_reported_rtt_ms_ = 0; const bool pacer_pushback_experiment_ = false; - const bool congestion_window_pushback_experiment_ = false; uint32_t min_pushback_target_bitrate_bps_; int64_t pacer_expected_queue_ms_ = 0; double encoding_rate_ratio_ = 1.0; + const std::unique_ptr + congestion_window_pushback_controller_; rtc::SequencedTaskChecker sequenced_checker_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ControlHandler); @@ -222,21 +216,18 @@ ControlHandler::ControlHandler(NetworkChangedObserver* observer, : observer_(observer), pacer_controller_(pacer_controller), pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()), - congestion_window_pushback_experiment_( - IsCongestionWindowExperimentEnabled()) { + congestion_window_pushback_controller_( + MaybeInitalizeCongestionWindowPushbackController()) { sequenced_checker_.Detach(); - if (congestion_window_pushback_experiment_ && - !ReadCongestionWindowPushbackExperimentParameter( - &min_pushback_target_bitrate_bps_)) { - min_pushback_target_bitrate_bps_ = kDefaultMinPushbackTargetBitrateBps; - } } void ControlHandler::PostUpdates(NetworkControlUpdate update) { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); if (update.congestion_window) { - congestion_window_ = update.congestion_window; - if (!congestion_window_pushback_experiment_) { + if (congestion_window_pushback_controller_) { + congestion_window_pushback_controller_->SetDataWindow( + update.congestion_window.value()); + } else { pacer_controller_->OnCongestionWindow(*update.congestion_window); } } @@ -260,7 +251,10 @@ void ControlHandler::OnNetworkAvailability(NetworkAvailability msg) { void ControlHandler::OnOutstandingData(DataSize in_flight_data) { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - outstanding_data_ = in_flight_data; + if (congestion_window_pushback_controller_) { + congestion_window_pushback_controller_->UpdateOutstandingData( + in_flight_data.bytes()); + } OnNetworkInvalidation(); } @@ -289,29 +283,10 @@ void ControlHandler::OnNetworkInvalidation() { if (!network_available_) { target_bitrate_bps = 0; - } else if (congestion_window_pushback_experiment_ && congestion_window_) { - double fill_ratio = outstanding_data_.bytes() / - static_cast(congestion_window_->bytes()); - if (fill_ratio > 1.5) { - encoding_rate_ratio_ *= 0.9; - } else if (fill_ratio > 1) { - encoding_rate_ratio_ *= 0.95; - } else if (fill_ratio < 0.1) { - encoding_rate_ratio_ = 1.0; - } else { - encoding_rate_ratio_ *= 1.05; - encoding_rate_ratio_ = std::min(encoding_rate_ratio_, 1.0); - } - - uint32_t adjusted_target_bitrate_bps = - static_cast(target_bitrate_bps * encoding_rate_ratio_); - - // If adjusted target bitrate is lower than minimum target bitrate, - // does not reduce target bitrate lower than minimum target bitrate. + } else if (congestion_window_pushback_controller_) { target_bitrate_bps = - adjusted_target_bitrate_bps < min_pushback_target_bitrate_bps_ - ? std::min(target_bitrate_bps, min_pushback_target_bitrate_bps_) - : adjusted_target_bitrate_bps; + congestion_window_pushback_controller_->UpdateTargetBitrate( + target_bitrate_bps); } else if (!pacer_pushback_experiment_) { target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps; } else { diff --git a/modules/congestion_controller/send_side_congestion_controller.cc b/modules/congestion_controller/send_side_congestion_controller.cc index ddf7043efd..12cfb4d55f 100644 --- a/modules/congestion_controller/send_side_congestion_controller.cc +++ b/modules/congestion_controller/send_side_congestion_controller.cc @@ -18,6 +18,7 @@ #include "absl/memory/memory.h" #include "modules/bitrate_controller/include/bitrate_controller.h" +#include "modules/congestion_controller/congestion_window_pushback_controller.h" #include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h" #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" @@ -36,6 +37,12 @@ namespace { const char kCwndExperiment[] = "WebRTC-CwndExperiment"; const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment"; + +// When CongestionWindowPushback is enabled, the pacer is oblivious to +// the congestion window. The relation between outstanding data and +// the congestion window affects encoder allocations directly. +const char kCongestionPushbackExperiment[] = "WebRTC-CongestionWindowPushback"; + const int64_t kDefaultAcceptedQueueMs = 250; bool CwndExperimentEnabled() { @@ -59,6 +66,18 @@ bool ReadCwndExperimentParameter(int64_t* accepted_queue_ms) { return false; } +bool IsCongestionWindowPushbackExperimentEnabled() { + return webrtc::field_trial::IsEnabled(kCongestionPushbackExperiment) && + webrtc::field_trial::IsEnabled(kCwndExperiment); +} + +std::unique_ptr +MaybeCreateCongestionWindowPushbackController() { + return IsCongestionWindowPushbackExperimentEnabled() + ? absl::make_unique() + : nullptr; +} + static const int64_t kRetransmitWindowSizeMs = 500; // Makes sure that the bitrate and the min, max values are in valid range. @@ -135,7 +154,9 @@ SendSideCongestionController::SendSideCongestionController( send_side_bwe_with_overhead_( webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")), transport_overhead_bytes_per_packet_(0), - pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) { + pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()), + congestion_window_pushback_controller_( + MaybeCreateCongestionWindowPushbackController()) { delay_based_bwe_->SetMinBitrate(min_bitrate_bps_); if (in_cwnd_experiment_ && !ReadCwndExperimentParameter(&accepted_queue_ms_)) { @@ -418,8 +439,9 @@ void SendSideCongestionController::OnTransportFeedback( pacer_->GetApplicationLimitedRegionStartTime()); probe_controller_->RequestProbe(clock_->TimeInMilliseconds()); } - if (in_cwnd_experiment_) + if (in_cwnd_experiment_) { LimitOutstandingBytes(transport_feedback_adapter_.GetOutstandingBytes()); + } } void SendSideCongestionController::LimitOutstandingBytes( @@ -443,7 +465,14 @@ void SendSideCongestionController::LimitOutstandingBytes( << " max outstanding: " << max_outstanding_bytes; RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_rtt_ms << " Bitrate: " << last_reported_bitrate_bps_; - pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes; + if (congestion_window_pushback_controller_) { + congestion_window_pushback_controller_->UpdateOutstandingData( + num_outstanding_bytes); + congestion_window_pushback_controller_->UpdateMaxOutstandingData( + max_outstanding_bytes); + } else { + pause_pacer_ = num_outstanding_bytes > max_outstanding_bytes; + } } std::vector @@ -478,25 +507,27 @@ void SendSideCongestionController::MaybeTriggerOnNetworkChanged() { retransmission_rate_limiter_->SetMaxRate(bitrate_bps); } - if (!pacer_pushback_experiment_) { - bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps; + if (IsNetworkDown()) { + bitrate_bps = 0; + } else if (congestion_window_pushback_controller_) { + rtc::CritScope lock(&network_state_lock_); + bitrate_bps = congestion_window_pushback_controller_->UpdateTargetBitrate( + bitrate_bps); + } else if (!pacer_pushback_experiment_) { + bitrate_bps = IsSendQueueFull() ? 0 : bitrate_bps; } else { - if (IsNetworkDown()) { - bitrate_bps = 0; - } else { - int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs(); + int64_t queue_length_ms = pacer_->ExpectedQueueTimeMs(); - if (queue_length_ms == 0) { - encoding_rate_ = 1.0; - } else if (queue_length_ms > 50) { - float encoding_rate = 1.0 - queue_length_ms / 1000.0; - encoding_rate_ = std::min(encoding_rate_, encoding_rate); - encoding_rate_ = std::max(encoding_rate_, 0.0f); - } - - bitrate_bps *= encoding_rate_; - bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps; + if (queue_length_ms == 0) { + encoding_rate_ = 1.0; + } else if (queue_length_ms > 50) { + float encoding_rate = 1.0 - queue_length_ms / 1000.0; + encoding_rate_ = std::min(encoding_rate_, encoding_rate); + encoding_rate_ = std::max(encoding_rate_, 0.0f); } + + bitrate_bps *= encoding_rate_; + bitrate_bps = bitrate_bps < 50000 ? 0 : bitrate_bps; } if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {