Default to current UI locale when recommended locales are invalid
[chromium-blink-merge.git] / media / base / pipeline_unittest.cc
blob4eb84f62c3f98eaa88a37c0dca1a1674527e546a
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/fake_text_track_stream.h"
14 #include "media/base/gmock_callback_support.h"
15 #include "media/base/media_log.h"
16 #include "media/base/mock_filters.h"
17 #include "media/base/pipeline.h"
18 #include "media/base/test_helpers.h"
19 #include "media/base/text_renderer.h"
20 #include "media/base/text_track_config.h"
21 #include "media/base/time_delta_interpolator.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/gfx/size.h"
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;
40 namespace media {
42 ACTION_P(SetDemuxerProperties, duration) {
43 arg0->SetDuration(duration);
46 ACTION_P2(Stop, pipeline, stop_cb) {
47 pipeline->Stop(stop_cb);
50 ACTION_P2(SetError, pipeline, status) {
51 pipeline->SetErrorForTesting(status);
54 ACTION_P2(SetBufferingState, cb, buffering_state) {
55 cb->Run(buffering_state);
58 // Used for setting expectations on pipeline callbacks. Using a StrictMock
59 // also lets us test for missing callbacks.
60 class CallbackHelper {
61 public:
62 CallbackHelper() {}
63 virtual ~CallbackHelper() {}
65 MOCK_METHOD1(OnStart, void(PipelineStatus));
66 MOCK_METHOD1(OnSeek, void(PipelineStatus));
67 MOCK_METHOD0(OnStop, void());
68 MOCK_METHOD0(OnEnded, void());
69 MOCK_METHOD1(OnError, void(PipelineStatus));
70 MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
71 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
72 MOCK_METHOD0(OnDurationChange, void());
74 private:
75 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
78 // TODO(scherkus): even though some filters are initialized on separate
79 // threads these test aren't flaky... why? It's because filters' Initialize()
80 // is executed on |message_loop_| and the mock filters instantly call
81 // InitializationComplete(), which keeps the pipeline humming along. If
82 // either filters don't call InitializationComplete() immediately or filter
83 // initialization is moved to a separate thread this test will become flaky.
84 class PipelineTest : public ::testing::Test {
85 public:
86 PipelineTest()
87 : pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
88 new MediaLog())),
89 filter_collection_(new FilterCollection()),
90 demuxer_(new StrictMock<MockDemuxer>()) {
91 filter_collection_->SetDemuxer(demuxer_.get());
93 video_renderer_ = new StrictMock<MockVideoRenderer>();
94 scoped_ptr<VideoRenderer> video_renderer(video_renderer_);
95 filter_collection_->SetVideoRenderer(video_renderer.Pass());
97 audio_renderer_ = new StrictMock<MockAudioRenderer>();
98 scoped_ptr<AudioRenderer> audio_renderer(audio_renderer_);
99 filter_collection_->SetAudioRenderer(audio_renderer.Pass());
101 text_renderer_ = new TextRenderer(
102 message_loop_.message_loop_proxy(),
103 base::Bind(&PipelineTest::OnAddTextTrack,
104 base::Unretained(this)));
105 scoped_ptr<TextRenderer> text_renderer(text_renderer_);
106 filter_collection_->SetTextRenderer(text_renderer.Pass());
108 // SetDemuxerExpectations() adds overriding expectations for expected
109 // non-NULL streams.
110 DemuxerStream* null_pointer = NULL;
111 EXPECT_CALL(*demuxer_, GetStream(_))
112 .WillRepeatedly(Return(null_pointer));
114 EXPECT_CALL(*demuxer_, GetTimelineOffset())
115 .WillRepeatedly(Return(base::Time()));
117 EXPECT_CALL(*demuxer_, GetLiveness())
118 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
121 virtual ~PipelineTest() {
122 if (!pipeline_ || !pipeline_->IsRunning())
123 return;
125 ExpectDemuxerStop();
127 // The mock demuxer doesn't stop the fake text track stream,
128 // so just stop it manually.
129 if (text_stream_) {
130 text_stream_->Stop();
131 message_loop_.RunUntilIdle();
134 // Expect a stop callback if we were started.
135 ExpectPipelineStopAndDestroyPipeline();
136 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop,
137 base::Unretained(&callbacks_)));
138 message_loop_.RunUntilIdle();
141 void OnDemuxerError() {
142 // Cast because OnDemuxerError is private in Pipeline.
143 static_cast<DemuxerHost*>(pipeline_.get())
144 ->OnDemuxerError(PIPELINE_ERROR_ABORT);
147 protected:
148 // Sets up expectations to allow the demuxer to initialize.
149 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
150 void SetDemuxerExpectations(MockDemuxerStreamVector* streams,
151 const base::TimeDelta& duration) {
152 EXPECT_CALL(callbacks_, OnDurationChange());
153 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
154 .WillOnce(DoAll(SetDemuxerProperties(duration),
155 RunCallback<1>(PIPELINE_OK)));
157 // Configure the demuxer to return the streams.
158 for (size_t i = 0; i < streams->size(); ++i) {
159 DemuxerStream* stream = (*streams)[i];
160 EXPECT_CALL(*demuxer_, GetStream(stream->type()))
161 .WillRepeatedly(Return(stream));
165 void SetDemuxerExpectations(MockDemuxerStreamVector* streams) {
166 // Initialize with a default non-zero duration.
167 SetDemuxerExpectations(streams, base::TimeDelta::FromSeconds(10));
170 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
171 DemuxerStream::Type type) {
172 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
173 new StrictMock<MockDemuxerStream>(type));
174 return stream.Pass();
177 // Sets up expectations to allow the video renderer to initialize.
178 void SetVideoRendererExpectations(DemuxerStream* stream) {
179 EXPECT_CALL(*video_renderer_, Initialize(stream, _, _, _, _, _, _, _, _, _))
180 .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
181 SaveArg<6>(&video_ended_cb_),
182 RunCallback<2>(PIPELINE_OK)));
185 // Sets up expectations to allow the audio renderer to initialize.
186 void SetAudioRendererExpectations(DemuxerStream* stream) {
187 EXPECT_CALL(*audio_renderer_, Initialize(stream, _, _, _, _, _, _))
188 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_),
189 SaveArg<4>(&audio_buffering_state_cb_),
190 SaveArg<5>(&audio_ended_cb_),
191 RunCallback<1>(PIPELINE_OK)));
194 void AddTextStream() {
195 EXPECT_CALL(*this, OnAddTextTrack(_,_))
196 .WillOnce(Invoke(this, &PipelineTest::DoOnAddTextTrack));
197 static_cast<DemuxerHost*>(pipeline_.get())->AddTextStream(text_stream(),
198 TextTrackConfig(kTextSubtitles, "", "", ""));
201 // Sets up expectations on the callback and initializes the pipeline. Called
202 // after tests have set expectations any filters they wish to use.
203 void StartPipeline(PipelineStatus start_status) {
204 EXPECT_CALL(callbacks_, OnStart(start_status));
206 if (start_status == PIPELINE_OK) {
207 EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
209 if (audio_stream_) {
210 EXPECT_CALL(*audio_renderer_, GetTimeSource())
211 .WillOnce(Return(&time_source_));
212 EXPECT_CALL(time_source_, SetPlaybackRate(0.0f));
213 EXPECT_CALL(time_source_, SetMediaTime(base::TimeDelta()));
214 EXPECT_CALL(time_source_, StartTicking());
215 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
216 EXPECT_CALL(*audio_renderer_, StartPlaying())
217 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
218 BUFFERING_HAVE_ENOUGH));
221 if (video_stream_) {
222 EXPECT_CALL(*video_renderer_, StartPlaying())
223 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
224 BUFFERING_HAVE_ENOUGH));
227 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
230 pipeline_->Start(
231 filter_collection_.Pass(),
232 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
233 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
234 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
235 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
236 base::Bind(&CallbackHelper::OnBufferingStateChange,
237 base::Unretained(&callbacks_)),
238 base::Bind(&CallbackHelper::OnDurationChange,
239 base::Unretained(&callbacks_)));
240 message_loop_.RunUntilIdle();
243 void CreateAudioStream() {
244 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
247 void CreateVideoStream() {
248 video_stream_ = CreateStream(DemuxerStream::VIDEO);
249 video_stream_->set_video_decoder_config(video_decoder_config_);
252 void CreateTextStream() {
253 scoped_ptr<FakeTextTrackStream> text_stream(new FakeTextTrackStream());
254 EXPECT_CALL(*text_stream, OnRead()).Times(AnyNumber());
255 text_stream_ = text_stream.Pass();
258 MockDemuxerStream* audio_stream() {
259 return audio_stream_.get();
262 MockDemuxerStream* video_stream() {
263 return video_stream_.get();
266 FakeTextTrackStream* text_stream() {
267 return text_stream_.get();
270 void ExpectSeek(const base::TimeDelta& seek_time, bool underflowed) {
271 // Every filter should receive a call to Seek().
272 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
273 .WillOnce(RunCallback<1>(PIPELINE_OK));
275 if (audio_stream_) {
276 if (!underflowed)
277 EXPECT_CALL(time_source_, StopTicking());
278 EXPECT_CALL(*audio_renderer_, Flush(_))
279 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
280 BUFFERING_HAVE_NOTHING),
281 RunClosure<0>()));
282 EXPECT_CALL(time_source_, SetMediaTime(seek_time));
283 EXPECT_CALL(time_source_, SetPlaybackRate(_));
284 EXPECT_CALL(time_source_, StartTicking());
285 EXPECT_CALL(*audio_renderer_, StartPlaying())
286 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
287 BUFFERING_HAVE_ENOUGH));
288 EXPECT_CALL(*audio_renderer_, SetVolume(_));
291 if (video_stream_) {
292 EXPECT_CALL(*video_renderer_, Flush(_))
293 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
294 BUFFERING_HAVE_NOTHING),
295 RunClosure<0>()));
296 EXPECT_CALL(*video_renderer_, StartPlaying())
297 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
298 BUFFERING_HAVE_ENOUGH));
301 // We expect a successful seek callback followed by a buffering update.
302 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
303 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
306 void DoSeek(const base::TimeDelta& seek_time) {
307 pipeline_->Seek(seek_time,
308 base::Bind(&CallbackHelper::OnSeek,
309 base::Unretained(&callbacks_)));
311 // We expect the time to be updated only after the seek has completed.
312 EXPECT_NE(seek_time, pipeline_->GetMediaTime());
313 message_loop_.RunUntilIdle();
314 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
317 void DestroyPipeline() {
318 // In real code Pipeline could be destroyed on a different thread. All weak
319 // pointers must have been invalidated before the stop callback returns.
320 DCHECK(!pipeline_->HasWeakPtrsForTesting());
321 pipeline_.reset();
324 void ExpectDemuxerStop() {
325 if (demuxer_)
326 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
329 void ExpectPipelineStopAndDestroyPipeline() {
330 // After the Pipeline is stopped, it could be destroyed any time. Always
331 // destroy the pipeline immediately after OnStop() to test this.
332 EXPECT_CALL(callbacks_, OnStop())
333 .WillOnce(Invoke(this, &PipelineTest::DestroyPipeline));
336 MOCK_METHOD2(OnAddTextTrack, void(const TextTrackConfig&,
337 const AddTextTrackDoneCB&));
339 void DoOnAddTextTrack(const TextTrackConfig& config,
340 const AddTextTrackDoneCB& done_cb) {
341 scoped_ptr<TextTrack> text_track(new MockTextTrack);
342 done_cb.Run(text_track.Pass());
345 // Fixture members.
346 StrictMock<CallbackHelper> callbacks_;
347 base::SimpleTestTickClock test_tick_clock_;
348 base::MessageLoop message_loop_;
349 scoped_ptr<Pipeline> pipeline_;
351 scoped_ptr<FilterCollection> filter_collection_;
352 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
353 StrictMock<MockVideoRenderer>* video_renderer_;
354 StrictMock<MockAudioRenderer>* audio_renderer_;
355 StrictMock<MockTimeSource> time_source_;
356 StrictMock<CallbackHelper> text_renderer_callbacks_;
357 TextRenderer* text_renderer_;
358 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
359 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
360 scoped_ptr<FakeTextTrackStream> text_stream_;
361 AudioRenderer::TimeCB audio_time_cb_;
362 BufferingStateCB audio_buffering_state_cb_;
363 BufferingStateCB video_buffering_state_cb_;
364 base::Closure audio_ended_cb_;
365 base::Closure video_ended_cb_;
366 VideoDecoderConfig video_decoder_config_;
367 PipelineMetadata metadata_;
369 private:
370 DISALLOW_COPY_AND_ASSIGN(PipelineTest);
373 // Test that playback controls methods no-op when the pipeline hasn't been
374 // started.
375 TEST_F(PipelineTest, NotStarted) {
376 const base::TimeDelta kZero;
378 EXPECT_FALSE(pipeline_->IsRunning());
380 // Setting should still work.
381 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
382 pipeline_->SetPlaybackRate(-1.0f);
383 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
384 pipeline_->SetPlaybackRate(1.0f);
385 EXPECT_EQ(1.0f, pipeline_->GetPlaybackRate());
387 // Setting should still work.
388 EXPECT_EQ(1.0f, pipeline_->GetVolume());
389 pipeline_->SetVolume(-1.0f);
390 EXPECT_EQ(1.0f, pipeline_->GetVolume());
391 pipeline_->SetVolume(0.0f);
392 EXPECT_EQ(0.0f, pipeline_->GetVolume());
394 EXPECT_TRUE(kZero == pipeline_->GetMediaTime());
395 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
396 EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
399 TEST_F(PipelineTest, NeverInitializes) {
400 // Don't execute the callback passed into Initialize().
401 EXPECT_CALL(*demuxer_, Initialize(_, _, _));
403 // This test hangs during initialization by never calling
404 // InitializationComplete(). StrictMock<> will ensure that the callback is
405 // never executed.
406 pipeline_->Start(
407 filter_collection_.Pass(),
408 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
409 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
410 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
411 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
412 base::Bind(&CallbackHelper::OnBufferingStateChange,
413 base::Unretained(&callbacks_)),
414 base::Bind(&CallbackHelper::OnDurationChange,
415 base::Unretained(&callbacks_)));
416 message_loop_.RunUntilIdle();
418 // Because our callback will get executed when the test tears down, we'll
419 // verify that nothing has been called, then set our expectation for the call
420 // made during tear down.
421 Mock::VerifyAndClear(&callbacks_);
422 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK));
425 TEST_F(PipelineTest, StopWithoutStart) {
426 ExpectPipelineStopAndDestroyPipeline();
427 pipeline_->Stop(
428 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
429 message_loop_.RunUntilIdle();
432 TEST_F(PipelineTest, StartThenStopImmediately) {
433 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
434 .WillOnce(RunCallback<1>(PIPELINE_OK));
435 EXPECT_CALL(*demuxer_, Stop(_))
436 .WillOnce(RunClosure<0>());
438 EXPECT_CALL(callbacks_, OnStart(_));
440 pipeline_->Start(
441 filter_collection_.Pass(),
442 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
443 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
444 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
445 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
446 base::Bind(&CallbackHelper::OnBufferingStateChange,
447 base::Unretained(&callbacks_)),
448 base::Bind(&CallbackHelper::OnDurationChange,
449 base::Unretained(&callbacks_)));
451 // Expect a stop callback if we were started.
452 ExpectPipelineStopAndDestroyPipeline();
453 pipeline_->Stop(
454 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
455 message_loop_.RunUntilIdle();
458 TEST_F(PipelineTest, DemuxerErrorDuringStop) {
459 CreateAudioStream();
460 MockDemuxerStreamVector streams;
461 streams.push_back(audio_stream());
463 SetDemuxerExpectations(&streams);
464 SetAudioRendererExpectations(audio_stream());
466 StartPipeline(PIPELINE_OK);
468 EXPECT_CALL(*demuxer_, Stop(_))
469 .WillOnce(DoAll(InvokeWithoutArgs(this, &PipelineTest::OnDemuxerError),
470 RunClosure<0>()));
471 ExpectPipelineStopAndDestroyPipeline();
473 pipeline_->Stop(
474 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
475 message_loop_.RunUntilIdle();
478 TEST_F(PipelineTest, URLNotFound) {
479 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
480 .WillOnce(RunCallback<1>(PIPELINE_ERROR_URL_NOT_FOUND));
481 EXPECT_CALL(*demuxer_, Stop(_))
482 .WillOnce(RunClosure<0>());
484 StartPipeline(PIPELINE_ERROR_URL_NOT_FOUND);
487 TEST_F(PipelineTest, NoStreams) {
488 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
489 .WillOnce(RunCallback<1>(PIPELINE_OK));
490 EXPECT_CALL(*demuxer_, Stop(_))
491 .WillOnce(RunClosure<0>());
493 StartPipeline(PIPELINE_ERROR_COULD_NOT_RENDER);
496 TEST_F(PipelineTest, AudioStream) {
497 CreateAudioStream();
498 MockDemuxerStreamVector streams;
499 streams.push_back(audio_stream());
501 SetDemuxerExpectations(&streams);
502 SetAudioRendererExpectations(audio_stream());
504 StartPipeline(PIPELINE_OK);
505 EXPECT_TRUE(metadata_.has_audio);
506 EXPECT_FALSE(metadata_.has_video);
509 TEST_F(PipelineTest, VideoStream) {
510 CreateVideoStream();
511 MockDemuxerStreamVector streams;
512 streams.push_back(video_stream());
514 SetDemuxerExpectations(&streams);
515 SetVideoRendererExpectations(video_stream());
517 StartPipeline(PIPELINE_OK);
518 EXPECT_FALSE(metadata_.has_audio);
519 EXPECT_TRUE(metadata_.has_video);
522 TEST_F(PipelineTest, AudioVideoStream) {
523 CreateAudioStream();
524 CreateVideoStream();
525 MockDemuxerStreamVector streams;
526 streams.push_back(audio_stream());
527 streams.push_back(video_stream());
529 SetDemuxerExpectations(&streams);
530 SetAudioRendererExpectations(audio_stream());
531 SetVideoRendererExpectations(video_stream());
533 StartPipeline(PIPELINE_OK);
534 EXPECT_TRUE(metadata_.has_audio);
535 EXPECT_TRUE(metadata_.has_video);
538 TEST_F(PipelineTest, VideoTextStream) {
539 CreateVideoStream();
540 CreateTextStream();
541 MockDemuxerStreamVector streams;
542 streams.push_back(video_stream());
544 SetDemuxerExpectations(&streams);
545 SetVideoRendererExpectations(video_stream());
547 StartPipeline(PIPELINE_OK);
548 EXPECT_FALSE(metadata_.has_audio);
549 EXPECT_TRUE(metadata_.has_video);
551 AddTextStream();
552 message_loop_.RunUntilIdle();
555 TEST_F(PipelineTest, VideoAudioTextStream) {
556 CreateVideoStream();
557 CreateAudioStream();
558 CreateTextStream();
559 MockDemuxerStreamVector streams;
560 streams.push_back(video_stream());
561 streams.push_back(audio_stream());
563 SetDemuxerExpectations(&streams);
564 SetVideoRendererExpectations(video_stream());
565 SetAudioRendererExpectations(audio_stream());
567 StartPipeline(PIPELINE_OK);
568 EXPECT_TRUE(metadata_.has_audio);
569 EXPECT_TRUE(metadata_.has_video);
571 AddTextStream();
572 message_loop_.RunUntilIdle();
575 TEST_F(PipelineTest, Seek) {
576 CreateAudioStream();
577 CreateVideoStream();
578 CreateTextStream();
579 MockDemuxerStreamVector streams;
580 streams.push_back(audio_stream());
581 streams.push_back(video_stream());
583 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
584 SetAudioRendererExpectations(audio_stream());
585 SetVideoRendererExpectations(video_stream());
587 // Initialize then seek!
588 StartPipeline(PIPELINE_OK);
590 // Every filter should receive a call to Seek().
591 base::TimeDelta expected = base::TimeDelta::FromSeconds(2000);
592 ExpectSeek(expected, false);
593 DoSeek(expected);
596 TEST_F(PipelineTest, SeekAfterError) {
597 CreateAudioStream();
598 MockDemuxerStreamVector streams;
599 streams.push_back(audio_stream());
601 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
602 SetAudioRendererExpectations(audio_stream());
604 // Initialize then seek!
605 StartPipeline(PIPELINE_OK);
607 EXPECT_CALL(*demuxer_, Stop(_))
608 .WillOnce(RunClosure<0>());
609 EXPECT_CALL(callbacks_, OnError(_));
611 static_cast<DemuxerHost*>(pipeline_.get())
612 ->OnDemuxerError(PIPELINE_ERROR_ABORT);
613 message_loop_.RunUntilIdle();
615 pipeline_->Seek(
616 base::TimeDelta::FromMilliseconds(100),
617 base::Bind(&CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
618 message_loop_.RunUntilIdle();
621 TEST_F(PipelineTest, SetVolume) {
622 CreateAudioStream();
623 MockDemuxerStreamVector streams;
624 streams.push_back(audio_stream());
626 SetDemuxerExpectations(&streams);
627 SetAudioRendererExpectations(audio_stream());
629 // The audio renderer should receive a call to SetVolume().
630 float expected = 0.5f;
631 EXPECT_CALL(*audio_renderer_, SetVolume(expected));
633 // Initialize then set volume!
634 StartPipeline(PIPELINE_OK);
635 pipeline_->SetVolume(expected);
638 TEST_F(PipelineTest, Properties) {
639 CreateVideoStream();
640 MockDemuxerStreamVector streams;
641 streams.push_back(video_stream());
643 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
644 SetDemuxerExpectations(&streams, kDuration);
645 SetVideoRendererExpectations(video_stream());
647 StartPipeline(PIPELINE_OK);
648 EXPECT_EQ(kDuration.ToInternalValue(),
649 pipeline_->GetMediaDuration().ToInternalValue());
650 EXPECT_FALSE(pipeline_->DidLoadingProgress());
653 TEST_F(PipelineTest, GetBufferedTimeRanges) {
654 CreateVideoStream();
655 MockDemuxerStreamVector streams;
656 streams.push_back(video_stream());
658 const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
659 SetDemuxerExpectations(&streams, kDuration);
660 SetVideoRendererExpectations(video_stream());
662 StartPipeline(PIPELINE_OK);
664 EXPECT_EQ(0u, pipeline_->GetBufferedTimeRanges().size());
666 EXPECT_FALSE(pipeline_->DidLoadingProgress());
667 pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8);
668 EXPECT_TRUE(pipeline_->DidLoadingProgress());
669 EXPECT_FALSE(pipeline_->DidLoadingProgress());
670 EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
671 EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0));
672 EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0));
674 base::TimeDelta kSeekTime = kDuration / 2;
675 ExpectSeek(kSeekTime, false);
676 DoSeek(kSeekTime);
678 EXPECT_FALSE(pipeline_->DidLoadingProgress());
681 TEST_F(PipelineTest, EndedCallback) {
682 CreateAudioStream();
683 CreateVideoStream();
684 CreateTextStream();
685 MockDemuxerStreamVector streams;
686 streams.push_back(audio_stream());
687 streams.push_back(video_stream());
689 SetDemuxerExpectations(&streams);
690 SetAudioRendererExpectations(audio_stream());
691 SetVideoRendererExpectations(video_stream());
692 StartPipeline(PIPELINE_OK);
694 AddTextStream();
696 // The ended callback shouldn't run until all renderers have ended.
697 audio_ended_cb_.Run();
698 message_loop_.RunUntilIdle();
700 video_ended_cb_.Run();
701 message_loop_.RunUntilIdle();
703 EXPECT_CALL(time_source_, StopTicking());
704 EXPECT_CALL(callbacks_, OnEnded());
705 text_stream()->SendEosNotification();
706 message_loop_.RunUntilIdle();
709 TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
710 base::TimeDelta duration = base::TimeDelta::FromSeconds(10);
712 CreateAudioStream();
713 CreateVideoStream();
714 MockDemuxerStreamVector streams;
715 streams.push_back(audio_stream());
716 streams.push_back(video_stream());
718 // Replace what's used for interpolating to simulate wall clock time.
719 pipeline_->SetTimeDeltaInterpolatorForTesting(
720 new TimeDeltaInterpolator(&test_tick_clock_));
722 SetDemuxerExpectations(&streams, duration);
723 SetAudioRendererExpectations(audio_stream());
724 SetVideoRendererExpectations(video_stream());
725 StartPipeline(PIPELINE_OK);
727 EXPECT_EQ(0, pipeline_->GetMediaTime().ToInternalValue());
729 float playback_rate = 1.0f;
730 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
731 pipeline_->SetPlaybackRate(playback_rate);
732 message_loop_.RunUntilIdle();
734 InSequence s;
736 // Verify that the clock doesn't advance since it hasn't been started by
737 // a time update from the audio stream.
738 int64 start_time = pipeline_->GetMediaTime().ToInternalValue();
739 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
740 EXPECT_EQ(pipeline_->GetMediaTime().ToInternalValue(), start_time);
742 // Signal end of audio stream.
743 audio_ended_cb_.Run();
744 message_loop_.RunUntilIdle();
746 // Verify that the clock advances.
747 start_time = pipeline_->GetMediaTime().ToInternalValue();
748 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(100));
749 EXPECT_GT(pipeline_->GetMediaTime().ToInternalValue(), start_time);
751 // Signal end of video stream and make sure OnEnded() callback occurs.
752 EXPECT_CALL(time_source_, StopTicking());
753 EXPECT_CALL(callbacks_, OnEnded());
754 video_ended_cb_.Run();
757 TEST_F(PipelineTest, ErrorDuringSeek) {
758 CreateAudioStream();
759 MockDemuxerStreamVector streams;
760 streams.push_back(audio_stream());
762 SetDemuxerExpectations(&streams);
763 SetAudioRendererExpectations(audio_stream());
764 StartPipeline(PIPELINE_OK);
766 float playback_rate = 1.0f;
767 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
768 pipeline_->SetPlaybackRate(playback_rate);
769 message_loop_.RunUntilIdle();
771 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
773 // Preroll() isn't called as the demuxer errors out first.
774 EXPECT_CALL(time_source_, StopTicking());
775 EXPECT_CALL(*audio_renderer_, Flush(_))
776 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
777 BUFFERING_HAVE_NOTHING),
778 RunClosure<0>()));
780 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
781 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
782 EXPECT_CALL(*demuxer_, Stop(_))
783 .WillOnce(RunClosure<0>());
785 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
786 base::Unretained(&callbacks_)));
787 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
788 message_loop_.RunUntilIdle();
791 // Invoked function OnError. This asserts that the pipeline does not enqueue
792 // non-teardown related tasks while tearing down.
793 static void TestNoCallsAfterError(
794 Pipeline* pipeline, base::MessageLoop* message_loop,
795 PipelineStatus /* status */) {
796 CHECK(pipeline);
797 CHECK(message_loop);
799 // When we get to this stage, the message loop should be empty.
800 EXPECT_TRUE(message_loop->IsIdleForTesting());
802 // Make calls on pipeline after error has occurred.
803 pipeline->SetPlaybackRate(0.5f);
804 pipeline->SetVolume(0.5f);
806 // No additional tasks should be queued as a result of these calls.
807 EXPECT_TRUE(message_loop->IsIdleForTesting());
810 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
811 CreateAudioStream();
812 MockDemuxerStreamVector streams;
813 streams.push_back(audio_stream());
815 SetDemuxerExpectations(&streams);
816 SetAudioRendererExpectations(audio_stream());
817 StartPipeline(PIPELINE_OK);
819 // Trigger additional requests on the pipeline during tear down from error.
820 base::Callback<void(PipelineStatus)> cb = base::Bind(
821 &TestNoCallsAfterError, pipeline_.get(), &message_loop_);
822 ON_CALL(callbacks_, OnError(_))
823 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
825 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
827 // Seek() isn't called as the demuxer errors out first.
828 EXPECT_CALL(time_source_, StopTicking());
829 EXPECT_CALL(*audio_renderer_, Flush(_))
830 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
831 BUFFERING_HAVE_NOTHING),
832 RunClosure<0>()));
834 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
835 .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ));
836 EXPECT_CALL(*demuxer_, Stop(_))
837 .WillOnce(RunClosure<0>());
839 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek,
840 base::Unretained(&callbacks_)));
841 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ));
842 message_loop_.RunUntilIdle();
845 static void RunTimeCB(const AudioRenderer::TimeCB& time_cb,
846 int time_in_ms,
847 int max_time_in_ms) {
848 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
849 base::TimeDelta::FromMilliseconds(max_time_in_ms));
852 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
853 CreateAudioStream();
854 MockDemuxerStreamVector streams;
855 streams.push_back(audio_stream());
857 SetDemuxerExpectations(&streams);
858 SetAudioRendererExpectations(audio_stream());
859 StartPipeline(PIPELINE_OK);
861 float playback_rate = 1.0f;
862 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
863 pipeline_->SetPlaybackRate(playback_rate);
864 message_loop_.RunUntilIdle();
866 // Provide an initial time update so that the pipeline transitions out of the
867 // "waiting for time update" state.
868 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(100),
869 base::TimeDelta::FromMilliseconds(500));
871 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5);
873 // Arrange to trigger a time update while the demuxer is in the middle of
874 // seeking. This update should be ignored by the pipeline and the clock should
875 // not get updated.
876 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700);
877 EXPECT_CALL(*demuxer_, Seek(seek_time, _))
878 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run),
879 RunCallback<1>(PIPELINE_OK)));
881 EXPECT_CALL(time_source_, StopTicking());
882 EXPECT_CALL(*audio_renderer_, Flush(_))
883 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
884 BUFFERING_HAVE_NOTHING),
885 RunClosure<0>()));
886 EXPECT_CALL(time_source_, SetMediaTime(seek_time));
887 EXPECT_CALL(time_source_, SetPlaybackRate(_));
888 EXPECT_CALL(time_source_, StartTicking());
889 EXPECT_CALL(*audio_renderer_, StartPlaying())
890 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
891 BUFFERING_HAVE_ENOUGH));
892 EXPECT_CALL(*audio_renderer_, SetVolume(_));
894 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
895 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
896 DoSeek(seek_time);
898 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
900 // Now that the seek is complete, verify that time updates advance the current
901 // time.
902 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
903 audio_time_cb_.Run(new_time, new_time);
905 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
908 TEST_F(PipelineTest, DestroyAfterStop) {
909 CreateAudioStream();
910 MockDemuxerStreamVector streams;
911 streams.push_back(audio_stream());
912 SetDemuxerExpectations(&streams);
913 SetAudioRendererExpectations(audio_stream());
914 StartPipeline(PIPELINE_OK);
916 ExpectDemuxerStop();
918 ExpectPipelineStopAndDestroyPipeline();
919 pipeline_->Stop(
920 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
921 message_loop_.RunUntilIdle();
924 TEST_F(PipelineTest, Underflow) {
925 CreateAudioStream();
926 CreateVideoStream();
927 MockDemuxerStreamVector streams;
928 streams.push_back(audio_stream());
929 streams.push_back(video_stream());
931 SetDemuxerExpectations(&streams);
932 SetAudioRendererExpectations(audio_stream());
933 SetVideoRendererExpectations(video_stream());
934 StartPipeline(PIPELINE_OK);
936 // Simulate underflow.
937 EXPECT_CALL(time_source_, StopTicking());
938 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
940 // Seek while underflowed. We shouldn't call StopTicking() again.
941 base::TimeDelta expected = base::TimeDelta::FromSeconds(5);
942 ExpectSeek(expected, true);
943 DoSeek(expected);
946 static void PostTimeCB(base::MessageLoop* message_loop,
947 const AudioRenderer::TimeCB& time_cb) {
948 base::TimeDelta new_time = base::TimeDelta::FromMilliseconds(100);
949 message_loop->PostTask(FROM_HERE, base::Bind(time_cb, new_time, new_time));
952 TEST_F(PipelineTest, TimeUpdateAfterStop) {
953 CreateAudioStream();
954 CreateVideoStream();
955 MockDemuxerStreamVector streams;
956 streams.push_back(audio_stream());
957 streams.push_back(video_stream());
959 SetDemuxerExpectations(&streams);
960 SetAudioRendererExpectations(audio_stream());
961 SetVideoRendererExpectations(video_stream());
962 StartPipeline(PIPELINE_OK);
964 // Double post here! This is a hack to simulate the case where TimeCB is
965 // posted during ~AudioRenderer(), which is triggered in Pipeline::DoStop.
966 // Since we can't EXPECT_CALL the dtor and Pipeline::DoStop() is posted
967 // as well, we need to post twice here.
968 message_loop_.PostTask(
969 FROM_HERE, base::Bind(&PostTimeCB, &message_loop_, audio_time_cb_));
971 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
973 ExpectPipelineStopAndDestroyPipeline();
974 pipeline_->Stop(
975 base::Bind(&CallbackHelper::OnStop, base::Unretained(&callbacks_)));
976 message_loop_.RunUntilIdle();
979 class PipelineTeardownTest : public PipelineTest {
980 public:
981 enum TeardownState {
982 kInitDemuxer,
983 kInitAudioRenderer,
984 kInitVideoRenderer,
985 kFlushing,
986 kSeeking,
987 kPlaying,
990 enum StopOrError {
991 kStop,
992 kError,
993 kErrorAndStop,
996 PipelineTeardownTest() {}
997 virtual ~PipelineTeardownTest() {}
999 void RunTest(TeardownState state, StopOrError stop_or_error) {
1000 switch (state) {
1001 case kInitDemuxer:
1002 case kInitAudioRenderer:
1003 case kInitVideoRenderer:
1004 DoInitialize(state, stop_or_error);
1005 break;
1007 case kFlushing:
1008 case kSeeking:
1009 DoInitialize(state, stop_or_error);
1010 DoSeek(state, stop_or_error);
1011 break;
1013 case kPlaying:
1014 DoInitialize(state, stop_or_error);
1015 DoStopOrError(stop_or_error);
1016 break;
1020 private:
1021 // TODO(scherkus): We do radically different things whether teardown is
1022 // invoked via stop vs error. The teardown path should be the same,
1023 // see http://crbug.com/110228
1024 void DoInitialize(TeardownState state, StopOrError stop_or_error) {
1025 PipelineStatus expected_status =
1026 SetInitializeExpectations(state, stop_or_error);
1028 EXPECT_CALL(callbacks_, OnStart(expected_status));
1029 pipeline_->Start(
1030 filter_collection_.Pass(),
1031 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
1032 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
1033 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
1034 base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
1035 base::Bind(&CallbackHelper::OnBufferingStateChange,
1036 base::Unretained(&callbacks_)),
1037 base::Bind(&CallbackHelper::OnDurationChange,
1038 base::Unretained(&callbacks_)));
1039 message_loop_.RunUntilIdle();
1042 PipelineStatus SetInitializeExpectations(TeardownState state,
1043 StopOrError stop_or_error) {
1044 PipelineStatus status = PIPELINE_OK;
1045 base::Closure stop_cb = base::Bind(
1046 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1048 if (state == kInitDemuxer) {
1049 if (stop_or_error == kStop) {
1050 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1051 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1052 RunCallback<1>(PIPELINE_OK)));
1053 ExpectPipelineStopAndDestroyPipeline();
1054 } else {
1055 status = DEMUXER_ERROR_COULD_NOT_OPEN;
1056 EXPECT_CALL(*demuxer_, Initialize(_, _, _))
1057 .WillOnce(RunCallback<1>(status));
1060 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1061 return status;
1064 CreateAudioStream();
1065 CreateVideoStream();
1066 MockDemuxerStreamVector streams;
1067 streams.push_back(audio_stream());
1068 streams.push_back(video_stream());
1069 SetDemuxerExpectations(&streams, base::TimeDelta::FromSeconds(3000));
1071 if (state == kInitAudioRenderer) {
1072 if (stop_or_error == kStop) {
1073 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1074 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1075 RunCallback<1>(PIPELINE_OK)));
1076 ExpectPipelineStopAndDestroyPipeline();
1077 } else {
1078 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1079 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1080 .WillOnce(RunCallback<1>(status));
1083 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1084 return status;
1087 EXPECT_CALL(*audio_renderer_, Initialize(_, _, _, _, _, _, _))
1088 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
1089 RunCallback<1>(PIPELINE_OK)));
1091 if (state == kInitVideoRenderer) {
1092 if (stop_or_error == kStop) {
1093 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1094 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1095 RunCallback<2>(PIPELINE_OK)));
1096 ExpectPipelineStopAndDestroyPipeline();
1097 } else {
1098 status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1099 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1100 .WillOnce(RunCallback<2>(status));
1103 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1104 return status;
1107 EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _, _, _))
1108 .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
1109 RunCallback<2>(PIPELINE_OK)));
1111 EXPECT_CALL(callbacks_, OnMetadata(_));
1113 // If we get here it's a successful initialization.
1114 EXPECT_CALL(*audio_renderer_, GetTimeSource())
1115 .WillOnce(Return(&time_source_));
1116 EXPECT_CALL(time_source_, SetMediaTime(base::TimeDelta()));
1117 EXPECT_CALL(time_source_, SetPlaybackRate(0.0f));
1118 EXPECT_CALL(time_source_, StartTicking());
1119 EXPECT_CALL(*audio_renderer_, SetVolume(1.0f));
1120 EXPECT_CALL(*audio_renderer_, StartPlaying())
1121 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
1122 BUFFERING_HAVE_ENOUGH));
1123 EXPECT_CALL(*video_renderer_, StartPlaying())
1124 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
1125 BUFFERING_HAVE_ENOUGH));
1127 if (status == PIPELINE_OK)
1128 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
1130 return status;
1133 void DoSeek(TeardownState state, StopOrError stop_or_error) {
1134 InSequence s;
1135 PipelineStatus status = SetSeekExpectations(state, stop_or_error);
1137 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1138 EXPECT_CALL(callbacks_, OnSeek(status));
1140 if (status == PIPELINE_OK) {
1141 ExpectPipelineStopAndDestroyPipeline();
1144 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind(
1145 &CallbackHelper::OnSeek, base::Unretained(&callbacks_)));
1146 message_loop_.RunUntilIdle();
1149 PipelineStatus SetSeekExpectations(TeardownState state,
1150 StopOrError stop_or_error) {
1151 PipelineStatus status = PIPELINE_OK;
1152 base::Closure stop_cb = base::Bind(
1153 &CallbackHelper::OnStop, base::Unretained(&callbacks_));
1155 EXPECT_CALL(time_source_, StopTicking());
1157 if (state == kFlushing) {
1158 if (stop_or_error == kStop) {
1159 EXPECT_CALL(*audio_renderer_, Flush(_))
1160 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1161 SetBufferingState(&audio_buffering_state_cb_,
1162 BUFFERING_HAVE_NOTHING),
1163 RunClosure<0>()));
1164 } else {
1165 status = PIPELINE_ERROR_READ;
1166 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(
1167 DoAll(SetError(pipeline_.get(), status),
1168 SetBufferingState(&audio_buffering_state_cb_,
1169 BUFFERING_HAVE_NOTHING),
1170 RunClosure<0>()));
1173 return status;
1176 EXPECT_CALL(*audio_renderer_, Flush(_))
1177 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
1178 BUFFERING_HAVE_NOTHING),
1179 RunClosure<0>()));
1180 EXPECT_CALL(*video_renderer_, Flush(_))
1181 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
1182 BUFFERING_HAVE_NOTHING),
1183 RunClosure<0>()));
1185 if (state == kSeeking) {
1186 if (stop_or_error == kStop) {
1187 EXPECT_CALL(*demuxer_, Seek(_, _))
1188 .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb),
1189 RunCallback<1>(PIPELINE_OK)));
1190 } else {
1191 status = PIPELINE_ERROR_READ;
1192 EXPECT_CALL(*demuxer_, Seek(_, _))
1193 .WillOnce(RunCallback<1>(status));
1196 return status;
1199 NOTREACHED() << "State not supported: " << state;
1200 return status;
1203 void DoStopOrError(StopOrError stop_or_error) {
1204 InSequence s;
1206 EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>());
1208 switch (stop_or_error) {
1209 case kStop:
1210 ExpectPipelineStopAndDestroyPipeline();
1211 pipeline_->Stop(base::Bind(
1212 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1213 break;
1215 case kError:
1216 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1217 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1218 break;
1220 case kErrorAndStop:
1221 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ));
1222 ExpectPipelineStopAndDestroyPipeline();
1223 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ);
1224 pipeline_->Stop(base::Bind(
1225 &CallbackHelper::OnStop, base::Unretained(&callbacks_)));
1226 break;
1229 message_loop_.RunUntilIdle();
1232 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest);
1235 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \
1236 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \
1237 RunTest(k##state, k##stop_or_error); \
1240 INSTANTIATE_TEARDOWN_TEST(Stop, InitDemuxer);
1241 INSTANTIATE_TEARDOWN_TEST(Stop, InitAudioRenderer);
1242 INSTANTIATE_TEARDOWN_TEST(Stop, InitVideoRenderer);
1243 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing);
1244 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking);
1245 INSTANTIATE_TEARDOWN_TEST(Stop, Playing);
1247 INSTANTIATE_TEARDOWN_TEST(Error, InitDemuxer);
1248 INSTANTIATE_TEARDOWN_TEST(Error, InitAudioRenderer);
1249 INSTANTIATE_TEARDOWN_TEST(Error, InitVideoRenderer);
1250 INSTANTIATE_TEARDOWN_TEST(Error, Flushing);
1251 INSTANTIATE_TEARDOWN_TEST(Error, Seeking);
1252 INSTANTIATE_TEARDOWN_TEST(Error, Playing);
1254 INSTANTIATE_TEARDOWN_TEST(ErrorAndStop, Playing);
1256 } // namespace media