Chromium Code Reviews| Index: media/base/audio_discard_helper_unittest.cc |
| diff --git a/media/base/audio_discard_helper_unittest.cc b/media/base/audio_discard_helper_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1a6b592120da4b8425361e606a89b28cb334c1b9 |
| --- /dev/null |
| +++ b/media/base/audio_discard_helper_unittest.cc |
| @@ -0,0 +1,214 @@ |
| +// Copyright 2014 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_buffer.h" |
| +#include "media/base/audio_discard_helper.h" |
| +#include "media/base/buffers.h" |
| +#include "media/base/decoder_buffer.h" |
| +#include "media/base/test_helpers.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace media { |
| + |
| +static const int kSampleRate = 48000; |
| + |
| +static scoped_refptr<DecoderBuffer> CreateEncodedBuffer( |
| + base::TimeDelta timestamp, |
| + base::TimeDelta duration) { |
| + scoped_refptr<DecoderBuffer> result(new DecoderBuffer(1)); |
| + result->set_timestamp(timestamp); |
| + result->set_duration(duration); |
| + return result; |
| +} |
| + |
| +static scoped_refptr<AudioBuffer> CreateDecodedBuffer(int frames) { |
| + return MakeAudioBuffer(kSampleFormatPlanarF32, |
| + CHANNEL_LAYOUT_MONO, |
| + 1, |
| + kSampleRate, |
| + 0.0f, |
| + 0.01f, |
| + frames, |
| + kNoTimestamp(), |
| + kNoTimestamp()); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, TimeDeltaToFrames) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + |
| + EXPECT_EQ(0, discard_helper.TimeDeltaToFrames(base::TimeDelta())); |
| + EXPECT_EQ( |
| + kSampleRate / 100, |
| + discard_helper.TimeDeltaToFrames(base::TimeDelta::FromMilliseconds(10))); |
| + |
| + // Ensure partial frames are always rounded up. The equation below calculates |
| + // a frame count with a fractional part < 0.5. |
| + const int small_remainder = |
| + base::Time::kMicrosecondsPerSecond * (kSampleRate - 0.9) / kSampleRate; |
| + EXPECT_EQ(kSampleRate, |
| + discard_helper.TimeDeltaToFrames( |
| + base::TimeDelta::FromMicroseconds(small_remainder))); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, BasicProcessBuffers) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + |
| + // Use an estimated duration which doesn't match the number of decoded frames |
| + // to ensure the helper is correctly setting durations based on output frames. |
| + const base::TimeDelta kEstimatedDuration = |
| + base::TimeDelta::FromMilliseconds(9); |
| + const base::TimeDelta kActualDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kActualDuration); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kEstimatedDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + // Verify the basic case where nothing is discarded. |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kActualDuration, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); |
| + |
| + // Verify a Reset() takes us back to an uninitialized state. |
| + discard_helper.Reset(0); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + // Verify a NULL output buffer returns false. |
| + ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, NULL)); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, ProcessBuffersWithInitialDiscard) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); |
| + |
| + // Tell the helper we want to discard half of the initial frames. |
| + discard_helper.Reset(kTestFrames / 2); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + // Verify half the frames end up discarded. |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, ProcessBuffersWithLargeInitialDiscard) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); |
| + |
| + // Tell the helper we want to discard 1.5 buffers worth of frames. |
| + discard_helper.Reset(kTestFrames * 1.5); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + // The first call should fail since no output buffer remains. |
| + ASSERT_FALSE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + |
| + // Generate another set of buffers and expect half the output frames. |
| + encoded_buffer = CreateEncodedBuffer(kTimestamp + kDuration, kDuration); |
| + decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + |
| + // The timestamp should match that of the initial buffer. |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, AllowNonMonotonicTimestamps) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); |
| + |
| + // Process the same input buffer again to ensure input timestamps which go |
|
wolenetz
2014/04/28 21:52:07
nit: timestamp really isn't going backwards in tim
DaleCurtis
2014/04/28 23:09:03
kTimestamp on buffer 2 is now behind kTimestamp+kD
|
| + // backwards in time are not errors. |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + EXPECT_EQ(kTimestamp + kDuration, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames, decoded_buffer->frame_count()); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, DiscardPadding) { |
|
wolenetz
2014/04/28 21:52:07
Versus ProcessBuffersWithInitialDiscard and Initia
DaleCurtis
2014/04/28 23:09:03
Done. Doing so required improving the accuracy of
|
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + // Set a discard padding equivalent to half the buffer. |
| + encoded_buffer->set_discard_padding(kDuration / 2); |
| + |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); |
| +} |
| + |
| +TEST(AudioDiscardHelperTest, InitialDiscardAndDiscardPadding) { |
| + AudioDiscardHelper discard_helper(kSampleRate); |
| + ASSERT_FALSE(discard_helper.initialized()); |
| + |
| + const base::TimeDelta kTimestamp = base::TimeDelta(); |
| + const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(10); |
| + const int kTestFrames = discard_helper.TimeDeltaToFrames(kDuration); |
| + |
| + scoped_refptr<DecoderBuffer> encoded_buffer = |
| + CreateEncodedBuffer(kTimestamp, kDuration); |
| + scoped_refptr<AudioBuffer> decoded_buffer = CreateDecodedBuffer(kTestFrames); |
| + |
| + // Set a discard padding equivalent to a quarter of the buffer. |
| + encoded_buffer->set_discard_padding(kDuration / 4); |
| + |
| + // Set an initial discard of a quarter of the buffer. |
| + discard_helper.Reset(kTestFrames / 4); |
| + |
| + ASSERT_TRUE(discard_helper.ProcessBuffers(encoded_buffer, decoded_buffer)); |
| + ASSERT_TRUE(discard_helper.initialized()); |
| + EXPECT_EQ(kTimestamp, decoded_buffer->timestamp()); |
| + EXPECT_EQ(kDuration / 2, decoded_buffer->duration()); |
| + EXPECT_EQ(kTestFrames / 2, decoded_buffer->frame_count()); |
| +} |
| + |
|
wolenetz
2014/04/28 21:52:07
nit: remove extra line.
DaleCurtis
2014/04/28 23:09:03
Done.
|
| + |
| +} // namespace media |