• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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