Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / filters / pipeline_integration_test_base.cc
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.
4
5 #include "media/filters/pipeline_integration_test_base.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "media/base/media_log.h"
10 #include "media/filters/audio_renderer_impl.h"
11 #include "media/filters/chunk_demuxer.h"
12 #include "media/filters/ffmpeg_audio_decoder.h"
13 #include "media/filters/ffmpeg_demuxer.h"
14 #include "media/filters/ffmpeg_video_decoder.h"
15 #include "media/filters/file_data_source.h"
16 #include "media/filters/opus_audio_decoder.h"
17 #include "media/filters/renderer_impl.h"
18 #include "media/filters/vpx_video_decoder.h"
19
20 using ::testing::_;
21 using ::testing::AnyNumber;
22 using ::testing::AtMost;
23 using ::testing::InvokeWithoutArgs;
24 using ::testing::SaveArg;
25
26 namespace media {
27
28 const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e";
29 const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,";
30
31 PipelineIntegrationTestBase::PipelineIntegrationTestBase()
32     : hashing_enabled_(false),
33       clockless_playback_(false),
34       pipeline_(
35           new Pipeline(message_loop_.message_loop_proxy(), new MediaLog())),
36       ended_(false),
37       pipeline_status_(PIPELINE_OK),
38       last_video_frame_format_(VideoFrame::UNKNOWN),
39       hardware_config_(AudioParameters(), AudioParameters()) {
40   base::MD5Init(&md5_context_);
41 }
42
43 PipelineIntegrationTestBase::~PipelineIntegrationTestBase() {
44   if (!pipeline_->IsRunning())
45     return;
46
47   Stop();
48 }
49
50 void PipelineIntegrationTestBase::SaveStatus(PipelineStatus status) {
51   pipeline_status_ = status;
52 }
53
54 void PipelineIntegrationTestBase::OnStatusCallback(
55     PipelineStatus status) {
56   pipeline_status_ = status;
57   message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
58 }
59
60 void PipelineIntegrationTestBase::OnStatusCallbackChecked(
61     PipelineStatus expected_status,
62     PipelineStatus status) {
63   EXPECT_EQ(expected_status, status);
64   OnStatusCallback(status);
65 }
66
67 PipelineStatusCB PipelineIntegrationTestBase::QuitOnStatusCB(
68     PipelineStatus expected_status) {
69   return base::Bind(&PipelineIntegrationTestBase::OnStatusCallbackChecked,
70                     base::Unretained(this),
71                     expected_status);
72 }
73
74 void PipelineIntegrationTestBase::DemuxerNeedKeyCB(
75     const std::string& type,
76     const std::vector<uint8>& init_data) {
77   DCHECK(!init_data.empty());
78   CHECK(!need_key_cb_.is_null());
79   need_key_cb_.Run(type, init_data);
80 }
81
82 void PipelineIntegrationTestBase::OnEnded() {
83   DCHECK(!ended_);
84   ended_ = true;
85   pipeline_status_ = PIPELINE_OK;
86   message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
87 }
88
89 bool PipelineIntegrationTestBase::WaitUntilOnEnded() {
90   if (ended_)
91     return (pipeline_status_ == PIPELINE_OK);
92   message_loop_.Run();
93   EXPECT_TRUE(ended_);
94   return ended_ && (pipeline_status_ == PIPELINE_OK);
95 }
96
97 PipelineStatus PipelineIntegrationTestBase::WaitUntilEndedOrError() {
98   if (ended_ || pipeline_status_ != PIPELINE_OK)
99     return pipeline_status_;
100   message_loop_.Run();
101   return pipeline_status_;
102 }
103
104 void PipelineIntegrationTestBase::OnError(PipelineStatus status) {
105   DCHECK_NE(status, PIPELINE_OK);
106   pipeline_status_ = status;
107   message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
108 }
109
110 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path,
111                                         PipelineStatus expected_status) {
112   EXPECT_CALL(*this, OnMetadata(_))
113       .Times(AtMost(1))
114       .WillRepeatedly(SaveArg<0>(&metadata_));
115   EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
116       .Times(AtMost(1));
117   CreateDemuxer(file_path);
118   pipeline_->Start(
119       demuxer_.get(),
120       CreateRenderer(NULL),
121       base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
122       base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
123       QuitOnStatusCB(expected_status),
124       base::Bind(&PipelineIntegrationTestBase::OnMetadata,
125                  base::Unretained(this)),
126       base::Bind(&PipelineIntegrationTestBase::OnBufferingStateChanged,
127                  base::Unretained(this)),
128       base::Closure(),
129       base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack,
130                  base::Unretained(this)));
131   message_loop_.Run();
132   return (pipeline_status_ == PIPELINE_OK);
133 }
134
135 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path,
136                                         PipelineStatus expected_status,
137                                         kTestType test_type) {
138   hashing_enabled_ = test_type == kHashed;
139   clockless_playback_ = test_type == kClockless;
140   return Start(file_path, expected_status);
141 }
142
143 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path) {
144   return Start(file_path, NULL);
145 }
146
147 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path,
148                                         Decryptor* decryptor) {
149   EXPECT_CALL(*this, OnMetadata(_))
150       .Times(AtMost(1))
151       .WillRepeatedly(SaveArg<0>(&metadata_));
152   EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
153       .Times(AtMost(1));
154
155   CreateDemuxer(file_path);
156   pipeline_->Start(
157       demuxer_.get(),
158       CreateRenderer(decryptor),
159       base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
160       base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
161       base::Bind(&PipelineIntegrationTestBase::OnStatusCallback,
162                  base::Unretained(this)),
163       base::Bind(&PipelineIntegrationTestBase::OnMetadata,
164                  base::Unretained(this)),
165       base::Bind(&PipelineIntegrationTestBase::OnBufferingStateChanged,
166                  base::Unretained(this)),
167       base::Closure(),
168       base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack,
169                  base::Unretained(this)));
170   message_loop_.Run();
171   return (pipeline_status_ == PIPELINE_OK);
172 }
173
174 void PipelineIntegrationTestBase::Play() {
175   pipeline_->SetPlaybackRate(1);
176 }
177
178 void PipelineIntegrationTestBase::Pause() {
179   pipeline_->SetPlaybackRate(0);
180 }
181
182 bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
183   ended_ = false;
184
185   EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
186       .WillOnce(InvokeWithoutArgs(&message_loop_, &base::MessageLoop::QuitNow));
187   pipeline_->Seek(seek_time,
188                   base::Bind(&PipelineIntegrationTestBase::SaveStatus,
189                              base::Unretained(this)));
190   message_loop_.Run();
191   return (pipeline_status_ == PIPELINE_OK);
192 }
193
194 void PipelineIntegrationTestBase::Stop() {
195   DCHECK(pipeline_->IsRunning());
196   pipeline_->Stop(base::MessageLoop::QuitClosure());
197   message_loop_.Run();
198 }
199
200 void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
201     const base::TimeDelta& quit_time) {
202   if (pipeline_->GetMediaTime() >= quit_time ||
203       pipeline_status_ != PIPELINE_OK) {
204     message_loop_.Quit();
205     return;
206   }
207
208   message_loop_.PostDelayedTask(
209       FROM_HERE,
210       base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
211                  base::Unretained(this), quit_time),
212       base::TimeDelta::FromMilliseconds(10));
213 }
214
215 bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
216     const base::TimeDelta& wait_time) {
217   DCHECK(pipeline_->IsRunning());
218   DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
219   DCHECK(wait_time <= pipeline_->GetMediaDuration());
220
221   message_loop_.PostDelayedTask(
222       FROM_HERE,
223       base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
224                  base::Unretained(this),
225                  wait_time),
226       base::TimeDelta::FromMilliseconds(10));
227   message_loop_.Run();
228   return (pipeline_status_ == PIPELINE_OK);
229 }
230
231 void PipelineIntegrationTestBase::CreateDemuxer(
232     const base::FilePath& file_path) {
233   FileDataSource* file_data_source = new FileDataSource();
234   CHECK(file_data_source->Initialize(file_path)) << "Is " << file_path.value()
235                                                  << " missing?";
236   data_source_.reset(file_data_source);
237
238   Demuxer::NeedKeyCB need_key_cb = base::Bind(
239       &PipelineIntegrationTestBase::DemuxerNeedKeyCB, base::Unretained(this));
240   demuxer_ =
241       scoped_ptr<Demuxer>(new FFmpegDemuxer(message_loop_.message_loop_proxy(),
242                                             data_source_.get(),
243                                             need_key_cb,
244                                             new MediaLog()));
245 }
246
247 scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer(
248     Decryptor* decryptor) {
249   ScopedVector<VideoDecoder> video_decoders;
250 #if !defined(MEDIA_DISABLE_LIBVPX)
251   video_decoders.push_back(
252       new VpxVideoDecoder(message_loop_.message_loop_proxy()));
253 #endif  // !defined(MEDIA_DISABLE_LIBVPX)
254   video_decoders.push_back(
255       new FFmpegVideoDecoder(message_loop_.message_loop_proxy()));
256
257   // Disable frame dropping if hashing is enabled.
258   scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
259       message_loop_.message_loop_proxy(),
260       video_decoders.Pass(),
261       base::Bind(&PipelineIntegrationTestBase::SetDecryptor,
262                  base::Unretained(this),
263                  decryptor),
264       base::Bind(&PipelineIntegrationTestBase::OnVideoRendererPaint,
265                  base::Unretained(this)),
266       false,
267       new MediaLog()));
268
269   if (!clockless_playback_) {
270     audio_sink_ = new NullAudioSink(message_loop_.message_loop_proxy());
271   } else {
272     clockless_audio_sink_ = new ClocklessAudioSink();
273   }
274
275   ScopedVector<AudioDecoder> audio_decoders;
276   audio_decoders.push_back(
277       new FFmpegAudioDecoder(message_loop_.message_loop_proxy(), LogCB()));
278   audio_decoders.push_back(
279       new OpusAudioDecoder(message_loop_.message_loop_proxy()));
280
281   AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
282                              CHANNEL_LAYOUT_STEREO,
283                              44100,
284                              16,
285                              512);
286   hardware_config_.UpdateOutputConfig(out_params);
287
288   scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
289       message_loop_.message_loop_proxy(),
290       (clockless_playback_)
291           ? static_cast<AudioRendererSink*>(clockless_audio_sink_.get())
292           : audio_sink_.get(),
293       audio_decoders.Pass(),
294       base::Bind(&PipelineIntegrationTestBase::SetDecryptor,
295                  base::Unretained(this),
296                  decryptor),
297       hardware_config_,
298       new MediaLog()));
299   if (hashing_enabled_)
300     audio_sink_->StartAudioHashForTesting();
301
302   scoped_ptr<RendererImpl> renderer_impl(
303       new RendererImpl(message_loop_.message_loop_proxy(),
304                        audio_renderer.Pass(),
305                        video_renderer.Pass()));
306
307   // Prevent non-deterministic buffering state callbacks from firing (e.g., slow
308   // machine, valgrind).
309   renderer_impl->DisableUnderflowForTesting();
310
311   if (clockless_playback_)
312     renderer_impl->EnableClocklessVideoPlaybackForTesting();
313
314   return renderer_impl.Pass();
315 }
316
317 void PipelineIntegrationTestBase::SetDecryptor(
318     Decryptor* decryptor,
319     const DecryptorReadyCB& decryptor_ready_cb) {
320   decryptor_ready_cb.Run(
321       decryptor,
322       base::Bind(&PipelineIntegrationTestBase::DecryptorAttached,
323                  base::Unretained(this)));
324   EXPECT_CALL(*this, DecryptorAttached(true));
325 }
326
327 void PipelineIntegrationTestBase::OnVideoRendererPaint(
328     const scoped_refptr<VideoFrame>& frame) {
329   last_video_frame_format_ = frame->format();
330   if (!hashing_enabled_)
331     return;
332   frame->HashFrameForTesting(&md5_context_);
333 }
334
335 std::string PipelineIntegrationTestBase::GetVideoHash() {
336   DCHECK(hashing_enabled_);
337   base::MD5Digest digest;
338   base::MD5Final(&digest, &md5_context_);
339   return base::MD5DigestToBase16(digest);
340 }
341
342 std::string PipelineIntegrationTestBase::GetAudioHash() {
343   DCHECK(hashing_enabled_);
344   return audio_sink_->GetAudioHashForTesting();
345 }
346
347 base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() {
348   DCHECK(clockless_playback_);
349   return clockless_audio_sink_->render_time();
350 }
351
352 base::TimeTicks DummyTickClock::NowTicks() {
353   now_ += base::TimeDelta::FromSeconds(60);
354   return now_;
355 }
356
357 }  // namespace media