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