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 "call/rtp_bitrate_configurator.h"
12
13 #include <algorithm>
14
15 #include "rtc_base/checks.h"
16
17 namespace {
18
19 // Returns its smallest positive argument. If neither argument is positive,
20 // returns an arbitrary nonpositive value.
MinPositive(int a,int b)21 int MinPositive(int a, int b) {
22 if (a <= 0) {
23 return b;
24 }
25 if (b <= 0) {
26 return a;
27 }
28 return std::min(a, b);
29 }
30
31 } // namespace
32
33 namespace webrtc {
RtpBitrateConfigurator(const BitrateConstraints & bitrate_config)34 RtpBitrateConfigurator::RtpBitrateConfigurator(
35 const BitrateConstraints& bitrate_config)
36 : bitrate_config_(bitrate_config), base_bitrate_config_(bitrate_config) {
37 RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
38 RTC_DCHECK_GE(bitrate_config.start_bitrate_bps,
39 bitrate_config.min_bitrate_bps);
40 if (bitrate_config.max_bitrate_bps != -1) {
41 RTC_DCHECK_GE(bitrate_config.max_bitrate_bps,
42 bitrate_config.start_bitrate_bps);
43 }
44 }
45
46 RtpBitrateConfigurator::~RtpBitrateConfigurator() = default;
47
GetConfig() const48 BitrateConstraints RtpBitrateConfigurator::GetConfig() const {
49 return bitrate_config_;
50 }
51
52 absl::optional<BitrateConstraints>
UpdateWithSdpParameters(const BitrateConstraints & bitrate_config)53 RtpBitrateConfigurator::UpdateWithSdpParameters(
54 const BitrateConstraints& bitrate_config) {
55 RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
56 RTC_DCHECK_NE(bitrate_config.start_bitrate_bps, 0);
57 if (bitrate_config.max_bitrate_bps != -1) {
58 RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
59 }
60
61 absl::optional<int> new_start;
62 // Only update the "start" bitrate if it's set, and different from the old
63 // value. In practice, this value comes from the x-google-start-bitrate codec
64 // parameter in SDP, and setting the same remote description twice shouldn't
65 // restart bandwidth estimation.
66 if (bitrate_config.start_bitrate_bps != -1 &&
67 bitrate_config.start_bitrate_bps !=
68 base_bitrate_config_.start_bitrate_bps) {
69 new_start.emplace(bitrate_config.start_bitrate_bps);
70 }
71 base_bitrate_config_ = bitrate_config;
72 return UpdateConstraints(new_start);
73 }
74
75 absl::optional<BitrateConstraints>
UpdateWithClientPreferences(const BitrateSettings & bitrate_mask)76 RtpBitrateConfigurator::UpdateWithClientPreferences(
77 const BitrateSettings& bitrate_mask) {
78 bitrate_config_mask_ = bitrate_mask;
79 return UpdateConstraints(bitrate_mask.start_bitrate_bps);
80 }
81
82 // Relay cap can change only max bitrate.
UpdateWithRelayCap(DataRate cap)83 absl::optional<BitrateConstraints> RtpBitrateConfigurator::UpdateWithRelayCap(
84 DataRate cap) {
85 if (cap.IsFinite()) {
86 RTC_DCHECK(!cap.IsZero());
87 }
88 max_bitrate_over_relay_ = cap;
89 return UpdateConstraints(absl::nullopt);
90 }
91
UpdateConstraints(const absl::optional<int> & new_start)92 absl::optional<BitrateConstraints> RtpBitrateConfigurator::UpdateConstraints(
93 const absl::optional<int>& new_start) {
94 BitrateConstraints updated;
95 updated.min_bitrate_bps =
96 std::max(bitrate_config_mask_.min_bitrate_bps.value_or(0),
97 base_bitrate_config_.min_bitrate_bps);
98
99 updated.max_bitrate_bps =
100 MinPositive(bitrate_config_mask_.max_bitrate_bps.value_or(-1),
101 base_bitrate_config_.max_bitrate_bps);
102 updated.max_bitrate_bps =
103 MinPositive(updated.max_bitrate_bps, max_bitrate_over_relay_.bps_or(-1));
104
105 // If the combined min ends up greater than the combined max, the max takes
106 // priority.
107 if (updated.max_bitrate_bps != -1 &&
108 updated.min_bitrate_bps > updated.max_bitrate_bps) {
109 updated.min_bitrate_bps = updated.max_bitrate_bps;
110 }
111
112 // If there is nothing to update (min/max unchanged, no new bandwidth
113 // estimation start value), return early.
114 if (updated.min_bitrate_bps == bitrate_config_.min_bitrate_bps &&
115 updated.max_bitrate_bps == bitrate_config_.max_bitrate_bps &&
116 !new_start) {
117 return absl::nullopt;
118 }
119
120 if (new_start) {
121 // Clamp start by min and max.
122 updated.start_bitrate_bps = MinPositive(
123 std::max(*new_start, updated.min_bitrate_bps), updated.max_bitrate_bps);
124 } else {
125 updated.start_bitrate_bps = -1;
126 }
127 BitrateConstraints config_to_return = updated;
128 if (!new_start) {
129 updated.start_bitrate_bps = bitrate_config_.start_bitrate_bps;
130 }
131 bitrate_config_ = updated;
132 return config_to_return;
133 }
134
135 } // namespace webrtc
136