bitrate_controller.cc (6125B)
1 /* 2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/congestion_controller/pcc/bitrate_controller.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <cstdint> 16 #include <cstdlib> 17 #include <memory> 18 #include <optional> 19 #include <utility> 20 #include <vector> 21 22 #include "api/units/data_rate.h" 23 #include "modules/congestion_controller/pcc/monitor_interval.h" 24 #include "modules/congestion_controller/pcc/utility_function.h" 25 26 namespace webrtc { 27 namespace pcc { 28 29 PccBitrateController::PccBitrateController(double initial_conversion_factor, 30 double initial_dynamic_boundary, 31 double dynamic_boundary_increment, 32 double rtt_gradient_coefficient, 33 double loss_coefficient, 34 double throughput_coefficient, 35 double throughput_power, 36 double rtt_gradient_threshold, 37 double delay_gradient_negative_bound) 38 : PccBitrateController(initial_conversion_factor, 39 initial_dynamic_boundary, 40 dynamic_boundary_increment, 41 std::make_unique<ModifiedVivaceUtilityFunction>( 42 rtt_gradient_coefficient, 43 loss_coefficient, 44 throughput_coefficient, 45 throughput_power, 46 rtt_gradient_threshold, 47 delay_gradient_negative_bound)) {} 48 49 PccBitrateController::PccBitrateController( 50 double initial_conversion_factor, 51 double initial_dynamic_boundary, 52 double dynamic_boundary_increment, 53 std::unique_ptr<PccUtilityFunctionInterface> utility_function) 54 : consecutive_boundary_adjustments_number_(0), 55 initial_dynamic_boundary_(initial_dynamic_boundary), 56 dynamic_boundary_increment_(dynamic_boundary_increment), 57 utility_function_(std::move(utility_function)), 58 step_size_adjustments_number_(0), 59 initial_conversion_factor_(initial_conversion_factor) {} 60 61 PccBitrateController::~PccBitrateController() = default; 62 63 double PccBitrateController::ComputeStepSize(double utility_gradient) { 64 // Computes number of consecutive step size adjustments. 65 if (utility_gradient > 0) { 66 step_size_adjustments_number_ = 67 std::max<int64_t>(step_size_adjustments_number_ + 1, 1); 68 } else if (utility_gradient < 0) { 69 step_size_adjustments_number_ = 70 std::min<int64_t>(step_size_adjustments_number_ - 1, -1); 71 } else { 72 step_size_adjustments_number_ = 0; 73 } 74 // Computes step size amplifier. 75 int64_t step_size_amplifier = 1; 76 if (std::abs(step_size_adjustments_number_) <= 3) { 77 step_size_amplifier = 78 std::max<int64_t>(std::abs(step_size_adjustments_number_), 1); 79 } else { 80 step_size_amplifier = 2 * std::abs(step_size_adjustments_number_) - 3; 81 } 82 return step_size_amplifier * initial_conversion_factor_; 83 } 84 85 double PccBitrateController::ApplyDynamicBoundary(double rate_change, 86 double bitrate) { 87 double rate_change_abs = std::abs(rate_change); 88 int64_t rate_change_sign = (rate_change > 0) ? 1 : -1; 89 if (consecutive_boundary_adjustments_number_ * rate_change_sign < 0) { 90 consecutive_boundary_adjustments_number_ = 0; 91 } 92 double dynamic_change_boundary = 93 initial_dynamic_boundary_ + 94 std::abs(consecutive_boundary_adjustments_number_) * 95 dynamic_boundary_increment_; 96 double boundary = bitrate * dynamic_change_boundary; 97 if (rate_change_abs > boundary) { 98 consecutive_boundary_adjustments_number_ += rate_change_sign; 99 return boundary * rate_change_sign; 100 } 101 // Rate change smaller than boundary. Reset boundary to the smallest possible 102 // that would allow the change. 103 while (rate_change_abs <= boundary && 104 consecutive_boundary_adjustments_number_ * rate_change_sign > 0) { 105 consecutive_boundary_adjustments_number_ -= rate_change_sign; 106 dynamic_change_boundary = 107 initial_dynamic_boundary_ + 108 std::abs(consecutive_boundary_adjustments_number_) * 109 dynamic_boundary_increment_; 110 boundary = bitrate * dynamic_change_boundary; 111 } 112 consecutive_boundary_adjustments_number_ += rate_change_sign; 113 return rate_change; 114 } 115 116 std::optional<DataRate> PccBitrateController::ComputeRateUpdateForSlowStartMode( 117 const PccMonitorInterval& monitor_interval) { 118 double utility_value = utility_function_->Compute(monitor_interval); 119 if (previous_utility_.has_value() && utility_value <= previous_utility_) { 120 return std::nullopt; 121 } 122 previous_utility_ = utility_value; 123 return monitor_interval.GetTargetSendingRate(); 124 } 125 126 DataRate PccBitrateController::ComputeRateUpdateForOnlineLearningMode( 127 const std::vector<PccMonitorInterval>& intervals, 128 DataRate bandwith_estimate) { 129 double first_utility = utility_function_->Compute(intervals[0]); 130 double second_utility = utility_function_->Compute(intervals[1]); 131 double first_bitrate_bps = intervals[0].GetTargetSendingRate().bps(); 132 double second_bitrate_bps = intervals[1].GetTargetSendingRate().bps(); 133 double gradient = (first_utility - second_utility) / 134 (first_bitrate_bps - second_bitrate_bps); 135 double rate_change_bps = gradient * ComputeStepSize(gradient); // delta_r 136 rate_change_bps = 137 ApplyDynamicBoundary(rate_change_bps, bandwith_estimate.bps()); 138 return DataRate::BitsPerSec( 139 std::max(0.0, bandwith_estimate.bps() + rate_change_bps)); 140 } 141 142 } // namespace pcc 143 } // namespace webrtc