summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/congestion_controller/pcc/bitrate_controller.cc
blob: 16b8e6966fa1c2dd0d47dbbe54ee41835fec7b9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 *  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 <algorithm>
#include <cmath>
#include <cstdlib>
#include <memory>
#include <utility>
#include <vector>


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<ModifiedVivaceUtilityFunction>(
                               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<PccUtilityFunctionInterface> 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<int64_t>(step_size_adjustments_number_ + 1, 1);
  } else if (utility_gradient < 0) {
    step_size_adjustments_number_ =
        std::min<int64_t>(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<int64_t>(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<DataRate>
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<PccMonitorInterval>& 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