Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / filters / renderer_impl_unittest.cc
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.
4
5 #include <vector>
6
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/filters/renderer_impl.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
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;
24
25 namespace media {
26
27 const int64 kStartPlayingTimeInMs = 100;
28
29 ACTION_P2(SetBufferingState, cb, buffering_state) {
30   cb->Run(buffering_state);
31 }
32
33 ACTION_P2(AudioError, cb, error) {
34   cb->Run(error);
35 }
36
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() {}
45
46     MOCK_METHOD0(OnInitialize, void());
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
53    private:
54     DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
55   };
56
57   RendererImplTest()
58       : demuxer_(new StrictMock<MockDemuxer>()),
59         video_renderer_(new StrictMock<MockVideoRenderer>()),
60         audio_renderer_(new StrictMock<MockAudioRenderer>()),
61         renderer_impl_(
62             new RendererImpl(message_loop_.message_loop_proxy(),
63                              demuxer_.get(),
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));
71     EXPECT_CALL(*demuxer_, GetLiveness())
72         .WillRepeatedly(Return(Demuxer::LIVENESS_UNKNOWN));
73   }
74
75   virtual ~RendererImplTest() {
76     renderer_impl_.reset();
77     base::RunLoop().RunUntilIdle();
78   }
79
80  protected:
81   typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
82
83   scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream(
84       DemuxerStream::Type type) {
85     scoped_ptr<StrictMock<MockDemuxerStream> > stream(
86         new StrictMock<MockDemuxerStream>(type));
87     return stream.Pass();
88   }
89
90   // Sets up expectations to allow the audio renderer to initialize.
91   void SetAudioRendererInitializeExpectations(PipelineStatus status) {
92     EXPECT_CALL(*audio_renderer_,
93                 Initialize(audio_stream_.get(), _,  _, _, _, _))
94         .WillOnce(DoAll(SaveArg<3>(&audio_buffering_state_cb_),
95                         SaveArg<4>(&audio_ended_cb_),
96                         SaveArg<5>(&audio_error_cb_),
97                         RunCallback<1>(status)));
98   }
99
100   // Sets up expectations to allow the video renderer to initialize.
101   void SetVideoRendererInitializeExpectations(PipelineStatus status) {
102     EXPECT_CALL(*video_renderer_,
103                 Initialize(video_stream_.get(), _, _, _, _, _, _, _))
104         .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_),
105                         SaveArg<5>(&video_ended_cb_),
106                         RunCallback<2>(status)));
107   }
108
109   void InitializeAndExpect(PipelineStatus start_status) {
110     if (start_status != PIPELINE_OK)
111       EXPECT_CALL(callbacks_, OnError(start_status));
112
113     EXPECT_CALL(callbacks_, OnInitialize());
114
115     if (start_status == PIPELINE_OK && audio_stream_) {
116       EXPECT_CALL(*audio_renderer_, GetTimeSource())
117           .WillOnce(Return(&time_source_));
118     }
119
120     renderer_impl_->Initialize(
121         base::Bind(&CallbackHelper::OnInitialize,
122                    base::Unretained(&callbacks_)),
123         base::Bind(&CallbackHelper::OnUpdateStatistics,
124                    base::Unretained(&callbacks_)),
125         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
126         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
127         base::Bind(&CallbackHelper::OnBufferingStateChange,
128                    base::Unretained(&callbacks_)));
129     base::RunLoop().RunUntilIdle();
130   }
131
132   void CreateAudioStream() {
133     audio_stream_ = CreateStream(DemuxerStream::AUDIO);
134     streams_.push_back(audio_stream_.get());
135     EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO))
136         .WillRepeatedly(Return(audio_stream_.get()));
137   }
138
139   void CreateVideoStream() {
140     video_stream_ = CreateStream(DemuxerStream::VIDEO);
141     video_stream_->set_video_decoder_config(video_decoder_config_);
142     streams_.push_back(video_stream_.get());
143     EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO))
144         .WillRepeatedly(Return(video_stream_.get()));
145   }
146
147   void CreateAudioAndVideoStream() {
148     CreateAudioStream();
149     CreateVideoStream();
150   }
151
152   void InitializeWithAudio() {
153     CreateAudioStream();
154     SetAudioRendererInitializeExpectations(PIPELINE_OK);
155     InitializeAndExpect(PIPELINE_OK);
156   }
157
158   void InitializeWithVideo() {
159     CreateVideoStream();
160     SetVideoRendererInitializeExpectations(PIPELINE_OK);
161     InitializeAndExpect(PIPELINE_OK);
162   }
163
164   void InitializeWithAudioAndVideo() {
165     CreateAudioAndVideoStream();
166     SetAudioRendererInitializeExpectations(PIPELINE_OK);
167     SetVideoRendererInitializeExpectations(PIPELINE_OK);
168     InitializeAndExpect(PIPELINE_OK);
169   }
170
171   void Play() {
172     DCHECK(audio_stream_ || video_stream_);
173     EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
174
175     base::TimeDelta start_time(
176         base::TimeDelta::FromMilliseconds(kStartPlayingTimeInMs));
177
178     if (audio_stream_) {
179       EXPECT_CALL(time_source_, SetMediaTime(start_time));
180       EXPECT_CALL(time_source_, StartTicking());
181       EXPECT_CALL(*audio_renderer_, StartPlaying())
182           .WillOnce(SetBufferingState(&audio_buffering_state_cb_,
183                                       BUFFERING_HAVE_ENOUGH));
184     }
185
186     if (video_stream_) {
187       EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time))
188           .WillOnce(SetBufferingState(&video_buffering_state_cb_,
189                                       BUFFERING_HAVE_ENOUGH));
190     }
191
192     renderer_impl_->StartPlayingFrom(start_time);
193     base::RunLoop().RunUntilIdle();
194   }
195
196   void Flush(bool underflowed) {
197     if (audio_stream_) {
198       if (!underflowed)
199         EXPECT_CALL(time_source_, StopTicking());
200       EXPECT_CALL(*audio_renderer_, Flush(_))
201           .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_,
202                                             BUFFERING_HAVE_NOTHING),
203                           RunClosure<0>()));
204     }
205
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>()));
211     }
212
213     EXPECT_CALL(callbacks_, OnFlushed());
214
215     renderer_impl_->Flush(
216         base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
217     base::RunLoop().RunUntilIdle();
218   }
219
220   void SetPlaybackRate(float playback_rate) {
221     EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate));
222     renderer_impl_->SetPlaybackRate(playback_rate);
223     base::RunLoop().RunUntilIdle();
224   }
225
226   int64 GetMediaTimeMs() {
227     return renderer_impl_->GetMediaTime().InMilliseconds();
228   }
229
230   bool IsMediaTimeAdvancing(float playback_rate) {
231     int64 start_time_ms = GetMediaTimeMs();
232     const int64 time_to_advance_ms = 100;
233
234     test_tick_clock_.Advance(
235         base::TimeDelta::FromMilliseconds(time_to_advance_ms));
236
237     if (GetMediaTimeMs() == start_time_ms + time_to_advance_ms * playback_rate)
238       return true;
239
240     DCHECK_EQ(start_time_ms, GetMediaTimeMs());
241     return false;
242   }
243
244   bool IsMediaTimeAdvancing() {
245     return IsMediaTimeAdvancing(1.0f);
246   }
247
248   // Fixture members.
249   base::MessageLoop message_loop_;
250   StrictMock<CallbackHelper> callbacks_;
251   base::SimpleTestTickClock test_tick_clock_;
252
253   scoped_ptr<StrictMock<MockDemuxer> > demuxer_;
254   StrictMock<MockVideoRenderer>* video_renderer_;
255   StrictMock<MockAudioRenderer>* audio_renderer_;
256   scoped_ptr<RendererImpl> renderer_impl_;
257
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_;
268
269  private:
270   DISALLOW_COPY_AND_ASSIGN(RendererImplTest);
271 };
272
273 TEST_F(RendererImplTest, DestroyBeforeInitialize) {
274   // |renderer_impl_| will be destroyed in the dtor.
275 }
276
277 TEST_F(RendererImplTest, InitializeWithAudio) {
278   InitializeWithAudio();
279 }
280
281 TEST_F(RendererImplTest, InitializeWithVideo) {
282   InitializeWithVideo();
283 }
284
285 TEST_F(RendererImplTest, InitializeWithAudioVideo) {
286   InitializeWithAudioAndVideo();
287 }
288
289 TEST_F(RendererImplTest, InitializeWithAudio_Failed) {
290   CreateAudioStream();
291   SetAudioRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
292   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
293 }
294
295 TEST_F(RendererImplTest, InitializeWithVideo_Failed) {
296   CreateVideoStream();
297   SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
298   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
299 }
300
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);
306 }
307
308 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) {
309   CreateAudioAndVideoStream();
310   SetAudioRendererInitializeExpectations(PIPELINE_OK);
311   SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED);
312   InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED);
313 }
314
315 TEST_F(RendererImplTest, StartPlayingFrom) {
316   InitializeWithAudioAndVideo();
317   Play();
318 }
319
320 TEST_F(RendererImplTest, FlushAfterInitialization) {
321   InitializeWithAudioAndVideo();
322   Flush(true);
323 }
324
325 TEST_F(RendererImplTest, FlushAfterPlay) {
326   InitializeWithAudioAndVideo();
327   Play();
328   Flush(false);
329 }
330
331 TEST_F(RendererImplTest, FlushAfterUnderflow) {
332   InitializeWithAudioAndVideo();
333   Play();
334
335   // Simulate underflow.
336   EXPECT_CALL(time_source_, StopTicking());
337   audio_buffering_state_cb_.Run(BUFFERING_HAVE_NOTHING);
338
339   // Flush while underflowed. We shouldn't call StopTicking() again.
340   Flush(true);
341 }
342
343 TEST_F(RendererImplTest, SetPlaybackRate) {
344   InitializeWithAudioAndVideo();
345   SetPlaybackRate(1.0f);
346   SetPlaybackRate(2.0f);
347 }
348
349 TEST_F(RendererImplTest, SetVolume) {
350   InitializeWithAudioAndVideo();
351   EXPECT_CALL(*audio_renderer_, SetVolume(2.0f));
352   renderer_impl_->SetVolume(2.0f);
353 }
354
355 TEST_F(RendererImplTest, AudioStreamEnded) {
356   InitializeWithAudio();
357   Play();
358
359   EXPECT_CALL(time_source_, StopTicking());
360   EXPECT_CALL(callbacks_, OnEnded());
361
362   audio_ended_cb_.Run();
363   base::RunLoop().RunUntilIdle();
364 }
365
366 TEST_F(RendererImplTest, VideoStreamEnded) {
367   InitializeWithVideo();
368   Play();
369
370   // Video ended won't affect |time_source_|.
371   EXPECT_CALL(callbacks_, OnEnded());
372
373   video_ended_cb_.Run();
374   base::RunLoop().RunUntilIdle();
375 }
376
377 TEST_F(RendererImplTest, AudioVideoStreamsEnded) {
378   InitializeWithAudioAndVideo();
379   Play();
380
381   // OnEnded() is called only when all streams have finished.
382   audio_ended_cb_.Run();
383   base::RunLoop().RunUntilIdle();
384
385   EXPECT_CALL(time_source_, StopTicking());
386   EXPECT_CALL(callbacks_, OnEnded());
387
388   video_ended_cb_.Run();
389   base::RunLoop().RunUntilIdle();
390 }
391
392 TEST_F(RendererImplTest, ErrorAfterInitialize) {
393   InitializeWithAudio();
394   EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
395   audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
396   base::RunLoop().RunUntilIdle();
397 }
398
399 TEST_F(RendererImplTest, ErrorDuringPlaying) {
400   InitializeWithAudio();
401   Play();
402
403   EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
404   audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
405   base::RunLoop().RunUntilIdle();
406 }
407
408 TEST_F(RendererImplTest, ErrorDuringFlush) {
409   InitializeWithAudio();
410   Play();
411
412   InSequence s;
413   EXPECT_CALL(time_source_, StopTicking());
414   EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(DoAll(
415       AudioError(&audio_error_cb_, PIPELINE_ERROR_DECODE),
416       RunClosure<0>()));
417   EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
418   EXPECT_CALL(callbacks_, OnFlushed());
419   renderer_impl_->Flush(
420       base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_)));
421   base::RunLoop().RunUntilIdle();
422 }
423
424 TEST_F(RendererImplTest, ErrorAfterFlush) {
425   InitializeWithAudio();
426   Play();
427   Flush(false);
428
429   EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_DECODE));
430   audio_error_cb_.Run(PIPELINE_ERROR_DECODE);
431   base::RunLoop().RunUntilIdle();
432 }
433
434 }  // namespace media