Ignore title parameter for navigator.registerProtocolHandler
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
blob2c559c10819233a2eef519387a3b2950001f3f6e
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.
5 #include <vector>
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"
25 using ::testing::_;
26 using ::testing::DeleteArg;
27 using ::testing::DoAll;
28 // TODO(scherkus): Remove InSequence after refactoring Pipeline.
29 using ::testing::InSequence;
30 using ::testing::Invoke;
31 using ::testing::InvokeWithoutArgs;
32 using ::testing::Mock;
33 using ::testing::NotNull;
34 using ::testing::Return;
35 using ::testing::SaveArg;
36 using ::testing::StrictMock;
37 using ::testing::WithArg;
39 namespace media {
41 ACTION_P(SetDemuxerProperties, duration) {
42 arg0->SetDuration(duration);
45 ACTION_P2(Stop, pipeline, stop_cb) {
46 pipeline->Stop(stop_cb);
49 ACTION_P2(SetError, pipeline, status) {
50 pipeline->SetErrorForTesting(status);
53 // Used for setting expectations on pipeline callbacks. Using a StrictMock
54 // also lets us test for missing callbacks.
55 class CallbackHelper {
56 public:
57 CallbackHelper() {}
58 virtual ~CallbackHelper() {}
60 MOCK_METHOD1(OnStart, void(PipelineStatus));
61 MOCK_METHOD1(OnSeek, void(PipelineStatus));
62 MOCK_METHOD0(OnStop, void());
63 MOCK_METHOD0(OnEnded, void());
64 MOCK_METHOD1(OnError, void(PipelineStatus));
65 MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
66 MOCK_METHOD0(OnPrerollCompleted, void());
67 MOCK_METHOD0(OnDurationChange, void());
69 private:
70 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
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.
79 class 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());
88 video_renderer_ = new MockVideoRenderer();
89 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
90 filter_collection_->SetVideoRenderer(video_renderer.Pass());
92 audio_renderer_ = new MockAudioRenderer();
93 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
94 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
96 text_renderer_ = new TextRenderer(
97 message_loop_.message_loop_proxy(),
98 base::Bind(&PipelineTest::OnAddTextTrack,
99 base::Unretained(this)));
100 scoped_ptr<TextRenderer> text_renderer(text_renderer_);
101 filter_collection_->SetTextRenderer(text_renderer.Pass());
103 // InitializeDemuxer() adds overriding expectations for expected non-NULL
104 // streams.
105 DemuxerStream* null_pointer = NULL;
106 EXPECT_CALL(*demuxer_, GetStream(_))
107 .WillRepeatedly(Return(null_pointer));
109 EXPECT_CALL(*demuxer_, GetStartTime())
110 .WillRepeatedly(Return(base::TimeDelta()));
112 EXPECT_CALL(*demuxer_, GetTimelineOffset())
113 .WillRepeatedly(Return(base::Time()));
115 EXPECT_CALL(*demuxer_, GetLiveness())
116 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
119 virtual ~PipelineTest() {
120 if (!pipeline_ || !pipeline_->IsRunning())
121 return;
123 ExpectStop();
125 // The mock demuxer doesn't stop the fake text track stream,
126 // so just stop it manually.
127 if (text_stream_) {
128 text_stream_->Stop();
129 message_loop_.RunUntilIdle();
132 // Expect a stop callback if we were started.
133 EXPECT_CALL(callbacks_, OnStop());
134 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
135 base::Unretained(&callbacks_)));
136 message_loop_.RunUntilIdle();
139 protected:
140 // Sets up expectations to allow the demuxer to initialize.
141 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
142 void InitializeDemuxer(MockDemuxerStreamVector* streams,
143 const base::TimeDelta& duration) {
144 EXPECT_CALL(callbacks_, OnDurationChange());
145 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
146 .WillOnce(DoAll(SetDemuxerProperties(duration),
147 RunCallback<1>(PIPELINE_OK)));
149 // Configure the demuxer to return the streams.
150 for (size_t i = 0; i < streams->size(); ++i) {
151 DemuxerStream* stream = (*streams)[i];
152 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
153 .WillRepeatedly(Return(stream));
157 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
158 // Initialize with a default non-zero duration.
159 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10));
162 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
163 DemuxerStream::Type type) {
164 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
165 new StrictMock<MockDemuxerStream>(type));
166 return stream.Pass();
169 // Sets up expectations to allow the video renderer to initialize.
170 void InitializeVideoRenderer(DemuxerStream* stream) {
171 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _))
172 .WillOnce(RunCallback<2>(PIPELINE_OK));
173 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
175 // Startup sequence.
176 EXPECT_CALL(*video_renderer_, Preroll(demuxer_->GetStartTime(), _))
177 .WillOnce(RunCallback<1>(PIPELINE_OK));
178 EXPECT_CALL(*video_renderer_, Play(_))
179 .WillOnce(RunClosure<0>());
182 // Sets up expectations to allow the audio renderer to initialize.
183 void InitializeAudioRenderer(DemuxerStream* stream) {
184 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _))
185 .WillOnce(DoAll(SaveArg<4>(&audio_time_cb_),
186 RunCallback<1>(PIPELINE_OK)));
189 void AddTextStream() {
190 EXPECT_CALL(*this, OnAddTextTrack(_,_))
191 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
192 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
193 TextTrackConfig(kTextSubtitles, "", "", ""));
196 // Sets up expectations on the callback and initializes the pipeline. Called
197 // after tests have set expectations any filters they wish to use.
198 void InitializePipeline(PipelineStatus start_status) {
199 EXPECT_CALL(callbacks_, OnStart(start_status));
201 if (start_status == PIPELINE_OK) {
202 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
204 if (audio_stream_) {
205 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
206 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
208 // Startup sequence.
209 EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
210 .WillOnce(RunCallback<1>(PIPELINE_OK));
211 EXPECT_CALL(*audio_renderer_, Play());
213 EXPECT_CALL(callbacks_, OnPrerollCompleted());
216 pipeline_->Start(
217 filter_collection_.Pass(),
218 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
219 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
220 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
221 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
222 base::Bind(&CallbackHelper::OnPrerollCompleted,
223 base::Unretained(&callbacks_)),
224 base::Bind(&CallbackHelper::OnDurationChange,
225 base::Unretained(&callbacks_)));
226 message_loop_.RunUntilIdle();
229 void CreateAudioStream() {
230 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
233 void CreateVideoStream() {
234 video_stream_ = CreateStream(DemuxerStream::VIDEO);
235 video_stream_->set_video_decoder_config(video_decoder_config_);
238 void CreateTextStream() {
239 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream);
240 text_stream_ = text_stream.Pass();
243 MockDemuxerStream* audio_stream() {
244 return audio_stream_.get();
247 MockDemuxerStream* video_stream() {
248 return video_stream_.get();
251 FakeTextTrackStream* text_stream() {
252 return text_stream_.get();
255 void ExpectSeek(const base::TimeDelta& seek_time) {
256 // Every filter should receive a call to Seek().
257 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
258 .WillOnce(RunCallback<1>(PIPELINE_OK));
260 if (audio_stream_) {
261 EXPECT_CALL(*audio_renderer_, Pause());
262 EXPECT_CALL(*audio_renderer_, Flush(_))
263 .WillOnce(RunClosure<0>());
264 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
265 .WillOnce(RunCallback<1>(PIPELINE_OK));
266 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
267 EXPECT_CALL(*audio_renderer_, SetVolume(_));
268 EXPECT_CALL(*audio_renderer_, Play());
271 if (video_stream_) {
272 EXPECT_CALL(*video_renderer_, Pause(_))
273 .WillOnce(RunClosure<0>());
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>());
283 EXPECT_CALL(callbacks_, OnPrerollCompleted());
285 // We expect a successful seek callback.
286 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
289 void DoSeek(const base::TimeDelta& seek_time) {
290 pipeline_->Seek(seek_time,
291 base::Bind(&CallbackHelper::OnSeek,
292 base::Unretained(&callbacks_)));
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());
300 void ExpectStop() {
301 if (demuxer_)
302 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
304 if (audio_stream_)
305 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
307 if (video_stream_)
308 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
311 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
312 const AddTextTrackDoneCB&));
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());
320 // Fixture members.
321 StrictMock<CallbackHelper> callbacks_;
322 base::SimpleTestTickClock test_tick_clock_;
323 base::MessageLoop message_loop_;
324 scoped_ptr<Pipeline> pipeline_;
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_;
339 private:
340 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
343 // Test that playback controls methods no-op when the pipeline hasn't been
344 // started.
345 TEST_F(PipelineTest, NotStarted) {
346 const base::TimeDelta kZero;
348 EXPECT_FALSE(pipeline_->IsRunning());
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());
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());
364 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
365 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
366 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
369 TEST_F(PipelineTest, NeverInitializes) {
370 // Don't execute the callback passed into Initialize().
371 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
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();
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));
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>());
402 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND);
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>());
411 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
414 TEST_F(PipelineTest, AudioStream) {
415 CreateAudioStream();
416 MockDemuxerStreamVector streams;
417 streams.push_back(audio_stream());
419 InitializeDemuxer(&streams);
420 InitializeAudioRenderer(audio_stream());
422 InitializePipeline(PIPELINE_OK);
423 EXPECT_TRUE(metadata_.has_audio);
424 EXPECT_FALSE(metadata_.has_video);
427 TEST_F(PipelineTest, VideoStream) {
428 CreateVideoStream();
429 MockDemuxerStreamVector streams;
430 streams.push_back(video_stream());
432 InitializeDemuxer(&streams);
433 InitializeVideoRenderer(video_stream());
435 InitializePipeline(PIPELINE_OK);
436 EXPECT_FALSE(metadata_.has_audio);
437 EXPECT_TRUE(metadata_.has_video);
440 TEST_F(PipelineTest, AudioVideoStream) {
441 CreateAudioStream();
442 CreateVideoStream();
443 MockDemuxerStreamVector streams;
444 streams.push_back(audio_stream());
445 streams.push_back(video_stream());
447 InitializeDemuxer(&streams);
448 InitializeAudioRenderer(audio_stream());
449 InitializeVideoRenderer(video_stream());
451 InitializePipeline(PIPELINE_OK);
452 EXPECT_TRUE(metadata_.has_audio);
453 EXPECT_TRUE(metadata_.has_video);
456 TEST_F(PipelineTest, VideoTextStream) {
457 CreateVideoStream();
458 CreateTextStream();
459 MockDemuxerStreamVector streams;
460 streams.push_back(video_stream());
462 InitializeDemuxer(&streams);
463 InitializeVideoRenderer(video_stream());
465 InitializePipeline(PIPELINE_OK);
466 EXPECT_FALSE(metadata_.has_audio);
467 EXPECT_TRUE(metadata_.has_video);
469 AddTextStream();
470 message_loop_.RunUntilIdle();
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());
481 InitializeDemuxer(&streams);
482 InitializeVideoRenderer(video_stream());
483 InitializeAudioRenderer(audio_stream());
485 InitializePipeline(PIPELINE_OK);
486 EXPECT_TRUE(metadata_.has_audio);
487 EXPECT_TRUE(metadata_.has_video);
489 AddTextStream();
490 message_loop_.RunUntilIdle();
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());
501 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000));
502 InitializeAudioRenderer(audio_stream());
503 InitializeVideoRenderer(video_stream());
505 // Initialize then seek!
506 InitializePipeline(PIPELINE_OK);
508 AddTextStream();
509 message_loop_.RunUntilIdle();
511 // Every filter should receive a call to Seek().
512 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
513 ExpectSeek(expected);
514 DoSeek(expected);
517 TEST_F(PipelineTest, SetVolume) {
518 CreateAudioStream();
519 MockDemuxerStreamVector streams;
520 streams.push_back(audio_stream());
522 InitializeDemuxer(&streams);
523 InitializeAudioRenderer(audio_stream());
525 // The audio renderer should receive a call to SetVolume().
526 float expected = 0.5f;
527 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
529 // Initialize then set volume!
530 InitializePipeline(PIPELINE_OK);
531 pipeline_->SetVolume(expected);
534 TEST_F(PipelineTest, Properties) {
535 CreateVideoStream();
536 MockDemuxerStreamVector streams;
537 streams.push_back(video_stream());
539 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
540 InitializeDemuxer(&streams, kDuration);
541 InitializeVideoRenderer(video_stream());
543 InitializePipeline(PIPELINE_OK);
544 EXPECT_EQ(kDuration.ToInternalValue(),
545 pipeline_->GetMediaDuration().ToInternalValue());
546 EXPECT_FALSE(pipeline_->DidLoadingProgress());
549 TEST_F(PipelineTest, GetBufferedTimeRanges) {
550 CreateVideoStream();
551 MockDemuxerStreamVector streams;
552 streams.push_back(video_stream());
554 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
555 InitializeDemuxer(&streams, kDuration);
556 InitializeVideoRenderer(video_stream());
558 InitializePipeline(PIPELINE_OK);
560 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
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));
570 base::TimeDelta kSeekTime = kDuration / 2;
571 ExpectSeek(kSeekTime);
572 DoSeek(kSeekTime);
574 EXPECT_FALSE(pipeline_->DidLoadingProgress());
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());
585 InitializeDemuxer(&streams);
586 InitializeAudioRenderer(audio_stream());
587 InitializeVideoRenderer(video_stream());
588 InitializePipeline(PIPELINE_OK);
590 AddTextStream();
592 // The ended callback shouldn't run until all renderers have ended.
593 pipeline_->OnAudioRendererEnded();
594 message_loop_.RunUntilIdle();
596 pipeline_->OnVideoRendererEnded();
597 message_loop_.RunUntilIdle();
599 EXPECT_CALL(callbacks_, OnEnded());
600 text_stream()->SendEosNotification();
601 message_loop_.RunUntilIdle();
604 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
605 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
607 CreateAudioStream();
608 CreateVideoStream();
609 MockDemuxerStreamVector streams;
610 streams.push_back(audio_stream());
611 streams.push_back(video_stream());
613 // Replace the clock so we can simulate wall clock time advancing w/o using
614 // Sleep().
615 pipeline_->SetClockForTesting(new Clock(&test_tick_clock_));
617 InitializeDemuxer(&streams, duration);
618 InitializeAudioRenderer(audio_stream());
619 InitializeVideoRenderer(video_stream());
620 InitializePipeline(PIPELINE_OK);
622 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
624 float playback_rate = 1.0f;
625 EXPECT_CALL(*video_renderer_, SetPlaybackRate(playback_rate));
626 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
627 pipeline_->SetPlaybackRate(playback_rate);
628 message_loop_.RunUntilIdle();
630 InSequence s;
632 // Verify that the clock doesn't advance since it hasn't been started by
633 // a time update from the audio stream.
634 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
635 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
636 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
638 // Signal end of audio stream.
639 pipeline_->OnAudioRendererEnded();
640 message_loop_.RunUntilIdle();
642 // Verify that the clock advances.
643 start_time = pipeline_->GetMediaTime().ToInternalValue();
644 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
645 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
647 // Signal end of video stream and make sure OnEnded() callback occurs.
648 EXPECT_CALL(callbacks_, OnEnded());
649 pipeline_->OnVideoRendererEnded();
652 TEST_F(PipelineTest, ErrorDuringSeek) {
653 CreateAudioStream();
654 MockDemuxerStreamVector streams;
655 streams.push_back(audio_stream());
657 InitializeDemuxer(&streams);
658 InitializeAudioRenderer(audio_stream());
659 InitializePipeline(PIPELINE_OK);
661 float playback_rate = 1.0f;
662 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
663 pipeline_->SetPlaybackRate(playback_rate);
664 message_loop_.RunUntilIdle();
666 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
668 // Preroll() isn't called as the demuxer errors out first.
669 EXPECT_CALL(*audio_renderer_, Pause());
670 EXPECT_CALL(*audio_renderer_, Flush(_))
671 .WillOnce(RunClosure<0>());
672 EXPECT_CALL(*audio_renderer_, Stop(_))
673 .WillOnce(RunClosure<0>());
675 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
676 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
677 EXPECT_CALL(*demuxer_, Stop(_))
678 .WillOnce(RunClosure<0>());
680 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
681 base::Unretained(&callbacks_)));
682 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
683 message_loop_.RunUntilIdle();
686 // Invoked function OnError. This asserts that the pipeline does not enqueue
687 // non-teardown related tasks while tearing down.
688 static void TestNoCallsAfterError(
689 Pipeline* pipeline, base::MessageLoop* message_loop,
690 PipelineStatus /* status */) {
691 CHECK(pipeline);
692 CHECK(message_loop);
694 // When we get to this stage, the message loop should be empty.
695 EXPECT_TRUE(message_loop->IsIdleForTesting());
697 // Make calls on pipeline after error has occurred.
698 pipeline->SetPlaybackRate(0.5f);
699 pipeline->SetVolume(0.5f);
701 // No additional tasks should be queued as a result of these calls.
702 EXPECT_TRUE(message_loop->IsIdleForTesting());
705 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
706 CreateAudioStream();
707 MockDemuxerStreamVector streams;
708 streams.push_back(audio_stream());
710 InitializeDemuxer(&streams);
711 InitializeAudioRenderer(audio_stream());
712 InitializePipeline(PIPELINE_OK);
714 // Trigger additional requests on the pipeline during tear down from error.
715 base::Callback<void(PipelineStatus)> cb = base::Bind(
716 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
717 ON_CALL(callbacks_, OnError(_))
718 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
720 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
722 // Seek() isn't called as the demuxer errors out first.
723 EXPECT_CALL(*audio_renderer_, Pause());
724 EXPECT_CALL(*audio_renderer_, Flush(_))
725 .WillOnce(RunClosure<0>());
726 EXPECT_CALL(*audio_renderer_, Stop(_))
727 .WillOnce(RunClosure<0>());
729 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
730 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
731 EXPECT_CALL(*demuxer_, Stop(_))
732 .WillOnce(RunClosure<0>());
734 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
735 base::Unretained(&callbacks_)));
736 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
737 message_loop_.RunUntilIdle();
740 TEST_F(PipelineTest, StartTimeIsZero) {
741 CreateVideoStream();
742 MockDemuxerStreamVector streams;
743 streams.push_back(video_stream());
745 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
746 InitializeDemuxer(&streams, kDuration);
747 InitializeVideoRenderer(video_stream());
749 InitializePipeline(PIPELINE_OK);
750 EXPECT_FALSE(metadata_.has_audio);
751 EXPECT_TRUE(metadata_.has_video);
753 EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
756 TEST_F(PipelineTest, StartTimeIsNonZero) {
757 const base::TimeDelta kStartTime = base::TimeDelta::FromSeconds(4);
758 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
760 EXPECT_CALL(*demuxer_, GetStartTime())
761 .WillRepeatedly(Return(kStartTime));
763 CreateVideoStream();
764 MockDemuxerStreamVector streams;
765 streams.push_back(video_stream());
767 InitializeDemuxer(&streams, kDuration);
768 InitializeVideoRenderer(video_stream());
770 InitializePipeline(PIPELINE_OK);
771 EXPECT_FALSE(metadata_.has_audio);
772 EXPECT_TRUE(metadata_.has_video);
774 EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
777 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
778 int time_in_ms,
779 int max_time_in_ms) {
780 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
781 base::TimeDelta::FromMilliseconds(max_time_in_ms));
784 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
785 CreateAudioStream();
786 MockDemuxerStreamVector streams;
787 streams.push_back(audio_stream());
789 InitializeDemuxer(&streams);
790 InitializeAudioRenderer(audio_stream());
791 InitializePipeline(PIPELINE_OK);
793 float playback_rate = 1.0f;
794 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(playback_rate));
795 pipeline_->SetPlaybackRate(playback_rate);
796 message_loop_.RunUntilIdle();
798 // Provide an initial time update so that the pipeline transitions out of the
799 // "waiting for time update" state.
800 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
801 base::TimeDelta::FromMilliseconds(500));
803 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
805 // Arrange to trigger a time update while the demuxer is in the middle of
806 // seeking. This update should be ignored by the pipeline and the clock should
807 // not get updated.
808 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
809 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
810 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
811 RunCallback<1>(PIPELINE_OK)));
813 EXPECT_CALL(*audio_renderer_, Pause());
814 EXPECT_CALL(*audio_renderer_, Flush(_))
815 .WillOnce(RunClosure<0>());
816 EXPECT_CALL(*audio_renderer_, Preroll(seek_time, _))
817 .WillOnce(RunCallback<1>(PIPELINE_OK));
818 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(_));
819 EXPECT_CALL(*audio_renderer_, SetVolume(_));
820 EXPECT_CALL(*audio_renderer_, Play());
822 EXPECT_CALL(callbacks_, OnPrerollCompleted());
823 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
824 DoSeek(seek_time);
826 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
828 // Now that the seek is complete, verify that time updates advance the current
829 // time.
830 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
831 audio_time_cb_.Run(new_time, new_time);
833 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
836 static void DeletePipeline(scoped_ptr<Pipeline> pipeline) {
837 // |pipeline| will go out of scope.
840 TEST_F(PipelineTest, DeleteAfterStop) {
841 CreateAudioStream();
842 MockDemuxerStreamVector streams;
843 streams.push_back(audio_stream());
844 InitializeDemuxer(&streams);
845 InitializeAudioRenderer(audio_stream());
846 InitializePipeline(PIPELINE_OK);
848 ExpectStop();
850 Pipeline* pipeline = pipeline_.get();
851 pipeline->Stop(base::Bind(&DeletePipeline, base::Passed(&pipeline_)));
852 message_loop_.RunUntilIdle();
855 class PipelineTeardownTest : public PipelineTest {
856 public:
857 enum TeardownState {
858 kInitDemuxer,
859 kInitAudioRenderer,
860 kInitVideoRenderer,
861 kPausing,
862 kFlushing,
863 kSeeking,
864 kPrerolling,
865 kStarting,
866 kPlaying,
869 enum StopOrError {
870 kStop,
871 kError,
872 kErrorAndStop,
875 PipelineTeardownTest() {}
876 virtual ~PipelineTeardownTest() {}
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;
886 case kPausing:
887 case kFlushing:
888 case kSeeking:
889 case kPrerolling:
890 case kStarting:
891 DoInitialize(state, stop_or_error);
892 DoSeek(state, stop_or_error);
893 break;
895 case kPlaying:
896 DoInitialize(state, stop_or_error);
897 DoStopOrError(stop_or_error);
898 break;
902 private:
903 // TODO(scherkus): We do radically different things whether teardown is
904 // invoked via stop vs error. The teardown path should be the same,
905 // see http://crbug.com/110228
906 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
907 PipelineStatus expected_status =
908 SetInitializeExpectations(state, stop_or_error);
910 EXPECT_CALL(callbacks_, OnStart(expected_status));
911 pipeline_->Start(
912 filter_collection_.Pass(),
913 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
914 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
915 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
916 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
917 base::Bind(&CallbackHelper::OnPrerollCompleted,
918 base::Unretained(&callbacks_)),
919 base::Bind(&CallbackHelper::OnDurationChange,
920 base::Unretained(&callbacks_)));
921 message_loop_.RunUntilIdle();
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_));
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));
942 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
943 return status;
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));
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));
965 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
966 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
967 return status;
970 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
971 .WillOnce(RunCallback<1>(PIPELINE_OK));
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<2>(PIPELINE_OK)));
978 EXPECT_CALL(callbacks_, OnStop());
979 } else {
980 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
981 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
982 .WillOnce(RunCallback<2>(status));
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;
991 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _))
992 .WillOnce(RunCallback<2>(PIPELINE_OK));
994 EXPECT_CALL(callbacks_, OnMetadata(_));
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));
1002 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1003 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1004 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1006 EXPECT_CALL(*audio_renderer_, Play());
1007 EXPECT_CALL(*video_renderer_, Play(_))
1008 .WillOnce(RunClosure<0>());
1010 if (status == PIPELINE_OK)
1011 EXPECT_CALL(callbacks_, OnPrerollCompleted());
1013 return status;
1016 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1017 InSequence s;
1018 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1020 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1021 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1022 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1023 EXPECT_CALL(callbacks_, OnSeek(status));
1025 if (status == PIPELINE_OK) {
1026 EXPECT_CALL(callbacks_, OnStop());
1029 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1030 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1031 message_loop_.RunUntilIdle();
1034 PipelineStatus SetSeekExpectations(TeardownState state,
1035 StopOrError stop_or_error) {
1036 PipelineStatus status = PIPELINE_OK;
1037 base::Closure stop_cb = base::Bind(
1038 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1040 if (state == kPausing) {
1041 if (stop_or_error == kStop) {
1042 EXPECT_CALL(*audio_renderer_, Pause())
1043 .WillOnce(Stop(pipeline_.get(), stop_cb));
1044 } else {
1045 status = PIPELINE_ERROR_READ;
1046 EXPECT_CALL(*audio_renderer_, Pause())
1047 .WillOnce(SetError(pipeline_.get(), status));
1050 return status;
1053 EXPECT_CALL(*audio_renderer_, Pause());
1054 EXPECT_CALL(*video_renderer_, Pause(_)).WillOnce(RunClosure<0>());
1056 if (state == kFlushing) {
1057 if (stop_or_error == kStop) {
1058 EXPECT_CALL(*audio_renderer_, Flush(_))
1059 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), RunClosure<0>()));
1060 } else {
1061 status = PIPELINE_ERROR_READ;
1062 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1063 DoAll(SetError(pipeline_.get(), status), RunClosure<0>()));
1066 return status;
1069 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1070 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
1072 if (state == kSeeking) {
1073 if (stop_or_error == kStop) {
1074 EXPECT_CALL(*demuxer_, Seek(_, _))
1075 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1076 RunCallback<1>(PIPELINE_OK)));
1077 } else {
1078 status = PIPELINE_ERROR_READ;
1079 EXPECT_CALL(*demuxer_, Seek(_, _))
1080 .WillOnce(RunCallback<1>(status));
1083 return status;
1086 EXPECT_CALL(*demuxer_, Seek(_, _))
1087 .WillOnce(RunCallback<1>(PIPELINE_OK));
1089 if (state == kPrerolling) {
1090 if (stop_or_error == kStop) {
1091 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1092 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1093 RunCallback<1>(PIPELINE_OK)));
1094 } else {
1095 status = PIPELINE_ERROR_READ;
1096 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1097 .WillOnce(RunCallback<1>(status));
1100 return status;
1103 EXPECT_CALL(*audio_renderer_, Preroll(_, _))
1104 .WillOnce(RunCallback<1>(PIPELINE_OK));
1105 EXPECT_CALL(*video_renderer_, Preroll(_, _))
1106 .WillOnce(RunCallback<1>(PIPELINE_OK));
1108 // Playback rate and volume are updated prior to starting.
1109 EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
1110 EXPECT_CALL(*video_renderer_, SetPlaybackRate(0.0f));
1111 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1113 if (state == kStarting) {
1114 if (stop_or_error == kStop) {
1115 EXPECT_CALL(*audio_renderer_, Play())
1116 .WillOnce(Stop(pipeline_.get(), stop_cb));
1117 } else {
1118 status = PIPELINE_ERROR_READ;
1119 EXPECT_CALL(*audio_renderer_, Play())
1120 .WillOnce(SetError(pipeline_.get(), status));
1122 return status;
1125 NOTREACHED() << "State not supported: " << state;
1126 return status;
1129 void DoStopOrError(StopOrError stop_or_error) {
1130 InSequence s;
1132 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1133 EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1134 EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>());
1136 switch (stop_or_error) {
1137 case kStop:
1138 EXPECT_CALL(callbacks_, OnStop());
1139 pipeline_->Stop(base::Bind(
1140 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1141 break;
1143 case kError:
1144 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1145 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1146 break;
1148 case kErrorAndStop:
1149 EXPECT_CALL(callbacks_, OnStop());
1150 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1151 pipeline_->Stop(base::Bind(
1152 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1153 break;
1156 message_loop_.RunUntilIdle();
1159 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1162 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1163 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1164 RunTest(k##state, k##stop_or_error); \
1167 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1168 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1169 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1170 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing);
1171 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1172 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1173 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling);
1174 INSTANTIATE_TEARDOWN_TEST(Stop, Starting);
1175 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1177 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1178 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1179 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1180 INSTANTIATE_TEARDOWN_TEST(Error, Pausing);
1181 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1182 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1183 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling);
1184 INSTANTIATE_TEARDOWN_TEST(Error, Starting);
1185 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1187 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1189 } // namespace media