diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-26 10:29:02 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-26 10:29:02 +0000 |
commit | 92b6b424f65f5bbeded0995ea89f2e0f5bc72919 (patch) | |
tree | c4d4049e9c63cb36b41032ab2329c30013ab879c /media/base/pipeline_unittest.cc | |
parent | 8c8b3db8212e7323b28d7aca0a08de61264ae5b7 (diff) | |
download | chromium_src-92b6b424f65f5bbeded0995ea89f2e0f5bc72919.zip chromium_src-92b6b424f65f5bbeded0995ea89f2e0f5bc72919.tar.gz chromium_src-92b6b424f65f5bbeded0995ea89f2e0f5bc72919.tar.bz2 |
Update AudioRenderer API to fire changes in BufferingState (round 2).
As a result, Pipeline now handles prerolling and underflow/rebuffering
by listening for BUFFERING_HAVE_NOTHING/ENOUGH callbacks. Preroll() is
renamed StartPlayingFrom() and no longer accepts a completion callback.
In this new model, AudioRenderers immediately enter and remain in
the "playing" state and fire buffering state callbacks to let Pipeline
know when to start/stop the clock.
BUG=144683
Review URL: https://codereview.chromium.org/354673007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279977 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/pipeline_unittest.cc')
-rw-r--r-- | media/base/pipeline_unittest.cc | 107 |
1 files changed, 76 insertions, 31 deletions
diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index a877143..d9f2f1f 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -51,6 +51,10 @@ ACTION_P2(SetError, pipeline, status) { pipeline->SetErrorForTesting(status); } +ACTION_P2(SetBufferingState, cb, buffering_state) { + cb->Run(buffering_state); +} + // Used for setting expectations on pipeline callbacks. Using a StrictMock // also lets us test for missing callbacks. class CallbackHelper { @@ -180,7 +184,8 @@ class PipelineTest : public ::testing::Test { // Sets up expectations to allow the audio renderer to initialize. void InitializeAudioRenderer(DemuxerStream* stream) { EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _)) - .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_), + .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), + SaveArg<4>(&audio_buffering_state_cb_), RunCallback<1>(PIPELINE_OK))); } @@ -202,10 +207,9 @@ class PipelineTest : public ::testing::Test { if (audio_stream_) { EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f)); EXPECT_CALL(*audio_renderer_, SetVolume(1.0f)); - - // Startup sequence. - EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(base::TimeDelta())) + .WillOnce(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_ENOUGH)); EXPECT_CALL(*audio_renderer_, StartRendering()); } EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)); @@ -251,17 +255,21 @@ class PipelineTest : public ::testing::Test { return text_stream_.get(); } - void ExpectSeek(const base::TimeDelta& seek_time) { + void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) { // Every filter should receive a call to Seek(). EXPECT_CALL(*demuxer_, Seek(seek_time, _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); if (audio_stream_) { - EXPECT_CALL(*audio_renderer_, StopRendering()); + if (!underflowed) + EXPECT_CALL(*audio_renderer_, StopRendering()); EXPECT_CALL(*audio_renderer_, Flush(_)) - .WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(seek_time)) + .WillOnce(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_ENOUGH)); EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_)); EXPECT_CALL(*audio_renderer_, SetVolume(_)); EXPECT_CALL(*audio_renderer_, StartRendering()); @@ -329,6 +337,7 @@ class PipelineTest : public ::testing::Test { scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_; scoped_ptr<FakeTextTrackStream> text_stream_; AudioRenderer::TimeCB audio_time_cb_; + AudioRenderer::BufferingStateCB audio_buffering_state_cb_; VideoDecoderConfig video_decoder_config_; PipelineMetadata metadata_; @@ -506,7 +515,7 @@ TEST_F(PipelineTest, Seek) { // Every filter should receive a call to Seek(). base::TimeDelta expected = base::TimeDelta::FromSeconds(2000); - ExpectSeek(expected); + ExpectSeek(expected, false); DoSeek(expected); } @@ -564,7 +573,7 @@ TEST_F(PipelineTest, GetBufferedTimeRanges) { EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); base::TimeDelta kSeekTime = kDuration / 2; - ExpectSeek(kSeekTime); + ExpectSeek(kSeekTime, false); DoSeek(kSeekTime); EXPECT_FALSE(pipeline_->DidLoadingProgress()); @@ -666,7 +675,9 @@ TEST_F(PipelineTest, ErrorDuringSeek) { // Preroll() isn't called as the demuxer errors out first. EXPECT_CALL(*audio_renderer_, StopRendering()); EXPECT_CALL(*audio_renderer_, Flush(_)) - .WillOnce(RunClosure<0>()); + .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); EXPECT_CALL(*audio_renderer_, Stop(_)) .WillOnce(RunClosure<0>()); @@ -720,7 +731,9 @@ TEST_F(PipelineTest, NoMessageDuringTearDownFromError) { // Seek() isn't called as the demuxer errors out first. EXPECT_CALL(*audio_renderer_, StopRendering()); EXPECT_CALL(*audio_renderer_, Flush(_)) - .WillOnce(RunClosure<0>()); + .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); EXPECT_CALL(*audio_renderer_, Stop(_)) .WillOnce(RunClosure<0>()); @@ -773,9 +786,12 @@ TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) { EXPECT_CALL(*audio_renderer_, StopRendering()); EXPECT_CALL(*audio_renderer_, Flush(_)) - .WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(seek_time)) + .WillOnce(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_ENOUGH)); EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_)); EXPECT_CALL(*audio_renderer_, SetVolume(_)); EXPECT_CALL(*audio_renderer_, StartRendering()); @@ -813,6 +829,28 @@ TEST_F(PipelineTest, DeleteAfterStop) { message_loop_.RunUntilIdle(); } +TEST_F(PipelineTest, Underflow) { + CreateAudioStream(); + CreateVideoStream(); + MockDemuxerStreamVector streams; + streams.push_back(audio_stream()); + streams.push_back(video_stream()); + + InitializeDemuxer(&streams); + InitializeAudioRenderer(audio_stream()); + InitializeVideoRenderer(video_stream()); + InitializePipeline(PIPELINE_OK); + + // Simulate underflow. + EXPECT_CALL(*audio_renderer_, StopRendering()); + audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING); + + // Seek while underflowed. We shouldn't call StopRendering() again. + base::TimeDelta expected = base::TimeDelta::FromSeconds(5); + ExpectSeek(expected, true); + DoSeek(expected); +} + class PipelineTeardownTest : public PipelineTest { public: enum TeardownState { @@ -925,7 +963,8 @@ class PipelineTeardownTest : public PipelineTest { } EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_), + RunCallback<1>(PIPELINE_OK))); if (state == kInitVideoRenderer) { if (stop_or_error == kStop) { @@ -951,8 +990,9 @@ class PipelineTeardownTest : public PipelineTest { EXPECT_CALL(callbacks_, OnMetadata(_)); // If we get here it's a successful initialization. - EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(base::TimeDelta())) + .WillOnce(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_ENOUGH)); EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _)) .WillOnce(RunCallback<1>(PIPELINE_OK)); @@ -999,17 +1039,26 @@ class PipelineTeardownTest : public PipelineTest { if (state == kFlushing) { if (stop_or_error == kStop) { EXPECT_CALL(*audio_renderer_, Flush(_)) - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>())); + .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), + SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); } else { status = PIPELINE_ERROR_READ; EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce( - DoAll(SetError(pipeline_.get(), status), RunClosure<0>())); + DoAll(SetError(pipeline_.get(), status), + SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); } return status; } - EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); + EXPECT_CALL(*audio_renderer_, Flush(_)) + .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, + BUFFERING_HAVE_NOTHING), + RunClosure<0>())); EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); if (state == kSeeking) { @@ -1031,22 +1080,18 @@ class PipelineTeardownTest : public PipelineTest { if (state == kPrerolling) { if (stop_or_error == kStop) { - EXPECT_CALL(*audio_renderer_, Preroll(_, _)) - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), - RunCallback<1>(PIPELINE_OK))); + EXPECT_CALL(*video_renderer_, Preroll(_, _)) + .WillOnce(Stop(pipeline_.get(), stop_cb)); } else { status = PIPELINE_ERROR_READ; - EXPECT_CALL(*audio_renderer_, Preroll(_, _)) + EXPECT_CALL(*video_renderer_, Preroll(_, _)) .WillOnce(RunCallback<1>(status)); } return status; } - EXPECT_CALL(*audio_renderer_, Preroll(_, _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); - EXPECT_CALL(*video_renderer_, Preroll(_, _)) - .WillOnce(RunCallback<1>(PIPELINE_OK)); + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(_)); // Playback rate and volume are updated prior to starting. EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f)); |