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.
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"
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
;
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
{
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());
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
{
85 : pipeline_(new Pipeline(message_loop_
.message_loop_proxy(),
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
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())
122 // The mock demuxer doesn't stop the fake text track stream,
123 // so just stop it manually.
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();
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
));
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|.
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
));
209 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(0.0f
));
210 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
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
));
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
));
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>());
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());
308 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
311 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
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());
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_
;
345 DISALLOW_COPY_AND_ASSIGN(PipelineTest
);
348 // Test that playback controls methods no-op when the pipeline hasn't been
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
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
) {
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
) {
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
) {
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
) {
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());
483 message_loop_
.RunUntilIdle();
486 TEST_F(PipelineTest
, VideoAudioTextStream
) {
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());
503 message_loop_
.RunUntilIdle();
506 TEST_F(PipelineTest
, Seek
) {
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
);
522 message_loop_
.RunUntilIdle();
524 // Every filter should receive a call to Seek().
525 base::TimeDelta expected
= base::TimeDelta::FromSeconds(2000);
526 ExpectSeek(expected
);
530 TEST_F(PipelineTest
, SetVolume
) {
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
) {
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
) {
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
);
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
) {
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
) {
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
) {
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
);
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);
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
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();
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
) {
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 */) {
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
) {
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
) {
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
));
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
,
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
) {
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
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
));
912 EXPECT_EQ(pipeline_
->GetMediaTime(), seek_time
);
914 // Now that the seek is complete, verify that time updates advance the current
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
) {
928 MockDemuxerStreamVector streams
;
929 streams
.push_back(audio_stream());
930 InitializeDemuxer(&streams
);
931 InitializeAudioRenderer(audio_stream(), false);
932 InitializePipeline(PIPELINE_OK
);
936 Pipeline
* pipeline
= pipeline_
.get();
937 pipeline
->Stop(base::Bind(&DeletePipeline
, base::Passed(&pipeline_
)));
938 message_loop_
.RunUntilIdle();
941 class PipelineTeardownTest
: public PipelineTest
{
961 PipelineTeardownTest() {}
962 virtual ~PipelineTeardownTest() {}
964 void RunTest(TeardownState state
, StopOrError stop_or_error
) {
967 case kInitAudioRenderer
:
968 case kInitVideoRenderer
:
969 DoInitialize(state
, stop_or_error
);
977 DoInitialize(state
, stop_or_error
);
978 DoSeek(state
, stop_or_error
);
982 DoInitialize(state
, stop_or_error
);
983 DoStopOrError(stop_or_error
);
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
));
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());
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>());
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());
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>());
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());
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>());
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
));
1102 void DoSeek(TeardownState state
, StopOrError stop_or_error
) {
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>()));
1131 status
= PIPELINE_ERROR_READ
;
1132 EXPECT_CALL(*audio_renderer_
, Pause(_
)).WillOnce(
1133 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
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>()));
1147 status
= PIPELINE_ERROR_READ
;
1148 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(
1149 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
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
)));
1164 status
= PIPELINE_ERROR_READ
;
1165 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1166 .WillOnce(RunCallback
<1>(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
)));
1181 status
= PIPELINE_ERROR_READ
;
1182 EXPECT_CALL(*audio_renderer_
, Preroll(_
, _
))
1183 .WillOnce(RunCallback
<1>(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>()));
1204 status
= PIPELINE_ERROR_READ
;
1205 EXPECT_CALL(*audio_renderer_
, Play(_
)).WillOnce(
1206 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
1211 NOTREACHED() << "State not supported: " << state
;
1215 void DoStopOrError(StopOrError stop_or_error
) {
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
) {
1224 EXPECT_CALL(callbacks_
, OnStop());
1225 pipeline_
->Stop(base::Bind(
1226 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1230 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1231 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1235 EXPECT_CALL(callbacks_
, OnStop());
1236 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1237 pipeline_
->Stop(base::Bind(
1238 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
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