Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1340)

Unified Diff: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc

Issue 2906663002: FecControler disables FEC when *below* threshold (Closed)
Patch Set: . Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
index fceae874f3dffc242d677778f98cc0e3c478fbda..0e23cb01f239e2341df888f65324e59f3a714b6c 100644
--- a/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
@@ -45,29 +45,38 @@ constexpr float kEnablingPacketLossAtLowBw = 0.1f;
constexpr int kEnablingBandwidthHigh = 64000;
constexpr float kEnablingPacketLossAtHighBw = 0.05f;
+constexpr float kEpsilon = 1e-5f;
+
struct FecControllerPlrBasedTestStates {
std::unique_ptr<FecControllerPlrBased> controller;
MockSmoothingFilter* packet_loss_smoother;
};
FecControllerPlrBasedTestStates CreateFecControllerPlrBased(
- bool initial_fec_enabled) {
+ bool initial_fec_enabled,
+ const ThresholdCurve& enabling_curve,
+ const ThresholdCurve& disabling_curve) {
FecControllerPlrBasedTestStates states;
std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
new NiceMock<MockSmoothingFilter>());
states.packet_loss_smoother = mock_smoothing_filter.get();
states.controller.reset(new FecControllerPlrBased(
- FecControllerPlrBased::Config(
- initial_fec_enabled,
- ThresholdCurve(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
- kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
- ThresholdCurve(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
- kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
- 0),
+ FecControllerPlrBased::Config(initial_fec_enabled, enabling_curve,
+ disabling_curve, 0),
std::move(mock_smoothing_filter)));
return states;
}
+FecControllerPlrBasedTestStates CreateFecControllerPlrBased(
+ bool initial_fec_enabled) {
+ return CreateFecControllerPlrBased(
+ initial_fec_enabled,
+ ThresholdCurve(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
+ kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
+ ThresholdCurve(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
+ kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw));
+}
+
void UpdateNetworkMetrics(FecControllerPlrBasedTestStates* states,
const rtc::Optional<int>& uplink_bandwidth_bps,
const rtc::Optional<float>& uplink_packet_loss) {
@@ -90,6 +99,15 @@ void UpdateNetworkMetrics(FecControllerPlrBasedTestStates* states,
}
}
+// TODO(eladalon): In a separate CL (to make reviewers' lives easier), use
+// this where applicable.
+void UpdateNetworkMetrics(FecControllerPlrBasedTestStates* states,
+ int uplink_bandwidth_bps,
+ float uplink_packet_loss) {
+ UpdateNetworkMetrics(states, rtc::Optional<int>(uplink_bandwidth_bps),
+ rtc::Optional<float>(uplink_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.
@@ -105,25 +123,44 @@ void CheckDecision(FecControllerPlrBasedTestStates* states,
} // namespace
+TEST(FecControllerPlrBasedTest, OutputInitValueBeforeAnyInputsAreReceived) {
+ for (bool initial_fec_enabled : {false, true}) {
+ auto states = CreateFecControllerPlrBased(initial_fec_enabled);
+ CheckDecision(&states, initial_fec_enabled, 0);
+ }
+}
+
TEST(FecControllerPlrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) {
- constexpr bool kInitialFecEnabled = true;
- auto states = CreateFecControllerPlrBased(kInitialFecEnabled);
- // Let uplink packet loss fraction be so low that would cause FEC to turn off
- // if uplink bandwidth was known.
- UpdateNetworkMetrics(&states, rtc::Optional<int>(),
- rtc::Optional<float>(kDisablingPacketLossAtHighBw));
- CheckDecision(&states, kInitialFecEnabled, kDisablingPacketLossAtHighBw);
+ // Regardless of the initial FEC state and the 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 packet_loss :
+ {kDisablingPacketLossAtLowBw - kEpsilon, kDisablingPacketLossAtLowBw,
+ kDisablingPacketLossAtLowBw + kEpsilon,
+ kEnablingPacketLossAtLowBw - kEpsilon, kEnablingPacketLossAtLowBw,
+ kEnablingPacketLossAtLowBw + kEpsilon}) {
+ auto states = CreateFecControllerPlrBased(initial_fec_enabled);
+ UpdateNetworkMetrics(&states, rtc::Optional<int>(),
+ rtc::Optional<float>(packet_loss));
+ CheckDecision(&states, initial_fec_enabled, packet_loss);
+ }
+ }
}
TEST(FecControllerPlrBasedTest,
OutputInitValueWhenUplinkPacketLossFractionUnknown) {
- constexpr bool kInitialFecEnabled = true;
- auto states = CreateFecControllerPlrBased(kInitialFecEnabled);
- // Let uplink bandwidth be so low that would cause FEC to turn off if uplink
- // bandwidth packet loss fraction was known.
- UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow - 1),
- rtc::Optional<float>());
- CheckDecision(&states, kInitialFecEnabled, 0.0);
+ // Regardless of the initial FEC state and the BWE, the initial FEC state
+ // is maintained as long as the packet-loss rate is unknown.
+ for (bool initial_fec_enabled : {false, true}) {
+ for (int bandwidth : {kDisablingBandwidthLow - 1, kDisablingBandwidthLow,
+ kDisablingBandwidthLow + 1, kEnablingBandwidthLow - 1,
+ kEnablingBandwidthLow, kEnablingBandwidthLow + 1}) {
+ auto states = CreateFecControllerPlrBased(initial_fec_enabled);
+ UpdateNetworkMetrics(&states, rtc::Optional<int>(bandwidth),
+ rtc::Optional<float>());
+ CheckDecision(&states, initial_fec_enabled, 0.0);
+ }
+ }
}
TEST(FecControllerPlrBasedTest, EnableFecForHighBandwidth) {
@@ -209,23 +246,25 @@ TEST(FecControllerPlrBasedTest, MaintainFecOffForVeryLowBandwidth) {
TEST(FecControllerPlrBasedTest, DisableFecForHighBandwidth) {
auto states = CreateFecControllerPlrBased(true);
+ constexpr float kPacketLoss = kDisablingPacketLossAtHighBw - kEpsilon;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
- rtc::Optional<float>(kDisablingPacketLossAtHighBw));
- CheckDecision(&states, false, kDisablingPacketLossAtHighBw);
+ rtc::Optional<float>(kPacketLoss));
+ CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerPlrBasedTest, MaintainFecOnForHighBandwidth) {
+ // Note: Disabling happens when the value is strictly below the threshold.
auto states = CreateFecControllerPlrBased(true);
- constexpr float kPacketLoss = kDisablingPacketLossAtHighBw * 1.01f;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
- rtc::Optional<float>(kPacketLoss));
- CheckDecision(&states, true, kPacketLoss);
+ rtc::Optional<float>(kDisablingPacketLossAtHighBw));
+ CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
}
TEST(FecControllerPlrBasedTest, DisableFecOnMediumBandwidth) {
auto states = CreateFecControllerPlrBased(true);
constexpr float kPacketLoss =
- (kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f;
+ (kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f -
+ kEpsilon;
UpdateNetworkMetrics(
&states,
rtc::Optional<int>((kDisablingBandwidthHigh + kDisablingBandwidthLow) /
@@ -237,7 +276,7 @@ TEST(FecControllerPlrBasedTest, DisableFecOnMediumBandwidth) {
TEST(FecControllerPlrBasedTest, MaintainFecOnForMediumBandwidth) {
auto states = CreateFecControllerPlrBased(true);
constexpr float kPacketLoss = kDisablingPacketLossAtLowBw * 0.51f +
- kDisablingPacketLossAtHighBw * 0.49f;
+ kDisablingPacketLossAtHighBw * 0.49f - kEpsilon;
UpdateNetworkMetrics(
&states,
rtc::Optional<int>((kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2),
@@ -247,9 +286,10 @@ TEST(FecControllerPlrBasedTest, MaintainFecOnForMediumBandwidth) {
TEST(FecControllerPlrBasedTest, DisableFecForLowBandwidth) {
auto states = CreateFecControllerPlrBased(true);
+ constexpr float kPacketLoss = kDisablingPacketLossAtLowBw - kEpsilon;
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthLow),
- rtc::Optional<float>(kDisablingPacketLossAtLowBw));
- CheckDecision(&states, false, kDisablingPacketLossAtLowBw);
+ rtc::Optional<float>(kPacketLoss));
+ CheckDecision(&states, false, kPacketLoss);
}
TEST(FecControllerPlrBasedTest, DisableFecForVeryLowBandwidth) {
@@ -284,10 +324,9 @@ TEST(FecControllerPlrBasedTest, CheckBehaviorOnChangingNetworkMetrics) {
rtc::Optional<float>(kEnablingPacketLossAtHighBw));
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
- UpdateNetworkMetrics(
- &states, rtc::Optional<int>(kDisablingBandwidthHigh),
- rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f));
- CheckDecision(&states, true, kDisablingPacketLossAtHighBw * 1.01f);
+ UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
+ rtc::Optional<float>(kDisablingPacketLossAtHighBw));
+ CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0));
@@ -335,16 +374,125 @@ TEST(FecControllerPlrBasedTest, CheckBehaviorOnSpecialCurves) {
rtc::Optional<float>(kEnablingPacketLossAtHighBw));
CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
- UpdateNetworkMetrics(
- &states, rtc::Optional<int>(kDisablingBandwidthHigh),
- rtc::Optional<float>(kDisablingPacketLossAtHighBw * 1.01f));
- CheckDecision(&states, true, kDisablingPacketLossAtHighBw * 1.01f);
+ UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh),
+ rtc::Optional<float>(kDisablingPacketLossAtHighBw));
+ CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
UpdateNetworkMetrics(&states, rtc::Optional<int>(kDisablingBandwidthHigh + 1),
rtc::Optional<float>(0.0));
CheckDecision(&states, false, 0.0);
}
+TEST(FecControllerPlrBasedTest, SingleThresholdCurveForEnablingAndDisabling) {
+ // Note: To avoid numerical errors, keep kPacketLossAtLowBw and
+ // kPacketLossAthighBw as (negative) integer powers of 2.
+ // This is mostly relevant for the O3 case.
+ constexpr int kBandwidthLow = 10000;
+ constexpr float kPacketLossAtLowBw = 0.25f;
+ constexpr int kBandwidthHigh = 20000;
+ constexpr float kPacketLossAtHighBw = 0.125f;
+ auto curve = ThresholdCurve(kBandwidthLow, kPacketLossAtLowBw, kBandwidthHigh,
+ kPacketLossAtHighBw);
+
+ // B* stands for "below-curve", O* for "on-curve", and A* for "above-curve".
+ //
+ // //
+ // packet-loss ^ //
+ // | | //
+ // | B1 O1 //
+ // | | //
+ // | O2 //
+ // | \ A1 //
+ // | \ //
+ // | O3 A2 //
+ // | B2 \ //
+ // | \ //
+ // | O4--O5---- //
+ // | //
+ // | B3 //
+ // |-----------------> bandwidth //
+
+ struct NetworkState {
+ int bandwidth;
+ float packet_loss;
+ };
+
+ std::vector<NetworkState> below{
+ {kBandwidthLow - 1, kPacketLossAtLowBw + 0.1f}, // B1
+ {(kBandwidthLow + kBandwidthHigh) / 2,
+ (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2 - kEpsilon}, // B2
+ {kBandwidthHigh + 1, kPacketLossAtHighBw - kEpsilon} // B3
+ };
+
+ std::vector<NetworkState> on{
+ {kBandwidthLow, kPacketLossAtLowBw + 0.1f}, // O1
+ {kBandwidthLow, kPacketLossAtLowBw}, // O2
+ {(kBandwidthLow + kBandwidthHigh) / 2,
+ (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2}, // O3
+ {kBandwidthHigh, kPacketLossAtHighBw}, // O4
+ {kBandwidthHigh + 1, kPacketLossAtHighBw}, // O5
+ };
+
+ std::vector<NetworkState> above{
+ {(kBandwidthLow + kBandwidthHigh) / 2,
+ (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2 + kEpsilon}, // A1
+ {kBandwidthHigh + 1, kPacketLossAtHighBw + 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}) {
+ auto states =
+ CreateFecControllerPlrBased(initial_fec_enabled, curve, curve);
+ UpdateNetworkMetrics(&states, net_state.bandwidth, net_state.packet_loss);
+ CheckDecision(&states, false, net_state.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}) {
+ auto states =
+ CreateFecControllerPlrBased(initial_fec_enabled, curve, curve);
+ UpdateNetworkMetrics(&states, net_state.bandwidth,
+ net_state.packet_loss);
+ CheckDecision(&states, true, net_state.packet_loss);
+ }
+ }
+ }
+}
+
+TEST(FecControllerPlrBasedTest, 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 packet_loss : {0.0f, 0.5f, 1.0f}) {
+ auto states = CreateFecControllerPlrBased(
+ initial_fec_enabled, always_off_curve, always_off_curve);
+ UpdateNetworkMetrics(&states, bandwidth, packet_loss);
+ CheckDecision(&states, false, packet_loss);
+ }
+ }
+ }
+}
+
+TEST(FecControllerPlrBasedTest, 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 packet_loss : {0.0f, 0.5f, 1.0f}) {
+ auto states = CreateFecControllerPlrBased(
+ initial_fec_enabled, always_on_curve, always_on_curve);
+ UpdateNetworkMetrics(&states, bandwidth, packet_loss);
+ CheckDecision(&states, true, packet_loss);
+ }
+ }
+ }
+}
+
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(FecControllerPlrBasedDeathTest, InvalidConfig) {
FecControllerPlrBasedTestStates states;

Powered by Google App Engine
This is Rietveld 408576698