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 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
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
) {
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
) {
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
) {
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
) {
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());
484 message_loop_
.RunUntilIdle();
487 TEST_F(PipelineTest
, VideoAudioTextStream
) {
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());
504 message_loop_
.RunUntilIdle();
507 TEST_F(PipelineTest
, Seek
) {
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
);
523 message_loop_
.RunUntilIdle();
525 // Every filter should receive a call to Seek().
526 base::TimeDelta expected
= base::TimeDelta::FromSeconds(2000);
527 ExpectSeek(expected
);
531 TEST_F(PipelineTest
, SetVolume
) {
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
) {
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
) {
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
);
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
) {
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
) {
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
) {
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
);
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);
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
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();
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
) {
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 */) {
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
) {
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
) {
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
));
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
,
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
) {
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
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
));
913 EXPECT_EQ(pipeline_
->GetMediaTime(), seek_time
);
915 // Now that the seek is complete, verify that time updates advance the current
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
) {
929 MockDemuxerStreamVector streams
;
930 streams
.push_back(audio_stream());
931 InitializeDemuxer(&streams
);
932 InitializeAudioRenderer(audio_stream(), false);
933 InitializePipeline(PIPELINE_OK
);
937 Pipeline
* pipeline
= pipeline_
.get();
938 pipeline
->Stop(base::Bind(&DeletePipeline
, base::Passed(&pipeline_
)));
939 message_loop_
.RunUntilIdle();
942 class PipelineTeardownTest
: public PipelineTest
{
962 PipelineTeardownTest() {}
963 virtual ~PipelineTeardownTest() {}
965 void RunTest(TeardownState state
, StopOrError stop_or_error
) {
968 case kInitAudioRenderer
:
969 case kInitVideoRenderer
:
970 DoInitialize(state
, stop_or_error
);
978 DoInitialize(state
, stop_or_error
);
979 DoSeek(state
, stop_or_error
);
983 DoInitialize(state
, stop_or_error
);
984 DoStopOrError(stop_or_error
);
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
));
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());
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>());
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());
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>());
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());
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>());
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
));
1103 void DoSeek(TeardownState state
, StopOrError stop_or_error
) {
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>()));
1132 status
= PIPELINE_ERROR_READ
;
1133 EXPECT_CALL(*audio_renderer_
, Pause(_
)).WillOnce(
1134 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
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>()));
1148 status
= PIPELINE_ERROR_READ
;
1149 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(
1150 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
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
)));
1165 status
= PIPELINE_ERROR_READ
;
1166 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1167 .WillOnce(RunCallback
<1>(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
)));
1182 status
= PIPELINE_ERROR_READ
;
1183 EXPECT_CALL(*audio_renderer_
, Preroll(_
, _
))
1184 .WillOnce(RunCallback
<1>(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>()));
1205 status
= PIPELINE_ERROR_READ
;
1206 EXPECT_CALL(*audio_renderer_
, Play(_
)).WillOnce(
1207 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
1212 NOTREACHED() << "State not supported: " << state
;
1216 void DoStopOrError(StopOrError stop_or_error
) {
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
) {
1225 EXPECT_CALL(callbacks_
, OnStop());
1226 pipeline_
->Stop(base::Bind(
1227 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1231 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1232 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1236 EXPECT_CALL(callbacks_
, OnStop());
1237 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1238 pipeline_
->Stop(base::Bind(
1239 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
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