Commit e8ba615a authored by acolwell@chromium.org's avatar acolwell@chromium.org

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
parent 5a77c1fc
...@@ -162,6 +162,11 @@ void AudioRendererBase::ConsumeAudioSamples(scoped_refptr<Buffer> buffer_in) { ...@@ -162,6 +162,11 @@ void AudioRendererBase::ConsumeAudioSamples(scoped_refptr<Buffer> buffer_in) {
// discard decoded audio data until we reach our desired seek timestamp. // discard decoded audio data until we reach our desired seek timestamp.
if (buffer_in->IsEndOfStream()) { if (buffer_in->IsEndOfStream()) {
recieved_end_of_stream_ = true; 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() && } else if (state_ == kSeeking && !buffer_in->IsEndOfStream() &&
(buffer_in->GetTimestamp() + buffer_in->GetDuration()) < (buffer_in->GetTimestamp() + buffer_in->GetDuration()) <
seek_timestamp_) { seek_timestamp_) {
......
...@@ -42,6 +42,8 @@ class MockAudioRendererBase : public AudioRendererBase { ...@@ -42,6 +42,8 @@ class MockAudioRendererBase : public AudioRendererBase {
private: private:
FRIEND_TEST(AudioRendererBaseTest, OneCompleteReadCycle); FRIEND_TEST(AudioRendererBaseTest, OneCompleteReadCycle);
FRIEND_TEST(AudioRendererBaseTest, Underflow); FRIEND_TEST(AudioRendererBaseTest, Underflow);
FRIEND_TEST(AudioRendererBaseTest, Underflow_EndOfStream);
friend class AudioRendererBaseTest;
DISALLOW_COPY_AND_ASSIGN(MockAudioRendererBase); DISALLOW_COPY_AND_ASSIGN(MockAudioRendererBase);
}; };
...@@ -88,18 +90,49 @@ class AudioRendererBaseTest : public ::testing::Test { ...@@ -88,18 +90,49 @@ class AudioRendererBaseTest : public ::testing::Test {
base::Unretained(this)); 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, void WriteUntilNoPendingReads(int data_size, uint8 value,
uint32* bytes_buffered) { uint32* bytes_buffered) {
while (pending_reads_ > 0) { while (pending_reads_ > 0) {
scoped_refptr<DataBuffer> buffer(new DataBuffer(data_size));
buffer->SetDataSize(data_size);
memset(buffer->GetWritableData(), value, buffer->GetDataSize());
--pending_reads_; --pending_reads_;
*bytes_buffered += data_size; *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: protected:
static const size_t kMaxQueueSize; static const size_t kMaxQueueSize;
...@@ -283,41 +316,25 @@ TEST_F(AudioRendererBaseTest, Underflow) { ...@@ -283,41 +316,25 @@ TEST_F(AudioRendererBaseTest, Underflow) {
EXPECT_EQ(1.0f, renderer_->GetPlaybackRate()); EXPECT_EQ(1.0f, renderer_->GetPlaybackRate());
// Consume all of the data passed into the renderer. // Consume all of the data passed into the renderer.
uint8 buffer[kDataSize]; ConsumeBufferedData(kDataSize, 1, &bytes_buffered);
while (bytes_buffered > 0) {
EXPECT_EQ(kDataSize,
renderer_->FillBuffer(buffer, kDataSize, playback_delay, false));
EXPECT_EQ(1, buffer[0]);
bytes_buffered -= kDataSize;
}
// Make sure there are read requests pending. // Make sure there are read requests pending.
EXPECT_GT(pending_reads_, 0u); EXPECT_GT(pending_reads_, 0u);
// Verify the next FillBuffer() call triggers calls the underflow callback // Verify the next FillBuffer() call triggers calls the underflow callback
// since the queue is empty. // since the queue is empty.
EXPECT_CALL(*this, OnUnderflow()); ExpectUnderflow(kDataSize, 1);
EXPECT_CALL(*renderer_, CheckPoint(1));
EXPECT_EQ(0u, renderer_->FillBuffer(buffer, kDataSize, playback_delay,
false));
renderer_->CheckPoint(1);
// Verify that zeroed out buffers are being returned during the underflow. // Verify that zeroed out buffers are being returned during the underflow.
for (int i = 0; i < 5; ++i) { uint32 zeros_to_read = 5 * kDataSize;
EXPECT_EQ(kDataSize, ConsumeBufferedData(kDataSize, 0, &zeros_to_read);
renderer_->FillBuffer(buffer, kDataSize, playback_delay, false));
EXPECT_EQ(0, buffer[0]);
}
renderer_->ResumeAfterUnderflow(false); renderer_->ResumeAfterUnderflow(false);
// Verify we are still getting zeroed out buffers since no new data has been // Verify we are still getting zeroed out buffers since no new data has been
// pushed to the renderer. // pushed to the renderer.
for (int i = 0; i < 5; ++i) { zeros_to_read = 5 * kDataSize;
EXPECT_EQ(kDataSize, ConsumeBufferedData(kDataSize, 0, &zeros_to_read);
renderer_->FillBuffer(buffer, kDataSize, playback_delay, false));
EXPECT_EQ(0, buffer[0]);
}
// Satisfy all pending read requests. // Satisfy all pending read requests.
WriteUntilNoPendingReads(kDataSize, 2, &bytes_buffered); WriteUntilNoPendingReads(kDataSize, 2, &bytes_buffered);
...@@ -325,12 +342,73 @@ TEST_F(AudioRendererBaseTest, Underflow) { ...@@ -325,12 +342,73 @@ TEST_F(AudioRendererBaseTest, Underflow) {
EXPECT_GE(bytes_buffered, bytes_for_preroll); EXPECT_GE(bytes_buffered, bytes_for_preroll);
// Verify that we are now getting the new data. // Verify that we are now getting the new data.
while (bytes_buffered > 0) { ConsumeBufferedData(kDataSize, 2, &bytes_buffered);
EXPECT_EQ(kDataSize, }
renderer_->FillBuffer(buffer, kDataSize, playback_delay, false));
EXPECT_EQ(2, buffer[0]);
bytes_buffered -= kDataSize; 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 } // namespace media
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment