summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-01 23:15:21 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-01 23:15:21 +0000
commite8ba615ab61359130553c7dd6419c331be5c49ad (patch)
tree9ed8fb65f7ee9363ce4ea3d6d9085398ae1c97f0 /media
parent5a77c1fce902db54e3a12aa03bc1749a3dcf7817 (diff)
downloadchromium_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.cc5
-rw-r--r--media/filters/audio_renderer_base_unittest.cc140
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