diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 20:01:04 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-01 20:01:04 +0000 |
commit | 12ba0bb19c538bb67b82b27b42b3fcbe8cd23434 (patch) | |
tree | dfba9dad234ab748f059421cb8fc56601860f33c /media | |
parent | ae6e53f30725b7e375caf9e377fed4e3e112494a (diff) | |
download | chromium_src-12ba0bb19c538bb67b82b27b42b3fcbe8cd23434.zip chromium_src-12ba0bb19c538bb67b82b27b42b3fcbe8cd23434.tar.gz chromium_src-12ba0bb19c538bb67b82b27b42b3fcbe8cd23434.tar.bz2 |
Fix ChunkDemuxer end of stream tracking during canceled seeks.
BUG=152595
Review URL: https://codereview.chromium.org/11013004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159540 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/chunk_demuxer.cc | 11 | ||||
-rw-r--r-- | media/filters/chunk_demuxer_unittest.cc | 98 |
2 files changed, 83 insertions, 26 deletions
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 03b18e7..77953b9 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -263,12 +263,13 @@ ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config) } void ChunkDemuxerStream::StartWaitingForSeek() { - DVLOG(1) << "StartWaitingForSeek()"; + DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; ReadCBQueue read_cbs; { base::AutoLock auto_lock(lock_); + if (state_ != CANCELED) + end_of_stream_ = false; ChangeState_Locked(WAITING_FOR_SEEK); - end_of_stream_ = false; std::swap(read_cbs_, read_cbs); } @@ -292,11 +293,12 @@ void ChunkDemuxerStream::Seek(TimeDelta time) { } void ChunkDemuxerStream::CancelPendingSeek() { - DVLOG(1) << "CancelPendingSeek()"; + DVLOG(1) << "ChunkDemuxerStream::CancelPendingSeek()"; ReadCBQueue read_cbs; { base::AutoLock auto_lock(lock_); ChangeState_Locked(CANCELED); + end_of_stream_ = false; std::swap(read_cbs_, read_cbs); } @@ -638,6 +640,9 @@ void ChunkDemuxer::CancelPendingSeek() { if (video_) video_->CancelPendingSeek(); + + if (state_ == ENDED) + ChangeState_Locked(INITIALIZED); } if (!cb.is_null()) diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index c0346ca..8aa0d76 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -101,6 +101,28 @@ static void OnReadDone_EOSExpected(bool* called, *called = true; } +static void StoreStatusAndBuffer(DemuxerStream::Status* status_out, + scoped_refptr<DecoderBuffer>* buffer_out, + DemuxerStream::Status status, + const scoped_refptr<DecoderBuffer>& buffer) { + *status_out = status; + *buffer_out = buffer; +} + +static void ReadUntilNotOkOrEndOfStream( + const scoped_refptr<DemuxerStream>& stream, + DemuxerStream::Status* status, + base::TimeDelta* last_timestamp) { + scoped_refptr<DecoderBuffer> buffer; + + *last_timestamp = kNoTimestamp(); + do { + stream->Read(base::Bind(&StoreStatusAndBuffer, status, &buffer)); + if (*status == DemuxerStream::kOk && !buffer->IsEndOfStream()) + *last_timestamp = buffer->GetTimestamp(); + } while (*status == DemuxerStream::kOk && !buffer->IsEndOfStream()); +} + class ChunkDemuxerTest : public testing::Test { protected: enum CodecsIndex { @@ -238,6 +260,11 @@ class ChunkDemuxerTest : public testing::Test { return AppendData(kSourceId, data, length); } + bool AppendCluster(int timecode, int block_count) { + scoped_ptr<Cluster> cluster(GenerateCluster(timecode, block_count)); + return AppendData(kSourceId, cluster->data(), cluster->size()); + } + bool AppendData(const std::string& source_id, const uint8* data, size_t length) { CHECK(length); @@ -1160,6 +1187,54 @@ TEST_F(ChunkDemuxerTest, TestReadsAfterEndOfStream) { end_of_stream_helper_3.CheckIfReadDonesWereCalled(true); } +TEST_F(ChunkDemuxerTest, TestEndOfStreamDuringCanceledSeek) { + ASSERT_TRUE(InitDemuxer(true, true, false)); + scoped_refptr<DemuxerStream> audio = + demuxer_->GetStream(DemuxerStream::AUDIO); + scoped_refptr<DemuxerStream> video = + demuxer_->GetStream(DemuxerStream::VIDEO); + + ASSERT_TRUE(AppendCluster(0, 10)); + EXPECT_CALL(host_, SetDuration(base::TimeDelta::FromMilliseconds(138))); + EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK)); + + // Start the first seek. + demuxer_->StartWaitingForSeek(); + + // Call EndOfStream() before the demuxer is notified of the desired + // seek point. This simulates end of stream being called before the + // pipeline gets a chance to call Seek(). + EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK)); + + // Simulate the pipeline finally calling Seek(). + demuxer_->Seek(base::TimeDelta::FromMilliseconds(20), + NewExpectedStatusCB(PIPELINE_OK)); + + // Simulate another seek being requested before the first + // seek has finished prerolling. + demuxer_->CancelPendingSeek(); + + // Call EndOfStream() again since the second seek should clear the + // previous end of stream state. + EXPECT_TRUE(demuxer_->EndOfStream(PIPELINE_OK)); + + // Finish second seek. + demuxer_->StartWaitingForSeek(); + demuxer_->Seek(base::TimeDelta::FromMilliseconds(30), + NewExpectedStatusCB(PIPELINE_OK)); + + DemuxerStream::Status status; + base::TimeDelta last_timestamp; + + // Make sure audio can reach end of stream. + ReadUntilNotOkOrEndOfStream(audio, &status, &last_timestamp); + ASSERT_EQ(status, DemuxerStream::kOk); + + // Make sure video can reach end of stream. + ReadUntilNotOkOrEndOfStream(video, &status, &last_timestamp); + ASSERT_EQ(status, DemuxerStream::kOk); +} + // Make sure AppendData() will accept elements that span multiple calls. TEST_F(ChunkDemuxerTest, TestAppendingInPieces) { EXPECT_CALL(*this, DemuxerOpened()); @@ -1989,29 +2064,6 @@ TEST_F(ChunkDemuxerTest, TestEndOfStreamDuringSeek) { end_of_stream_helper.CheckIfReadDonesWereCalled(true); } -static void ConfigChangeReadDone(DemuxerStream::Status* status_out, - scoped_refptr<DecoderBuffer>* buffer_out, - DemuxerStream::Status status, - const scoped_refptr<DecoderBuffer>& buffer) { - *status_out = status; - *buffer_out = buffer; -} - -static void ReadUntilNotOkOrEndOfStream( - const scoped_refptr<DemuxerStream>& stream, - DemuxerStream::Status* status, - base::TimeDelta* last_timestamp) { - scoped_refptr<DecoderBuffer> buffer; - - *last_timestamp = kNoTimestamp(); - do { - stream->Read(base::Bind(&ConfigChangeReadDone, status, &buffer)); - if (*status == DemuxerStream::kOk && !buffer->IsEndOfStream()) - *last_timestamp = buffer->GetTimestamp(); - - } while (*status == DemuxerStream::kOk && !buffer->IsEndOfStream()); -} - TEST_F(ChunkDemuxerTest, TestConfigChange_Video) { InSequence s; |