summaryrefslogtreecommitdiffstats
path: root/media/base/audio_splicer_unittest.cc
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 17:37:19 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-05 17:37:19 +0000
commit1bae3ad673292afa7915611c3432b313b221c373 (patch)
tree32f24d337c6686c185940aaa6f72965dbde7d79d /media/base/audio_splicer_unittest.cc
parent0bf6a0602e14a2642d87c88ab8ef4abe9b2f3345 (diff)
downloadchromium_src-1bae3ad673292afa7915611c3432b313b221c373.zip
chromium_src-1bae3ad673292afa7915611c3432b313b221c373.tar.gz
chromium_src-1bae3ad673292afa7915611c3432b313b221c373.tar.bz2
Add support for audio config changes.
BUG=151046 Review URL: https://codereview.chromium.org/11419174 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171249 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/audio_splicer_unittest.cc')
-rw-r--r--media/base/audio_splicer_unittest.cc366
1 files changed, 366 insertions, 0 deletions
diff --git a/media/base/audio_splicer_unittest.cc b/media/base/audio_splicer_unittest.cc
new file mode 100644
index 0000000..2096789
--- /dev/null
+++ b/media/base/audio_splicer_unittest.cc
@@ -0,0 +1,366 @@
+// 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 "base/memory/scoped_ptr.h"
+#include "media/base/audio_splicer.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/buffers.h"
+#include "media/base/data_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+static const int kBytesPerFrame = 4;
+static const int kDefaultSampleRate = 44100;
+static const int kDefaultBufferSize = 100 * kBytesPerFrame;
+
+class AudioSplicerTest : public ::testing::Test {
+ public:
+ AudioSplicerTest()
+ : splicer_(kBytesPerFrame, kDefaultSampleRate),
+ input_timestamp_helper_(kBytesPerFrame, kDefaultSampleRate) {
+ input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
+ }
+
+ scoped_refptr<Buffer> GetNextInputBuffer(uint8 value) {
+ return GetNextInputBuffer(value, kDefaultBufferSize);
+ }
+
+ scoped_refptr<Buffer> GetNextInputBuffer(uint8 value, int size) {
+ scoped_refptr<DataBuffer> buffer = new DataBuffer(size);
+ buffer->SetDataSize(size);
+ memset(buffer->GetWritableData(), value, buffer->GetDataSize());
+ buffer->SetTimestamp(input_timestamp_helper_.GetTimestamp());
+ buffer->SetDuration(
+ input_timestamp_helper_.GetDuration(buffer->GetDataSize()));
+ input_timestamp_helper_.AddBytes(buffer->GetDataSize());
+ return buffer;
+ }
+
+ bool VerifyData(const uint8* data, int size, int value) {
+ for (int i = 0; i < size; ++i) {
+ if (data[i] != value)
+ return false;
+ }
+ return true;
+ }
+
+ protected:
+ AudioSplicer splicer_;
+ AudioTimestampHelper input_timestamp_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioSplicerTest);
+};
+
+TEST_F(AudioSplicerTest, PassThru) {
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Test single buffer pass-thru behavior.
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+
+ // Test that multiple buffers can be queued in the splicer.
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2);
+ scoped_refptr<Buffer> input_3 = GetNextInputBuffer(3);
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(splicer_.AddInput(input_3));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_2->GetTimestamp(), output_2->GetTimestamp());
+ EXPECT_EQ(input_2->GetDuration(), output_2->GetDuration());
+ EXPECT_EQ(input_2->GetDataSize(), output_2->GetDataSize());
+
+ scoped_refptr<Buffer> output_3 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_3->GetTimestamp(), output_3->GetTimestamp());
+ EXPECT_EQ(input_3->GetDuration(), output_3->GetDuration());
+ EXPECT_EQ(input_3->GetDataSize(), output_3->GetDataSize());
+}
+
+TEST_F(AudioSplicerTest, Reset) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+
+ splicer_.Reset();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Add some bytes to the timestamp helper so that the
+ // next buffer starts many frames beyond the end of
+ // |input_1|. This is to make sure that Reset() actually
+ // clears its state and doesn't try to insert a gap.
+ input_timestamp_helper_.AddBytes(100 * kBytesPerFrame);
+
+ // Verify that a new input buffer passes through as expected.
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2);
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_2->GetTimestamp(), output_2->GetTimestamp());
+ EXPECT_EQ(input_2->GetDuration(), output_2->GetDuration());
+ EXPECT_EQ(input_2->GetDataSize(), output_2->GetDataSize());
+}
+
+TEST_F(AudioSplicerTest, EndOfStream) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+ scoped_refptr<Buffer> input_2 = new DataBuffer(0); // End of stream.
+ scoped_refptr<Buffer> input_3 = GetNextInputBuffer(2);
+ EXPECT_TRUE(input_2->IsEndOfStream());
+
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+
+ EXPECT_TRUE(output_2->IsEndOfStream());
+
+ // Verify that buffers can be added again after Reset().
+ splicer_.Reset();
+ EXPECT_TRUE(splicer_.AddInput(input_3));
+ scoped_refptr<Buffer> output_3 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_3->GetTimestamp(), output_3->GetTimestamp());
+ EXPECT_EQ(input_3->GetDuration(), output_3->GetDuration());
+ EXPECT_EQ(input_3->GetDataSize(), output_3->GetDataSize());
+}
+
+
+// Test the gap insertion code.
+// +--------------+ +--------------+
+// |11111111111111| |22222222222222|
+// +--------------+ +--------------+
+// Results in:
+// +--------------+----+--------------+
+// |11111111111111|0000|22222222222222|
+// +--------------+----+--------------+
+TEST_F(AudioSplicerTest, GapInsertion) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+
+ // Add bytes to the timestamp helper so that the next buffer
+ // will have a starting timestamp that indicates a gap is
+ // present.
+ const int kGapSize = 7 * kBytesPerFrame;
+ input_timestamp_helper_.AddBytes(kGapSize);
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2);
+
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+
+ // Verify that a gap buffer is generated.
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ scoped_refptr<Buffer> output_3 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Verify that the first input buffer passed through unmodified.
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_1->GetData(), output_1->GetDataSize(), 1));
+
+ // Verify the contents of the gap buffer.
+ base::TimeDelta gap_timestamp =
+ input_1->GetTimestamp() + input_1->GetDuration();
+ base::TimeDelta gap_duration = input_2->GetTimestamp() - gap_timestamp;
+ EXPECT_GT(gap_duration, base::TimeDelta());
+ EXPECT_EQ(gap_timestamp, output_2->GetTimestamp());
+ EXPECT_EQ(gap_duration, output_2->GetDuration());
+ EXPECT_EQ(kGapSize, output_2->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_2->GetData(), output_2->GetDataSize(), 0));
+
+ // Verify that the second input buffer passed through unmodified.
+ EXPECT_EQ(input_2->GetTimestamp(), output_3->GetTimestamp());
+ EXPECT_EQ(input_2->GetDuration(), output_3->GetDuration());
+ EXPECT_EQ(input_2->GetDataSize(), output_3->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_3->GetData(), output_3->GetDataSize(), 2));
+}
+
+
+// Test that an error is signalled when the gap between input buffers is
+// too large.
+TEST_F(AudioSplicerTest, GapTooLarge) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+
+ // Add a seconds worth of bytes so that an unacceptably large
+ // gap exists between |input_1| and |input_2|.
+ const int kGapSize = kDefaultSampleRate * kBytesPerFrame;
+ input_timestamp_helper_.AddBytes(kGapSize);
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2);
+
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_FALSE(splicer_.AddInput(input_2));
+
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+
+ // Verify that the first input buffer passed through unmodified.
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_1->GetData(), output_1->GetDataSize(), 1));
+
+ // Verify that the second buffer is not available.
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Reset the timestamp helper so it can generate a buffer that is
+ // right after |input_1|.
+ input_timestamp_helper_.SetBaseTimestamp(
+ input_1->GetTimestamp() + input_1->GetDuration());
+
+ // Verify that valid buffers are still accepted.
+ scoped_refptr<Buffer> input_3 = GetNextInputBuffer(3);
+ EXPECT_TRUE(splicer_.AddInput(input_3));
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+ EXPECT_EQ(input_3->GetTimestamp(), output_2->GetTimestamp());
+ EXPECT_EQ(input_3->GetDuration(), output_2->GetDuration());
+ EXPECT_EQ(input_3->GetDataSize(), output_2->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_2->GetData(), output_2->GetDataSize(), 3));
+}
+
+
+// Verifies that an error is signalled if AddInput() is called
+// with a timestamp that is earlier than the first buffer added.
+TEST_F(AudioSplicerTest, BufferAddedBeforeBase) {
+ input_timestamp_helper_.SetBaseTimestamp(
+ base::TimeDelta::FromMicroseconds(10));
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+
+ // Reset the timestamp helper so the next buffer will have a timestamp earlier
+ // than |input_1|.
+ input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta::FromSeconds(0));
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(1);
+
+ EXPECT_GT(input_1->GetTimestamp(), input_2->GetTimestamp());
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_FALSE(splicer_.AddInput(input_2));
+}
+
+
+// Test when one buffer partially overlaps another.
+// +--------------+
+// |11111111111111|
+// +--------------+
+// +--------------+
+// |22222222222222|
+// +--------------+
+// Results in:
+// +--------------+----------+
+// |11111111111111|2222222222|
+// +--------------+----------+
+TEST_F(AudioSplicerTest, PartialOverlap) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+
+ // Reset timestamp helper so that the next buffer will have a
+ // timestamp that starts in the middle of |input_1|.
+ const int kOverlapSize = input_1->GetDataSize() / 4;
+ input_timestamp_helper_.SetBaseTimestamp(input_1->GetTimestamp());
+ input_timestamp_helper_.AddBytes(input_1->GetDataSize() - kOverlapSize);
+
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2);
+
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Verify that the first input buffer passed through unmodified.
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_1->GetData(), output_1->GetDataSize(), 1));
+
+
+ // Verify that the second input buffer was truncated to only contain
+ // the samples that are after the end of |input_1|.
+ base::TimeDelta expected_timestamp =
+ input_1->GetTimestamp() + input_1->GetDuration();
+ base::TimeDelta expected_duration =
+ (input_2->GetTimestamp() + input_2->GetDuration()) - expected_timestamp;
+ EXPECT_EQ(expected_timestamp, output_2->GetTimestamp());
+ EXPECT_EQ(expected_duration, output_2->GetDuration());
+ EXPECT_EQ(input_2->GetDataSize() - kOverlapSize, output_2->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_2->GetData(), output_2->GetDataSize(), 2));
+}
+
+
+// Test that an input buffer that is completely overlapped by a buffer
+// that was already added is dropped.
+// +--------------+
+// |11111111111111|
+// +--------------+
+// +-----+
+// |22222|
+// +-----+
+// +-------------+
+// |3333333333333|
+// +-------------+
+// Results in:
+// +--------------+-------------+
+// |11111111111111|3333333333333|
+// +--------------+-------------+
+TEST_F(AudioSplicerTest, DropBuffer) {
+ scoped_refptr<Buffer> input_1 = GetNextInputBuffer(1);
+
+ // Reset timestamp helper so that the next buffer will have a
+ // timestamp that starts in the middle of |input_1|.
+ const int kOverlapOffset = input_1->GetDataSize() / 2;
+ const int kOverlapSize = input_1->GetDataSize() / 4;
+ input_timestamp_helper_.SetBaseTimestamp(input_1->GetTimestamp());
+ input_timestamp_helper_.AddBytes(kOverlapOffset);
+
+ scoped_refptr<Buffer> input_2 = GetNextInputBuffer(2, kOverlapSize);
+
+ // Reset the timestamp helper so the next buffer will be right after
+ // |input_1|.
+ input_timestamp_helper_.SetBaseTimestamp(input_1->GetTimestamp());
+ input_timestamp_helper_.AddBytes(input_1->GetDataSize());
+ scoped_refptr<Buffer> input_3 = GetNextInputBuffer(3);
+
+ EXPECT_TRUE(splicer_.AddInput(input_1));
+ EXPECT_TRUE(splicer_.AddInput(input_2));
+ EXPECT_TRUE(splicer_.AddInput(input_3));
+
+ EXPECT_TRUE(splicer_.HasNextBuffer());
+ scoped_refptr<Buffer> output_1 = splicer_.GetNextBuffer();
+ scoped_refptr<Buffer> output_2 = splicer_.GetNextBuffer();
+ EXPECT_FALSE(splicer_.HasNextBuffer());
+
+ // Verify that the first input buffer passed through unmodified.
+ EXPECT_EQ(input_1->GetTimestamp(), output_1->GetTimestamp());
+ EXPECT_EQ(input_1->GetDuration(), output_1->GetDuration());
+ EXPECT_EQ(input_1->GetDataSize(), output_1->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_1->GetData(), output_1->GetDataSize(), 1));
+
+ // Verify that the second output buffer only contains
+ // the samples that are in |input_3|.
+ EXPECT_EQ(input_3->GetTimestamp(), output_2->GetTimestamp());
+ EXPECT_EQ(input_3->GetDuration(), output_2->GetDuration());
+ EXPECT_EQ(input_3->GetDataSize(), output_2->GetDataSize());
+ EXPECT_TRUE(VerifyData(output_2->GetData(), output_2->GetDataSize(), 3));
+}
+
+} // namespace media