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