| Index: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
|
| diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
|
| index 3884df61a0bc3b7b0fd950fbf2dc647ed6392687..f0272d4831bca0bef6ebcdf6ef5c1a3a961ac53e 100644
|
| --- a/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
|
| +++ b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
|
| @@ -42,6 +42,8 @@ constexpr float kEnablingRecoverablePacketLossAtLowBw = 0.1f;
|
| constexpr int kEnablingBandwidthHigh = 64000;
|
| constexpr float kEnablingRecoverablePacketLossAtHighBw = 0.05f;
|
|
|
| +constexpr float kEpsilon = 1e-5f;
|
| +
|
| rtc::Optional<float> GetRandomProbabilityOrUnknown() {
|
| std::random_device rd;
|
| std::mt19937 generator(rd());
|
| @@ -98,7 +100,7 @@ void UpdateNetworkMetrics(
|
| FecControllerRplrBased* controller,
|
| const rtc::Optional<int>& uplink_bandwidth_bps,
|
| const rtc::Optional<float>& uplink_recoveralbe_packet_loss) {
|
| - // FecControllerRplrBased doesn't current use the PLR (general packet-loss
|
| + // FecControllerRplrBased doesn't currently use the PLR (general packet-loss
|
| // rate) at all. (This might be changed in the future.) The unit-tests will
|
| // use a random value (including unknown), to show this does not interfere.
|
| UpdateNetworkMetrics(controller, uplink_bandwidth_bps,
|
| @@ -106,6 +108,15 @@ void UpdateNetworkMetrics(
|
| uplink_recoveralbe_packet_loss);
|
| }
|
|
|
| +// TODO(eladalon): In a separate CL (to make reviewers' lives easier), use
|
| +// this where applicable.
|
| +void UpdateNetworkMetrics(FecControllerRplrBased* controller,
|
| + int uplink_bandwidth_bps,
|
| + float uplink_recoveralbe_packet_loss) {
|
| + UpdateNetworkMetrics(controller, rtc::Optional<int>(uplink_bandwidth_bps),
|
| + rtc::Optional<float>(uplink_recoveralbe_packet_loss));
|
| +}
|
| +
|
| // Checks that the FEC decision and |uplink_packet_loss_fraction| given by
|
| // |states->controller->MakeDecision| matches |expected_enable_fec| and
|
| // |expected_uplink_packet_loss_fraction|, respectively.
|
| @@ -129,29 +140,46 @@ void CheckDecision(FecControllerRplrBased* controller,
|
|
|
| } // namespace
|
|
|
| -TEST(FecControllerRplrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) {
|
| +TEST(FecControllerRplrBasedTest, OutputInitValueBeforeAnyInputsAreReceived) {
|
| for (bool initial_fec_enabled : {false, true}) {
|
| auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
|
| - // Let uplink recoverable packet loss fraction be so low that it
|
| - // would cause FEC to turn off if uplink bandwidth was known.
|
| - UpdateNetworkMetrics(
|
| - controller.get(), rtc::Optional<int>(),
|
| - rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw));
|
| - CheckDecision(controller.get(), initial_fec_enabled,
|
| - kDisablingRecoverablePacketLossAtHighBw);
|
| + CheckDecision(controller.get(), initial_fec_enabled, 0);
|
| + }
|
| +}
|
| +
|
| +TEST(FecControllerRplrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) {
|
| + // Regardless of the initial FEC state and the recoverable-packet-loss
|
| + // rate, the initial FEC state is maintained as long as the BWE is unknown.
|
| + for (bool initial_fec_enabled : {false, true}) {
|
| + for (float recoverable_packet_loss :
|
| + {kDisablingRecoverablePacketLossAtHighBw - kEpsilon,
|
| + kDisablingRecoverablePacketLossAtHighBw,
|
| + kDisablingRecoverablePacketLossAtHighBw + kEpsilon,
|
| + kEnablingRecoverablePacketLossAtHighBw - kEpsilon,
|
| + kEnablingRecoverablePacketLossAtHighBw,
|
| + kEnablingRecoverablePacketLossAtHighBw + kEpsilon}) {
|
| + auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
|
| + UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(),
|
| + rtc::Optional<float>(recoverable_packet_loss));
|
| + CheckDecision(controller.get(), initial_fec_enabled,
|
| + recoverable_packet_loss);
|
| + }
|
| }
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest,
|
| - OutputInitValueWhenUplinkPacketLossFractionUnknown) {
|
| + OutputInitValueWhenUplinkRecoverablePacketLossFractionUnknown) {
|
| + // Regardless of the initial FEC state and the BWE, the initial FEC state
|
| + // is maintained as long as the recoverable-packet-loss rate is unknown.
|
| for (bool initial_fec_enabled : {false, true}) {
|
| - auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
|
| - // Let uplink bandwidth be so low that it would cause FEC to turn off
|
| - // if uplink bandwidth packet loss fraction was known.
|
| - UpdateNetworkMetrics(controller.get(),
|
| - rtc::Optional<int>(kDisablingBandwidthLow - 1),
|
| - rtc::Optional<float>());
|
| - CheckDecision(controller.get(), initial_fec_enabled, 0.0);
|
| + for (int bandwidth : {kDisablingBandwidthLow - 1, kDisablingBandwidthLow,
|
| + kDisablingBandwidthLow + 1, kEnablingBandwidthLow - 1,
|
| + kEnablingBandwidthLow, kEnablingBandwidthLow + 1}) {
|
| + auto controller = CreateFecControllerRplrBased(initial_fec_enabled);
|
| + UpdateNetworkMetrics(controller.get(), rtc::Optional<int>(bandwidth),
|
| + rtc::Optional<float>());
|
| + CheckDecision(controller.get(), initial_fec_enabled, 0.0);
|
| + }
|
| }
|
| }
|
|
|
| @@ -185,34 +213,36 @@ TEST(FecControllerRplrBasedTest, UpdateMultipleNetworkMetricsAtOnce) {
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOffForHighBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(false);
|
| - constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtHighBw * 0.99f;
|
| + constexpr float kRecoverablePacketLoss =
|
| + kEnablingRecoverablePacketLossAtHighBw * 0.99f;
|
| UpdateNetworkMetrics(controller.get(),
|
| rtc::Optional<int>(kEnablingBandwidthHigh),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), false, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, EnableFecForMediumBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(false);
|
| - constexpr float kPacketLoss = (kEnablingRecoverablePacketLossAtLowBw +
|
| - kEnablingRecoverablePacketLossAtHighBw) /
|
| - 2.0;
|
| + constexpr float kRecoverablePacketLoss =
|
| + (kEnablingRecoverablePacketLossAtLowBw +
|
| + kEnablingRecoverablePacketLossAtHighBw) / 2.0;
|
| UpdateNetworkMetrics(
|
| controller.get(),
|
| rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), true, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), true, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOffForMediumBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(false);
|
| - constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtLowBw * 0.49f +
|
| - kEnablingRecoverablePacketLossAtHighBw * 0.51f;
|
| + constexpr float kRecoverablePacketLoss =
|
| + kEnablingRecoverablePacketLossAtLowBw * 0.49f +
|
| + kEnablingRecoverablePacketLossAtHighBw * 0.51f;
|
| UpdateNetworkMetrics(
|
| controller.get(),
|
| rtc::Optional<int>((kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), false, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, EnableFecForLowBandwidth) {
|
| @@ -225,11 +255,12 @@ TEST(FecControllerRplrBasedTest, EnableFecForLowBandwidth) {
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOffForLowBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(false);
|
| - constexpr float kPacketLoss = kEnablingRecoverablePacketLossAtLowBw * 0.99f;
|
| + constexpr float kRecoverablePacketLoss =
|
| + kEnablingRecoverablePacketLossAtLowBw * 0.99f;
|
| UpdateNetworkMetrics(controller.get(),
|
| rtc::Optional<int>(kEnablingBandwidthLow),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), false, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOffForVeryLowBandwidth) {
|
| @@ -244,53 +275,57 @@ TEST(FecControllerRplrBasedTest, MaintainFecOffForVeryLowBandwidth) {
|
|
|
| TEST(FecControllerRplrBasedTest, DisableFecForHighBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(true);
|
| - UpdateNetworkMetrics(
|
| - controller.get(), rtc::Optional<int>(kDisablingBandwidthHigh),
|
| - rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw));
|
| - CheckDecision(controller.get(), false,
|
| - kDisablingRecoverablePacketLossAtHighBw);
|
| + constexpr float kRecoverablePacketLoss =
|
| + kDisablingRecoverablePacketLossAtHighBw - kEpsilon;
|
| + UpdateNetworkMetrics(controller.get(),
|
| + rtc::Optional<int>(kDisablingBandwidthHigh),
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOnForHighBandwidth) {
|
| + // Note: Disabling happens when the value is strictly below the threshold.
|
| auto controller = CreateFecControllerRplrBased(true);
|
| - constexpr float kPacketLoss = kDisablingRecoverablePacketLossAtHighBw * 1.01f;
|
| - UpdateNetworkMetrics(controller.get(),
|
| - rtc::Optional<int>(kDisablingBandwidthHigh),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), true, kPacketLoss);
|
| + UpdateNetworkMetrics(
|
| + controller.get(), rtc::Optional<int>(kDisablingBandwidthHigh),
|
| + rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw));
|
| + CheckDecision(controller.get(), true,
|
| + kDisablingRecoverablePacketLossAtHighBw);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, DisableFecOnMediumBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(true);
|
| - constexpr float kPacketLoss = (kDisablingRecoverablePacketLossAtLowBw +
|
| - kDisablingRecoverablePacketLossAtHighBw) /
|
| - 2.0f;
|
| + constexpr float kRecoverablePacketLoss =
|
| + ((kDisablingRecoverablePacketLossAtLowBw +
|
| + kDisablingRecoverablePacketLossAtHighBw) / 2.0f) - kEpsilon;
|
| UpdateNetworkMetrics(
|
| controller.get(),
|
| rtc::Optional<int>((kDisablingBandwidthHigh + kDisablingBandwidthLow) /
|
| 2),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), false, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, MaintainFecOnForMediumBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(true);
|
| - constexpr float kPacketLoss = kDisablingRecoverablePacketLossAtLowBw * 0.51f +
|
| - kDisablingRecoverablePacketLossAtHighBw * 0.49f;
|
| + constexpr float kRecoverablePacketLoss =
|
| + kDisablingRecoverablePacketLossAtLowBw * 0.51f +
|
| + kDisablingRecoverablePacketLossAtHighBw * 0.49f - kEpsilon;
|
| UpdateNetworkMetrics(
|
| controller.get(),
|
| rtc::Optional<int>((kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2),
|
| - rtc::Optional<float>(kPacketLoss));
|
| - CheckDecision(controller.get(), true, kPacketLoss);
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), true, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, DisableFecForLowBandwidth) {
|
| auto controller = CreateFecControllerRplrBased(true);
|
| - UpdateNetworkMetrics(
|
| - controller.get(), rtc::Optional<int>(kDisablingBandwidthLow),
|
| - rtc::Optional<float>(kDisablingRecoverablePacketLossAtLowBw));
|
| - CheckDecision(controller.get(), false,
|
| - kDisablingRecoverablePacketLossAtLowBw);
|
| + constexpr float kRecoverablePacketLoss =
|
| + kDisablingRecoverablePacketLossAtLowBw - kEpsilon;
|
| + UpdateNetworkMetrics(controller.get(),
|
| + rtc::Optional<int>(kDisablingBandwidthLow),
|
| + rtc::Optional<float>(kRecoverablePacketLoss));
|
| + CheckDecision(controller.get(), false, kRecoverablePacketLoss);
|
| }
|
|
|
| TEST(FecControllerRplrBasedTest, DisableFecForVeryLowBandwidth) {
|
| @@ -333,9 +368,9 @@ TEST(FecControllerRplrBasedTest, CheckBehaviorOnChangingNetworkMetrics) {
|
|
|
| UpdateNetworkMetrics(
|
| controller.get(), rtc::Optional<int>(kDisablingBandwidthHigh),
|
| - rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw * 1.01f));
|
| + rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw));
|
| CheckDecision(controller.get(), true,
|
| - kDisablingRecoverablePacketLossAtHighBw * 1.01f);
|
| + kDisablingRecoverablePacketLossAtHighBw);
|
|
|
| UpdateNetworkMetrics(controller.get(),
|
| rtc::Optional<int>(kDisablingBandwidthHigh + 1),
|
| @@ -386,9 +421,8 @@ TEST(FecControllerRplrBasedTest, CheckBehaviorOnSpecialCurves) {
|
|
|
| UpdateNetworkMetrics(
|
| &controller, rtc::Optional<int>(kDisablingBandwidthHigh),
|
| - rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw * 1.01f));
|
| - CheckDecision(&controller, true,
|
| - kDisablingRecoverablePacketLossAtHighBw * 1.01f);
|
| + rtc::Optional<float>(kDisablingRecoverablePacketLossAtHighBw));
|
| + CheckDecision(&controller, true, kDisablingRecoverablePacketLossAtHighBw);
|
|
|
| UpdateNetworkMetrics(&controller,
|
| rtc::Optional<int>(kDisablingBandwidthHigh + 1),
|
| @@ -396,6 +430,120 @@ TEST(FecControllerRplrBasedTest, CheckBehaviorOnSpecialCurves) {
|
| CheckDecision(&controller, false, 0.0);
|
| }
|
|
|
| +TEST(FecControllerRplrBasedTest, SingleThresholdCurveForEnablingAndDisabling) {
|
| + // Note: To avoid numerical errors, keep kRecoverablePacketLossAtLowBw and
|
| + // kRecoverablePacketLossAthighBw as (negative) integer powers of 2.
|
| + // This is mostly relevant for the O3 case.
|
| + constexpr int kBandwidthLow = 10000;
|
| + constexpr float kRecoverablePacketLossAtLowBw = 0.25f;
|
| + constexpr int kBandwidthHigh = 20000;
|
| + constexpr float kRecoverablePacketLossAtHighBw = 0.125f;
|
| + auto curve = ThresholdCurve(kBandwidthLow, kRecoverablePacketLossAtLowBw,
|
| + kBandwidthHigh, kRecoverablePacketLossAtHighBw);
|
| +
|
| + // B* stands for "below-curve", O* for "on-curve", and A* for "above-curve".
|
| + //
|
| + // //
|
| + // recoverable ^ //
|
| + // packet-loss | | //
|
| + // | B1 O1 //
|
| + // | | //
|
| + // | O2 //
|
| + // | \ A1 //
|
| + // | \ //
|
| + // | O3 A2 //
|
| + // | B2 \ //
|
| + // | \ //
|
| + // | O4--O5---- //
|
| + // | //
|
| + // | B3 //
|
| + // |-----------------> bandwidth //
|
| +
|
| + struct NetworkState {
|
| + int bandwidth;
|
| + float recoverable_packet_loss;
|
| + };
|
| +
|
| + std::vector<NetworkState> below{
|
| + {kBandwidthLow - 1, kRecoverablePacketLossAtLowBw + 0.1f}, // B1
|
| + {(kBandwidthLow + kBandwidthHigh) / 2,
|
| + (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 -
|
| + kEpsilon}, // B2
|
| + {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw - kEpsilon} // B3
|
| + };
|
| +
|
| + std::vector<NetworkState> on{
|
| + {kBandwidthLow, kRecoverablePacketLossAtLowBw + 0.1f}, // O1
|
| + {kBandwidthLow, kRecoverablePacketLossAtLowBw}, // O2
|
| + {(kBandwidthLow + kBandwidthHigh) / 2,
|
| + (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) /
|
| + 2}, // O3
|
| + {kBandwidthHigh, kRecoverablePacketLossAtHighBw}, // O4
|
| + {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw}, // O5
|
| + };
|
| +
|
| + std::vector<NetworkState> above{
|
| + {(kBandwidthLow + kBandwidthHigh) / 2,
|
| + (kRecoverablePacketLossAtLowBw + kRecoverablePacketLossAtHighBw) / 2 +
|
| + kEpsilon}, // A1
|
| + {kBandwidthHigh + 1, kRecoverablePacketLossAtHighBw + kEpsilon}, // A2
|
| + };
|
| +
|
| + // Test that FEC is turned off whenever we're below the curve, independent
|
| + // of the starting FEC state.
|
| + for (NetworkState net_state : below) {
|
| + for (bool initial_fec_enabled : {false, true}) {
|
| + FecControllerRplrBased controller(
|
| + FecControllerRplrBased::Config(initial_fec_enabled, curve, curve));
|
| + UpdateNetworkMetrics(&controller, net_state.bandwidth,
|
| + net_state.recoverable_packet_loss);
|
| + CheckDecision(&controller, false, net_state.recoverable_packet_loss);
|
| + }
|
| + }
|
| +
|
| + // Test that FEC is turned on whenever we're on the curve or above it,
|
| + // independent of the starting FEC state.
|
| + for (std::vector<NetworkState> states_list : {on, above}) {
|
| + for (NetworkState net_state : states_list) {
|
| + for (bool initial_fec_enabled : {false, true}) {
|
| + FecControllerRplrBased controller(
|
| + FecControllerRplrBased::Config(initial_fec_enabled, curve, curve));
|
| + UpdateNetworkMetrics(&controller, net_state.bandwidth,
|
| + net_state.recoverable_packet_loss);
|
| + CheckDecision(&controller, true, net_state.recoverable_packet_loss);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST(FecControllerRplrBasedTest, FecAlwaysOff) {
|
| + ThresholdCurve always_off_curve(0, 1.0f + kEpsilon, 0, 1.0f + kEpsilon);
|
| + for (bool initial_fec_enabled : {false, true}) {
|
| + for (int bandwidth : {0, 10000}) {
|
| + for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) {
|
| + FecControllerRplrBased controller(FecControllerRplrBased::Config(
|
| + initial_fec_enabled, always_off_curve, always_off_curve));
|
| + UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss);
|
| + CheckDecision(&controller, false, recoverable_packet_loss);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST(FecControllerRplrBasedTest, FecAlwaysOn) {
|
| + ThresholdCurve always_on_curve(0, 0.0f, 0, 0.0f);
|
| + for (bool initial_fec_enabled : {false, true}) {
|
| + for (int bandwidth : {0, 10000}) {
|
| + for (float recoverable_packet_loss : {0.0f, 0.5f, 1.0f}) {
|
| + FecControllerRplrBased controller(FecControllerRplrBased::Config(
|
| + initial_fec_enabled, always_on_curve, always_on_curve));
|
| + UpdateNetworkMetrics(&controller, bandwidth, recoverable_packet_loss);
|
| + CheckDecision(&controller, true, recoverable_packet_loss);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
|
| TEST(FecControllerRplrBasedDeathTest, InvalidConfig) {
|
| EXPECT_DEATH(
|
|
|