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