diff options
author | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-14 04:58:30 +0000 |
---|---|---|
committer | acolwell@chromium.org <acolwell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-14 04:58:30 +0000 |
commit | 96dda5b4f00897d10f40f4e8f31f070eb94ab40c (patch) | |
tree | f0a808ba91782a0a51c968e121d9630d7c18c02c /media | |
parent | b184a49812342c2e7e0c43c2568c26bf16356dff (diff) | |
download | chromium_src-96dda5b4f00897d10f40f4e8f31f070eb94ab40c.zip chromium_src-96dda5b4f00897d10f40f4e8f31f070eb94ab40c.tar.gz chromium_src-96dda5b4f00897d10f40f4e8f31f070eb94ab40c.tar.bz2 |
Fix HTMLMediaElement.currentTime flakiness caused by time updates during a seek.
BUG=WK85952
TEST=PipelineTest.TimeUpdateDuringSeek
Review URL: https://chromiumcodereview.appspot.com/10781006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146721 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/pipeline.cc | 6 | ||||
-rw-r--r-- | media/base/pipeline_unittest.cc | 66 |
2 files changed, 71 insertions, 1 deletions
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index 658b414..2b26541 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc @@ -400,6 +400,9 @@ void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { if (waiting_for_clock_update_ && time < clock_->Elapsed()) return; + if (state_ == kSeeking) + return; + clock_->SetTime(time, max_time); StartClockIfWaitingForTimeUpdate_Locked(); } @@ -411,6 +414,9 @@ void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { if (has_audio_) return; + if (state_ == kSeeking) + return; + DCHECK(!waiting_for_clock_update_); clock_->SetMaxTime(max_time); } diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index 6261345..33808ab 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -23,10 +23,12 @@ using ::testing::DeleteArg; using ::testing::DoAll; using ::testing::InSequence; using ::testing::Invoke; +using ::testing::InvokeWithoutArgs; using ::testing::Mock; using ::testing::NotNull; using ::testing::Return; using ::testing::ReturnRef; +using ::testing::SaveArg; using ::testing::StrictMock; using ::testing::WithArg; @@ -204,7 +206,8 @@ class PipelineTest : public ::testing::Test { } else { EXPECT_CALL(*mocks_->audio_renderer(), Initialize( scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), _, _, _)) - .WillOnce(Invoke(&RunPipelineStatusCB4)); + .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), + Invoke(&RunPipelineStatusCB4))); } EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f)); @@ -294,6 +297,7 @@ class PipelineTest : public ::testing::Test { scoped_ptr<media::MockFilterCollection> mocks_; scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream_; scoped_refptr<StrictMock<MockDemuxerStream> > video_stream_; + AudioRenderer::TimeCB audio_time_cb_; private: DISALLOW_COPY_AND_ASSIGN(PipelineTest); @@ -863,6 +867,66 @@ TEST_F(PipelineTest, StartTimeIsNonZero) { EXPECT_EQ(kStartTime, pipeline_->GetCurrentTime()); } +static void RunTimeCB(const AudioRenderer::TimeCB& time_cb, + int time_in_ms, + int max_time_in_ms) { + time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms), + base::TimeDelta::FromMilliseconds(max_time_in_ms)); +} + +TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) { + CreateAudioStream(); + MockDemuxerStreamVector streams; + streams.push_back(audio_stream()); + + InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(10)); + InitializeAudioDecoder(audio_stream()); + InitializeAudioRenderer(); + InitializePipeline(PIPELINE_OK); + + float playback_rate = 1.0f; + EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate)); + EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate)); + pipeline_->SetPlaybackRate(playback_rate); + message_loop_.RunAllPending(); + + // Provide an initial time update so that the pipeline transitions out of the + // "waiting for time update" state. + audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100), + base::TimeDelta::FromMilliseconds(500)); + + base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); + + // Arrange to trigger a time update while the demuxer is in the middle of + // seeking. This update should be ignored by the pipeline and the clock should + // not get updated. + base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700); + EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) + .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run), + Invoke(&RunPipelineStatusCB2))); + + EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) + .WillOnce(Invoke(&RunClosure)); + EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) + .WillOnce(Invoke(&RunClosure)); + EXPECT_CALL(*mocks_->audio_renderer(), Seek(seek_time, _)) + .WillOnce(Invoke(&RunPipelineStatusCB2)); + EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) + .WillOnce(Invoke(&RunClosure)); + + EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); + DoSeek(seek_time); + + EXPECT_EQ(pipeline_->GetCurrentTime(), seek_time); + + // Now that the seek is complete, verify that time updates advance the current + // time. + base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100); + audio_time_cb_.Run(new_time, new_time); + + EXPECT_EQ(pipeline_->GetCurrentTime(), new_time); +} + class FlexibleCallbackRunner : public base::DelegateSimpleThread::Delegate { public: FlexibleCallbackRunner(base::TimeDelta delay, PipelineStatus status, |