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() {
318 // In real code Pipeline could be destroyed on a different thread. All weak
319 // pointers must have been invalidated before the stop callback returns.
320 DCHECK(!pipeline_
->HasWeakPtrsForTesting());
324 void ExpectDemuxerStop() {
326 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
329 void ExpectPipelineStopAndDestroyPipeline() {
330 // After the Pipeline is stopped, it could be destroyed any time. Always
331 // destroy the pipeline immediately after OnStop() to test this.
332 EXPECT_CALL(callbacks_
, OnStop())
333 .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline
));
336 MOCK_METHOD2(OnAddTextTrack
, void(const TextTrackConfig
&,
337 const AddTextTrackDoneCB
&));
339 void DoOnAddTextTrack(const TextTrackConfig
& config
,
340 const AddTextTrackDoneCB
& done_cb
) {
341 scoped_ptr
<TextTrack
> text_track(new MockTextTrack
);
342 done_cb
.Run(text_track
.Pass());
346 StrictMock
<CallbackHelper
> callbacks_
;
347 base::SimpleTestTickClock test_tick_clock_
;
348 base::MessageLoop message_loop_
;
349 scoped_ptr
<Pipeline
> pipeline_
;
351 scoped_ptr
<FilterCollection
> filter_collection_
;
352 scoped_ptr
<StrictMock
<MockDemuxer
> > demuxer_
;
353 StrictMock
<MockVideoRenderer
>* video_renderer_
;
354 StrictMock
<MockAudioRenderer
>* audio_renderer_
;
355 StrictMock
<MockTimeSource
> time_source_
;
356 StrictMock
<CallbackHelper
> text_renderer_callbacks_
;
357 TextRenderer
* text_renderer_
;
358 scoped_ptr
<StrictMock
<MockDemuxerStream
> > audio_stream_
;
359 scoped_ptr
<StrictMock
<MockDemuxerStream
> > video_stream_
;
360 scoped_ptr
<FakeTextTrackStream
> text_stream_
;
361 AudioRenderer::TimeCB audio_time_cb_
;
362 BufferingStateCB audio_buffering_state_cb_
;
363 BufferingStateCB video_buffering_state_cb_
;
364 base::Closure audio_ended_cb_
;
365 base::Closure video_ended_cb_
;
366 VideoDecoderConfig video_decoder_config_
;
367 PipelineMetadata metadata_
;
370 DISALLOW_COPY_AND_ASSIGN(PipelineTest
);
373 // Test that playback controls methods no-op when the pipeline hasn't been
375 TEST_F(PipelineTest
, NotStarted
) {
376 const base::TimeDelta kZero
;
378 EXPECT_FALSE(pipeline_
->IsRunning());
380 // Setting should still work.
381 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
382 pipeline_
->SetPlaybackRate(-1.0f
);
383 EXPECT_EQ(0.0f
, pipeline_
->GetPlaybackRate());
384 pipeline_
->SetPlaybackRate(1.0f
);
385 EXPECT_EQ(1.0f
, pipeline_
->GetPlaybackRate());
387 // Setting should still work.
388 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
389 pipeline_
->SetVolume(-1.0f
);
390 EXPECT_EQ(1.0f
, pipeline_
->GetVolume());
391 pipeline_
->SetVolume(0.0f
);
392 EXPECT_EQ(0.0f
, pipeline_
->GetVolume());
394 EXPECT_TRUE(kZero
== pipeline_
->GetMediaTime());
395 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
396 EXPECT_TRUE(kZero
== pipeline_
->GetMediaDuration());
399 TEST_F(PipelineTest
, NeverInitializes
) {
400 // Don't execute the callback passed into Initialize().
401 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
));
403 // This test hangs during initialization by never calling
404 // InitializationComplete(). StrictMock<> will ensure that the callback is
407 filter_collection_
.Pass(),
408 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
409 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
410 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
411 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
412 base::Bind(&CallbackHelper::OnBufferingStateChange
,
413 base::Unretained(&callbacks_
)),
414 base::Bind(&CallbackHelper::OnDurationChange
,
415 base::Unretained(&callbacks_
)));
416 message_loop_
.RunUntilIdle();
418 // Because our callback will get executed when the test tears down, we'll
419 // verify that nothing has been called, then set our expectation for the call
420 // made during tear down.
421 Mock::VerifyAndClear(&callbacks_
);
422 EXPECT_CALL(callbacks_
, OnStart(PIPELINE_OK
));
425 TEST_F(PipelineTest
, StopWithoutStart
) {
426 ExpectPipelineStopAndDestroyPipeline();
428 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
429 message_loop_
.RunUntilIdle();
432 TEST_F(PipelineTest
, StartThenStopImmediately
) {
433 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
434 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
435 EXPECT_CALL(*demuxer_
, Stop(_
))
436 .WillOnce(RunClosure
<0>());
438 EXPECT_CALL(callbacks_
, OnStart(_
));
441 filter_collection_
.Pass(),
442 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
443 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
444 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
445 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
446 base::Bind(&CallbackHelper::OnBufferingStateChange
,
447 base::Unretained(&callbacks_
)),
448 base::Bind(&CallbackHelper::OnDurationChange
,
449 base::Unretained(&callbacks_
)));
451 // Expect a stop callback if we were started.
452 ExpectPipelineStopAndDestroyPipeline();
454 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
455 message_loop_
.RunUntilIdle();
458 TEST_F(PipelineTest
, DemuxerErrorDuringStop
) {
460 MockDemuxerStreamVector streams
;
461 streams
.push_back(audio_stream());
463 SetDemuxerExpectations(&streams
);
464 SetAudioRendererExpectations(audio_stream());
466 StartPipeline(PIPELINE_OK
);
468 EXPECT_CALL(*demuxer_
, Stop(_
))
469 .WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError
),
471 ExpectPipelineStopAndDestroyPipeline();
474 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
475 message_loop_
.RunUntilIdle();
478 TEST_F(PipelineTest
, URLNotFound
) {
479 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
480 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_URL_NOT_FOUND
));
481 EXPECT_CALL(*demuxer_
, Stop(_
))
482 .WillOnce(RunClosure
<0>());
484 StartPipeline(PIPELINE_ERROR_URL_NOT_FOUND
);
487 TEST_F(PipelineTest
, NoStreams
) {
488 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
489 .WillOnce(RunCallback
<1>(PIPELINE_OK
));
490 EXPECT_CALL(*demuxer_
, Stop(_
))
491 .WillOnce(RunClosure
<0>());
493 StartPipeline(PIPELINE_ERROR_COULD_NOT_RENDER
);
496 TEST_F(PipelineTest
, AudioStream
) {
498 MockDemuxerStreamVector streams
;
499 streams
.push_back(audio_stream());
501 SetDemuxerExpectations(&streams
);
502 SetAudioRendererExpectations(audio_stream());
504 StartPipeline(PIPELINE_OK
);
505 EXPECT_TRUE(metadata_
.has_audio
);
506 EXPECT_FALSE(metadata_
.has_video
);
509 TEST_F(PipelineTest
, VideoStream
) {
511 MockDemuxerStreamVector streams
;
512 streams
.push_back(video_stream());
514 SetDemuxerExpectations(&streams
);
515 SetVideoRendererExpectations(video_stream());
517 StartPipeline(PIPELINE_OK
);
518 EXPECT_FALSE(metadata_
.has_audio
);
519 EXPECT_TRUE(metadata_
.has_video
);
522 TEST_F(PipelineTest
, AudioVideoStream
) {
525 MockDemuxerStreamVector streams
;
526 streams
.push_back(audio_stream());
527 streams
.push_back(video_stream());
529 SetDemuxerExpectations(&streams
);
530 SetAudioRendererExpectations(audio_stream());
531 SetVideoRendererExpectations(video_stream());
533 StartPipeline(PIPELINE_OK
);
534 EXPECT_TRUE(metadata_
.has_audio
);
535 EXPECT_TRUE(metadata_
.has_video
);
538 TEST_F(PipelineTest
, VideoTextStream
) {
541 MockDemuxerStreamVector streams
;
542 streams
.push_back(video_stream());
544 SetDemuxerExpectations(&streams
);
545 SetVideoRendererExpectations(video_stream());
547 StartPipeline(PIPELINE_OK
);
548 EXPECT_FALSE(metadata_
.has_audio
);
549 EXPECT_TRUE(metadata_
.has_video
);
552 message_loop_
.RunUntilIdle();
555 TEST_F(PipelineTest
, VideoAudioTextStream
) {
559 MockDemuxerStreamVector streams
;
560 streams
.push_back(video_stream());
561 streams
.push_back(audio_stream());
563 SetDemuxerExpectations(&streams
);
564 SetVideoRendererExpectations(video_stream());
565 SetAudioRendererExpectations(audio_stream());
567 StartPipeline(PIPELINE_OK
);
568 EXPECT_TRUE(metadata_
.has_audio
);
569 EXPECT_TRUE(metadata_
.has_video
);
572 message_loop_
.RunUntilIdle();
575 TEST_F(PipelineTest
, Seek
) {
579 MockDemuxerStreamVector streams
;
580 streams
.push_back(audio_stream());
581 streams
.push_back(video_stream());
583 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
584 SetAudioRendererExpectations(audio_stream());
585 SetVideoRendererExpectations(video_stream());
587 // Initialize then seek!
588 StartPipeline(PIPELINE_OK
);
590 // Every filter should receive a call to Seek().
591 base::TimeDelta expected
= base::TimeDelta::FromSeconds(2000);
592 ExpectSeek(expected
, false);
596 TEST_F(PipelineTest
, SeekAfterError
) {
598 MockDemuxerStreamVector streams
;
599 streams
.push_back(audio_stream());
601 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
602 SetAudioRendererExpectations(audio_stream());
604 // Initialize then seek!
605 StartPipeline(PIPELINE_OK
);
607 EXPECT_CALL(*demuxer_
, Stop(_
))
608 .WillOnce(RunClosure
<0>());
609 EXPECT_CALL(callbacks_
, OnError(_
));
611 static_cast<DemuxerHost
*>(pipeline_
.get())
612 ->OnDemuxerError(PIPELINE_ERROR_ABORT
);
613 message_loop_
.RunUntilIdle();
616 base::TimeDelta::FromMilliseconds(100),
617 base::Bind(&CallbackHelper::OnSeek
, base::Unretained(&callbacks_
)));
618 message_loop_
.RunUntilIdle();
621 TEST_F(PipelineTest
, SetVolume
) {
623 MockDemuxerStreamVector streams
;
624 streams
.push_back(audio_stream());
626 SetDemuxerExpectations(&streams
);
627 SetAudioRendererExpectations(audio_stream());
629 // The audio renderer should receive a call to SetVolume().
630 float expected
= 0.5f
;
631 EXPECT_CALL(*audio_renderer_
, SetVolume(expected
));
633 // Initialize then set volume!
634 StartPipeline(PIPELINE_OK
);
635 pipeline_
->SetVolume(expected
);
638 TEST_F(PipelineTest
, Properties
) {
640 MockDemuxerStreamVector streams
;
641 streams
.push_back(video_stream());
643 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
644 SetDemuxerExpectations(&streams
, kDuration
);
645 SetVideoRendererExpectations(video_stream());
647 StartPipeline(PIPELINE_OK
);
648 EXPECT_EQ(kDuration
.ToInternalValue(),
649 pipeline_
->GetMediaDuration().ToInternalValue());
650 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
653 TEST_F(PipelineTest
, GetBufferedTimeRanges
) {
655 MockDemuxerStreamVector streams
;
656 streams
.push_back(video_stream());
658 const base::TimeDelta kDuration
= base::TimeDelta::FromSeconds(100);
659 SetDemuxerExpectations(&streams
, kDuration
);
660 SetVideoRendererExpectations(video_stream());
662 StartPipeline(PIPELINE_OK
);
664 EXPECT_EQ(0u, pipeline_
->GetBufferedTimeRanges().size());
666 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
667 pipeline_
->AddBufferedTimeRange(base::TimeDelta(), kDuration
/ 8);
668 EXPECT_TRUE(pipeline_
->DidLoadingProgress());
669 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
670 EXPECT_EQ(1u, pipeline_
->GetBufferedTimeRanges().size());
671 EXPECT_EQ(base::TimeDelta(), pipeline_
->GetBufferedTimeRanges().start(0));
672 EXPECT_EQ(kDuration
/ 8, pipeline_
->GetBufferedTimeRanges().end(0));
674 base::TimeDelta kSeekTime
= kDuration
/ 2;
675 ExpectSeek(kSeekTime
, false);
678 EXPECT_FALSE(pipeline_
->DidLoadingProgress());
681 TEST_F(PipelineTest
, EndedCallback
) {
685 MockDemuxerStreamVector streams
;
686 streams
.push_back(audio_stream());
687 streams
.push_back(video_stream());
689 SetDemuxerExpectations(&streams
);
690 SetAudioRendererExpectations(audio_stream());
691 SetVideoRendererExpectations(video_stream());
692 StartPipeline(PIPELINE_OK
);
696 // The ended callback shouldn't run until all renderers have ended.
697 audio_ended_cb_
.Run();
698 message_loop_
.RunUntilIdle();
700 video_ended_cb_
.Run();
701 message_loop_
.RunUntilIdle();
703 EXPECT_CALL(time_source_
, StopTicking());
704 EXPECT_CALL(callbacks_
, OnEnded());
705 text_stream()->SendEosNotification();
706 message_loop_
.RunUntilIdle();
709 TEST_F(PipelineTest
, AudioStreamShorterThanVideo
) {
710 base::TimeDelta duration
= base::TimeDelta::FromSeconds(10);
714 MockDemuxerStreamVector streams
;
715 streams
.push_back(audio_stream());
716 streams
.push_back(video_stream());
718 // Replace what's used for interpolating to simulate wall clock time.
719 pipeline_
->SetTimeDeltaInterpolatorForTesting(
720 new TimeDeltaInterpolator(&test_tick_clock_
));
722 SetDemuxerExpectations(&streams
, duration
);
723 SetAudioRendererExpectations(audio_stream());
724 SetVideoRendererExpectations(video_stream());
725 StartPipeline(PIPELINE_OK
);
727 EXPECT_EQ(0, pipeline_
->GetMediaTime().ToInternalValue());
729 float playback_rate
= 1.0f
;
730 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
731 pipeline_
->SetPlaybackRate(playback_rate
);
732 message_loop_
.RunUntilIdle();
736 // Verify that the clock doesn't advance since it hasn't been started by
737 // a time update from the audio stream.
738 int64 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
739 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
740 EXPECT_EQ(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
742 // Signal end of audio stream.
743 audio_ended_cb_
.Run();
744 message_loop_
.RunUntilIdle();
746 // Verify that the clock advances.
747 start_time
= pipeline_
->GetMediaTime().ToInternalValue();
748 test_tick_clock_
.Advance(base::TimeDelta::FromMilliseconds(100));
749 EXPECT_GT(pipeline_
->GetMediaTime().ToInternalValue(), start_time
);
751 // Signal end of video stream and make sure OnEnded() callback occurs.
752 EXPECT_CALL(time_source_
, StopTicking());
753 EXPECT_CALL(callbacks_
, OnEnded());
754 video_ended_cb_
.Run();
757 TEST_F(PipelineTest
, ErrorDuringSeek
) {
759 MockDemuxerStreamVector streams
;
760 streams
.push_back(audio_stream());
762 SetDemuxerExpectations(&streams
);
763 SetAudioRendererExpectations(audio_stream());
764 StartPipeline(PIPELINE_OK
);
766 float playback_rate
= 1.0f
;
767 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
768 pipeline_
->SetPlaybackRate(playback_rate
);
769 message_loop_
.RunUntilIdle();
771 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
773 // Preroll() isn't called as the demuxer errors out first.
774 EXPECT_CALL(time_source_
, StopTicking());
775 EXPECT_CALL(*audio_renderer_
, Flush(_
))
776 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
777 BUFFERING_HAVE_NOTHING
),
780 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
781 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
782 EXPECT_CALL(*demuxer_
, Stop(_
))
783 .WillOnce(RunClosure
<0>());
785 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
786 base::Unretained(&callbacks_
)));
787 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
788 message_loop_
.RunUntilIdle();
791 // Invoked function OnError. This asserts that the pipeline does not enqueue
792 // non-teardown related tasks while tearing down.
793 static void TestNoCallsAfterError(
794 Pipeline
* pipeline
, base::MessageLoop
* message_loop
,
795 PipelineStatus
/* status */) {
799 // When we get to this stage, the message loop should be empty.
800 EXPECT_TRUE(message_loop
->IsIdleForTesting());
802 // Make calls on pipeline after error has occurred.
803 pipeline
->SetPlaybackRate(0.5f
);
804 pipeline
->SetVolume(0.5f
);
806 // No additional tasks should be queued as a result of these calls.
807 EXPECT_TRUE(message_loop
->IsIdleForTesting());
810 TEST_F(PipelineTest
, NoMessageDuringTearDownFromError
) {
812 MockDemuxerStreamVector streams
;
813 streams
.push_back(audio_stream());
815 SetDemuxerExpectations(&streams
);
816 SetAudioRendererExpectations(audio_stream());
817 StartPipeline(PIPELINE_OK
);
819 // Trigger additional requests on the pipeline during tear down from error.
820 base::Callback
<void(PipelineStatus
)> cb
= base::Bind(
821 &TestNoCallsAfterError
, pipeline_
.get(), &message_loop_
);
822 ON_CALL(callbacks_
, OnError(_
))
823 .WillByDefault(Invoke(&cb
, &base::Callback
<void(PipelineStatus
)>::Run
));
825 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
827 // Seek() isn't called as the demuxer errors out first.
828 EXPECT_CALL(time_source_
, StopTicking());
829 EXPECT_CALL(*audio_renderer_
, Flush(_
))
830 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
831 BUFFERING_HAVE_NOTHING
),
834 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
835 .WillOnce(RunCallback
<1>(PIPELINE_ERROR_READ
));
836 EXPECT_CALL(*demuxer_
, Stop(_
))
837 .WillOnce(RunClosure
<0>());
839 pipeline_
->Seek(seek_time
, base::Bind(&CallbackHelper::OnSeek
,
840 base::Unretained(&callbacks_
)));
841 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_ERROR_READ
));
842 message_loop_
.RunUntilIdle();
845 static void RunTimeCB(const AudioRenderer::TimeCB
& time_cb
,
847 int max_time_in_ms
) {
848 time_cb
.Run(base::TimeDelta::FromMilliseconds(time_in_ms
),
849 base::TimeDelta::FromMilliseconds(max_time_in_ms
));
852 TEST_F(PipelineTest
, AudioTimeUpdateDuringSeek
) {
854 MockDemuxerStreamVector streams
;
855 streams
.push_back(audio_stream());
857 SetDemuxerExpectations(&streams
);
858 SetAudioRendererExpectations(audio_stream());
859 StartPipeline(PIPELINE_OK
);
861 float playback_rate
= 1.0f
;
862 EXPECT_CALL(time_source_
, SetPlaybackRate(playback_rate
));
863 pipeline_
->SetPlaybackRate(playback_rate
);
864 message_loop_
.RunUntilIdle();
866 // Provide an initial time update so that the pipeline transitions out of the
867 // "waiting for time update" state.
868 audio_time_cb_
.Run(base::TimeDelta::FromMilliseconds(100),
869 base::TimeDelta::FromMilliseconds(500));
871 base::TimeDelta seek_time
= base::TimeDelta::FromSeconds(5);
873 // Arrange to trigger a time update while the demuxer is in the middle of
874 // seeking. This update should be ignored by the pipeline and the clock should
876 base::Closure closure
= base::Bind(&RunTimeCB
, audio_time_cb_
, 300, 700);
877 EXPECT_CALL(*demuxer_
, Seek(seek_time
, _
))
878 .WillOnce(DoAll(InvokeWithoutArgs(&closure
, &base::Closure::Run
),
879 RunCallback
<1>(PIPELINE_OK
)));
881 EXPECT_CALL(time_source_
, StopTicking());
882 EXPECT_CALL(*audio_renderer_
, Flush(_
))
883 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
884 BUFFERING_HAVE_NOTHING
),
886 EXPECT_CALL(time_source_
, SetMediaTime(seek_time
));
887 EXPECT_CALL(time_source_
, SetPlaybackRate(_
));
888 EXPECT_CALL(time_source_
, StartTicking());
889 EXPECT_CALL(*audio_renderer_
, StartPlaying())
890 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
891 BUFFERING_HAVE_ENOUGH
));
892 EXPECT_CALL(*audio_renderer_
, SetVolume(_
));
894 EXPECT_CALL(callbacks_
, OnSeek(PIPELINE_OK
));
895 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
898 EXPECT_EQ(pipeline_
->GetMediaTime(), seek_time
);
900 // Now that the seek is complete, verify that time updates advance the current
902 base::TimeDelta new_time
= seek_time
+ base::TimeDelta::FromMilliseconds(100);
903 audio_time_cb_
.Run(new_time
, new_time
);
905 EXPECT_EQ(pipeline_
->GetMediaTime(), new_time
);
908 TEST_F(PipelineTest
, DestroyAfterStop
) {
910 MockDemuxerStreamVector streams
;
911 streams
.push_back(audio_stream());
912 SetDemuxerExpectations(&streams
);
913 SetAudioRendererExpectations(audio_stream());
914 StartPipeline(PIPELINE_OK
);
918 ExpectPipelineStopAndDestroyPipeline();
920 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
921 message_loop_
.RunUntilIdle();
924 TEST_F(PipelineTest
, Underflow
) {
927 MockDemuxerStreamVector streams
;
928 streams
.push_back(audio_stream());
929 streams
.push_back(video_stream());
931 SetDemuxerExpectations(&streams
);
932 SetAudioRendererExpectations(audio_stream());
933 SetVideoRendererExpectations(video_stream());
934 StartPipeline(PIPELINE_OK
);
936 // Simulate underflow.
937 EXPECT_CALL(time_source_
, StopTicking());
938 audio_buffering_state_cb_
.Run(BUFFERING_HAVE_NOTHING
);
940 // Seek while underflowed. We shouldn't call StopTicking() again.
941 base::TimeDelta expected
= base::TimeDelta::FromSeconds(5);
942 ExpectSeek(expected
, true);
946 static void PostTimeCB(base::MessageLoop
* message_loop
,
947 const AudioRenderer::TimeCB
& time_cb
) {
948 base::TimeDelta new_time
= base::TimeDelta::FromMilliseconds(100);
949 message_loop
->PostTask(FROM_HERE
, base::Bind(time_cb
, new_time
, new_time
));
952 TEST_F(PipelineTest
, TimeUpdateAfterStop
) {
955 MockDemuxerStreamVector streams
;
956 streams
.push_back(audio_stream());
957 streams
.push_back(video_stream());
959 SetDemuxerExpectations(&streams
);
960 SetAudioRendererExpectations(audio_stream());
961 SetVideoRendererExpectations(video_stream());
962 StartPipeline(PIPELINE_OK
);
964 // Double post here! This is a hack to simulate the case where TimeCB is
965 // posted during ~AudioRenderer(), which is triggered in Pipeline::DoStop.
966 // Since we can't EXPECT_CALL the dtor and Pipeline::DoStop() is posted
967 // as well, we need to post twice here.
968 message_loop_
.PostTask(
969 FROM_HERE
, base::Bind(&PostTimeCB
, &message_loop_
, audio_time_cb_
));
971 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
973 ExpectPipelineStopAndDestroyPipeline();
975 base::Bind(&CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
976 message_loop_
.RunUntilIdle();
979 class PipelineTeardownTest
: public PipelineTest
{
996 PipelineTeardownTest() {}
997 virtual ~PipelineTeardownTest() {}
999 void RunTest(TeardownState state
, StopOrError stop_or_error
) {
1002 case kInitAudioRenderer
:
1003 case kInitVideoRenderer
:
1004 DoInitialize(state
, stop_or_error
);
1009 DoInitialize(state
, stop_or_error
);
1010 DoSeek(state
, stop_or_error
);
1014 DoInitialize(state
, stop_or_error
);
1015 DoStopOrError(stop_or_error
);
1021 // TODO(scherkus): We do radically different things whether teardown is
1022 // invoked via stop vs error. The teardown path should be the same,
1023 // see http://crbug.com/110228
1024 void DoInitialize(TeardownState state
, StopOrError stop_or_error
) {
1025 PipelineStatus expected_status
=
1026 SetInitializeExpectations(state
, stop_or_error
);
1028 EXPECT_CALL(callbacks_
, OnStart(expected_status
));
1030 filter_collection_
.Pass(),
1031 base::Bind(&CallbackHelper::OnEnded
, base::Unretained(&callbacks_
)),
1032 base::Bind(&CallbackHelper::OnError
, base::Unretained(&callbacks_
)),
1033 base::Bind(&CallbackHelper::OnStart
, base::Unretained(&callbacks_
)),
1034 base::Bind(&CallbackHelper::OnMetadata
, base::Unretained(&callbacks_
)),
1035 base::Bind(&CallbackHelper::OnBufferingStateChange
,
1036 base::Unretained(&callbacks_
)),
1037 base::Bind(&CallbackHelper::OnDurationChange
,
1038 base::Unretained(&callbacks_
)));
1039 message_loop_
.RunUntilIdle();
1042 PipelineStatus
SetInitializeExpectations(TeardownState state
,
1043 StopOrError stop_or_error
) {
1044 PipelineStatus status
= PIPELINE_OK
;
1045 base::Closure stop_cb
= base::Bind(
1046 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
1048 if (state
== kInitDemuxer
) {
1049 if (stop_or_error
== kStop
) {
1050 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
1051 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1052 RunCallback
<1>(PIPELINE_OK
)));
1053 ExpectPipelineStopAndDestroyPipeline();
1055 status
= DEMUXER_ERROR_COULD_NOT_OPEN
;
1056 EXPECT_CALL(*demuxer_
, Initialize(_
, _
, _
))
1057 .WillOnce(RunCallback
<1>(status
));
1060 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1064 CreateAudioStream();
1065 CreateVideoStream();
1066 MockDemuxerStreamVector streams
;
1067 streams
.push_back(audio_stream());
1068 streams
.push_back(video_stream());
1069 SetDemuxerExpectations(&streams
, base::TimeDelta::FromSeconds(3000));
1071 if (state
== kInitAudioRenderer
) {
1072 if (stop_or_error
== kStop
) {
1073 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1074 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1075 RunCallback
<1>(PIPELINE_OK
)));
1076 ExpectPipelineStopAndDestroyPipeline();
1078 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
1079 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1080 .WillOnce(RunCallback
<1>(status
));
1083 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1087 EXPECT_CALL(*audio_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
))
1088 .WillOnce(DoAll(SaveArg
<4>(&audio_buffering_state_cb_
),
1089 RunCallback
<1>(PIPELINE_OK
)));
1091 if (state
== kInitVideoRenderer
) {
1092 if (stop_or_error
== kStop
) {
1093 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1094 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1095 RunCallback
<2>(PIPELINE_OK
)));
1096 ExpectPipelineStopAndDestroyPipeline();
1098 status
= PIPELINE_ERROR_INITIALIZATION_FAILED
;
1099 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1100 .WillOnce(RunCallback
<2>(status
));
1103 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1107 EXPECT_CALL(*video_renderer_
, Initialize(_
, _
, _
, _
, _
, _
, _
, _
, _
, _
))
1108 .WillOnce(DoAll(SaveArg
<5>(&video_buffering_state_cb_
),
1109 RunCallback
<2>(PIPELINE_OK
)));
1111 EXPECT_CALL(callbacks_
, OnMetadata(_
));
1113 // If we get here it's a successful initialization.
1114 EXPECT_CALL(*audio_renderer_
, GetTimeSource())
1115 .WillOnce(Return(&time_source_
));
1116 EXPECT_CALL(time_source_
, SetMediaTime(base::TimeDelta()));
1117 EXPECT_CALL(time_source_
, SetPlaybackRate(0.0f
));
1118 EXPECT_CALL(time_source_
, StartTicking());
1119 EXPECT_CALL(*audio_renderer_
, SetVolume(1.0f
));
1120 EXPECT_CALL(*audio_renderer_
, StartPlaying())
1121 .WillOnce(SetBufferingState(&audio_buffering_state_cb_
,
1122 BUFFERING_HAVE_ENOUGH
));
1123 EXPECT_CALL(*video_renderer_
, StartPlaying())
1124 .WillOnce(SetBufferingState(&video_buffering_state_cb_
,
1125 BUFFERING_HAVE_ENOUGH
));
1127 if (status
== PIPELINE_OK
)
1128 EXPECT_CALL(callbacks_
, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH
));
1133 void DoSeek(TeardownState state
, StopOrError stop_or_error
) {
1135 PipelineStatus status
= SetSeekExpectations(state
, stop_or_error
);
1137 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1138 EXPECT_CALL(callbacks_
, OnSeek(status
));
1140 if (status
== PIPELINE_OK
) {
1141 ExpectPipelineStopAndDestroyPipeline();
1144 pipeline_
->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1145 &CallbackHelper::OnSeek
, base::Unretained(&callbacks_
)));
1146 message_loop_
.RunUntilIdle();
1149 PipelineStatus
SetSeekExpectations(TeardownState state
,
1150 StopOrError stop_or_error
) {
1151 PipelineStatus status
= PIPELINE_OK
;
1152 base::Closure stop_cb
= base::Bind(
1153 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
));
1155 EXPECT_CALL(time_source_
, StopTicking());
1157 if (state
== kFlushing
) {
1158 if (stop_or_error
== kStop
) {
1159 EXPECT_CALL(*audio_renderer_
, Flush(_
))
1160 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1161 SetBufferingState(&audio_buffering_state_cb_
,
1162 BUFFERING_HAVE_NOTHING
),
1165 status
= PIPELINE_ERROR_READ
;
1166 EXPECT_CALL(*audio_renderer_
, Flush(_
)).WillOnce(
1167 DoAll(SetError(pipeline_
.get(), status
),
1168 SetBufferingState(&audio_buffering_state_cb_
,
1169 BUFFERING_HAVE_NOTHING
),
1176 EXPECT_CALL(*audio_renderer_
, Flush(_
))
1177 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_
,
1178 BUFFERING_HAVE_NOTHING
),
1180 EXPECT_CALL(*video_renderer_
, Flush(_
))
1181 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_
,
1182 BUFFERING_HAVE_NOTHING
),
1185 if (state
== kSeeking
) {
1186 if (stop_or_error
== kStop
) {
1187 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1188 .WillOnce(DoAll(Stop(pipeline_
.get(), stop_cb
),
1189 RunCallback
<1>(PIPELINE_OK
)));
1191 status
= PIPELINE_ERROR_READ
;
1192 EXPECT_CALL(*demuxer_
, Seek(_
, _
))
1193 .WillOnce(RunCallback
<1>(status
));
1199 NOTREACHED() << "State not supported: " << state
;
1203 void DoStopOrError(StopOrError stop_or_error
) {
1206 EXPECT_CALL(*demuxer_
, Stop(_
)).WillOnce(RunClosure
<0>());
1208 switch (stop_or_error
) {
1210 ExpectPipelineStopAndDestroyPipeline();
1211 pipeline_
->Stop(base::Bind(
1212 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1216 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1217 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1221 EXPECT_CALL(callbacks_
, OnError(PIPELINE_ERROR_READ
));
1222 ExpectPipelineStopAndDestroyPipeline();
1223 pipeline_
->SetErrorForTesting(PIPELINE_ERROR_READ
);
1224 pipeline_
->Stop(base::Bind(
1225 &CallbackHelper::OnStop
, base::Unretained(&callbacks_
)));
1229 message_loop_
.RunUntilIdle();
1232 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest
);
1235 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1236 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1237 RunTest(k##state, k##stop_or_error); \
1240 INSTANTIATE_TEARDOWN_TEST(Stop
, InitDemuxer
);
1241 INSTANTIATE_TEARDOWN_TEST(Stop
, InitAudioRenderer
);
1242 INSTANTIATE_TEARDOWN_TEST(Stop
, InitVideoRenderer
);
1243 INSTANTIATE_TEARDOWN_TEST(Stop
, Flushing
);
1244 INSTANTIATE_TEARDOWN_TEST(Stop
, Seeking
);
1245 INSTANTIATE_TEARDOWN_TEST(Stop
, Playing
);
1247 INSTANTIATE_TEARDOWN_TEST(Error
, InitDemuxer
);
1248 INSTANTIATE_TEARDOWN_TEST(Error
, InitAudioRenderer
);
1249 INSTANTIATE_TEARDOWN_TEST(Error
, InitVideoRenderer
);
1250 INSTANTIATE_TEARDOWN_TEST(Error
, Flushing
);
1251 INSTANTIATE_TEARDOWN_TEST(Error
, Seeking
);
1252 INSTANTIATE_TEARDOWN_TEST(Error
, Playing
);
1254 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop
, Playing
);
1256 } // namespace media