InputImeEventRouter::RegisterImeExtension should register extensions
[chromium-blink-merge.git] / media / filters / renderer_impl_unittest.cc
blob7e0b1cba10adac1cc4357dbec62a5a03a76ac166
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/base/time_delta_interpolator.h"
15 #include "media/filters/renderer_impl.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using ::testing::_;
19 using ::testing::DoAll;
20 using ::testing::InSequence;
21 using ::testing::Mock;
22 using ::testing::Return;
23 using ::testing::SaveArg;
24 using ::testing::StrictMock;
26 namespace media {
28 const int64 kStartPlayingTimeInMs = 100;
29 const int64 kDurationInMs = 3000;
30 const int64 kAudioUpdateTimeMs = 150;
31 const int64 kAudioUpdateMaxTimeMs = 1000;
33 ACTION_P2(SetBufferingState, cb, buffering_state) {
34 cb->Run(buffering_state);
37 ACTION_P3(UpdateAudioTime, cb, time, max_time) {
38 cb->Run(base::TimeDelta::FromMilliseconds(time),
39 base::TimeDelta::FromMilliseconds(max_time));
42 ACTION_P2(AudioError, cb, error) {
43 cb->Run(error);
46 static base::TimeDelta GetDuration() {
47 return base::TimeDelta::FromMilliseconds(kDurationInMs);
50 class RendererImplTest : public ::testing::Test {
51 public:
52 // Used for setting expectations on pipeline callbacks. Using a StrictMock
53 // also lets us test for missing callbacks.
54 class CallbackHelper {
55 public:
56 CallbackHelper() {}
57 virtual ~CallbackHelper() {}
59 MOCK_METHOD1(OnInitialize, void(PipelineStatus));
60 MOCK_METHOD0(OnFlushed, void());
61 MOCK_METHOD0(OnEnded, void());
62 MOCK_METHOD1(OnError, void(PipelineStatus));
63 MOCK_METHOD1(OnUpdateStatistics, void(const PipelineStatistics&));
64 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
66 private:
67 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
70 RendererImplTest()
71 : demuxer_(new StrictMock<MockDemuxer>()),
72 video_renderer_(new StrictMock<MockVideoRenderer>()),
73 audio_renderer_(new StrictMock<MockAudioRenderer>()),
74 renderer_impl_(
75 new RendererImpl(message_loop_.message_loop_proxy(),
76 demuxer_.get(),
77 scoped_ptr<AudioRenderer>(audio_renderer_),
78 scoped_ptr<VideoRenderer>(video_renderer_))) {
79 // SetDemuxerExpectations() adds overriding expectations for expected
80 // non-NULL streams.
81 DemuxerStream* null_pointer = NULL;
82 EXPECT_CALL(*demuxer_, GetStream(_))
83 .WillRepeatedly(Return(null_pointer));
84 EXPECT_CALL(*demuxer_, GetLiveness())
85 .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
88 virtual ~RendererImplTest() {
89 renderer_impl_.reset();
90 base::RunLoop().RunUntilIdle();
93 protected:
94 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
96 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
97 DemuxerStream::Type type) {
98 scoped_ptr<StrictMock<MockDemuxerStream> > stream(
99 new StrictMock<MockDemuxerStream>(type));
100 return stream.Pass();
103 // Sets up expectations to allow the audio renderer to initialize.
104 void SetAudioRendererInitializeExpectations(PipelineStatus status) {
105 EXPECT_CALL(*audio_renderer_,
106 Initialize(audio_stream_.get(), _, _, _, _, _, _))
107 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_),
108 SaveArg<4>(&audio_buffering_state_cb_),
109 SaveArg<5>(&audio_ended_cb_),
110 SaveArg<6>(&audio_error_cb_),
111 RunCallback<1>(status)));
112 if (status == PIPELINE_OK) {
113 EXPECT_CALL(*audio_renderer_, GetTimeSource())
114 .WillOnce(Return(&time_source_));
118 // Sets up expectations to allow the video renderer to initialize.
119 void SetVideoRendererInitializeExpectations(PipelineStatus status) {
120 EXPECT_CALL(*video_renderer_,
121 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _, _))
122 .WillOnce(DoAll(SaveArg<5>(&video_buffering_state_cb_),
123 SaveArg<6>(&video_ended_cb_),
124 RunCallback<2>(status)));
127 void InitializeAndExpect(PipelineStatus start_status) {
128 EXPECT_CALL(callbacks_, OnInitialize(start_status));
130 renderer_impl_->Initialize(
131 base::Bind(&CallbackHelper::OnInitialize,
132 base::Unretained(&callbacks_)),
133 base::Bind(&CallbackHelper::OnUpdateStatistics,
134 base::Unretained(&callbacks_)),
135 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
136 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
137 base::Bind(&CallbackHelper::OnBufferingStateChange,
138 base::Unretained(&callbacks_)),
139 base::Bind(&GetDuration));
140 base::RunLoop().RunUntilIdle();
143 void CreateAudioStream() {
144 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
145 streams_.push_back(audio_stream_.get());
146 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
147 .WillRepeatedly(Return(audio_stream_.get()));
150 void CreateVideoStream() {
151 video_stream_ = CreateStream(DemuxerStream::VIDEO);
152 video_stream_->set_video_decoder_config(video_decoder_config_);
153 streams_.push_back(video_stream_.get());
154 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
155 .WillRepeatedly(Return(video_stream_.get()));
158 void CreateAudioAndVideoStream() {
159 CreateAudioStream();
160 CreateVideoStream();
163 void InitializeWithAudio() {
164 CreateAudioStream();
165 SetAudioRendererInitializeExpectations(PIPELINE_OK);
166 InitializeAndExpect(PIPELINE_OK);
169 void InitializeWithVideo() {
170 CreateVideoStream();
171 SetVideoRendererInitializeExpectations(PIPELINE_OK);
172 InitializeAndExpect(PIPELINE_OK);
175 void InitializeWithAudioAndVideo() {
176 CreateAudioAndVideoStream();
177 SetAudioRendererInitializeExpectations(PIPELINE_OK);
178 SetVideoRendererInitializeExpectations(PIPELINE_OK);
179 InitializeAndExpect(PIPELINE_OK);
182 void Play() {
183 DCHECK(audio_stream_ || video_stream_);
184 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
186 if (audio_stream_) {
187 EXPECT_CALL(time_source_,
188 SetMediaTime(base::TimeDelta::FromMilliseconds(
189 kStartPlayingTimeInMs)));
190 EXPECT_CALL(time_source_, StartTicking());
191 EXPECT_CALL(*audio_renderer_, StartPlaying())
192 .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
193 BUFFERING_HAVE_ENOUGH));
196 if (video_stream_) {
197 EXPECT_CALL(*video_renderer_, StartPlaying())
198 .WillOnce(SetBufferingState(&video_buffering_state_cb_,
199 BUFFERING_HAVE_ENOUGH));
202 renderer_impl_->StartPlayingFrom(
203 base::TimeDelta::FromMilliseconds(kStartPlayingTimeInMs));
204 base::RunLoop().RunUntilIdle();
207 void Flush(bool underflowed) {
208 if (audio_stream_) {
209 if (!underflowed)
210 EXPECT_CALL(time_source_, StopTicking());
211 EXPECT_CALL(*audio_renderer_, Flush(_))
212 .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
213 BUFFERING_HAVE_NOTHING),
214 RunClosure<0>()));
217 if (video_stream_) {
218 EXPECT_CALL(*video_renderer_, Flush(_))
219 .WillOnce(DoAll(SetBufferingState(&video_buffering_state_cb_,
220 BUFFERING_HAVE_NOTHING),
221 RunClosure<0>()));
224 EXPECT_CALL(callbacks_, OnFlushed());
226 renderer_impl_->Flush(
227 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
228 base::RunLoop().RunUntilIdle();
231 void SetPlaybackRate(float playback_rate) {
232 EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
233 renderer_impl_->SetPlaybackRate(playback_rate);
234 base::RunLoop().RunUntilIdle();
237 int64 GetMediaTimeMs() {
238 return renderer_impl_->GetMediaTime().InMilliseconds();
241 bool IsMediaTimeAdvancing(float playback_rate) {
242 int64 start_time_ms = GetMediaTimeMs();
243 const int64 time_to_advance_ms = 100;
245 test_tick_clock_.Advance(
246 base::TimeDelta::FromMilliseconds(time_to_advance_ms));
248 if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
249 return true;
251 DCHECK_EQ(start_time_ms, GetMediaTimeMs());
252 return false;
255 bool IsMediaTimeAdvancing() {
256 return IsMediaTimeAdvancing(1.0f);
259 // Fixture members.
260 base::MessageLoop message_loop_;
261 StrictMock<CallbackHelper> callbacks_;
262 base::SimpleTestTickClock test_tick_clock_;
264 scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
265 StrictMock<MockVideoRenderer>* video_renderer_;
266 StrictMock<MockAudioRenderer>* audio_renderer_;
267 scoped_ptr<RendererImpl> renderer_impl_;
269 StrictMock<MockTimeSource> time_source_;
270 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_;
271 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_;
272 MockDemuxerStreamVector streams_;
273 AudioRenderer::TimeCB audio_time_cb_;
274 BufferingStateCB audio_buffering_state_cb_;
275 BufferingStateCB video_buffering_state_cb_;
276 base::Closure audio_ended_cb_;
277 base::Closure video_ended_cb_;
278 PipelineStatusCB audio_error_cb_;
279 VideoDecoderConfig video_decoder_config_;
281 private:
282 DISALLOW_COPY_AND_ASSIGN(RendererImplTest);
285 TEST_F(RendererImplTest, DestroyBeforeInitialize) {
286 // |renderer_impl_| will be destroyed in the dtor.
289 TEST_F(RendererImplTest, InitializeWithAudio) {
290 InitializeWithAudio();
293 TEST_F(RendererImplTest, InitializeWithVideo) {
294 InitializeWithVideo();
297 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
298 InitializeWithAudioAndVideo();
301 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
302 CreateAudioStream();
303 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
304 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
307 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
308 CreateVideoStream();
309 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
310 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
313 TEST_F(RendererImplTest, InitializeWithAudioVideo_AudioRendererFailed) {
314 CreateAudioAndVideoStream();
315 SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
316 // VideoRenderer::Initialize() should not be called.
317 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
320 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
321 CreateAudioAndVideoStream();
322 SetAudioRendererInitializeExpectations(PIPELINE_OK);
323 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
324 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
327 TEST_F(RendererImplTest, StartPlayingFrom) {
328 InitializeWithAudioAndVideo();
329 Play();
332 TEST_F(RendererImplTest, FlushAfterInitialization) {
333 InitializeWithAudioAndVideo();
334 Flush(true);
337 TEST_F(RendererImplTest, FlushAfterPlay) {
338 InitializeWithAudioAndVideo();
339 Play();
340 Flush(false);
343 TEST_F(RendererImplTest, FlushAfterUnderflow) {
344 InitializeWithAudioAndVideo();
345 Play();
347 // Simulate underflow.
348 EXPECT_CALL(time_source_, StopTicking());
349 audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
351 // Flush while underflowed. We shouldn't call StopTicking() again.
352 Flush(true);
355 TEST_F(RendererImplTest, SetPlaybackRate) {
356 InitializeWithAudioAndVideo();
357 SetPlaybackRate(1.0f);
358 SetPlaybackRate(2.0f);
361 TEST_F(RendererImplTest, SetVolume) {
362 InitializeWithAudioAndVideo();
363 EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
364 renderer_impl_->SetVolume(2.0f);
367 TEST_F(RendererImplTest, GetMediaTime) {
368 // Replace what's used for interpolating to simulate wall clock time.
369 renderer_impl_->SetTimeDeltaInterpolatorForTesting(
370 new TimeDeltaInterpolator(&test_tick_clock_));
372 InitializeWithAudioAndVideo();
373 Play();
375 EXPECT_EQ(kStartPlayingTimeInMs, GetMediaTimeMs());
377 // Verify that the clock doesn't advance since it hasn't been started by
378 // a time update from the audio stream.
379 EXPECT_FALSE(IsMediaTimeAdvancing());
381 // Provide an initial time update so that the pipeline transitions out of the
382 // "waiting for time update" state.
383 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(kAudioUpdateTimeMs),
384 base::TimeDelta::FromMilliseconds(kAudioUpdateMaxTimeMs));
385 EXPECT_EQ(kAudioUpdateTimeMs, GetMediaTimeMs());
387 // Advance the clock so that GetMediaTime() also advances. This also verifies
388 // that the default playback rate is 1.
389 EXPECT_TRUE(IsMediaTimeAdvancing());
391 // Verify that playback rate affects the rate GetMediaTime() advances.
392 SetPlaybackRate(2.0f);
393 EXPECT_TRUE(IsMediaTimeAdvancing(2.0f));
395 // Verify that GetMediaTime() is bounded by audio max time.
396 DCHECK_GT(GetMediaTimeMs() + 2000, kAudioUpdateMaxTimeMs);
397 test_tick_clock_.Advance(base::TimeDelta::FromMilliseconds(2000));
398 EXPECT_EQ(kAudioUpdateMaxTimeMs, GetMediaTimeMs());
401 TEST_F(RendererImplTest, AudioStreamShorterThanVideo) {
402 // Replace what's used for interpolating to simulate wall clock time.
403 renderer_impl_->SetTimeDeltaInterpolatorForTesting(
404 new TimeDeltaInterpolator(&test_tick_clock_));
406 InitializeWithAudioAndVideo();
407 Play();
409 EXPECT_EQ(kStartPlayingTimeInMs, GetMediaTimeMs());
411 // Verify that the clock doesn't advance since it hasn't been started by
412 // a time update from the audio stream.
413 EXPECT_FALSE(IsMediaTimeAdvancing());
415 // Signal end of audio stream.
416 audio_ended_cb_.Run();
417 base::RunLoop().RunUntilIdle();
419 // Verify that the clock advances.
420 EXPECT_TRUE(IsMediaTimeAdvancing());
422 // Signal end of video stream and make sure OnEnded() callback occurs.
423 EXPECT_CALL(time_source_, StopTicking());
424 EXPECT_CALL(callbacks_, OnEnded());
425 video_ended_cb_.Run();
426 base::RunLoop().RunUntilIdle();
429 TEST_F(RendererImplTest, AudioTimeUpdateDuringFlush) {
430 // Replace what's used for interpolating to simulate wall clock time.
431 renderer_impl_->SetTimeDeltaInterpolatorForTesting(
432 new TimeDeltaInterpolator(&test_tick_clock_));
434 InitializeWithAudio();
435 Play();
437 // Provide an initial time update so that the pipeline transitions out of the
438 // "waiting for time update" state.
439 audio_time_cb_.Run(base::TimeDelta::FromMilliseconds(kAudioUpdateTimeMs),
440 base::TimeDelta::FromMilliseconds(kAudioUpdateMaxTimeMs));
441 EXPECT_EQ(kAudioUpdateTimeMs, GetMediaTimeMs());
443 int64 start_time = GetMediaTimeMs();
445 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
446 UpdateAudioTime(
447 &audio_time_cb_, kAudioUpdateTimeMs + 100, kAudioUpdateMaxTimeMs),
448 SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_NOTHING),
449 RunClosure<0>()));
450 EXPECT_CALL(time_source_, StopTicking());
451 EXPECT_CALL(callbacks_, OnFlushed());
452 renderer_impl_->Flush(
453 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
455 // Audio time update during Flush() has no effect.
456 EXPECT_EQ(start_time, GetMediaTimeMs());
458 // Verify that the clock doesn't advance since it hasn't been started by
459 // a time update from the audio stream.
460 EXPECT_FALSE(IsMediaTimeAdvancing());
463 TEST_F(RendererImplTest, PostTimeUpdateDuringDestroy) {
464 InitializeWithAudioAndVideo();
466 // Simulate the case where TimeCB is posted during ~AudioRenderer(), which is
467 // triggered in ~Renderer().
468 base::TimeDelta time = base::TimeDelta::FromMilliseconds(100);
469 message_loop_.PostTask(FROM_HERE, base::Bind(audio_time_cb_, time, time));
471 renderer_impl_.reset();
472 message_loop_.RunUntilIdle();
475 TEST_F(RendererImplTest, AudioStreamEnded) {
476 InitializeWithAudio();
477 Play();
479 EXPECT_CALL(time_source_, StopTicking());
480 EXPECT_CALL(callbacks_, OnEnded());
482 audio_ended_cb_.Run();
483 base::RunLoop().RunUntilIdle();
486 TEST_F(RendererImplTest, VideoStreamEnded) {
487 InitializeWithVideo();
488 Play();
490 // Video ended won't affect |time_source_|.
491 EXPECT_CALL(callbacks_, OnEnded());
493 video_ended_cb_.Run();
494 base::RunLoop().RunUntilIdle();
497 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
498 InitializeWithAudioAndVideo();
499 Play();
501 // OnEnded() is called only when all streams have finished.
502 audio_ended_cb_.Run();
503 base::RunLoop().RunUntilIdle();
505 EXPECT_CALL(time_source_, StopTicking());
506 EXPECT_CALL(callbacks_, OnEnded());
508 video_ended_cb_.Run();
509 base::RunLoop().RunUntilIdle();
512 TEST_F(RendererImplTest, ErrorAfterInitialize) {
513 InitializeWithAudio();
514 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
515 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
516 base::RunLoop().RunUntilIdle();
519 TEST_F(RendererImplTest, ErrorDuringPlaying) {
520 InitializeWithAudio();
521 Play();
523 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
524 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
525 base::RunLoop().RunUntilIdle();
528 TEST_F(RendererImplTest, ErrorDuringFlush) {
529 InitializeWithAudio();
530 Play();
532 InSequence s;
533 EXPECT_CALL(time_source_, StopTicking());
534 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
535 AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
536 RunClosure<0>()));
537 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
538 EXPECT_CALL(callbacks_, OnFlushed());
539 renderer_impl_->Flush(
540 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
541 base::RunLoop().RunUntilIdle();
544 TEST_F(RendererImplTest, ErrorAfterFlush) {
545 InitializeWithAudio();
546 Play();
547 Flush(false);
549 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
550 audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
551 base::RunLoop().RunUntilIdle();
554 } // namespace media