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 #include "call/rtp_bitrate_configurator.h"
11 
12 #include <memory>
13 
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 using absl::nullopt;
18 
19 class RtpBitrateConfiguratorTest : public ::testing::Test {
20  public:
RtpBitrateConfiguratorTest()21   RtpBitrateConfiguratorTest()
22       : configurator_(new RtpBitrateConfigurator(BitrateConstraints())) {}
23   std::unique_ptr<RtpBitrateConfigurator> configurator_;
UpdateConfigMatches(BitrateConstraints bitrate_config,absl::optional<int> min_bitrate_bps,absl::optional<int> start_bitrate_bps,absl::optional<int> max_bitrate_bps)24   void UpdateConfigMatches(BitrateConstraints bitrate_config,
25                            absl::optional<int> min_bitrate_bps,
26                            absl::optional<int> start_bitrate_bps,
27                            absl::optional<int> max_bitrate_bps) {
28     absl::optional<BitrateConstraints> result =
29         configurator_->UpdateWithSdpParameters(bitrate_config);
30     EXPECT_TRUE(result.has_value());
31     if (start_bitrate_bps.has_value())
32       EXPECT_EQ(result->start_bitrate_bps, start_bitrate_bps);
33     if (min_bitrate_bps.has_value())
34       EXPECT_EQ(result->min_bitrate_bps, min_bitrate_bps);
35     if (max_bitrate_bps.has_value())
36       EXPECT_EQ(result->max_bitrate_bps, max_bitrate_bps);
37   }
38 
UpdateMaskMatches(BitrateSettings bitrate_mask,absl::optional<int> min_bitrate_bps,absl::optional<int> start_bitrate_bps,absl::optional<int> max_bitrate_bps)39   void UpdateMaskMatches(BitrateSettings bitrate_mask,
40                          absl::optional<int> min_bitrate_bps,
41                          absl::optional<int> start_bitrate_bps,
42                          absl::optional<int> max_bitrate_bps) {
43     absl::optional<BitrateConstraints> result =
44         configurator_->UpdateWithClientPreferences(bitrate_mask);
45     EXPECT_TRUE(result.has_value());
46     if (start_bitrate_bps.has_value())
47       EXPECT_EQ(result->start_bitrate_bps, start_bitrate_bps);
48     if (min_bitrate_bps.has_value())
49       EXPECT_EQ(result->min_bitrate_bps, min_bitrate_bps);
50     if (max_bitrate_bps.has_value())
51       EXPECT_EQ(result->max_bitrate_bps, max_bitrate_bps);
52   }
53 };
54 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithValidConfigReturnsNewConfig)55 TEST_F(RtpBitrateConfiguratorTest, NewConfigWithValidConfigReturnsNewConfig) {
56   BitrateConstraints bitrate_config;
57   bitrate_config.min_bitrate_bps = 1;
58   bitrate_config.start_bitrate_bps = 2;
59   bitrate_config.max_bitrate_bps = 3;
60 
61   UpdateConfigMatches(bitrate_config, 1, 2, 3);
62 }
63 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithDifferentMinReturnsNewConfig)64 TEST_F(RtpBitrateConfiguratorTest, NewConfigWithDifferentMinReturnsNewConfig) {
65   BitrateConstraints bitrate_config;
66   bitrate_config.min_bitrate_bps = 10;
67   bitrate_config.start_bitrate_bps = 20;
68   bitrate_config.max_bitrate_bps = 30;
69   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
70 
71   bitrate_config.min_bitrate_bps = 11;
72   UpdateConfigMatches(bitrate_config, 11, -1, 30);
73 }
74 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithDifferentStartReturnsNewConfig)75 TEST_F(RtpBitrateConfiguratorTest,
76        NewConfigWithDifferentStartReturnsNewConfig) {
77   BitrateConstraints bitrate_config;
78   bitrate_config.min_bitrate_bps = 10;
79   bitrate_config.start_bitrate_bps = 20;
80   bitrate_config.max_bitrate_bps = 30;
81   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
82 
83   bitrate_config.start_bitrate_bps = 21;
84   UpdateConfigMatches(bitrate_config, 10, 21, 30);
85 }
86 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithDifferentMaxReturnsNewConfig)87 TEST_F(RtpBitrateConfiguratorTest, NewConfigWithDifferentMaxReturnsNewConfig) {
88   BitrateConstraints bitrate_config;
89   bitrate_config.min_bitrate_bps = 10;
90   bitrate_config.start_bitrate_bps = 20;
91   bitrate_config.max_bitrate_bps = 30;
92   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
93 
94   bitrate_config.max_bitrate_bps = 31;
95   UpdateConfigMatches(bitrate_config, 10, -1, 31);
96 }
97 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithSameConfigElidesSecondCall)98 TEST_F(RtpBitrateConfiguratorTest, NewConfigWithSameConfigElidesSecondCall) {
99   BitrateConstraints bitrate_config;
100   bitrate_config.min_bitrate_bps = 1;
101   bitrate_config.start_bitrate_bps = 2;
102   bitrate_config.max_bitrate_bps = 3;
103 
104   UpdateConfigMatches(bitrate_config, 1, 2, 3);
105   EXPECT_FALSE(
106       configurator_->UpdateWithSdpParameters(bitrate_config).has_value());
107 }
108 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithSameMinMaxAndNegativeStartElidesSecondCall)109 TEST_F(RtpBitrateConfiguratorTest,
110        NewConfigWithSameMinMaxAndNegativeStartElidesSecondCall) {
111   BitrateConstraints bitrate_config;
112   bitrate_config.min_bitrate_bps = 1;
113   bitrate_config.start_bitrate_bps = 2;
114   bitrate_config.max_bitrate_bps = 3;
115 
116   UpdateConfigMatches(bitrate_config, 1, 2, 3);
117 
118   bitrate_config.start_bitrate_bps = -1;
119   EXPECT_FALSE(
120       configurator_->UpdateWithSdpParameters(bitrate_config).has_value());
121 }
122 
TEST_F(RtpBitrateConfiguratorTest,BiggerMaskMinUsed)123 TEST_F(RtpBitrateConfiguratorTest, BiggerMaskMinUsed) {
124   BitrateSettings mask;
125   mask.min_bitrate_bps = 1234;
126   UpdateMaskMatches(mask, *mask.min_bitrate_bps, nullopt, nullopt);
127 }
128 
TEST_F(RtpBitrateConfiguratorTest,BiggerConfigMinUsed)129 TEST_F(RtpBitrateConfiguratorTest, BiggerConfigMinUsed) {
130   BitrateSettings mask;
131   mask.min_bitrate_bps = 1000;
132   UpdateMaskMatches(mask, 1000, nullopt, nullopt);
133 
134   BitrateConstraints config;
135   config.min_bitrate_bps = 1234;
136   UpdateConfigMatches(config, 1234, nullopt, nullopt);
137 }
138 
139 // The last call to set start should be used.
TEST_F(RtpBitrateConfiguratorTest,LatestStartMaskPreferred)140 TEST_F(RtpBitrateConfiguratorTest, LatestStartMaskPreferred) {
141   BitrateSettings mask;
142   mask.start_bitrate_bps = 1300;
143   UpdateMaskMatches(mask, nullopt, *mask.start_bitrate_bps, nullopt);
144 
145   BitrateConstraints bitrate_config;
146   bitrate_config.start_bitrate_bps = 1200;
147 
148   UpdateConfigMatches(bitrate_config, nullopt, bitrate_config.start_bitrate_bps,
149                       nullopt);
150 }
151 
TEST_F(RtpBitrateConfiguratorTest,SmallerMaskMaxUsed)152 TEST_F(RtpBitrateConfiguratorTest, SmallerMaskMaxUsed) {
153   BitrateConstraints bitrate_config;
154   bitrate_config.max_bitrate_bps = bitrate_config.start_bitrate_bps + 2000;
155   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
156 
157   BitrateSettings mask;
158   mask.max_bitrate_bps = bitrate_config.start_bitrate_bps + 1000;
159 
160   UpdateMaskMatches(mask, nullopt, nullopt, *mask.max_bitrate_bps);
161 }
162 
TEST_F(RtpBitrateConfiguratorTest,SmallerConfigMaxUsed)163 TEST_F(RtpBitrateConfiguratorTest, SmallerConfigMaxUsed) {
164   BitrateConstraints bitrate_config;
165   bitrate_config.max_bitrate_bps = bitrate_config.start_bitrate_bps + 1000;
166   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
167 
168   BitrateSettings mask;
169   mask.max_bitrate_bps = bitrate_config.start_bitrate_bps + 2000;
170 
171   // Expect no return because nothing changes
172   EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
173 }
174 
TEST_F(RtpBitrateConfiguratorTest,MaskStartLessThanConfigMinClamped)175 TEST_F(RtpBitrateConfiguratorTest, MaskStartLessThanConfigMinClamped) {
176   BitrateConstraints bitrate_config;
177   bitrate_config.min_bitrate_bps = 2000;
178   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
179 
180   BitrateSettings mask;
181   mask.start_bitrate_bps = 1000;
182   UpdateMaskMatches(mask, 2000, 2000, nullopt);
183 }
184 
TEST_F(RtpBitrateConfiguratorTest,MaskStartGreaterThanConfigMaxClamped)185 TEST_F(RtpBitrateConfiguratorTest, MaskStartGreaterThanConfigMaxClamped) {
186   BitrateConstraints bitrate_config;
187   bitrate_config.start_bitrate_bps = 2000;
188   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
189 
190   BitrateSettings mask;
191   mask.max_bitrate_bps = 1000;
192 
193   UpdateMaskMatches(mask, nullopt, -1, 1000);
194 }
195 
TEST_F(RtpBitrateConfiguratorTest,MaskMinGreaterThanConfigMaxClamped)196 TEST_F(RtpBitrateConfiguratorTest, MaskMinGreaterThanConfigMaxClamped) {
197   BitrateConstraints bitrate_config;
198   bitrate_config.min_bitrate_bps = 2000;
199   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
200 
201   BitrateSettings mask;
202   mask.max_bitrate_bps = 1000;
203 
204   UpdateMaskMatches(mask, 1000, nullopt, 1000);
205 }
206 
TEST_F(RtpBitrateConfiguratorTest,SettingMaskStartForcesUpdate)207 TEST_F(RtpBitrateConfiguratorTest, SettingMaskStartForcesUpdate) {
208   BitrateSettings mask;
209   mask.start_bitrate_bps = 1000;
210 
211   // Config should be returned twice with the same params since
212   // start_bitrate_bps is set.
213   UpdateMaskMatches(mask, nullopt, 1000, nullopt);
214   UpdateMaskMatches(mask, nullopt, 1000, nullopt);
215 }
216 
TEST_F(RtpBitrateConfiguratorTest,NewConfigWithNoChangesDoesNotCallNewConfig)217 TEST_F(RtpBitrateConfiguratorTest, NewConfigWithNoChangesDoesNotCallNewConfig) {
218   BitrateConstraints config1;
219   config1.min_bitrate_bps = 0;
220   config1.start_bitrate_bps = 1000;
221   config1.max_bitrate_bps = -1;
222 
223   BitrateConstraints config2;
224   config2.min_bitrate_bps = 0;
225   config2.start_bitrate_bps = -1;
226   config2.max_bitrate_bps = -1;
227 
228   // The second call should not return anything because it doesn't
229   // change any values.
230   UpdateConfigMatches(config1, 0, 1000, -1);
231   EXPECT_FALSE(configurator_->UpdateWithSdpParameters(config2).has_value());
232 }
233 
234 // If config changes the max, but not the effective max,
235 // new config shouldn't be returned, to avoid unnecessary encoder
236 // reconfigurations.
TEST_F(RtpBitrateConfiguratorTest,NewConfigNotReturnedWhenEffectiveMaxUnchanged)237 TEST_F(RtpBitrateConfiguratorTest,
238        NewConfigNotReturnedWhenEffectiveMaxUnchanged) {
239   BitrateConstraints config;
240   config.min_bitrate_bps = 0;
241   config.start_bitrate_bps = -1;
242   config.max_bitrate_bps = 2000;
243   UpdateConfigMatches(config, nullopt, nullopt, 2000);
244 
245   // Reduce effective max to 1000 with the mask.
246   BitrateSettings mask;
247   mask.max_bitrate_bps = 1000;
248   UpdateMaskMatches(mask, nullopt, nullopt, 1000);
249 
250   // This leaves the effective max unchanged, so new config shouldn't be
251   // returned again.
252   config.max_bitrate_bps = 1000;
253   EXPECT_FALSE(configurator_->UpdateWithSdpParameters(config).has_value());
254 }
255 
256 // When the "start bitrate" mask is removed, new config shouldn't be returned
257 // again, since nothing's changing.
TEST_F(RtpBitrateConfiguratorTest,NewConfigNotReturnedWhenStartMaskRemoved)258 TEST_F(RtpBitrateConfiguratorTest, NewConfigNotReturnedWhenStartMaskRemoved) {
259   BitrateSettings mask;
260   mask.start_bitrate_bps = 1000;
261   UpdateMaskMatches(mask, 0, 1000, -1);
262 
263   mask.start_bitrate_bps.reset();
264   EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
265 }
266 
267 // Test that if a new config is returned after BitrateSettings applies a
268 // "start" value, the new config won't return that start value a
269 // second time.
TEST_F(RtpBitrateConfiguratorTest,NewConfigAfterBitrateConfigMaskWithStart)270 TEST_F(RtpBitrateConfiguratorTest, NewConfigAfterBitrateConfigMaskWithStart) {
271   BitrateSettings mask;
272   mask.start_bitrate_bps = 1000;
273   UpdateMaskMatches(mask, 0, 1000, -1);
274 
275   BitrateConstraints config;
276   config.min_bitrate_bps = 0;
277   config.start_bitrate_bps = -1;
278   config.max_bitrate_bps = 5000;
279   // The start value isn't changing, so new config should be returned with
280   // -1.
281   UpdateConfigMatches(config, 0, -1, 5000);
282 }
283 
TEST_F(RtpBitrateConfiguratorTest,NewConfigNotReturnedWhenClampedMinUnchanged)284 TEST_F(RtpBitrateConfiguratorTest,
285        NewConfigNotReturnedWhenClampedMinUnchanged) {
286   BitrateConstraints bitrate_config;
287   bitrate_config.start_bitrate_bps = 500;
288   bitrate_config.max_bitrate_bps = 1000;
289   configurator_.reset(new RtpBitrateConfigurator(bitrate_config));
290 
291   // Set min to 2000; it is clamped to the max (1000).
292   BitrateSettings mask;
293   mask.min_bitrate_bps = 2000;
294   UpdateMaskMatches(mask, 1000, -1, 1000);
295 
296   // Set min to 3000; the clamped value stays the same so nothing happens.
297   mask.min_bitrate_bps = 3000;
298   EXPECT_FALSE(configurator_->UpdateWithClientPreferences(mask).has_value());
299 }
300 }  // namespace webrtc
301