/* * 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/pcc/bitrate_controller.h" #include #include #include #include #include #include namespace webrtc { namespace pcc { PccBitrateController::PccBitrateController(double initial_conversion_factor, double initial_dynamic_boundary, double dynamic_boundary_increment, double rtt_gradient_coefficient, double loss_coefficient, double throughput_coefficient, double throughput_power, double rtt_gradient_threshold, double delay_gradient_negative_bound) : PccBitrateController(initial_conversion_factor, initial_dynamic_boundary, dynamic_boundary_increment, std::make_unique( rtt_gradient_coefficient, loss_coefficient, throughput_coefficient, throughput_power, rtt_gradient_threshold, delay_gradient_negative_bound)) {} PccBitrateController::PccBitrateController( double initial_conversion_factor, double initial_dynamic_boundary, double dynamic_boundary_increment, std::unique_ptr utility_function) : consecutive_boundary_adjustments_number_(0), initial_dynamic_boundary_(initial_dynamic_boundary), dynamic_boundary_increment_(dynamic_boundary_increment), utility_function_(std::move(utility_function)), step_size_adjustments_number_(0), initial_conversion_factor_(initial_conversion_factor) {} PccBitrateController::~PccBitrateController() = default; double PccBitrateController::ComputeStepSize(double utility_gradient) { // Computes number of consecutive step size adjustments. if (utility_gradient > 0) { step_size_adjustments_number_ = std::max(step_size_adjustments_number_ + 1, 1); } else if (utility_gradient < 0) { step_size_adjustments_number_ = std::min(step_size_adjustments_number_ - 1, -1); } else { step_size_adjustments_number_ = 0; } // Computes step size amplifier. int64_t step_size_amplifier = 1; if (std::abs(step_size_adjustments_number_) <= 3) { step_size_amplifier = std::max(std::abs(step_size_adjustments_number_), 1); } else { step_size_amplifier = 2 * std::abs(step_size_adjustments_number_) - 3; } return step_size_amplifier * initial_conversion_factor_; } double PccBitrateController::ApplyDynamicBoundary(double rate_change, double bitrate) { double rate_change_abs = std::abs(rate_change); int64_t rate_change_sign = (rate_change > 0) ? 1 : -1; if (consecutive_boundary_adjustments_number_ * rate_change_sign < 0) { consecutive_boundary_adjustments_number_ = 0; } double dynamic_change_boundary = initial_dynamic_boundary_ + std::abs(consecutive_boundary_adjustments_number_) * dynamic_boundary_increment_; double boundary = bitrate * dynamic_change_boundary; if (rate_change_abs > boundary) { consecutive_boundary_adjustments_number_ += rate_change_sign; return boundary * rate_change_sign; } // Rate change smaller than boundary. Reset boundary to the smallest possible // that would allow the change. while (rate_change_abs <= boundary && consecutive_boundary_adjustments_number_ * rate_change_sign > 0) { consecutive_boundary_adjustments_number_ -= rate_change_sign; dynamic_change_boundary = initial_dynamic_boundary_ + std::abs(consecutive_boundary_adjustments_number_) * dynamic_boundary_increment_; boundary = bitrate * dynamic_change_boundary; } consecutive_boundary_adjustments_number_ += rate_change_sign; return rate_change; } absl::optional PccBitrateController::ComputeRateUpdateForSlowStartMode( const PccMonitorInterval& monitor_interval) { double utility_value = utility_function_->Compute(monitor_interval); if (previous_utility_.has_value() && utility_value <= previous_utility_) { return absl::nullopt; } previous_utility_ = utility_value; return monitor_interval.GetTargetSendingRate(); } DataRate PccBitrateController::ComputeRateUpdateForOnlineLearningMode( const std::vector& intervals, DataRate bandwith_estimate) { double first_utility = utility_function_->Compute(intervals[0]); double second_utility = utility_function_->Compute(intervals[1]); double first_bitrate_bps = intervals[0].GetTargetSendingRate().bps(); double second_bitrate_bps = intervals[1].GetTargetSendingRate().bps(); double gradient = (first_utility - second_utility) / (first_bitrate_bps - second_bitrate_bps); double rate_change_bps = gradient * ComputeStepSize(gradient); // delta_r rate_change_bps = ApplyDynamicBoundary(rate_change_bps, bandwith_estimate.bps()); return DataRate::BitsPerSec( std::max(0.0, bandwith_estimate.bps() + rate_change_bps)); } } // namespace pcc } // namespace webrtc