| Index: media/filters/audio_renderer_base_unittest.cc
|
| diff --git a/media/filters/audio_renderer_base_unittest.cc b/media/filters/audio_renderer_base_unittest.cc
|
| deleted file mode 100644
|
| index ee756f14fed21c3d55b1a650cad800a5799eb9ed..0000000000000000000000000000000000000000
|
| --- a/media/filters/audio_renderer_base_unittest.cc
|
| +++ /dev/null
|
| @@ -1,442 +0,0 @@
|
| -// 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/bind.h"
|
| -#include "base/gtest_prod_util.h"
|
| -#include "base/stl_util.h"
|
| -#include "media/base/data_buffer.h"
|
| -#include "media/base/mock_callback.h"
|
| -#include "media/base/mock_filter_host.h"
|
| -#include "media/base/mock_filters.h"
|
| -#include "media/filters/audio_renderer_base.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using ::testing::_;
|
| -using ::testing::AnyNumber;
|
| -using ::testing::Invoke;
|
| -using ::testing::Return;
|
| -using ::testing::NiceMock;
|
| -using ::testing::StrictMock;
|
| -
|
| -namespace {
|
| -
|
| -class MockAudioSink : public media::AudioRendererSink {
|
| - public:
|
| - MOCK_METHOD2(Initialize, void(const media::AudioParameters& params,
|
| - RenderCallback* callback));
|
| - MOCK_METHOD0(Start, void());
|
| - MOCK_METHOD0(Stop, void());
|
| - MOCK_METHOD1(Pause, void(bool flush));
|
| - MOCK_METHOD0(Play, void());
|
| - MOCK_METHOD1(SetPlaybackRate, void(float rate));
|
| - MOCK_METHOD1(SetVolume, bool(double volume));
|
| - MOCK_METHOD1(GetVolume, void(double* volume));
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -namespace media {
|
| -
|
| -// Constants for distinguishing between muted audio and playing audio when using
|
| -// ConsumeBufferedData().
|
| -static uint8 kMutedAudio = 0x00;
|
| -static uint8 kPlayingAudio = 0x99;
|
| -
|
| -class AudioRendererBaseTest : public ::testing::Test {
|
| - public:
|
| - // Give the decoder some non-garbage media properties.
|
| - AudioRendererBaseTest()
|
| - : renderer_(new AudioRendererBase(new NiceMock<MockAudioSink>())),
|
| - decoder_(new MockAudioDecoder()) {
|
| - renderer_->set_host(&host_);
|
| -
|
| - // Queue all reads from the decoder by default.
|
| - ON_CALL(*decoder_, Read(_))
|
| - .WillByDefault(Invoke(this, &AudioRendererBaseTest::SaveReadCallback));
|
| -
|
| - // Set up audio properties.
|
| - SetSupportedAudioDecoderProperties();
|
| - EXPECT_CALL(*decoder_, bits_per_channel())
|
| - .Times(AnyNumber());
|
| - EXPECT_CALL(*decoder_, channel_layout())
|
| - .Times(AnyNumber());
|
| - EXPECT_CALL(*decoder_, samples_per_second())
|
| - .Times(AnyNumber());
|
| - }
|
| -
|
| - virtual ~AudioRendererBaseTest() {
|
| - renderer_->Stop(NewExpectedClosure());
|
| - }
|
| -
|
| - MOCK_METHOD1(OnSeekComplete, void(PipelineStatus));
|
| - PipelineStatusCB NewSeekCB() {
|
| - return base::Bind(&AudioRendererBaseTest::OnSeekComplete,
|
| - base::Unretained(this));
|
| - }
|
| -
|
| - MOCK_METHOD0(OnUnderflow, void());
|
| - base::Closure NewUnderflowClosure() {
|
| - return base::Bind(&AudioRendererBaseTest::OnUnderflow,
|
| - base::Unretained(this));
|
| - }
|
| -
|
| - void SetSupportedAudioDecoderProperties() {
|
| - ON_CALL(*decoder_, bits_per_channel())
|
| - .WillByDefault(Return(16));
|
| - ON_CALL(*decoder_, channel_layout())
|
| - .WillByDefault(Return(CHANNEL_LAYOUT_MONO));
|
| - ON_CALL(*decoder_, samples_per_second())
|
| - .WillByDefault(Return(44100));
|
| - }
|
| -
|
| - void SetUnsupportedAudioDecoderProperties() {
|
| - ON_CALL(*decoder_, bits_per_channel())
|
| - .WillByDefault(Return(3));
|
| - ON_CALL(*decoder_, channel_layout())
|
| - .WillByDefault(Return(CHANNEL_LAYOUT_UNSUPPORTED));
|
| - ON_CALL(*decoder_, samples_per_second())
|
| - .WillByDefault(Return(0));
|
| - }
|
| -
|
| - void OnAudioTimeCallback(
|
| - base::TimeDelta current_time, base::TimeDelta max_time) {
|
| - CHECK(current_time <= max_time);
|
| - }
|
| -
|
| - AudioRenderer::TimeCB NewAudioTimeClosure() {
|
| - return base::Bind(&AudioRendererBaseTest::OnAudioTimeCallback,
|
| - base::Unretained(this));
|
| - }
|
| -
|
| - void Initialize() {
|
| - renderer_->Initialize(
|
| - decoder_, NewExpectedStatusCB(PIPELINE_OK), NewUnderflowClosure(),
|
| - NewAudioTimeClosure());
|
| - }
|
| -
|
| - void Preroll() {
|
| - // Seek to trigger prerolling.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - renderer_->Seek(base::TimeDelta(), NewSeekCB());
|
| -
|
| - // Fill entire buffer to complete prerolling.
|
| - EXPECT_CALL(*this, OnSeekComplete(PIPELINE_OK));
|
| - DeliverRemainingAudio();
|
| - }
|
| -
|
| - void Play() {
|
| - renderer_->Play(NewExpectedClosure());
|
| - renderer_->SetPlaybackRate(1.0f);
|
| - }
|
| -
|
| - void Seek(base::TimeDelta seek_time) {
|
| - next_timestamp_ = seek_time;
|
| -
|
| - // Seek to trigger prerolling.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - renderer_->Seek(seek_time, NewSeekCB());
|
| -
|
| - // Fill entire buffer to complete prerolling.
|
| - EXPECT_CALL(*this, OnSeekComplete(PIPELINE_OK));
|
| - DeliverRemainingAudio();
|
| - }
|
| -
|
| - // Delivers |size| bytes with value kPlayingAudio to |renderer_|.
|
| - //
|
| - // There must be a pending read callback.
|
| - void FulfillPendingRead(size_t size) {
|
| - CHECK(!read_cb_.is_null());
|
| - scoped_refptr<DataBuffer> buffer(new DataBuffer(size));
|
| - buffer->SetDataSize(size);
|
| - memset(buffer->GetWritableData(), kPlayingAudio, buffer->GetDataSize());
|
| -
|
| - buffer->SetTimestamp(next_timestamp_);
|
| - int64 bps = decoder_->bits_per_channel() * decoder_->samples_per_second();
|
| - buffer->SetDuration(base::TimeDelta::FromMilliseconds(8000 * size / bps));
|
| - next_timestamp_ += buffer->GetDuration();
|
| -
|
| - AudioDecoder::ReadCB read_cb;
|
| - std::swap(read_cb, read_cb_);
|
| - read_cb.Run(buffer);
|
| - }
|
| -
|
| - void AbortPendingRead() {
|
| - AudioDecoder::ReadCB read_cb;
|
| - std::swap(read_cb, read_cb_);
|
| - read_cb.Run(NULL);
|
| - }
|
| -
|
| - // Delivers an end of stream buffer to |renderer_|.
|
| - //
|
| - // There must be a pending read callback.
|
| - void DeliverEndOfStream() {
|
| - FulfillPendingRead(0);
|
| - }
|
| -
|
| - // Delivers bytes until |renderer_|'s internal buffer is full and no longer
|
| - // has pending reads.
|
| - void DeliverRemainingAudio() {
|
| - CHECK(!read_cb_.is_null());
|
| - FulfillPendingRead(bytes_remaining_in_buffer());
|
| - CHECK(read_cb_.is_null());
|
| - }
|
| -
|
| - // Attempts to consume |size| bytes from |renderer_|'s internal buffer,
|
| - // returning true if all |size| bytes were consumed, false if less than
|
| - // |size| bytes were consumed.
|
| - //
|
| - // |muted| is optional and if passed will get set if the byte value of
|
| - // the consumed data is muted audio.
|
| - bool ConsumeBufferedData(uint32 size, bool* muted) {
|
| - scoped_array<uint8> buffer(new uint8[size]);
|
| - uint32 bytes_per_frame = (decoder_->bits_per_channel() / 8) *
|
| - ChannelLayoutToChannelCount(decoder_->channel_layout());
|
| - uint32 requested_frames = size / bytes_per_frame;
|
| - uint32 frames_read = renderer_->FillBuffer(
|
| - buffer.get(), requested_frames, base::TimeDelta());
|
| -
|
| - if (frames_read > 0 && muted) {
|
| - *muted = (buffer[0] == kMutedAudio);
|
| - }
|
| - return (frames_read == requested_frames);
|
| - }
|
| -
|
| - uint32 bytes_buffered() {
|
| - return renderer_->algorithm_->bytes_buffered();
|
| - }
|
| -
|
| - uint32 buffer_capacity() {
|
| - return renderer_->algorithm_->QueueCapacity();
|
| - }
|
| -
|
| - uint32 bytes_remaining_in_buffer() {
|
| - // This can happen if too much data was delivered, in which case the buffer
|
| - // will accept the data but not increase capacity.
|
| - if (bytes_buffered() > buffer_capacity()) {
|
| - return 0;
|
| - }
|
| - return buffer_capacity() - bytes_buffered();
|
| - }
|
| -
|
| - void CallResumeAfterUnderflow() {
|
| - renderer_->ResumeAfterUnderflow(false);
|
| - }
|
| -
|
| - // Fixture members.
|
| - scoped_refptr<AudioRendererBase> renderer_;
|
| - scoped_refptr<MockAudioDecoder> decoder_;
|
| - StrictMock<MockFilterHost> host_;
|
| - AudioDecoder::ReadCB read_cb_;
|
| - base::TimeDelta next_timestamp_;
|
| -
|
| - private:
|
| - void SaveReadCallback(const AudioDecoder::ReadCB& callback) {
|
| - CHECK(read_cb_.is_null()) << "Overlapping reads are not permitted";
|
| - read_cb_ = callback;
|
| - }
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(AudioRendererBaseTest);
|
| -};
|
| -
|
| -TEST_F(AudioRendererBaseTest, Initialize_Failed) {
|
| - SetUnsupportedAudioDecoderProperties();
|
| - renderer_->Initialize(
|
| - decoder_,
|
| - NewExpectedStatusCB(PIPELINE_ERROR_INITIALIZATION_FAILED),
|
| - NewUnderflowClosure(), NewAudioTimeClosure());
|
| -
|
| - // We should have no reads.
|
| - EXPECT_TRUE(read_cb_.is_null());
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Initialize_Successful) {
|
| - renderer_->Initialize(decoder_, NewExpectedStatusCB(PIPELINE_OK),
|
| - NewUnderflowClosure(), NewAudioTimeClosure());
|
| -
|
| - // We should have no reads.
|
| - EXPECT_TRUE(read_cb_.is_null());
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Preroll) {
|
| - Initialize();
|
| - Preroll();
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Play) {
|
| - Initialize();
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Drain internal buffer, we should have a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, EndOfStream) {
|
| - Initialize();
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Drain internal buffer, we should have a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| -
|
| - // Fulfill the read with an end-of-stream packet, we shouldn't report ended
|
| - // nor have a read until we drain the internal buffer.
|
| - DeliverEndOfStream();
|
| - EXPECT_FALSE(renderer_->HasEnded());
|
| -
|
| - // Drain internal buffer, now we should report ended.
|
| - EXPECT_CALL(host_, NotifyEnded());
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| - EXPECT_TRUE(renderer_->HasEnded());
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Underflow) {
|
| - Initialize();
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Drain internal buffer, we should have a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| -
|
| - // Verify the next FillBuffer() call triggers the underflow callback
|
| - // since the decoder hasn't delivered any data after it was drained.
|
| - const size_t kDataSize = 1024;
|
| - EXPECT_CALL(*this, OnUnderflow());
|
| - EXPECT_FALSE(ConsumeBufferedData(kDataSize, NULL));
|
| -
|
| - renderer_->ResumeAfterUnderflow(false);
|
| -
|
| - // Verify after resuming that we're still not getting data.
|
| - //
|
| - // NOTE: FillBuffer() satisfies the read but returns muted audio, which
|
| - // is crazy http://crbug.com/106600
|
| - bool muted = false;
|
| - EXPECT_EQ(0u, bytes_buffered());
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_TRUE(muted);
|
| -
|
| - // Deliver data, we should get non-muted audio.
|
| - DeliverRemainingAudio();
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_FALSE(muted);
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Underflow_EndOfStream) {
|
| - Initialize();
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Drain internal buffer, we should have a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| -
|
| - // Verify the next FillBuffer() call triggers the underflow callback
|
| - // since the decoder hasn't delivered any data after it was drained.
|
| - const size_t kDataSize = 1024;
|
| - EXPECT_CALL(*this, OnUnderflow());
|
| - EXPECT_FALSE(ConsumeBufferedData(kDataSize, NULL));
|
| -
|
| - // Deliver a little bit of data.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - FulfillPendingRead(kDataSize);
|
| -
|
| - // Verify we're getting muted audio during underflow.
|
| - //
|
| - // NOTE: FillBuffer() satisfies the read but returns muted audio, which
|
| - // is crazy http://crbug.com/106600
|
| - bool muted = false;
|
| - EXPECT_EQ(kDataSize, bytes_buffered());
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_TRUE(muted);
|
| -
|
| - // Now deliver end of stream, we should get our little bit of data back.
|
| - DeliverEndOfStream();
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_EQ(kDataSize, bytes_buffered());
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_FALSE(muted);
|
| -
|
| - // Deliver another end of stream buffer and attempt to read to make sure
|
| - // we're truly at the end of stream.
|
| - //
|
| - // TODO(scherkus): fix AudioRendererBase and AudioRendererAlgorithmBase to
|
| - // stop reading after receiving an end of stream buffer. It should have also
|
| - // called NotifyEnded() http://crbug.com/106641
|
| - DeliverEndOfStream();
|
| - EXPECT_CALL(host_, NotifyEnded());
|
| -
|
| - EXPECT_CALL(host_, GetTime()).WillOnce(Return(base::TimeDelta()));
|
| - EXPECT_FALSE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_FALSE(muted);
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, Underflow_ResumeFromCallback) {
|
| - Initialize();
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Drain internal buffer, we should have a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| -
|
| - // Verify the next FillBuffer() call triggers the underflow callback
|
| - // since the decoder hasn't delivered any data after it was drained.
|
| - const size_t kDataSize = 1024;
|
| - EXPECT_CALL(*this, OnUnderflow())
|
| - .WillOnce(Invoke(this, &AudioRendererBaseTest::CallResumeAfterUnderflow));
|
| - EXPECT_FALSE(ConsumeBufferedData(kDataSize, NULL));
|
| -
|
| - // Verify after resuming that we're still not getting data.
|
| - bool muted = false;
|
| - EXPECT_EQ(0u, bytes_buffered());
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_TRUE(muted);
|
| -
|
| - // Deliver data, we should get non-muted audio.
|
| - DeliverRemainingAudio();
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(kDataSize, &muted));
|
| - EXPECT_FALSE(muted);
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, AbortPendingRead_Preroll) {
|
| - Initialize();
|
| -
|
| - // Seek to trigger prerolling.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - renderer_->Seek(base::TimeDelta(), NewSeekCB());
|
| -
|
| - // Simulate the decoder aborting the pending read.
|
| - EXPECT_CALL(*this, OnSeekComplete(PIPELINE_OK));
|
| - AbortPendingRead();
|
| -
|
| - // Seek to trigger another preroll and verify it completes
|
| - // normally.
|
| - Seek(base::TimeDelta::FromSeconds(1));
|
| -
|
| - ASSERT_TRUE(read_cb_.is_null());
|
| -}
|
| -
|
| -TEST_F(AudioRendererBaseTest, AbortPendingRead_Pause) {
|
| - Initialize();
|
| -
|
| - Preroll();
|
| - Play();
|
| -
|
| - // Partially drain internal buffer so we get a pending read.
|
| - EXPECT_CALL(*decoder_, Read(_));
|
| - EXPECT_TRUE(ConsumeBufferedData(bytes_buffered() / 2, NULL));
|
| -
|
| - renderer_->Pause(NewExpectedClosure());
|
| -
|
| - AbortPendingRead();
|
| -
|
| - Seek(base::TimeDelta::FromSeconds(1));
|
| -}
|
| -
|
| -} // namespace media
|
|
|