diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index b0bf6f31f0..829faea381 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -348,7 +348,13 @@ rtc::Optional GoogCcNetworkController::MaybeUpdateCongestionWindow() { TimeDelta time_window = TimeDelta::ms(*min_feedback_rtt_ms_ + accepted_queue_ms_); DataSize data_window = last_bandwidth_ * time_window; - data_window = std::max(kMinCwnd, data_window); + if (current_data_window_) { + data_window = + std::max(kMinCwnd, (data_window + current_data_window_.value()) / 2); + } else { + data_window = std::max(kMinCwnd, data_window); + } + current_data_window_ = data_window; RTC_LOG(LS_INFO) << "Feedback rtt: " << *min_feedback_rtt_ms_ << " Bitrate: " << last_bandwidth_.bps(); return data_window; diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/modules/congestion_controller/goog_cc/goog_cc_network_control.h index f7039f0a17..3afd8d23a7 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -89,6 +89,8 @@ class GoogCcNetworkController : public NetworkControllerInterface { int64_t accepted_queue_ms_; bool previously_in_alr = false; + rtc::Optional current_data_window_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController); }; diff --git a/modules/congestion_controller/rtp/send_side_congestion_controller.cc b/modules/congestion_controller/rtp/send_side_congestion_controller.cc index fa010e8234..4ee5b7c4f8 100644 --- a/modules/congestion_controller/rtp/send_side_congestion_controller.cc +++ b/modules/congestion_controller/rtp/send_side_congestion_controller.cc @@ -38,8 +38,16 @@ namespace webrtc_cc { namespace { using send_side_cc_internal::PeriodicTask; +// 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"; + +// When PacerPushbackExperiment is enabled, build-up in the pacer due to +// the congestion window and/or data spikes reduces encoder allocations. const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment"; const int64_t PacerQueueUpdateIntervalMs = 25; +const uint32_t MinPushbackTargetBitrateBps = 30000; bool IsPacerPushbackExperimentEnabled() { return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment) || @@ -48,6 +56,10 @@ bool IsPacerPushbackExperimentEnabled() { webrtc::runtime_enabled_features::kDualStreamModeFeatureName)); } +bool IsCongestionWindowExperimentEnabled() { + return webrtc::field_trial::IsEnabled(kCongestionPushbackExperiment); +} + void SortPacketFeedbackVector(std::vector* input) { std::sort(input->begin(), input->end(), PacketFeedbackComparator()); } @@ -155,6 +167,7 @@ class ControlHandler { void PostUpdates(NetworkControlUpdate update); void OnNetworkAvailability(NetworkAvailability msg); + void OnOutstandingData(DataSize in_flight_data); void OnPacerQueueUpdate(TimeDelta expected_queue_time); rtc::Optional last_transfer_rate(); @@ -172,13 +185,16 @@ class ControlHandler { PacerController* pacer_controller_; rtc::Optional current_target_rate_msg_; + rtc::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; int64_t pacer_expected_queue_ms_ = 0; - float encoding_rate_ratio_ = 1.0; + double encoding_rate_ratio_ = 1.0; rtc::SequencedTaskChecker sequenced_checker_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ControlHandler); @@ -189,14 +205,19 @@ ControlHandler::ControlHandler(NetworkChangedObserver* observer, const Clock* clock) : observer_(observer), pacer_controller_(pacer_controller), - pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) { + pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()), + congestion_window_pushback_experiment_( + IsCongestionWindowExperimentEnabled()) { sequenced_checker_.Detach(); } void ControlHandler::PostUpdates(NetworkControlUpdate update) { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); - if (update.congestion_window) { - pacer_controller_->OnCongestionWindow(*update.congestion_window); + if (congestion_window_pushback_experiment_) { + if (update.congestion_window) { + congestion_window_ = update.congestion_window; + pacer_controller_->OnCongestionWindow(*update.congestion_window); + } } if (update.pacer_config) { pacer_controller_->OnPacerConfig(*update.pacer_config); @@ -216,6 +237,12 @@ void ControlHandler::OnNetworkAvailability(NetworkAvailability msg) { OnNetworkInvalidation(); } +void ControlHandler::OnOutstandingData(DataSize in_flight_data) { + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); + outstanding_data_ = in_flight_data; + OnNetworkInvalidation(); +} + void ControlHandler::OnPacerQueueUpdate(TimeDelta expected_queue_time) { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_); pacer_expected_queue_ms_ = expected_queue_time.ms(); @@ -241,6 +268,29 @@ 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. + target_bitrate_bps = + adjusted_target_bitrate_bps < MinPushbackTargetBitrateBps + ? std::min(target_bitrate_bps, MinPushbackTargetBitrateBps) + : adjusted_target_bitrate_bps; } else if (!pacer_pushback_experiment_) { target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps; } else { @@ -249,9 +299,9 @@ void ControlHandler::OnNetworkInvalidation() { if (queue_length_ms == 0) { encoding_rate_ratio_ = 1.0; } else if (queue_length_ms > 50) { - float encoding_ratio = 1.0 - queue_length_ms / 1000.0; + double encoding_ratio = 1.0 - queue_length_ms / 1000.0; encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio); - encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0f); + encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0); } target_bitrate_bps *= encoding_rate_ratio_; @@ -667,6 +717,8 @@ void SendSideCongestionController::MaybeUpdateOutstandingData() { task_queue_->PostTask([this, in_flight_data]() { RTC_DCHECK_RUN_ON(task_queue_); pacer_controller_->OnOutstandingData(in_flight_data); + if (control_handler_) + control_handler_->OnOutstandingData(in_flight_data); }); }