| Index: media/base/pipeline_unittest.cc
|
| diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc
|
| index 45cc73ba36fa7b1a46c5f19aed717b78da5be1fe..47e5f0a44749c7a723736942f3d98ca865c88462 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 {
|
| @@ -183,7 +187,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)));
|
| }
|
|
|
| @@ -205,10 +210,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_, OnPrerollCompleted());
|
| @@ -254,17 +258,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());
|
| @@ -333,6 +341,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_;
|
|
|
| @@ -510,7 +519,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);
|
| }
|
|
|
| @@ -568,7 +577,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());
|
| @@ -670,7 +679,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>());
|
|
|
| @@ -724,7 +735,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>());
|
|
|
| @@ -814,9 +827,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());
|
| @@ -854,6 +870,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 {
|
| @@ -966,7 +1004,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) {
|
| @@ -992,8 +1031,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));
|
|
|
| @@ -1040,17 +1080,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) {
|
| @@ -1072,20 +1121,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(*audio_renderer_, StartPlayingFrom(_))
|
| + .WillOnce(Stop(pipeline_.get(), stop_cb));
|
| } else {
|
| status = PIPELINE_ERROR_READ;
|
| - EXPECT_CALL(*audio_renderer_, Preroll(_, _))
|
| - .WillOnce(RunCallback<1>(status));
|
| + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(_))
|
| + .WillOnce(SetError(pipeline_.get(), status));
|
| }
|
|
|
| return status;
|
| }
|
|
|
| - EXPECT_CALL(*audio_renderer_, Preroll(_, _))
|
| - .WillOnce(RunCallback<1>(PIPELINE_OK));
|
| + EXPECT_CALL(*audio_renderer_, StartPlayingFrom(_));
|
| EXPECT_CALL(*video_renderer_, Preroll(_, _))
|
| .WillOnce(RunCallback<1>(PIPELINE_OK));
|
|
|
|
|