Chromium Code Reviews| Index: media/base/audio_splicer_unittest.cc |
| diff --git a/media/base/audio_splicer_unittest.cc b/media/base/audio_splicer_unittest.cc |
| index 43902687fae9f3bcc55824647581be817c3795b6..43af22d1e33a2acd4a6b4fce6dff1bd04cd61650 100644 |
| --- a/media/base/audio_splicer_unittest.cc |
| +++ b/media/base/audio_splicer_unittest.cc |
| @@ -22,8 +22,10 @@ class AudioSplicerTest : public ::testing::Test { |
| public: |
| AudioSplicerTest() |
| : splicer_(kDefaultSampleRate), |
| - input_timestamp_helper_(kDefaultSampleRate) { |
| + input_timestamp_helper_(kDefaultSampleRate), |
| + output_timestamp_helper_(kDefaultSampleRate) { |
| input_timestamp_helper_.SetBaseTimestamp(base::TimeDelta()); |
| + output_timestamp_helper_.SetBaseTimestamp(base::TimeDelta()); |
| } |
| scoped_refptr<AudioBuffer> GetNextInputBuffer(float value) { |
| @@ -43,20 +45,123 @@ class AudioSplicerTest : public ::testing::Test { |
| return buffer; |
| } |
| - bool VerifyData(scoped_refptr<AudioBuffer> buffer, float value) { |
| + bool VerifyData(const scoped_refptr<AudioBuffer>& buffer, float value) { |
| int frames = buffer->frame_count(); |
| scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames); |
| buffer->ReadFrames(frames, 0, 0, bus.get()); |
| - for (int i = 0; i < frames; ++i) { |
| - if (bus->channel(0)[i] != value) |
| - return false; |
| + for (int ch = 0; ch < buffer->channel_count(); ++ch) { |
| + for (int i = 0; i < frames; ++i) { |
| + if (bus->channel(ch)[i] != value) |
| + return false; |
| + } |
| } |
| return true; |
| } |
| + void VerifyNextBuffer(const scoped_refptr<AudioBuffer>& input, float value) { |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + scoped_refptr<AudioBuffer> output = splicer_.GetNextBuffer(); |
| + EXPECT_EQ(input->timestamp(), output->timestamp()); |
| + EXPECT_EQ(input->duration(), output->duration()); |
| + EXPECT_EQ(input->frame_count(), output->frame_count()); |
| + EXPECT_TRUE(VerifyData(output, value)); |
| + output_timestamp_helper_.AddFrames(output->frame_count()); |
| + } |
| + |
| + void VerifyPreSpliceOutput( |
| + const scoped_refptr<AudioBuffer>& overlapped_buffer, |
| + const scoped_refptr<AudioBuffer>& overlapping_buffer, |
| + float overlapped_value) { |
| + const base::TimeDelta kSpliceTimestamp = overlapping_buffer->timestamp(); |
| + const int kExpectedPreSpliceSize = |
| + output_timestamp_helper_.GetFramesToTarget(kSpliceTimestamp); |
| + const base::TimeDelta kExpectedPreSpliceDuration = |
| + output_timestamp_helper_.GetFrameDuration(kExpectedPreSpliceSize); |
| + |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + scoped_refptr<AudioBuffer> pre_splice_output = splicer_.GetNextBuffer(); |
| + EXPECT_EQ(overlapped_buffer->timestamp(), pre_splice_output->timestamp()); |
| + EXPECT_EQ(kExpectedPreSpliceDuration, pre_splice_output->duration()); |
| + EXPECT_EQ(kExpectedPreSpliceSize, pre_splice_output->frame_count()); |
| + EXPECT_TRUE(VerifyData(pre_splice_output, overlapped_value)); |
| + output_timestamp_helper_.AddFrames(pre_splice_output->frame_count()); |
| + } |
| + |
| + base::TimeDelta CalculateCrossfadeDuration( |
| + const scoped_refptr<AudioBuffer>& overlapped_buffer, |
| + const scoped_refptr<AudioBuffer>& overlapping_buffer) { |
| + return std::min(max_crossfade_duration(), |
| + std::min(overlapped_buffer->timestamp() + |
| + overlapped_buffer->duration() - |
| + overlapping_buffer->timestamp(), |
| + overlapping_buffer->duration())); |
| + } |
| + |
| + void VerifyCrossfadeOutput( |
| + const scoped_refptr<AudioBuffer>& overlapped_buffer, |
| + const scoped_refptr<AudioBuffer>& overlapping_buffer, |
| + float overlapped_value, |
| + float overlapping_value, |
| + base::TimeDelta* expected_crossfade_duration, |
| + int64* expected_crossfade_size) { |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + |
| + const base::TimeDelta kSpliceTimestamp = |
|
acolwell GONE FROM CHROMIUM
2014/02/27 17:10:14
I'm a little concerned that we are trying to repli
DaleCurtis
2014/02/27 19:45:01
I generally dislike constant only verification in
DaleCurtis
2014/02/28 00:24:41
Mostly done. I also cleaned up the verify syntax.
|
| + output_timestamp_helper_.GetTimestamp(); |
| + *expected_crossfade_size = output_timestamp_helper_.GetFramesToTarget( |
| + kSpliceTimestamp + |
| + CalculateCrossfadeDuration(overlapped_buffer, overlapping_buffer)); |
| + // Don't use the calculated duration directly as it may differ in truthiness |
| + // by a few microseconds from what the AudioTimestampHelper is returning. |
| + *expected_crossfade_duration = |
| + output_timestamp_helper_.GetFrameDuration(*expected_crossfade_size); |
| + |
| + scoped_refptr<AudioBuffer> crossfade_output = splicer_.GetNextBuffer(); |
| + EXPECT_EQ(kSpliceTimestamp, crossfade_output->timestamp()); |
| + EXPECT_EQ(*expected_crossfade_duration, crossfade_output->duration()); |
| + EXPECT_EQ(*expected_crossfade_size, crossfade_output->frame_count()); |
| + output_timestamp_helper_.AddFrames(crossfade_output->frame_count()); |
| + |
| + // Verify the actual crossfade. |
| + const int frames = crossfade_output->frame_count(); |
| + scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, frames); |
| + crossfade_output->ReadFrames(frames, 0, 0, bus.get()); |
| + for (int ch = 0; ch < crossfade_output->channel_count(); ++ch) { |
| + float cf_ratio = 0; |
| + const float cf_increment = 1.0f / frames; |
| + for (int i = 0; i < frames; ++i, cf_ratio += cf_increment) { |
| + const float actual = bus->channel(ch)[i]; |
| + const float expected = |
| + (1.0f - cf_ratio) * overlapped_value + cf_ratio * overlapping_value; |
| + ASSERT_FLOAT_EQ(expected, actual) << "i=" << i; |
| + } |
| + } |
| + } |
| + |
| + bool AddInput(const scoped_refptr<AudioBuffer>& input) { |
| + // Since the splicer doesn't make copies it's working directly on the input |
| + // buffers. We must make a copy before adding to ensure the original buffer |
| + // is not modified in unexpected ways. |
| + scoped_refptr<AudioBuffer> buffer_copy = |
| + input->end_of_stream() |
| + ? AudioBuffer::CreateEOSBuffer() |
| + : AudioBuffer::CopyFrom(kSampleFormat, |
| + input->channel_count(), |
| + input->frame_count(), |
| + &input->channel_data()[0], |
| + input->timestamp(), |
| + input->duration()); |
| + return splicer_.AddInput(buffer_copy); |
| + } |
| + |
| + base::TimeDelta max_crossfade_duration() { |
| + return splicer_.max_crossfade_duration_; |
| + } |
| + |
| protected: |
| AudioSplicer splicer_; |
| AudioTimestampHelper input_timestamp_helper_; |
| + AudioTimestampHelper output_timestamp_helper_; |
| DISALLOW_COPY_AND_ASSIGN(AudioSplicerTest); |
| }; |
| @@ -66,40 +171,24 @@ TEST_F(AudioSplicerTest, PassThru) { |
| // Test single buffer pass-thru behavior. |
| scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - |
| - scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + VerifyNextBuffer(input_1, 0.1f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_1, 0.1f)); |
| // Test that multiple buffers can be queued in the splicer. |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f); |
| scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f); |
| - EXPECT_TRUE(splicer_.AddInput(input_2)); |
| - EXPECT_TRUE(splicer_.AddInput(input_3)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - |
| - scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_2->timestamp(), output_2->timestamp()); |
| - EXPECT_EQ(input_2->duration(), output_2->duration()); |
| - EXPECT_EQ(input_2->frame_count(), output_2->frame_count()); |
| - |
| - scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_2)); |
| + EXPECT_TRUE(AddInput(input_3)); |
| + VerifyNextBuffer(input_2, 0.2f); |
| + VerifyNextBuffer(input_3, 0.3f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_3->timestamp(), output_3->timestamp()); |
| - EXPECT_EQ(input_3->duration(), output_3->duration()); |
| - EXPECT_EQ(input_3->frame_count(), output_3->frame_count()); |
| } |
| TEST_F(AudioSplicerTest, Reset) { |
| scoped_refptr<AudioBuffer> input_1 = GetNextInputBuffer(0.1f); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| splicer_.Reset(); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| @@ -112,14 +201,10 @@ TEST_F(AudioSplicerTest, Reset) { |
| // Verify that a new input buffer passes through as expected. |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f); |
| - EXPECT_TRUE(splicer_.AddInput(input_2)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - |
| - scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_2)); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + VerifyNextBuffer(input_2, 0.2f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_2->timestamp(), output_2->timestamp()); |
| - EXPECT_EQ(input_2->duration(), output_2->duration()); |
| - EXPECT_EQ(input_2->frame_count(), output_2->frame_count()); |
| } |
| TEST_F(AudioSplicerTest, EndOfStream) { |
| @@ -128,30 +213,22 @@ TEST_F(AudioSplicerTest, EndOfStream) { |
| scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.2f); |
| EXPECT_TRUE(input_2->end_of_stream()); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_TRUE(splicer_.AddInput(input_2)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_TRUE(AddInput(input_2)); |
| + |
| + VerifyNextBuffer(input_1, 0.1f); |
| - scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - |
| EXPECT_TRUE(output_2->end_of_stream()); |
| // Verify that buffers can be added again after Reset(). |
| splicer_.Reset(); |
| - EXPECT_TRUE(splicer_.AddInput(input_3)); |
| - scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_3)); |
| + VerifyNextBuffer(input_3, 0.2f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_3->timestamp(), output_3->timestamp()); |
| - EXPECT_EQ(input_3->duration(), output_3->duration()); |
| - EXPECT_EQ(input_3->frame_count(), output_3->frame_count()); |
| } |
| - |
| // Test the gap insertion code. |
| // +--------------+ +--------------+ |
| // |11111111111111| |22222222222222| |
| @@ -170,23 +247,14 @@ TEST_F(AudioSplicerTest, GapInsertion) { |
| input_timestamp_helper_.AddFrames(kGapSize); |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f); |
| - 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<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| - scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| - scoped_refptr<AudioBuffer> output_3 = splicer_.GetNextBuffer(); |
| - EXPECT_FALSE(splicer_.HasNextBuffer()); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_TRUE(AddInput(input_2)); |
| // Verify that the first input buffer passed through unmodified. |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_1, 0.1f)); |
| + VerifyNextBuffer(input_1, 0.1f); |
| // Verify the contents of the gap buffer. |
| + scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| base::TimeDelta gap_timestamp = |
| input_1->timestamp() + input_1->duration(); |
| base::TimeDelta gap_duration = input_2->timestamp() - gap_timestamp; |
| @@ -197,13 +265,10 @@ TEST_F(AudioSplicerTest, GapInsertion) { |
| EXPECT_TRUE(VerifyData(output_2, 0.0f)); |
| // Verify that the second input buffer passed through unmodified. |
| - EXPECT_EQ(input_2->timestamp(), output_3->timestamp()); |
| - EXPECT_EQ(input_2->duration(), output_3->duration()); |
| - EXPECT_EQ(input_2->frame_count(), output_3->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_3, 0.2f)); |
| + VerifyNextBuffer(input_2, 0.2f); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| } |
| - |
| // Test that an error is signalled when the gap between input buffers is |
| // too large. |
| TEST_F(AudioSplicerTest, GapTooLarge) { |
| @@ -215,17 +280,10 @@ TEST_F(AudioSplicerTest, GapTooLarge) { |
| input_timestamp_helper_.AddFrames(kGapSize); |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_FALSE(splicer_.AddInput(input_2)); |
| - |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_FALSE(AddInput(input_2)); |
| - // Verify that the first input buffer passed through unmodified. |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_1, 0.1f)); |
| + VerifyNextBuffer(input_1, 0.1f); |
| // Verify that the second buffer is not available. |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| @@ -237,17 +295,11 @@ TEST_F(AudioSplicerTest, GapTooLarge) { |
| // Verify that valid buffers are still accepted. |
| scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f); |
| - EXPECT_TRUE(splicer_.AddInput(input_3)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(AddInput(input_3)); |
| + VerifyNextBuffer(input_3, 0.3f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - EXPECT_EQ(input_3->timestamp(), output_2->timestamp()); |
| - EXPECT_EQ(input_3->duration(), output_2->duration()); |
| - EXPECT_EQ(input_3->frame_count(), output_2->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_2, 0.3f)); |
| } |
| - |
| // 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) { |
| @@ -261,11 +313,10 @@ TEST_F(AudioSplicerTest, BufferAddedBeforeBase) { |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.1f); |
| EXPECT_GT(input_1->timestamp(), input_2->timestamp()); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_FALSE(splicer_.AddInput(input_2)); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_FALSE(AddInput(input_2)); |
| } |
| - |
| // Test when one buffer partially overlaps another. |
| // +--------------+ |
| // |11111111111111| |
| @@ -288,23 +339,18 @@ TEST_F(AudioSplicerTest, PartialOverlap) { |
| scoped_refptr<AudioBuffer> input_2 = GetNextInputBuffer(0.2f); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_TRUE(splicer_.AddInput(input_2)); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_TRUE(AddInput(input_2)); |
| + |
| + // Verify that the first input buffer passed through unmodified. |
| + VerifyNextBuffer(input_1, 0.1f); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| - // Verify that the first input buffer passed through unmodified. |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_1, 0.1f)); |
| - |
| // Verify that the second input buffer was truncated to only contain |
| - // the samples that are after the end of |input_1|. Note that data is not |
| - // copied, so |input_2|'s values are modified. |
| + // the samples that are after the end of |input_1|. |
| base::TimeDelta expected_timestamp = |
| input_1->timestamp() + input_1->duration(); |
| base::TimeDelta expected_duration = |
| @@ -314,7 +360,6 @@ TEST_F(AudioSplicerTest, PartialOverlap) { |
| EXPECT_TRUE(VerifyData(output_2, 0.2f)); |
| } |
| - |
| // Test that an input buffer that is completely overlapped by a buffer |
| // that was already added is dropped. |
| // +--------------+ |
| @@ -348,27 +393,221 @@ TEST_F(AudioSplicerTest, DropBuffer) { |
| input_timestamp_helper_.AddFrames(input_1->frame_count()); |
| scoped_refptr<AudioBuffer> input_3 = GetNextInputBuffer(0.3f); |
| - EXPECT_TRUE(splicer_.AddInput(input_1)); |
| - EXPECT_TRUE(splicer_.AddInput(input_2)); |
| - EXPECT_TRUE(splicer_.AddInput(input_3)); |
| + EXPECT_TRUE(AddInput(input_1)); |
| + EXPECT_TRUE(AddInput(input_2)); |
| + EXPECT_TRUE(AddInput(input_3)); |
| - EXPECT_TRUE(splicer_.HasNextBuffer()); |
| - scoped_refptr<AudioBuffer> output_1 = splicer_.GetNextBuffer(); |
| - scoped_refptr<AudioBuffer> output_2 = splicer_.GetNextBuffer(); |
| + VerifyNextBuffer(input_1, 0.1f); |
| + VerifyNextBuffer(input_3, 0.3f); |
| EXPECT_FALSE(splicer_.HasNextBuffer()); |
| +} |
| - // Verify that the first input buffer passed through unmodified. |
| - EXPECT_EQ(input_1->timestamp(), output_1->timestamp()); |
| - EXPECT_EQ(input_1->duration(), output_1->duration()); |
| - EXPECT_EQ(input_1->frame_count(), output_1->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_1, 0.1f)); |
| - |
| - // Verify that the second output buffer only contains |
| - // the samples that are in |input_3|. |
| - EXPECT_EQ(input_3->timestamp(), output_2->timestamp()); |
| - EXPECT_EQ(input_3->duration(), output_2->duration()); |
| - EXPECT_EQ(input_3->frame_count(), output_2->frame_count()); |
| - EXPECT_TRUE(VerifyData(output_2, 0.3f)); |
| +// Test crossfade when one buffer partially overlaps another. |
| +// +--------------+ |
| +// |11111111111111| |
| +// +--------------+ |
| +// +--------------+ |
| +// |22222222222222| |
| +// +--------------+ |
| +// Results in: |
| +// +----------+----+----------+ |
| +// |1111111111|xxxx|2222222222| |
| +// +----------+----+----------+ |
| +// Where "xxxx" represents the crossfaded portion of the signal. |
| +TEST_F(AudioSplicerTest, PartialOverlapCrossfade) { |
| + const int kCrossfadeSize = |
| + input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()); |
| + const int kBufferSize = kCrossfadeSize * 2; |
| + |
| + scoped_refptr<AudioBuffer> extra_pre_splice_buffer = |
| + GetNextInputBuffer(0.2f, kBufferSize); |
| + scoped_refptr<AudioBuffer> overlapped_buffer = |
| + GetNextInputBuffer(1.0f, kBufferSize); |
| + |
| + // Reset timestamp helper so that the next buffer will have a timestamp that |
| + // starts in the middle of |overlapped_buffer|. |
| + input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp()); |
| + input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() - |
| + kCrossfadeSize); |
| + const base::TimeDelta splice_timestamp = |
| + input_timestamp_helper_.GetTimestamp(); |
| + splicer_.SetSpliceTimestamp(splice_timestamp); |
| + scoped_refptr<AudioBuffer> overlapping_buffer = |
| + GetNextInputBuffer(0.0f, kBufferSize); |
| + |
| + // |extra_pre_splice_buffer| is entirely before the splice and should be ready |
| + // for output. |
| + EXPECT_TRUE(AddInput(extra_pre_splice_buffer)); |
| + VerifyNextBuffer(extra_pre_splice_buffer, 0.2f); |
| + |
| + // The splicer should be internally queuing input since |overlapped_buffer| is |
| + // part of the splice. |
| + EXPECT_TRUE(AddInput(overlapped_buffer)); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| + |
| + // |overlapping_buffer| should complete the splice, so ensure output is now |
| + // available. |
| + EXPECT_TRUE(AddInput(overlapping_buffer)); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + |
| + // Add one more buffer to make sure it's passed through untouched. |
| + scoped_refptr<AudioBuffer> extra_post_splice_buffer = |
| + GetNextInputBuffer(0.5f, kBufferSize); |
| + EXPECT_TRUE(AddInput(extra_post_splice_buffer)); |
| + |
| + VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f); |
| + |
| + int64 expected_crossfade_size = 0; |
| + base::TimeDelta expected_crossfade_duration; |
| + VerifyCrossfadeOutput(overlapped_buffer, |
| + overlapping_buffer, |
| + 1.0f, |
| + 0.0f, |
| + &expected_crossfade_duration, |
| + &expected_crossfade_size); |
| + const int kExpectedPostSpliceSize = |
| + overlapping_buffer->frame_count() - expected_crossfade_size; |
| + |
| + // Retrieve the remaining portion after crossfade. |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer(); |
| + EXPECT_EQ(output_timestamp_helper_.GetTimestamp(), |
| + post_splice_output->timestamp()); |
| + EXPECT_EQ(kExpectedPostSpliceSize, post_splice_output->frame_count()); |
| + EXPECT_EQ(output_timestamp_helper_.GetFrameDuration(kExpectedPostSpliceSize), |
| + post_splice_output->duration()); |
| + |
| + EXPECT_TRUE(VerifyData(post_splice_output, 0.0f)); |
| + |
| + VerifyNextBuffer(extra_post_splice_buffer, 0.5f); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| +} |
| + |
| +// Test crossfade when one buffer partially overlaps another, but an end of |
| +// stream buffer is received before the crossfade duration is reached. |
| +// +--------------+ |
| +// |11111111111111| |
| +// +--------------+ |
| +// +---------++---+ |
| +// |222222222||EOS| |
| +// +---------++---+ |
| +// Results in: |
| +// +----------+----+----++---+ |
| +// |1111111111|xxxx|2222||EOS| |
| +// +----------+----+----++---+ |
| +// Where "x" represents the crossfaded portion of the signal. |
| +TEST_F(AudioSplicerTest, PartialOverlapCrossfadeEndOfStream) { |
| + const int kCrossfadeSize = |
| + input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()); |
| + |
| + scoped_refptr<AudioBuffer> overlapped_buffer = |
| + GetNextInputBuffer(1.0f, kCrossfadeSize * 2); |
| + |
| + // Reset timestamp helper so that the next buffer will have a timestamp that |
| + // starts 3/4 of the way into |overlapped_buffer|. |
| + input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp()); |
| + input_timestamp_helper_.AddFrames(3 * overlapped_buffer->frame_count() / 4); |
| + const base::TimeDelta splice_timestamp = |
| + input_timestamp_helper_.GetTimestamp(); |
| + splicer_.SetSpliceTimestamp(splice_timestamp); |
| + scoped_refptr<AudioBuffer> overlapping_buffer = |
| + GetNextInputBuffer(0.0f, kCrossfadeSize / 3); |
| + |
| + // The splicer should be internally queuing input since |overlapped_buffer| is |
| + // part of the splice. |
| + EXPECT_TRUE(AddInput(overlapped_buffer)); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| + |
| + // |overlapping_buffer| should not have enough data to complete the splice, so |
| + // ensure output is not available. |
| + EXPECT_TRUE(AddInput(overlapping_buffer)); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| + |
| + // Now add an EOS buffer which should complete the splice. |
| + EXPECT_TRUE(AddInput(AudioBuffer::CreateEOSBuffer())); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + |
| + VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f); |
| + int64 expected_crossfade_size = 0; |
| + base::TimeDelta expected_crossfade_duration; |
| + VerifyCrossfadeOutput(overlapped_buffer, |
| + overlapping_buffer, |
| + 1.0f, |
| + 0.0f, |
| + &expected_crossfade_duration, |
| + &expected_crossfade_size); |
| + |
| + // Ensure the last buffer is an EOS buffer. |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer(); |
| + EXPECT_TRUE(post_splice_output->end_of_stream()); |
| + |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| +} |
| + |
| +// Test crossfade when one buffer partially overlaps another, but the amount of |
| +// overlapped data is less than the crossfade duration. |
| +// +------------+ |
| +// |111111111111| |
| +// +------------+ |
| +// +--------------+ |
| +// |22222222222222| |
| +// +--------------+ |
| +// Results in: |
| +// +----------+-+------------+ |
| +// |1111111111|x|222222222222| |
| +// +----------+-+------------+ |
| +// Where "x" represents the crossfaded portion of the signal. |
| +TEST_F(AudioSplicerTest, PartialOverlapCrossfadeShortPreSplice) { |
| + const int kCrossfadeSize = |
| + input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()); |
| + |
| + scoped_refptr<AudioBuffer> overlapped_buffer = |
| + GetNextInputBuffer(1.0f, kCrossfadeSize / 2); |
| + |
| + // Reset timestamp helper so that the next buffer will have a timestamp that |
| + // starts in the middle of |overlapped_buffer|. |
| + input_timestamp_helper_.SetBaseTimestamp(overlapped_buffer->timestamp()); |
| + input_timestamp_helper_.AddFrames(overlapped_buffer->frame_count() / 2); |
| + const base::TimeDelta splice_timestamp = |
| + input_timestamp_helper_.GetTimestamp(); |
| + splicer_.SetSpliceTimestamp(splice_timestamp); |
| + scoped_refptr<AudioBuffer> overlapping_buffer = |
| + GetNextInputBuffer(0.0f, kCrossfadeSize * 2); |
| + |
| + // The splicer should be internally queuing input since |overlapped_buffer| is |
| + // part of the splice. |
| + EXPECT_TRUE(AddInput(overlapped_buffer)); |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| + |
| + // |overlapping_buffer| should complete the splice, so ensure output is now |
| + // available. |
| + EXPECT_TRUE(AddInput(overlapping_buffer)); |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + |
| + VerifyPreSpliceOutput(overlapped_buffer, overlapping_buffer, 1.0f); |
| + |
| + int64 expected_crossfade_size = 0; |
| + base::TimeDelta expected_crossfade_duration; |
| + VerifyCrossfadeOutput(overlapped_buffer, |
| + overlapping_buffer, |
| + 1.0f, |
| + 0.0f, |
| + &expected_crossfade_duration, |
| + &expected_crossfade_size); |
| + |
| + // Retrieve the remaining portion after crossfade. |
| + ASSERT_TRUE(splicer_.HasNextBuffer()); |
| + scoped_refptr<AudioBuffer> post_splice_output = splicer_.GetNextBuffer(); |
| + EXPECT_EQ(output_timestamp_helper_.GetTimestamp(), |
| + post_splice_output->timestamp()); |
| + EXPECT_EQ(overlapping_buffer->duration() - expected_crossfade_duration, |
| + post_splice_output->duration()); |
| + EXPECT_EQ(overlapping_buffer->frame_count() - expected_crossfade_size, |
| + post_splice_output->frame_count()); |
| + EXPECT_TRUE(VerifyData(post_splice_output, 0.0f)); |
| + |
| + EXPECT_FALSE(splicer_.HasNextBuffer()); |
| } |
| } // namespace media |