cc: Fix logic for detecting when raster tasks were throttled
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
bloba7a8cae316cdcc7cf2f56d712cecd1329e473cb3
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <vector>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/threading/simple_thread.h"
12 #include "base/time/clock.h"
13 #include "media/base/clock.h"
14 #include "media/base/fake_text_track_stream.h"
15 #include "media/base/gmock_callback_support.h"
16 #include "media/base/media_log.h"
17 #include "media/base/mock_filters.h"
18 #include "media/base/pipeline.h"
19 #include "media/base/test_helpers.h"
20 #include "media/base/text_renderer.h"
21 #include "media/base/text_track_config.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
25 using ::testing::_;
26 using ::testing::DeleteArg;
27 using ::testing::DoAll;
28 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
29 using ::testing::InSequence;
30 using ::testing::Invoke;
31 using ::testing::InvokeWithoutArgs;
32 using ::testing::Mock;
33 using ::testing::NotNull;
34 using ::testing::Return;
35 using ::testing::SaveArg;
36 using ::testing::StrictMock;
37 using ::testing::WithArg;
39 namespace media {
41 // Demuxer properties.
42 const int kTotalBytes = 1024;
44 ACTION_P(SetDemuxerProperties, duration) {
45 arg0->SetTotalBytes(kTotalBytes);
46 arg0->SetDuration(duration);
49 ACTION_P2(Stop, pipeline, stop_cb) {
50 pipeline->Stop(stop_cb);
53 ACTION_P2(SetError, pipeline, status) {
54 pipeline->SetErrorForTesting(status);
57 // Used for setting expectations on pipeline callbacks. Using a StrictMock
58 // also lets us test for missing callbacks.
59 class CallbackHelper {
60 public:
61 CallbackHelper() {}
62 virtual ~CallbackHelper() {}
64 MOCK_METHOD1(OnStart, void(PipelineStatus));
65 MOCK_METHOD1(OnSeek, void(PipelineStatus));
66 MOCK_METHOD0(OnStop, void());
67 MOCK_METHOD0(OnEnded, void());
68 MOCK_METHOD1(OnError, void(PipelineStatus));
69 MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState));
70 MOCK_METHOD0(OnDurationChange, void());
72 private:
73 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
76 // TODO(scherkus): even though some filters are initialized on separate
77 // threads these test aren't flaky... why? It's because filters' Initialize()
78 // is executed on |message_loop_| and the mock filters instantly call
79 // InitializationComplete(), which keeps the pipeline humming along. If
80 // either filters don't call InitializationComplete() immediately or filter
81 // initialization is moved to a separate thread this test will become flaky.
82 class PipelineTest : public ::testing::Test {
83 public:
84 PipelineTest()
85 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
86 new MediaLog())),
87 filter_collection_(new FilterCollection()),
88 demuxer_(new MockDemuxer()) {
89 filter_collection_->SetDemuxer(demuxer_.get());
91 video_renderer_ = new MockVideoRenderer();
92 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
93 filter_collection_->SetVideoRenderer(video_renderer.Pass());
95 audio_renderer_ = new MockAudioRenderer();
96 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
97 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
99 text_renderer_ = new TextRenderer(
100 message_loop_.message_loop_proxy(),
101 base::Bind(&PipelineTest::OnAddTextTrack,
102 base::Unretained(this)));
103 scoped_ptr<TextRenderer> text_renderer(text_renderer_);
104 filter_collection_->SetTextRenderer(text_renderer.Pass());
106 // InitializeDemuxer() adds overriding expectations for expected non-NULL
107 // streams.
108 DemuxerStream* null_pointer = NULL;
109 EXPECT_CALL(*demuxer_, GetStream(_))
110 .WillRepeatedly(Return(null_pointer));
112 EXPECT_CALL(*demuxer_, GetStartTime())
113 .WillRepeatedly(Return(base::TimeDelta()));
116 virtual ~PipelineTest() {
117 if (!pipeline_ || !pipeline_->IsRunning())
118 return;
120 ExpectStop();
122 // The mock demuxer doesn't stop the fake text track stream,
123 // so just stop it manually.
124 if (text_stream_) {
125 text_stream_->Stop();
126 message_loop_.RunUntilIdle();
129 // Expect a stop callback if we were started.
130 EXPECT_CALL(callbacks_, OnStop());
131 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
132 base::Unretained(&callbacks_)));
133 message_loop_.RunUntilIdle();
136 protected:
137 // Sets up expectations to allow the demuxer to initialize.
138 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
139 void InitializeDemuxer(MockDemuxerStreamVector* streams,
140 const base::TimeDelta& duration) {
141 EXPECT_CALL(callbacks_, OnDurationChange());
142 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
143 .WillOnce(DoAll(SetDemuxerProperties(duration),
144 RunCallback<1>(PIPELINE_OK)));
146 // Configure the demuxer to return the streams.
147 for (size_t i = 0; i < streams->size(); ++i) {
148 DemuxerStream* stream = (*streams)[i];
149 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
150 .WillRepeatedly(Return(stream));
154 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
155 // Initialize with a default non-zero duration.
156 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
159 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
160 DemuxerStream::Type type) {
161 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
162 new StrictMock<MockDemuxerStream>(type));
163 return stream.Pass();
166 // Sets up expectations to allow the video renderer to initialize.
167 void InitializeVideoRenderer(DemuxerStream* stream) {
168 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _))
169 .WillOnce(RunCallback<1>(PIPELINE_OK));
170 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
172 // Startup sequence.
173 EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _))
174 .WillOnce(RunCallback<1>(PIPELINE_OK));
175 EXPECT_CALL(*video_renderer_, Play(_))
176 .WillOnce(RunClosure<0>());
179 // Sets up expectations to allow the audio renderer to initialize.
180 void InitializeAudioRenderer(DemuxerStream* stream,
181 bool disable_after_init_cb) {
182 if (disable_after_init_cb) {
183 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _))
184 .WillOnce(DoAll(RunCallback<1>(PIPELINE_OK),
185 WithArg<6>(RunClosure<0>()))); // |disabled_cb|.
186 } else {
187 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _, _))
188 .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_),
189 RunCallback<1>(PIPELINE_OK)));
193 void AddTextStream() {
194 EXPECT_CALL(*this, OnAddTextTrack(_,_))
195 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
196 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
197 TextTrackConfig(kTextSubtitles, "", "", ""));
200 // Sets up expectations on the callback and initializes the pipeline. Called
201 // after tests have set expectations any filters they wish to use.
202 void InitializePipeline(PipelineStatus start_status) {
203 EXPECT_CALL(callbacks_, OnStart(start_status));
205 if (start_status == PIPELINE_OK) {
206 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
208 if (audio_stream_) {
209 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
210 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
212 // Startup sequence.
213 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
214 .WillOnce(RunCallback<1>(PIPELINE_OK));
215 EXPECT_CALL(*audio_renderer_, Play(_))
216 .WillOnce(RunClosure<0>());
218 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
221 pipeline_->Start(
222 filter_collection_.Pass(),
223 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
224 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
225 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
226 base::Bind(&CallbackHelper::OnBufferingState,
227 base::Unretained(&callbacks_)),
228 base::Bind(&CallbackHelper::OnDurationChange,
229 base::Unretained(&callbacks_)));
230 message_loop_.RunUntilIdle();
233 void CreateAudioStream() {
234 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
237 void CreateVideoStream() {
238 video_stream_ = CreateStream(DemuxerStream::VIDEO);
239 video_stream_->set_video_decoder_config(video_decoder_config_);
242 void CreateTextStream() {
243 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream);
244 text_stream_ = text_stream.Pass();
247 MockDemuxerStream* audio_stream() {
248 return audio_stream_.get();
251 MockDemuxerStream* video_stream() {
252 return video_stream_.get();
255 FakeTextTrackStream* text_stream() {
256 return text_stream_.get();
259 void ExpectSeek(const base::TimeDelta& seek_time) {
260 // Every filter should receive a call to Seek().
261 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
262 .WillOnce(RunCallback<1>(PIPELINE_OK));
264 if (audio_stream_) {
265 EXPECT_CALL(*audio_renderer_, Pause(_))
266 .WillOnce(RunClosure<0>());
267 EXPECT_CALL(*audio_renderer_, Flush(_))
268 .WillOnce(RunClosure<0>());
269 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
270 .WillOnce(RunCallback<1>(PIPELINE_OK));
271 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
272 EXPECT_CALL(*audio_renderer_, SetVolume(_));
273 EXPECT_CALL(*audio_renderer_, Play(_))
274 .WillOnce(RunClosure<0>());
277 if (video_stream_) {
278 EXPECT_CALL(*video_renderer_, Pause(_))
279 .WillOnce(RunClosure<0>());
280 EXPECT_CALL(*video_renderer_, Flush(_))
281 .WillOnce(RunClosure<0>());
282 EXPECT_CALL(*video_renderer_, Preroll(seek_time, _))
283 .WillOnce(RunCallback<1>(PIPELINE_OK));
284 EXPECT_CALL(*video_renderer_, SetPlaybackRate(_));
285 EXPECT_CALL(*video_renderer_, Play(_))
286 .WillOnce(RunClosure<0>());
289 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
291 // We expect a successful seek callback.
292 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
295 void DoSeek(const base::TimeDelta& seek_time) {
296 pipeline_->Seek(seek_time,
297 base::Bind(&CallbackHelper::OnSeek,
298 base::Unretained(&callbacks_)));
300 // We expect the time to be updated only after the seek has completed.
301 EXPECT_NE(seek_time, pipeline_->GetMediaTime());
302 message_loop_.RunUntilIdle();
303 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
306 void ExpectStop() {
307 if (demuxer_)
308 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
310 if (audio_stream_)
311 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
313 if (video_stream_)
314 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
317 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
318 const AddTextTrackDoneCB&));
320 void DoOnAddTextTrack(const TextTrackConfig& config,
321 const AddTextTrackDoneCB& done_cb) {
322 scoped_ptr<TextTrack> text_track(new MockTextTrack);
323 done_cb.Run(text_track.Pass());
326 // Fixture members.
327 StrictMock<CallbackHelper> callbacks_;
328 base::SimpleTestTickClock test_tick_clock_;
329 base::MessageLoop message_loop_;
330 scoped_ptr<Pipeline> pipeline_;
332 scoped_ptr<FilterCollection> filter_collection_;
333 scoped_ptr<MockDemuxer> demuxer_;
334 MockVideoRenderer* video_renderer_;
335 MockAudioRenderer* audio_renderer_;
336 StrictMock<CallbackHelper> text_renderer_callbacks_;
337 TextRenderer* text_renderer_;
338 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
339 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
340 scoped_ptr<FakeTextTrackStream> text_stream_;
341 AudioRenderer::TimeCB audio_time_cb_;
342 VideoDecoderConfig video_decoder_config_;
344 private:
345 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
348 // Test that playback controls methods no-op when the pipeline hasn't been
349 // started.
350 TEST_F(PipelineTest, NotStarted) {
351 const base::TimeDelta kZero;
353 EXPECT_FALSE(pipeline_->IsRunning());
354 EXPECT_FALSE(pipeline_->HasAudio());
355 EXPECT_FALSE(pipeline_->HasVideo());
357 // Setting should still work.
358 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
359 pipeline_->SetPlaybackRate(-1.0f);
360 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
361 pipeline_->SetPlaybackRate(1.0f);
362 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
364 // Setting should still work.
365 EXPECT_EQ(1.0f, pipeline_->GetVolume());
366 pipeline_->SetVolume(-1.0f);
367 EXPECT_EQ(1.0f, pipeline_->GetVolume());
368 pipeline_->SetVolume(0.0f);
369 EXPECT_EQ(0.0f, pipeline_->GetVolume());
371 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
372 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
373 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
375 EXPECT_EQ(0, pipeline_->GetTotalBytes());
377 // Should always get set to zero.
378 gfx::Size size(1, 1);
379 pipeline_->GetNaturalVideoSize(&size);
380 EXPECT_EQ(0, size.width());
381 EXPECT_EQ(0, size.height());
384 TEST_F(PipelineTest, NeverInitializes) {
385 // Don't execute the callback passed into Initialize().
386 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
388 // This test hangs during initialization by never calling
389 // InitializationComplete(). StrictMock<> will ensure that the callback is
390 // never executed.
391 pipeline_->Start(
392 filter_collection_.Pass(),
393 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
394 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
395 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
396 base::Bind(&CallbackHelper::OnBufferingState,
397 base::Unretained(&callbacks_)),
398 base::Bind(&CallbackHelper::OnDurationChange,
399 base::Unretained(&callbacks_)));
400 message_loop_.RunUntilIdle();
403 // Because our callback will get executed when the test tears down, we'll
404 // verify that nothing has been called, then set our expectation for the call
405 // made during tear down.
406 Mock::VerifyAndClear(&callbacks_);
407 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
410 TEST_F(PipelineTest, URLNotFound) {
411 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
412 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
413 EXPECT_CALL(*demuxer_, Stop(_))
414 .WillOnce(RunClosure<0>());
416 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
419 TEST_F(PipelineTest, NoStreams) {
420 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
421 .WillOnce(RunCallback<1>(PIPELINE_OK));
422 EXPECT_CALL(*demuxer_, Stop(_))
423 .WillOnce(RunClosure<0>());
425 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
428 TEST_F(PipelineTest, AudioStream) {
429 CreateAudioStream();
430 MockDemuxerStreamVector streams;
431 streams.push_back(audio_stream());
433 InitializeDemuxer(&streams);
434 InitializeAudioRenderer(audio_stream(), false);
436 InitializePipeline(PIPELINE_OK);
437 EXPECT_TRUE(pipeline_->HasAudio());
438 EXPECT_FALSE(pipeline_->HasVideo());
441 TEST_F(PipelineTest, VideoStream) {
442 CreateVideoStream();
443 MockDemuxerStreamVector streams;
444 streams.push_back(video_stream());
446 InitializeDemuxer(&streams);
447 InitializeVideoRenderer(video_stream());
449 InitializePipeline(PIPELINE_OK);
450 EXPECT_FALSE(pipeline_->HasAudio());
451 EXPECT_TRUE(pipeline_->HasVideo());
454 TEST_F(PipelineTest, AudioVideoStream) {
455 CreateAudioStream();
456 CreateVideoStream();
457 MockDemuxerStreamVector streams;
458 streams.push_back(audio_stream());
459 streams.push_back(video_stream());
461 InitializeDemuxer(&streams);
462 InitializeAudioRenderer(audio_stream(), false);
463 InitializeVideoRenderer(video_stream());
465 InitializePipeline(PIPELINE_OK);
466 EXPECT_TRUE(pipeline_->HasAudio());
467 EXPECT_TRUE(pipeline_->HasVideo());
470 TEST_F(PipelineTest, VideoTextStream) {
471 CreateVideoStream();
472 CreateTextStream();
473 MockDemuxerStreamVector streams;
474 streams.push_back(video_stream());
476 InitializeDemuxer(&streams);
477 InitializeVideoRenderer(video_stream());
479 InitializePipeline(PIPELINE_OK);
480 EXPECT_FALSE(pipeline_->HasAudio());
481 EXPECT_TRUE(pipeline_->HasVideo());
483 AddTextStream();
484 message_loop_.RunUntilIdle();
487 TEST_F(PipelineTest, VideoAudioTextStream) {
488 CreateVideoStream();
489 CreateAudioStream();
490 CreateTextStream();
491 MockDemuxerStreamVector streams;
492 streams.push_back(video_stream());
493 streams.push_back(audio_stream());
495 InitializeDemuxer(&streams);
496 InitializeVideoRenderer(video_stream());
497 InitializeAudioRenderer(audio_stream(), false);
499 InitializePipeline(PIPELINE_OK);
500 EXPECT_TRUE(pipeline_->HasAudio());
501 EXPECT_TRUE(pipeline_->HasVideo());
503 AddTextStream();
504 message_loop_.RunUntilIdle();
507 TEST_F(PipelineTest, Seek) {
508 CreateAudioStream();
509 CreateVideoStream();
510 CreateTextStream();
511 MockDemuxerStreamVector streams;
512 streams.push_back(audio_stream());
513 streams.push_back(video_stream());
515 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
516 InitializeAudioRenderer(audio_stream(), false);
517 InitializeVideoRenderer(video_stream());
519 // Initialize then seek!
520 InitializePipeline(PIPELINE_OK);
522 AddTextStream();
523 message_loop_.RunUntilIdle();
525 // Every filter should receive a call to Seek().
526 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
527 ExpectSeek(expected);
528 DoSeek(expected);
531 TEST_F(PipelineTest, SetVolume) {
532 CreateAudioStream();
533 MockDemuxerStreamVector streams;
534 streams.push_back(audio_stream());
536 InitializeDemuxer(&streams);
537 InitializeAudioRenderer(audio_stream(), false);
539 // The audio renderer should receive a call to SetVolume().
540 float expected = 0.5f;
541 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
543 // Initialize then set volume!
544 InitializePipeline(PIPELINE_OK);
545 pipeline_->SetVolume(expected);
548 TEST_F(PipelineTest, Properties) {
549 CreateVideoStream();
550 MockDemuxerStreamVector streams;
551 streams.push_back(video_stream());
553 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
554 InitializeDemuxer(&streams, kDuration);
555 InitializeVideoRenderer(video_stream());
557 InitializePipeline(PIPELINE_OK);
558 EXPECT_EQ(kDuration.ToInternalValue(),
559 pipeline_->GetMediaDuration().ToInternalValue());
560 EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes());
561 EXPECT_FALSE(pipeline_->DidLoadingProgress());
564 TEST_F(PipelineTest, GetBufferedTimeRanges) {
565 CreateVideoStream();
566 MockDemuxerStreamVector streams;
567 streams.push_back(video_stream());
569 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
570 InitializeDemuxer(&streams, kDuration);
571 InitializeVideoRenderer(video_stream());
573 InitializePipeline(PIPELINE_OK);
575 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
577 EXPECT_FALSE(pipeline_->DidLoadingProgress());
578 pipeline_->AddBufferedByteRange(0, kTotalBytes / 8);
579 EXPECT_TRUE(pipeline_->DidLoadingProgress());
580 EXPECT_FALSE(pipeline_->DidLoadingProgress());
581 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
582 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
583 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
584 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
585 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
586 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
588 base::TimeDelta kSeekTime = kDuration / 2;
589 ExpectSeek(kSeekTime);
590 DoSeek(kSeekTime);
592 EXPECT_TRUE(pipeline_->DidLoadingProgress());
593 EXPECT_FALSE(pipeline_->DidLoadingProgress());
594 pipeline_->AddBufferedByteRange(kTotalBytes / 2,
595 kTotalBytes / 2 + kTotalBytes / 8);
596 EXPECT_TRUE(pipeline_->DidLoadingProgress());
597 EXPECT_FALSE(pipeline_->DidLoadingProgress());
598 EXPECT_EQ(2u, pipeline_->GetBufferedTimeRanges().size());
599 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
600 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
601 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(1));
602 EXPECT_EQ(kDuration / 2 + kDuration / 8,
603 pipeline_->GetBufferedTimeRanges().end(1));
605 pipeline_->AddBufferedTimeRange(kDuration / 4, 3 * kDuration / 8);
606 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
607 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
608 EXPECT_EQ(kDuration / 4, pipeline_->GetBufferedTimeRanges().start(1));
609 EXPECT_EQ(3* kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1));
610 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(2));
611 EXPECT_EQ(kDuration / 2 + kDuration / 8,
612 pipeline_->GetBufferedTimeRanges().end(2));
615 TEST_F(PipelineTest, DisableAudioRenderer) {
616 CreateAudioStream();
617 CreateVideoStream();
618 MockDemuxerStreamVector streams;
619 streams.push_back(audio_stream());
620 streams.push_back(video_stream());
622 InitializeDemuxer(&streams);
623 InitializeAudioRenderer(audio_stream(), false);
624 InitializeVideoRenderer(video_stream());
626 InitializePipeline(PIPELINE_OK);
627 EXPECT_TRUE(pipeline_->HasAudio());
628 EXPECT_TRUE(pipeline_->HasVideo());
630 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
631 pipeline_->OnAudioDisabled();
633 // Verify that ended event is fired when video ends.
634 EXPECT_CALL(callbacks_, OnEnded());
635 pipeline_->OnVideoRendererEnded();
638 TEST_F(PipelineTest, DisableAudioRendererDuringInit) {
639 CreateAudioStream();
640 CreateVideoStream();
641 MockDemuxerStreamVector streams;
642 streams.push_back(audio_stream());
643 streams.push_back(video_stream());
645 InitializeDemuxer(&streams);
646 InitializeAudioRenderer(audio_stream(), true);
647 InitializeVideoRenderer(video_stream());
649 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
651 InitializePipeline(PIPELINE_OK);
652 EXPECT_FALSE(pipeline_->HasAudio());
653 EXPECT_TRUE(pipeline_->HasVideo());
655 // Verify that ended event is fired when video ends.
656 EXPECT_CALL(callbacks_, OnEnded());
657 pipeline_->OnVideoRendererEnded();
660 TEST_F(PipelineTest, EndedCallback) {
661 CreateAudioStream();
662 CreateVideoStream();
663 CreateTextStream();
664 MockDemuxerStreamVector streams;
665 streams.push_back(audio_stream());
666 streams.push_back(video_stream());
668 InitializeDemuxer(&streams);
669 InitializeAudioRenderer(audio_stream(), false);
670 InitializeVideoRenderer(video_stream());
671 InitializePipeline(PIPELINE_OK);
673 AddTextStream();
675 // The ended callback shouldn't run until all renderers have ended.
676 pipeline_->OnAudioRendererEnded();
677 message_loop_.RunUntilIdle();
679 pipeline_->OnVideoRendererEnded();
680 message_loop_.RunUntilIdle();
682 EXPECT_CALL(callbacks_, OnEnded());
683 text_stream()->SendEosNotification();
684 message_loop_.RunUntilIdle();
687 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
688 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
690 CreateAudioStream();
691 CreateVideoStream();
692 MockDemuxerStreamVector streams;
693 streams.push_back(audio_stream());
694 streams.push_back(video_stream());
696 // Replace the clock so we can simulate wallclock time advancing w/o using
697 // Sleep().
698 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
700 InitializeDemuxer(&streams, duration);
701 InitializeAudioRenderer(audio_stream(), false);
702 InitializeVideoRenderer(video_stream());
703 InitializePipeline(PIPELINE_OK);
705 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
707 float playback_rate = 1.0f;
708 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
709 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
710 pipeline_->SetPlaybackRate(playback_rate);
711 message_loop_.RunUntilIdle();
713 InSequence s;
715 // Verify that the clock doesn't advance since it hasn't been started by
716 // a time update from the audio stream.
717 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
718 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
719 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
721 // Signal end of audio stream.
722 pipeline_->OnAudioRendererEnded();
723 message_loop_.RunUntilIdle();
725 // Verify that the clock advances.
726 start_time = pipeline_->GetMediaTime().ToInternalValue();
727 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
728 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
730 // Signal end of video stream and make sure OnEnded() callback occurs.
731 EXPECT_CALL(callbacks_, OnEnded());
732 pipeline_->OnVideoRendererEnded();
735 TEST_F(PipelineTest, ErrorDuringSeek) {
736 CreateAudioStream();
737 MockDemuxerStreamVector streams;
738 streams.push_back(audio_stream());
740 InitializeDemuxer(&streams);
741 InitializeAudioRenderer(audio_stream(), false);
742 InitializePipeline(PIPELINE_OK);
744 float playback_rate = 1.0f;
745 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
746 pipeline_->SetPlaybackRate(playback_rate);
747 message_loop_.RunUntilIdle();
749 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
751 // Preroll() isn't called as the demuxer errors out first.
752 EXPECT_CALL(*audio_renderer_, Pause(_))
753 .WillOnce(RunClosure<0>());
754 EXPECT_CALL(*audio_renderer_, Flush(_))
755 .WillOnce(RunClosure<0>());
756 EXPECT_CALL(*audio_renderer_, Stop(_))
757 .WillOnce(RunClosure<0>());
759 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
760 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
761 EXPECT_CALL(*demuxer_, Stop(_))
762 .WillOnce(RunClosure<0>());
764 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
765 base::Unretained(&callbacks_)));
766 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
767 message_loop_.RunUntilIdle();
770 // Invoked function OnError. This asserts that the pipeline does not enqueue
771 // non-teardown related tasks while tearing down.
772 static void TestNoCallsAfterError(
773 Pipeline* pipeline, base::MessageLoop* message_loop,
774 PipelineStatus /* status */) {
775 CHECK(pipeline);
776 CHECK(message_loop);
778 // When we get to this stage, the message loop should be empty.
779 EXPECT_TRUE(message_loop->IsIdleForTesting());
781 // Make calls on pipeline after error has occurred.
782 pipeline->SetPlaybackRate(0.5f);
783 pipeline->SetVolume(0.5f);
785 // No additional tasks should be queued as a result of these calls.
786 EXPECT_TRUE(message_loop->IsIdleForTesting());
789 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
790 CreateAudioStream();
791 MockDemuxerStreamVector streams;
792 streams.push_back(audio_stream());
794 InitializeDemuxer(&streams);
795 InitializeAudioRenderer(audio_stream(), false);
796 InitializePipeline(PIPELINE_OK);
798 // Trigger additional requests on the pipeline during tear down from error.
799 base::Callback<void(PipelineStatus)> cb = base::Bind(
800 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
801 ON_CALL(callbacks_, OnError(_))
802 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
804 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
806 // Seek() isn't called as the demuxer errors out first.
807 EXPECT_CALL(*audio_renderer_, Pause(_))
808 .WillOnce(RunClosure<0>());
809 EXPECT_CALL(*audio_renderer_, Flush(_))
810 .WillOnce(RunClosure<0>());
811 EXPECT_CALL(*audio_renderer_, Stop(_))
812 .WillOnce(RunClosure<0>());
814 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
815 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
816 EXPECT_CALL(*demuxer_, Stop(_))
817 .WillOnce(RunClosure<0>());
819 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
820 base::Unretained(&callbacks_)));
821 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
822 message_loop_.RunUntilIdle();
825 TEST_F(PipelineTest, StartTimeIsZero) {
826 CreateVideoStream();
827 MockDemuxerStreamVector streams;
828 streams.push_back(video_stream());
830 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
831 InitializeDemuxer(&streams, kDuration);
832 InitializeVideoRenderer(video_stream());
834 InitializePipeline(PIPELINE_OK);
835 EXPECT_FALSE(pipeline_->HasAudio());
836 EXPECT_TRUE(pipeline_->HasVideo());
838 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
841 TEST_F(PipelineTest, StartTimeIsNonZero) {
842 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
843 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
845 EXPECT_CALL(*demuxer_, GetStartTime())
846 .WillRepeatedly(Return(kStartTime));
848 CreateVideoStream();
849 MockDemuxerStreamVector streams;
850 streams.push_back(video_stream());
852 InitializeDemuxer(&streams, kDuration);
853 InitializeVideoRenderer(video_stream());
855 InitializePipeline(PIPELINE_OK);
856 EXPECT_FALSE(pipeline_->HasAudio());
857 EXPECT_TRUE(pipeline_->HasVideo());
859 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
862 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
863 int time_in_ms,
864 int max_time_in_ms) {
865 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
866 base::TimeDelta::FromMilliseconds(max_time_in_ms));
869 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
870 CreateAudioStream();
871 MockDemuxerStreamVector streams;
872 streams.push_back(audio_stream());
874 InitializeDemuxer(&streams);
875 InitializeAudioRenderer(audio_stream(), false);
876 InitializePipeline(PIPELINE_OK);
878 float playback_rate = 1.0f;
879 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
880 pipeline_->SetPlaybackRate(playback_rate);
881 message_loop_.RunUntilIdle();
883 // Provide an initial time update so that the pipeline transitions out of the
884 // "waiting for time update" state.
885 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
886 base::TimeDelta::FromMilliseconds(500));
888 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
890 // Arrange to trigger a time update while the demuxer is in the middle of
891 // seeking. This update should be ignored by the pipeline and the clock should
892 // not get updated.
893 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
894 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
895 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
896 RunCallback<1>(PIPELINE_OK)));
898 EXPECT_CALL(*audio_renderer_, Pause(_))
899 .WillOnce(RunClosure<0>());
900 EXPECT_CALL(*audio_renderer_, Flush(_))
901 .WillOnce(RunClosure<0>());
902 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
903 .WillOnce(RunCallback<1>(PIPELINE_OK));
904 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
905 EXPECT_CALL(*audio_renderer_, SetVolume(_));
906 EXPECT_CALL(*audio_renderer_, Play(_))
907 .WillOnce(RunClosure<0>());
909 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
910 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
911 DoSeek(seek_time);
913 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
915 // Now that the seek is complete, verify that time updates advance the current
916 // time.
917 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
918 audio_time_cb_.Run(new_time, new_time);
920 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
923 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
924 // |pipeline| will go out of scope.
927 TEST_F(PipelineTest, DeleteAfterStop) {
928 CreateAudioStream();
929 MockDemuxerStreamVector streams;
930 streams.push_back(audio_stream());
931 InitializeDemuxer(&streams);
932 InitializeAudioRenderer(audio_stream(), false);
933 InitializePipeline(PIPELINE_OK);
935 ExpectStop();
937 Pipeline* pipeline = pipeline_.get();
938 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
939 message_loop_.RunUntilIdle();
942 class PipelineTeardownTest : public PipelineTest {
943 public:
944 enum TeardownState {
945 kInitDemuxer,
946 kInitAudioRenderer,
947 kInitVideoRenderer,
948 kPausing,
949 kFlushing,
950 kSeeking,
951 kPrerolling,
952 kStarting,
953 kPlaying,
956 enum StopOrError {
957 kStop,
958 kError,
959 kErrorAndStop,
962 PipelineTeardownTest() {}
963 virtual ~PipelineTeardownTest() {}
965 void RunTest(TeardownState state, StopOrError stop_or_error) {
966 switch (state) {
967 case kInitDemuxer:
968 case kInitAudioRenderer:
969 case kInitVideoRenderer:
970 DoInitialize(state, stop_or_error);
971 break;
973 case kPausing:
974 case kFlushing:
975 case kSeeking:
976 case kPrerolling:
977 case kStarting:
978 DoInitialize(state, stop_or_error);
979 DoSeek(state, stop_or_error);
980 break;
982 case kPlaying:
983 DoInitialize(state, stop_or_error);
984 DoStopOrError(stop_or_error);
985 break;
989 private:
990 // TODO(scherkus): We do radically different things whether teardown is
991 // invoked via stop vs error. The teardown path should be the same,
992 // see http://crbug.com/110228
993 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
994 PipelineStatus expected_status =
995 SetInitializeExpectations(state, stop_or_error);
997 EXPECT_CALL(callbacks_, OnStart(expected_status));
998 pipeline_->Start(
999 filter_collection_.Pass(),
1000 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
1001 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
1002 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
1003 base::Bind(&CallbackHelper::OnBufferingState,
1004 base::Unretained(&callbacks_)),
1005 base::Bind(&CallbackHelper::OnDurationChange,
1006 base::Unretained(&callbacks_)));
1007 message_loop_.RunUntilIdle();
1010 PipelineStatus SetInitializeExpectations(TeardownState state,
1011 StopOrError stop_or_error) {
1012 PipelineStatus status = PIPELINE_OK;
1013 base::Closure stop_cb = base::Bind(
1014 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1016 if (state == kInitDemuxer) {
1017 if (stop_or_error == kStop) {
1018 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1019 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1020 RunCallback<1>(PIPELINE_OK)));
1021 EXPECT_CALL(callbacks_, OnStop());
1022 } else {
1023 status = DEMUXER_ERROR_COULD_NOT_OPEN;
1024 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1025 .WillOnce(RunCallback<1>(status));
1028 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1029 return status;
1032 CreateAudioStream();
1033 CreateVideoStream();
1034 MockDemuxerStreamVector streams;
1035 streams.push_back(audio_stream());
1036 streams.push_back(video_stream());
1037 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
1039 if (state == kInitAudioRenderer) {
1040 if (stop_or_error == kStop) {
1041 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1042 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1043 RunCallback<1>(PIPELINE_OK)));
1044 EXPECT_CALL(callbacks_, OnStop());
1045 } else {
1046 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1047 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1048 .WillOnce(RunCallback<1>(status));
1051 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1052 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1053 return status;
1056 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1057 .WillOnce(RunCallback<1>(PIPELINE_OK));
1059 if (state == kInitVideoRenderer) {
1060 if (stop_or_error == kStop) {
1061 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
1062 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1063 RunCallback<1>(PIPELINE_OK)));
1064 EXPECT_CALL(callbacks_, OnStop());
1065 } else {
1066 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1067 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
1068 .WillOnce(RunCallback<1>(status));
1071 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1072 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1073 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1074 return status;
1077 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
1078 .WillOnce(RunCallback<1>(PIPELINE_OK));
1080 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
1082 // If we get here it's a successful initialization.
1083 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
1084 .WillOnce(RunCallback<1>(PIPELINE_OK));
1085 EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _))
1086 .WillOnce(RunCallback<1>(PIPELINE_OK));
1088 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1089 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1090 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1092 EXPECT_CALL(*audio_renderer_, Play(_))
1093 .WillOnce(RunClosure<0>());
1094 EXPECT_CALL(*video_renderer_, Play(_))
1095 .WillOnce(RunClosure<0>());
1097 if (status == PIPELINE_OK)
1098 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
1100 return status;
1103 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1104 InSequence s;
1105 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1107 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1108 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1109 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1110 EXPECT_CALL(callbacks_, OnSeek(status));
1112 if (status == PIPELINE_OK) {
1113 EXPECT_CALL(callbacks_, OnStop());
1116 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1117 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1118 message_loop_.RunUntilIdle();
1121 PipelineStatus SetSeekExpectations(TeardownState state,
1122 StopOrError stop_or_error) {
1123 PipelineStatus status = PIPELINE_OK;
1124 base::Closure stop_cb = base::Bind(
1125 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1127 if (state == kPausing) {
1128 if (stop_or_error == kStop) {
1129 EXPECT_CALL(*audio_renderer_, Pause(_))
1130 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1131 } else {
1132 status = PIPELINE_ERROR_READ;
1133 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(
1134 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1137 return status;
1140 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1141 EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1143 if (state == kFlushing) {
1144 if (stop_or_error == kStop) {
1145 EXPECT_CALL(*audio_renderer_, Flush(_))
1146 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1147 } else {
1148 status = PIPELINE_ERROR_READ;
1149 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1150 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1153 return status;
1156 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1157 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1159 if (state == kSeeking) {
1160 if (stop_or_error == kStop) {
1161 EXPECT_CALL(*demuxer_, Seek(_, _))
1162 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1163 RunCallback<1>(PIPELINE_OK)));
1164 } else {
1165 status = PIPELINE_ERROR_READ;
1166 EXPECT_CALL(*demuxer_, Seek(_, _))
1167 .WillOnce(RunCallback<1>(status));
1170 return status;
1173 EXPECT_CALL(*demuxer_, Seek(_, _))
1174 .WillOnce(RunCallback<1>(PIPELINE_OK));
1176 if (state == kPrerolling) {
1177 if (stop_or_error == kStop) {
1178 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1179 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1180 RunCallback<1>(PIPELINE_OK)));
1181 } else {
1182 status = PIPELINE_ERROR_READ;
1183 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1184 .WillOnce(RunCallback<1>(status));
1187 return status;
1190 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1191 .WillOnce(RunCallback<1>(PIPELINE_OK));
1192 EXPECT_CALL(*video_renderer_, Preroll(_, _))
1193 .WillOnce(RunCallback<1>(PIPELINE_OK));
1195 // Playback rate and volume are updated prior to starting.
1196 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1197 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1198 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1200 if (state == kStarting) {
1201 if (stop_or_error == kStop) {
1202 EXPECT_CALL(*audio_renderer_, Play(_))
1203 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1204 } else {
1205 status = PIPELINE_ERROR_READ;
1206 EXPECT_CALL(*audio_renderer_, Play(_)).WillOnce(
1207 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1209 return status;
1212 NOTREACHED() << "State not supported: " << state;
1213 return status;
1216 void DoStopOrError(StopOrError stop_or_error) {
1217 InSequence s;
1219 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1220 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1221 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1223 switch (stop_or_error) {
1224 case kStop:
1225 EXPECT_CALL(callbacks_, OnStop());
1226 pipeline_->Stop(base::Bind(
1227 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1228 break;
1230 case kError:
1231 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1232 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1233 break;
1235 case kErrorAndStop:
1236 EXPECT_CALL(callbacks_, OnStop());
1237 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1238 pipeline_->Stop(base::Bind(
1239 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1240 break;
1243 message_loop_.RunUntilIdle();
1246 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1249 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1250 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1251 RunTest(k##state, k##stop_or_error); \
1254 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1255 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1256 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1257 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1258 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1259 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1260 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1261 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1262 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1264 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1265 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1266 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1267 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1268 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1269 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1270 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1271 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1272 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1274 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1276 } // namespace media