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