1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/platform/audio/push_pull_fifo.h"
6 
7 #include <memory>
8 #include <vector>
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/blink/public/platform/platform.h"
11 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
12 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
13 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
14 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
15 #include "third_party/blink/renderer/platform/wtf/functional.h"
16 
17 namespace blink {
18 
19 namespace {
20 
21 // Check the basic contract of FIFO. This test only covers the single thread
22 // scenario.
TEST(PushPullFIFOBasicTest,BasicTests)23 TEST(PushPullFIFOBasicTest, BasicTests) {
24   // This suppresses the multi-thread warning for GTest. Potently it increases
25   // the test execution time, but this specific test is very short and simple.
26   testing::FLAGS_gtest_death_test_style = "threadsafe";
27 
28   // FIFO length exceeding the maximum length allowed will cause crash.
29   // i.e.) fifo_length_ <= kMaxFIFOLength
30   EXPECT_DEATH(new PushPullFIFO(2, PushPullFIFO::kMaxFIFOLength + 1), "");
31 
32   std::unique_ptr<PushPullFIFO> test_fifo =
33       std::make_unique<PushPullFIFO>(2, 1024);
34 
35   // The input bus length must be |audio_utilities::kRenderQuantumFrames|.
36   // i.e.) input_bus->length() == kRenderQuantumFrames
37   scoped_refptr<AudioBus> input_bus_129_frames =
38       AudioBus::Create(2, audio_utilities::kRenderQuantumFrames + 1);
39   EXPECT_DEATH(test_fifo->Push(input_bus_129_frames.get()), "");
40   scoped_refptr<AudioBus> input_bus_127_frames =
41       AudioBus::Create(2, audio_utilities::kRenderQuantumFrames - 1);
42   EXPECT_DEATH(test_fifo->Push(input_bus_127_frames.get()), "");
43 
44   // Pull request frames cannot exceed the length of output bus.
45   // i.e.) frames_requested <= output_bus->length()
46   scoped_refptr<AudioBus> output_bus_512_frames = AudioBus::Create(2, 512);
47   EXPECT_DEATH(test_fifo->Pull(output_bus_512_frames.get(), 513), "");
48 
49   // Pull request frames cannot exceed the length of FIFO.
50   // i.e.) frames_requested <= fifo_length_
51   scoped_refptr<AudioBus> output_bus_1025_frames = AudioBus::Create(2, 1025);
52   EXPECT_DEATH(test_fifo->Pull(output_bus_1025_frames.get(), 1025), "");
53 }
54 
55 // Fills each AudioChannel in an AudioBus with a series of linearly increasing
56 // values starting from |starting_value| and incrementing by 1. Then return
57 // value will be |starting_value| + |bus_length|.
FillBusWithLinearRamp(AudioBus * target_bus,size_t starting_value)58 size_t FillBusWithLinearRamp(AudioBus* target_bus, size_t starting_value) {
59   for (unsigned c = 0; c < target_bus->NumberOfChannels(); ++c) {
60     float* bus_channel = target_bus->Channel(c)->MutableData();
61     for (size_t i = 0; i < target_bus->Channel(c)->length(); ++i) {
62       bus_channel[i] = static_cast<float>(starting_value + i);
63     }
64   }
65   return starting_value + target_bus->length();
66 }
67 
68 // Inspect the content of AudioBus with a given set of index and value across
69 // channels.
VerifyBusValueAtIndex(AudioBus * target_bus,int index,float expected_value)70 bool VerifyBusValueAtIndex(AudioBus* target_bus,
71                            int index,
72                            float expected_value) {
73   for (unsigned c = 0; c < target_bus->NumberOfChannels(); ++c) {
74     float* bus_channel = target_bus->Channel(c)->MutableData();
75     if (bus_channel[index] != expected_value) {
76       LOG(ERROR) << ">> [FAIL] expected " << expected_value << " at index "
77                  << index << " but got " << bus_channel[index] << ".";
78       return false;
79     }
80   }
81   return true;
82 }
83 
84 struct FIFOAction {
85   // The type of action; "PUSH" or "PULL".
86   const char* action;
87   // Number of frames for the operation.
88   const size_t number_of_frames;
89 };
90 
91 struct AudioBusSample {
92   // The frame index of a sample in the bus.
93   const size_t index;
94   // The value at the |index| above.
95   const float value;
96 };
97 
98 struct FIFOTestSetup {
99   // Length of FIFO to be created for test case.
100   const size_t fifo_length;
101   // Channel count of FIFO to be created for test case.
102   const unsigned number_of_channels;
103   // A list of |FIFOAction| entries to be performed in test case.
104   const std::vector<FIFOAction> fifo_actions;
105 };
106 
107 struct FIFOTestExpectedState {
108   // Expected read index in FIFO.
109   const size_t index_read;
110   // Expected write index in FIFO.
111   const size_t index_write;
112   // Expected overflow count in FIFO.
113   const unsigned overflow_count;
114   // Expected underflow count in FIFO.
115   const unsigned underflow_count;
116   // A list of expected |AudioBusSample| entries for the FIFO bus.
117   const std::vector<AudioBusSample> fifo_samples;
118   // A list of expected |AudioBusSample| entries for the output bus.
119   const std::vector<AudioBusSample> output_samples;
120 };
121 
122 // The data structure for the parameterized test cases.
123 struct FIFOTestParam {
124   FIFOTestSetup setup;
125   FIFOTestExpectedState expected_state;
126 };
127 
operator <<(std::ostream & out,const FIFOTestParam & param)128 std::ostream& operator<<(std::ostream& out, const FIFOTestParam& param) {
129   out << "fifoLength=" << param.setup.fifo_length
130       << " numberOfChannels=" << param.setup.number_of_channels;
131   return out;
132 }
133 
134 class PushPullFIFOFeatureTest : public testing::TestWithParam<FIFOTestParam> {};
135 
TEST_P(PushPullFIFOFeatureTest,FeatureTests)136 TEST_P(PushPullFIFOFeatureTest, FeatureTests) {
137   const FIFOTestSetup setup = GetParam().setup;
138   const FIFOTestExpectedState expected_state = GetParam().expected_state;
139 
140   // Create a FIFO with a specified configuration.
141   std::unique_ptr<PushPullFIFO> fifo = std::make_unique<PushPullFIFO>(
142       setup.number_of_channels, setup.fifo_length);
143 
144   scoped_refptr<AudioBus> output_bus;
145 
146   // Iterate all the scheduled push/pull actions.
147   size_t frame_counter = 0;
148   for (const auto& action : setup.fifo_actions) {
149     if (strcmp(action.action, "PUSH") == 0) {
150       scoped_refptr<AudioBus> input_bus =
151           AudioBus::Create(setup.number_of_channels, action.number_of_frames);
152       frame_counter = FillBusWithLinearRamp(input_bus.get(), frame_counter);
153       fifo->Push(input_bus.get());
154       LOG(INFO) << "PUSH " << action.number_of_frames
155                 << " frames (frameCounter=" << frame_counter << ")";
156     } else {
157       output_bus =
158           AudioBus::Create(setup.number_of_channels, action.number_of_frames);
159       fifo->Pull(output_bus.get(), action.number_of_frames);
160       LOG(INFO) << "PULL " << action.number_of_frames << " frames";
161     }
162   }
163 
164   // Get FIFO config data.
165   const PushPullFIFOStateForTest actual_state = fifo->GetStateForTest();
166 
167   // Verify the read/write indexes.
168   EXPECT_EQ(expected_state.index_read, actual_state.index_read);
169   EXPECT_EQ(expected_state.index_write, actual_state.index_write);
170   EXPECT_EQ(expected_state.overflow_count, actual_state.overflow_count);
171   EXPECT_EQ(expected_state.underflow_count, actual_state.underflow_count);
172 
173   // Verify in-FIFO samples.
174   for (const auto& sample : expected_state.fifo_samples) {
175     EXPECT_TRUE(VerifyBusValueAtIndex(fifo->GetFIFOBusForTest(),
176                                       sample.index, sample.value));
177   }
178 
179   // Verify samples from the most recent output bus.
180   for (const auto& sample : expected_state.output_samples) {
181     EXPECT_TRUE(
182         VerifyBusValueAtIndex(output_bus.get(), sample.index, sample.value));
183   }
184 }
185 
186 FIFOTestParam g_feature_test_params[] = {
187     // Test cases 0 ~ 3: Regular operation on various channel configuration.
188     //  - Mono, Stereo, Quad, 5.1.
189     //  - FIFO length and pull size are RQ-aligned.
190     {{512, 1, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
191      {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
192 
193     {{512, 2, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
194      {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
195 
196     {{512, 4, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
197      {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
198 
199     {{512, 6, {{"PUSH", 128}, {"PUSH", 128}, {"PULL", 256}}},
200      {256, 256, 0, 0, {{0, 0}}, {{0, 0}, {255, 255}}}},
201 
202     // Test case 4: Pull size less than or equal to 128.
203     {{128, 2, {{"PUSH", 128}, {"PULL", 128}, {"PUSH", 128}, {"PULL", 64}}},
204      {64, 0, 0, 0, {{64, 192}, {0, 128}}, {{0, 128}, {63, 191}}}},
205 
206     // Test case 5: Unusual FIFO and Pull length.
207     //  - FIFO and pull length that are not aligned to render quantum.
208     //  - Check if the indexes are wrapping around correctly.
209     //  - Check if the output bus starts and ends with correct values.
210     {{997,
211       1,
212       {
213           {"PUSH", 128},
214           {"PUSH", 128},
215           {"PUSH", 128},
216           {"PUSH", 128},
217           {"PULL", 449},
218           {"PUSH", 128},
219           {"PUSH", 128},
220           {"PUSH", 128},
221           {"PUSH", 128},
222           {"PULL", 449},
223       }},
224      // - expectedIndexRead = 898, expectedIndexWrite = 27
225      // - overflowCount = 0, underflowCount = 0
226      // - FIFO samples (index, expectedValue) = (898, 898), (27, 27)
227      // - Output bus samples (index, expectedValue) = (0, 499), (448, 897)
228      {898, 27, 0, 0, {{898, 898}, {27, 27}}, {{0, 449}, {448, 897}}}},
229 
230     // Test case 6: Overflow
231     //  - Check overflow counter.
232     //  - After the overflow occurs, the read index must be moved to the write
233     //    index. Thus pulled frames must not contain overwritten data.
234     {{512,
235       3,
236       {
237           {"PUSH", 128},
238           {"PUSH", 128},
239           {"PUSH", 128},
240           {"PUSH", 128},
241           {"PUSH", 128},
242           {"PULL", 256},
243       }},
244      // - expectedIndexRead = 384, expectedIndexWrite = 128
245      // - overflowCount = 1, underflowCount = 0
246      // - FIFO samples (index, expectedValue) = (384, 384), (128, 128)
247      // - Output bus samples (index, expectedValue) = (0, 128), (255, 383)
248      {384, 128, 1, 0, {{384, 384}, {128, 128}}, {{0, 128}, {255, 383}}}},
249 
250     // Test case 7: Overflow in unusual FIFO and pull length.
251     //  - Check overflow counter.
252     //  - After the overflow occurs, the read index must be moved to the write
253     //    index. Thus pulled frames must not contain overwritten data.
254     {{577,
255       5,
256       {
257           {"PUSH", 128},
258           {"PUSH", 128},
259           {"PUSH", 128},
260           {"PUSH", 128},
261           {"PUSH", 128},
262           {"PULL", 227},
263       }},
264      // - expectedIndexRead = 290, expectedIndexWrite = 63
265      // - overflowCount = 1, underflowCount = 0
266      // - FIFO samples (index, expectedValue) = (63, 63), (290, 290)
267      // - Output bus samples (index, expectedValue) = (0, 63), (226, 289)
268      {290, 63, 1, 0, {{63, 63}, {290, 290}}, {{0, 63}, {226, 289}}}},
269 
270     // Test case 8: Underflow
271     //  - Check underflow counter.
272     //  - After the underflow occurs, the write index must be moved to the read
273     //    index. Frames pulled after FIFO underflows must be zeroed.
274     {{512,
275       7,
276       {
277           {"PUSH", 128},
278           {"PUSH", 128},
279           {"PUSH", 128},
280           {"PULL", 384},
281           {"PUSH", 128},
282           {"PUSH", 128},
283           {"PULL", 384},
284       }},
285      // - expectedIndexRead = 128, expectedIndexWrite = 128
286      // - overflowCount = 0, underflowCount = 1
287      // - FIFO samples (index, expectedValue) = (128, 128)
288      // - Output bus samples (index, expectedValue) = (0, 384), (255, 639)
289      //                                               (256, 0), (383, 0)
290      {128,
291       128,
292       0,
293       1,
294       {{128, 128}},
295       {{0, 384}, {255, 639}, {256, 0}, {383, 0}}}},
296 
297     // Test case 9: Underflow in unusual FIFO and pull length.
298     //  - Check underflow counter.
299     //  - After the underflow occurs, the write index must be moved to the read
300     //    index. Frames pulled after FIFO underflows must be zeroed.
301     {{523,
302       11,
303       {
304           {"PUSH", 128},
305           {"PUSH", 128},
306           {"PUSH", 128},
307           {"PULL", 383},
308           {"PUSH", 128},
309           {"PUSH", 128},
310           {"PULL", 383},
311       }},
312      // - expectedIndexRead = 117, expectedIndexWrite = 117
313      // - overflowCount = 0, underflowCount = 1
314      // - FIFO samples (index, expectedValue) = (117, 117)
315      // - Output bus samples (index, expectedValue) = (0, 383), (256, 639)
316      //                                               (257, 0), (382, 0)
317      {117,
318       117,
319       0,
320       1,
321       {{117, 117}},
322       {{0, 383}, {256, 639}, {257, 0}, {382, 0}}}},
323 
324     // Test case 10: Multiple pull from an empty FIFO.
325     //  - Check underflow counter.
326     //  - After the underflow occurs, the write index must be moved to the read
327     //    index. Frames pulled after FIFO underflows must be zeroed.
328     {{1024,
329       11,
330       {
331           {"PUSH", 128},
332           {"PUSH", 128},
333           {"PULL", 440},
334           {"PULL", 440},
335           {"PULL", 440},
336           {"PULL", 440},
337           {"PULL", 440},
338       }},
339      // - expectedIndexRead = 117, expectedIndexWrite = 117
340      // - overflowCount = 0, underflowCount = 1
341      // - FIFO samples (index, expectedValue) = (117, 117)
342      // - Output bus samples (index, expectedValue) = (0, 383), (256, 639)
343      //                                               (257, 0), (382, 0)
344      {256, 256, 0, 5, {{256, 0}}, {{0, 0}, {439, 0}}}},
345 
346     // Test case 11: Multiple pull from an empty FIFO. (zero push)
347     {{1024,
348       11,
349       {
350           {"PULL", 144},
351           {"PULL", 144},
352           {"PULL", 144},
353           {"PULL", 144},
354       }},
355      // - expectedIndexRead = 0, expectedIndexWrite = 0
356      // - overflowCount = 0, underflowCount = 4
357      // - FIFO samples (index, expectedValue) = (0, 0), (1023, 0)
358      // - Output bus samples (index, expectedValue) = (0, 0), (143, 0)
359      {0, 0, 0, 4, {{0, 0}, {1023, 0}}, {{0, 0}, {143, 0}}}}};
360 
361 INSTANTIATE_TEST_SUITE_P(PushPullFIFOFeatureTest,
362                          PushPullFIFOFeatureTest,
363                          testing::ValuesIn(g_feature_test_params));
364 
365 }  // namespace
366 
367 }  // namespace blink
368