summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authoracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-01 20:01:04 +0000
committeracolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-01 20:01:04 +0000
commit12ba0bb19c538bb67b82b27b42b3fcbe8cd23434 (patch)
treedfba9dad234ab748f059421cb8fc56601860f33c /media
parentae6e53f30725b7e375caf9e377fed4e3e112494a (diff)
downloadchromium_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.cc11
-rw-r--r--media/filters/chunk_demuxer_unittest.cc98
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;