OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2017 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 <random> |
| 12 #include <utility> |
| 13 |
| 14 #include "webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_
based.h" |
| 15 #include "webrtc/test/gmock.h" |
| 16 #include "webrtc/test/gtest.h" |
| 17 |
| 18 namespace webrtc { |
| 19 |
| 20 using ::testing::NiceMock; |
| 21 using ::testing::Return; |
| 22 using ::testing::_; |
| 23 |
| 24 namespace { |
| 25 |
| 26 // The test uses the following settings: |
| 27 // |
| 28 // recoverable ^ |
| 29 // packet-loss | | | |
| 30 // | A| C| FEC |
| 31 // | \ \ ON |
| 32 // | FEC \ D\_______ |
| 33 // | OFF B\_________ |
| 34 // |-----------------> bandwidth |
| 35 // |
| 36 // A : (kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw) |
| 37 // B : (kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw) |
| 38 // C : (kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw) |
| 39 // D : (kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw) |
| 40 |
| 41 constexpr int kDisablingBandwidthLow = 15000; |
| 42 constexpr float kDisablingRecoverablePacketLossAtLowBw = 0.08f; |
| 43 constexpr int kDisablingBandwidthHigh = 64000; |
| 44 constexpr float kDisablingRecoverablePacketLossAtHighBw = 0.01f; |
| 45 constexpr int kEnablingBandwidthLow = 17000; |
| 46 constexpr float kEnablingRecoverablePacketLossAtLowBw = 0.1f; |
| 47 constexpr int kEnablingBandwidthHigh = 64000; |
| 48 constexpr float kEnablingRecoverablePacketLossAtHighBw = 0.05f; |
| 49 |
| 50 rtc::Optional<float> GetRandomProbabilityOrUnknown() { |
| 51 std::random_device rd; |
| 52 std::mt19937 generator(rd()); |
| 53 std::uniform_real_distribution<> distribution(0, 1); |
| 54 |
| 55 if (distribution(generator) < 0.2) { |
| 56 return rtc::Optional<float>(); |
| 57 } else { |
| 58 return rtc::Optional<float>(distribution(generator)); |
| 59 } |
| 60 } |
| 61 |
| 62 std::unique_ptr<FecControllerRplrBased> CreateFecControllerRplrBased( |
| 63 bool initial_fec_enabled) { |
| 64 using Threshold = FecControllerRplrBased::Config::Threshold; |
| 65 return std::unique_ptr<FecControllerRplrBased>( |
| 66 new FecControllerRplrBased(FecControllerRplrBased::Config( |
| 67 initial_fec_enabled, |
| 68 Threshold( |
| 69 kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw, |
| 70 kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), |
| 71 Threshold( |
| 72 kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw, |
| 73 kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw), |
| 74 0, nullptr))); |
| 75 } |
| 76 |
| 77 void UpdateNetworkMetrics( |
| 78 FecControllerRplrBased* controller, |
| 79 const rtc::Optional<int>& uplink_bandwidth_bps, |
| 80 const rtc::Optional<float>& uplink_packet_loss, |
| 81 const rtc::Optional<float>& uplink_recoveralbe_packet_loss) { |
| 82 // UpdateNetworkMetrics can accept multiple network metric updates at once. |
| 83 // However, currently, the most used case is to update one metric at a time. |
| 84 // To reflect this fact, we separate the calls. |
| 85 if (uplink_bandwidth_bps) { |
| 86 Controller::NetworkMetrics network_metrics; |
| 87 network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps; |
| 88 controller->UpdateNetworkMetrics(network_metrics); |
| 89 } |
| 90 if (uplink_packet_loss) { |
| 91 Controller::NetworkMetrics network_metrics; |
| 92 network_metrics.uplink_packet_loss_fraction = uplink_packet_loss; |
| 93 controller->UpdateNetworkMetrics(network_metrics); |
| 94 } |
| 95 if (uplink_recoveralbe_packet_loss) { |
| 96 Controller::NetworkMetrics network_metrics; |
| 97 network_metrics.uplink_recoverable_packet_loss_fraction = |
| 98 uplink_recoveralbe_packet_loss; |
| 99 controller->UpdateNetworkMetrics(network_metrics); |
| 100 } |
| 101 } |
| 102 |
| 103 void UpdateNetworkMetrics( |
| 104 FecControllerRplrBased* controller, |
| 105 const rtc::Optional<int>& uplink_bandwidth_bps, |
| 106 const rtc::Optional<float>& uplink_recoveralbe_packet_loss) { |
| 107 // FecControllerRplrBased doesn't current use the PLR (general packet-loss |
| 108 // rate) at all. (This might be changed in the future.) The unit-tests will |
| 109 // use a random value (including unknown), to show this does not interfere. |
| 110 UpdateNetworkMetrics(controller, uplink_bandwidth_bps, |
| 111 GetRandomProbabilityOrUnknown(), |
| 112 uplink_recoveralbe_packet_loss); |
| 113 } |
| 114 |
| 115 // Checks that the FEC decision and |uplink_packet_loss_fraction| given by |
| 116 // |states->controller->MakeDecision| matches |expected_enable_fec| and |
| 117 // |expected_uplink_packet_loss_fraction|, respectively. |
| 118 void CheckDecision(FecControllerRplrBased* controller, |
| 119 bool expected_enable_fec, |
| 120 float expected_uplink_packet_loss_fraction) { |
| 121 AudioNetworkAdaptor::EncoderRuntimeConfig config; |
| 122 controller->MakeDecision(&config); |
| 123 |
| 124 // Less compact than comparing optionals, but yields more readable errors. |
| 125 EXPECT_TRUE(config.enable_fec); |
| 126 if (config.enable_fec) { |
| 127 EXPECT_EQ(expected_enable_fec, *config.enable_fec); |
| 128 } |
| 129 EXPECT_TRUE(config.uplink_packet_loss_fraction); |
| 130 if (config.uplink_packet_loss_fraction) { |
| 131 EXPECT_EQ(expected_uplink_packet_loss_fraction, |
| 132 *config.uplink_packet_loss_fraction); |
| 133 } |
| 134 } |
| 135 |
| 136 } // namespace |
| 137 |
| 138 TEST(FecControllerRplrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) { |
| 139 for (bool initial_fec_enabled : {false, true}) { |
| 140 auto controller = CreateFecControllerRplrBased(initial_fec_enabled); |
| 141 // Let uplink recoverable packet loss fraction be so low that it |
| 142 // would cause FEC to turn off if uplink bandwidth was known. |
| 143 UpdateNetworkMetrics( |
| 144 controller.get(), rtc::Optional<int>(), |
| 145 rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw)); |
| 146 CheckDecision(controller.get(), initial_fec_enabled, |
| 147 kDisablingRecoverablePacketLossAtHighBw); |
| 148 } |
| 149 } |
| 150 |
| 151 TEST(FecControllerRplrBasedTest, |
| 152 OutputInitValueWhenUplinkPacketLossFractionUnknown) { |
| 153 for (bool initial_fec_enabled : {false, true}) { |
| 154 auto controller = CreateFecControllerRplrBased(initial_fec_enabled); |
| 155 // Let uplink bandwidth be so low that it would cause FEC to turn off |
| 156 // if uplink bandwidth packet loss fraction was known. |
| 157 UpdateNetworkMetrics(controller.get(), |
| 158 rtc::Optional<int>(kDisablingBandwidthLow - 1), |
| 159 rtc::Optional<float>()); |
| 160 CheckDecision(controller.get(), initial_fec_enabled, 0.0); |
| 161 } |
| 162 } |
| 163 |
| 164 TEST(FecControllerRplrBasedTest, EnableFecForHighBandwidth) { |
| 165 auto controller = CreateFecControllerRplrBased(false); |
| 166 UpdateNetworkMetrics( |
| 167 controller.get(), rtc::Optional<int>(kEnablingBandwidthHigh), |
| 168 rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw)); |
| 169 CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); |
| 170 } |
| 171 |
| 172 TEST(FecControllerRplrBasedTest, UpdateMultipleNetworkMetricsAtOnce) { |
| 173 // This test is similar to EnableFecForHighBandwidth. But instead of |
| 174 // using ::UpdateNetworkMetrics(...), which calls |
| 175 // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) multiple times, we |
| 176 // we call it only once. This is to verify that |
| 177 // FecControllerRplrBasedTest::UpdateNetworkMetrics(...) can handle multiple |
| 178 // network updates at once. This is, however, not a common use case in current |
| 179 // audio_network_adaptor_impl.cc. |
| 180 auto controller = CreateFecControllerRplrBased(false); |
| 181 Controller::NetworkMetrics network_metrics; |
| 182 network_metrics.uplink_bandwidth_bps = |
| 183 rtc::Optional<int>(kEnablingBandwidthHigh); |
| 184 network_metrics.uplink_packet_loss_fraction = |
| 185 rtc::Optional<float>(GetRandomProbabilityOrUnknown()); |
| 186 network_metrics.uplink_recoverable_packet_loss_fraction = |
| 187 rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw); |
| 188 controller->UpdateNetworkMetrics(network_metrics); |
| 189 CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); |
| 190 } |
| 191 |
| 192 TEST(FecControllerRplrBasedTest, MaintainFecOffForHighBandwidth) { |
| 193 auto controller = CreateFecControllerRplrBased(false); |
| 194 constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtHighBw * 0.99f; |
| 195 UpdateNetworkMetrics(controller.get(), |
| 196 rtc::Optional<int>(kEnablingBandwidthHigh), |
| 197 rtc::Optional<float>(kPacketLoss)); |
| 198 CheckDecision(controller.get(), false, kPacketLoss); |
| 199 } |
| 200 |
| 201 TEST(FecControllerRplrBasedTest, EnableFecForMediumBandwidth) { |
| 202 auto controller = CreateFecControllerRplrBased(false); |
| 203 constexpr float kPacketLoss = (kEnablingRecoverablePacketLossAtLowBw + |
| 204 kEnablingRecoverablePacketLossAtHighBw) / |
| 205 2.0; |
| 206 UpdateNetworkMetrics( |
| 207 controller.get(), |
| 208 rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2), |
| 209 rtc::Optional<float>(kPacketLoss)); |
| 210 CheckDecision(controller.get(), true, kPacketLoss); |
| 211 } |
| 212 |
| 213 TEST(FecControllerRplrBasedTest, MaintainFecOffForMediumBandwidth) { |
| 214 auto controller = CreateFecControllerRplrBased(false); |
| 215 constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtLowBw * 0.49f + |
| 216 kEnablingRecoverablePacketLossAtHighBw * 0.51f; |
| 217 UpdateNetworkMetrics( |
| 218 controller.get(), |
| 219 rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2), |
| 220 rtc::Optional<float>(kPacketLoss)); |
| 221 CheckDecision(controller.get(), false, kPacketLoss); |
| 222 } |
| 223 |
| 224 TEST(FecControllerRplrBasedTest, EnableFecForLowBandwidth) { |
| 225 auto controller = CreateFecControllerRplrBased(false); |
| 226 UpdateNetworkMetrics( |
| 227 controller.get(), rtc::Optional<int>(kEnablingBandwidthLow), |
| 228 rtc::Optional<float>(kEnablingRecoverablePacketLossAtLowBw)); |
| 229 CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtLowBw); |
| 230 } |
| 231 |
| 232 TEST(FecControllerRplrBasedTest, MaintainFecOffForLowBandwidth) { |
| 233 auto controller = CreateFecControllerRplrBased(false); |
| 234 constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtLowBw * 0.99f; |
| 235 UpdateNetworkMetrics(controller.get(), |
| 236 rtc::Optional<int>(kEnablingBandwidthLow), |
| 237 rtc::Optional<float>(kPacketLoss)); |
| 238 CheckDecision(controller.get(), false, kPacketLoss); |
| 239 } |
| 240 |
| 241 TEST(FecControllerRplrBasedTest, MaintainFecOffForVeryLowBandwidth) { |
| 242 auto controller = CreateFecControllerRplrBased(false); |
| 243 // Below |kEnablingBandwidthLow|, no recoverable packet loss fraction can |
| 244 // cause FEC to turn on. |
| 245 UpdateNetworkMetrics(controller.get(), |
| 246 rtc::Optional<int>(kEnablingBandwidthLow - 1), |
| 247 rtc::Optional<float>(1.0)); |
| 248 CheckDecision(controller.get(), false, 1.0); |
| 249 } |
| 250 |
| 251 TEST(FecControllerRplrBasedTest, DisableFecForHighBandwidth) { |
| 252 auto controller = CreateFecControllerRplrBased(true); |
| 253 UpdateNetworkMetrics( |
| 254 controller.get(), rtc::Optional<int>(kDisablingBandwidthHigh), |
| 255 rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw)); |
| 256 CheckDecision(controller.get(), false, |
| 257 kDisablingRecoverablePacketLossAtHighBw); |
| 258 } |
| 259 |
| 260 TEST(FecControllerRplrBasedTest, MaintainFecOnForHighBandwidth) { |
| 261 auto controller = CreateFecControllerRplrBased(true); |
| 262 constexpr float kPacketLoss = kDisablingRecoverablePacketLossAtHighBw * 1.01f; |
| 263 UpdateNetworkMetrics(controller.get(), |
| 264 rtc::Optional<int>(kDisablingBandwidthHigh), |
| 265 rtc::Optional<float>(kPacketLoss)); |
| 266 CheckDecision(controller.get(), true, kPacketLoss); |
| 267 } |
| 268 |
| 269 TEST(FecControllerRplrBasedTest, DisableFecOnMediumBandwidth) { |
| 270 auto controller = CreateFecControllerRplrBased(true); |
| 271 constexpr float kPacketLoss = (kDisablingRecoverablePacketLossAtLowBw + |
| 272 kDisablingRecoverablePacketLossAtHighBw) / |
| 273 2.0f; |
| 274 UpdateNetworkMetrics( |
| 275 controller.get(), |
| 276 rtc::Optional<int>((kDisablingBandwidthHigh + kDisablingBandwidthLow) / |
| 277 2), |
| 278 rtc::Optional<float>(kPacketLoss)); |
| 279 CheckDecision(controller.get(), false, kPacketLoss); |
| 280 } |
| 281 |
| 282 TEST(FecControllerRplrBasedTest, MaintainFecOnForMediumBandwidth) { |
| 283 auto controller = CreateFecControllerRplrBased(true); |
| 284 constexpr float kPacketLoss = kDisablingRecoverablePacketLossAtLowBw * 0.51f + |
| 285 kDisablingRecoverablePacketLossAtHighBw * 0.49f; |
| 286 UpdateNetworkMetrics( |
| 287 controller.get(), |
| 288 rtc::Optional<int>((kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2), |
| 289 rtc::Optional<float>(kPacketLoss)); |
| 290 CheckDecision(controller.get(), true, kPacketLoss); |
| 291 } |
| 292 |
| 293 TEST(FecControllerRplrBasedTest, DisableFecForLowBandwidth) { |
| 294 auto controller = CreateFecControllerRplrBased(true); |
| 295 UpdateNetworkMetrics( |
| 296 controller.get(), rtc::Optional<int>(kDisablingBandwidthLow), |
| 297 rtc::Optional<float>(kDisablingRecoverablePacketLossAtLowBw)); |
| 298 CheckDecision(controller.get(), false, |
| 299 kDisablingRecoverablePacketLossAtLowBw); |
| 300 } |
| 301 |
| 302 TEST(FecControllerRplrBasedTest, DisableFecForVeryLowBandwidth) { |
| 303 auto controller = CreateFecControllerRplrBased(true); |
| 304 // Below |kEnablingBandwidthLow|, any recoverable packet loss fraction can |
| 305 // cause FEC to turn off. |
| 306 UpdateNetworkMetrics(controller.get(), |
| 307 rtc::Optional<int>(kDisablingBandwidthLow - 1), |
| 308 rtc::Optional<float>(1.0)); |
| 309 CheckDecision(controller.get(), false, 1.0); |
| 310 } |
| 311 |
| 312 TEST(FecControllerRplrBasedTest, CheckBehaviorOnChangingNetworkMetrics) { |
| 313 // In this test, we let the network metrics to traverse from 1 to 5. |
| 314 // |
| 315 // recoverable ^ |
| 316 // packet-loss | 1 | | |
| 317 // | | 2| |
| 318 // | \ \ 3 |
| 319 // | \4 \_______ |
| 320 // | \_________ |
| 321 // |---------5-------> bandwidth |
| 322 |
| 323 auto controller = CreateFecControllerRplrBased(true); |
| 324 UpdateNetworkMetrics(controller.get(), |
| 325 rtc::Optional<int>(kDisablingBandwidthLow - 1), |
| 326 rtc::Optional<float>(1.0)); |
| 327 CheckDecision(controller.get(), false, 1.0); |
| 328 |
| 329 UpdateNetworkMetrics( |
| 330 controller.get(), rtc::Optional<int>(kEnablingBandwidthLow), |
| 331 rtc::Optional<float>(kEnablingRecoverablePacketLossAtLowBw * 0.99f)); |
| 332 CheckDecision(controller.get(), false, |
| 333 kEnablingRecoverablePacketLossAtLowBw * 0.99f); |
| 334 |
| 335 UpdateNetworkMetrics( |
| 336 controller.get(), rtc::Optional<int>(kEnablingBandwidthHigh), |
| 337 rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw)); |
| 338 CheckDecision(controller.get(), true, kEnablingRecoverablePacketLossAtHighBw); |
| 339 |
| 340 UpdateNetworkMetrics( |
| 341 controller.get(), rtc::Optional<int>(kDisablingBandwidthHigh), |
| 342 rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw * 1.01f)); |
| 343 CheckDecision(controller.get(), true, |
| 344 kDisablingRecoverablePacketLossAtHighBw * 1.01f); |
| 345 |
| 346 UpdateNetworkMetrics(controller.get(), |
| 347 rtc::Optional<int>(kDisablingBandwidthHigh + 1), |
| 348 rtc::Optional<float>(0.0)); |
| 349 CheckDecision(controller.get(), false, 0.0); |
| 350 } |
| 351 |
| 352 TEST(FecControllerRplrBasedTest, CheckBehaviorOnSpecialCurves) { |
| 353 // We test a special configuration, where the points to define the FEC |
| 354 // enabling/disabling curves are placed like the following, otherwise the test |
| 355 // is the same as CheckBehaviorOnChangingNetworkMetrics. |
| 356 // |
| 357 // recoverable ^ |
| 358 // packet-loss | | | |
| 359 // | | C| |
| 360 // | | | |
| 361 // | | D|_______ |
| 362 // | A|___B______ |
| 363 // |-----------------> bandwidth |
| 364 |
| 365 constexpr int kEnablingBandwidthHigh = kEnablingBandwidthLow; |
| 366 constexpr float kDisablingRecoverablePacketLossAtLowBw = |
| 367 kDisablingRecoverablePacketLossAtHighBw; |
| 368 using Threshold = FecControllerRplrBased::Config::Threshold; |
| 369 FecControllerRplrBased controller(FecControllerRplrBased::Config( |
| 370 true, |
| 371 Threshold(kEnablingBandwidthLow, kEnablingRecoverablePacketLossAtLowBw, |
| 372 kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), |
| 373 Threshold(kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw, |
| 374 kDisablingBandwidthHigh, |
| 375 kDisablingRecoverablePacketLossAtHighBw), |
| 376 0, nullptr)); |
| 377 |
| 378 UpdateNetworkMetrics(&controller, |
| 379 rtc::Optional<int>(kDisablingBandwidthLow - 1), |
| 380 rtc::Optional<float>(1.0)); |
| 381 CheckDecision(&controller, false, 1.0); |
| 382 |
| 383 UpdateNetworkMetrics( |
| 384 &controller, rtc::Optional<int>(kEnablingBandwidthLow), |
| 385 rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw * 0.99f)); |
| 386 CheckDecision(&controller, false, |
| 387 kEnablingRecoverablePacketLossAtHighBw * 0.99f); |
| 388 |
| 389 UpdateNetworkMetrics( |
| 390 &controller, rtc::Optional<int>(kEnablingBandwidthHigh), |
| 391 rtc::Optional<float>(kEnablingRecoverablePacketLossAtHighBw)); |
| 392 CheckDecision(&controller, true, kEnablingRecoverablePacketLossAtHighBw); |
| 393 |
| 394 UpdateNetworkMetrics( |
| 395 &controller, rtc::Optional<int>(kDisablingBandwidthHigh), |
| 396 rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw * 1.01f)); |
| 397 CheckDecision(&controller, true, |
| 398 kDisablingRecoverablePacketLossAtHighBw * 1.01f); |
| 399 |
| 400 UpdateNetworkMetrics(&controller, |
| 401 rtc::Optional<int>(kDisablingBandwidthHigh + 1), |
| 402 rtc::Optional<float>(0.0)); |
| 403 CheckDecision(&controller, false, 0.0); |
| 404 } |
| 405 |
| 406 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) |
| 407 TEST(FecControllerRplrBasedDeathTest, InvalidConfig) { |
| 408 using Threshold = FecControllerRplrBased::Config::Threshold; |
| 409 EXPECT_DEATH( |
| 410 FecControllerRplrBased controller(FecControllerRplrBased::Config( |
| 411 true, |
| 412 Threshold( |
| 413 kDisablingBandwidthLow - 1, kEnablingRecoverablePacketLossAtLowBw, |
| 414 kEnablingBandwidthHigh, kEnablingRecoverablePacketLossAtHighBw), |
| 415 Threshold( |
| 416 kDisablingBandwidthLow, kDisablingRecoverablePacketLossAtLowBw, |
| 417 kDisablingBandwidthHigh, kDisablingRecoverablePacketLossAtHighBw), |
| 418 0, nullptr)), |
| 419 "Check failed"); |
| 420 } |
| 421 #endif |
| 422 |
| 423 } // namespace webrtc |
OLD | NEW |