• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdlib>
16 #include <memory>
17 #include <utility>
18 #include <vector>
19 
20 
21 namespace webrtc {
22 namespace pcc {
23 
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)24 PccBitrateController::PccBitrateController(double initial_conversion_factor,
25                                            double initial_dynamic_boundary,
26                                            double dynamic_boundary_increment,
27                                            double rtt_gradient_coefficient,
28                                            double loss_coefficient,
29                                            double throughput_coefficient,
30                                            double throughput_power,
31                                            double rtt_gradient_threshold,
32                                            double delay_gradient_negative_bound)
33     : PccBitrateController(initial_conversion_factor,
34                            initial_dynamic_boundary,
35                            dynamic_boundary_increment,
36                            std::make_unique<ModifiedVivaceUtilityFunction>(
37                                rtt_gradient_coefficient,
38                                loss_coefficient,
39                                throughput_coefficient,
40                                throughput_power,
41                                rtt_gradient_threshold,
42                                delay_gradient_negative_bound)) {}
43 
PccBitrateController(double initial_conversion_factor,double initial_dynamic_boundary,double dynamic_boundary_increment,std::unique_ptr<PccUtilityFunctionInterface> utility_function)44 PccBitrateController::PccBitrateController(
45     double initial_conversion_factor,
46     double initial_dynamic_boundary,
47     double dynamic_boundary_increment,
48     std::unique_ptr<PccUtilityFunctionInterface> utility_function)
49     : consecutive_boundary_adjustments_number_(0),
50       initial_dynamic_boundary_(initial_dynamic_boundary),
51       dynamic_boundary_increment_(dynamic_boundary_increment),
52       utility_function_(std::move(utility_function)),
53       step_size_adjustments_number_(0),
54       initial_conversion_factor_(initial_conversion_factor) {}
55 
56 PccBitrateController::~PccBitrateController() = default;
57 
ComputeStepSize(double utility_gradient)58 double PccBitrateController::ComputeStepSize(double utility_gradient) {
59   // Computes number of consecutive step size adjustments.
60   if (utility_gradient > 0) {
61     step_size_adjustments_number_ =
62         std::max<int64_t>(step_size_adjustments_number_ + 1, 1);
63   } else if (utility_gradient < 0) {
64     step_size_adjustments_number_ =
65         std::min<int64_t>(step_size_adjustments_number_ - 1, -1);
66   } else {
67     step_size_adjustments_number_ = 0;
68   }
69   // Computes step size amplifier.
70   int64_t step_size_amplifier = 1;
71   if (std::abs(step_size_adjustments_number_) <= 3) {
72     step_size_amplifier =
73         std::max<int64_t>(std::abs(step_size_adjustments_number_), 1);
74   } else {
75     step_size_amplifier = 2 * std::abs(step_size_adjustments_number_) - 3;
76   }
77   return step_size_amplifier * initial_conversion_factor_;
78 }
79 
ApplyDynamicBoundary(double rate_change,double bitrate)80 double PccBitrateController::ApplyDynamicBoundary(double rate_change,
81                                                   double bitrate) {
82   double rate_change_abs = std::abs(rate_change);
83   int64_t rate_change_sign = (rate_change > 0) ? 1 : -1;
84   if (consecutive_boundary_adjustments_number_ * rate_change_sign < 0) {
85     consecutive_boundary_adjustments_number_ = 0;
86   }
87   double dynamic_change_boundary =
88       initial_dynamic_boundary_ +
89       std::abs(consecutive_boundary_adjustments_number_) *
90           dynamic_boundary_increment_;
91   double boundary = bitrate * dynamic_change_boundary;
92   if (rate_change_abs > boundary) {
93     consecutive_boundary_adjustments_number_ += rate_change_sign;
94     return boundary * rate_change_sign;
95   }
96   // Rate change smaller than boundary. Reset boundary to the smallest possible
97   // that would allow the change.
98   while (rate_change_abs <= boundary &&
99          consecutive_boundary_adjustments_number_ * rate_change_sign > 0) {
100     consecutive_boundary_adjustments_number_ -= rate_change_sign;
101     dynamic_change_boundary =
102         initial_dynamic_boundary_ +
103         std::abs(consecutive_boundary_adjustments_number_) *
104             dynamic_boundary_increment_;
105     boundary = bitrate * dynamic_change_boundary;
106   }
107   consecutive_boundary_adjustments_number_ += rate_change_sign;
108   return rate_change;
109 }
110 
111 absl::optional<DataRate>
ComputeRateUpdateForSlowStartMode(const PccMonitorInterval & monitor_interval)112 PccBitrateController::ComputeRateUpdateForSlowStartMode(
113     const PccMonitorInterval& monitor_interval) {
114   double utility_value = utility_function_->Compute(monitor_interval);
115   if (previous_utility_.has_value() && utility_value <= previous_utility_) {
116     return absl::nullopt;
117   }
118   previous_utility_ = utility_value;
119   return monitor_interval.GetTargetSendingRate();
120 }
121 
ComputeRateUpdateForOnlineLearningMode(const std::vector<PccMonitorInterval> & intervals,DataRate bandwith_estimate)122 DataRate PccBitrateController::ComputeRateUpdateForOnlineLearningMode(
123     const std::vector<PccMonitorInterval>& intervals,
124     DataRate bandwith_estimate) {
125   double first_utility = utility_function_->Compute(intervals[0]);
126   double second_utility = utility_function_->Compute(intervals[1]);
127   double first_bitrate_bps = intervals[0].GetTargetSendingRate().bps();
128   double second_bitrate_bps = intervals[1].GetTargetSendingRate().bps();
129   double gradient = (first_utility - second_utility) /
130                     (first_bitrate_bps - second_bitrate_bps);
131   double rate_change_bps = gradient * ComputeStepSize(gradient);  // delta_r
132   rate_change_bps =
133       ApplyDynamicBoundary(rate_change_bps, bandwith_estimate.bps());
134   return DataRate::BitsPerSec(
135       std::max(0.0, bandwith_estimate.bps() + rate_change_bps));
136 }
137 
138 }  // namespace pcc
139 }  // namespace webrtc
140