diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 23:15:21 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-01 23:15:21 +0000 |
commit | e8ba615ab61359130553c7dd6419c331be5c49ad (patch) | |
tree | 9ed8fb65f7ee9363ce4ea3d6d9085398ae1c97f0 /media | |
parent | 5a77c1fce902db54e3a12aa03bc1749a3dcf7817 (diff) | |
download | chromium_src-e8ba615ab61359130553c7dd6419c331be5c49ad.zip chromium_src-e8ba615ab61359130553c7dd6419c331be5c49ad.tar.gz chromium_src-e8ba615ab61359130553c7dd6419c331be5c49ad.tar.bz2 |
Adding transition to kPlaying when end of stream is reached during an underflow.
BUG=92254
TEST=AudioRendererBaseTest::Underflow_EndOfStream
Review URL: http://codereview.chromium.org/8430015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108191 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/audio_renderer_base.cc | 5 | ||||
-rw-r--r-- | media/filters/audio_renderer_base_unittest.cc | 140 |
2 files changed, 114 insertions, 31 deletions
diff --git a/media/filters/audio_renderer_base.cc b/media/filters/audio_renderer_base.cc index 2d32d98..2528a70 100644 --- a/media/filters/audio_renderer_base.cc +++ b/media/filters/audio_renderer_base.cc @@ -162,6 +162,11 @@ void AudioRendererBase::ConsumeAudioSamples(scoped_refptr<Buffer> buffer_in) { // discard decoded audio data until we reach our desired seek timestamp. if (buffer_in->IsEndOfStream()) { recieved_end_of_stream_ = true; + + // Transition to kPlaying if we are currently handling an underflow since no + // more data will be arriving. + if (state_ == kUnderflow || state_ == kRebuffering) + state_ = kPlaying; } else if (state_ == kSeeking && !buffer_in->IsEndOfStream() && (buffer_in->GetTimestamp() + buffer_in->GetDuration()) < seek_timestamp_) { diff --git a/media/filters/audio_renderer_base_unittest.cc b/media/filters/audio_renderer_base_unittest.cc index 76b1915..5682d37 100644 --- a/media/filters/audio_renderer_base_unittest.cc +++ b/media/filters/audio_renderer_base_unittest.cc @@ -42,6 +42,8 @@ class MockAudioRendererBase : public AudioRendererBase { private: FRIEND_TEST(AudioRendererBaseTest, OneCompleteReadCycle); FRIEND_TEST(AudioRendererBaseTest, Underflow); + FRIEND_TEST(AudioRendererBaseTest, Underflow_EndOfStream); + friend class AudioRendererBaseTest; DISALLOW_COPY_AND_ASSIGN(MockAudioRendererBase); }; @@ -88,18 +90,49 @@ class AudioRendererBaseTest : public ::testing::Test { 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 WriteUntilNoPendingReads(int data_size, uint8 value, uint32* bytes_buffered) { while (pending_reads_ > 0) { - scoped_refptr<DataBuffer> buffer(new DataBuffer(data_size)); - buffer->SetDataSize(data_size); - memset(buffer->GetWritableData(), value, buffer->GetDataSize()); --pending_reads_; *bytes_buffered += data_size; - decoder_->ConsumeAudioSamplesForTest(buffer); + decoder_->ConsumeAudioSamplesForTest(CreateBuffer(data_size, value)); + } + } + + 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 ExpectUnderflow(uint32 data_size, int checkpoint_value) { + scoped_array<uint8> buffer(new uint8[data_size]); + base::TimeDelta playback_delay(base::TimeDelta::FromSeconds(1)); + + 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); + } + + protected: static const size_t kMaxQueueSize; @@ -283,41 +316,25 @@ TEST_F(AudioRendererBaseTest, Underflow) { EXPECT_EQ(1.0f, renderer_->GetPlaybackRate()); // Consume all of the data passed into the renderer. - uint8 buffer[kDataSize]; - while (bytes_buffered > 0) { - EXPECT_EQ(kDataSize, - renderer_->FillBuffer(buffer, kDataSize, playback_delay, false)); - EXPECT_EQ(1, buffer[0]); - bytes_buffered -= kDataSize; - } + 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. - EXPECT_CALL(*this, OnUnderflow()); - EXPECT_CALL(*renderer_, CheckPoint(1)); - EXPECT_EQ(0u, renderer_->FillBuffer(buffer, kDataSize, playback_delay, - false)); - renderer_->CheckPoint(1); + ExpectUnderflow(kDataSize, 1); // Verify that zeroed out buffers are being returned during the underflow. - for (int i = 0; i < 5; ++i) { - EXPECT_EQ(kDataSize, - renderer_->FillBuffer(buffer, kDataSize, playback_delay, false)); - EXPECT_EQ(0, buffer[0]); - } + uint32 zeros_to_read = 5 * kDataSize; + ConsumeBufferedData(kDataSize, 0, &zeros_to_read); renderer_->ResumeAfterUnderflow(false); // Verify we are still getting zeroed out buffers since no new data has been // pushed to the renderer. - for (int i = 0; i < 5; ++i) { - EXPECT_EQ(kDataSize, - renderer_->FillBuffer(buffer, kDataSize, playback_delay, false)); - EXPECT_EQ(0, buffer[0]); - } + zeros_to_read = 5 * kDataSize; + ConsumeBufferedData(kDataSize, 0, &zeros_to_read); // Satisfy all pending read requests. WriteUntilNoPendingReads(kDataSize, 2, &bytes_buffered); @@ -325,12 +342,73 @@ TEST_F(AudioRendererBaseTest, Underflow) { EXPECT_GE(bytes_buffered, bytes_for_preroll); // Verify that we are now getting the new data. - while (bytes_buffered > 0) { - EXPECT_EQ(kDataSize, - renderer_->FillBuffer(buffer, kDataSize, playback_delay, false)); - EXPECT_EQ(2, buffer[0]); - bytes_buffered -= kDataSize; + ConsumeBufferedData(kDataSize, 2, &bytes_buffered); +} + + +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); } } // namespace media |