| Index: media/base/pipeline_unittest.cc
|
| diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc
|
| deleted file mode 100644
|
| index 8f43d608889805db4a7eac842ef7d6db84ab1733..0000000000000000000000000000000000000000
|
| --- a/media/base/pipeline_unittest.cc
|
| +++ /dev/null
|
| @@ -1,1166 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "media/base/pipeline.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/macros.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/test/simple_test_tick_clock.h"
|
| -#include "base/threading/simple_thread.h"
|
| -#include "base/time/clock.h"
|
| -#include "media/base/fake_text_track_stream.h"
|
| -#include "media/base/gmock_callback_support.h"
|
| -#include "media/base/media_log.h"
|
| -#include "media/base/mock_filters.h"
|
| -#include "media/base/test_helpers.h"
|
| -#include "media/base/text_renderer.h"
|
| -#include "media/base/text_track_config.h"
|
| -#include "media/base/time_delta_interpolator.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "ui/gfx/geometry/size.h"
|
| -
|
| -using ::testing::_;
|
| -using ::testing::AnyNumber;
|
| -using ::testing::DeleteArg;
|
| -using ::testing::DoAll;
|
| -// TODO(scherkus): Remove InSequence after refactoring Pipeline.
|
| -using ::testing::InSequence;
|
| -using ::testing::Invoke;
|
| -using ::testing::InvokeWithoutArgs;
|
| -using ::testing::Mock;
|
| -using ::testing::NotNull;
|
| -using ::testing::Return;
|
| -using ::testing::SaveArg;
|
| -using ::testing::StrictMock;
|
| -using ::testing::WithArg;
|
| -
|
| -namespace media {
|
| -
|
| -ACTION_P(SetDemuxerProperties, duration) {
|
| - arg0->SetDuration(duration);
|
| -}
|
| -
|
| -ACTION_P2(Stop, pipeline, stop_cb) {
|
| - pipeline->Stop(stop_cb);
|
| -}
|
| -
|
| -ACTION_P2(SetError, pipeline, status) {
|
| - pipeline->SetErrorForTesting(status);
|
| -}
|
| -
|
| -ACTION_P2(SetBufferingState, cb, buffering_state) {
|
| - cb->Run(buffering_state);
|
| -}
|
| -
|
| -ACTION_TEMPLATE(PostCallback,
|
| - HAS_1_TEMPLATE_PARAMS(int, k),
|
| - AND_1_VALUE_PARAMS(p0)) {
|
| - return base::MessageLoop::current()->PostTask(
|
| - FROM_HERE, base::Bind(::std::tr1::get<k>(args), p0));
|
| -}
|
| -
|
| -// TODO(scherkus): even though some filters are initialized on separate
|
| -// threads these test aren't flaky... why? It's because filters' Initialize()
|
| -// is executed on |message_loop_| and the mock filters instantly call
|
| -// InitializationComplete(), which keeps the pipeline humming along. If
|
| -// either filters don't call InitializationComplete() immediately or filter
|
| -// initialization is moved to a separate thread this test will become flaky.
|
| -class PipelineTest : public ::testing::Test {
|
| - public:
|
| - // Used for setting expectations on pipeline callbacks. Using a StrictMock
|
| - // also lets us test for missing callbacks.
|
| - class CallbackHelper {
|
| - public:
|
| - CallbackHelper() {}
|
| - virtual ~CallbackHelper() {}
|
| -
|
| - MOCK_METHOD1(OnStart, void(PipelineStatus));
|
| - MOCK_METHOD1(OnSeek, void(PipelineStatus));
|
| - MOCK_METHOD1(OnSuspend, void(PipelineStatus));
|
| - MOCK_METHOD1(OnResume, void(PipelineStatus));
|
| - MOCK_METHOD0(OnStop, void());
|
| - MOCK_METHOD0(OnEnded, void());
|
| - MOCK_METHOD1(OnError, void(PipelineStatus));
|
| - MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
|
| - MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
|
| - MOCK_METHOD0(OnDurationChange, void());
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
|
| - };
|
| -
|
| - PipelineTest()
|
| - : pipeline_(new Pipeline(message_loop_.task_runner(),
|
| - new MediaLog())),
|
| - demuxer_(new StrictMock<MockDemuxer>()),
|
| - scoped_renderer_(new StrictMock<MockRenderer>()),
|
| - renderer_(scoped_renderer_.get()) {
|
| - // SetDemuxerExpectations() adds overriding expectations for expected
|
| - // non-NULL streams.
|
| - DemuxerStream* null_pointer = NULL;
|
| - EXPECT_CALL(*demuxer_, GetStream(_))
|
| - .WillRepeatedly(Return(null_pointer));
|
| -
|
| - EXPECT_CALL(*demuxer_, GetTimelineOffset())
|
| - .WillRepeatedly(Return(base::Time()));
|
| -
|
| - EXPECT_CALL(*renderer_, GetMediaTime())
|
| - .WillRepeatedly(Return(base::TimeDelta()));
|
| -
|
| - EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
|
| - }
|
| -
|
| - virtual ~PipelineTest() {
|
| - if (!pipeline_ || !pipeline_->IsRunning())
|
| - return;
|
| -
|
| - ExpectDemuxerStop();
|
| -
|
| - // The mock demuxer doesn't stop the fake text track stream,
|
| - // so just stop it manually.
|
| - if (text_stream_) {
|
| - text_stream_->Stop();
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - // Expect a stop callback if we were started.
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
|
| - base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - void OnDemuxerError() {
|
| - // Cast because OnDemuxerError is private in Pipeline.
|
| - static_cast<DemuxerHost*>(pipeline_.get())
|
| - ->OnDemuxerError(PIPELINE_ERROR_ABORT);
|
| - }
|
| -
|
| - protected:
|
| - // Sets up expectations to allow the demuxer to initialize.
|
| - typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
|
| - void SetDemuxerExpectations(MockDemuxerStreamVector* streams,
|
| - const base::TimeDelta& duration) {
|
| - EXPECT_CALL(callbacks_, OnDurationChange());
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(DoAll(SetDemuxerProperties(duration),
|
| - PostCallback<1>(PIPELINE_OK)));
|
| -
|
| - // Configure the demuxer to return the streams.
|
| - for (size_t i = 0; i < streams->size(); ++i) {
|
| - DemuxerStream* stream = (*streams)[i];
|
| - EXPECT_CALL(*demuxer_, GetStream(stream->type()))
|
| - .WillRepeatedly(Return(stream));
|
| - }
|
| - }
|
| -
|
| - void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
|
| - // Initialize with a default non-zero duration.
|
| - SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
|
| - }
|
| -
|
| - scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
|
| - DemuxerStream::Type type) {
|
| - scoped_ptr<StrictMock<MockDemuxerStream> > stream(
|
| - new StrictMock<MockDemuxerStream>(type));
|
| - return stream;
|
| - }
|
| -
|
| - // Sets up expectations to allow the video renderer to initialize.
|
| - void SetRendererExpectations() {
|
| - EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _))
|
| - .WillOnce(DoAll(SaveArg<3>(&buffering_state_cb_),
|
| - SaveArg<4>(&ended_cb_),
|
| - PostCallback<1>(PIPELINE_OK)));
|
| - EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(audio_stream()));
|
| - EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(video_stream()));
|
| - }
|
| -
|
| - void AddTextStream() {
|
| - EXPECT_CALL(*this, OnAddTextTrack(_,_))
|
| - .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
|
| - static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
|
| - TextTrackConfig(kTextSubtitles, "", "", ""));
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - void StartPipeline() {
|
| - EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
|
| - pipeline_->Start(
|
| - demuxer_.get(), std::move(scoped_renderer_),
|
| - base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
|
| - base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
|
| - base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
|
| - base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
|
| - base::Bind(&CallbackHelper::OnBufferingStateChange,
|
| - base::Unretained(&callbacks_)),
|
| - base::Bind(&CallbackHelper::OnDurationChange,
|
| - base::Unretained(&callbacks_)),
|
| - base::Bind(&PipelineTest::OnAddTextTrack, base::Unretained(this)),
|
| - base::Bind(&PipelineTest::OnWaitingForDecryptionKey,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - // Sets up expectations on the callback and initializes the pipeline. Called
|
| - // after tests have set expectations any filters they wish to use.
|
| - void StartPipelineAndExpect(PipelineStatus start_status) {
|
| - EXPECT_CALL(callbacks_, OnStart(start_status));
|
| -
|
| - if (start_status == PIPELINE_OK) {
|
| - EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
|
| - EXPECT_CALL(*renderer_, SetVolume(1.0f));
|
| - EXPECT_CALL(*renderer_, StartPlayingFrom(start_time_))
|
| - .WillOnce(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_ENOUGH));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
|
| - }
|
| -
|
| - StartPipeline();
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - void CreateAudioStream() {
|
| - audio_stream_ = CreateStream(DemuxerStream::AUDIO);
|
| - }
|
| -
|
| - void CreateVideoStream() {
|
| - video_stream_ = CreateStream(DemuxerStream::VIDEO);
|
| - video_stream_->set_video_decoder_config(video_decoder_config_);
|
| - }
|
| -
|
| - void CreateTextStream() {
|
| - scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
|
| - EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
|
| - text_stream_ = std::move(text_stream);
|
| - }
|
| -
|
| - MockDemuxerStream* audio_stream() {
|
| - return audio_stream_.get();
|
| - }
|
| -
|
| - MockDemuxerStream* video_stream() {
|
| - return video_stream_.get();
|
| - }
|
| -
|
| - FakeTextTrackStream* text_stream() {
|
| - return text_stream_.get();
|
| - }
|
| -
|
| - void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
|
| - EXPECT_CALL(*demuxer_, Seek(seek_time, _))
|
| - .WillOnce(RunCallback<1>(PIPELINE_OK));
|
| -
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(_));
|
| - EXPECT_CALL(*renderer_, SetVolume(_));
|
| - EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
|
| - .WillOnce(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_ENOUGH));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| -
|
| - // We expect a successful seek callback followed by a buffering update.
|
| - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
|
| - }
|
| -
|
| - void DoSeek(const base::TimeDelta& seek_time) {
|
| - pipeline_->Seek(seek_time,
|
| - base::Bind(&CallbackHelper::OnSeek,
|
| - base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - void ExpectSuspend() {
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(0));
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(
|
| - SetBufferingState(&buffering_state_cb_, BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
|
| - }
|
| -
|
| - void DoSuspend() {
|
| - pipeline_->Suspend(
|
| - base::Bind(&CallbackHelper::OnSuspend, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -
|
| - // |renderer_| has been deleted, replace it.
|
| - scoped_renderer_.reset(new StrictMock<MockRenderer>()),
|
| - renderer_ = scoped_renderer_.get();
|
| - }
|
| -
|
| - void ExpectResume(const base::TimeDelta& seek_time) {
|
| - SetRendererExpectations();
|
| - EXPECT_CALL(*demuxer_, Seek(seek_time, _))
|
| - .WillOnce(RunCallback<1>(PIPELINE_OK));
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(_));
|
| - EXPECT_CALL(*renderer_, SetVolume(_));
|
| - EXPECT_CALL(*renderer_, StartPlayingFrom(seek_time))
|
| - .WillOnce(
|
| - SetBufferingState(&buffering_state_cb_, BUFFERING_HAVE_ENOUGH));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
|
| - EXPECT_CALL(callbacks_, OnResume(PIPELINE_OK));
|
| - }
|
| -
|
| - void DoResume(const base::TimeDelta& seek_time) {
|
| - pipeline_->Resume(
|
| - std::move(scoped_renderer_), seek_time,
|
| - base::Bind(&CallbackHelper::OnResume, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - void DestroyPipeline() {
|
| - // In real code Pipeline could be destroyed on a different thread. All weak
|
| - // pointers must have been invalidated before the stop callback returns.
|
| - DCHECK(!pipeline_->HasWeakPtrsForTesting());
|
| - pipeline_.reset();
|
| - }
|
| -
|
| - void ExpectDemuxerStop() {
|
| - if (demuxer_)
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - }
|
| -
|
| - void ExpectPipelineStopAndDestroyPipeline() {
|
| - // After the Pipeline is stopped, it could be destroyed any time. Always
|
| - // destroy the pipeline immediately after OnStop() to test this.
|
| - EXPECT_CALL(callbacks_, OnStop())
|
| - .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline));
|
| - }
|
| -
|
| - MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
|
| - const AddTextTrackDoneCB&));
|
| - MOCK_METHOD0(OnWaitingForDecryptionKey, void(void));
|
| -
|
| - void DoOnAddTextTrack(const TextTrackConfig& config,
|
| - const AddTextTrackDoneCB& done_cb) {
|
| - scoped_ptr<TextTrack> text_track(new MockTextTrack);
|
| - done_cb.Run(std::move(text_track));
|
| - }
|
| -
|
| - // Fixture members.
|
| - StrictMock<CallbackHelper> callbacks_;
|
| - base::SimpleTestTickClock test_tick_clock_;
|
| - base::MessageLoop message_loop_;
|
| - scoped_ptr<Pipeline> pipeline_;
|
| -
|
| - scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
|
| - scoped_ptr<StrictMock<MockRenderer> > scoped_renderer_;
|
| - StrictMock<MockRenderer>* renderer_;
|
| - StrictMock<CallbackHelper> text_renderer_callbacks_;
|
| - TextRenderer* text_renderer_;
|
| - scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
|
| - scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
|
| - scoped_ptr<FakeTextTrackStream> text_stream_;
|
| - BufferingStateCB buffering_state_cb_;
|
| - base::Closure ended_cb_;
|
| - VideoDecoderConfig video_decoder_config_;
|
| - PipelineMetadata metadata_;
|
| - base::TimeDelta start_time_;
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(PipelineTest);
|
| -};
|
| -
|
| -// Test that playback controls methods no-op when the pipeline hasn't been
|
| -// started.
|
| -TEST_F(PipelineTest, NotStarted) {
|
| - const base::TimeDelta kZero;
|
| -
|
| - EXPECT_FALSE(pipeline_->IsRunning());
|
| -
|
| - // Setting should still work.
|
| - EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
|
| - pipeline_->SetPlaybackRate(-1.0);
|
| - EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
|
| - pipeline_->SetPlaybackRate(1.0);
|
| - EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
|
| -
|
| - // Setting should still work.
|
| - EXPECT_EQ(1.0f, pipeline_->GetVolume());
|
| - pipeline_->SetVolume(-1.0f);
|
| - EXPECT_EQ(1.0f, pipeline_->GetVolume());
|
| - pipeline_->SetVolume(0.0f);
|
| - EXPECT_EQ(0.0f, pipeline_->GetVolume());
|
| -
|
| - EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
|
| - EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
|
| - EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
|
| -}
|
| -
|
| -TEST_F(PipelineTest, NeverInitializes) {
|
| - // Don't execute the callback passed into Initialize().
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _));
|
| -
|
| - // This test hangs during initialization by never calling
|
| - // InitializationComplete(). StrictMock<> will ensure that the callback is
|
| - // never executed.
|
| - StartPipeline();
|
| - message_loop_.RunUntilIdle();
|
| -
|
| - // Because our callback will get executed when the test tears down, we'll
|
| - // verify that nothing has been called, then set our expectation for the call
|
| - // made during tear down.
|
| - Mock::VerifyAndClear(&callbacks_);
|
| - EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
|
| -}
|
| -
|
| -TEST_F(PipelineTest, StopWithoutStart) {
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, StartThenStopImmediately) {
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(PostCallback<1>(PIPELINE_OK));
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| -
|
| - EXPECT_CALL(callbacks_, OnStart(_));
|
| - StartPipeline();
|
| -
|
| - // Expect a stop callback if we were started.
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, DemuxerErrorDuringStop) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop())
|
| - .WillOnce(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError));
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| -
|
| - pipeline_->Stop(
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, URLNotFound) {
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(PostCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| -
|
| - StartPipelineAndExpect(PIPELINE_ERROR_URL_NOT_FOUND);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, NoStreams) {
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(PostCallback<1>(PIPELINE_OK));
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - EXPECT_CALL(callbacks_, OnMetadata(_));
|
| -
|
| - StartPipelineAndExpect(PIPELINE_ERROR_COULD_NOT_RENDER);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, AudioStream) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_TRUE(metadata_.has_audio);
|
| - EXPECT_FALSE(metadata_.has_video);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, VideoStream) {
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_FALSE(metadata_.has_audio);
|
| - EXPECT_TRUE(metadata_.has_video);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, AudioVideoStream) {
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_TRUE(metadata_.has_audio);
|
| - EXPECT_TRUE(metadata_.has_video);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, VideoTextStream) {
|
| - CreateVideoStream();
|
| - CreateTextStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_FALSE(metadata_.has_audio);
|
| - EXPECT_TRUE(metadata_.has_video);
|
| -
|
| - AddTextStream();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, VideoAudioTextStream) {
|
| - CreateVideoStream();
|
| - CreateAudioStream();
|
| - CreateTextStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(video_stream());
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_TRUE(metadata_.has_audio);
|
| - EXPECT_TRUE(metadata_.has_video);
|
| -
|
| - AddTextStream();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, Seek) {
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - CreateTextStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
|
| - SetRendererExpectations();
|
| -
|
| - // Initialize then seek!
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - // Every filter should receive a call to Seek().
|
| - base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
|
| - ExpectSeek(expected, false);
|
| - DoSeek(expected);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, SeekAfterError) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
|
| - SetRendererExpectations();
|
| -
|
| - // Initialize then seek!
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - EXPECT_CALL(callbacks_, OnError(_));
|
| -
|
| - static_cast<DemuxerHost*>(pipeline_.get())
|
| - ->OnDemuxerError(PIPELINE_ERROR_ABORT);
|
| - message_loop_.RunUntilIdle();
|
| -
|
| - pipeline_->Seek(
|
| - base::TimeDelta::FromMilliseconds(100),
|
| - base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, SuspendResume) {
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - CreateTextStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - ExpectSuspend();
|
| - DoSuspend();
|
| -
|
| - base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
|
| - ExpectResume(expected);
|
| - DoResume(expected);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, SetVolume) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| -
|
| - // The audio renderer should receive a call to SetVolume().
|
| - float expected = 0.5f;
|
| - EXPECT_CALL(*renderer_, SetVolume(expected));
|
| -
|
| - // Initialize then set volume!
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - pipeline_->SetVolume(expected);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, Properties) {
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(video_stream());
|
| -
|
| - const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
|
| - SetDemuxerExpectations(&streams, kDuration);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - EXPECT_EQ(kDuration.ToInternalValue(),
|
| - pipeline_->GetMediaDuration().ToInternalValue());
|
| - EXPECT_FALSE(pipeline_->DidLoadingProgress());
|
| -}
|
| -
|
| -TEST_F(PipelineTest, GetBufferedTimeRanges) {
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(video_stream());
|
| -
|
| - const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
|
| - SetDemuxerExpectations(&streams, kDuration);
|
| - SetRendererExpectations();
|
| -
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
|
| -
|
| - EXPECT_FALSE(pipeline_->DidLoadingProgress());
|
| - Ranges<base::TimeDelta> ranges;
|
| - ranges.Add(base::TimeDelta(), kDuration / 8);
|
| - pipeline_->OnBufferedTimeRangesChanged(ranges);
|
| - EXPECT_TRUE(pipeline_->DidLoadingProgress());
|
| - EXPECT_FALSE(pipeline_->DidLoadingProgress());
|
| - EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
|
| - EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
|
| - EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
|
| -
|
| - base::TimeDelta kSeekTime = kDuration / 2;
|
| - ExpectSeek(kSeekTime, false);
|
| - DoSeek(kSeekTime);
|
| -
|
| - EXPECT_FALSE(pipeline_->DidLoadingProgress());
|
| -}
|
| -
|
| -TEST_F(PipelineTest, EndedCallback) {
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - CreateTextStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - AddTextStream();
|
| -
|
| - // The ended callback shouldn't run until all renderers have ended.
|
| - ended_cb_.Run();
|
| - message_loop_.RunUntilIdle();
|
| -
|
| - EXPECT_CALL(callbacks_, OnEnded());
|
| - text_stream()->SendEosNotification();
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, ErrorDuringSeek) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - double playback_rate = 1.0;
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(playback_rate));
|
| - pipeline_->SetPlaybackRate(playback_rate);
|
| - message_loop_.RunUntilIdle();
|
| -
|
| - base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
|
| -
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| -
|
| - EXPECT_CALL(*demuxer_, Seek(seek_time, _))
|
| - .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| -
|
| - pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
|
| - base::Unretained(&callbacks_)));
|
| - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -// Invoked function OnError. This asserts that the pipeline does not enqueue
|
| -// non-teardown related tasks while tearing down.
|
| -static void TestNoCallsAfterError(
|
| - Pipeline* pipeline, base::MessageLoop* message_loop,
|
| - PipelineStatus /* status */) {
|
| - CHECK(pipeline);
|
| - CHECK(message_loop);
|
| -
|
| - // When we get to this stage, the message loop should be empty.
|
| - EXPECT_TRUE(message_loop->IsIdleForTesting());
|
| -
|
| - // Make calls on pipeline after error has occurred.
|
| - pipeline->SetPlaybackRate(0.5);
|
| - pipeline->SetVolume(0.5f);
|
| -
|
| - // No additional tasks should be queued as a result of these calls.
|
| - EXPECT_TRUE(message_loop->IsIdleForTesting());
|
| -}
|
| -
|
| -TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - // Trigger additional requests on the pipeline during tear down from error.
|
| - base::Callback<void(PipelineStatus)> cb = base::Bind(
|
| - &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
|
| - ON_CALL(callbacks_, OnError(_))
|
| - .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
|
| -
|
| - base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
|
| -
|
| - // Seek() isn't called as the demuxer errors out first.
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| -
|
| - EXPECT_CALL(*demuxer_, Seek(seek_time, _))
|
| - .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| -
|
| - pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
|
| - base::Unretained(&callbacks_)));
|
| - EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, DestroyAfterStop) {
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - ExpectDemuxerStop();
|
| -
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -TEST_F(PipelineTest, Underflow) {
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| -
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| -
|
| - // Simulate underflow.
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
|
| -
|
| - // Seek while underflowed.
|
| - base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
|
| - ExpectSeek(expected, true);
|
| - DoSeek(expected);
|
| -}
|
| -
|
| -TEST_F(PipelineTest, PositiveStartTime) {
|
| - start_time_ = base::TimeDelta::FromSeconds(1);
|
| - EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_));
|
| - CreateAudioStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - SetDemuxerExpectations(&streams);
|
| - SetRendererExpectations();
|
| - StartPipelineAndExpect(PIPELINE_OK);
|
| - ExpectDemuxerStop();
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| -}
|
| -
|
| -class PipelineTeardownTest : public PipelineTest {
|
| - public:
|
| - enum TeardownState {
|
| - kInitDemuxer,
|
| - kInitRenderer,
|
| - kFlushing,
|
| - kSeeking,
|
| - kPlaying,
|
| - kSuspending,
|
| - kSuspended,
|
| - kResuming,
|
| - };
|
| -
|
| - enum StopOrError {
|
| - kStop,
|
| - kError,
|
| - kErrorAndStop,
|
| - };
|
| -
|
| - PipelineTeardownTest() {}
|
| - ~PipelineTeardownTest() override {}
|
| -
|
| - void RunTest(TeardownState state, StopOrError stop_or_error) {
|
| - switch (state) {
|
| - case kInitDemuxer:
|
| - case kInitRenderer:
|
| - DoInitialize(state, stop_or_error);
|
| - break;
|
| -
|
| - case kFlushing:
|
| - case kSeeking:
|
| - DoInitialize(state, stop_or_error);
|
| - DoSeek(state, stop_or_error);
|
| - break;
|
| -
|
| - case kPlaying:
|
| - DoInitialize(state, stop_or_error);
|
| - DoStopOrError(stop_or_error);
|
| - break;
|
| -
|
| - case kSuspending:
|
| - case kSuspended:
|
| - case kResuming:
|
| - DoInitialize(state, stop_or_error);
|
| - DoSuspend(state, stop_or_error);
|
| - break;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - // TODO(scherkus): We do radically different things whether teardown is
|
| - // invoked via stop vs error. The teardown path should be the same,
|
| - // see http://crbug.com/110228
|
| - void DoInitialize(TeardownState state, StopOrError stop_or_error) {
|
| - PipelineStatus expected_status =
|
| - SetInitializeExpectations(state, stop_or_error);
|
| -
|
| - EXPECT_CALL(callbacks_, OnStart(expected_status));
|
| - StartPipeline();
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - PipelineStatus SetInitializeExpectations(TeardownState state,
|
| - StopOrError stop_or_error) {
|
| - PipelineStatus status = PIPELINE_OK;
|
| - base::Closure stop_cb = base::Bind(
|
| - &CallbackHelper::OnStop, base::Unretained(&callbacks_));
|
| -
|
| - if (state == kInitDemuxer) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
|
| - PostCallback<1>(PIPELINE_OK)));
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - } else {
|
| - status = DEMUXER_ERROR_COULD_NOT_OPEN;
|
| - EXPECT_CALL(*demuxer_, Initialize(_, _, _))
|
| - .WillOnce(PostCallback<1>(status));
|
| - }
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - return status;
|
| - }
|
| -
|
| - CreateAudioStream();
|
| - CreateVideoStream();
|
| - MockDemuxerStreamVector streams;
|
| - streams.push_back(audio_stream());
|
| - streams.push_back(video_stream());
|
| - SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
|
| -
|
| - EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(true));
|
| - EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(true));
|
| -
|
| - if (state == kInitRenderer) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _))
|
| - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
|
| - PostCallback<1>(PIPELINE_OK)));
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - } else {
|
| - status = PIPELINE_ERROR_INITIALIZATION_FAILED;
|
| - EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _))
|
| - .WillOnce(PostCallback<1>(status));
|
| - }
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - EXPECT_CALL(callbacks_, OnMetadata(_));
|
| - return status;
|
| - }
|
| -
|
| - EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _))
|
| - .WillOnce(DoAll(SaveArg<3>(&buffering_state_cb_),
|
| - PostCallback<1>(PIPELINE_OK)));
|
| -
|
| - EXPECT_CALL(callbacks_, OnMetadata(_));
|
| -
|
| - // If we get here it's a successful initialization.
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(0.0));
|
| - EXPECT_CALL(*renderer_, SetVolume(1.0f));
|
| - EXPECT_CALL(*renderer_, StartPlayingFrom(base::TimeDelta()))
|
| - .WillOnce(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_ENOUGH));
|
| -
|
| - if (status == PIPELINE_OK)
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
|
| -
|
| - return status;
|
| - }
|
| -
|
| - void DoSeek(TeardownState state, StopOrError stop_or_error) {
|
| - InSequence s;
|
| - PipelineStatus status = SetSeekExpectations(state, stop_or_error);
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - EXPECT_CALL(callbacks_, OnSeek(status));
|
| -
|
| - if (status == PIPELINE_OK) {
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - }
|
| -
|
| - pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
|
| - &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - PipelineStatus SetSeekExpectations(TeardownState state,
|
| - StopOrError stop_or_error) {
|
| - PipelineStatus status = PIPELINE_OK;
|
| - base::Closure stop_cb = base::Bind(
|
| - &CallbackHelper::OnStop, base::Unretained(&callbacks_));
|
| -
|
| - if (state == kFlushing) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
|
| - SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - } else {
|
| - status = PIPELINE_ERROR_READ;
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(SetError(pipeline_.get(), status),
|
| - SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - }
|
| -
|
| - return status;
|
| - }
|
| -
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(SetBufferingState(&buffering_state_cb_,
|
| - BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| -
|
| - if (state == kSeeking) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*demuxer_, Seek(_, _))
|
| - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
|
| - RunCallback<1>(PIPELINE_OK)));
|
| - } else {
|
| - status = PIPELINE_ERROR_READ;
|
| - EXPECT_CALL(*demuxer_, Seek(_, _))
|
| - .WillOnce(RunCallback<1>(status));
|
| - }
|
| -
|
| - return status;
|
| - }
|
| -
|
| - NOTREACHED() << "State not supported: " << state;
|
| - return status;
|
| - }
|
| -
|
| - void DoSuspend(TeardownState state, StopOrError stop_or_error) {
|
| - PipelineStatus status = SetSuspendExpectations(state, stop_or_error);
|
| -
|
| - if (state != kSuspended) {
|
| - // DoStopOrError() handles these for kSuspended.
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| - if (status == PIPELINE_OK) {
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - }
|
| - }
|
| -
|
| - PipelineTest::DoSuspend();
|
| -
|
| - if (state == kSuspended) {
|
| - DoStopOrError(stop_or_error);
|
| - } else if (state == kResuming) {
|
| - PipelineTest::DoResume(base::TimeDelta());
|
| - }
|
| - }
|
| -
|
| - PipelineStatus SetSuspendExpectations(TeardownState state,
|
| - StopOrError stop_or_error) {
|
| - PipelineStatus status = PIPELINE_OK;
|
| - base::Closure stop_cb =
|
| - base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_));
|
| -
|
| - EXPECT_CALL(*renderer_, SetPlaybackRate(0));
|
| - if (state == kSuspended || state == kResuming) {
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(
|
| - SetBufferingState(&buffering_state_cb_, BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
|
| - if (state == kResuming) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*demuxer_, Seek(_, _))
|
| - .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
|
| - RunCallback<1>(PIPELINE_OK)));
|
| - EXPECT_CALL(callbacks_, OnResume(PIPELINE_OK));
|
| - } else {
|
| - status = PIPELINE_ERROR_READ;
|
| - EXPECT_CALL(*demuxer_, Seek(_, _)).WillOnce(RunCallback<1>(status));
|
| - EXPECT_CALL(callbacks_, OnResume(status));
|
| - }
|
| - }
|
| - return status;
|
| - } else if (state == kSuspending) {
|
| - if (stop_or_error == kStop) {
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(DoAll(
|
| - Stop(pipeline_.get(), stop_cb),
|
| - SetBufferingState(&buffering_state_cb_, BUFFERING_HAVE_NOTHING),
|
| - RunClosure<0>()));
|
| - EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| - EXPECT_CALL(callbacks_, OnSuspend(PIPELINE_OK));
|
| - } else {
|
| - status = PIPELINE_ERROR_READ;
|
| - EXPECT_CALL(*renderer_, Flush(_))
|
| - .WillOnce(SetError(pipeline_.get(), status));
|
| - EXPECT_CALL(callbacks_, OnSuspend(status));
|
| - }
|
| - return status;
|
| - }
|
| -
|
| - NOTREACHED() << "State not supported: " << state;
|
| - return status;
|
| - }
|
| -
|
| - void DoStopOrError(StopOrError stop_or_error) {
|
| - InSequence s;
|
| -
|
| - EXPECT_CALL(*demuxer_, Stop());
|
| -
|
| - switch (stop_or_error) {
|
| - case kStop:
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->Stop(base::Bind(
|
| - &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - break;
|
| -
|
| - case kError:
|
| - EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
|
| - pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
|
| - break;
|
| -
|
| - case kErrorAndStop:
|
| - EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
|
| - ExpectPipelineStopAndDestroyPipeline();
|
| - pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
|
| - message_loop_.RunUntilIdle();
|
| - pipeline_->Stop(base::Bind(
|
| - &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
|
| - break;
|
| - }
|
| -
|
| - message_loop_.RunUntilIdle();
|
| - }
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
|
| -};
|
| -
|
| -#define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
|
| - TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
|
| - RunTest(k##state, k##stop_or_error); \
|
| - }
|
| -
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, InitRenderer);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Suspending);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Suspended);
|
| -INSTANTIATE_TEARDOWN_TEST(Stop, Resuming);
|
| -
|
| -INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, InitRenderer);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Playing);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Suspending);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Suspended);
|
| -INSTANTIATE_TEARDOWN_TEST(Error, Resuming);
|
| -
|
| -INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
|
| -INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Suspended);
|
| -
|
| -} // namespace media
|
|
|