Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / media / test / pipeline_integration_test_base.cc
blob5217925217b713ce57ccfd6e32354f3a27e003c2
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::Invoke;
30 using ::testing::InvokeWithoutArgs;
31 using ::testing::SaveArg;
33 namespace media {
35 const char kNullVideoHash[] = "d41d8cd98f00b204e9800998ecf8427e";
36 const char kNullAudioHash[] = "0.00,0.00,0.00,0.00,0.00,0.00,";
38 PipelineIntegrationTestBase::PipelineIntegrationTestBase()
39 : hashing_enabled_(false),
40 clockless_playback_(false),
41 pipeline_(
42 new Pipeline(message_loop_.message_loop_proxy(), new MediaLog())),
43 ended_(false),
44 pipeline_status_(PIPELINE_OK),
45 last_video_frame_format_(VideoFrame::UNKNOWN),
46 hardware_config_(AudioParameters(), AudioParameters()) {
47 base::MD5Init(&md5_context_);
50 PipelineIntegrationTestBase::~PipelineIntegrationTestBase() {
51 if (!pipeline_->IsRunning())
52 return;
54 Stop();
57 void PipelineIntegrationTestBase::OnSeeked(base::TimeDelta seek_time,
58 PipelineStatus status) {
59 EXPECT_EQ(seek_time, pipeline_->GetMediaTime());
60 pipeline_status_ = status;
63 void PipelineIntegrationTestBase::OnStatusCallback(
64 PipelineStatus status) {
65 pipeline_status_ = status;
66 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
69 void PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB(
70 EmeInitDataType type,
71 const std::vector<uint8>& init_data) {
72 DCHECK(!init_data.empty());
73 CHECK(!encrypted_media_init_data_cb_.is_null());
74 encrypted_media_init_data_cb_.Run(type, init_data);
77 void PipelineIntegrationTestBase::OnEnded() {
78 DCHECK(!ended_);
79 ended_ = true;
80 pipeline_status_ = PIPELINE_OK;
81 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
84 bool PipelineIntegrationTestBase::WaitUntilOnEnded() {
85 if (ended_)
86 return (pipeline_status_ == PIPELINE_OK);
87 message_loop_.Run();
88 EXPECT_TRUE(ended_);
89 return ended_ && (pipeline_status_ == PIPELINE_OK);
92 PipelineStatus PipelineIntegrationTestBase::WaitUntilEndedOrError() {
93 if (ended_ || pipeline_status_ != PIPELINE_OK)
94 return pipeline_status_;
95 message_loop_.Run();
96 return pipeline_status_;
99 void PipelineIntegrationTestBase::OnError(PipelineStatus status) {
100 DCHECK_NE(status, PIPELINE_OK);
101 pipeline_status_ = status;
102 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
105 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename) {
106 return Start(filename, nullptr);
109 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
110 CdmContext* cdm_context) {
111 EXPECT_CALL(*this, OnMetadata(_))
112 .Times(AtMost(1))
113 .WillRepeatedly(SaveArg<0>(&metadata_));
114 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
115 .Times(AtMost(1));
116 CreateDemuxer(filename);
118 if (cdm_context) {
119 EXPECT_CALL(*this, DecryptorAttached(true));
120 pipeline_->SetCdm(
121 cdm_context, base::Bind(&PipelineIntegrationTestBase::DecryptorAttached,
122 base::Unretained(this)));
125 // Should never be called as the required decryption keys for the encrypted
126 // media files are provided in advance.
127 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0);
129 pipeline_->Start(
130 demuxer_.get(), CreateRenderer(),
131 base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
132 base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
133 base::Bind(&PipelineIntegrationTestBase::OnStatusCallback,
134 base::Unretained(this)),
135 base::Bind(&PipelineIntegrationTestBase::OnMetadata,
136 base::Unretained(this)),
137 base::Bind(&PipelineIntegrationTestBase::OnBufferingStateChanged,
138 base::Unretained(this)),
139 base::Closure(), base::Bind(&PipelineIntegrationTestBase::OnAddTextTrack,
140 base::Unretained(this)),
141 base::Bind(&PipelineIntegrationTestBase::OnWaitingForDecryptionKey,
142 base::Unretained(this)));
143 message_loop_.Run();
144 return pipeline_status_;
147 PipelineStatus PipelineIntegrationTestBase::Start(const std::string& filename,
148 kTestType test_type) {
149 hashing_enabled_ = test_type == kHashed;
150 clockless_playback_ = test_type == kClockless;
151 return Start(filename);
154 void PipelineIntegrationTestBase::Play() {
155 pipeline_->SetPlaybackRate(1);
158 void PipelineIntegrationTestBase::Pause() {
159 pipeline_->SetPlaybackRate(0);
162 bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
163 ended_ = false;
165 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH))
166 .WillOnce(InvokeWithoutArgs(&message_loop_, &base::MessageLoop::QuitNow));
167 pipeline_->Seek(seek_time, base::Bind(&PipelineIntegrationTestBase::OnSeeked,
168 base::Unretained(this), seek_time));
169 message_loop_.Run();
170 return (pipeline_status_ == PIPELINE_OK);
173 void PipelineIntegrationTestBase::Stop() {
174 DCHECK(pipeline_->IsRunning());
175 pipeline_->Stop(base::MessageLoop::QuitClosure());
176 message_loop_.Run();
179 void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
180 const base::TimeDelta& quit_time) {
181 if (pipeline_->GetMediaTime() >= quit_time ||
182 pipeline_status_ != PIPELINE_OK) {
183 message_loop_.Quit();
184 return;
187 message_loop_.PostDelayedTask(
188 FROM_HERE,
189 base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
190 base::Unretained(this), quit_time),
191 base::TimeDelta::FromMilliseconds(10));
194 bool PipelineIntegrationTestBase::WaitUntilCurrentTimeIsAfter(
195 const base::TimeDelta& wait_time) {
196 DCHECK(pipeline_->IsRunning());
197 DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
198 DCHECK(wait_time <= pipeline_->GetMediaDuration());
200 message_loop_.PostDelayedTask(
201 FROM_HERE,
202 base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
203 base::Unretained(this),
204 wait_time),
205 base::TimeDelta::FromMilliseconds(10));
206 message_loop_.Run();
207 return (pipeline_status_ == PIPELINE_OK);
210 void PipelineIntegrationTestBase::CreateDemuxer(const std::string& filename) {
211 FileDataSource* file_data_source = new FileDataSource();
212 base::FilePath file_path(GetTestDataFilePath(filename));
213 CHECK(file_data_source->Initialize(file_path)) << "Is " << file_path.value()
214 << " missing?";
215 data_source_.reset(file_data_source);
217 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
218 base::Bind(&PipelineIntegrationTestBase::DemuxerEncryptedMediaInitDataCB,
219 base::Unretained(this));
221 #if !defined(MEDIA_DISABLE_FFMPEG)
222 demuxer_ = scoped_ptr<Demuxer>(
223 new FFmpegDemuxer(message_loop_.message_loop_proxy(), data_source_.get(),
224 encrypted_media_init_data_cb, new MediaLog()));
225 #endif
228 scoped_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer() {
229 ScopedVector<VideoDecoder> video_decoders;
230 #if !defined(MEDIA_DISABLE_LIBVPX)
231 video_decoders.push_back(
232 new VpxVideoDecoder(message_loop_.message_loop_proxy()));
233 #endif // !defined(MEDIA_DISABLE_LIBVPX)
235 #if !defined(MEDIA_DISABLE_FFMPEG)
236 video_decoders.push_back(
237 new FFmpegVideoDecoder(message_loop_.message_loop_proxy()));
238 #endif
240 // Simulate a 60Hz rendering sink.
241 video_sink_.reset(new NullVideoSink(
242 clockless_playback_, base::TimeDelta::FromSecondsD(1.0 / 60),
243 base::Bind(&PipelineIntegrationTestBase::OnVideoFramePaint,
244 base::Unretained(this)),
245 message_loop_.task_runner()));
247 // Disable frame dropping if hashing is enabled.
248 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
249 message_loop_.message_loop_proxy(), video_sink_.get(),
250 video_decoders.Pass(), false, new MediaLog()));
252 if (!clockless_playback_) {
253 audio_sink_ = new NullAudioSink(message_loop_.message_loop_proxy());
254 } else {
255 clockless_audio_sink_ = new ClocklessAudioSink();
258 ScopedVector<AudioDecoder> audio_decoders;
260 #if !defined(MEDIA_DISABLE_FFMPEG)
261 audio_decoders.push_back(
262 new FFmpegAudioDecoder(message_loop_.message_loop_proxy(), LogCB()));
263 #endif
265 audio_decoders.push_back(
266 new OpusAudioDecoder(message_loop_.message_loop_proxy()));
268 AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
269 CHANNEL_LAYOUT_STEREO,
270 44100,
272 512);
273 hardware_config_.UpdateOutputConfig(out_params);
275 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
276 message_loop_.message_loop_proxy(),
277 (clockless_playback_)
278 ? static_cast<AudioRendererSink*>(clockless_audio_sink_.get())
279 : audio_sink_.get(),
280 audio_decoders.Pass(), hardware_config_, new MediaLog()));
281 if (hashing_enabled_)
282 audio_sink_->StartAudioHashForTesting();
284 scoped_ptr<RendererImpl> renderer_impl(
285 new RendererImpl(message_loop_.message_loop_proxy(),
286 audio_renderer.Pass(),
287 video_renderer.Pass()));
289 // Prevent non-deterministic buffering state callbacks from firing (e.g., slow
290 // machine, valgrind).
291 renderer_impl->DisableUnderflowForTesting();
293 if (clockless_playback_)
294 renderer_impl->EnableClocklessVideoPlaybackForTesting();
296 return renderer_impl.Pass();
299 void PipelineIntegrationTestBase::OnVideoFramePaint(
300 const scoped_refptr<VideoFrame>& frame) {
301 last_video_frame_format_ = frame->format();
302 if (!hashing_enabled_)
303 return;
304 frame->HashFrameForTesting(&md5_context_);
307 std::string PipelineIntegrationTestBase::GetVideoHash() {
308 DCHECK(hashing_enabled_);
309 base::MD5Digest digest;
310 base::MD5Final(&digest, &md5_context_);
311 return base::MD5DigestToBase16(digest);
314 std::string PipelineIntegrationTestBase::GetAudioHash() {
315 DCHECK(hashing_enabled_);
316 return audio_sink_->GetAudioHashForTesting();
319 base::TimeDelta PipelineIntegrationTestBase::GetAudioTime() {
320 DCHECK(clockless_playback_);
321 return clockless_audio_sink_->render_time();
324 base::TimeTicks DummyTickClock::NowTicks() {
325 now_ += base::TimeDelta::FromSeconds(60);
326 return now_;
329 } // namespace media