Clean up:
[chromium-blink-merge.git] / media / renderers / renderer_impl_unittest.cc
blobe4396580aa91e71d4e01a5f2c3d627be2e73e4ec
1 // Copyright 2014 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/run_loop.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "media/base/gmock_callback_support.h"
12 #include "media/base/mock_filters.h"
13 #include "media/base/test_helpers.h"
14 #include "media/renderers/renderer_impl.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using ::testing::_;
18 using ::testing::DoAll;
19 using ::testing::InSequence;
20 using ::testing::Mock;
21 using ::testing::Return;
22 using ::testing::SaveArg;
23 using ::testing::StrictMock;
25 namespace media {
27 const int64 kStartPlayingTimeInMs = 100;
29 ACTION_P2(SetBufferingState, cb, buffering_state) {
30 cb->Run(buffering_state);
33 ACTION_P2(AudioError, cb, error) {
34 cb->Run(error);
37 class RendererImplTest : public ::testing::Test {
38 public:
39 // Used for setting expectations on pipeline callbacks. Using a StrictMock
40 // also lets us test for missing callbacks.
41 class CallbackHelper {
42 public:
43 CallbackHelper() {}
44 virtual ~CallbackHelper() {}
46 MOCK_METHOD1(OnInitialize, void(PipelineStatus));
47 MOCK_METHOD0(OnFlushed, void());
48 MOCK_METHOD0(OnEnded, void());
49 MOCK_METHOD1(OnError, void(PipelineStatus));
50 MOCK_METHOD1(OnUpdateStatistics, void(const PipelineStatistics&));
51 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
52 MOCK_METHOD0(OnWaitingForDecryptionKey, void());
54 private:
55 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
58 RendererImplTest()
59 : demuxer_(new StrictMock<MockDemuxer>()),
60 video_renderer_(new StrictMock<MockVideoRenderer>()),
61 audio_renderer_(new StrictMock<MockAudioRenderer>()),
62 renderer_impl_(
63 new RendererImpl(message_loop_.message_loop_proxy(),
64 scoped_ptr<AudioRenderer>(audio_renderer_),
65 scoped_ptr<VideoRenderer>(video_renderer_))) {
66 // SetDemuxerExpectations() adds overriding expectations for expected
67 // non-NULL streams.
68 DemuxerStream* null_pointer = NULL;
69 EXPECT_CALL(*demuxer_, GetStream(_))
70 .WillRepeatedly(Return(null_pointer));
73 virtual ~RendererImplTest() {
74 renderer_impl_.reset();
75 base::RunLoop().RunUntilIdle();
78 protected:
79 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
81 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
82 DemuxerStream::Type type) {
83 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
84 new StrictMock<MockDemuxerStream>(type));
85 return stream.Pass();
88 // Sets up expectations to allow the audio renderer to initialize.
89 void SetAudioRendererInitializeExpectations(PipelineStatus status) {
90 EXPECT_CALL(*audio_renderer_,
91 Initialize(audio_stream_.get(), _, _, _, _, _, _, _))
92 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_),
93 SaveArg<5>(&audio_ended_cb_),
94 SaveArg<6>(&audio_error_cb_), RunCallback<1>(status)));
97 // Sets up expectations to allow the video renderer to initialize.
98 void SetVideoRendererInitializeExpectations(PipelineStatus status) {
99 EXPECT_CALL(*video_renderer_,
100 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _))
101 .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_),
102 SaveArg<5>(&video_ended_cb_), RunCallback<1>(status)));
105 void InitializeAndExpect(PipelineStatus start_status) {
106 EXPECT_CALL(callbacks_, OnInitialize(start_status));
107 EXPECT_CALL(callbacks_, OnWaitingForDecryptionKey()).Times(0);
109 if (start_status == PIPELINE_OK && audio_stream_) {
110 EXPECT_CALL(*audio_renderer_, GetTimeSource())
111 .WillOnce(Return(&time_source_));
112 } else {
113 renderer_impl_->set_time_source_for_testing(&time_source_);
116 renderer_impl_->Initialize(
117 demuxer_.get(),
118 base::Bind(&CallbackHelper::OnInitialize,
119 base::Unretained(&callbacks_)),
120 base::Bind(&CallbackHelper::OnUpdateStatistics,
121 base::Unretained(&callbacks_)),
122 base::Bind(&CallbackHelper::OnBufferingStateChange,
123 base::Unretained(&callbacks_)),
124 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
125 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
126 base::Bind(&CallbackHelper::OnWaitingForDecryptionKey,
127 base::Unretained(&callbacks_)));
128 base::RunLoop().RunUntilIdle();
131 void CreateAudioStream() {
132 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
133 streams_.push_back(audio_stream_.get());
134 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
135 .WillRepeatedly(Return(audio_stream_.get()));
138 void CreateVideoStream() {
139 video_stream_ = CreateStream(DemuxerStream::VIDEO);
140 video_stream_->set_video_decoder_config(video_decoder_config_);
141 streams_.push_back(video_stream_.get());
142 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
143 .WillRepeatedly(Return(video_stream_.get()));
146 void CreateAudioAndVideoStream() {
147 CreateAudioStream();
148 CreateVideoStream();
151 void InitializeWithAudio() {
152 CreateAudioStream();
153 SetAudioRendererInitializeExpectations(PIPELINE_OK);
154 InitializeAndExpect(PIPELINE_OK);
157 void InitializeWithVideo() {
158 CreateVideoStream();
159 SetVideoRendererInitializeExpectations(PIPELINE_OK);
160 InitializeAndExpect(PIPELINE_OK);
163 void InitializeWithAudioAndVideo() {
164 CreateAudioAndVideoStream();
165 SetAudioRendererInitializeExpectations(PIPELINE_OK);
166 SetVideoRendererInitializeExpectations(PIPELINE_OK);
167 InitializeAndExpect(PIPELINE_OK);
170 void Play() {
171 DCHECK(audio_stream_ || video_stream_);
172 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
174 base::TimeDelta start_time(
175 base::TimeDelta::FromMilliseconds(kStartPlayingTimeInMs));
176 EXPECT_CALL(time_source_, SetMediaTime(start_time));
177 EXPECT_CALL(time_source_, StartTicking());
179 if (audio_stream_) {
180 EXPECT_CALL(*audio_renderer_, StartPlaying())
181 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
182 BUFFERING_HAVE_ENOUGH));
185 if (video_stream_) {
186 EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time))
187 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
188 BUFFERING_HAVE_ENOUGH));
191 renderer_impl_->StartPlayingFrom(start_time);
192 base::RunLoop().RunUntilIdle();
195 void Flush(bool underflowed) {
196 if (!underflowed)
197 EXPECT_CALL(time_source_, StopTicking());
199 if (audio_stream_) {
200 EXPECT_CALL(*audio_renderer_, Flush(_))
201 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
202 BUFFERING_HAVE_NOTHING),
203 RunClosure<0>()));
206 if (video_stream_) {
207 EXPECT_CALL(*video_renderer_, Flush(_))
208 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
209 BUFFERING_HAVE_NOTHING),
210 RunClosure<0>()));
213 EXPECT_CALL(callbacks_, OnFlushed());
215 renderer_impl_->Flush(
216 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
217 base::RunLoop().RunUntilIdle();
220 void SetPlaybackRate(double playback_rate) {
221 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
222 renderer_impl_->SetPlaybackRate(playback_rate);
223 base::RunLoop().RunUntilIdle();
226 int64 GetMediaTimeMs() {
227 return renderer_impl_->GetMediaTime().InMilliseconds();
230 bool IsMediaTimeAdvancing(double playback_rate) {
231 int64 start_time_ms = GetMediaTimeMs();
232 const int64 time_to_advance_ms = 100;
234 test_tick_clock_.Advance(
235 base::TimeDelta::FromMilliseconds(time_to_advance_ms));
237 if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
238 return true;
240 DCHECK_EQ(start_time_ms, GetMediaTimeMs());
241 return false;
244 bool IsMediaTimeAdvancing() {
245 return IsMediaTimeAdvancing(1.0);
248 // Fixture members.
249 base::MessageLoop message_loop_;
250 StrictMock<CallbackHelper> callbacks_;
251 base::SimpleTestTickClock test_tick_clock_;
253 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
254 StrictMock<MockVideoRenderer>* video_renderer_;
255 StrictMock<MockAudioRenderer>* audio_renderer_;
256 scoped_ptr<RendererImpl> renderer_impl_;
258 StrictMock<MockTimeSource> time_source_;
259 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
260 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
261 MockDemuxerStreamVector streams_;
262 BufferingStateCB audio_buffering_state_cb_;
263 BufferingStateCB video_buffering_state_cb_;
264 base::Closure audio_ended_cb_;
265 base::Closure video_ended_cb_;
266 PipelineStatusCB audio_error_cb_;
267 VideoDecoderConfig video_decoder_config_;
269 private:
270 DISALLOW_COPY_AND_ASSIGN(RendererImplTest);
273 TEST_F(RendererImplTest, DestroyBeforeInitialize) {
274 // |renderer_impl_| will be destroyed in the dtor.
277 TEST_F(RendererImplTest, InitializeWithAudio) {
278 InitializeWithAudio();
281 TEST_F(RendererImplTest, InitializeWithVideo) {
282 InitializeWithVideo();
285 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
286 InitializeWithAudioAndVideo();
289 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
290 CreateAudioStream();
291 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
292 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
295 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
296 CreateVideoStream();
297 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
298 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
301 TEST_F(RendererImplTest, InitializeWithAudioVideo_AudioRendererFailed) {
302 CreateAudioAndVideoStream();
303 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
304 // VideoRenderer::Initialize() should not be called.
305 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
308 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
309 CreateAudioAndVideoStream();
310 SetAudioRendererInitializeExpectations(PIPELINE_OK);
311 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
312 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
315 TEST_F(RendererImplTest, StartPlayingFrom) {
316 InitializeWithAudioAndVideo();
317 Play();
320 TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) {
321 InitializeWithAudioAndVideo();
323 // Play with a zero playback rate shouldn't start time.
324 Play();
325 Mock::VerifyAndClearExpectations(video_renderer_);
327 // Positive playback rate when ticking should start time.
328 EXPECT_CALL(*video_renderer_, OnTimeStateChanged(true));
329 SetPlaybackRate(1.0);
330 Mock::VerifyAndClearExpectations(video_renderer_);
332 // Double notifications shouldn't be sent.
333 SetPlaybackRate(1.0);
334 Mock::VerifyAndClearExpectations(video_renderer_);
336 // Zero playback rate should stop time.
337 EXPECT_CALL(*video_renderer_, OnTimeStateChanged(false));
338 SetPlaybackRate(0.0);
339 Mock::VerifyAndClearExpectations(video_renderer_);
341 // Double notifications shouldn't be sent.
342 SetPlaybackRate(0.0);
343 Mock::VerifyAndClearExpectations(video_renderer_);
345 // Starting playback and flushing should cause time to stop.
346 EXPECT_CALL(*video_renderer_, OnTimeStateChanged(true));
347 EXPECT_CALL(*video_renderer_, OnTimeStateChanged(false));
348 SetPlaybackRate(1.0);
349 Flush(false);
351 // A positive playback rate when playback isn't started should do nothing.
352 SetPlaybackRate(1.0);
355 TEST_F(RendererImplTest, FlushAfterInitialization) {
356 InitializeWithAudioAndVideo();
357 Flush(true);
360 TEST_F(RendererImplTest, FlushAfterPlay) {
361 InitializeWithAudioAndVideo();
362 Play();
363 Flush(false);
366 TEST_F(RendererImplTest, FlushAfterUnderflow) {
367 InitializeWithAudioAndVideo();
368 Play();
370 // Simulate underflow.
371 EXPECT_CALL(time_source_, StopTicking());
372 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
374 // Flush while underflowed. We shouldn't call StopTicking() again.
375 Flush(true);
378 TEST_F(RendererImplTest, SetPlaybackRate) {
379 InitializeWithAudioAndVideo();
380 SetPlaybackRate(1.0);
381 SetPlaybackRate(2.0);
384 TEST_F(RendererImplTest, SetVolume) {
385 InitializeWithAudioAndVideo();
386 EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
387 renderer_impl_->SetVolume(2.0f);
390 TEST_F(RendererImplTest, AudioStreamEnded) {
391 InitializeWithAudio();
392 Play();
394 EXPECT_CALL(time_source_, StopTicking());
395 EXPECT_CALL(callbacks_, OnEnded());
397 audio_ended_cb_.Run();
398 base::RunLoop().RunUntilIdle();
401 TEST_F(RendererImplTest, VideoStreamEnded) {
402 InitializeWithVideo();
403 Play();
405 EXPECT_CALL(time_source_, StopTicking());
406 EXPECT_CALL(callbacks_, OnEnded());
408 video_ended_cb_.Run();
409 base::RunLoop().RunUntilIdle();
412 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
413 InitializeWithAudioAndVideo();
414 Play();
416 // OnEnded() is called only when all streams have finished.
417 audio_ended_cb_.Run();
418 base::RunLoop().RunUntilIdle();
420 EXPECT_CALL(time_source_, StopTicking());
421 EXPECT_CALL(callbacks_, OnEnded());
423 video_ended_cb_.Run();
424 base::RunLoop().RunUntilIdle();
427 TEST_F(RendererImplTest, ErrorAfterInitialize) {
428 InitializeWithAudio();
429 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
430 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
431 base::RunLoop().RunUntilIdle();
434 TEST_F(RendererImplTest, ErrorDuringPlaying) {
435 InitializeWithAudio();
436 Play();
438 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
439 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
440 base::RunLoop().RunUntilIdle();
443 TEST_F(RendererImplTest, ErrorDuringFlush) {
444 InitializeWithAudio();
445 Play();
447 InSequence s;
448 EXPECT_CALL(time_source_, StopTicking());
449 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
450 AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
451 RunClosure<0>()));
452 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
453 EXPECT_CALL(callbacks_, OnFlushed());
454 renderer_impl_->Flush(
455 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
456 base::RunLoop().RunUntilIdle();
459 TEST_F(RendererImplTest, ErrorAfterFlush) {
460 InitializeWithAudio();
461 Play();
462 Flush(false);
464 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
465 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
466 base::RunLoop().RunUntilIdle();
469 TEST_F(RendererImplTest, ErrorDuringInitialize) {
470 CreateAudioAndVideoStream();
471 SetAudioRendererInitializeExpectations(PIPELINE_OK);
473 // Force an audio error to occur during video renderer initialization.
474 EXPECT_CALL(*video_renderer_,
475 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _))
476 .WillOnce(DoAll(AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
477 SaveArg<4>(&video_buffering_state_cb_),
478 SaveArg<5>(&video_ended_cb_),
479 RunCallback<1>(PIPELINE_OK)));
481 InitializeAndExpect(PIPELINE_ERROR_DECODE);
484 TEST_F(RendererImplTest, AudioUnderflow) {
485 InitializeWithAudio();
486 Play();
488 // Underflow should occur immediately with a single audio track.
489 EXPECT_CALL(time_source_, StopTicking());
490 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
493 TEST_F(RendererImplTest, AudioUnderflowWithVideo) {
494 InitializeWithAudioAndVideo();
495 Play();
497 // Underflow should be immediate when both audio and video are present and
498 // audio underflows.
499 EXPECT_CALL(time_source_, StopTicking());
500 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
503 TEST_F(RendererImplTest, VideoUnderflow) {
504 InitializeWithVideo();
505 Play();
507 // Underflow should occur immediately with a single video track.
508 EXPECT_CALL(time_source_, StopTicking());
509 video_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
512 TEST_F(RendererImplTest, VideoUnderflowWithAudio) {
513 InitializeWithAudioAndVideo();
514 Play();
516 // Set a zero threshold such that the underflow will be executed on the next
517 // run of the message loop.
518 renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
520 // Underflow should be delayed when both audio and video are present and video
521 // underflows.
522 video_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
523 Mock::VerifyAndClearExpectations(&time_source_);
525 EXPECT_CALL(time_source_, StopTicking());
526 base::RunLoop().RunUntilIdle();
529 TEST_F(RendererImplTest, VideoUnderflowWithAudioVideoRecovers) {
530 InitializeWithAudioAndVideo();
531 Play();
533 // Set a zero threshold such that the underflow will be executed on the next
534 // run of the message loop.
535 renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
537 // Underflow should be delayed when both audio and video are present and video
538 // underflows.
539 video_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
540 Mock::VerifyAndClearExpectations(&time_source_);
542 // If video recovers, the underflow should never occur.
543 video_buffering_state_cb_.Run(BUFFERING_HAVE_ENOUGH);
544 base::RunLoop().RunUntilIdle();
547 TEST_F(RendererImplTest, VideoAndAudioUnderflow) {
548 InitializeWithAudioAndVideo();
549 Play();
551 // Set a zero threshold such that the underflow will be executed on the next
552 // run of the message loop.
553 renderer_impl_->set_video_underflow_threshold_for_testing(base::TimeDelta());
555 // Underflow should be delayed when both audio and video are present and video
556 // underflows.
557 video_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
558 Mock::VerifyAndClearExpectations(&time_source_);
560 EXPECT_CALL(time_source_, StopTicking());
561 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
563 // Nothing else should primed on the message loop.
564 base::RunLoop().RunUntilIdle();
567 TEST_F(RendererImplTest, VideoUnderflowWithAudioFlush) {
568 InitializeWithAudioAndVideo();
569 Play();
571 // Set a massive threshold such that it shouldn't fire within this test.
572 renderer_impl_->set_video_underflow_threshold_for_testing(
573 base::TimeDelta::FromSeconds(100));
575 // Simulate the cases where audio underflows and then video underflows.
576 EXPECT_CALL(time_source_, StopTicking());
577 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
578 video_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
579 Mock::VerifyAndClearExpectations(&time_source_);
581 // Flush the audio and video renderers, both think they're in an underflow
582 // state, but if the video renderer underflow was deferred, RendererImpl would
583 // think it still has enough data.
584 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>());
585 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>());
586 EXPECT_CALL(callbacks_, OnFlushed());
587 renderer_impl_->Flush(
588 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
589 base::RunLoop().RunUntilIdle();
591 // Start playback after the flush, but never return BUFFERING_HAVE_ENOUGH from
592 // the video renderer (which simulates spool up time for the video renderer).
593 const base::TimeDelta kStartTime;
594 EXPECT_CALL(time_source_, SetMediaTime(kStartTime));
595 EXPECT_CALL(*audio_renderer_, StartPlaying())
596 .WillOnce(
597 SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_ENOUGH));
598 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime));
599 renderer_impl_->StartPlayingFrom(kStartTime);
601 // Nothing else should primed on the message loop.
602 base::RunLoop().RunUntilIdle();
605 } // namespace media