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