1 /*
2 * Copyright (c) 2016 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/audio_coding/audio_network_adaptor/controller_manager.h"
12
13 #include <string>
14 #include <utility>
15
16 #include "absl/strings/string_view.h"
17 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
18 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
19 #include "rtc_base/fake_clock.h"
20 #include "rtc_base/ignore_wundef.h"
21 #include "test/gtest.h"
22
23 #if WEBRTC_ENABLE_PROTOBUF
24 RTC_PUSH_IGNORING_WUNDEF()
25 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
26 #include "external/webrtc/webrtc/modules/audio_coding/audio_network_adaptor/config.pb.h"
27 #else
28 #include "modules/audio_coding/audio_network_adaptor/config.pb.h"
29 #endif
30 RTC_POP_IGNORING_WUNDEF()
31 #endif
32
33 namespace webrtc {
34
35 using ::testing::_;
36 using ::testing::NiceMock;
37
38 namespace {
39
40 constexpr size_t kNumControllers = 4;
41 constexpr int kChracteristicBandwithBps[2] = {15000, 0};
42 constexpr float kChracteristicPacketLossFraction[2] = {0.2f, 0.0f};
43 constexpr int kMinReorderingTimeMs = 200;
44 constexpr int kFactor = 100;
45 constexpr float kMinReorderingSquareDistance = 1.0f / kFactor / kFactor;
46
47 // `kMinUplinkBandwidthBps` and `kMaxUplinkBandwidthBps` are copied from
48 // controller_manager.cc
49 constexpr int kMinUplinkBandwidthBps = 0;
50 constexpr int kMaxUplinkBandwidthBps = 120000;
51 constexpr int kMinBandwithChangeBps =
52 (kMaxUplinkBandwidthBps - kMinUplinkBandwidthBps) / kFactor;
53
54 struct ControllerManagerStates {
55 std::unique_ptr<ControllerManager> controller_manager;
56 std::vector<MockController*> mock_controllers;
57 };
58
CreateControllerManager()59 ControllerManagerStates CreateControllerManager() {
60 ControllerManagerStates states;
61 std::vector<std::unique_ptr<Controller>> controllers;
62 std::map<const Controller*, std::pair<int, float>> chracteristic_points;
63 for (size_t i = 0; i < kNumControllers; ++i) {
64 auto controller =
65 std::unique_ptr<MockController>(new NiceMock<MockController>());
66 EXPECT_CALL(*controller, Die());
67 states.mock_controllers.push_back(controller.get());
68 controllers.push_back(std::move(controller));
69 }
70
71 // Assign characteristic points to the last two controllers.
72 chracteristic_points[states.mock_controllers[kNumControllers - 2]] =
73 std::make_pair(kChracteristicBandwithBps[0],
74 kChracteristicPacketLossFraction[0]);
75 chracteristic_points[states.mock_controllers[kNumControllers - 1]] =
76 std::make_pair(kChracteristicBandwithBps[1],
77 kChracteristicPacketLossFraction[1]);
78
79 states.controller_manager.reset(new ControllerManagerImpl(
80 ControllerManagerImpl::Config(kMinReorderingTimeMs,
81 kMinReorderingSquareDistance),
82 std::move(controllers), chracteristic_points));
83 return states;
84 }
85
86 // `expected_order` contains the expected indices of all controllers in the
87 // vector of controllers returned by GetSortedControllers(). A negative index
88 // means that we do not care about its exact place, but we do check that it
89 // exists in the vector.
CheckControllersOrder(ControllerManagerStates * states,const absl::optional<int> & uplink_bandwidth_bps,const absl::optional<float> & uplink_packet_loss_fraction,const std::vector<int> & expected_order)90 void CheckControllersOrder(
91 ControllerManagerStates* states,
92 const absl::optional<int>& uplink_bandwidth_bps,
93 const absl::optional<float>& uplink_packet_loss_fraction,
94 const std::vector<int>& expected_order) {
95 RTC_DCHECK_EQ(kNumControllers, expected_order.size());
96 Controller::NetworkMetrics metrics;
97 metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
98 metrics.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
99 auto check = states->controller_manager->GetSortedControllers(metrics);
100 EXPECT_EQ(states->mock_controllers.size(), check.size());
101 for (size_t i = 0; i < states->mock_controllers.size(); ++i) {
102 if (expected_order[i] >= 0) {
103 EXPECT_EQ(states->mock_controllers[i], check[expected_order[i]]);
104 } else {
105 EXPECT_NE(check.end(), std::find(check.begin(), check.end(),
106 states->mock_controllers[i]));
107 }
108 }
109 }
110
111 } // namespace
112
TEST(ControllerManagerTest,GetControllersReturnAllControllers)113 TEST(ControllerManagerTest, GetControllersReturnAllControllers) {
114 auto states = CreateControllerManager();
115 auto check = states.controller_manager->GetControllers();
116 // Verify that controllers in `check` are one-to-one mapped to those in
117 // `mock_controllers_`.
118 EXPECT_EQ(states.mock_controllers.size(), check.size());
119 for (auto& controller : check)
120 EXPECT_NE(states.mock_controllers.end(),
121 std::find(states.mock_controllers.begin(),
122 states.mock_controllers.end(), controller));
123 }
124
TEST(ControllerManagerTest,ControllersInDefaultOrderOnEmptyNetworkMetrics)125 TEST(ControllerManagerTest, ControllersInDefaultOrderOnEmptyNetworkMetrics) {
126 auto states = CreateControllerManager();
127 // `network_metrics` are empty, and the controllers are supposed to follow the
128 // default order.
129 CheckControllersOrder(&states, absl::nullopt, absl::nullopt, {0, 1, 2, 3});
130 }
131
TEST(ControllerManagerTest,ControllersWithoutCharPointAtEndAndInDefaultOrder)132 TEST(ControllerManagerTest, ControllersWithoutCharPointAtEndAndInDefaultOrder) {
133 auto states = CreateControllerManager();
134 CheckControllersOrder(&states, 0, 0.0,
135 {kNumControllers - 2, kNumControllers - 1, -1, -1});
136 }
137
TEST(ControllerManagerTest,ControllersWithCharPointDependOnNetworkMetrics)138 TEST(ControllerManagerTest, ControllersWithCharPointDependOnNetworkMetrics) {
139 auto states = CreateControllerManager();
140 CheckControllersOrder(&states, kChracteristicBandwithBps[1],
141 kChracteristicPacketLossFraction[1],
142 {kNumControllers - 2, kNumControllers - 1, 1, 0});
143 }
144
TEST(ControllerManagerTest,DoNotReorderBeforeMinReordingTime)145 TEST(ControllerManagerTest, DoNotReorderBeforeMinReordingTime) {
146 rtc::ScopedFakeClock fake_clock;
147 auto states = CreateControllerManager();
148 CheckControllersOrder(&states, kChracteristicBandwithBps[0],
149 kChracteristicPacketLossFraction[0],
150 {kNumControllers - 2, kNumControllers - 1, 0, 1});
151 fake_clock.AdvanceTime(TimeDelta::Millis(kMinReorderingTimeMs - 1));
152 // Move uplink bandwidth and packet loss fraction to the other controller's
153 // characteristic point, which would cause controller manager to reorder the
154 // controllers if time had reached min reordering time.
155 CheckControllersOrder(&states, kChracteristicBandwithBps[1],
156 kChracteristicPacketLossFraction[1],
157 {kNumControllers - 2, kNumControllers - 1, 0, 1});
158 }
159
TEST(ControllerManagerTest,ReorderBeyondMinReordingTimeAndMinDistance)160 TEST(ControllerManagerTest, ReorderBeyondMinReordingTimeAndMinDistance) {
161 rtc::ScopedFakeClock fake_clock;
162 auto states = CreateControllerManager();
163 constexpr int kBandwidthBps =
164 (kChracteristicBandwithBps[0] + kChracteristicBandwithBps[1]) / 2;
165 constexpr float kPacketLossFraction = (kChracteristicPacketLossFraction[0] +
166 kChracteristicPacketLossFraction[1]) /
167 2.0f;
168 // Set network metrics to be in the middle between the characteristic points
169 // of two controllers.
170 CheckControllersOrder(&states, kBandwidthBps, kPacketLossFraction,
171 {kNumControllers - 2, kNumControllers - 1, 0, 1});
172 fake_clock.AdvanceTime(TimeDelta::Millis(kMinReorderingTimeMs));
173 // Then let network metrics move a little towards the other controller.
174 CheckControllersOrder(&states, kBandwidthBps - kMinBandwithChangeBps - 1,
175 kPacketLossFraction,
176 {kNumControllers - 2, kNumControllers - 1, 1, 0});
177 }
178
TEST(ControllerManagerTest,DoNotReorderIfNetworkMetricsChangeTooSmall)179 TEST(ControllerManagerTest, DoNotReorderIfNetworkMetricsChangeTooSmall) {
180 rtc::ScopedFakeClock fake_clock;
181 auto states = CreateControllerManager();
182 constexpr int kBandwidthBps =
183 (kChracteristicBandwithBps[0] + kChracteristicBandwithBps[1]) / 2;
184 constexpr float kPacketLossFraction = (kChracteristicPacketLossFraction[0] +
185 kChracteristicPacketLossFraction[1]) /
186 2.0f;
187 // Set network metrics to be in the middle between the characteristic points
188 // of two controllers.
189 CheckControllersOrder(&states, kBandwidthBps, kPacketLossFraction,
190 {kNumControllers - 2, kNumControllers - 1, 0, 1});
191 fake_clock.AdvanceTime(TimeDelta::Millis(kMinReorderingTimeMs));
192 // Then let network metrics move a little towards the other controller.
193 CheckControllersOrder(&states, kBandwidthBps - kMinBandwithChangeBps + 1,
194 kPacketLossFraction,
195 {kNumControllers - 2, kNumControllers - 1, 0, 1});
196 }
197
198 #if WEBRTC_ENABLE_PROTOBUF
199
200 namespace {
201
AddBitrateControllerConfig(audio_network_adaptor::config::ControllerManager * config)202 void AddBitrateControllerConfig(
203 audio_network_adaptor::config::ControllerManager* config) {
204 config->add_controllers()->mutable_bitrate_controller();
205 }
206
AddChannelControllerConfig(audio_network_adaptor::config::ControllerManager * config)207 void AddChannelControllerConfig(
208 audio_network_adaptor::config::ControllerManager* config) {
209 auto controller_config =
210 config->add_controllers()->mutable_channel_controller();
211 controller_config->set_channel_1_to_2_bandwidth_bps(31000);
212 controller_config->set_channel_2_to_1_bandwidth_bps(29000);
213 }
214
AddDtxControllerConfig(audio_network_adaptor::config::ControllerManager * config)215 void AddDtxControllerConfig(
216 audio_network_adaptor::config::ControllerManager* config) {
217 auto controller_config = config->add_controllers()->mutable_dtx_controller();
218 controller_config->set_dtx_enabling_bandwidth_bps(55000);
219 controller_config->set_dtx_disabling_bandwidth_bps(65000);
220 }
221
AddFecControllerConfig(audio_network_adaptor::config::ControllerManager * config)222 void AddFecControllerConfig(
223 audio_network_adaptor::config::ControllerManager* config) {
224 auto controller_config_ext = config->add_controllers();
225 auto controller_config = controller_config_ext->mutable_fec_controller();
226 auto fec_enabling_threshold =
227 controller_config->mutable_fec_enabling_threshold();
228 fec_enabling_threshold->set_low_bandwidth_bps(17000);
229 fec_enabling_threshold->set_low_bandwidth_packet_loss(0.1f);
230 fec_enabling_threshold->set_high_bandwidth_bps(64000);
231 fec_enabling_threshold->set_high_bandwidth_packet_loss(0.05f);
232 auto fec_disabling_threshold =
233 controller_config->mutable_fec_disabling_threshold();
234 fec_disabling_threshold->set_low_bandwidth_bps(15000);
235 fec_disabling_threshold->set_low_bandwidth_packet_loss(0.08f);
236 fec_disabling_threshold->set_high_bandwidth_bps(64000);
237 fec_disabling_threshold->set_high_bandwidth_packet_loss(0.01f);
238 controller_config->set_time_constant_ms(500);
239
240 auto scoring_point = controller_config_ext->mutable_scoring_point();
241 scoring_point->set_uplink_bandwidth_bps(kChracteristicBandwithBps[0]);
242 scoring_point->set_uplink_packet_loss_fraction(
243 kChracteristicPacketLossFraction[0]);
244 }
245
AddFrameLengthControllerConfig(audio_network_adaptor::config::ControllerManager * config)246 void AddFrameLengthControllerConfig(
247 audio_network_adaptor::config::ControllerManager* config) {
248 auto controller_config_ext = config->add_controllers();
249 auto controller_config =
250 controller_config_ext->mutable_frame_length_controller();
251 controller_config->set_fl_decreasing_packet_loss_fraction(0.05f);
252 controller_config->set_fl_increasing_packet_loss_fraction(0.04f);
253 controller_config->set_fl_20ms_to_40ms_bandwidth_bps(80000);
254 controller_config->set_fl_40ms_to_20ms_bandwidth_bps(88000);
255 controller_config->set_fl_40ms_to_60ms_bandwidth_bps(72000);
256 controller_config->set_fl_60ms_to_40ms_bandwidth_bps(80000);
257
258 auto scoring_point = controller_config_ext->mutable_scoring_point();
259 scoring_point->set_uplink_bandwidth_bps(kChracteristicBandwithBps[1]);
260 scoring_point->set_uplink_packet_loss_fraction(
261 kChracteristicPacketLossFraction[1]);
262 }
263
AddFrameLengthControllerV2Config(audio_network_adaptor::config::ControllerManager * config)264 void AddFrameLengthControllerV2Config(
265 audio_network_adaptor::config::ControllerManager* config) {
266 auto controller =
267 config->add_controllers()->mutable_frame_length_controller_v2();
268 controller->set_min_payload_bitrate_bps(16000);
269 controller->set_use_slow_adaptation(true);
270 }
271
272 constexpr int kInitialBitrateBps = 24000;
273 constexpr size_t kIntialChannelsToEncode = 1;
274 constexpr bool kInitialDtxEnabled = true;
275 constexpr bool kInitialFecEnabled = true;
276 constexpr int kInitialFrameLengthMs = 60;
277 constexpr int kMinBitrateBps = 6000;
278
CreateControllerManager(absl::string_view config_string)279 ControllerManagerStates CreateControllerManager(
280 absl::string_view config_string) {
281 ControllerManagerStates states;
282 constexpr size_t kNumEncoderChannels = 2;
283 const std::vector<int> encoder_frame_lengths_ms = {20, 60};
284 states.controller_manager = ControllerManagerImpl::Create(
285 config_string, kNumEncoderChannels, encoder_frame_lengths_ms,
286 kMinBitrateBps, kIntialChannelsToEncode, kInitialFrameLengthMs,
287 kInitialBitrateBps, kInitialFecEnabled, kInitialDtxEnabled);
288 return states;
289 }
290
291 enum class ControllerType : int8_t {
292 FEC,
293 CHANNEL,
294 DTX,
295 FRAME_LENGTH,
296 BIT_RATE
297 };
298
CheckControllersOrder(const std::vector<Controller * > & controllers,const std::vector<ControllerType> & expected_types)299 void CheckControllersOrder(const std::vector<Controller*>& controllers,
300 const std::vector<ControllerType>& expected_types) {
301 ASSERT_EQ(expected_types.size(), controllers.size());
302
303 // We also check that the controllers follow the initial settings.
304 AudioEncoderRuntimeConfig encoder_config;
305
306 for (size_t i = 0; i < controllers.size(); ++i) {
307 AudioEncoderRuntimeConfig encoder_config;
308 // We check the order of `controllers` by judging their decisions.
309 controllers[i]->MakeDecision(&encoder_config);
310
311 // Since controllers are not provided with network metrics, they give the
312 // initial values.
313 switch (expected_types[i]) {
314 case ControllerType::FEC:
315 EXPECT_EQ(kInitialFecEnabled, encoder_config.enable_fec);
316 break;
317 case ControllerType::CHANNEL:
318 EXPECT_EQ(kIntialChannelsToEncode, encoder_config.num_channels);
319 break;
320 case ControllerType::DTX:
321 EXPECT_EQ(kInitialDtxEnabled, encoder_config.enable_dtx);
322 break;
323 case ControllerType::FRAME_LENGTH:
324 EXPECT_EQ(kInitialFrameLengthMs, encoder_config.frame_length_ms);
325 break;
326 case ControllerType::BIT_RATE:
327 EXPECT_EQ(kInitialBitrateBps, encoder_config.bitrate_bps);
328 }
329 }
330 }
331
332 MATCHER_P(ControllerManagerEqual, value, "") {
333 std::string value_string;
334 std::string arg_string;
335 EXPECT_TRUE(arg.SerializeToString(&arg_string));
336 EXPECT_TRUE(value.SerializeToString(&value_string));
337 return arg_string == value_string;
338 }
339
340 } // namespace
341
TEST(ControllerManagerTest,DebugDumpLoggedWhenCreateFromConfigString)342 TEST(ControllerManagerTest, DebugDumpLoggedWhenCreateFromConfigString) {
343 audio_network_adaptor::config::ControllerManager config;
344 config.set_min_reordering_time_ms(kMinReorderingTimeMs);
345 config.set_min_reordering_squared_distance(kMinReorderingSquareDistance);
346
347 AddFecControllerConfig(&config);
348 AddChannelControllerConfig(&config);
349 AddDtxControllerConfig(&config);
350 AddFrameLengthControllerConfig(&config);
351 AddBitrateControllerConfig(&config);
352
353 std::string config_string;
354 config.SerializeToString(&config_string);
355
356 constexpr size_t kNumEncoderChannels = 2;
357 const std::vector<int> encoder_frame_lengths_ms = {20, 60};
358
359 constexpr int64_t kClockInitialTimeMs = 12345678;
360 rtc::ScopedFakeClock fake_clock;
361 fake_clock.AdvanceTime(TimeDelta::Millis(kClockInitialTimeMs));
362 auto debug_dump_writer =
363 std::unique_ptr<MockDebugDumpWriter>(new NiceMock<MockDebugDumpWriter>());
364 EXPECT_CALL(*debug_dump_writer, Die());
365 EXPECT_CALL(*debug_dump_writer,
366 DumpControllerManagerConfig(ControllerManagerEqual(config),
367 kClockInitialTimeMs));
368
369 ControllerManagerImpl::Create(config_string, kNumEncoderChannels,
370 encoder_frame_lengths_ms, kMinBitrateBps,
371 kIntialChannelsToEncode, kInitialFrameLengthMs,
372 kInitialBitrateBps, kInitialFecEnabled,
373 kInitialDtxEnabled, debug_dump_writer.get());
374 }
375
TEST(ControllerManagerTest,CreateFromConfigStringAndCheckDefaultOrder)376 TEST(ControllerManagerTest, CreateFromConfigStringAndCheckDefaultOrder) {
377 audio_network_adaptor::config::ControllerManager config;
378 config.set_min_reordering_time_ms(kMinReorderingTimeMs);
379 config.set_min_reordering_squared_distance(kMinReorderingSquareDistance);
380
381 AddFecControllerConfig(&config);
382 AddChannelControllerConfig(&config);
383 AddDtxControllerConfig(&config);
384 AddFrameLengthControllerConfig(&config);
385 AddBitrateControllerConfig(&config);
386
387 std::string config_string;
388 config.SerializeToString(&config_string);
389
390 auto states = CreateControllerManager(config_string);
391 Controller::NetworkMetrics metrics;
392
393 auto controllers = states.controller_manager->GetSortedControllers(metrics);
394 CheckControllersOrder(
395 controllers,
396 std::vector<ControllerType>{
397 ControllerType::FEC, ControllerType::CHANNEL, ControllerType::DTX,
398 ControllerType::FRAME_LENGTH, ControllerType::BIT_RATE});
399 }
400
TEST(ControllerManagerTest,CreateCharPointFreeConfigAndCheckDefaultOrder)401 TEST(ControllerManagerTest, CreateCharPointFreeConfigAndCheckDefaultOrder) {
402 audio_network_adaptor::config::ControllerManager config;
403
404 // Following controllers have no characteristic points.
405 AddChannelControllerConfig(&config);
406 AddDtxControllerConfig(&config);
407 AddBitrateControllerConfig(&config);
408
409 std::string config_string;
410 config.SerializeToString(&config_string);
411
412 auto states = CreateControllerManager(config_string);
413 Controller::NetworkMetrics metrics;
414
415 auto controllers = states.controller_manager->GetSortedControllers(metrics);
416 CheckControllersOrder(
417 controllers,
418 std::vector<ControllerType>{ControllerType::CHANNEL, ControllerType::DTX,
419 ControllerType::BIT_RATE});
420 }
421
TEST(ControllerManagerTest,CreateFromConfigStringAndCheckReordering)422 TEST(ControllerManagerTest, CreateFromConfigStringAndCheckReordering) {
423 rtc::ScopedFakeClock fake_clock;
424 audio_network_adaptor::config::ControllerManager config;
425 config.set_min_reordering_time_ms(kMinReorderingTimeMs);
426 config.set_min_reordering_squared_distance(kMinReorderingSquareDistance);
427
428 AddChannelControllerConfig(&config);
429
430 // Internally associated with characteristic point 0.
431 AddFecControllerConfig(&config);
432
433 AddDtxControllerConfig(&config);
434
435 // Internally associated with characteristic point 1.
436 AddFrameLengthControllerConfig(&config);
437
438 AddBitrateControllerConfig(&config);
439
440 std::string config_string;
441 config.SerializeToString(&config_string);
442
443 auto states = CreateControllerManager(config_string);
444
445 Controller::NetworkMetrics metrics;
446 metrics.uplink_bandwidth_bps = kChracteristicBandwithBps[0];
447 metrics.uplink_packet_loss_fraction = kChracteristicPacketLossFraction[0];
448
449 auto controllers = states.controller_manager->GetSortedControllers(metrics);
450 CheckControllersOrder(controllers,
451 std::vector<ControllerType>{
452 ControllerType::FEC, ControllerType::FRAME_LENGTH,
453 ControllerType::CHANNEL, ControllerType::DTX,
454 ControllerType::BIT_RATE});
455
456 metrics.uplink_bandwidth_bps = kChracteristicBandwithBps[1];
457 metrics.uplink_packet_loss_fraction = kChracteristicPacketLossFraction[1];
458 fake_clock.AdvanceTime(TimeDelta::Millis(kMinReorderingTimeMs - 1));
459 controllers = states.controller_manager->GetSortedControllers(metrics);
460 // Should not reorder since min reordering time is not met.
461 CheckControllersOrder(controllers,
462 std::vector<ControllerType>{
463 ControllerType::FEC, ControllerType::FRAME_LENGTH,
464 ControllerType::CHANNEL, ControllerType::DTX,
465 ControllerType::BIT_RATE});
466
467 fake_clock.AdvanceTime(TimeDelta::Millis(1));
468 controllers = states.controller_manager->GetSortedControllers(metrics);
469 // Reorder now.
470 CheckControllersOrder(controllers,
471 std::vector<ControllerType>{
472 ControllerType::FRAME_LENGTH, ControllerType::FEC,
473 ControllerType::CHANNEL, ControllerType::DTX,
474 ControllerType::BIT_RATE});
475 }
476
TEST(ControllerManagerTest,CreateFrameLengthControllerV2)477 TEST(ControllerManagerTest, CreateFrameLengthControllerV2) {
478 audio_network_adaptor::config::ControllerManager config;
479 AddFrameLengthControllerV2Config(&config);
480 auto states = CreateControllerManager(config.SerializeAsString());
481 auto controllers = states.controller_manager->GetControllers();
482 EXPECT_TRUE(controllers.size() == 1);
483 }
484 #endif // WEBRTC_ENABLE_PROTOBUF
485
486 } // namespace webrtc
487