| Index: media/base/audio_fifo_unittest.cc
|
| diff --git a/media/base/audio_fifo_unittest.cc b/media/base/audio_fifo_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5b183009de0232bbc66df2662fa05e5de1161303
|
| --- /dev/null
|
| +++ b/media/base/audio_fifo_unittest.cc
|
| @@ -0,0 +1,196 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <limits>
|
| +
|
| +#include "media/base/audio_bus.h"
|
| +#include "media/base/audio_fifo.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace media {
|
| +
|
| +class AudioFifoTest : public testing::Test {
|
| + public:
|
| + AudioFifoTest() {}
|
| + ~AudioFifoTest() {}
|
| +
|
| + void VerifyValue(const float data[], int size, float value) {
|
| + for (int i = 0; i < size; ++i)
|
| + ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
|
| + }
|
| +
|
| + protected:
|
| + DISALLOW_COPY_AND_ASSIGN(AudioFifoTest);
|
| +};
|
| +
|
| +// Verify that construction works as intended.
|
| +TEST_F(AudioFifoTest, Construct) {
|
| + const int kChannels = 6;
|
| + const int kMaxFrameCount = 128;
|
| + AudioFifo fifo(kChannels, kMaxFrameCount);
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| +}
|
| +
|
| +// Pushes audio bus objects to a FIFO and fill it up to different degrees.
|
| +// Also, verify that it is not possible to overflow the FIFO.
|
| +TEST_F(AudioFifoTest, Push) {
|
| + const int kChannels = 2;
|
| + const int kMaxFrameCount = 128;
|
| + AudioFifo fifo(kChannels, kMaxFrameCount);
|
| + {
|
| + SCOPED_TRACE("Push 50%");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), bus->frames());
|
| + fifo.Clear();
|
| + }
|
| + {
|
| + SCOPED_TRACE("Push 100%");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), bus->frames());
|
| + fifo.Clear();
|
| + }
|
| + {
|
| + SCOPED_TRACE("Overflow");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount + 1);
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + EXPECT_FALSE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + }
|
| +}
|
| +
|
| +// Consumes audio bus objects from a FIFO and empty it to different degrees.
|
| +// Also, verify that it is not possible to ask for more data than the FIFO
|
| +// contains (corresponds to underrun).
|
| +TEST_F(AudioFifoTest, Consume) {
|
| + const int kChannels = 2;
|
| + const int kMaxFrameCount = 128;
|
| + AudioFifo fifo(kChannels, kMaxFrameCount);
|
| + {
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), kMaxFrameCount);
|
| + }
|
| + {
|
| + SCOPED_TRACE("Consume 50%");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + EXPECT_TRUE(fifo.frames_in_fifo() == bus->frames());
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), kMaxFrameCount);
|
| + }
|
| + {
|
| + SCOPED_TRACE("Consume 100%");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), kMaxFrameCount);
|
| + }
|
| + {
|
| + SCOPED_TRACE("Underrun");
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount + 1);
|
| + EXPECT_FALSE(fifo.Consume(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), kMaxFrameCount);
|
| + }
|
| +}
|
| +
|
| +// Verify that the frames_in_fifo() method of the FIFO works as intended while
|
| +// appending and removing audio bus elements to/from the FIFO.
|
| +TEST_F(AudioFifoTest, FramesInFifo) {
|
| + const int kChannels = 2;
|
| + const int kMaxFrameCount = 64;
|
| + AudioFifo fifo(kChannels, kMaxFrameCount);
|
| +
|
| + // Fill up the FIFO and verify that the size grows as it should while adding
|
| + // one audio frame each time.
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, 1);
|
| + int n = 0;
|
| + while (fifo.frames_in_fifo() < kMaxFrameCount) {
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), ++n);
|
| + }
|
| +
|
| + // Ensure that we can't append more data when the FIFO is full.
|
| + EXPECT_EQ(fifo.frames_in_fifo(), kMaxFrameCount);
|
| + EXPECT_FALSE(fifo.Push(bus.get()));
|
| +
|
| + // Empty the FIFO and verify that the size decreases as it should.
|
| + // Reduce the size of the FIFO by one frame each time.
|
| + while (fifo.frames_in_fifo() > 0) {
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), --n);
|
| + }
|
| +
|
| + // Ensure that we can't remove more data when the FIFO is empty.
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 0);
|
| + EXPECT_FALSE(fifo.Consume(bus.get()));
|
| +
|
| + // Verify that a steady-state size of one frame in the FIFO is maintained
|
| + // during a sequence of Push/Consume calls which involves wrapping.
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 1);
|
| + for (int n = 0; n < 10 * kMaxFrameCount; ++n) {
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), 1);
|
| + }
|
| +}
|
| +
|
| +// Do a more realistic test of how the FIFO will be used and also verify that
|
| +// the actual data content is correct.
|
| +TEST_F(AudioFifoTest, PushAndConsume) {
|
| + const int kChannels = 2;
|
| + const int kFrameCount = 256;
|
| + const int kMaxAudioBusesInFifoCount = 128;
|
| +
|
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
|
| + AudioFifo fifo(kChannels, bus->frames() * kMaxAudioBusesInFifoCount);
|
| +
|
| + // Start by filling up half the FIFO with audio frames. The first audio frame
|
| + // will contain all 1's, the second all 2's etc. All channels contain the
|
| + // same value.
|
| + int value = 1;
|
| + while (fifo.frames_in_fifo() <
|
| + bus->frames() * (kMaxAudioBusesInFifoCount / 2)) {
|
| + // Fill all channels in the bus with dummy values.
|
| + for (int j = 0; j < bus->channels(); ++j)
|
| + std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(), bus->frames() * value);
|
| + ++value;
|
| + }
|
| +
|
| + // Do a sequence of Consume/Push calls and verify that the acquired values
|
| + // are correct and that the wrap-around mechanism works as intended.
|
| + // The size of the FIFO will be constant during this step.
|
| + const int steady_state_offset = fifo.frames_in_fifo() / bus->frames();
|
| + for (int i = 0; i < kMaxAudioBusesInFifoCount; ++i) {
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + value = steady_state_offset + i + 1;
|
| + for (int j = 0; j < bus->channels(); ++j) {
|
| + VerifyValue(bus->channel(j), bus->frames(), value - steady_state_offset);
|
| + std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
|
| + }
|
| + EXPECT_TRUE(fifo.Push(bus.get()));
|
| + EXPECT_EQ(fifo.frames_in_fifo(),
|
| + bus->frames() * (kMaxAudioBusesInFifoCount / 2));
|
| + }
|
| +
|
| + // As a last step, flush the FIFO and verify that the retrieved values
|
| + // are correct.
|
| + value = value - steady_state_offset + 1;
|
| + while (fifo.frames_in_fifo() > 0) {
|
| + EXPECT_TRUE(fifo.Consume(bus.get()));
|
| + for (int j = 0; j < bus->channels(); ++j) {
|
| + VerifyValue(bus->channel(j), bus->frames(), value);
|
| + }
|
| + value++;
|
| + }
|
| +}
|
| +
|
| +} // namespace media
|
|
|