| 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
|
| index 6f53c0c7f1bb99f5607d857f0f286bff4310d9d8..964686eb1a7701274d1d1b3f273898fff71544c5 100644
|
| --- a/media/filters/audio_renderer_base_unittest.cc
|
| +++ b/media/filters/audio_renderer_base_unittest.cc
|
| @@ -14,14 +14,17 @@
|
|
|
| using ::testing::_;
|
| using ::testing::AnyNumber;
|
| -using ::testing::InSequence;
|
| using ::testing::Invoke;
|
| -using ::testing::NotNull;
|
| using ::testing::Return;
|
| using ::testing::StrictMock;
|
|
|
| namespace media {
|
|
|
| +// Constants for distinguishing between muted audio and playing audio when using
|
| +// ConsumeBufferedData().
|
| +static uint8 kMutedAudio = 0x00;
|
| +static uint8 kPlayingAudio = 0x99;
|
| +
|
| // Mocked subclass of AudioRendererBase for testing purposes.
|
| class MockAudioRendererBase : public AudioRendererBase {
|
| public:
|
| @@ -36,15 +39,7 @@ class MockAudioRendererBase : public AudioRendererBase {
|
| MOCK_METHOD3(OnInitialize, bool(int, ChannelLayout, int));
|
| MOCK_METHOD0(OnStop, void());
|
|
|
| - // Used for verifying check points during tests.
|
| - MOCK_METHOD1(CheckPoint, void(int id));
|
| -
|
| private:
|
| - FRIEND_TEST_ALL_PREFIXES(AudioRendererBaseTest, OneCompleteReadCycle);
|
| - FRIEND_TEST_ALL_PREFIXES(AudioRendererBaseTest, Underflow);
|
| - FRIEND_TEST_ALL_PREFIXES(AudioRendererBaseTest, Underflow_EndOfStream);
|
| - friend class AudioRendererBaseTest;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(MockAudioRendererBase);
|
| };
|
|
|
| @@ -53,13 +48,12 @@ class AudioRendererBaseTest : public ::testing::Test {
|
| // Give the decoder some non-garbage media properties.
|
| AudioRendererBaseTest()
|
| : renderer_(new MockAudioRendererBase()),
|
| - decoder_(new MockAudioDecoder()),
|
| - pending_reads_(0) {
|
| + decoder_(new MockAudioDecoder()) {
|
| renderer_->set_host(&host_);
|
|
|
| - // Queue all reads from the decoder.
|
| - EXPECT_CALL(*decoder_, ProduceAudioSamples(_))
|
| - .WillRepeatedly(Invoke(this, &AudioRendererBaseTest::EnqueueCallback));
|
| + // Queue all reads from the decoder by default.
|
| + ON_CALL(*decoder_, Read(_))
|
| + .WillByDefault(Invoke(this, &AudioRendererBaseTest::SaveReadCallback));
|
|
|
| // Set up audio properties.
|
| ON_CALL(*decoder_, bits_per_channel())
|
| @@ -78,337 +72,253 @@ class AudioRendererBaseTest : public ::testing::Test {
|
| }
|
|
|
| virtual ~AudioRendererBaseTest() {
|
| - // Expect a call into the subclass.
|
| EXPECT_CALL(*renderer_, OnStop());
|
| renderer_->Stop(NewExpectedClosure());
|
| }
|
|
|
| - MOCK_METHOD0(OnUnderflow, void());
|
| + MOCK_METHOD1(OnSeekComplete, void(PipelineStatus));
|
| + FilterStatusCB NewSeekCB() {
|
| + return base::Bind(&AudioRendererBaseTest::OnSeekComplete,
|
| + base::Unretained(this));
|
| + }
|
|
|
| + MOCK_METHOD0(OnUnderflow, void());
|
| base::Closure NewUnderflowClosure() {
|
| return base::Bind(&AudioRendererBaseTest::OnUnderflow,
|
| base::Unretained(this));
|
| }
|
|
|
| - scoped_refptr<DataBuffer> CreateBuffer(int data_size, uint8 value) {
|
| - scoped_refptr<DataBuffer> buffer(new DataBuffer(data_size));
|
| - buffer->SetDataSize(data_size);
|
| - memset(buffer->GetWritableData(), value, buffer->GetDataSize());
|
| - return buffer;
|
| + void Initialize() {
|
| + EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| + .WillOnce(Return(true));
|
| + renderer_->Initialize(
|
| + decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
| }
|
|
|
| - void WriteUntilNoPendingReads(int data_size, uint8 value,
|
| - uint32* bytes_buffered) {
|
| - while (pending_reads_ > 0) {
|
| - --pending_reads_;
|
| - *bytes_buffered += data_size;
|
| - decoder_->ConsumeAudioSamplesForTest(CreateBuffer(data_size, value));
|
| - }
|
| + 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 ConsumeBufferedData(uint32 data_size, uint8 expected_value,
|
| - uint32* bytes_buffered) {
|
| - DCHECK(bytes_buffered);
|
| - DCHECK_GT(*bytes_buffered, 0u);
|
| -
|
| - base::TimeDelta playback_delay(base::TimeDelta::FromSeconds(1));
|
| - scoped_array<uint8> buffer(new uint8[data_size]);
|
| - while (*bytes_buffered > 0) {
|
| - EXPECT_EQ(data_size, renderer_->FillBuffer(buffer.get(), data_size,
|
| - playback_delay, false));
|
| - EXPECT_EQ(expected_value, buffer[0]);
|
| - *bytes_buffered -= data_size;
|
| - }
|
| + void Play() {
|
| + renderer_->Play(NewExpectedClosure());
|
| + renderer_->SetPlaybackRate(1.0f);
|
| + }
|
| +
|
| + // 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());
|
| +
|
| + AudioDecoder::ReadCB read_cb;
|
| + std::swap(read_cb, read_cb_);
|
| + read_cb.Run(buffer);
|
| + }
|
| +
|
| + // 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());
|
| }
|
|
|
| - void ExpectUnderflow(uint32 data_size, int checkpoint_value) {
|
| - scoped_array<uint8> buffer(new uint8[data_size]);
|
| - base::TimeDelta playback_delay(base::TimeDelta::FromSeconds(1));
|
| + // 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_read = renderer_->FillBuffer(buffer.get(), size,
|
| + base::TimeDelta(), true);
|
| + if (bytes_read > 0 && muted) {
|
| + *muted = (buffer[0] == kMutedAudio);
|
| + }
|
| + return (bytes_read == size);
|
| + }
|
|
|
| - EXPECT_CALL(*this, OnUnderflow());
|
| - EXPECT_CALL(*renderer_, CheckPoint(checkpoint_value));
|
| - EXPECT_EQ(0u, renderer_->FillBuffer(buffer.get(), data_size, playback_delay,
|
| - false));
|
| - renderer_->CheckPoint(checkpoint_value);
|
| + uint32 bytes_buffered() {
|
| + return renderer_->algorithm_->QueueSize();
|
| }
|
|
|
| + uint32 buffer_capacity() {
|
| + return renderer_->algorithm_->QueueCapacity();
|
| + }
|
|
|
| - protected:
|
| - static const size_t kMaxQueueSize;
|
| + 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();
|
| + }
|
|
|
| // Fixture members.
|
| scoped_refptr<MockAudioRendererBase> renderer_;
|
| scoped_refptr<MockAudioDecoder> decoder_;
|
| StrictMock<MockFilterHost> host_;
|
| -
|
| - // Number of asynchronous read requests sent to |decoder_|.
|
| - size_t pending_reads_;
|
| + AudioDecoder::ReadCB read_cb_;
|
|
|
| private:
|
| - void EnqueueCallback(scoped_refptr<Buffer> buffer) {
|
| - ++pending_reads_;
|
| + void SaveReadCallback(const AudioDecoder::ReadCB& callback) {
|
| + CHECK(read_cb_.is_null()) << "Overlapping reads are not permitted";
|
| + read_cb_ = callback;
|
| }
|
|
|
| DISALLOW_COPY_AND_ASSIGN(AudioRendererBaseTest);
|
| };
|
|
|
| -const size_t AudioRendererBaseTest::kMaxQueueSize = 1u;
|
| -
|
| TEST_F(AudioRendererBaseTest, Initialize_Failed) {
|
| - InSequence s;
|
| -
|
| - // Our subclass will fail when asked to initialize.
|
| EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| .WillOnce(Return(false));
|
| -
|
| - // We expect to receive an error.
|
| EXPECT_CALL(host_, SetError(PIPELINE_ERROR_INITIALIZATION_FAILED));
|
| -
|
| - // Initialize, we expect to have no reads.
|
| renderer_->Initialize(decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
| - EXPECT_EQ(0u, pending_reads_);
|
| +
|
| + // We should have no reads.
|
| + EXPECT_TRUE(read_cb_.is_null());
|
| }
|
|
|
| TEST_F(AudioRendererBaseTest, Initialize_Successful) {
|
| - InSequence s;
|
| -
|
| - // Then our subclass will be asked to initialize.
|
| EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| .WillOnce(Return(true));
|
| -
|
| - // Initialize, we shouldn't have any reads.
|
| renderer_->Initialize(decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
|
|
| - EXPECT_EQ(0u, pending_reads_);
|
| -
|
| - // Now seek to trigger prerolling, verifying the callback hasn't been
|
| - // executed yet.
|
| - EXPECT_CALL(*renderer_, CheckPoint(0));
|
| - renderer_->Seek(base::TimeDelta(), NewExpectedStatusCB(PIPELINE_OK));
|
| - EXPECT_EQ(kMaxQueueSize, pending_reads_);
|
| - renderer_->CheckPoint(0);
|
| -
|
| - // Now satisfy the read requests. Our callback should be executed after
|
| - // exiting this loop.
|
| - while (pending_reads_) {
|
| - scoped_refptr<DataBuffer> buffer(new DataBuffer(1024));
|
| - buffer->SetDataSize(1024);
|
| - --pending_reads_;
|
| - decoder_->ConsumeAudioSamplesForTest(buffer);
|
| - }
|
| + // We should have no reads.
|
| + EXPECT_TRUE(read_cb_.is_null());
|
| }
|
|
|
| -TEST_F(AudioRendererBaseTest, OneCompleteReadCycle) {
|
| - InSequence s;
|
| -
|
| - // Then our subclass will be asked to initialize.
|
| - EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| - .WillOnce(Return(true));
|
| -
|
| - // Initialize, we shouldn't have any reads.
|
| - renderer_->Initialize(decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
| - EXPECT_EQ(0u, pending_reads_);
|
| -
|
| - // Now seek to trigger prerolling, verifying the callback hasn't been
|
| - // executed yet.
|
| - EXPECT_CALL(*renderer_, CheckPoint(0));
|
| - renderer_->Seek(base::TimeDelta(), NewExpectedStatusCB(PIPELINE_OK));
|
| - EXPECT_EQ(kMaxQueueSize, pending_reads_);
|
| - renderer_->CheckPoint(0);
|
| -
|
| - // Now satisfy the read requests. Our callback should be executed after
|
| - // exiting this loop.
|
| - const uint32 kDataSize = 1024;
|
| - uint32 bytes_buffered = 0;
|
| -
|
| - WriteUntilNoPendingReads(kDataSize, 1, &bytes_buffered);
|
| -
|
| - // Then set the renderer to play state.
|
| - renderer_->Play(NewExpectedClosure());
|
| - renderer_->SetPlaybackRate(1.0f);
|
| - EXPECT_EQ(1.0f, renderer_->GetPlaybackRate());
|
| -
|
| - // Then flush the data in the renderer by reading from it.
|
| - uint8 buffer[kDataSize];
|
| - for (size_t i = 0; i < kMaxQueueSize; ++i) {
|
| - EXPECT_EQ(kDataSize,
|
| - renderer_->FillBuffer(buffer, kDataSize,
|
| - base::TimeDelta(), true));
|
| - bytes_buffered -= kDataSize;
|
| - }
|
| +TEST_F(AudioRendererBaseTest, Preroll) {
|
| + Initialize();
|
| + Preroll();
|
| +}
|
|
|
| - // Make sure the read request queue is full.
|
| - EXPECT_EQ(kMaxQueueSize, pending_reads_);
|
| +TEST_F(AudioRendererBaseTest, Play) {
|
| + Initialize();
|
| + Preroll();
|
| + Play();
|
|
|
| - // Fulfill the read with an end-of-stream packet.
|
| - scoped_refptr<DataBuffer> last_buffer(new DataBuffer(0));
|
| - decoder_->ConsumeAudioSamplesForTest(last_buffer);
|
| - --pending_reads_;
|
| + // Drain internal buffer, we should have a pending read.
|
| + EXPECT_CALL(*decoder_, Read(_));
|
| + EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| +}
|
|
|
| - // We shouldn't report ended until all data has been flushed out.
|
| - EXPECT_FALSE(renderer_->HasEnded());
|
| +TEST_F(AudioRendererBaseTest, EndOfStream) {
|
| + Initialize();
|
| + Preroll();
|
| + Play();
|
|
|
| - // We should have one less read request in the queue.
|
| - EXPECT_EQ(kMaxQueueSize - 1, pending_reads_);
|
| -
|
| - // Flush the entire internal buffer and verify NotifyEnded() isn't called
|
| - // right away.
|
| - EXPECT_CALL(*renderer_, CheckPoint(1));
|
| - EXPECT_EQ(0u, bytes_buffered % kDataSize);
|
| - while (bytes_buffered > 0) {
|
| - EXPECT_EQ(kDataSize,
|
| - renderer_->FillBuffer(buffer, kDataSize,
|
| - base::TimeDelta(), true));
|
| - bytes_buffered -= kDataSize;
|
| - }
|
| + // Drain internal buffer, we should have a pending read.
|
| + EXPECT_CALL(*decoder_, Read(_));
|
| + EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
|
|
| - // Although we've emptied the buffer, we don't consider ourselves ended until
|
| - // we request another buffer. This way we know the last of the audio has
|
| - // played.
|
| + // 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());
|
| - renderer_->CheckPoint(1);
|
|
|
| - // Do an additional read to trigger NotifyEnded().
|
| + // Drain internal buffer, now we should report ended.
|
| EXPECT_CALL(host_, NotifyEnded());
|
| - EXPECT_EQ(0u, renderer_->FillBuffer(buffer, kDataSize,
|
| - base::TimeDelta(), true));
|
| -
|
| - // We should now report ended.
|
| + EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
| EXPECT_TRUE(renderer_->HasEnded());
|
| -
|
| - // Further reads should return muted audio and not notify any more.
|
| - EXPECT_EQ(0u, renderer_->FillBuffer(buffer, kDataSize,
|
| - base::TimeDelta(), true));
|
| }
|
|
|
| TEST_F(AudioRendererBaseTest, Underflow) {
|
| - InSequence s;
|
| -
|
| - base::TimeDelta playback_delay(base::TimeDelta::FromSeconds(1));
|
| -
|
| - // Then our subclass will be asked to initialize.
|
| - EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| - .WillOnce(Return(true));
|
| -
|
| - // Initialize, we shouldn't have any reads.
|
| - renderer_->Initialize(decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
| - EXPECT_EQ(0u, pending_reads_);
|
| -
|
| - // Now seek to trigger prerolling, verifying the callback hasn't been
|
| - // executed yet.
|
| - EXPECT_CALL(*renderer_, CheckPoint(0));
|
| - renderer_->Seek(base::TimeDelta(), NewExpectedStatusCB(PIPELINE_OK));
|
| - EXPECT_EQ(kMaxQueueSize, pending_reads_);
|
| - renderer_->CheckPoint(0);
|
| -
|
| - // Now satisfy the read requests. Our callback should be executed after
|
| - // exiting this loop.
|
| - const uint32 kDataSize = 1024;
|
| - uint32 bytes_buffered = 0;
|
| -
|
| - WriteUntilNoPendingReads(kDataSize, 1, &bytes_buffered);
|
| + Initialize();
|
| + Preroll();
|
| + Play();
|
|
|
| - uint32 bytes_for_preroll = bytes_buffered;
|
| + // Drain internal buffer, we should have a pending read.
|
| + EXPECT_CALL(*decoder_, Read(_));
|
| + EXPECT_TRUE(ConsumeBufferedData(bytes_buffered(), NULL));
|
|
|
| - // Then set the renderer to play state.
|
| - renderer_->Play(NewExpectedClosure());
|
| - renderer_->SetPlaybackRate(1.0f);
|
| - EXPECT_EQ(1.0f, renderer_->GetPlaybackRate());
|
| -
|
| - // Consume all of the data passed into the renderer.
|
| - ConsumeBufferedData(kDataSize, 1, &bytes_buffered);
|
| -
|
| - // Make sure there are read requests pending.
|
| - EXPECT_GT(pending_reads_, 0u);
|
| -
|
| - // Verify the next FillBuffer() call triggers calls the underflow callback
|
| - // since the queue is empty.
|
| - ExpectUnderflow(kDataSize, 1);
|
| -
|
| - // Verify that zeroed out buffers are being returned during the underflow.
|
| - uint32 zeros_to_read = 5 * kDataSize;
|
| - ConsumeBufferedData(kDataSize, 0, &zeros_to_read);
|
| + // 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 we are still getting zeroed out buffers since no new data has been
|
| - // pushed to the renderer.
|
| - zeros_to_read = 5 * kDataSize;
|
| - ConsumeBufferedData(kDataSize, 0, &zeros_to_read);
|
| -
|
| - // Satisfy all pending read requests.
|
| - WriteUntilNoPendingReads(kDataSize, 2, &bytes_buffered);
|
| -
|
| - EXPECT_GE(bytes_buffered, bytes_for_preroll);
|
| -
|
| - // Verify that we are now getting the new data.
|
| - ConsumeBufferedData(kDataSize, 2, &bytes_buffered);
|
| + // 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) {
|
| - InSequence s;
|
| -
|
| - base::TimeDelta playback_delay(base::TimeDelta::FromSeconds(1));
|
| -
|
| - // Then our subclass will be asked to initialize.
|
| - EXPECT_CALL(*renderer_, OnInitialize(_, _, _))
|
| - .WillOnce(Return(true));
|
| -
|
| - // Initialize, we shouldn't have any reads.
|
| - renderer_->Initialize(decoder_, NewExpectedClosure(), NewUnderflowClosure());
|
| - EXPECT_EQ(0u, pending_reads_);
|
| -
|
| - // Now seek to trigger prerolling, verifying the callback hasn't been
|
| - // executed yet.
|
| - EXPECT_CALL(*renderer_, CheckPoint(0));
|
| - renderer_->Seek(base::TimeDelta(), NewExpectedStatusCB(PIPELINE_OK));
|
| - EXPECT_EQ(kMaxQueueSize, pending_reads_);
|
| - renderer_->CheckPoint(0);
|
| -
|
| - // Now satisfy the read requests. Our callback should be executed after
|
| - // exiting this loop.
|
| - const uint32 kDataSize = 1024;
|
| - uint32 bytes_buffered = 0;
|
| -
|
| - WriteUntilNoPendingReads(kDataSize, 1, &bytes_buffered);
|
| -
|
| - // Then set the renderer to play state.
|
| - renderer_->Play(NewExpectedClosure());
|
| - renderer_->SetPlaybackRate(1.0f);
|
| - EXPECT_EQ(1.0f, renderer_->GetPlaybackRate());
|
| -
|
| - // Consume all of the data passed into the renderer.
|
| - ConsumeBufferedData(kDataSize, 1, &bytes_buffered);
|
| -
|
| - // Make sure there are read requests pending.
|
| - EXPECT_GT(pending_reads_, 0u);
|
| -
|
| - // Verify the next FillBuffer() call triggers calls the underflow callback
|
| - // since the queue is empty.
|
| - ExpectUnderflow(kDataSize, 1);
|
| -
|
| - DCHECK_GE(pending_reads_, 2u);
|
| -
|
| - // Write a buffer.
|
| - bytes_buffered += kDataSize;
|
| - --pending_reads_;
|
| - decoder_->ConsumeAudioSamplesForTest(CreateBuffer(kDataSize, 3));
|
| -
|
| - // Verify we are getting zeroed out buffers since we haven't pushed enough
|
| - // data to satisfy preroll.
|
| - uint32 zeros_to_read = 5 * kDataSize;
|
| - ConsumeBufferedData(kDataSize, 0, &zeros_to_read);
|
| -
|
| - // Send end of stream buffers for all pending reads.
|
| - while (pending_reads_ > 0) {
|
| - scoped_refptr<DataBuffer> buffer(new DataBuffer(0));
|
| - --pending_reads_;
|
| - decoder_->ConsumeAudioSamplesForTest(buffer);
|
| - }
|
| -
|
| - // Verify that we are now getting the new data.
|
| - ConsumeBufferedData(kDataSize, 3, &bytes_buffered);
|
| + 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_FALSE(ConsumeBufferedData(kDataSize, &muted));
|
| + EXPECT_FALSE(muted);
|
| }
|
|
|
| } // namespace media
|
|
|