Remove old about scheme URL constants.
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
blob3264226ad02964c2e91daec5eb3a0b6eb4aa9cb6
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 be zero.
378 gfx::Size size = pipeline_->GetInitialNaturalSize();
379 EXPECT_EQ(0, size.width());
380 EXPECT_EQ(0, size.height());
383 TEST_F(PipelineTest, NeverInitializes) {
384 // Don't execute the callback passed into Initialize().
385 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
387 // This test hangs during initialization by never calling
388 // InitializationComplete(). StrictMock<> will ensure that the callback is
389 // never executed.
390 pipeline_->Start(
391 filter_collection_.Pass(),
392 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
393 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
394 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
395 base::Bind(&CallbackHelper::OnBufferingState,
396 base::Unretained(&callbacks_)),
397 base::Bind(&CallbackHelper::OnDurationChange,
398 base::Unretained(&callbacks_)));
399 message_loop_.RunUntilIdle();
402 // Because our callback will get executed when the test tears down, we'll
403 // verify that nothing has been called, then set our expectation for the call
404 // made during tear down.
405 Mock::VerifyAndClear(&callbacks_);
406 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
409 TEST_F(PipelineTest, URLNotFound) {
410 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
411 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
412 EXPECT_CALL(*demuxer_, Stop(_))
413 .WillOnce(RunClosure<0>());
415 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
418 TEST_F(PipelineTest, NoStreams) {
419 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
420 .WillOnce(RunCallback<1>(PIPELINE_OK));
421 EXPECT_CALL(*demuxer_, Stop(_))
422 .WillOnce(RunClosure<0>());
424 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
427 TEST_F(PipelineTest, AudioStream) {
428 CreateAudioStream();
429 MockDemuxerStreamVector streams;
430 streams.push_back(audio_stream());
432 InitializeDemuxer(&streams);
433 InitializeAudioRenderer(audio_stream(), false);
435 InitializePipeline(PIPELINE_OK);
436 EXPECT_TRUE(pipeline_->HasAudio());
437 EXPECT_FALSE(pipeline_->HasVideo());
440 TEST_F(PipelineTest, VideoStream) {
441 CreateVideoStream();
442 MockDemuxerStreamVector streams;
443 streams.push_back(video_stream());
445 InitializeDemuxer(&streams);
446 InitializeVideoRenderer(video_stream());
448 InitializePipeline(PIPELINE_OK);
449 EXPECT_FALSE(pipeline_->HasAudio());
450 EXPECT_TRUE(pipeline_->HasVideo());
453 TEST_F(PipelineTest, AudioVideoStream) {
454 CreateAudioStream();
455 CreateVideoStream();
456 MockDemuxerStreamVector streams;
457 streams.push_back(audio_stream());
458 streams.push_back(video_stream());
460 InitializeDemuxer(&streams);
461 InitializeAudioRenderer(audio_stream(), false);
462 InitializeVideoRenderer(video_stream());
464 InitializePipeline(PIPELINE_OK);
465 EXPECT_TRUE(pipeline_->HasAudio());
466 EXPECT_TRUE(pipeline_->HasVideo());
469 TEST_F(PipelineTest, VideoTextStream) {
470 CreateVideoStream();
471 CreateTextStream();
472 MockDemuxerStreamVector streams;
473 streams.push_back(video_stream());
475 InitializeDemuxer(&streams);
476 InitializeVideoRenderer(video_stream());
478 InitializePipeline(PIPELINE_OK);
479 EXPECT_FALSE(pipeline_->HasAudio());
480 EXPECT_TRUE(pipeline_->HasVideo());
482 AddTextStream();
483 message_loop_.RunUntilIdle();
486 TEST_F(PipelineTest, VideoAudioTextStream) {
487 CreateVideoStream();
488 CreateAudioStream();
489 CreateTextStream();
490 MockDemuxerStreamVector streams;
491 streams.push_back(video_stream());
492 streams.push_back(audio_stream());
494 InitializeDemuxer(&streams);
495 InitializeVideoRenderer(video_stream());
496 InitializeAudioRenderer(audio_stream(), false);
498 InitializePipeline(PIPELINE_OK);
499 EXPECT_TRUE(pipeline_->HasAudio());
500 EXPECT_TRUE(pipeline_->HasVideo());
502 AddTextStream();
503 message_loop_.RunUntilIdle();
506 TEST_F(PipelineTest, Seek) {
507 CreateAudioStream();
508 CreateVideoStream();
509 CreateTextStream();
510 MockDemuxerStreamVector streams;
511 streams.push_back(audio_stream());
512 streams.push_back(video_stream());
514 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
515 InitializeAudioRenderer(audio_stream(), false);
516 InitializeVideoRenderer(video_stream());
518 // Initialize then seek!
519 InitializePipeline(PIPELINE_OK);
521 AddTextStream();
522 message_loop_.RunUntilIdle();
524 // Every filter should receive a call to Seek().
525 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
526 ExpectSeek(expected);
527 DoSeek(expected);
530 TEST_F(PipelineTest, SetVolume) {
531 CreateAudioStream();
532 MockDemuxerStreamVector streams;
533 streams.push_back(audio_stream());
535 InitializeDemuxer(&streams);
536 InitializeAudioRenderer(audio_stream(), false);
538 // The audio renderer should receive a call to SetVolume().
539 float expected = 0.5f;
540 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
542 // Initialize then set volume!
543 InitializePipeline(PIPELINE_OK);
544 pipeline_->SetVolume(expected);
547 TEST_F(PipelineTest, Properties) {
548 CreateVideoStream();
549 MockDemuxerStreamVector streams;
550 streams.push_back(video_stream());
552 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
553 InitializeDemuxer(&streams, kDuration);
554 InitializeVideoRenderer(video_stream());
556 InitializePipeline(PIPELINE_OK);
557 EXPECT_EQ(kDuration.ToInternalValue(),
558 pipeline_->GetMediaDuration().ToInternalValue());
559 EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes());
560 EXPECT_FALSE(pipeline_->DidLoadingProgress());
563 TEST_F(PipelineTest, GetBufferedTimeRanges) {
564 CreateVideoStream();
565 MockDemuxerStreamVector streams;
566 streams.push_back(video_stream());
568 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
569 InitializeDemuxer(&streams, kDuration);
570 InitializeVideoRenderer(video_stream());
572 InitializePipeline(PIPELINE_OK);
574 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
576 EXPECT_FALSE(pipeline_->DidLoadingProgress());
577 pipeline_->AddBufferedByteRange(0, kTotalBytes / 8);
578 EXPECT_TRUE(pipeline_->DidLoadingProgress());
579 EXPECT_FALSE(pipeline_->DidLoadingProgress());
580 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
581 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
582 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
583 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
584 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
585 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
587 base::TimeDelta kSeekTime = kDuration / 2;
588 ExpectSeek(kSeekTime);
589 DoSeek(kSeekTime);
591 EXPECT_TRUE(pipeline_->DidLoadingProgress());
592 EXPECT_FALSE(pipeline_->DidLoadingProgress());
593 pipeline_->AddBufferedByteRange(kTotalBytes / 2,
594 kTotalBytes / 2 + kTotalBytes / 8);
595 EXPECT_TRUE(pipeline_->DidLoadingProgress());
596 EXPECT_FALSE(pipeline_->DidLoadingProgress());
597 EXPECT_EQ(2u, pipeline_->GetBufferedTimeRanges().size());
598 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
599 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
600 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(1));
601 EXPECT_EQ(kDuration / 2 + kDuration / 8,
602 pipeline_->GetBufferedTimeRanges().end(1));
604 pipeline_->AddBufferedTimeRange(kDuration / 4, 3 * kDuration / 8);
605 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
606 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
607 EXPECT_EQ(kDuration / 4, pipeline_->GetBufferedTimeRanges().start(1));
608 EXPECT_EQ(3* kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1));
609 EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(2));
610 EXPECT_EQ(kDuration / 2 + kDuration / 8,
611 pipeline_->GetBufferedTimeRanges().end(2));
614 TEST_F(PipelineTest, DisableAudioRenderer) {
615 CreateAudioStream();
616 CreateVideoStream();
617 MockDemuxerStreamVector streams;
618 streams.push_back(audio_stream());
619 streams.push_back(video_stream());
621 InitializeDemuxer(&streams);
622 InitializeAudioRenderer(audio_stream(), false);
623 InitializeVideoRenderer(video_stream());
625 InitializePipeline(PIPELINE_OK);
626 EXPECT_TRUE(pipeline_->HasAudio());
627 EXPECT_TRUE(pipeline_->HasVideo());
629 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
630 pipeline_->OnAudioDisabled();
632 // Verify that ended event is fired when video ends.
633 EXPECT_CALL(callbacks_, OnEnded());
634 pipeline_->OnVideoRendererEnded();
637 TEST_F(PipelineTest, DisableAudioRendererDuringInit) {
638 CreateAudioStream();
639 CreateVideoStream();
640 MockDemuxerStreamVector streams;
641 streams.push_back(audio_stream());
642 streams.push_back(video_stream());
644 InitializeDemuxer(&streams);
645 InitializeAudioRenderer(audio_stream(), true);
646 InitializeVideoRenderer(video_stream());
648 EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
650 InitializePipeline(PIPELINE_OK);
651 EXPECT_FALSE(pipeline_->HasAudio());
652 EXPECT_TRUE(pipeline_->HasVideo());
654 // Verify that ended event is fired when video ends.
655 EXPECT_CALL(callbacks_, OnEnded());
656 pipeline_->OnVideoRendererEnded();
659 TEST_F(PipelineTest, EndedCallback) {
660 CreateAudioStream();
661 CreateVideoStream();
662 CreateTextStream();
663 MockDemuxerStreamVector streams;
664 streams.push_back(audio_stream());
665 streams.push_back(video_stream());
667 InitializeDemuxer(&streams);
668 InitializeAudioRenderer(audio_stream(), false);
669 InitializeVideoRenderer(video_stream());
670 InitializePipeline(PIPELINE_OK);
672 AddTextStream();
674 // The ended callback shouldn't run until all renderers have ended.
675 pipeline_->OnAudioRendererEnded();
676 message_loop_.RunUntilIdle();
678 pipeline_->OnVideoRendererEnded();
679 message_loop_.RunUntilIdle();
681 EXPECT_CALL(callbacks_, OnEnded());
682 text_stream()->SendEosNotification();
683 message_loop_.RunUntilIdle();
686 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
687 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
689 CreateAudioStream();
690 CreateVideoStream();
691 MockDemuxerStreamVector streams;
692 streams.push_back(audio_stream());
693 streams.push_back(video_stream());
695 // Replace the clock so we can simulate wallclock time advancing w/o using
696 // Sleep().
697 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
699 InitializeDemuxer(&streams, duration);
700 InitializeAudioRenderer(audio_stream(), false);
701 InitializeVideoRenderer(video_stream());
702 InitializePipeline(PIPELINE_OK);
704 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
706 float playback_rate = 1.0f;
707 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
708 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
709 pipeline_->SetPlaybackRate(playback_rate);
710 message_loop_.RunUntilIdle();
712 InSequence s;
714 // Verify that the clock doesn't advance since it hasn't been started by
715 // a time update from the audio stream.
716 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
717 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
718 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
720 // Signal end of audio stream.
721 pipeline_->OnAudioRendererEnded();
722 message_loop_.RunUntilIdle();
724 // Verify that the clock advances.
725 start_time = pipeline_->GetMediaTime().ToInternalValue();
726 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
727 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
729 // Signal end of video stream and make sure OnEnded() callback occurs.
730 EXPECT_CALL(callbacks_, OnEnded());
731 pipeline_->OnVideoRendererEnded();
734 TEST_F(PipelineTest, ErrorDuringSeek) {
735 CreateAudioStream();
736 MockDemuxerStreamVector streams;
737 streams.push_back(audio_stream());
739 InitializeDemuxer(&streams);
740 InitializeAudioRenderer(audio_stream(), false);
741 InitializePipeline(PIPELINE_OK);
743 float playback_rate = 1.0f;
744 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
745 pipeline_->SetPlaybackRate(playback_rate);
746 message_loop_.RunUntilIdle();
748 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
750 // Preroll() isn't called as the demuxer errors out first.
751 EXPECT_CALL(*audio_renderer_, Pause(_))
752 .WillOnce(RunClosure<0>());
753 EXPECT_CALL(*audio_renderer_, Flush(_))
754 .WillOnce(RunClosure<0>());
755 EXPECT_CALL(*audio_renderer_, Stop(_))
756 .WillOnce(RunClosure<0>());
758 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
759 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
760 EXPECT_CALL(*demuxer_, Stop(_))
761 .WillOnce(RunClosure<0>());
763 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
764 base::Unretained(&callbacks_)));
765 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
766 message_loop_.RunUntilIdle();
769 // Invoked function OnError. This asserts that the pipeline does not enqueue
770 // non-teardown related tasks while tearing down.
771 static void TestNoCallsAfterError(
772 Pipeline* pipeline, base::MessageLoop* message_loop,
773 PipelineStatus /* status */) {
774 CHECK(pipeline);
775 CHECK(message_loop);
777 // When we get to this stage, the message loop should be empty.
778 EXPECT_TRUE(message_loop->IsIdleForTesting());
780 // Make calls on pipeline after error has occurred.
781 pipeline->SetPlaybackRate(0.5f);
782 pipeline->SetVolume(0.5f);
784 // No additional tasks should be queued as a result of these calls.
785 EXPECT_TRUE(message_loop->IsIdleForTesting());
788 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
789 CreateAudioStream();
790 MockDemuxerStreamVector streams;
791 streams.push_back(audio_stream());
793 InitializeDemuxer(&streams);
794 InitializeAudioRenderer(audio_stream(), false);
795 InitializePipeline(PIPELINE_OK);
797 // Trigger additional requests on the pipeline during tear down from error.
798 base::Callback<void(PipelineStatus)> cb = base::Bind(
799 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
800 ON_CALL(callbacks_, OnError(_))
801 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
803 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
805 // Seek() isn't called as the demuxer errors out first.
806 EXPECT_CALL(*audio_renderer_, Pause(_))
807 .WillOnce(RunClosure<0>());
808 EXPECT_CALL(*audio_renderer_, Flush(_))
809 .WillOnce(RunClosure<0>());
810 EXPECT_CALL(*audio_renderer_, Stop(_))
811 .WillOnce(RunClosure<0>());
813 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
814 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
815 EXPECT_CALL(*demuxer_, Stop(_))
816 .WillOnce(RunClosure<0>());
818 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
819 base::Unretained(&callbacks_)));
820 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
821 message_loop_.RunUntilIdle();
824 TEST_F(PipelineTest, StartTimeIsZero) {
825 CreateVideoStream();
826 MockDemuxerStreamVector streams;
827 streams.push_back(video_stream());
829 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
830 InitializeDemuxer(&streams, kDuration);
831 InitializeVideoRenderer(video_stream());
833 InitializePipeline(PIPELINE_OK);
834 EXPECT_FALSE(pipeline_->HasAudio());
835 EXPECT_TRUE(pipeline_->HasVideo());
837 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
840 TEST_F(PipelineTest, StartTimeIsNonZero) {
841 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
842 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
844 EXPECT_CALL(*demuxer_, GetStartTime())
845 .WillRepeatedly(Return(kStartTime));
847 CreateVideoStream();
848 MockDemuxerStreamVector streams;
849 streams.push_back(video_stream());
851 InitializeDemuxer(&streams, kDuration);
852 InitializeVideoRenderer(video_stream());
854 InitializePipeline(PIPELINE_OK);
855 EXPECT_FALSE(pipeline_->HasAudio());
856 EXPECT_TRUE(pipeline_->HasVideo());
858 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
861 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
862 int time_in_ms,
863 int max_time_in_ms) {
864 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
865 base::TimeDelta::FromMilliseconds(max_time_in_ms));
868 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
869 CreateAudioStream();
870 MockDemuxerStreamVector streams;
871 streams.push_back(audio_stream());
873 InitializeDemuxer(&streams);
874 InitializeAudioRenderer(audio_stream(), false);
875 InitializePipeline(PIPELINE_OK);
877 float playback_rate = 1.0f;
878 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
879 pipeline_->SetPlaybackRate(playback_rate);
880 message_loop_.RunUntilIdle();
882 // Provide an initial time update so that the pipeline transitions out of the
883 // "waiting for time update" state.
884 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
885 base::TimeDelta::FromMilliseconds(500));
887 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
889 // Arrange to trigger a time update while the demuxer is in the middle of
890 // seeking. This update should be ignored by the pipeline and the clock should
891 // not get updated.
892 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
893 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
894 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
895 RunCallback<1>(PIPELINE_OK)));
897 EXPECT_CALL(*audio_renderer_, Pause(_))
898 .WillOnce(RunClosure<0>());
899 EXPECT_CALL(*audio_renderer_, Flush(_))
900 .WillOnce(RunClosure<0>());
901 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
902 .WillOnce(RunCallback<1>(PIPELINE_OK));
903 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
904 EXPECT_CALL(*audio_renderer_, SetVolume(_));
905 EXPECT_CALL(*audio_renderer_, Play(_))
906 .WillOnce(RunClosure<0>());
908 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
909 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
910 DoSeek(seek_time);
912 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
914 // Now that the seek is complete, verify that time updates advance the current
915 // time.
916 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
917 audio_time_cb_.Run(new_time, new_time);
919 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
922 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
923 // |pipeline| will go out of scope.
926 TEST_F(PipelineTest, DeleteAfterStop) {
927 CreateAudioStream();
928 MockDemuxerStreamVector streams;
929 streams.push_back(audio_stream());
930 InitializeDemuxer(&streams);
931 InitializeAudioRenderer(audio_stream(), false);
932 InitializePipeline(PIPELINE_OK);
934 ExpectStop();
936 Pipeline* pipeline = pipeline_.get();
937 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
938 message_loop_.RunUntilIdle();
941 class PipelineTeardownTest : public PipelineTest {
942 public:
943 enum TeardownState {
944 kInitDemuxer,
945 kInitAudioRenderer,
946 kInitVideoRenderer,
947 kPausing,
948 kFlushing,
949 kSeeking,
950 kPrerolling,
951 kStarting,
952 kPlaying,
955 enum StopOrError {
956 kStop,
957 kError,
958 kErrorAndStop,
961 PipelineTeardownTest() {}
962 virtual ~PipelineTeardownTest() {}
964 void RunTest(TeardownState state, StopOrError stop_or_error) {
965 switch (state) {
966 case kInitDemuxer:
967 case kInitAudioRenderer:
968 case kInitVideoRenderer:
969 DoInitialize(state, stop_or_error);
970 break;
972 case kPausing:
973 case kFlushing:
974 case kSeeking:
975 case kPrerolling:
976 case kStarting:
977 DoInitialize(state, stop_or_error);
978 DoSeek(state, stop_or_error);
979 break;
981 case kPlaying:
982 DoInitialize(state, stop_or_error);
983 DoStopOrError(stop_or_error);
984 break;
988 private:
989 // TODO(scherkus): We do radically different things whether teardown is
990 // invoked via stop vs error. The teardown path should be the same,
991 // see http://crbug.com/110228
992 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
993 PipelineStatus expected_status =
994 SetInitializeExpectations(state, stop_or_error);
996 EXPECT_CALL(callbacks_, OnStart(expected_status));
997 pipeline_->Start(
998 filter_collection_.Pass(),
999 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
1000 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
1001 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
1002 base::Bind(&CallbackHelper::OnBufferingState,
1003 base::Unretained(&callbacks_)),
1004 base::Bind(&CallbackHelper::OnDurationChange,
1005 base::Unretained(&callbacks_)));
1006 message_loop_.RunUntilIdle();
1009 PipelineStatus SetInitializeExpectations(TeardownState state,
1010 StopOrError stop_or_error) {
1011 PipelineStatus status = PIPELINE_OK;
1012 base::Closure stop_cb = base::Bind(
1013 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1015 if (state == kInitDemuxer) {
1016 if (stop_or_error == kStop) {
1017 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1018 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1019 RunCallback<1>(PIPELINE_OK)));
1020 EXPECT_CALL(callbacks_, OnStop());
1021 } else {
1022 status = DEMUXER_ERROR_COULD_NOT_OPEN;
1023 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1024 .WillOnce(RunCallback<1>(status));
1027 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1028 return status;
1031 CreateAudioStream();
1032 CreateVideoStream();
1033 MockDemuxerStreamVector streams;
1034 streams.push_back(audio_stream());
1035 streams.push_back(video_stream());
1036 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
1038 if (state == kInitAudioRenderer) {
1039 if (stop_or_error == kStop) {
1040 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1041 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1042 RunCallback<1>(PIPELINE_OK)));
1043 EXPECT_CALL(callbacks_, OnStop());
1044 } else {
1045 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1046 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1047 .WillOnce(RunCallback<1>(status));
1050 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1051 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1052 return status;
1055 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _, _))
1056 .WillOnce(RunCallback<1>(PIPELINE_OK));
1058 if (state == kInitVideoRenderer) {
1059 if (stop_or_error == kStop) {
1060 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _))
1061 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1062 RunCallback<1>(PIPELINE_OK)));
1063 EXPECT_CALL(callbacks_, OnStop());
1064 } else {
1065 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1066 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _))
1067 .WillOnce(RunCallback<1>(status));
1070 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1071 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1072 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1073 return status;
1076 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _))
1077 .WillOnce(RunCallback<1>(PIPELINE_OK));
1079 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
1081 // If we get here it's a successful initialization.
1082 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
1083 .WillOnce(RunCallback<1>(PIPELINE_OK));
1084 EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _))
1085 .WillOnce(RunCallback<1>(PIPELINE_OK));
1087 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1088 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1089 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1091 EXPECT_CALL(*audio_renderer_, Play(_))
1092 .WillOnce(RunClosure<0>());
1093 EXPECT_CALL(*video_renderer_, Play(_))
1094 .WillOnce(RunClosure<0>());
1096 if (status == PIPELINE_OK)
1097 EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
1099 return status;
1102 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1103 InSequence s;
1104 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1106 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1107 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1108 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1109 EXPECT_CALL(callbacks_, OnSeek(status));
1111 if (status == PIPELINE_OK) {
1112 EXPECT_CALL(callbacks_, OnStop());
1115 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1116 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1117 message_loop_.RunUntilIdle();
1120 PipelineStatus SetSeekExpectations(TeardownState state,
1121 StopOrError stop_or_error) {
1122 PipelineStatus status = PIPELINE_OK;
1123 base::Closure stop_cb = base::Bind(
1124 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1126 if (state == kPausing) {
1127 if (stop_or_error == kStop) {
1128 EXPECT_CALL(*audio_renderer_, Pause(_))
1129 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1130 } else {
1131 status = PIPELINE_ERROR_READ;
1132 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(
1133 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1136 return status;
1139 EXPECT_CALL(*audio_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1140 EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1142 if (state == kFlushing) {
1143 if (stop_or_error == kStop) {
1144 EXPECT_CALL(*audio_renderer_, Flush(_))
1145 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1146 } else {
1147 status = PIPELINE_ERROR_READ;
1148 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1149 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1152 return status;
1155 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1156 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1158 if (state == kSeeking) {
1159 if (stop_or_error == kStop) {
1160 EXPECT_CALL(*demuxer_, Seek(_, _))
1161 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1162 RunCallback<1>(PIPELINE_OK)));
1163 } else {
1164 status = PIPELINE_ERROR_READ;
1165 EXPECT_CALL(*demuxer_, Seek(_, _))
1166 .WillOnce(RunCallback<1>(status));
1169 return status;
1172 EXPECT_CALL(*demuxer_, Seek(_, _))
1173 .WillOnce(RunCallback<1>(PIPELINE_OK));
1175 if (state == kPrerolling) {
1176 if (stop_or_error == kStop) {
1177 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1178 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1179 RunCallback<1>(PIPELINE_OK)));
1180 } else {
1181 status = PIPELINE_ERROR_READ;
1182 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1183 .WillOnce(RunCallback<1>(status));
1186 return status;
1189 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1190 .WillOnce(RunCallback<1>(PIPELINE_OK));
1191 EXPECT_CALL(*video_renderer_, Preroll(_, _))
1192 .WillOnce(RunCallback<1>(PIPELINE_OK));
1194 // Playback rate and volume are updated prior to starting.
1195 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1196 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1197 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1199 if (state == kStarting) {
1200 if (stop_or_error == kStop) {
1201 EXPECT_CALL(*audio_renderer_, Play(_))
1202 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1203 } else {
1204 status = PIPELINE_ERROR_READ;
1205 EXPECT_CALL(*audio_renderer_, Play(_)).WillOnce(
1206 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1208 return status;
1211 NOTREACHED() << "State not supported: " << state;
1212 return status;
1215 void DoStopOrError(StopOrError stop_or_error) {
1216 InSequence s;
1218 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1219 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1220 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1222 switch (stop_or_error) {
1223 case kStop:
1224 EXPECT_CALL(callbacks_, OnStop());
1225 pipeline_->Stop(base::Bind(
1226 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1227 break;
1229 case kError:
1230 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1231 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1232 break;
1234 case kErrorAndStop:
1235 EXPECT_CALL(callbacks_, OnStop());
1236 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1237 pipeline_->Stop(base::Bind(
1238 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1239 break;
1242 message_loop_.RunUntilIdle();
1245 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1248 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1249 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1250 RunTest(k##state, k##stop_or_error); \
1253 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1254 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1255 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1256 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1257 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1258 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1259 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1260 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1261 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1263 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1264 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1265 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1266 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1267 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1268 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1269 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1270 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1271 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1273 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1275 } // namespace media