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/fake_text_track_stream.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 "media/base/text_renderer.h"
20 #include "media/base/text_track_config.h"
21 #include "media/base/time_delta_interpolator.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
26 using ::testing::AnyNumber
;
27 using ::testing::DeleteArg
;
28 using ::testing::DoAll
;
29 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
30 using ::testing::InSequence
;
31 using ::testing::Invoke
;
32 using ::testing::InvokeWithoutArgs
;
33 using ::testing::Mock
;
34 using ::testing::NotNull
;
35 using ::testing::Return
;
36 using ::testing::SaveArg
;
37 using ::testing::StrictMock
;
38 using ::testing::WithArg
;
42 ACTION_P(SetDemuxerProperties
, duration
) {
43 arg0
->SetDuration(duration
);
46 ACTION_P2(Stop
, pipeline
, stop_cb
) {
47 pipeline
->Stop(stop_cb
);
50 ACTION_P2(SetError
, pipeline
, status
) {
51 pipeline
->SetErrorForTesting(status
);
54 ACTION_P2(SetBufferingState
, cb
, buffering_state
) {
55 cb
->Run(buffering_state
);
58 // Used for setting expectations on pipeline callbacks. Using a StrictMock
59 // also lets us test for missing callbacks.
60 class CallbackHelper
{
63 virtual ~CallbackHelper() {}
65 MOCK_METHOD1(OnStart
, void(PipelineStatus
));
66 MOCK_METHOD1(OnSeek
, void(PipelineStatus
));
67 MOCK_METHOD0(OnStop
, void());
68 MOCK_METHOD0(OnEnded
, void());
69 MOCK_METHOD1(OnError
, void(PipelineStatus
));
70 MOCK_METHOD1(OnMetadata
, void(PipelineMetadata
));
71 MOCK_METHOD1(OnBufferingStateChange
, void(BufferingState
));
72 MOCK_METHOD0(OnDurationChange
, void());
75 DISALLOW_COPY_AND_ASSIGN(CallbackHelper
);
78 // TODO(scherkus): even though some filters are initialized on separate
79 // threads these test aren't flaky... why? It's because filters' Initialize()
80 // is executed on |message_loop_| and the mock filters instantly call
81 // InitializationComplete(), which keeps the pipeline humming along. If
82 // either filters don't call InitializationComplete() immediately or filter
83 // initialization is moved to a separate thread this test will become flaky.
84 class PipelineTest
: public ::testing::Test
{
87 : pipeline_(new Pipeline(message_loop_
.message_loop_proxy(),
89 filter_collection_(new FilterCollection()),
90 demuxer_(new StrictMock
<MockDemuxer
>()) {
91 filter_collection_
->SetDemuxer(demuxer_
.get());
93 video_renderer_
= new StrictMock
<MockVideoRenderer
>();
94 scoped_ptr
<VideoRenderer
> video_renderer(video_renderer_
);
95 filter_collection_
->SetVideoRenderer(video_renderer
.Pass());
97 audio_renderer_
= new StrictMock
<MockAudioRenderer
>();
98 scoped_ptr
<AudioRenderer
> audio_renderer(audio_renderer_
);
99 filter_collection_
->SetAudioRenderer(audio_renderer
.Pass());
101 text_renderer_
= new TextRenderer(
102 message_loop_
.message_loop_proxy(),
103 base::Bind(&PipelineTest::OnAddTextTrack
,
104 base::Unretained(this)));
105 scoped_ptr
<TextRenderer
> text_renderer(text_renderer_
);
106 filter_collection_
->SetTextRenderer(text_renderer
.Pass());
108 // SetDemuxerExpectations() adds overriding expectations for expected
110 DemuxerStream
* null_pointer
= NULL
;
111 EXPECT_CALL(*demuxer_
, GetStream(_
))
112 .WillRepeatedly(Return(null_pointer
));
114 EXPECT_CALL(*demuxer_
, GetTimelineOffset())
115 .WillRepeatedly(Return(base::Time()));
117 EXPECT_CALL(*demuxer_
, GetLiveness())
118 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN
));
121 virtual ~PipelineTest() {
122 if (!pipeline_
|| !pipeline_
->IsRunning())
127 // The mock demuxer doesn't stop the fake text track stream,
128 // so just stop it manually.
130 text_stream_
->Stop();
131 message_loop_
.RunUntilIdle();
134 // Expect a stop callback if we were started.
135 ExpectPipelineStopAndDestroyPipeline();
136 pipeline_
->Stop(base::Bind(&CallbackHelper::OnStop
,
137 base::Unretained(&callbacks_
)));
138 message_loop_
.RunUntilIdle();
141 void OnDemuxerError() {
142 // Cast because OnDemuxerError is private in Pipeline.
143 static_cast<DemuxerHost
*>(pipeline_
.get())
144 ->OnDemuxerError(PIPELINE_ERROR_ABORT
);
148 // Sets up expectations to allow the demuxer to initialize.
149 typedef std::vector
<MockDemuxerStream
*> MockDemuxerStreamVector
;
150 void SetDemuxerExpectations(MockDemuxerStreamVector
* streams
,
151 const base::TimeDelta
& duration
) {
152 EXPECT_CALL(callbacks_
, OnDurationChange());
153 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
154 .WillOnce(DoAll(SetDemuxerProperties(duration
),
155 RunCallback
<1>(PIPELINE_OK
)));
157 // Configure the demuxer to return the streams.
158 for (size_t i
= 0; i
< streams
->size(); ++i
) {
159 DemuxerStream
* stream
= (*streams
)[i
];
160 EXPECT_CALL(*demuxer_
, GetStream(stream
->type()))
161 .WillRepeatedly(Return(stream
));
165 void SetDemuxerExpectations(MockDemuxerStreamVector
* streams
) {
166 // Initialize with a default non-zero duration.
167 SetDemuxerExpectations(streams
, base::TimeDelta::FromSeconds(10));
170 scoped_ptr
<StrictMock
<MockDemuxerStream
> > CreateStream(
171 DemuxerStream::Type type
) {
172 scoped_ptr
<StrictMock
<MockDemuxerStream
> > stream(
173 new StrictMock
<MockDemuxerStream
>(type
));
174 return stream
.Pass();
177 // Sets up expectations to allow the video renderer to initialize.
178 void SetVideoRendererExpectations(DemuxerStream
* stream
) {
179 EXPECT_CALL(*video_renderer_
, Initialize(stream
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
180 .WillOnce(DoAll(SaveArg
<5>(&video_buffering_state_cb_
),
181 SaveArg
<6>(&video_ended_cb_
),
182 RunCallback
<2>(PIPELINE_OK
)));
185 // Sets up expectations to allow the audio renderer to initialize.
186 void SetAudioRendererExpectations(DemuxerStream
* stream
) {
187 EXPECT_CALL(*audio_renderer_
, Initialize(stream
, _
, _
, _
, _
, _
, _
))
188 .WillOnce(DoAll(SaveArg
<3>(&audio_time_cb_
),
189 SaveArg
<4>(&audio_buffering_state_cb_
),
190 SaveArg
<5>(&audio_ended_cb_
),
191 RunCallback
<1>(PIPELINE_OK
)));
194 void AddTextStream() {
195 EXPECT_CALL(*this, OnAddTextTrack(_
,_
))
196 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack
));
197 static_cast<DemuxerHost
*>(pipeline_
.get())->AddTextStream(text_stream(),
198 TextTrackConfig(kTextSubtitles
, "", "", ""));
201 // Sets up expectations on the callback and initializes the pipeline. Called
202 // after tests have set expectations any filters they wish to use.
203 void StartPipeline(PipelineStatus start_status
) {
204 EXPECT_CALL(callbacks_
, OnStart(start_status
));
206 if (start_status
== PIPELINE_OK
) {
207 EXPECT_CALL(callbacks_
, OnMetadata(_
)).WillOnce(SaveArg
<0>(&metadata_
));
210 EXPECT_CALL(*audio_renderer_
, GetTimeSource())
211 .WillOnce(Return(&time_source_
));
212 EXPECT_CALL(time_source_
, SetPlaybackRate(0.0f
));
213 EXPECT_CALL(time_source_
, SetMediaTime(base::TimeDelta()));
214 EXPECT_CALL(time_source_
, StartTicking());
215 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
216 EXPECT_CALL(*audio_renderer_
, StartPlaying())
217 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
218 BUFFERING_HAVE_ENOUGH
));
222 EXPECT_CALL(*video_renderer_
, StartPlaying())
223 .WillOnce(SetBufferingState(&video_buffering_state_cb_
,
224 BUFFERING_HAVE_ENOUGH
));
227 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
231 filter_collection_
.Pass(),
232 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
233 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
234 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
235 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
236 base::Bind(&CallbackHelper::OnBufferingStateChange
,
237 base::Unretained(&callbacks_
)),
238 base::Bind(&CallbackHelper::OnDurationChange
,
239 base::Unretained(&callbacks_
)));
240 message_loop_
.RunUntilIdle();
243 void CreateAudioStream() {
244 audio_stream_
= CreateStream(DemuxerStream::AUDIO
);
247 void CreateVideoStream() {
248 video_stream_
= CreateStream(DemuxerStream::VIDEO
);
249 video_stream_
->set_video_decoder_config(video_decoder_config_
);
252 void CreateTextStream() {
253 scoped_ptr
<FakeTextTrackStream
> text_stream(new FakeTextTrackStream());
254 EXPECT_CALL(*text_stream
, OnRead()).Times(AnyNumber());
255 text_stream_
= text_stream
.Pass();
258 MockDemuxerStream
* audio_stream() {
259 return audio_stream_
.get();
262 MockDemuxerStream
* video_stream() {
263 return video_stream_
.get();
266 FakeTextTrackStream
* text_stream() {
267 return text_stream_
.get();
270 void ExpectSeek(const base::TimeDelta
& seek_time
, bool underflowed
) {
271 // Every filter should receive a call to Seek().
272 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
273 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
277 EXPECT_CALL(time_source_
, StopTicking());
278 EXPECT_CALL(*audio_renderer_
, Flush(_
))
279 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
280 BUFFERING_HAVE_NOTHING
),
282 EXPECT_CALL(time_source_
, SetMediaTime(seek_time
));
283 EXPECT_CALL(time_source_
, SetPlaybackRate(_
));
284 EXPECT_CALL(time_source_
, StartTicking());
285 EXPECT_CALL(*audio_renderer_
, StartPlaying())
286 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
287 BUFFERING_HAVE_ENOUGH
));
288 EXPECT_CALL(*audio_renderer_
, SetVolume(_
));
292 EXPECT_CALL(*video_renderer_
, Flush(_
))
293 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_
,
294 BUFFERING_HAVE_NOTHING
),
296 EXPECT_CALL(*video_renderer_
, StartPlaying())
297 .WillOnce(SetBufferingState(&video_buffering_state_cb_
,
298 BUFFERING_HAVE_ENOUGH
));
301 // We expect a successful seek callback followed by a buffering update.
302 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_OK
));
303 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
306 void DoSeek(const base::TimeDelta
& seek_time
) {
307 pipeline_
->Seek(seek_time
,
308 base::Bind(&CallbackHelper::OnSeek
,
309 base::Unretained(&callbacks_
)));
311 // We expect the time to be updated only after the seek has completed.
312 EXPECT_NE(seek_time
, pipeline_
->GetMediaTime());
313 message_loop_
.RunUntilIdle();
314 EXPECT_EQ(seek_time
, pipeline_
->GetMediaTime());
317 void DestroyPipeline() {
321 void ExpectDemuxerStop() {
323 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
326 void ExpectPipelineStopAndDestroyPipeline() {
327 // After the Pipeline is stopped, it could be destroyed any time. Always
328 // destroy the pipeline immediately after OnStop() to test this.
329 EXPECT_CALL(callbacks_
, OnStop())
330 .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline
));
333 MOCK_METHOD2(OnAddTextTrack
, void(const TextTrackConfig
&,
334 const AddTextTrackDoneCB
&));
336 void DoOnAddTextTrack(const TextTrackConfig
& config
,
337 const AddTextTrackDoneCB
& done_cb
) {
338 scoped_ptr
<TextTrack
> text_track(new MockTextTrack
);
339 done_cb
.Run(text_track
.Pass());
343 StrictMock
<CallbackHelper
> callbacks_
;
344 base::SimpleTestTickClock test_tick_clock_
;
345 base::MessageLoop message_loop_
;
346 scoped_ptr
<Pipeline
> pipeline_
;
348 scoped_ptr
<FilterCollection
> filter_collection_
;
349 scoped_ptr
<StrictMock
<MockDemuxer
> > demuxer_
;
350 StrictMock
<MockVideoRenderer
>* video_renderer_
;
351 StrictMock
<MockAudioRenderer
>* audio_renderer_
;
352 StrictMock
<MockTimeSource
> time_source_
;
353 StrictMock
<CallbackHelper
> text_renderer_callbacks_
;
354 TextRenderer
* text_renderer_
;
355 scoped_ptr
<StrictMock
<MockDemuxerStream
> > audio_stream_
;
356 scoped_ptr
<StrictMock
<MockDemuxerStream
> > video_stream_
;
357 scoped_ptr
<FakeTextTrackStream
> text_stream_
;
358 AudioRenderer::TimeCB audio_time_cb_
;
359 BufferingStateCB audio_buffering_state_cb_
;
360 BufferingStateCB video_buffering_state_cb_
;
361 base::Closure audio_ended_cb_
;
362 base::Closure video_ended_cb_
;
363 VideoDecoderConfig video_decoder_config_
;
364 PipelineMetadata metadata_
;
367 DISALLOW_COPY_AND_ASSIGN(PipelineTest
);
370 // Test that playback controls methods no-op when the pipeline hasn't been
372 TEST_F(PipelineTest
, NotStarted
) {
373 const base::TimeDelta kZero
;
375 EXPECT_FALSE(pipeline_
->IsRunning());
377 // Setting should still work.
378 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
379 pipeline_
->SetPlaybackRate(-1.0f
);
380 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
381 pipeline_
->SetPlaybackRate(1.0f
);
382 EXPECT_EQ(1.0f
, pipeline_
->GetPlaybackRate());
384 // Setting should still work.
385 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
386 pipeline_
->SetVolume(-1.0f
);
387 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
388 pipeline_
->SetVolume(0.0f
);
389 EXPECT_EQ(0.0f
, pipeline_
->GetVolume());
391 EXPECT_TRUE(kZero
== pipeline_
->GetMediaTime());
392 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
393 EXPECT_TRUE(kZero
== pipeline_
->GetMediaDuration());
396 TEST_F(PipelineTest
, NeverInitializes
) {
397 // Don't execute the callback passed into Initialize().
398 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
));
400 // This test hangs during initialization by never calling
401 // InitializationComplete(). StrictMock<> will ensure that the callback is
404 filter_collection_
.Pass(),
405 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
406 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
407 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
408 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
409 base::Bind(&CallbackHelper::OnBufferingStateChange
,
410 base::Unretained(&callbacks_
)),
411 base::Bind(&CallbackHelper::OnDurationChange
,
412 base::Unretained(&callbacks_
)));
413 message_loop_
.RunUntilIdle();
415 // Because our callback will get executed when the test tears down, we'll
416 // verify that nothing has been called, then set our expectation for the call
417 // made during tear down.
418 Mock::VerifyAndClear(&callbacks_
);
419 EXPECT_CALL(callbacks_
, OnStart(PIPELINE_OK
));
422 TEST_F(PipelineTest
, StopWithoutStart
) {
423 ExpectPipelineStopAndDestroyPipeline();
425 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
426 message_loop_
.RunUntilIdle();
429 TEST_F(PipelineTest
, StartThenStopImmediately
) {
430 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
431 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
432 EXPECT_CALL(*demuxer_
, Stop(_
))
433 .WillOnce(RunClosure
<0>());
435 EXPECT_CALL(callbacks_
, OnStart(_
));
438 filter_collection_
.Pass(),
439 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
440 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
441 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
442 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
443 base::Bind(&CallbackHelper::OnBufferingStateChange
,
444 base::Unretained(&callbacks_
)),
445 base::Bind(&CallbackHelper::OnDurationChange
,
446 base::Unretained(&callbacks_
)));
448 // Expect a stop callback if we were started.
449 ExpectPipelineStopAndDestroyPipeline();
451 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
452 message_loop_
.RunUntilIdle();
455 TEST_F(PipelineTest
, DemuxerErrorDuringStop
) {
457 MockDemuxerStreamVector streams
;
458 streams
.push_back(audio_stream());
460 SetDemuxerExpectations(&streams
);
461 SetAudioRendererExpectations(audio_stream());
463 StartPipeline(PIPELINE_OK
);
465 EXPECT_CALL(*demuxer_
, Stop(_
))
466 .WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError
),
468 ExpectPipelineStopAndDestroyPipeline();
471 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
472 message_loop_
.RunUntilIdle();
475 TEST_F(PipelineTest
, URLNotFound
) {
476 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
477 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_URL_NOT_FOUND
));
478 EXPECT_CALL(*demuxer_
, Stop(_
))
479 .WillOnce(RunClosure
<0>());
481 StartPipeline(PIPELINE_ERROR_URL_NOT_FOUND
);
484 TEST_F(PipelineTest
, NoStreams
) {
485 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
486 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
487 EXPECT_CALL(*demuxer_
, Stop(_
))
488 .WillOnce(RunClosure
<0>());
490 StartPipeline(PIPELINE_ERROR_COULD_NOT_RENDER
);
493 TEST_F(PipelineTest
, AudioStream
) {
495 MockDemuxerStreamVector streams
;
496 streams
.push_back(audio_stream());
498 SetDemuxerExpectations(&streams
);
499 SetAudioRendererExpectations(audio_stream());
501 StartPipeline(PIPELINE_OK
);
502 EXPECT_TRUE(metadata_
.has_audio
);
503 EXPECT_FALSE(metadata_
.has_video
);
506 TEST_F(PipelineTest
, VideoStream
) {
508 MockDemuxerStreamVector streams
;
509 streams
.push_back(video_stream());
511 SetDemuxerExpectations(&streams
);
512 SetVideoRendererExpectations(video_stream());
514 StartPipeline(PIPELINE_OK
);
515 EXPECT_FALSE(metadata_
.has_audio
);
516 EXPECT_TRUE(metadata_
.has_video
);
519 TEST_F(PipelineTest
, AudioVideoStream
) {
522 MockDemuxerStreamVector streams
;
523 streams
.push_back(audio_stream());
524 streams
.push_back(video_stream());
526 SetDemuxerExpectations(&streams
);
527 SetAudioRendererExpectations(audio_stream());
528 SetVideoRendererExpectations(video_stream());
530 StartPipeline(PIPELINE_OK
);
531 EXPECT_TRUE(metadata_
.has_audio
);
532 EXPECT_TRUE(metadata_
.has_video
);
535 TEST_F(PipelineTest
, VideoTextStream
) {
538 MockDemuxerStreamVector streams
;
539 streams
.push_back(video_stream());
541 SetDemuxerExpectations(&streams
);
542 SetVideoRendererExpectations(video_stream());
544 StartPipeline(PIPELINE_OK
);
545 EXPECT_FALSE(metadata_
.has_audio
);
546 EXPECT_TRUE(metadata_
.has_video
);
549 message_loop_
.RunUntilIdle();
552 TEST_F(PipelineTest
, VideoAudioTextStream
) {
556 MockDemuxerStreamVector streams
;
557 streams
.push_back(video_stream());
558 streams
.push_back(audio_stream());
560 SetDemuxerExpectations(&streams
);
561 SetVideoRendererExpectations(video_stream());
562 SetAudioRendererExpectations(audio_stream());
564 StartPipeline(PIPELINE_OK
);
565 EXPECT_TRUE(metadata_
.has_audio
);
566 EXPECT_TRUE(metadata_
.has_video
);
569 message_loop_
.RunUntilIdle();
572 TEST_F(PipelineTest
, Seek
) {
576 MockDemuxerStreamVector streams
;
577 streams
.push_back(audio_stream());
578 streams
.push_back(video_stream());
580 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
581 SetAudioRendererExpectations(audio_stream());
582 SetVideoRendererExpectations(video_stream());
584 // Initialize then seek!
585 StartPipeline(PIPELINE_OK
);
587 // Every filter should receive a call to Seek().
588 base::TimeDelta expected
= base::TimeDelta::FromSeconds(2000);
589 ExpectSeek(expected
, false);
593 TEST_F(PipelineTest
, SeekAfterError
) {
595 MockDemuxerStreamVector streams
;
596 streams
.push_back(audio_stream());
598 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
599 SetAudioRendererExpectations(audio_stream());
601 // Initialize then seek!
602 StartPipeline(PIPELINE_OK
);
604 EXPECT_CALL(*demuxer_
, Stop(_
))
605 .WillOnce(RunClosure
<0>());
606 EXPECT_CALL(callbacks_
, OnError(_
));
608 static_cast<DemuxerHost
*>(pipeline_
.get())
609 ->OnDemuxerError(PIPELINE_ERROR_ABORT
);
610 message_loop_
.RunUntilIdle();
613 base::TimeDelta::FromMilliseconds(100),
614 base::Bind(&CallbackHelper::OnSeek
, base::Unretained(&callbacks_
)));
615 message_loop_
.RunUntilIdle();
618 TEST_F(PipelineTest
, SetVolume
) {
620 MockDemuxerStreamVector streams
;
621 streams
.push_back(audio_stream());
623 SetDemuxerExpectations(&streams
);
624 SetAudioRendererExpectations(audio_stream());
626 // The audio renderer should receive a call to SetVolume().
627 float expected
= 0.5f
;
628 EXPECT_CALL(*audio_renderer_
, SetVolume(expected
));
630 // Initialize then set volume!
631 StartPipeline(PIPELINE_OK
);
632 pipeline_
->SetVolume(expected
);
635 TEST_F(PipelineTest
, Properties
) {
637 MockDemuxerStreamVector streams
;
638 streams
.push_back(video_stream());
640 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
641 SetDemuxerExpectations(&streams
, kDuration
);
642 SetVideoRendererExpectations(video_stream());
644 StartPipeline(PIPELINE_OK
);
645 EXPECT_EQ(kDuration
.ToInternalValue(),
646 pipeline_
->GetMediaDuration().ToInternalValue());
647 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
650 TEST_F(PipelineTest
, GetBufferedTimeRanges
) {
652 MockDemuxerStreamVector streams
;
653 streams
.push_back(video_stream());
655 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
656 SetDemuxerExpectations(&streams
, kDuration
);
657 SetVideoRendererExpectations(video_stream());
659 StartPipeline(PIPELINE_OK
);
661 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
663 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
664 pipeline_
->AddBufferedTimeRange(base::TimeDelta(), kDuration
/ 8);
665 EXPECT_TRUE(pipeline_
->DidLoadingProgress());
666 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
667 EXPECT_EQ(1u, pipeline_
->GetBufferedTimeRanges().size());
668 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
669 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
671 base::TimeDelta kSeekTime
= kDuration
/ 2;
672 ExpectSeek(kSeekTime
, false);
675 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
678 TEST_F(PipelineTest
, EndedCallback
) {
682 MockDemuxerStreamVector streams
;
683 streams
.push_back(audio_stream());
684 streams
.push_back(video_stream());
686 SetDemuxerExpectations(&streams
);
687 SetAudioRendererExpectations(audio_stream());
688 SetVideoRendererExpectations(video_stream());
689 StartPipeline(PIPELINE_OK
);
693 // The ended callback shouldn't run until all renderers have ended.
694 audio_ended_cb_
.Run();
695 message_loop_
.RunUntilIdle();
697 video_ended_cb_
.Run();
698 message_loop_
.RunUntilIdle();
700 EXPECT_CALL(time_source_
, StopTicking());
701 EXPECT_CALL(callbacks_
, OnEnded());
702 text_stream()->SendEosNotification();
703 message_loop_
.RunUntilIdle();
706 TEST_F(PipelineTest
, AudioStreamShorterThanVideo
) {
707 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
711 MockDemuxerStreamVector streams
;
712 streams
.push_back(audio_stream());
713 streams
.push_back(video_stream());
715 // Replace what's used for interpolating to simulate wall clock time.
716 pipeline_
->SetTimeDeltaInterpolatorForTesting(
717 new TimeDeltaInterpolator(&test_tick_clock_
));
719 SetDemuxerExpectations(&streams
, duration
);
720 SetAudioRendererExpectations(audio_stream());
721 SetVideoRendererExpectations(video_stream());
722 StartPipeline(PIPELINE_OK
);
724 EXPECT_EQ(0, pipeline_
->GetMediaTime().ToInternalValue());
726 float playback_rate
= 1.0f
;
727 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
728 pipeline_
->SetPlaybackRate(playback_rate
);
729 message_loop_
.RunUntilIdle();
733 // Verify that the clock doesn't advance since it hasn't been started by
734 // a time update from the audio stream.
735 int64 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
736 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
737 EXPECT_EQ(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
739 // Signal end of audio stream.
740 audio_ended_cb_
.Run();
741 message_loop_
.RunUntilIdle();
743 // Verify that the clock advances.
744 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
745 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
746 EXPECT_GT(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
748 // Signal end of video stream and make sure OnEnded() callback occurs.
749 EXPECT_CALL(time_source_
, StopTicking());
750 EXPECT_CALL(callbacks_
, OnEnded());
751 video_ended_cb_
.Run();
754 TEST_F(PipelineTest
, ErrorDuringSeek
) {
756 MockDemuxerStreamVector streams
;
757 streams
.push_back(audio_stream());
759 SetDemuxerExpectations(&streams
);
760 SetAudioRendererExpectations(audio_stream());
761 StartPipeline(PIPELINE_OK
);
763 float playback_rate
= 1.0f
;
764 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
765 pipeline_
->SetPlaybackRate(playback_rate
);
766 message_loop_
.RunUntilIdle();
768 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
770 // Preroll() isn't called as the demuxer errors out first.
771 EXPECT_CALL(time_source_
, StopTicking());
772 EXPECT_CALL(*audio_renderer_
, Flush(_
))
773 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
774 BUFFERING_HAVE_NOTHING
),
777 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
778 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
779 EXPECT_CALL(*demuxer_
, Stop(_
))
780 .WillOnce(RunClosure
<0>());
782 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
783 base::Unretained(&callbacks_
)));
784 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
785 message_loop_
.RunUntilIdle();
788 // Invoked function OnError. This asserts that the pipeline does not enqueue
789 // non-teardown related tasks while tearing down.
790 static void TestNoCallsAfterError(
791 Pipeline
* pipeline
, base::MessageLoop
* message_loop
,
792 PipelineStatus
/* status */) {
796 // When we get to this stage, the message loop should be empty.
797 EXPECT_TRUE(message_loop
->IsIdleForTesting());
799 // Make calls on pipeline after error has occurred.
800 pipeline
->SetPlaybackRate(0.5f
);
801 pipeline
->SetVolume(0.5f
);
803 // No additional tasks should be queued as a result of these calls.
804 EXPECT_TRUE(message_loop
->IsIdleForTesting());
807 TEST_F(PipelineTest
, NoMessageDuringTearDownFromError
) {
809 MockDemuxerStreamVector streams
;
810 streams
.push_back(audio_stream());
812 SetDemuxerExpectations(&streams
);
813 SetAudioRendererExpectations(audio_stream());
814 StartPipeline(PIPELINE_OK
);
816 // Trigger additional requests on the pipeline during tear down from error.
817 base::Callback
<void(PipelineStatus
)> cb
= base::Bind(
818 &TestNoCallsAfterError
, pipeline_
.get(), &message_loop_
);
819 ON_CALL(callbacks_
, OnError(_
))
820 .WillByDefault(Invoke(&cb
, &base::Callback
<void(PipelineStatus
)>::Run
));
822 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
824 // Seek() isn't called as the demuxer errors out first.
825 EXPECT_CALL(time_source_
, StopTicking());
826 EXPECT_CALL(*audio_renderer_
, Flush(_
))
827 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
828 BUFFERING_HAVE_NOTHING
),
831 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
832 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
833 EXPECT_CALL(*demuxer_
, Stop(_
))
834 .WillOnce(RunClosure
<0>());
836 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
837 base::Unretained(&callbacks_
)));
838 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
839 message_loop_
.RunUntilIdle();
842 static void RunTimeCB(const AudioRenderer::TimeCB
& time_cb
,
844 int max_time_in_ms
) {
845 time_cb
.Run(base::TimeDelta::FromMilliseconds(time_in_ms
),
846 base::TimeDelta::FromMilliseconds(max_time_in_ms
));
849 TEST_F(PipelineTest
, AudioTimeUpdateDuringSeek
) {
851 MockDemuxerStreamVector streams
;
852 streams
.push_back(audio_stream());
854 SetDemuxerExpectations(&streams
);
855 SetAudioRendererExpectations(audio_stream());
856 StartPipeline(PIPELINE_OK
);
858 float playback_rate
= 1.0f
;
859 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
860 pipeline_
->SetPlaybackRate(playback_rate
);
861 message_loop_
.RunUntilIdle();
863 // Provide an initial time update so that the pipeline transitions out of the
864 // "waiting for time update" state.
865 audio_time_cb_
.Run(base::TimeDelta::FromMilliseconds(100),
866 base::TimeDelta::FromMilliseconds(500));
868 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
870 // Arrange to trigger a time update while the demuxer is in the middle of
871 // seeking. This update should be ignored by the pipeline and the clock should
873 base::Closure closure
= base::Bind(&RunTimeCB
, audio_time_cb_
, 300, 700);
874 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
875 .WillOnce(DoAll(InvokeWithoutArgs(&closure
, &base::Closure::Run
),
876 RunCallback
<1>(PIPELINE_OK
)));
878 EXPECT_CALL(time_source_
, StopTicking());
879 EXPECT_CALL(*audio_renderer_
, Flush(_
))
880 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
881 BUFFERING_HAVE_NOTHING
),
883 EXPECT_CALL(time_source_
, SetMediaTime(seek_time
));
884 EXPECT_CALL(time_source_
, SetPlaybackRate(_
));
885 EXPECT_CALL(time_source_
, StartTicking());
886 EXPECT_CALL(*audio_renderer_
, StartPlaying())
887 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
888 BUFFERING_HAVE_ENOUGH
));
889 EXPECT_CALL(*audio_renderer_
, SetVolume(_
));
891 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_OK
));
892 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
895 EXPECT_EQ(pipeline_
->GetMediaTime(), seek_time
);
897 // Now that the seek is complete, verify that time updates advance the current
899 base::TimeDelta new_time
= seek_time
+ base::TimeDelta::FromMilliseconds(100);
900 audio_time_cb_
.Run(new_time
, new_time
);
902 EXPECT_EQ(pipeline_
->GetMediaTime(), new_time
);
905 TEST_F(PipelineTest
, DestroyAfterStop
) {
907 MockDemuxerStreamVector streams
;
908 streams
.push_back(audio_stream());
909 SetDemuxerExpectations(&streams
);
910 SetAudioRendererExpectations(audio_stream());
911 StartPipeline(PIPELINE_OK
);
915 ExpectPipelineStopAndDestroyPipeline();
917 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
918 message_loop_
.RunUntilIdle();
921 TEST_F(PipelineTest
, Underflow
) {
924 MockDemuxerStreamVector streams
;
925 streams
.push_back(audio_stream());
926 streams
.push_back(video_stream());
928 SetDemuxerExpectations(&streams
);
929 SetAudioRendererExpectations(audio_stream());
930 SetVideoRendererExpectations(video_stream());
931 StartPipeline(PIPELINE_OK
);
933 // Simulate underflow.
934 EXPECT_CALL(time_source_
, StopTicking());
935 audio_buffering_state_cb_
.Run(BUFFERING_HAVE_NOTHING
);
937 // Seek while underflowed. We shouldn't call StopTicking() again.
938 base::TimeDelta expected
= base::TimeDelta::FromSeconds(5);
939 ExpectSeek(expected
, true);
943 static void PostTimeCB(base::MessageLoop
* message_loop
,
944 const AudioRenderer::TimeCB
& time_cb
) {
945 base::TimeDelta new_time
= base::TimeDelta::FromMilliseconds(100);
946 message_loop
->PostTask(FROM_HERE
, base::Bind(time_cb
, new_time
, new_time
));
949 TEST_F(PipelineTest
, TimeUpdateAfterStop
) {
952 MockDemuxerStreamVector streams
;
953 streams
.push_back(audio_stream());
954 streams
.push_back(video_stream());
956 SetDemuxerExpectations(&streams
);
957 SetAudioRendererExpectations(audio_stream());
958 SetVideoRendererExpectations(video_stream());
959 StartPipeline(PIPELINE_OK
);
961 // Double post here! This is a hack to simulate the case where TimeCB is
962 // posted during ~AudioRenderer(), which is triggered in Pipeline::DoStop.
963 // Since we can't EXPECT_CALL the dtor and Pipeline::DoStop() is posted
964 // as well, we need to post twice here.
965 message_loop_
.PostTask(
966 FROM_HERE
, base::Bind(&PostTimeCB
, &message_loop_
, audio_time_cb_
));
968 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
970 ExpectPipelineStopAndDestroyPipeline();
972 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
973 message_loop_
.RunUntilIdle();
976 class PipelineTeardownTest
: public PipelineTest
{
993 PipelineTeardownTest() {}
994 virtual ~PipelineTeardownTest() {}
996 void RunTest(TeardownState state
, StopOrError stop_or_error
) {
999 case kInitAudioRenderer
:
1000 case kInitVideoRenderer
:
1001 DoInitialize(state
, stop_or_error
);
1006 DoInitialize(state
, stop_or_error
);
1007 DoSeek(state
, stop_or_error
);
1011 DoInitialize(state
, stop_or_error
);
1012 DoStopOrError(stop_or_error
);
1018 // TODO(scherkus): We do radically different things whether teardown is
1019 // invoked via stop vs error. The teardown path should be the same,
1020 // see http://crbug.com/110228
1021 void DoInitialize(TeardownState state
, StopOrError stop_or_error
) {
1022 PipelineStatus expected_status
=
1023 SetInitializeExpectations(state
, stop_or_error
);
1025 EXPECT_CALL(callbacks_
, OnStart(expected_status
));
1027 filter_collection_
.Pass(),
1028 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
1029 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
1030 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
1031 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
1032 base::Bind(&CallbackHelper::OnBufferingStateChange
,
1033 base::Unretained(&callbacks_
)),
1034 base::Bind(&CallbackHelper::OnDurationChange
,
1035 base::Unretained(&callbacks_
)));
1036 message_loop_
.RunUntilIdle();
1039 PipelineStatus
SetInitializeExpectations(TeardownState state
,
1040 StopOrError stop_or_error
) {
1041 PipelineStatus status
= PIPELINE_OK
;
1042 base::Closure stop_cb
= base::Bind(
1043 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
1045 if (state
== kInitDemuxer
) {
1046 if (stop_or_error
== kStop
) {
1047 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
1048 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1049 RunCallback
<1>(PIPELINE_OK
)));
1050 ExpectPipelineStopAndDestroyPipeline();
1052 status
= DEMUXER_ERROR_COULD_NOT_OPEN
;
1053 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
1054 .WillOnce(RunCallback
<1>(status
));
1057 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1061 CreateAudioStream();
1062 CreateVideoStream();
1063 MockDemuxerStreamVector streams
;
1064 streams
.push_back(audio_stream());
1065 streams
.push_back(video_stream());
1066 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
1068 if (state
== kInitAudioRenderer
) {
1069 if (stop_or_error
== kStop
) {
1070 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1071 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1072 RunCallback
<1>(PIPELINE_OK
)));
1073 ExpectPipelineStopAndDestroyPipeline();
1075 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
1076 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1077 .WillOnce(RunCallback
<1>(status
));
1080 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1084 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1085 .WillOnce(DoAll(SaveArg
<4>(&audio_buffering_state_cb_
),
1086 RunCallback
<1>(PIPELINE_OK
)));
1088 if (state
== kInitVideoRenderer
) {
1089 if (stop_or_error
== kStop
) {
1090 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1091 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1092 RunCallback
<2>(PIPELINE_OK
)));
1093 ExpectPipelineStopAndDestroyPipeline();
1095 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
1096 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1097 .WillOnce(RunCallback
<2>(status
));
1100 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1104 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1105 .WillOnce(DoAll(SaveArg
<5>(&video_buffering_state_cb_
),
1106 RunCallback
<2>(PIPELINE_OK
)));
1108 EXPECT_CALL(callbacks_
, OnMetadata(_
));
1110 // If we get here it's a successful initialization.
1111 EXPECT_CALL(*audio_renderer_
, GetTimeSource())
1112 .WillOnce(Return(&time_source_
));
1113 EXPECT_CALL(time_source_
, SetMediaTime(base::TimeDelta()));
1114 EXPECT_CALL(time_source_
, SetPlaybackRate(0.0f
));
1115 EXPECT_CALL(time_source_
, StartTicking());
1116 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
1117 EXPECT_CALL(*audio_renderer_
, StartPlaying())
1118 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
1119 BUFFERING_HAVE_ENOUGH
));
1120 EXPECT_CALL(*video_renderer_
, StartPlaying())
1121 .WillOnce(SetBufferingState(&video_buffering_state_cb_
,
1122 BUFFERING_HAVE_ENOUGH
));
1124 if (status
== PIPELINE_OK
)
1125 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
1130 void DoSeek(TeardownState state
, StopOrError stop_or_error
) {
1132 PipelineStatus status
= SetSeekExpectations(state
, stop_or_error
);
1134 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1135 EXPECT_CALL(callbacks_
, OnSeek(status
));
1137 if (status
== PIPELINE_OK
) {
1138 ExpectPipelineStopAndDestroyPipeline();
1141 pipeline_
->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1142 &CallbackHelper::OnSeek
, base::Unretained(&callbacks_
)));
1143 message_loop_
.RunUntilIdle();
1146 PipelineStatus
SetSeekExpectations(TeardownState state
,
1147 StopOrError stop_or_error
) {
1148 PipelineStatus status
= PIPELINE_OK
;
1149 base::Closure stop_cb
= base::Bind(
1150 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
1152 EXPECT_CALL(time_source_
, StopTicking());
1154 if (state
== kFlushing
) {
1155 if (stop_or_error
== kStop
) {
1156 EXPECT_CALL(*audio_renderer_
, Flush(_
))
1157 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1158 SetBufferingState(&audio_buffering_state_cb_
,
1159 BUFFERING_HAVE_NOTHING
),
1162 status
= PIPELINE_ERROR_READ
;
1163 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(
1164 DoAll(SetError(pipeline_
.get(), status
),
1165 SetBufferingState(&audio_buffering_state_cb_
,
1166 BUFFERING_HAVE_NOTHING
),
1173 EXPECT_CALL(*audio_renderer_
, Flush(_
))
1174 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
1175 BUFFERING_HAVE_NOTHING
),
1177 EXPECT_CALL(*video_renderer_
, Flush(_
))
1178 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_
,
1179 BUFFERING_HAVE_NOTHING
),
1182 if (state
== kSeeking
) {
1183 if (stop_or_error
== kStop
) {
1184 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1185 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1186 RunCallback
<1>(PIPELINE_OK
)));
1188 status
= PIPELINE_ERROR_READ
;
1189 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1190 .WillOnce(RunCallback
<1>(status
));
1196 NOTREACHED() << "State not supported: " << state
;
1200 void DoStopOrError(StopOrError stop_or_error
) {
1203 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1205 switch (stop_or_error
) {
1207 ExpectPipelineStopAndDestroyPipeline();
1208 pipeline_
->Stop(base::Bind(
1209 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1213 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1214 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1218 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1219 ExpectPipelineStopAndDestroyPipeline();
1220 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1221 pipeline_
->Stop(base::Bind(
1222 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1226 message_loop_
.RunUntilIdle();
1229 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest
);
1232 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1233 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1234 RunTest(k##state, k##stop_or_error); \
1237 INSTANTIATE_TEARDOWN_TEST(Stop
, InitDemuxer
);
1238 INSTANTIATE_TEARDOWN_TEST(Stop
, InitAudioRenderer
);
1239 INSTANTIATE_TEARDOWN_TEST(Stop
, InitVideoRenderer
);
1240 INSTANTIATE_TEARDOWN_TEST(Stop
, Flushing
);
1241 INSTANTIATE_TEARDOWN_TEST(Stop
, Seeking
);
1242 INSTANTIATE_TEARDOWN_TEST(Stop
, Playing
);
1244 INSTANTIATE_TEARDOWN_TEST(Error
, InitDemuxer
);
1245 INSTANTIATE_TEARDOWN_TEST(Error
, InitAudioRenderer
);
1246 INSTANTIATE_TEARDOWN_TEST(Error
, InitVideoRenderer
);
1247 INSTANTIATE_TEARDOWN_TEST(Error
, Flushing
);
1248 INSTANTIATE_TEARDOWN_TEST(Error
, Seeking
);
1249 INSTANTIATE_TEARDOWN_TEST(Error
, Playing
);
1251 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop
, Playing
);
1253 } // namespace media