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.
4
5 #include <vector>
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/threading/simple_thread.h"
12 #include "base/time/clock.h"
13 #include "media/base/clock.h"
14 #include "media/base/fake_text_track_stream.h"
15 #include "media/base/gmock_callback_support.h"
16 #include "media/base/media_log.h"
17 #include "media/base/mock_filters.h"
18 #include "media/base/pipeline.h"
19 #include "media/base/test_helpers.h"
20 #include "media/base/text_renderer.h"
21 #include "media/base/text_track_config.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
24
25 using ::testing::_;
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;
39
40 namespace media {
41
ACTION_P(SetDemuxerProperties,duration)42 ACTION_P(SetDemuxerProperties, duration) {
43 arg0->SetDuration(duration);
44 }
45
ACTION_P2(Stop,pipeline,stop_cb)46 ACTION_P2(Stop, pipeline, stop_cb) {
47 pipeline->Stop(stop_cb);
48 }
49
ACTION_P2(SetError,pipeline,status)50 ACTION_P2(SetError, pipeline, status) {
51 pipeline->SetErrorForTesting(status);
52 }
53
54 // Used for setting expectations on pipeline callbacks. Using a StrictMock
55 // also lets us test for missing callbacks.
56 class CallbackHelper {
57 public:
CallbackHelper()58 CallbackHelper() {}
~CallbackHelper()59 virtual ~CallbackHelper() {}
60
61 MOCK_METHOD1(OnStart, void(PipelineStatus));
62 MOCK_METHOD1(OnSeek, void(PipelineStatus));
63 MOCK_METHOD0(OnStop, void());
64 MOCK_METHOD0(OnEnded, void());
65 MOCK_METHOD1(OnError, void(PipelineStatus));
66 MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
67 MOCK_METHOD0(OnPrerollCompleted, void());
68 MOCK_METHOD0(OnDurationChange, void());
69
70 private:
71 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
72 };
73
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 {
81 public:
PipelineTest()82 PipelineTest()
83 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
84 new MediaLog())),
85 filter_collection_(new FilterCollection()),
86 demuxer_(new MockDemuxer()) {
87 filter_collection_->SetDemuxer(demuxer_.get());
88
89 video_renderer_ = new MockVideoRenderer();
90 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
91 filter_collection_->SetVideoRenderer(video_renderer.Pass());
92
93 audio_renderer_ = new MockAudioRenderer();
94 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
95 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
96
97 text_renderer_ = new TextRenderer(
98 message_loop_.message_loop_proxy(),
99 base::Bind(&PipelineTest::OnAddTextTrack,
100 base::Unretained(this)));
101 scoped_ptr<TextRenderer> text_renderer(text_renderer_);
102 filter_collection_->SetTextRenderer(text_renderer.Pass());
103
104 // InitializeDemuxer() adds overriding expectations for expected non-NULL
105 // streams.
106 DemuxerStream* null_pointer = NULL;
107 EXPECT_CALL(*demuxer_, GetStream(_))
108 .WillRepeatedly(Return(null_pointer));
109
110 EXPECT_CALL(*demuxer_, GetStartTime())
111 .WillRepeatedly(Return(base::TimeDelta()));
112
113 EXPECT_CALL(*demuxer_, GetTimelineOffset())
114 .WillRepeatedly(Return(base::Time()));
115
116 EXPECT_CALL(*demuxer_, GetLiveness())
117 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
118 }
119
~PipelineTest()120 virtual ~PipelineTest() {
121 if (!pipeline_ || !pipeline_->IsRunning())
122 return;
123
124 ExpectStop();
125
126 // The mock demuxer doesn't stop the fake text track stream,
127 // so just stop it manually.
128 if (text_stream_) {
129 text_stream_->Stop();
130 message_loop_.RunUntilIdle();
131 }
132
133 // Expect a stop callback if we were started.
134 EXPECT_CALL(callbacks_, OnStop());
135 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
136 base::Unretained(&callbacks_)));
137 message_loop_.RunUntilIdle();
138 }
139
140 protected:
141 // Sets up expectations to allow the demuxer to initialize.
142 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
InitializeDemuxer(MockDemuxerStreamVector * streams,const base::TimeDelta & duration)143 void InitializeDemuxer(MockDemuxerStreamVector* streams,
144 const base::TimeDelta& duration) {
145 EXPECT_CALL(callbacks_, OnDurationChange());
146 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
147 .WillOnce(DoAll(SetDemuxerProperties(duration),
148 RunCallback<1>(PIPELINE_OK)));
149
150 // Configure the demuxer to return the streams.
151 for (size_t i = 0; i < streams->size(); ++i) {
152 DemuxerStream* stream = (*streams)[i];
153 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
154 .WillRepeatedly(Return(stream));
155 }
156 }
157
InitializeDemuxer(MockDemuxerStreamVector * streams)158 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
159 // Initialize with a default non-zero duration.
160 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
161 }
162
CreateStream(DemuxerStream::Type type)163 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
164 DemuxerStream::Type type) {
165 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
166 new StrictMock<MockDemuxerStream>(type));
167 return stream.Pass();
168 }
169
170 // Sets up expectations to allow the video renderer to initialize.
InitializeVideoRenderer(DemuxerStream * stream)171 void InitializeVideoRenderer(DemuxerStream* stream) {
172 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _))
173 .WillOnce(RunCallback<2>(PIPELINE_OK));
174 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
175
176 // Startup sequence.
177 EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _))
178 .WillOnce(RunCallback<1>(PIPELINE_OK));
179 EXPECT_CALL(*video_renderer_, Play(_))
180 .WillOnce(RunClosure<0>());
181 }
182
183 // Sets up expectations to allow the audio renderer to initialize.
InitializeAudioRenderer(DemuxerStream * stream)184 void InitializeAudioRenderer(DemuxerStream* stream) {
185 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _))
186 .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_),
187 RunCallback<1>(PIPELINE_OK)));
188 }
189
AddTextStream()190 void AddTextStream() {
191 EXPECT_CALL(*this, OnAddTextTrack(_,_))
192 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
193 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
194 TextTrackConfig(kTextSubtitles, "", "", ""));
195 }
196
197 // Sets up expectations on the callback and initializes the pipeline. Called
198 // after tests have set expectations any filters they wish to use.
InitializePipeline(PipelineStatus start_status)199 void InitializePipeline(PipelineStatus start_status) {
200 EXPECT_CALL(callbacks_, OnStart(start_status));
201
202 if (start_status == PIPELINE_OK) {
203 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
204
205 if (audio_stream_) {
206 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
207 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
208
209 // Startup sequence.
210 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
211 .WillOnce(RunCallback<1>(PIPELINE_OK));
212 EXPECT_CALL(*audio_renderer_, StartRendering());
213 }
214 EXPECT_CALL(callbacks_, OnPrerollCompleted());
215 }
216
217 pipeline_->Start(
218 filter_collection_.Pass(),
219 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
220 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
221 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
222 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
223 base::Bind(&CallbackHelper::OnPrerollCompleted,
224 base::Unretained(&callbacks_)),
225 base::Bind(&CallbackHelper::OnDurationChange,
226 base::Unretained(&callbacks_)));
227 message_loop_.RunUntilIdle();
228 }
229
CreateAudioStream()230 void CreateAudioStream() {
231 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
232 }
233
CreateVideoStream()234 void CreateVideoStream() {
235 video_stream_ = CreateStream(DemuxerStream::VIDEO);
236 video_stream_->set_video_decoder_config(video_decoder_config_);
237 }
238
CreateTextStream()239 void CreateTextStream() {
240 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
241 EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
242 text_stream_ = text_stream.Pass();
243 }
244
audio_stream()245 MockDemuxerStream* audio_stream() {
246 return audio_stream_.get();
247 }
248
video_stream()249 MockDemuxerStream* video_stream() {
250 return video_stream_.get();
251 }
252
text_stream()253 FakeTextTrackStream* text_stream() {
254 return text_stream_.get();
255 }
256
ExpectSeek(const base::TimeDelta & seek_time)257 void ExpectSeek(const base::TimeDelta& seek_time) {
258 // Every filter should receive a call to Seek().
259 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
260 .WillOnce(RunCallback<1>(PIPELINE_OK));
261
262 if (audio_stream_) {
263 EXPECT_CALL(*audio_renderer_, StopRendering());
264 EXPECT_CALL(*audio_renderer_, Flush(_))
265 .WillOnce(RunClosure<0>());
266 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
267 .WillOnce(RunCallback<1>(PIPELINE_OK));
268 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
269 EXPECT_CALL(*audio_renderer_, SetVolume(_));
270 EXPECT_CALL(*audio_renderer_, StartRendering());
271 }
272
273 if (video_stream_) {
274 EXPECT_CALL(*video_renderer_, Flush(_))
275 .WillOnce(RunClosure<0>());
276 EXPECT_CALL(*video_renderer_, Preroll(seek_time, _))
277 .WillOnce(RunCallback<1>(PIPELINE_OK));
278 EXPECT_CALL(*video_renderer_, SetPlaybackRate(_));
279 EXPECT_CALL(*video_renderer_, Play(_))
280 .WillOnce(RunClosure<0>());
281 }
282
283 EXPECT_CALL(callbacks_, OnPrerollCompleted());
284
285 // We expect a successful seek callback.
286 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
287 }
288
DoSeek(const base::TimeDelta & seek_time)289 void DoSeek(const base::TimeDelta& seek_time) {
290 pipeline_->Seek(seek_time,
291 base::Bind(&CallbackHelper::OnSeek,
292 base::Unretained(&callbacks_)));
293
294 // We expect the time to be updated only after the seek has completed.
295 EXPECT_NE(seek_time, pipeline_->GetMediaTime());
296 message_loop_.RunUntilIdle();
297 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
298 }
299
ExpectStop()300 void ExpectStop() {
301 if (demuxer_)
302 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
303
304 if (audio_stream_)
305 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
306
307 if (video_stream_)
308 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
309 }
310
311 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
312 const AddTextTrackDoneCB&));
313
DoOnAddTextTrack(const TextTrackConfig & config,const AddTextTrackDoneCB & done_cb)314 void DoOnAddTextTrack(const TextTrackConfig& config,
315 const AddTextTrackDoneCB& done_cb) {
316 scoped_ptr<TextTrack> text_track(new MockTextTrack);
317 done_cb.Run(text_track.Pass());
318 }
319
320 // Fixture members.
321 StrictMock<CallbackHelper> callbacks_;
322 base::SimpleTestTickClock test_tick_clock_;
323 base::MessageLoop message_loop_;
324 scoped_ptr<Pipeline> pipeline_;
325
326 scoped_ptr<FilterCollection> filter_collection_;
327 scoped_ptr<MockDemuxer> demuxer_;
328 MockVideoRenderer* video_renderer_;
329 MockAudioRenderer* audio_renderer_;
330 StrictMock<CallbackHelper> text_renderer_callbacks_;
331 TextRenderer* text_renderer_;
332 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
333 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
334 scoped_ptr<FakeTextTrackStream> text_stream_;
335 AudioRenderer::TimeCB audio_time_cb_;
336 VideoDecoderConfig video_decoder_config_;
337 PipelineMetadata metadata_;
338
339 private:
340 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
341 };
342
343 // Test that playback controls methods no-op when the pipeline hasn't been
344 // started.
TEST_F(PipelineTest,NotStarted)345 TEST_F(PipelineTest, NotStarted) {
346 const base::TimeDelta kZero;
347
348 EXPECT_FALSE(pipeline_->IsRunning());
349
350 // Setting should still work.
351 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
352 pipeline_->SetPlaybackRate(-1.0f);
353 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
354 pipeline_->SetPlaybackRate(1.0f);
355 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
356
357 // Setting should still work.
358 EXPECT_EQ(1.0f, pipeline_->GetVolume());
359 pipeline_->SetVolume(-1.0f);
360 EXPECT_EQ(1.0f, pipeline_->GetVolume());
361 pipeline_->SetVolume(0.0f);
362 EXPECT_EQ(0.0f, pipeline_->GetVolume());
363
364 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
365 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
366 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
367 }
368
TEST_F(PipelineTest,NeverInitializes)369 TEST_F(PipelineTest, NeverInitializes) {
370 // Don't execute the callback passed into Initialize().
371 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
372
373 // This test hangs during initialization by never calling
374 // InitializationComplete(). StrictMock<> will ensure that the callback is
375 // never executed.
376 pipeline_->Start(
377 filter_collection_.Pass(),
378 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
379 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
380 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
381 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
382 base::Bind(&CallbackHelper::OnPrerollCompleted,
383 base::Unretained(&callbacks_)),
384 base::Bind(&CallbackHelper::OnDurationChange,
385 base::Unretained(&callbacks_)));
386 message_loop_.RunUntilIdle();
387
388
389 // Because our callback will get executed when the test tears down, we'll
390 // verify that nothing has been called, then set our expectation for the call
391 // made during tear down.
392 Mock::VerifyAndClear(&callbacks_);
393 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
394 }
395
TEST_F(PipelineTest,URLNotFound)396 TEST_F(PipelineTest, URLNotFound) {
397 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
398 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
399 EXPECT_CALL(*demuxer_, Stop(_))
400 .WillOnce(RunClosure<0>());
401
402 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
403 }
404
TEST_F(PipelineTest,NoStreams)405 TEST_F(PipelineTest, NoStreams) {
406 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
407 .WillOnce(RunCallback<1>(PIPELINE_OK));
408 EXPECT_CALL(*demuxer_, Stop(_))
409 .WillOnce(RunClosure<0>());
410
411 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
412 }
413
TEST_F(PipelineTest,AudioStream)414 TEST_F(PipelineTest, AudioStream) {
415 CreateAudioStream();
416 MockDemuxerStreamVector streams;
417 streams.push_back(audio_stream());
418
419 InitializeDemuxer(&streams);
420 InitializeAudioRenderer(audio_stream());
421
422 InitializePipeline(PIPELINE_OK);
423 EXPECT_TRUE(metadata_.has_audio);
424 EXPECT_FALSE(metadata_.has_video);
425 }
426
TEST_F(PipelineTest,VideoStream)427 TEST_F(PipelineTest, VideoStream) {
428 CreateVideoStream();
429 MockDemuxerStreamVector streams;
430 streams.push_back(video_stream());
431
432 InitializeDemuxer(&streams);
433 InitializeVideoRenderer(video_stream());
434
435 InitializePipeline(PIPELINE_OK);
436 EXPECT_FALSE(metadata_.has_audio);
437 EXPECT_TRUE(metadata_.has_video);
438 }
439
TEST_F(PipelineTest,AudioVideoStream)440 TEST_F(PipelineTest, AudioVideoStream) {
441 CreateAudioStream();
442 CreateVideoStream();
443 MockDemuxerStreamVector streams;
444 streams.push_back(audio_stream());
445 streams.push_back(video_stream());
446
447 InitializeDemuxer(&streams);
448 InitializeAudioRenderer(audio_stream());
449 InitializeVideoRenderer(video_stream());
450
451 InitializePipeline(PIPELINE_OK);
452 EXPECT_TRUE(metadata_.has_audio);
453 EXPECT_TRUE(metadata_.has_video);
454 }
455
TEST_F(PipelineTest,VideoTextStream)456 TEST_F(PipelineTest, VideoTextStream) {
457 CreateVideoStream();
458 CreateTextStream();
459 MockDemuxerStreamVector streams;
460 streams.push_back(video_stream());
461
462 InitializeDemuxer(&streams);
463 InitializeVideoRenderer(video_stream());
464
465 InitializePipeline(PIPELINE_OK);
466 EXPECT_FALSE(metadata_.has_audio);
467 EXPECT_TRUE(metadata_.has_video);
468
469 AddTextStream();
470 message_loop_.RunUntilIdle();
471 }
472
TEST_F(PipelineTest,VideoAudioTextStream)473 TEST_F(PipelineTest, VideoAudioTextStream) {
474 CreateVideoStream();
475 CreateAudioStream();
476 CreateTextStream();
477 MockDemuxerStreamVector streams;
478 streams.push_back(video_stream());
479 streams.push_back(audio_stream());
480
481 InitializeDemuxer(&streams);
482 InitializeVideoRenderer(video_stream());
483 InitializeAudioRenderer(audio_stream());
484
485 InitializePipeline(PIPELINE_OK);
486 EXPECT_TRUE(metadata_.has_audio);
487 EXPECT_TRUE(metadata_.has_video);
488
489 AddTextStream();
490 message_loop_.RunUntilIdle();
491 }
492
TEST_F(PipelineTest,Seek)493 TEST_F(PipelineTest, Seek) {
494 CreateAudioStream();
495 CreateVideoStream();
496 CreateTextStream();
497 MockDemuxerStreamVector streams;
498 streams.push_back(audio_stream());
499 streams.push_back(video_stream());
500
501 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
502 InitializeAudioRenderer(audio_stream());
503 InitializeVideoRenderer(video_stream());
504
505 // Initialize then seek!
506 InitializePipeline(PIPELINE_OK);
507
508 AddTextStream();
509 message_loop_.RunUntilIdle();
510
511 // Every filter should receive a call to Seek().
512 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
513 ExpectSeek(expected);
514 DoSeek(expected);
515 }
516
TEST_F(PipelineTest,SetVolume)517 TEST_F(PipelineTest, SetVolume) {
518 CreateAudioStream();
519 MockDemuxerStreamVector streams;
520 streams.push_back(audio_stream());
521
522 InitializeDemuxer(&streams);
523 InitializeAudioRenderer(audio_stream());
524
525 // The audio renderer should receive a call to SetVolume().
526 float expected = 0.5f;
527 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
528
529 // Initialize then set volume!
530 InitializePipeline(PIPELINE_OK);
531 pipeline_->SetVolume(expected);
532 }
533
TEST_F(PipelineTest,Properties)534 TEST_F(PipelineTest, Properties) {
535 CreateVideoStream();
536 MockDemuxerStreamVector streams;
537 streams.push_back(video_stream());
538
539 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
540 InitializeDemuxer(&streams, kDuration);
541 InitializeVideoRenderer(video_stream());
542
543 InitializePipeline(PIPELINE_OK);
544 EXPECT_EQ(kDuration.ToInternalValue(),
545 pipeline_->GetMediaDuration().ToInternalValue());
546 EXPECT_FALSE(pipeline_->DidLoadingProgress());
547 }
548
TEST_F(PipelineTest,GetBufferedTimeRanges)549 TEST_F(PipelineTest, GetBufferedTimeRanges) {
550 CreateVideoStream();
551 MockDemuxerStreamVector streams;
552 streams.push_back(video_stream());
553
554 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
555 InitializeDemuxer(&streams, kDuration);
556 InitializeVideoRenderer(video_stream());
557
558 InitializePipeline(PIPELINE_OK);
559
560 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
561
562 EXPECT_FALSE(pipeline_->DidLoadingProgress());
563 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
564 EXPECT_TRUE(pipeline_->DidLoadingProgress());
565 EXPECT_FALSE(pipeline_->DidLoadingProgress());
566 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
567 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
568 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
569
570 base::TimeDelta kSeekTime = kDuration / 2;
571 ExpectSeek(kSeekTime);
572 DoSeek(kSeekTime);
573
574 EXPECT_FALSE(pipeline_->DidLoadingProgress());
575 }
576
TEST_F(PipelineTest,EndedCallback)577 TEST_F(PipelineTest, EndedCallback) {
578 CreateAudioStream();
579 CreateVideoStream();
580 CreateTextStream();
581 MockDemuxerStreamVector streams;
582 streams.push_back(audio_stream());
583 streams.push_back(video_stream());
584
585 InitializeDemuxer(&streams);
586 InitializeAudioRenderer(audio_stream());
587 InitializeVideoRenderer(video_stream());
588 InitializePipeline(PIPELINE_OK);
589
590 AddTextStream();
591
592 // The ended callback shouldn't run until all renderers have ended.
593 pipeline_->OnAudioRendererEnded();
594 message_loop_.RunUntilIdle();
595
596 pipeline_->OnVideoRendererEnded();
597 message_loop_.RunUntilIdle();
598
599 EXPECT_CALL(*audio_renderer_, StopRendering());
600 EXPECT_CALL(callbacks_, OnEnded());
601 text_stream()->SendEosNotification();
602 message_loop_.RunUntilIdle();
603 }
604
TEST_F(PipelineTest,AudioStreamShorterThanVideo)605 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
606 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
607
608 CreateAudioStream();
609 CreateVideoStream();
610 MockDemuxerStreamVector streams;
611 streams.push_back(audio_stream());
612 streams.push_back(video_stream());
613
614 // Replace the clock so we can simulate wall clock time advancing w/o using
615 // Sleep().
616 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
617
618 InitializeDemuxer(&streams, duration);
619 InitializeAudioRenderer(audio_stream());
620 InitializeVideoRenderer(video_stream());
621 InitializePipeline(PIPELINE_OK);
622
623 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
624
625 float playback_rate = 1.0f;
626 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
627 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
628 pipeline_->SetPlaybackRate(playback_rate);
629 message_loop_.RunUntilIdle();
630
631 InSequence s;
632
633 // Verify that the clock doesn't advance since it hasn't been started by
634 // a time update from the audio stream.
635 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
636 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
637 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
638
639 // Signal end of audio stream.
640 pipeline_->OnAudioRendererEnded();
641 message_loop_.RunUntilIdle();
642
643 // Verify that the clock advances.
644 start_time = pipeline_->GetMediaTime().ToInternalValue();
645 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
646 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
647
648 // Signal end of video stream and make sure OnEnded() callback occurs.
649 EXPECT_CALL(*audio_renderer_, StopRendering());
650 EXPECT_CALL(callbacks_, OnEnded());
651 pipeline_->OnVideoRendererEnded();
652 }
653
TEST_F(PipelineTest,ErrorDuringSeek)654 TEST_F(PipelineTest, ErrorDuringSeek) {
655 CreateAudioStream();
656 MockDemuxerStreamVector streams;
657 streams.push_back(audio_stream());
658
659 InitializeDemuxer(&streams);
660 InitializeAudioRenderer(audio_stream());
661 InitializePipeline(PIPELINE_OK);
662
663 float playback_rate = 1.0f;
664 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
665 pipeline_->SetPlaybackRate(playback_rate);
666 message_loop_.RunUntilIdle();
667
668 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
669
670 // Preroll() isn't called as the demuxer errors out first.
671 EXPECT_CALL(*audio_renderer_, StopRendering());
672 EXPECT_CALL(*audio_renderer_, Flush(_))
673 .WillOnce(RunClosure<0>());
674 EXPECT_CALL(*audio_renderer_, Stop(_))
675 .WillOnce(RunClosure<0>());
676
677 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
678 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
679 EXPECT_CALL(*demuxer_, Stop(_))
680 .WillOnce(RunClosure<0>());
681
682 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
683 base::Unretained(&callbacks_)));
684 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
685 message_loop_.RunUntilIdle();
686 }
687
688 // Invoked function OnError. This asserts that the pipeline does not enqueue
689 // non-teardown related tasks while tearing down.
TestNoCallsAfterError(Pipeline * pipeline,base::MessageLoop * message_loop,PipelineStatus)690 static void TestNoCallsAfterError(
691 Pipeline* pipeline, base::MessageLoop* message_loop,
692 PipelineStatus /* status */) {
693 CHECK(pipeline);
694 CHECK(message_loop);
695
696 // When we get to this stage, the message loop should be empty.
697 EXPECT_TRUE(message_loop->IsIdleForTesting());
698
699 // Make calls on pipeline after error has occurred.
700 pipeline->SetPlaybackRate(0.5f);
701 pipeline->SetVolume(0.5f);
702
703 // No additional tasks should be queued as a result of these calls.
704 EXPECT_TRUE(message_loop->IsIdleForTesting());
705 }
706
TEST_F(PipelineTest,NoMessageDuringTearDownFromError)707 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
708 CreateAudioStream();
709 MockDemuxerStreamVector streams;
710 streams.push_back(audio_stream());
711
712 InitializeDemuxer(&streams);
713 InitializeAudioRenderer(audio_stream());
714 InitializePipeline(PIPELINE_OK);
715
716 // Trigger additional requests on the pipeline during tear down from error.
717 base::Callback<void(PipelineStatus)> cb = base::Bind(
718 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
719 ON_CALL(callbacks_, OnError(_))
720 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
721
722 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
723
724 // Seek() isn't called as the demuxer errors out first.
725 EXPECT_CALL(*audio_renderer_, StopRendering());
726 EXPECT_CALL(*audio_renderer_, Flush(_))
727 .WillOnce(RunClosure<0>());
728 EXPECT_CALL(*audio_renderer_, Stop(_))
729 .WillOnce(RunClosure<0>());
730
731 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
732 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
733 EXPECT_CALL(*demuxer_, Stop(_))
734 .WillOnce(RunClosure<0>());
735
736 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
737 base::Unretained(&callbacks_)));
738 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
739 message_loop_.RunUntilIdle();
740 }
741
TEST_F(PipelineTest,StartTimeIsZero)742 TEST_F(PipelineTest, StartTimeIsZero) {
743 CreateVideoStream();
744 MockDemuxerStreamVector streams;
745 streams.push_back(video_stream());
746
747 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
748 InitializeDemuxer(&streams, kDuration);
749 InitializeVideoRenderer(video_stream());
750
751 InitializePipeline(PIPELINE_OK);
752 EXPECT_FALSE(metadata_.has_audio);
753 EXPECT_TRUE(metadata_.has_video);
754
755 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
756 }
757
TEST_F(PipelineTest,StartTimeIsNonZero)758 TEST_F(PipelineTest, StartTimeIsNonZero) {
759 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
760 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
761
762 EXPECT_CALL(*demuxer_, GetStartTime())
763 .WillRepeatedly(Return(kStartTime));
764
765 CreateVideoStream();
766 MockDemuxerStreamVector streams;
767 streams.push_back(video_stream());
768
769 InitializeDemuxer(&streams, kDuration);
770 InitializeVideoRenderer(video_stream());
771
772 InitializePipeline(PIPELINE_OK);
773 EXPECT_FALSE(metadata_.has_audio);
774 EXPECT_TRUE(metadata_.has_video);
775
776 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
777 }
778
RunTimeCB(const AudioRenderer::TimeCB & time_cb,int time_in_ms,int max_time_in_ms)779 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
780 int time_in_ms,
781 int max_time_in_ms) {
782 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
783 base::TimeDelta::FromMilliseconds(max_time_in_ms));
784 }
785
TEST_F(PipelineTest,AudioTimeUpdateDuringSeek)786 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
787 CreateAudioStream();
788 MockDemuxerStreamVector streams;
789 streams.push_back(audio_stream());
790
791 InitializeDemuxer(&streams);
792 InitializeAudioRenderer(audio_stream());
793 InitializePipeline(PIPELINE_OK);
794
795 float playback_rate = 1.0f;
796 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
797 pipeline_->SetPlaybackRate(playback_rate);
798 message_loop_.RunUntilIdle();
799
800 // Provide an initial time update so that the pipeline transitions out of the
801 // "waiting for time update" state.
802 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
803 base::TimeDelta::FromMilliseconds(500));
804
805 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
806
807 // Arrange to trigger a time update while the demuxer is in the middle of
808 // seeking. This update should be ignored by the pipeline and the clock should
809 // not get updated.
810 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
811 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
812 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
813 RunCallback<1>(PIPELINE_OK)));
814
815 EXPECT_CALL(*audio_renderer_, StopRendering());
816 EXPECT_CALL(*audio_renderer_, Flush(_))
817 .WillOnce(RunClosure<0>());
818 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
819 .WillOnce(RunCallback<1>(PIPELINE_OK));
820 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
821 EXPECT_CALL(*audio_renderer_, SetVolume(_));
822 EXPECT_CALL(*audio_renderer_, StartRendering());
823
824 EXPECT_CALL(callbacks_, OnPrerollCompleted());
825 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
826 DoSeek(seek_time);
827
828 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
829
830 // Now that the seek is complete, verify that time updates advance the current
831 // time.
832 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
833 audio_time_cb_.Run(new_time, new_time);
834
835 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
836 }
837
DeletePipeline(scoped_ptr<Pipeline> pipeline)838 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
839 // |pipeline| will go out of scope.
840 }
841
TEST_F(PipelineTest,DeleteAfterStop)842 TEST_F(PipelineTest, DeleteAfterStop) {
843 CreateAudioStream();
844 MockDemuxerStreamVector streams;
845 streams.push_back(audio_stream());
846 InitializeDemuxer(&streams);
847 InitializeAudioRenderer(audio_stream());
848 InitializePipeline(PIPELINE_OK);
849
850 ExpectStop();
851
852 Pipeline* pipeline = pipeline_.get();
853 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
854 message_loop_.RunUntilIdle();
855 }
856
857 class PipelineTeardownTest : public PipelineTest {
858 public:
859 enum TeardownState {
860 kInitDemuxer,
861 kInitAudioRenderer,
862 kInitVideoRenderer,
863 kFlushing,
864 kSeeking,
865 kPrerolling,
866 kPlaying,
867 };
868
869 enum StopOrError {
870 kStop,
871 kError,
872 kErrorAndStop,
873 };
874
PipelineTeardownTest()875 PipelineTeardownTest() {}
~PipelineTeardownTest()876 virtual ~PipelineTeardownTest() {}
877
RunTest(TeardownState state,StopOrError stop_or_error)878 void RunTest(TeardownState state, StopOrError stop_or_error) {
879 switch (state) {
880 case kInitDemuxer:
881 case kInitAudioRenderer:
882 case kInitVideoRenderer:
883 DoInitialize(state, stop_or_error);
884 break;
885
886 case kFlushing:
887 case kSeeking:
888 case kPrerolling:
889 DoInitialize(state, stop_or_error);
890 DoSeek(state, stop_or_error);
891 break;
892
893 case kPlaying:
894 DoInitialize(state, stop_or_error);
895 DoStopOrError(stop_or_error);
896 break;
897 }
898 }
899
900 private:
901 // TODO(scherkus): We do radically different things whether teardown is
902 // invoked via stop vs error. The teardown path should be the same,
903 // see http://crbug.com/110228
DoInitialize(TeardownState state,StopOrError stop_or_error)904 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
905 PipelineStatus expected_status =
906 SetInitializeExpectations(state, stop_or_error);
907
908 EXPECT_CALL(callbacks_, OnStart(expected_status));
909 pipeline_->Start(
910 filter_collection_.Pass(),
911 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
912 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
913 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
914 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
915 base::Bind(&CallbackHelper::OnPrerollCompleted,
916 base::Unretained(&callbacks_)),
917 base::Bind(&CallbackHelper::OnDurationChange,
918 base::Unretained(&callbacks_)));
919 message_loop_.RunUntilIdle();
920 }
921
SetInitializeExpectations(TeardownState state,StopOrError stop_or_error)922 PipelineStatus SetInitializeExpectations(TeardownState state,
923 StopOrError stop_or_error) {
924 PipelineStatus status = PIPELINE_OK;
925 base::Closure stop_cb = base::Bind(
926 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
927
928 if (state == kInitDemuxer) {
929 if (stop_or_error == kStop) {
930 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
931 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
932 RunCallback<1>(PIPELINE_OK)));
933 EXPECT_CALL(callbacks_, OnStop());
934 } else {
935 status = DEMUXER_ERROR_COULD_NOT_OPEN;
936 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
937 .WillOnce(RunCallback<1>(status));
938 }
939
940 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
941 return status;
942 }
943
944 CreateAudioStream();
945 CreateVideoStream();
946 MockDemuxerStreamVector streams;
947 streams.push_back(audio_stream());
948 streams.push_back(video_stream());
949 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
950
951 if (state == kInitAudioRenderer) {
952 if (stop_or_error == kStop) {
953 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
954 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
955 RunCallback<1>(PIPELINE_OK)));
956 EXPECT_CALL(callbacks_, OnStop());
957 } else {
958 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
959 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
960 .WillOnce(RunCallback<1>(status));
961 }
962
963 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
964 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
965 return status;
966 }
967
968 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
969 .WillOnce(RunCallback<1>(PIPELINE_OK));
970
971 if (state == kInitVideoRenderer) {
972 if (stop_or_error == kStop) {
973 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
974 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
975 RunCallback<2>(PIPELINE_OK)));
976 EXPECT_CALL(callbacks_, OnStop());
977 } else {
978 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
979 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
980 .WillOnce(RunCallback<2>(status));
981 }
982
983 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
984 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
985 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
986 return status;
987 }
988
989 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
990 .WillOnce(RunCallback<2>(PIPELINE_OK));
991
992 EXPECT_CALL(callbacks_, OnMetadata(_));
993
994 // If we get here it's a successful initialization.
995 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
996 .WillOnce(RunCallback<1>(PIPELINE_OK));
997 EXPECT_CALL(*video_renderer_, Preroll(base::TimeDelta(), _))
998 .WillOnce(RunCallback<1>(PIPELINE_OK));
999
1000 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1001 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1002 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1003
1004 EXPECT_CALL(*audio_renderer_, StartRendering());
1005 EXPECT_CALL(*video_renderer_, Play(_))
1006 .WillOnce(RunClosure<0>());
1007
1008 if (status == PIPELINE_OK)
1009 EXPECT_CALL(callbacks_, OnPrerollCompleted());
1010
1011 return status;
1012 }
1013
DoSeek(TeardownState state,StopOrError stop_or_error)1014 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1015 InSequence s;
1016 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1017
1018 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1019 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1020 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1021 EXPECT_CALL(callbacks_, OnSeek(status));
1022
1023 if (status == PIPELINE_OK) {
1024 EXPECT_CALL(callbacks_, OnStop());
1025 }
1026
1027 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1028 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1029 message_loop_.RunUntilIdle();
1030 }
1031
SetSeekExpectations(TeardownState state,StopOrError stop_or_error)1032 PipelineStatus SetSeekExpectations(TeardownState state,
1033 StopOrError stop_or_error) {
1034 PipelineStatus status = PIPELINE_OK;
1035 base::Closure stop_cb = base::Bind(
1036 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1037
1038 EXPECT_CALL(*audio_renderer_, StopRendering());
1039
1040 if (state == kFlushing) {
1041 if (stop_or_error == kStop) {
1042 EXPECT_CALL(*audio_renderer_, Flush(_))
1043 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1044 } else {
1045 status = PIPELINE_ERROR_READ;
1046 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1047 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1048 }
1049
1050 return status;
1051 }
1052
1053 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1054 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1055
1056 if (state == kSeeking) {
1057 if (stop_or_error == kStop) {
1058 EXPECT_CALL(*demuxer_, Seek(_, _))
1059 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1060 RunCallback<1>(PIPELINE_OK)));
1061 } else {
1062 status = PIPELINE_ERROR_READ;
1063 EXPECT_CALL(*demuxer_, Seek(_, _))
1064 .WillOnce(RunCallback<1>(status));
1065 }
1066
1067 return status;
1068 }
1069
1070 EXPECT_CALL(*demuxer_, Seek(_, _))
1071 .WillOnce(RunCallback<1>(PIPELINE_OK));
1072
1073 if (state == kPrerolling) {
1074 if (stop_or_error == kStop) {
1075 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1076 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1077 RunCallback<1>(PIPELINE_OK)));
1078 } else {
1079 status = PIPELINE_ERROR_READ;
1080 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1081 .WillOnce(RunCallback<1>(status));
1082 }
1083
1084 return status;
1085 }
1086
1087 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1088 .WillOnce(RunCallback<1>(PIPELINE_OK));
1089 EXPECT_CALL(*video_renderer_, Preroll(_, _))
1090 .WillOnce(RunCallback<1>(PIPELINE_OK));
1091
1092 // Playback rate and volume are updated prior to starting.
1093 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1094 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1095 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1096
1097 NOTREACHED() << "State not supported: " << state;
1098 return status;
1099 }
1100
DoStopOrError(StopOrError stop_or_error)1101 void DoStopOrError(StopOrError stop_or_error) {
1102 InSequence s;
1103
1104 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1105 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1106 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1107
1108 switch (stop_or_error) {
1109 case kStop:
1110 EXPECT_CALL(callbacks_, OnStop());
1111 pipeline_->Stop(base::Bind(
1112 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1113 break;
1114
1115 case kError:
1116 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1117 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1118 break;
1119
1120 case kErrorAndStop:
1121 EXPECT_CALL(callbacks_, OnStop());
1122 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1123 pipeline_->Stop(base::Bind(
1124 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1125 break;
1126 }
1127
1128 message_loop_.RunUntilIdle();
1129 }
1130
1131 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1132 };
1133
1134 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1135 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1136 RunTest(k##state, k##stop_or_error); \
1137 }
1138
1139 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1140 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1141 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1142 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1143 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1144 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1145 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1146
1147 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1148 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1149 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1150 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1151 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1152 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1153 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1154
1155 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1156
1157 } // namespace media
1158