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/fec_controller_plr_based.h"
12 
13 #include <utility>
14 
15 #include "common_audio/mocks/mock_smoothing_filter.h"
16 #include "test/gtest.h"
17 
18 namespace webrtc {
19 
20 using ::testing::_;
21 using ::testing::NiceMock;
22 using ::testing::Return;
23 
24 namespace {
25 
26 // The test uses the following settings:
27 //
28 // packet-loss ^   |  |
29 //             |  A| C|   FEC
30 //             |    \  \   ON
31 //             | FEC \ D\_______
32 //             | OFF B\_________
33 //             |-----------------> bandwidth
34 //
35 // A : (kDisablingBandwidthLow, kDisablingPacketLossAtLowBw)
36 // B : (kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw)
37 // C : (kEnablingBandwidthLow, kEnablingPacketLossAtLowBw)
38 // D : (kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw)
39 
40 constexpr int kDisablingBandwidthLow = 15000;
41 constexpr float kDisablingPacketLossAtLowBw = 0.08f;
42 constexpr int kDisablingBandwidthHigh = 64000;
43 constexpr float kDisablingPacketLossAtHighBw = 0.01f;
44 constexpr int kEnablingBandwidthLow = 17000;
45 constexpr float kEnablingPacketLossAtLowBw = 0.1f;
46 constexpr int kEnablingBandwidthHigh = 64000;
47 constexpr float kEnablingPacketLossAtHighBw = 0.05f;
48 
49 constexpr float kEpsilon = 1e-5f;
50 
51 struct FecControllerPlrBasedTestStates {
52   std::unique_ptr<FecControllerPlrBased> controller;
53   MockSmoothingFilter* packet_loss_smoother;
54 };
55 
CreateFecControllerPlrBased(bool initial_fec_enabled,const ThresholdCurve & enabling_curve,const ThresholdCurve & disabling_curve)56 FecControllerPlrBasedTestStates CreateFecControllerPlrBased(
57     bool initial_fec_enabled,
58     const ThresholdCurve& enabling_curve,
59     const ThresholdCurve& disabling_curve) {
60   FecControllerPlrBasedTestStates states;
61   std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
62       new NiceMock<MockSmoothingFilter>());
63   states.packet_loss_smoother = mock_smoothing_filter.get();
64   states.controller.reset(new FecControllerPlrBased(
65       FecControllerPlrBased::Config(initial_fec_enabled, enabling_curve,
66                                     disabling_curve, 0),
67       std::move(mock_smoothing_filter)));
68   return states;
69 }
70 
CreateFecControllerPlrBased(bool initial_fec_enabled)71 FecControllerPlrBasedTestStates CreateFecControllerPlrBased(
72     bool initial_fec_enabled) {
73   return CreateFecControllerPlrBased(
74       initial_fec_enabled,
75       ThresholdCurve(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
76                      kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
77       ThresholdCurve(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
78                      kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw));
79 }
80 
UpdateNetworkMetrics(FecControllerPlrBasedTestStates * states,const absl::optional<int> & uplink_bandwidth_bps,const absl::optional<float> & uplink_packet_loss)81 void UpdateNetworkMetrics(FecControllerPlrBasedTestStates* states,
82                           const absl::optional<int>& uplink_bandwidth_bps,
83                           const absl::optional<float>& uplink_packet_loss) {
84   // UpdateNetworkMetrics can accept multiple network metric updates at once.
85   // However, currently, the most used case is to update one metric at a time.
86   // To reflect this fact, we separate the calls.
87   if (uplink_bandwidth_bps) {
88     Controller::NetworkMetrics network_metrics;
89     network_metrics.uplink_bandwidth_bps = uplink_bandwidth_bps;
90     states->controller->UpdateNetworkMetrics(network_metrics);
91   }
92   if (uplink_packet_loss) {
93     Controller::NetworkMetrics network_metrics;
94     network_metrics.uplink_packet_loss_fraction = uplink_packet_loss;
95     EXPECT_CALL(*states->packet_loss_smoother, AddSample(*uplink_packet_loss));
96     states->controller->UpdateNetworkMetrics(network_metrics);
97     // This is called during CheckDecision().
98     EXPECT_CALL(*states->packet_loss_smoother, GetAverage())
99         .WillOnce(Return(*uplink_packet_loss));
100   }
101 }
102 
103 // Checks that the FEC decision and |uplink_packet_loss_fraction| given by
104 // |states->controller->MakeDecision| matches |expected_enable_fec| and
105 // |expected_uplink_packet_loss_fraction|, respectively.
CheckDecision(FecControllerPlrBasedTestStates * states,bool expected_enable_fec,float expected_uplink_packet_loss_fraction)106 void CheckDecision(FecControllerPlrBasedTestStates* states,
107                    bool expected_enable_fec,
108                    float expected_uplink_packet_loss_fraction) {
109   AudioEncoderRuntimeConfig config;
110   states->controller->MakeDecision(&config);
111   EXPECT_EQ(expected_enable_fec, config.enable_fec);
112   EXPECT_EQ(expected_uplink_packet_loss_fraction,
113             config.uplink_packet_loss_fraction);
114 }
115 
116 }  // namespace
117 
TEST(FecControllerPlrBasedTest,OutputInitValueBeforeAnyInputsAreReceived)118 TEST(FecControllerPlrBasedTest, OutputInitValueBeforeAnyInputsAreReceived) {
119   for (bool initial_fec_enabled : {false, true}) {
120     auto states = CreateFecControllerPlrBased(initial_fec_enabled);
121     CheckDecision(&states, initial_fec_enabled, 0);
122   }
123 }
124 
TEST(FecControllerPlrBasedTest,OutputInitValueWhenUplinkBandwidthUnknown)125 TEST(FecControllerPlrBasedTest, OutputInitValueWhenUplinkBandwidthUnknown) {
126   // Regardless of the initial FEC state and the packet-loss rate,
127   // the initial FEC state is maintained as long as the BWE is unknown.
128   for (bool initial_fec_enabled : {false, true}) {
129     for (float packet_loss :
130          {kDisablingPacketLossAtLowBw - kEpsilon, kDisablingPacketLossAtLowBw,
131           kDisablingPacketLossAtLowBw + kEpsilon,
132           kEnablingPacketLossAtLowBw - kEpsilon, kEnablingPacketLossAtLowBw,
133           kEnablingPacketLossAtLowBw + kEpsilon}) {
134       auto states = CreateFecControllerPlrBased(initial_fec_enabled);
135       UpdateNetworkMetrics(&states, absl::nullopt, packet_loss);
136       CheckDecision(&states, initial_fec_enabled, packet_loss);
137     }
138   }
139 }
140 
TEST(FecControllerPlrBasedTest,OutputInitValueWhenUplinkPacketLossFractionUnknown)141 TEST(FecControllerPlrBasedTest,
142      OutputInitValueWhenUplinkPacketLossFractionUnknown) {
143   // Regardless of the initial FEC state and the BWE, the initial FEC state
144   // is maintained as long as the packet-loss rate is unknown.
145   for (bool initial_fec_enabled : {false, true}) {
146     for (int bandwidth : {kDisablingBandwidthLow - 1, kDisablingBandwidthLow,
147                           kDisablingBandwidthLow + 1, kEnablingBandwidthLow - 1,
148                           kEnablingBandwidthLow, kEnablingBandwidthLow + 1}) {
149       auto states = CreateFecControllerPlrBased(initial_fec_enabled);
150       UpdateNetworkMetrics(&states, bandwidth, absl::nullopt);
151       CheckDecision(&states, initial_fec_enabled, 0.0);
152     }
153   }
154 }
155 
TEST(FecControllerPlrBasedTest,EnableFecForHighBandwidth)156 TEST(FecControllerPlrBasedTest, EnableFecForHighBandwidth) {
157   auto states = CreateFecControllerPlrBased(false);
158   UpdateNetworkMetrics(&states, kEnablingBandwidthHigh,
159                        kEnablingPacketLossAtHighBw);
160   CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
161 }
162 
TEST(FecControllerPlrBasedTest,UpdateMultipleNetworkMetricsAtOnce)163 TEST(FecControllerPlrBasedTest, UpdateMultipleNetworkMetricsAtOnce) {
164   // This test is similar to EnableFecForHighBandwidth. But instead of
165   // using ::UpdateNetworkMetrics(...), which calls
166   // FecControllerPlrBased::UpdateNetworkMetrics(...) multiple times, we
167   // we call it only once. This is to verify that
168   // FecControllerPlrBased::UpdateNetworkMetrics(...) can handle multiple
169   // network updates at once. This is, however, not a common use case in current
170   // audio_network_adaptor_impl.cc.
171   auto states = CreateFecControllerPlrBased(false);
172   Controller::NetworkMetrics network_metrics;
173   network_metrics.uplink_bandwidth_bps = kEnablingBandwidthHigh;
174   network_metrics.uplink_packet_loss_fraction = kEnablingPacketLossAtHighBw;
175   EXPECT_CALL(*states.packet_loss_smoother, GetAverage())
176       .WillOnce(Return(kEnablingPacketLossAtHighBw));
177   states.controller->UpdateNetworkMetrics(network_metrics);
178   CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
179 }
180 
TEST(FecControllerPlrBasedTest,MaintainFecOffForHighBandwidth)181 TEST(FecControllerPlrBasedTest, MaintainFecOffForHighBandwidth) {
182   auto states = CreateFecControllerPlrBased(false);
183   constexpr float kPacketLoss = kEnablingPacketLossAtHighBw * 0.99f;
184   UpdateNetworkMetrics(&states, kEnablingBandwidthHigh, kPacketLoss);
185   CheckDecision(&states, false, kPacketLoss);
186 }
187 
TEST(FecControllerPlrBasedTest,EnableFecForMediumBandwidth)188 TEST(FecControllerPlrBasedTest, EnableFecForMediumBandwidth) {
189   auto states = CreateFecControllerPlrBased(false);
190   constexpr float kPacketLoss =
191       (kEnablingPacketLossAtLowBw + kEnablingPacketLossAtHighBw) / 2.0;
192   UpdateNetworkMetrics(&states,
193                        (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2,
194                        kPacketLoss);
195   CheckDecision(&states, true, kPacketLoss);
196 }
197 
TEST(FecControllerPlrBasedTest,MaintainFecOffForMediumBandwidth)198 TEST(FecControllerPlrBasedTest, MaintainFecOffForMediumBandwidth) {
199   auto states = CreateFecControllerPlrBased(false);
200   constexpr float kPacketLoss =
201       kEnablingPacketLossAtLowBw * 0.49f + kEnablingPacketLossAtHighBw * 0.51f;
202   UpdateNetworkMetrics(&states,
203                        (kEnablingBandwidthHigh + kEnablingBandwidthLow) / 2,
204                        kPacketLoss);
205   CheckDecision(&states, false, kPacketLoss);
206 }
207 
TEST(FecControllerPlrBasedTest,EnableFecForLowBandwidth)208 TEST(FecControllerPlrBasedTest, EnableFecForLowBandwidth) {
209   auto states = CreateFecControllerPlrBased(false);
210   UpdateNetworkMetrics(&states, kEnablingBandwidthLow,
211                        kEnablingPacketLossAtLowBw);
212   CheckDecision(&states, true, kEnablingPacketLossAtLowBw);
213 }
214 
TEST(FecControllerPlrBasedTest,MaintainFecOffForLowBandwidth)215 TEST(FecControllerPlrBasedTest, MaintainFecOffForLowBandwidth) {
216   auto states = CreateFecControllerPlrBased(false);
217   constexpr float kPacketLoss = kEnablingPacketLossAtLowBw * 0.99f;
218   UpdateNetworkMetrics(&states, kEnablingBandwidthLow, kPacketLoss);
219   CheckDecision(&states, false, kPacketLoss);
220 }
221 
TEST(FecControllerPlrBasedTest,MaintainFecOffForVeryLowBandwidth)222 TEST(FecControllerPlrBasedTest, MaintainFecOffForVeryLowBandwidth) {
223   auto states = CreateFecControllerPlrBased(false);
224   // Below |kEnablingBandwidthLow|, no packet loss fraction can cause FEC to
225   // turn on.
226   UpdateNetworkMetrics(&states, kEnablingBandwidthLow - 1, 1.0);
227   CheckDecision(&states, false, 1.0);
228 }
229 
TEST(FecControllerPlrBasedTest,DisableFecForHighBandwidth)230 TEST(FecControllerPlrBasedTest, DisableFecForHighBandwidth) {
231   auto states = CreateFecControllerPlrBased(true);
232   constexpr float kPacketLoss = kDisablingPacketLossAtHighBw - kEpsilon;
233   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh, kPacketLoss);
234   CheckDecision(&states, false, kPacketLoss);
235 }
236 
TEST(FecControllerPlrBasedTest,MaintainFecOnForHighBandwidth)237 TEST(FecControllerPlrBasedTest, MaintainFecOnForHighBandwidth) {
238   // Note: Disabling happens when the value is strictly below the threshold.
239   auto states = CreateFecControllerPlrBased(true);
240   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh,
241                        kDisablingPacketLossAtHighBw);
242   CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
243 }
244 
TEST(FecControllerPlrBasedTest,DisableFecOnMediumBandwidth)245 TEST(FecControllerPlrBasedTest, DisableFecOnMediumBandwidth) {
246   auto states = CreateFecControllerPlrBased(true);
247   constexpr float kPacketLoss =
248       (kDisablingPacketLossAtLowBw + kDisablingPacketLossAtHighBw) / 2.0f -
249       kEpsilon;
250   UpdateNetworkMetrics(&states,
251                        (kDisablingBandwidthHigh + kDisablingBandwidthLow) / 2,
252                        kPacketLoss);
253   CheckDecision(&states, false, kPacketLoss);
254 }
255 
TEST(FecControllerPlrBasedTest,MaintainFecOnForMediumBandwidth)256 TEST(FecControllerPlrBasedTest, MaintainFecOnForMediumBandwidth) {
257   auto states = CreateFecControllerPlrBased(true);
258   constexpr float kPacketLoss = kDisablingPacketLossAtLowBw * 0.51f +
259                                 kDisablingPacketLossAtHighBw * 0.49f - kEpsilon;
260   UpdateNetworkMetrics(&states,
261                        (kEnablingBandwidthHigh + kDisablingBandwidthLow) / 2,
262                        kPacketLoss);
263   CheckDecision(&states, true, kPacketLoss);
264 }
265 
TEST(FecControllerPlrBasedTest,DisableFecForLowBandwidth)266 TEST(FecControllerPlrBasedTest, DisableFecForLowBandwidth) {
267   auto states = CreateFecControllerPlrBased(true);
268   constexpr float kPacketLoss = kDisablingPacketLossAtLowBw - kEpsilon;
269   UpdateNetworkMetrics(&states, kDisablingBandwidthLow, kPacketLoss);
270   CheckDecision(&states, false, kPacketLoss);
271 }
272 
TEST(FecControllerPlrBasedTest,DisableFecForVeryLowBandwidth)273 TEST(FecControllerPlrBasedTest, DisableFecForVeryLowBandwidth) {
274   auto states = CreateFecControllerPlrBased(true);
275   // Below |kEnablingBandwidthLow|, any packet loss fraction can cause FEC to
276   // turn off.
277   UpdateNetworkMetrics(&states, kDisablingBandwidthLow - 1, 1.0);
278   CheckDecision(&states, false, 1.0);
279 }
280 
TEST(FecControllerPlrBasedTest,CheckBehaviorOnChangingNetworkMetrics)281 TEST(FecControllerPlrBasedTest, CheckBehaviorOnChangingNetworkMetrics) {
282   // In this test, we let the network metrics to traverse from 1 to 5.
283   // packet-loss ^ 1 |  |
284   //             |   | 2|
285   //             |    \  \ 3
286   //             |     \4 \_______
287   //             |      \_________
288   //             |---------5-------> bandwidth
289 
290   auto states = CreateFecControllerPlrBased(true);
291   UpdateNetworkMetrics(&states, kDisablingBandwidthLow - 1, 1.0);
292   CheckDecision(&states, false, 1.0);
293 
294   UpdateNetworkMetrics(&states, kEnablingBandwidthLow,
295                        kEnablingPacketLossAtLowBw * 0.99f);
296   CheckDecision(&states, false, kEnablingPacketLossAtLowBw * 0.99f);
297 
298   UpdateNetworkMetrics(&states, kEnablingBandwidthHigh,
299                        kEnablingPacketLossAtHighBw);
300   CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
301 
302   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh,
303                        kDisablingPacketLossAtHighBw);
304   CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
305 
306   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh + 1, 0.0);
307   CheckDecision(&states, false, 0.0);
308 }
309 
TEST(FecControllerPlrBasedTest,CheckBehaviorOnSpecialCurves)310 TEST(FecControllerPlrBasedTest, CheckBehaviorOnSpecialCurves) {
311   // We test a special configuration, where the points to define the FEC
312   // enabling/disabling curves are placed like the following, otherwise the test
313   // is the same as CheckBehaviorOnChangingNetworkMetrics.
314   //
315   // packet-loss ^   |  |
316   //             |   | C|
317   //             |   |  |
318   //             |   | D|_______
319   //             |  A|___B______
320   //             |-----------------> bandwidth
321 
322   constexpr int kEnablingBandwidthHigh = kEnablingBandwidthLow;
323   constexpr float kDisablingPacketLossAtLowBw = kDisablingPacketLossAtHighBw;
324   FecControllerPlrBasedTestStates states;
325   std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
326       new NiceMock<MockSmoothingFilter>());
327   states.packet_loss_smoother = mock_smoothing_filter.get();
328   states.controller.reset(new FecControllerPlrBased(
329       FecControllerPlrBased::Config(
330           true,
331           ThresholdCurve(kEnablingBandwidthLow, kEnablingPacketLossAtLowBw,
332                          kEnablingBandwidthHigh, kEnablingPacketLossAtHighBw),
333           ThresholdCurve(kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
334                          kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
335           0),
336       std::move(mock_smoothing_filter)));
337 
338   UpdateNetworkMetrics(&states, kDisablingBandwidthLow - 1, 1.0);
339   CheckDecision(&states, false, 1.0);
340 
341   UpdateNetworkMetrics(&states, kEnablingBandwidthLow,
342                        kEnablingPacketLossAtHighBw * 0.99f);
343   CheckDecision(&states, false, kEnablingPacketLossAtHighBw * 0.99f);
344 
345   UpdateNetworkMetrics(&states, kEnablingBandwidthHigh,
346                        kEnablingPacketLossAtHighBw);
347   CheckDecision(&states, true, kEnablingPacketLossAtHighBw);
348 
349   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh,
350                        kDisablingPacketLossAtHighBw);
351   CheckDecision(&states, true, kDisablingPacketLossAtHighBw);
352 
353   UpdateNetworkMetrics(&states, kDisablingBandwidthHigh + 1, 0.0);
354   CheckDecision(&states, false, 0.0);
355 }
356 
TEST(FecControllerPlrBasedTest,SingleThresholdCurveForEnablingAndDisabling)357 TEST(FecControllerPlrBasedTest, SingleThresholdCurveForEnablingAndDisabling) {
358   // Note: To avoid numerical errors, keep kPacketLossAtLowBw and
359   // kPacketLossAthighBw as (negative) integer powers of 2.
360   // This is mostly relevant for the O3 case.
361   constexpr int kBandwidthLow = 10000;
362   constexpr float kPacketLossAtLowBw = 0.25f;
363   constexpr int kBandwidthHigh = 20000;
364   constexpr float kPacketLossAtHighBw = 0.125f;
365   auto curve = ThresholdCurve(kBandwidthLow, kPacketLossAtLowBw, kBandwidthHigh,
366                               kPacketLossAtHighBw);
367 
368   // B* stands for "below-curve", O* for "on-curve", and A* for "above-curve".
369   //
370   //                                            //
371   // packet-loss ^                              //
372   //             |    |                         //
373   //             | B1 O1                        //
374   //             |    |                         //
375   //             |    O2                        //
376   //             |     \ A1                     //
377   //             |      \                       //
378   //             |       O3   A2                //
379   //             |     B2 \                     //
380   //             |         \                    //
381   //             |          O4--O5----          //
382   //             |                              //
383   //             |            B3                //
384   //             |-----------------> bandwidth  //
385 
386   struct NetworkState {
387     int bandwidth;
388     float packet_loss;
389   };
390 
391   std::vector<NetworkState> below{
392       {kBandwidthLow - 1, kPacketLossAtLowBw + 0.1f},  // B1
393       {(kBandwidthLow + kBandwidthHigh) / 2,
394        (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2 - kEpsilon},  // B2
395       {kBandwidthHigh + 1, kPacketLossAtHighBw - kEpsilon}          // B3
396   };
397 
398   std::vector<NetworkState> on{
399       {kBandwidthLow, kPacketLossAtLowBw + 0.1f},  // O1
400       {kBandwidthLow, kPacketLossAtLowBw},         // O2
401       {(kBandwidthLow + kBandwidthHigh) / 2,
402        (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2},  // O3
403       {kBandwidthHigh, kPacketLossAtHighBw},             // O4
404       {kBandwidthHigh + 1, kPacketLossAtHighBw},         // O5
405   };
406 
407   std::vector<NetworkState> above{
408       {(kBandwidthLow + kBandwidthHigh) / 2,
409        (kPacketLossAtLowBw + kPacketLossAtHighBw) / 2 + kEpsilon},  // A1
410       {kBandwidthHigh + 1, kPacketLossAtHighBw + kEpsilon},         // A2
411   };
412 
413   // Test that FEC is turned off whenever we're below the curve, independent
414   // of the starting FEC state.
415   for (NetworkState net_state : below) {
416     for (bool initial_fec_enabled : {false, true}) {
417       auto states =
418           CreateFecControllerPlrBased(initial_fec_enabled, curve, curve);
419       UpdateNetworkMetrics(&states, net_state.bandwidth, net_state.packet_loss);
420       CheckDecision(&states, false, net_state.packet_loss);
421     }
422   }
423 
424   // Test that FEC is turned on whenever we're on the curve or above it,
425   // independent of the starting FEC state.
426   for (const std::vector<NetworkState>& states_list : {on, above}) {
427     for (NetworkState net_state : states_list) {
428       for (bool initial_fec_enabled : {false, true}) {
429         auto states =
430             CreateFecControllerPlrBased(initial_fec_enabled, curve, curve);
431         UpdateNetworkMetrics(&states, net_state.bandwidth,
432                              net_state.packet_loss);
433         CheckDecision(&states, true, net_state.packet_loss);
434       }
435     }
436   }
437 }
438 
TEST(FecControllerPlrBasedTest,FecAlwaysOff)439 TEST(FecControllerPlrBasedTest, FecAlwaysOff) {
440   ThresholdCurve always_off_curve(0, 1.0f + kEpsilon, 0, 1.0f + kEpsilon);
441   for (bool initial_fec_enabled : {false, true}) {
442     for (int bandwidth : {0, 10000}) {
443       for (float packet_loss : {0.0f, 0.5f, 1.0f}) {
444         auto states = CreateFecControllerPlrBased(
445             initial_fec_enabled, always_off_curve, always_off_curve);
446         UpdateNetworkMetrics(&states, bandwidth, packet_loss);
447         CheckDecision(&states, false, packet_loss);
448       }
449     }
450   }
451 }
452 
TEST(FecControllerPlrBasedTest,FecAlwaysOn)453 TEST(FecControllerPlrBasedTest, FecAlwaysOn) {
454   ThresholdCurve always_on_curve(0, 0.0f, 0, 0.0f);
455   for (bool initial_fec_enabled : {false, true}) {
456     for (int bandwidth : {0, 10000}) {
457       for (float packet_loss : {0.0f, 0.5f, 1.0f}) {
458         auto states = CreateFecControllerPlrBased(
459             initial_fec_enabled, always_on_curve, always_on_curve);
460         UpdateNetworkMetrics(&states, bandwidth, packet_loss);
461         CheckDecision(&states, true, packet_loss);
462       }
463     }
464   }
465 }
466 
467 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(FecControllerPlrBasedDeathTest,InvalidConfig)468 TEST(FecControllerPlrBasedDeathTest, InvalidConfig) {
469   FecControllerPlrBasedTestStates states;
470   std::unique_ptr<MockSmoothingFilter> mock_smoothing_filter(
471       new NiceMock<MockSmoothingFilter>());
472   states.packet_loss_smoother = mock_smoothing_filter.get();
473   EXPECT_DEATH(
474       states.controller.reset(new FecControllerPlrBased(
475           FecControllerPlrBased::Config(
476               true,
477               ThresholdCurve(kDisablingBandwidthLow - 1,
478                              kEnablingPacketLossAtLowBw, kEnablingBandwidthHigh,
479                              kEnablingPacketLossAtHighBw),
480               ThresholdCurve(
481                   kDisablingBandwidthLow, kDisablingPacketLossAtLowBw,
482                   kDisablingBandwidthHigh, kDisablingPacketLossAtHighBw),
483               0),
484           std::move(mock_smoothing_filter))),
485       "Check failed");
486 }
487 #endif
488 
489 }  // namespace webrtc
490