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/gmock_callback_support.h"
15 #include "media/base/media_log.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/pipeline.h"
18 #include "media/base/test_helpers.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/gfx/size.h"
23 using ::testing::DeleteArg
;
24 using ::testing::DoAll
;
25 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
26 using ::testing::InSequence
;
27 using ::testing::Invoke
;
28 using ::testing::InvokeWithoutArgs
;
29 using ::testing::Mock
;
30 using ::testing::NotNull
;
31 using ::testing::Return
;
32 using ::testing::SaveArg
;
33 using ::testing::StrictMock
;
34 using ::testing::WithArg
;
38 // Demuxer properties.
39 static const int kTotalBytes
= 1024;
40 static const int kBitrate
= 1234;
42 ACTION_P(SetDemuxerProperties
, duration
) {
43 arg0
->SetTotalBytes(kTotalBytes
);
44 arg0
->SetDuration(duration
);
47 ACTION_P2(Stop
, pipeline
, stop_cb
) {
48 pipeline
->Stop(stop_cb
);
51 ACTION_P2(SetError
, pipeline
, status
) {
52 pipeline
->SetErrorForTesting(status
);
55 // Used for setting expectations on pipeline callbacks. Using a StrictMock
56 // also lets us test for missing callbacks.
57 class CallbackHelper
{
60 virtual ~CallbackHelper() {}
62 MOCK_METHOD1(OnStart
, void(PipelineStatus
));
63 MOCK_METHOD1(OnSeek
, void(PipelineStatus
));
64 MOCK_METHOD0(OnStop
, void());
65 MOCK_METHOD0(OnEnded
, void());
66 MOCK_METHOD1(OnError
, void(PipelineStatus
));
67 MOCK_METHOD1(OnBufferingState
, void(Pipeline::BufferingState
));
68 MOCK_METHOD0(OnDurationChange
, void());
71 DISALLOW_COPY_AND_ASSIGN(CallbackHelper
);
74 // TODO(scherkus): even though some filters are initialized on separate
75 // threads these test aren't flaky... why? It's because filters' Initialize()
76 // is executed on |message_loop_| and the mock filters instantly call
77 // InitializationComplete(), which keeps the pipeline humming along. If
78 // either filters don't call InitializationComplete() immediately or filter
79 // initialization is moved to a separate thread this test will become flaky.
80 class PipelineTest
: public ::testing::Test
{
83 : pipeline_(new Pipeline(message_loop_
.message_loop_proxy(),
85 filter_collection_(new FilterCollection()),
86 demuxer_(new MockDemuxer()) {
87 filter_collection_
->SetDemuxer(demuxer_
.get());
89 video_renderer_
= new MockVideoRenderer();
90 scoped_ptr
<VideoRenderer
> video_renderer(video_renderer_
);
91 filter_collection_
->SetVideoRenderer(video_renderer
.Pass());
93 audio_renderer_
= new MockAudioRenderer();
94 scoped_ptr
<AudioRenderer
> audio_renderer(audio_renderer_
);
95 filter_collection_
->SetAudioRenderer(audio_renderer
.Pass());
97 // InitializeDemuxer() adds overriding expectations for expected non-NULL
99 DemuxerStream
* null_pointer
= NULL
;
100 EXPECT_CALL(*demuxer_
, GetStream(_
))
101 .WillRepeatedly(Return(null_pointer
));
103 EXPECT_CALL(*demuxer_
, GetStartTime())
104 .WillRepeatedly(Return(base::TimeDelta()));
107 virtual ~PipelineTest() {
108 if (!pipeline_
|| !pipeline_
->IsRunning())
113 // Expect a stop callback if we were started.
114 EXPECT_CALL(callbacks_
, OnStop());
115 pipeline_
->Stop(base::Bind(&CallbackHelper::OnStop
,
116 base::Unretained(&callbacks_
)));
117 message_loop_
.RunUntilIdle();
121 // Sets up expectations to allow the demuxer to initialize.
122 typedef std::vector
<MockDemuxerStream
*> MockDemuxerStreamVector
;
123 void InitializeDemuxer(MockDemuxerStreamVector
* streams
,
124 const base::TimeDelta
& duration
) {
125 EXPECT_CALL(callbacks_
, OnDurationChange());
126 EXPECT_CALL(*demuxer_
, Initialize(_
, _
))
127 .WillOnce(DoAll(SetDemuxerProperties(duration
),
128 RunCallback
<1>(PIPELINE_OK
)));
130 // Configure the demuxer to return the streams.
131 for (size_t i
= 0; i
< streams
->size(); ++i
) {
132 DemuxerStream
* stream
= (*streams
)[i
];
133 EXPECT_CALL(*demuxer_
, GetStream(stream
->type()))
134 .WillRepeatedly(Return(stream
));
138 void InitializeDemuxer(MockDemuxerStreamVector
* streams
) {
139 // Initialize with a default non-zero duration.
140 InitializeDemuxer(streams
, base::TimeDelta::FromSeconds(10));
143 scoped_ptr
<StrictMock
<MockDemuxerStream
> > CreateStream(
144 DemuxerStream::Type type
) {
145 scoped_ptr
<StrictMock
<MockDemuxerStream
> > stream(
146 new StrictMock
<MockDemuxerStream
>(type
));
147 return stream
.Pass();
150 // Sets up expectations to allow the video renderer to initialize.
151 void InitializeVideoRenderer(DemuxerStream
* stream
) {
152 EXPECT_CALL(*video_renderer_
, Initialize(stream
, _
, _
, _
, _
, _
, _
, _
, _
))
153 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
154 EXPECT_CALL(*video_renderer_
, SetPlaybackRate(0.0f
));
157 EXPECT_CALL(*video_renderer_
, Preroll(demuxer_
->GetStartTime(), _
))
158 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
159 EXPECT_CALL(*video_renderer_
, Play(_
))
160 .WillOnce(RunClosure
<0>());
163 // Sets up expectations to allow the audio renderer to initialize.
164 void InitializeAudioRenderer(DemuxerStream
* stream
,
165 bool disable_after_init_cb
) {
166 if (disable_after_init_cb
) {
167 EXPECT_CALL(*audio_renderer_
, Initialize(stream
, _
, _
, _
, _
, _
, _
, _
))
168 .WillOnce(DoAll(RunCallback
<1>(PIPELINE_OK
),
169 WithArg
<6>(RunClosure
<0>()))); // |disabled_cb|.
171 EXPECT_CALL(*audio_renderer_
, Initialize(stream
, _
, _
, _
, _
, _
, _
, _
))
172 .WillOnce(DoAll(SaveArg
<4>(&audio_time_cb_
),
173 RunCallback
<1>(PIPELINE_OK
)));
177 // Sets up expectations on the callback and initializes the pipeline. Called
178 // after tests have set expectations any filters they wish to use.
179 void InitializePipeline(PipelineStatus start_status
) {
180 EXPECT_CALL(callbacks_
, OnStart(start_status
));
182 if (start_status
== PIPELINE_OK
) {
183 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kHaveMetadata
));
184 EXPECT_CALL(*demuxer_
, SetPlaybackRate(0.0f
));
187 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(0.0f
));
188 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
191 EXPECT_CALL(*audio_renderer_
, Preroll(base::TimeDelta(), _
))
192 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
193 EXPECT_CALL(*audio_renderer_
, Play(_
))
194 .WillOnce(RunClosure
<0>());
196 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kPrerollCompleted
));
200 filter_collection_
.Pass(),
201 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
202 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
203 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
204 base::Bind(&CallbackHelper::OnBufferingState
,
205 base::Unretained(&callbacks_
)),
206 base::Bind(&CallbackHelper::OnDurationChange
,
207 base::Unretained(&callbacks_
)));
208 message_loop_
.RunUntilIdle();
211 void CreateAudioStream() {
212 audio_stream_
= CreateStream(DemuxerStream::AUDIO
);
215 void CreateVideoStream() {
216 video_stream_
= CreateStream(DemuxerStream::VIDEO
);
217 video_stream_
->set_video_decoder_config(video_decoder_config_
);
220 MockDemuxerStream
* audio_stream() {
221 return audio_stream_
.get();
224 MockDemuxerStream
* video_stream() {
225 return video_stream_
.get();
228 void ExpectSeek(const base::TimeDelta
& seek_time
) {
229 // Every filter should receive a call to Seek().
230 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
231 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
232 EXPECT_CALL(*demuxer_
, SetPlaybackRate(_
));
235 EXPECT_CALL(*audio_renderer_
, Pause(_
))
236 .WillOnce(RunClosure
<0>());
237 EXPECT_CALL(*audio_renderer_
, Flush(_
))
238 .WillOnce(RunClosure
<0>());
239 EXPECT_CALL(*audio_renderer_
, Preroll(seek_time
, _
))
240 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
241 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(_
));
242 EXPECT_CALL(*audio_renderer_
, SetVolume(_
));
243 EXPECT_CALL(*audio_renderer_
, Play(_
))
244 .WillOnce(RunClosure
<0>());
248 EXPECT_CALL(*video_renderer_
, Pause(_
))
249 .WillOnce(RunClosure
<0>());
250 EXPECT_CALL(*video_renderer_
, Flush(_
))
251 .WillOnce(RunClosure
<0>());
252 EXPECT_CALL(*video_renderer_
, Preroll(seek_time
, _
))
253 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
254 EXPECT_CALL(*video_renderer_
, SetPlaybackRate(_
));
255 EXPECT_CALL(*video_renderer_
, Play(_
))
256 .WillOnce(RunClosure
<0>());
259 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kPrerollCompleted
));
261 // We expect a successful seek callback.
262 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_OK
));
265 void DoSeek(const base::TimeDelta
& seek_time
) {
266 pipeline_
->Seek(seek_time
,
267 base::Bind(&CallbackHelper::OnSeek
,
268 base::Unretained(&callbacks_
)));
270 // We expect the time to be updated only after the seek has completed.
271 EXPECT_NE(seek_time
, pipeline_
->GetMediaTime());
272 message_loop_
.RunUntilIdle();
273 EXPECT_EQ(seek_time
, pipeline_
->GetMediaTime());
278 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
281 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
284 EXPECT_CALL(*video_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
288 StrictMock
<CallbackHelper
> callbacks_
;
289 base::SimpleTestTickClock test_tick_clock_
;
290 base::MessageLoop message_loop_
;
291 scoped_ptr
<Pipeline
> pipeline_
;
293 scoped_ptr
<FilterCollection
> filter_collection_
;
294 scoped_ptr
<MockDemuxer
> demuxer_
;
295 MockVideoRenderer
* video_renderer_
;
296 MockAudioRenderer
* audio_renderer_
;
297 scoped_ptr
<StrictMock
<MockDemuxerStream
> > audio_stream_
;
298 scoped_ptr
<StrictMock
<MockDemuxerStream
> > video_stream_
;
299 AudioRenderer::TimeCB audio_time_cb_
;
300 VideoDecoderConfig video_decoder_config_
;
303 DISALLOW_COPY_AND_ASSIGN(PipelineTest
);
306 // Test that playback controls methods no-op when the pipeline hasn't been
308 TEST_F(PipelineTest
, NotStarted
) {
309 const base::TimeDelta kZero
;
311 EXPECT_FALSE(pipeline_
->IsRunning());
312 EXPECT_FALSE(pipeline_
->HasAudio());
313 EXPECT_FALSE(pipeline_
->HasVideo());
315 // Setting should still work.
316 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
317 pipeline_
->SetPlaybackRate(-1.0f
);
318 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
319 pipeline_
->SetPlaybackRate(1.0f
);
320 EXPECT_EQ(1.0f
, pipeline_
->GetPlaybackRate());
322 // Setting should still work.
323 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
324 pipeline_
->SetVolume(-1.0f
);
325 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
326 pipeline_
->SetVolume(0.0f
);
327 EXPECT_EQ(0.0f
, pipeline_
->GetVolume());
329 EXPECT_TRUE(kZero
== pipeline_
->GetMediaTime());
330 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
331 EXPECT_TRUE(kZero
== pipeline_
->GetMediaDuration());
333 EXPECT_EQ(0, pipeline_
->GetTotalBytes());
335 // Should always get set to zero.
336 gfx::Size
size(1, 1);
337 pipeline_
->GetNaturalVideoSize(&size
);
338 EXPECT_EQ(0, size
.width());
339 EXPECT_EQ(0, size
.height());
342 TEST_F(PipelineTest
, NeverInitializes
) {
343 // Don't execute the callback passed into Initialize().
344 EXPECT_CALL(*demuxer_
, Initialize(_
, _
));
346 // This test hangs during initialization by never calling
347 // InitializationComplete(). StrictMock<> will ensure that the callback is
350 filter_collection_
.Pass(),
351 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
352 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
353 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
354 base::Bind(&CallbackHelper::OnBufferingState
,
355 base::Unretained(&callbacks_
)),
356 base::Bind(&CallbackHelper::OnDurationChange
,
357 base::Unretained(&callbacks_
)));
358 message_loop_
.RunUntilIdle();
361 // Because our callback will get executed when the test tears down, we'll
362 // verify that nothing has been called, then set our expectation for the call
363 // made during tear down.
364 Mock::VerifyAndClear(&callbacks_
);
365 EXPECT_CALL(callbacks_
, OnStart(PIPELINE_OK
));
368 TEST_F(PipelineTest
, URLNotFound
) {
369 EXPECT_CALL(*demuxer_
, Initialize(_
, _
))
370 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_URL_NOT_FOUND
));
371 EXPECT_CALL(*demuxer_
, Stop(_
))
372 .WillOnce(RunClosure
<0>());
374 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND
);
377 TEST_F(PipelineTest
, NoStreams
) {
378 EXPECT_CALL(*demuxer_
, Initialize(_
, _
))
379 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
380 EXPECT_CALL(*demuxer_
, Stop(_
))
381 .WillOnce(RunClosure
<0>());
383 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER
);
386 TEST_F(PipelineTest
, AudioStream
) {
388 MockDemuxerStreamVector streams
;
389 streams
.push_back(audio_stream());
391 InitializeDemuxer(&streams
);
392 InitializeAudioRenderer(audio_stream(), false);
394 InitializePipeline(PIPELINE_OK
);
395 EXPECT_TRUE(pipeline_
->HasAudio());
396 EXPECT_FALSE(pipeline_
->HasVideo());
399 TEST_F(PipelineTest
, VideoStream
) {
401 MockDemuxerStreamVector streams
;
402 streams
.push_back(video_stream());
404 InitializeDemuxer(&streams
);
405 InitializeVideoRenderer(video_stream());
407 InitializePipeline(PIPELINE_OK
);
408 EXPECT_FALSE(pipeline_
->HasAudio());
409 EXPECT_TRUE(pipeline_
->HasVideo());
412 TEST_F(PipelineTest
, AudioVideoStream
) {
415 MockDemuxerStreamVector streams
;
416 streams
.push_back(audio_stream());
417 streams
.push_back(video_stream());
419 InitializeDemuxer(&streams
);
420 InitializeAudioRenderer(audio_stream(), false);
421 InitializeVideoRenderer(video_stream());
423 InitializePipeline(PIPELINE_OK
);
424 EXPECT_TRUE(pipeline_
->HasAudio());
425 EXPECT_TRUE(pipeline_
->HasVideo());
428 TEST_F(PipelineTest
, Seek
) {
431 MockDemuxerStreamVector streams
;
432 streams
.push_back(audio_stream());
433 streams
.push_back(video_stream());
435 InitializeDemuxer(&streams
, base::TimeDelta::FromSeconds(3000));
436 InitializeAudioRenderer(audio_stream(), false);
437 InitializeVideoRenderer(video_stream());
439 // Initialize then seek!
440 InitializePipeline(PIPELINE_OK
);
442 // Every filter should receive a call to Seek().
443 base::TimeDelta expected
= base::TimeDelta::FromSeconds(2000);
444 ExpectSeek(expected
);
448 TEST_F(PipelineTest
, SetVolume
) {
450 MockDemuxerStreamVector streams
;
451 streams
.push_back(audio_stream());
453 InitializeDemuxer(&streams
);
454 InitializeAudioRenderer(audio_stream(), false);
456 // The audio renderer should receive a call to SetVolume().
457 float expected
= 0.5f
;
458 EXPECT_CALL(*audio_renderer_
, SetVolume(expected
));
460 // Initialize then set volume!
461 InitializePipeline(PIPELINE_OK
);
462 pipeline_
->SetVolume(expected
);
465 TEST_F(PipelineTest
, Properties
) {
467 MockDemuxerStreamVector streams
;
468 streams
.push_back(video_stream());
470 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
471 InitializeDemuxer(&streams
, kDuration
);
472 InitializeVideoRenderer(video_stream());
474 InitializePipeline(PIPELINE_OK
);
475 EXPECT_EQ(kDuration
.ToInternalValue(),
476 pipeline_
->GetMediaDuration().ToInternalValue());
477 EXPECT_EQ(kTotalBytes
, pipeline_
->GetTotalBytes());
478 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
481 TEST_F(PipelineTest
, GetBufferedTimeRanges
) {
483 MockDemuxerStreamVector streams
;
484 streams
.push_back(video_stream());
486 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
487 InitializeDemuxer(&streams
, kDuration
);
488 InitializeVideoRenderer(video_stream());
490 InitializePipeline(PIPELINE_OK
);
492 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
494 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
495 pipeline_
->AddBufferedByteRange(0, kTotalBytes
/ 8);
496 EXPECT_TRUE(pipeline_
->DidLoadingProgress());
497 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
498 EXPECT_EQ(1u, pipeline_
->GetBufferedTimeRanges().size());
499 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
500 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
501 pipeline_
->AddBufferedTimeRange(base::TimeDelta(), kDuration
/ 8);
502 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
503 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
505 base::TimeDelta kSeekTime
= kDuration
/ 2;
506 ExpectSeek(kSeekTime
);
509 EXPECT_TRUE(pipeline_
->DidLoadingProgress());
510 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
511 pipeline_
->AddBufferedByteRange(kTotalBytes
/ 2,
512 kTotalBytes
/ 2 + kTotalBytes
/ 8);
513 EXPECT_TRUE(pipeline_
->DidLoadingProgress());
514 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
515 EXPECT_EQ(2u, pipeline_
->GetBufferedTimeRanges().size());
516 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
517 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
518 EXPECT_EQ(kDuration
/ 2, pipeline_
->GetBufferedTimeRanges().start(1));
519 EXPECT_EQ(kDuration
/ 2 + kDuration
/ 8,
520 pipeline_
->GetBufferedTimeRanges().end(1));
522 pipeline_
->AddBufferedTimeRange(kDuration
/ 4, 3 * kDuration
/ 8);
523 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
524 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
525 EXPECT_EQ(kDuration
/ 4, pipeline_
->GetBufferedTimeRanges().start(1));
526 EXPECT_EQ(3* kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(1));
527 EXPECT_EQ(kDuration
/ 2, pipeline_
->GetBufferedTimeRanges().start(2));
528 EXPECT_EQ(kDuration
/ 2 + kDuration
/ 8,
529 pipeline_
->GetBufferedTimeRanges().end(2));
532 TEST_F(PipelineTest
, DisableAudioRenderer
) {
535 MockDemuxerStreamVector streams
;
536 streams
.push_back(audio_stream());
537 streams
.push_back(video_stream());
539 InitializeDemuxer(&streams
);
540 InitializeAudioRenderer(audio_stream(), false);
541 InitializeVideoRenderer(video_stream());
543 InitializePipeline(PIPELINE_OK
);
544 EXPECT_TRUE(pipeline_
->HasAudio());
545 EXPECT_TRUE(pipeline_
->HasVideo());
547 EXPECT_CALL(*demuxer_
, OnAudioRendererDisabled());
548 pipeline_
->OnAudioDisabled();
550 // Verify that ended event is fired when video ends.
551 EXPECT_CALL(callbacks_
, OnEnded());
552 pipeline_
->OnVideoRendererEnded();
555 TEST_F(PipelineTest
, DisableAudioRendererDuringInit
) {
558 MockDemuxerStreamVector streams
;
559 streams
.push_back(audio_stream());
560 streams
.push_back(video_stream());
562 InitializeDemuxer(&streams
);
563 InitializeAudioRenderer(audio_stream(), true);
564 InitializeVideoRenderer(video_stream());
566 EXPECT_CALL(*demuxer_
, OnAudioRendererDisabled());
568 InitializePipeline(PIPELINE_OK
);
569 EXPECT_FALSE(pipeline_
->HasAudio());
570 EXPECT_TRUE(pipeline_
->HasVideo());
572 // Verify that ended event is fired when video ends.
573 EXPECT_CALL(callbacks_
, OnEnded());
574 pipeline_
->OnVideoRendererEnded();
577 TEST_F(PipelineTest
, EndedCallback
) {
580 MockDemuxerStreamVector streams
;
581 streams
.push_back(audio_stream());
582 streams
.push_back(video_stream());
584 InitializeDemuxer(&streams
);
585 InitializeAudioRenderer(audio_stream(), false);
586 InitializeVideoRenderer(video_stream());
587 InitializePipeline(PIPELINE_OK
);
589 // The ended callback shouldn't run until both renderers have ended.
590 pipeline_
->OnAudioRendererEnded();
591 message_loop_
.RunUntilIdle();
593 EXPECT_CALL(callbacks_
, OnEnded());
594 pipeline_
->OnVideoRendererEnded();
595 message_loop_
.RunUntilIdle();
598 TEST_F(PipelineTest
, AudioStreamShorterThanVideo
) {
599 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
603 MockDemuxerStreamVector streams
;
604 streams
.push_back(audio_stream());
605 streams
.push_back(video_stream());
607 // Replace the clock so we can simulate wallclock time advancing w/o using
609 pipeline_
->SetClockForTesting(new Clock(&test_tick_clock_
));
611 InitializeDemuxer(&streams
, duration
);
612 InitializeAudioRenderer(audio_stream(), false);
613 InitializeVideoRenderer(video_stream());
614 InitializePipeline(PIPELINE_OK
);
616 EXPECT_EQ(0, pipeline_
->GetMediaTime().ToInternalValue());
618 float playback_rate
= 1.0f
;
619 EXPECT_CALL(*demuxer_
, SetPlaybackRate(playback_rate
));
620 EXPECT_CALL(*video_renderer_
, SetPlaybackRate(playback_rate
));
621 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(playback_rate
));
622 pipeline_
->SetPlaybackRate(playback_rate
);
623 message_loop_
.RunUntilIdle();
627 // Verify that the clock doesn't advance since it hasn't been started by
628 // a time update from the audio stream.
629 int64 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
630 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
631 EXPECT_EQ(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
633 // Signal end of audio stream.
634 pipeline_
->OnAudioRendererEnded();
635 message_loop_
.RunUntilIdle();
637 // Verify that the clock advances.
638 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
639 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
640 EXPECT_GT(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
642 // Signal end of video stream and make sure OnEnded() callback occurs.
643 EXPECT_CALL(callbacks_
, OnEnded());
644 pipeline_
->OnVideoRendererEnded();
647 TEST_F(PipelineTest
, ErrorDuringSeek
) {
649 MockDemuxerStreamVector streams
;
650 streams
.push_back(audio_stream());
652 InitializeDemuxer(&streams
);
653 InitializeAudioRenderer(audio_stream(), false);
654 InitializePipeline(PIPELINE_OK
);
656 float playback_rate
= 1.0f
;
657 EXPECT_CALL(*demuxer_
, SetPlaybackRate(playback_rate
));
658 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(playback_rate
));
659 pipeline_
->SetPlaybackRate(playback_rate
);
660 message_loop_
.RunUntilIdle();
662 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
664 // Preroll() isn't called as the demuxer errors out first.
665 EXPECT_CALL(*audio_renderer_
, Pause(_
))
666 .WillOnce(RunClosure
<0>());
667 EXPECT_CALL(*audio_renderer_
, Flush(_
))
668 .WillOnce(RunClosure
<0>());
669 EXPECT_CALL(*audio_renderer_
, Stop(_
))
670 .WillOnce(RunClosure
<0>());
672 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
673 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
674 EXPECT_CALL(*demuxer_
, Stop(_
))
675 .WillOnce(RunClosure
<0>());
677 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
678 base::Unretained(&callbacks_
)));
679 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
680 message_loop_
.RunUntilIdle();
683 // Invoked function OnError. This asserts that the pipeline does not enqueue
684 // non-teardown related tasks while tearing down.
685 static void TestNoCallsAfterError(
686 Pipeline
* pipeline
, base::MessageLoop
* message_loop
,
687 PipelineStatus
/* status */) {
691 // When we get to this stage, the message loop should be empty.
692 EXPECT_TRUE(message_loop
->IsIdleForTesting());
694 // Make calls on pipeline after error has occurred.
695 pipeline
->SetPlaybackRate(0.5f
);
696 pipeline
->SetVolume(0.5f
);
698 // No additional tasks should be queued as a result of these calls.
699 EXPECT_TRUE(message_loop
->IsIdleForTesting());
702 TEST_F(PipelineTest
, NoMessageDuringTearDownFromError
) {
704 MockDemuxerStreamVector streams
;
705 streams
.push_back(audio_stream());
707 InitializeDemuxer(&streams
);
708 InitializeAudioRenderer(audio_stream(), false);
709 InitializePipeline(PIPELINE_OK
);
711 // Trigger additional requests on the pipeline during tear down from error.
712 base::Callback
<void(PipelineStatus
)> cb
= base::Bind(
713 &TestNoCallsAfterError
, pipeline_
.get(), &message_loop_
);
714 ON_CALL(callbacks_
, OnError(_
))
715 .WillByDefault(Invoke(&cb
, &base::Callback
<void(PipelineStatus
)>::Run
));
717 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
719 // Seek() isn't called as the demuxer errors out first.
720 EXPECT_CALL(*audio_renderer_
, Pause(_
))
721 .WillOnce(RunClosure
<0>());
722 EXPECT_CALL(*audio_renderer_
, Flush(_
))
723 .WillOnce(RunClosure
<0>());
724 EXPECT_CALL(*audio_renderer_
, Stop(_
))
725 .WillOnce(RunClosure
<0>());
727 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
728 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
729 EXPECT_CALL(*demuxer_
, Stop(_
))
730 .WillOnce(RunClosure
<0>());
732 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
733 base::Unretained(&callbacks_
)));
734 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
735 message_loop_
.RunUntilIdle();
738 TEST_F(PipelineTest
, StartTimeIsZero
) {
740 MockDemuxerStreamVector streams
;
741 streams
.push_back(video_stream());
743 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
744 InitializeDemuxer(&streams
, kDuration
);
745 InitializeVideoRenderer(video_stream());
747 InitializePipeline(PIPELINE_OK
);
748 EXPECT_FALSE(pipeline_
->HasAudio());
749 EXPECT_TRUE(pipeline_
->HasVideo());
751 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetMediaTime());
754 TEST_F(PipelineTest
, StartTimeIsNonZero
) {
755 const base::TimeDelta kStartTime
= base::TimeDelta::FromSeconds(4);
756 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
758 EXPECT_CALL(*demuxer_
, GetStartTime())
759 .WillRepeatedly(Return(kStartTime
));
762 MockDemuxerStreamVector streams
;
763 streams
.push_back(video_stream());
765 InitializeDemuxer(&streams
, kDuration
);
766 InitializeVideoRenderer(video_stream());
768 InitializePipeline(PIPELINE_OK
);
769 EXPECT_FALSE(pipeline_
->HasAudio());
770 EXPECT_TRUE(pipeline_
->HasVideo());
772 EXPECT_EQ(kStartTime
, pipeline_
->GetMediaTime());
775 static void RunTimeCB(const AudioRenderer::TimeCB
& time_cb
,
777 int max_time_in_ms
) {
778 time_cb
.Run(base::TimeDelta::FromMilliseconds(time_in_ms
),
779 base::TimeDelta::FromMilliseconds(max_time_in_ms
));
782 TEST_F(PipelineTest
, AudioTimeUpdateDuringSeek
) {
784 MockDemuxerStreamVector streams
;
785 streams
.push_back(audio_stream());
787 InitializeDemuxer(&streams
);
788 InitializeAudioRenderer(audio_stream(), false);
789 InitializePipeline(PIPELINE_OK
);
791 float playback_rate
= 1.0f
;
792 EXPECT_CALL(*demuxer_
, SetPlaybackRate(playback_rate
));
793 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(playback_rate
));
794 pipeline_
->SetPlaybackRate(playback_rate
);
795 message_loop_
.RunUntilIdle();
797 // Provide an initial time update so that the pipeline transitions out of the
798 // "waiting for time update" state.
799 audio_time_cb_
.Run(base::TimeDelta::FromMilliseconds(100),
800 base::TimeDelta::FromMilliseconds(500));
802 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
804 // Arrange to trigger a time update while the demuxer is in the middle of
805 // seeking. This update should be ignored by the pipeline and the clock should
807 base::Closure closure
= base::Bind(&RunTimeCB
, audio_time_cb_
, 300, 700);
808 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
809 .WillOnce(DoAll(InvokeWithoutArgs(&closure
, &base::Closure::Run
),
810 RunCallback
<1>(PIPELINE_OK
)));
812 EXPECT_CALL(*audio_renderer_
, Pause(_
))
813 .WillOnce(RunClosure
<0>());
814 EXPECT_CALL(*audio_renderer_
, Flush(_
))
815 .WillOnce(RunClosure
<0>());
816 EXPECT_CALL(*audio_renderer_
, Preroll(seek_time
, _
))
817 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
818 EXPECT_CALL(*demuxer_
, SetPlaybackRate(_
));
819 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(_
));
820 EXPECT_CALL(*audio_renderer_
, SetVolume(_
));
821 EXPECT_CALL(*audio_renderer_
, Play(_
))
822 .WillOnce(RunClosure
<0>());
824 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kPrerollCompleted
));
825 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_OK
));
828 EXPECT_EQ(pipeline_
->GetMediaTime(), seek_time
);
830 // Now that the seek is complete, verify that time updates advance the current
832 base::TimeDelta new_time
= seek_time
+ base::TimeDelta::FromMilliseconds(100);
833 audio_time_cb_
.Run(new_time
, new_time
);
835 EXPECT_EQ(pipeline_
->GetMediaTime(), new_time
);
838 static void DeletePipeline(scoped_ptr
<Pipeline
> pipeline
) {
839 // |pipeline| will go out of scope.
842 TEST_F(PipelineTest
, DeleteAfterStop
) {
844 MockDemuxerStreamVector streams
;
845 streams
.push_back(audio_stream());
846 InitializeDemuxer(&streams
);
847 InitializeAudioRenderer(audio_stream(), false);
848 InitializePipeline(PIPELINE_OK
);
852 Pipeline
* pipeline
= pipeline_
.get();
853 pipeline
->Stop(base::Bind(&DeletePipeline
, base::Passed(&pipeline_
)));
854 message_loop_
.RunUntilIdle();
857 class PipelineTeardownTest
: public PipelineTest
{
877 PipelineTeardownTest() {}
878 virtual ~PipelineTeardownTest() {}
880 void RunTest(TeardownState state
, StopOrError stop_or_error
) {
883 case kInitAudioRenderer
:
884 case kInitVideoRenderer
:
885 DoInitialize(state
, stop_or_error
);
893 DoInitialize(state
, stop_or_error
);
894 DoSeek(state
, stop_or_error
);
898 DoInitialize(state
, stop_or_error
);
899 DoStopOrError(stop_or_error
);
905 // TODO(scherkus): We do radically different things whether teardown is
906 // invoked via stop vs error. The teardown path should be the same,
907 // see http://crbug.com/110228
908 void DoInitialize(TeardownState state
, StopOrError stop_or_error
) {
909 PipelineStatus expected_status
=
910 SetInitializeExpectations(state
, stop_or_error
);
912 EXPECT_CALL(callbacks_
, OnStart(expected_status
));
914 filter_collection_
.Pass(),
915 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
916 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
917 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
918 base::Bind(&CallbackHelper::OnBufferingState
,
919 base::Unretained(&callbacks_
)),
920 base::Bind(&CallbackHelper::OnDurationChange
,
921 base::Unretained(&callbacks_
)));
922 message_loop_
.RunUntilIdle();
925 PipelineStatus
SetInitializeExpectations(TeardownState state
,
926 StopOrError stop_or_error
) {
927 PipelineStatus status
= PIPELINE_OK
;
928 base::Closure stop_cb
= base::Bind(
929 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
931 if (state
== kInitDemuxer
) {
932 if (stop_or_error
== kStop
) {
933 EXPECT_CALL(*demuxer_
, Initialize(_
, _
))
934 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
935 RunCallback
<1>(PIPELINE_OK
)));
936 EXPECT_CALL(callbacks_
, OnStop());
938 status
= DEMUXER_ERROR_COULD_NOT_OPEN
;
939 EXPECT_CALL(*demuxer_
, Initialize(_
, _
))
940 .WillOnce(RunCallback
<1>(status
));
943 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
949 MockDemuxerStreamVector streams
;
950 streams
.push_back(audio_stream());
951 streams
.push_back(video_stream());
952 InitializeDemuxer(&streams
, base::TimeDelta::FromSeconds(3000));
954 if (state
== kInitAudioRenderer
) {
955 if (stop_or_error
== kStop
) {
956 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
))
957 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
958 RunCallback
<1>(PIPELINE_OK
)));
959 EXPECT_CALL(callbacks_
, OnStop());
961 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
962 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
))
963 .WillOnce(RunCallback
<1>(status
));
966 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
967 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
971 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
))
972 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
974 if (state
== kInitVideoRenderer
) {
975 if (stop_or_error
== kStop
) {
976 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
))
977 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
978 RunCallback
<1>(PIPELINE_OK
)));
979 EXPECT_CALL(callbacks_
, OnStop());
981 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
982 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
))
983 .WillOnce(RunCallback
<1>(status
));
986 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
987 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
988 EXPECT_CALL(*video_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
992 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
))
993 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
995 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kHaveMetadata
));
997 // If we get here it's a successful initialization.
998 EXPECT_CALL(*audio_renderer_
, Preroll(base::TimeDelta(), _
))
999 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
1000 EXPECT_CALL(*video_renderer_
, Preroll(base::TimeDelta(), _
))
1001 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
1003 EXPECT_CALL(*demuxer_
, SetPlaybackRate(0.0f
));
1004 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(0.0f
));
1005 EXPECT_CALL(*video_renderer_
, SetPlaybackRate(0.0f
));
1006 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
1008 EXPECT_CALL(*audio_renderer_
, Play(_
))
1009 .WillOnce(RunClosure
<0>());
1010 EXPECT_CALL(*video_renderer_
, Play(_
))
1011 .WillOnce(RunClosure
<0>());
1013 if (status
== PIPELINE_OK
)
1014 EXPECT_CALL(callbacks_
, OnBufferingState(Pipeline::kPrerollCompleted
));
1019 void DoSeek(TeardownState state
, StopOrError stop_or_error
) {
1021 PipelineStatus status
= SetSeekExpectations(state
, stop_or_error
);
1023 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1024 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1025 EXPECT_CALL(*video_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1026 EXPECT_CALL(callbacks_
, OnSeek(status
));
1028 if (status
== PIPELINE_OK
) {
1029 EXPECT_CALL(callbacks_
, OnStop());
1032 pipeline_
->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1033 &CallbackHelper::OnSeek
, base::Unretained(&callbacks_
)));
1034 message_loop_
.RunUntilIdle();
1037 PipelineStatus
SetSeekExpectations(TeardownState state
,
1038 StopOrError stop_or_error
) {
1039 PipelineStatus status
= PIPELINE_OK
;
1040 base::Closure stop_cb
= base::Bind(
1041 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
1043 if (state
== kPausing
) {
1044 if (stop_or_error
== kStop
) {
1045 EXPECT_CALL(*audio_renderer_
, Pause(_
))
1046 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
), RunClosure
<0>()));
1048 status
= PIPELINE_ERROR_READ
;
1049 EXPECT_CALL(*audio_renderer_
, Pause(_
)).WillOnce(
1050 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
1056 EXPECT_CALL(*audio_renderer_
, Pause(_
)).WillOnce(RunClosure
<0>());
1057 EXPECT_CALL(*video_renderer_
, Pause(_
)).WillOnce(RunClosure
<0>());
1059 if (state
== kFlushing
) {
1060 if (stop_or_error
== kStop
) {
1061 EXPECT_CALL(*audio_renderer_
, Flush(_
))
1062 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
), RunClosure
<0>()));
1064 status
= PIPELINE_ERROR_READ
;
1065 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(
1066 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
1072 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(RunClosure
<0>());
1073 EXPECT_CALL(*video_renderer_
, Flush(_
)).WillOnce(RunClosure
<0>());
1075 if (state
== kSeeking
) {
1076 if (stop_or_error
== kStop
) {
1077 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1078 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1079 RunCallback
<1>(PIPELINE_OK
)));
1081 status
= PIPELINE_ERROR_READ
;
1082 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1083 .WillOnce(RunCallback
<1>(status
));
1089 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1090 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
1092 if (state
== kPrerolling
) {
1093 if (stop_or_error
== kStop
) {
1094 EXPECT_CALL(*audio_renderer_
, Preroll(_
, _
))
1095 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1096 RunCallback
<1>(PIPELINE_OK
)));
1098 status
= PIPELINE_ERROR_READ
;
1099 EXPECT_CALL(*audio_renderer_
, Preroll(_
, _
))
1100 .WillOnce(RunCallback
<1>(status
));
1106 EXPECT_CALL(*audio_renderer_
, Preroll(_
, _
))
1107 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
1108 EXPECT_CALL(*video_renderer_
, Preroll(_
, _
))
1109 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
1111 // Playback rate and volume are updated prior to starting.
1112 EXPECT_CALL(*demuxer_
, SetPlaybackRate(0.0f
));
1113 EXPECT_CALL(*audio_renderer_
, SetPlaybackRate(0.0f
));
1114 EXPECT_CALL(*video_renderer_
, SetPlaybackRate(0.0f
));
1115 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
1117 if (state
== kStarting
) {
1118 if (stop_or_error
== kStop
) {
1119 EXPECT_CALL(*audio_renderer_
, Play(_
))
1120 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
), RunClosure
<0>()));
1122 status
= PIPELINE_ERROR_READ
;
1123 EXPECT_CALL(*audio_renderer_
, Play(_
)).WillOnce(
1124 DoAll(SetError(pipeline_
.get(), status
), RunClosure
<0>()));
1129 NOTREACHED() << "State not supported: " << state
;
1133 void DoStopOrError(StopOrError stop_or_error
) {
1136 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1137 EXPECT_CALL(*audio_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1138 EXPECT_CALL(*video_renderer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1140 switch (stop_or_error
) {
1142 EXPECT_CALL(callbacks_
, OnStop());
1143 pipeline_
->Stop(base::Bind(
1144 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1148 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1149 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1153 EXPECT_CALL(callbacks_
, OnStop());
1154 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1155 pipeline_
->Stop(base::Bind(
1156 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1160 message_loop_
.RunUntilIdle();
1163 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest
);
1166 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1167 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1168 RunTest(k##state, k##stop_or_error); \
1171 INSTANTIATE_TEARDOWN_TEST(Stop
, InitDemuxer
);
1172 INSTANTIATE_TEARDOWN_TEST(Stop
, InitAudioRenderer
);
1173 INSTANTIATE_TEARDOWN_TEST(Stop
, InitVideoRenderer
);
1174 INSTANTIATE_TEARDOWN_TEST(Stop
, Pausing
);
1175 INSTANTIATE_TEARDOWN_TEST(Stop
, Flushing
);
1176 INSTANTIATE_TEARDOWN_TEST(Stop
, Seeking
);
1177 INSTANTIATE_TEARDOWN_TEST(Stop
, Prerolling
);
1178 INSTANTIATE_TEARDOWN_TEST(Stop
, Starting
);
1179 INSTANTIATE_TEARDOWN_TEST(Stop
, Playing
);
1181 INSTANTIATE_TEARDOWN_TEST(Error
, InitDemuxer
);
1182 INSTANTIATE_TEARDOWN_TEST(Error
, InitAudioRenderer
);
1183 INSTANTIATE_TEARDOWN_TEST(Error
, InitVideoRenderer
);
1184 INSTANTIATE_TEARDOWN_TEST(Error
, Pausing
);
1185 INSTANTIATE_TEARDOWN_TEST(Error
, Flushing
);
1186 INSTANTIATE_TEARDOWN_TEST(Error
, Seeking
);
1187 INSTANTIATE_TEARDOWN_TEST(Error
, Prerolling
);
1188 INSTANTIATE_TEARDOWN_TEST(Error
, Starting
);
1189 INSTANTIATE_TEARDOWN_TEST(Error
, Playing
);
1191 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop
, Playing
);
1193 } // namespace media