Add an UMA stat to be able to see if the User pods are show on start screen,
[chromium-blink-merge.git] / media / test / pipeline_integration_test_base.cc
blobda3a9f8555788a374b5f0441e91d5b12c3357b4a
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 "media/test/pipeline_integration_test_base.h"
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "media/base/cdm_context.h"
10 #include "media/base/media_log.h"
11 #include "media/base/test_data_util.h"
12 #include "media/filters/chunk_demuxer.h"
13 #if !defined(MEDIA_DISABLE_FFMPEG)
14 #include "media/filters/ffmpeg_audio_decoder.h"
15 #include "media/filters/ffmpeg_demuxer.h"
16 #include "media/filters/ffmpeg_video_decoder.h"
17 #endif
18 #include "media/filters/file_data_source.h"
19 #include "media/filters/opus_audio_decoder.h"
20 #include "media/renderers/audio_renderer_impl.h"
21 #include "media/renderers/renderer_impl.h"
22 #if !defined(MEDIA_DISABLE_LIBVPX)
23 #include "media/filters/vpx_video_decoder.h"
24 #endif
26 using ::testing::_;
27 using ::testing::AnyNumber;
28 using ::testing::AtMost;
29 using ::testing::InvokeWithoutArgs;
30 using ::testing::SaveArg;
32 namespace media {
34 const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e";
35 const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,";
37 PipelineIntegrationTestBase::PipelineIntegrationTestBase()
38 : hashing_enabled_(false),
39 clockless_playback_(false),
40 pipeline_(
41 new Pipeline(message_loop_.message_loop_proxy(), new MediaLog())),
42 ended_(false),
43 pipeline_status_(PIPELINE_OK),
44 last_video_frame_format_(VideoFrame::UNKNOWN),
45 hardware_config_(AudioParameters(), AudioParameters()) {
46 base::MD5Init(&md5_context_);
49 PipelineIntegrationTestBase::~PipelineIntegrationTestBase() {
50 if (!pipeline_->IsRunning())
51 return;
53 Stop();
56 void PipelineIntegrationTestBase::OnSeeked(base::TimeDelta seek_time,
57 PipelineStatus status) {
58 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
59 pipeline_status_ = status;
62 void PipelineIntegrationTestBase::OnStatusCallback(
63 PipelineStatus status) {
64 pipeline_status_ = status;
65 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
68 void PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB(
69 EmeInitDataType type,
70 const std::vector<uint8>& init_data) {
71 DCHECK(!init_data.empty());
72 CHECK(!encrypted_media_init_data_cb_.is_null());
73 encrypted_media_init_data_cb_.Run(type, init_data);
76 void PipelineIntegrationTestBase::OnEnded() {
77 DCHECK(!ended_);
78 ended_ = true;
79 pipeline_status_ = PIPELINE_OK;
80 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
83 bool PipelineIntegrationTestBase::WaitUntilOnEnded() {
84 if (ended_)
85 return (pipeline_status_ == PIPELINE_OK);
86 message_loop_.Run();
87 EXPECT_TRUE(ended_);
88 return ended_ && (pipeline_status_ == PIPELINE_OK);
91 PipelineStatus PipelineIntegrationTestBase::WaitUntilEndedOrError() {
92 if (ended_ || pipeline_status_ != PIPELINE_OK)
93 return pipeline_status_;
94 message_loop_.Run();
95 return pipeline_status_;
98 void PipelineIntegrationTestBase::OnError(PipelineStatus status) {
99 DCHECK_NE(status, PIPELINE_OK);
100 pipeline_status_ = status;
101 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
104 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename) {
105 return Start(filename, nullptr);
108 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
109 CdmContext* cdm_context) {
110 EXPECT_CALL(*this, OnMetadata(_))
111 .Times(AtMost(1))
112 .WillRepeatedly(SaveArg<0>(&metadata_));
113 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
114 .Times(AtMost(1));
115 CreateDemuxer(filename);
117 if (cdm_context) {
118 EXPECT_CALL(*this, DecryptorAttached(true));
119 pipeline_->SetCdm(
120 cdm_context, base::Bind(&PipelineIntegrationTestBase::DecryptorAttached,
121 base::Unretained(this)));
124 // Should never be called as the required decryption keys for the encrypted
125 // media files are provided in advance.
126 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
128 pipeline_->Start(
129 demuxer_.get(), CreateRenderer(),
130 base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
131 base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
132 base::Bind(&PipelineIntegrationTestBase::OnStatusCallback,
133 base::Unretained(this)),
134 base::Bind(&PipelineIntegrationTestBase::OnMetadata,
135 base::Unretained(this)),
136 base::Bind(&PipelineIntegrationTestBase::OnBufferingStateChanged,
137 base::Unretained(this)),
138 base::Bind(&PipelineIntegrationTestBase::OnVideoFramePaint,
139 base::Unretained(this)),
140 base::Closure(), base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack,
141 base::Unretained(this)),
142 base::Bind(&PipelineIntegrationTestBase::OnWaitingForDecryptionKey,
143 base::Unretained(this)));
144 message_loop_.Run();
145 return pipeline_status_;
148 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
149 kTestType test_type) {
150 hashing_enabled_ = test_type == kHashed;
151 clockless_playback_ = test_type == kClockless;
152 return Start(filename);
155 void PipelineIntegrationTestBase::Play() {
156 pipeline_->SetPlaybackRate(1);
159 void PipelineIntegrationTestBase::Pause() {
160 pipeline_->SetPlaybackRate(0);
163 bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
164 ended_ = false;
166 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
167 .WillOnce(InvokeWithoutArgs(&message_loop_, &base::MessageLoop::QuitNow));
168 pipeline_->Seek(seek_time, base::Bind(&PipelineIntegrationTestBase::OnSeeked,
169 base::Unretained(this), seek_time));
170 message_loop_.Run();
171 return (pipeline_status_ == PIPELINE_OK);
174 void PipelineIntegrationTestBase::Stop() {
175 DCHECK(pipeline_->IsRunning());
176 pipeline_->Stop(base::MessageLoop::QuitClosure());
177 message_loop_.Run();
180 void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
181 const base::TimeDelta& quit_time) {
182 if (pipeline_->GetMediaTime() >= quit_time ||
183 pipeline_status_ != PIPELINE_OK) {
184 message_loop_.Quit();
185 return;
188 message_loop_.PostDelayedTask(
189 FROM_HERE,
190 base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
191 base::Unretained(this), quit_time),
192 base::TimeDelta::FromMilliseconds(10));
195 bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
196 const base::TimeDelta& wait_time) {
197 DCHECK(pipeline_->IsRunning());
198 DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
199 DCHECK(wait_time <= pipeline_->GetMediaDuration());
201 message_loop_.PostDelayedTask(
202 FROM_HERE,
203 base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
204 base::Unretained(this),
205 wait_time),
206 base::TimeDelta::FromMilliseconds(10));
207 message_loop_.Run();
208 return (pipeline_status_ == PIPELINE_OK);
211 void PipelineIntegrationTestBase::CreateDemuxer(const std::string& filename) {
212 FileDataSource* file_data_source = new FileDataSource();
213 base::FilePath file_path(GetTestDataFilePath(filename));
214 CHECK(file_data_source->Initialize(file_path)) << "Is " << file_path.value()
215 << " missing?";
216 data_source_.reset(file_data_source);
218 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
219 base::Bind(&PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB,
220 base::Unretained(this));
222 #if !defined(MEDIA_DISABLE_FFMPEG)
223 demuxer_ = scoped_ptr<Demuxer>(
224 new FFmpegDemuxer(message_loop_.message_loop_proxy(), data_source_.get(),
225 encrypted_media_init_data_cb, new MediaLog()));
226 #endif
229 scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer() {
230 ScopedVector<VideoDecoder> video_decoders;
231 #if !defined(MEDIA_DISABLE_LIBVPX)
232 video_decoders.push_back(
233 new VpxVideoDecoder(message_loop_.message_loop_proxy()));
234 #endif // !defined(MEDIA_DISABLE_LIBVPX)
236 #if !defined(MEDIA_DISABLE_FFMPEG)
237 video_decoders.push_back(
238 new FFmpegVideoDecoder(message_loop_.message_loop_proxy()));
239 #endif
241 // Disable frame dropping if hashing is enabled.
242 scoped_ptr<VideoRenderer> video_renderer(
243 new VideoRendererImpl(message_loop_.message_loop_proxy(),
244 video_decoders.Pass(), false, new MediaLog()));
246 if (!clockless_playback_) {
247 audio_sink_ = new NullAudioSink(message_loop_.message_loop_proxy());
248 } else {
249 clockless_audio_sink_ = new ClocklessAudioSink();
252 ScopedVector<AudioDecoder> audio_decoders;
254 #if !defined(MEDIA_DISABLE_FFMPEG)
255 audio_decoders.push_back(
256 new FFmpegAudioDecoder(message_loop_.message_loop_proxy(), LogCB()));
257 #endif
259 audio_decoders.push_back(
260 new OpusAudioDecoder(message_loop_.message_loop_proxy()));
262 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
263 CHANNEL_LAYOUT_STEREO,
264 44100,
266 512);
267 hardware_config_.UpdateOutputConfig(out_params);
269 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
270 message_loop_.message_loop_proxy(),
271 (clockless_playback_)
272 ? static_cast<AudioRendererSink*>(clockless_audio_sink_.get())
273 : audio_sink_.get(),
274 audio_decoders.Pass(), hardware_config_, new MediaLog()));
275 if (hashing_enabled_)
276 audio_sink_->StartAudioHashForTesting();
278 scoped_ptr<RendererImpl> renderer_impl(
279 new RendererImpl(message_loop_.message_loop_proxy(),
280 audio_renderer.Pass(),
281 video_renderer.Pass()));
283 // Prevent non-deterministic buffering state callbacks from firing (e.g., slow
284 // machine, valgrind).
285 renderer_impl->DisableUnderflowForTesting();
287 if (clockless_playback_)
288 renderer_impl->EnableClocklessVideoPlaybackForTesting();
290 return renderer_impl.Pass();
293 void PipelineIntegrationTestBase::OnVideoFramePaint(
294 const scoped_refptr<VideoFrame>& frame) {
295 last_video_frame_format_ = frame->format();
296 if (!hashing_enabled_)
297 return;
298 frame->HashFrameForTesting(&md5_context_);
301 std::string PipelineIntegrationTestBase::GetVideoHash() {
302 DCHECK(hashing_enabled_);
303 base::MD5Digest digest;
304 base::MD5Final(&digest, &md5_context_);
305 return base::MD5DigestToBase16(digest);
308 std::string PipelineIntegrationTestBase::GetAudioHash() {
309 DCHECK(hashing_enabled_);
310 return audio_sink_->GetAudioHashForTesting();
313 base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() {
314 DCHECK(clockless_playback_);
315 return clockless_audio_sink_->render_time();
318 base::TimeTicks DummyTickClock::NowTicks() {
319 now_ += base::TimeDelta::FromSeconds(60);
320 return now_;
323 } // namespace media