Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: media/base/android/media_codec_decoder_unittest.cc

Issue 1176993005: Audio and video decoders for MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added tests for video decoder, video decoder now reports current time. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 "base/bind.h"
6 #include "base/logging.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/thread_task_runner_handle.h"
9 #include "base/timer/timer.h"
10 #include "media/base/android/media_codec_audio_decoder.h"
11 #include "media/base/android/media_codec_bridge.h"
12 #include "media/base/android/media_codec_video_decoder.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/test_data_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gl/android/surface_texture.h"
17
18 namespace media {
19
20 // Helper macro to skip the test if MediaCodecBridge isn't available.
21 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \
22 do { \
23 if (!MediaCodecBridge::IsAvailable()) { \
24 VLOG(0) << "Could not run test - not supported on device."; \
25 return; \
26 } \
27 } while (0)
28
29 namespace {
30
31 const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200);
32 const base::TimeDelta kAudioFramePeriod = base::TimeDelta::FromMilliseconds(20);
33 const base::TimeDelta kVideoFramePeriod = base::TimeDelta::FromMilliseconds(20);
34
35 DemuxerConfigs CreateAudioConfigs(AudioCodec audio_codec,
36 const base::TimeDelta& duration) {
37 DemuxerConfigs configs;
38 configs.audio_codec = audio_codec;
39 configs.audio_channels = 2;
40 configs.is_audio_encrypted = false;
41 configs.duration = duration;
42
43 // Other codecs are not yet supported by this helper.
44 EXPECT_TRUE(audio_codec == kCodecAAC || audio_codec == kCodecVorbis);
45
46 switch (audio_codec) {
47 case kCodecVorbis: {
48 configs.audio_sampling_rate = 44100;
49 scoped_refptr<DecoderBuffer> buffer =
50 ReadTestDataFile("vorbis-extradata");
51 configs.audio_extra_data = std::vector<uint8>(
52 buffer->data(), buffer->data() + buffer->data_size());
53 } break;
54
55 case kCodecAAC: {
56 configs.audio_sampling_rate = 48000;
57 uint8 aac_extra_data[] = {0x13, 0x10};
58 configs.audio_extra_data =
59 std::vector<uint8>(aac_extra_data, aac_extra_data + 2);
60 } break;
61
62 default:
63 NOTREACHED();
64 break;
65 }
66
67 return configs;
68 }
69
70 DemuxerConfigs CreateVideoConfigs(const base::TimeDelta& duration) {
71 DemuxerConfigs configs;
72 configs.video_codec = kCodecH264;
73 configs.video_size = gfx::Size(320, 240);
74 configs.is_video_encrypted = false;
75 configs.duration = duration;
76 return configs;
77 }
78
79 } // namespace (anonymous)
80
81 // DataFactory defines how the data will be generated.
82
83 class DataFactory {
84 public:
85 DataFactory(const char* file_name_format,
86 const base::TimeDelta& duration,
87 const base::TimeDelta& frame_period);
88 virtual ~DataFactory() {}
89
90 void CreateChunk(DemuxerData* chunk, base::TimeDelta* delay);
91
92 base::TimeDelta last_pts() const { return last_pts_; }
93
94 protected:
95 virtual void FillAccessUnit(int index_in_chunk, AccessUnit* unit) = 0;
96
97 base::TimeDelta duration_;
98 base::TimeDelta frame_period_;
99 std::vector<uint8> packet_[4];
100 base::TimeDelta regular_pts_;
101 base::TimeDelta last_pts_;
102 };
103
104 class AudioFactory : public DataFactory {
105 public:
106 AudioFactory(const base::TimeDelta& duration);
107
108 protected:
109 void FillAccessUnit(int index_in_chunk, AccessUnit* unit) override;
110 };
111
112 class VideoFactory : public DataFactory {
113 public:
114 VideoFactory(const base::TimeDelta& duration);
115
116 protected:
117 void FillAccessUnit(int index_in_chunk, AccessUnit* unit) override;
118 };
119
120 DataFactory::DataFactory(const char* file_name_format,
121 const base::TimeDelta& duration,
122 const base::TimeDelta& frame_period)
123 : duration_(duration), frame_period_(frame_period) {
124 // Load packets
125 for (int i = 0; i < 4; ++i) {
126 scoped_refptr<DecoderBuffer> buffer =
127 ReadTestDataFile(base::StringPrintf(file_name_format, i));
128 packet_[i] = std::vector<uint8>(buffer->data(),
129 buffer->data() + buffer->data_size());
130 }
131 }
132
133 void DataFactory::CreateChunk(DemuxerData* chunk, base::TimeDelta* delay) {
134 DCHECK(chunk);
135 DCHECK(delay);
136
137 *delay = base::TimeDelta();
138
139 for (int i = 0; i < 4; ++i) {
140 chunk->access_units.push_back(AccessUnit());
141 AccessUnit& unit = chunk->access_units.back();
142 unit.status = DemuxerStream::kOk;
143
144 unit.timestamp = regular_pts_;
145 regular_pts_ += frame_period_;
146
147 if (unit.timestamp > duration_) {
148 unit.is_end_of_stream = true;
149 break; // EOS units have no data
150 }
151
152 FillAccessUnit(i, &unit);
153
154 // Maintain last PTS. FillAccessUnit can modify unit's PTS.
155 if (last_pts_ < unit.timestamp)
156 last_pts_ = unit.timestamp;
157 }
158 }
159
160 AudioFactory::AudioFactory(const base::TimeDelta& duration)
161 : DataFactory("vorbis-packet-%d", duration, kAudioFramePeriod) {
162 }
163
164 void AudioFactory::FillAccessUnit(int index_in_chunk, AccessUnit* unit) {
165 unit->data = packet_[index_in_chunk];
166
167 // Vorbis needs 4 extra bytes padding on Android to decode properly. Check
168 // NuMediaExtractor.cpp in Android source code.
169 uint8 padding[4] = {0xff, 0xff, 0xff, 0xff};
170 unit->data.insert(unit->data.end(), padding, padding + 4);
171 }
172
173 VideoFactory::VideoFactory(const base::TimeDelta& duration)
174 : DataFactory("h264-320x180-frame-%d", duration, kVideoFramePeriod) {
175 }
176
177 void VideoFactory::FillAccessUnit(int index_in_chunk, AccessUnit* unit) {
178 unit->data = packet_[index_in_chunk];
179
180 // The frames are taken from High profile and some are B-frames.
181 // The first 4 frames appear in the file in the following order:
182 //
183 // Frames: I P B P
184 // Decoding order: 0 1 2 3
185 // Presentation order: 0 2 1 4(3)
186 //
187 // I keep the last PTS to be 3 for simplicity.
188
189 // Swap pts for second and third frames.
190 if (index_in_chunk == 1) // second frame
191 unit->timestamp += frame_period_;
192 if (index_in_chunk == 2) // third frame
193 unit->timestamp -= frame_period_;
194
195 if (index_in_chunk == 0)
196 unit->is_key_frame = true;
197 }
198
199 // Class that computes statistics: number of calls, minimum and maximum values.
200 // It is used for PTS statistics to verify that playback did actually happen.
201
202 template <typename T>
203 class Minimax {
204 public:
205 Minimax() : num_values_(0) {}
206 ~Minimax() {}
207
208 void AddValue(const T& value) {
209 ++num_values_;
210 if (value < min_)
211 min_ = value;
212 else if (max_ < value)
213 max_ = value;
214 }
215
216 const T& min() const { return min_; }
217 const T& max() const { return max_; }
218 int num_values() const { return num_values_; }
219
220 private:
221 T min_;
222 T max_;
223 int num_values_;
224 };
225
226 // The test fixture for MediaCodecDecoder
227
228 class MediaCodecDecoderTest : public testing::Test {
229 public:
230 MediaCodecDecoderTest();
231 ~MediaCodecDecoderTest() override;
232
233 // Conditions we wait for.
234 bool is_prefetched() const { return is_prefetched_; }
235 bool is_stopped() const { return is_stopped_; }
236 bool is_starved() const { return is_starved_; }
237
238 // Prefetch callback has to be public.
239 void SetPrefetched() { is_prefetched_ = true; }
240
241 protected:
242 typedef base::Callback<bool()> Predicate;
243
244 typedef base::Callback<void(const DemuxerData&)> DataAvailableCallback;
245
246 // Waits for condition to become true or for timeout to expire.
247 // Returns true if the condition becomes true.
248 bool WaitForCondition(const Predicate& condition,
249 const base::TimeDelta& timeout = kDefaultTimeout);
250
251 void SetDataFactory(scoped_ptr<DataFactory> factory) {
252 data_factory_ = factory.Pass();
253 }
254
255 void CreateAudioDecoder();
256 void CreateVideoDecoder();
257 void SetVideoSurface();
258
259 // Decoder callbacks.
260 void OnDataRequested();
261 void OnStarvation() { is_starved_ = true; }
262 void OnStopDone() { is_stopped_ = true; }
263 void OnError() {}
264 void OnUpdateCurrentTime(base::TimeDelta now_playing,
265 base::TimeDelta last_buffered) {
266 pts_stat_.AddValue(now_playing);
267 }
268 void OnVideoSizeChanged(const gfx::Size& video_size) {}
269 void OnVideoCodecCreated() {}
270
271 scoped_ptr<MediaCodecDecoder> decoder_;
272 scoped_ptr<DataFactory> data_factory_;
273 Minimax<base::TimeDelta> pts_stat_;
274
275 private:
276 bool is_timeout_expired() const { return is_timeout_expired_; }
277 void SetTimeoutExpired(bool value) { is_timeout_expired_ = value; }
278
279 base::MessageLoop message_loop_;
280 bool is_timeout_expired_;
281
282 bool is_prefetched_;
283 bool is_stopped_;
284 bool is_starved_;
285
286 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
287 DataAvailableCallback data_available_cb_;
288 scoped_refptr<gfx::SurfaceTexture> surface_texture_;
289
290 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoderTest);
291 };
292
293 MediaCodecDecoderTest::MediaCodecDecoderTest()
294 : is_timeout_expired_(false),
295 is_prefetched_(false),
296 is_stopped_(false),
297 is_starved_(false),
298 task_runner_(base::ThreadTaskRunnerHandle::Get()) {
299 }
300
301 MediaCodecDecoderTest::~MediaCodecDecoderTest() {
302 }
303
304 bool MediaCodecDecoderTest::WaitForCondition(const Predicate& condition,
305 const base::TimeDelta& timeout) {
306 // Let the message_loop_ process events.
307 // We start the timer and RunUntilIdle() until it signals.
308
309 SetTimeoutExpired(false);
310
311 base::Timer timer(false, false);
312 timer.Start(FROM_HERE, timeout,
313 base::Bind(&MediaCodecDecoderTest::SetTimeoutExpired,
314 base::Unretained(this), true));
315
316 do {
317 if (condition.Run()) {
318 timer.Stop();
319 return true;
320 }
321 message_loop_.RunUntilIdle();
322 } while (!is_timeout_expired());
323
324 DCHECK(!timer.IsRunning());
325 return false;
326 }
327
328 void MediaCodecDecoderTest::CreateAudioDecoder() {
329 decoder_ = scoped_ptr<MediaCodecDecoder>(new MediaCodecAudioDecoder(
330 task_runner_, base::Bind(&MediaCodecDecoderTest::OnDataRequested,
331 base::Unretained(this)),
332 base::Bind(&MediaCodecDecoderTest::OnStarvation, base::Unretained(this)),
333 base::Bind(&MediaCodecDecoderTest::OnStopDone, base::Unretained(this)),
334 base::Bind(&MediaCodecDecoderTest::OnError, base::Unretained(this)),
335 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime,
336 base::Unretained(this))));
337
338 data_available_cb_ = base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable,
339 base::Unretained(decoder_.get()));
340 }
341
342 void MediaCodecDecoderTest::CreateVideoDecoder() {
343 decoder_ = scoped_ptr<MediaCodecDecoder>(new MediaCodecVideoDecoder(
344 task_runner_, base::Bind(&MediaCodecDecoderTest::OnDataRequested,
345 base::Unretained(this)),
346 base::Bind(&MediaCodecDecoderTest::OnStarvation, base::Unretained(this)),
347 base::Bind(&MediaCodecDecoderTest::OnStopDone, base::Unretained(this)),
348 base::Bind(&MediaCodecDecoderTest::OnError, base::Unretained(this)),
349 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime,
350 base::Unretained(this)),
351 base::Bind(&MediaCodecDecoderTest::OnVideoSizeChanged,
352 base::Unretained(this)),
353 base::Bind(&MediaCodecDecoderTest::OnVideoCodecCreated,
354 base::Unretained(this))));
355
356 data_available_cb_ = base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable,
357 base::Unretained(decoder_.get()));
358 }
359
360 void MediaCodecDecoderTest::OnDataRequested() {
361 if (!data_factory_)
362 return;
363
364 DemuxerData data;
365 base::TimeDelta delay;
366 data_factory_->CreateChunk(&data, &delay);
367
368 task_runner_->PostDelayedTask(FROM_HERE, base::Bind(data_available_cb_, data),
369 delay);
370 }
371
372 void MediaCodecDecoderTest::SetVideoSurface() {
373 surface_texture_ = gfx::SurfaceTexture::Create(0);
374 gfx::ScopedJavaSurface surface(surface_texture_.get());
375 ASSERT_NE(nullptr, decoder_.get());
376 MediaCodecVideoDecoder* video_decoder =
377 static_cast<MediaCodecVideoDecoder*>(decoder_.get());
378 video_decoder->SetPendingSurface(surface.Pass());
379 }
380
381 TEST_F(MediaCodecDecoderTest, AudioPrefetch) {
382 CreateAudioDecoder();
383
384 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
385 SetDataFactory(scoped_ptr<DataFactory>(new AudioFactory(duration)));
386
387 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
388 base::Unretained(this)));
389
390 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
391 base::Unretained(this))));
392 }
393
394 TEST_F(MediaCodecDecoderTest, VideoPrefetch) {
395 CreateVideoDecoder();
396
397 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
398 SetDataFactory(scoped_ptr<DataFactory>(new VideoFactory(duration)));
399
400 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
401 base::Unretained(this)));
402
403 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
404 base::Unretained(this))));
405 }
406
407 TEST_F(MediaCodecDecoderTest, AudioConfigureNoParams) {
408 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
409
410 CreateAudioDecoder();
411
412 // Cannot configure without config parameters.
413 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure());
414 }
415
416 TEST_F(MediaCodecDecoderTest, AudioConfigureValidParams) {
417 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
418
419 CreateAudioDecoder();
420
421 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
422 decoder_->SetDemuxerConfigs(CreateAudioConfigs(kCodecVorbis, duration));
423
424 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure());
425 }
426
427 TEST_F(MediaCodecDecoderTest, VideoConfigureNoParams) {
428 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
429
430 CreateVideoDecoder();
431
432 // Cannot configure without config parameters.
433 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure());
434 }
435
436 TEST_F(MediaCodecDecoderTest, VideoConfigureNoSurface) {
437 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
438
439 CreateVideoDecoder();
440
441 // decoder_->Configure() searches back for the key frame.
442 // We have to prefetch decoder.
443
444 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
445 SetDataFactory(scoped_ptr<DataFactory>(new VideoFactory(duration)));
446
447 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
448 base::Unretained(this)));
449
450 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
451 base::Unretained(this))));
452
453 decoder_->SetDemuxerConfigs(CreateVideoConfigs(duration));
454
455 // Surface is not set, Configure() should fail.
456
457 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure());
458 }
459
460 TEST_F(MediaCodecDecoderTest, VideoConfigureInvalidSurface) {
461 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
462
463 CreateVideoDecoder();
464
465 // decoder_->Configure() searches back for the key frame.
466 // We have to prefetch decoder.
467
468 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
469 SetDataFactory(scoped_ptr<DataFactory>(new VideoFactory(duration)));
470
471 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
472 base::Unretained(this)));
473
474 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
475 base::Unretained(this))));
476
477 decoder_->SetDemuxerConfigs(CreateVideoConfigs(duration));
478
479 // Prepare the surface.
480 scoped_refptr<gfx::SurfaceTexture> surface_texture(
481 gfx::SurfaceTexture::Create(0));
482 gfx::ScopedJavaSurface surface(surface_texture.get());
483
484 // Release the surface texture.
485 surface_texture = NULL;
486
487 MediaCodecVideoDecoder* video_decoder =
488 static_cast<MediaCodecVideoDecoder*>(decoder_.get());
489 video_decoder->SetPendingSurface(surface.Pass());
490
491 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure());
492 }
493
494 TEST_F(MediaCodecDecoderTest, VideoConfigureValidParams) {
495 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
496
497 CreateVideoDecoder();
498
499 // decoder_->Configure() searches back for the key frame.
500 // We have to prefetch decoder.
501
502 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
503 SetDataFactory(scoped_ptr<DataFactory>(new VideoFactory(duration)));
504
505 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
506 base::Unretained(this)));
507
508 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
509 base::Unretained(this))));
510
511 decoder_->SetDemuxerConfigs(CreateVideoConfigs(duration));
512
513 SetVideoSurface();
514
515 // Now we can expect Configure() to succeed.
516
517 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure());
518 }
519
520 TEST_F(MediaCodecDecoderTest, AudioStartWithoutConfigure) {
521 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
522
523 CreateAudioDecoder();
524
525 // Decoder has to be configured first.
526 EXPECT_FALSE(decoder_->Start(base::TimeDelta::FromMilliseconds(0)));
527 }
528
529 TEST_F(MediaCodecDecoderTest, AudioStarvation) {
530 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
531
532 CreateAudioDecoder();
533
534 // We do not set data factory and do not call Prefetch.
535 // In this case decoder shoudl report starvation right after Start.
536
537 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
538 decoder_->SetDemuxerConfigs(CreateAudioConfigs(kCodecVorbis, duration));
539
540 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure());
541
542 EXPECT_TRUE(decoder_->Start(base::TimeDelta::FromMilliseconds(0)));
543
544 EXPECT_TRUE(WaitForCondition(
545 base::Bind(&MediaCodecDecoderTest::is_starved, base::Unretained(this))));
546 }
547
548 TEST_F(MediaCodecDecoderTest, AudioPlayTillCompletion) {
549 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
550
551 CreateAudioDecoder();
552
553 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
554 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(600);
555 SetDataFactory(scoped_ptr<DataFactory>(new AudioFactory(duration)));
556
557 // Prefetch to avoid starvation at the beginning of playback.
558 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
559 base::Unretained(this)));
560
561 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
562 base::Unretained(this))));
563
564 decoder_->SetDemuxerConfigs(CreateAudioConfigs(kCodecVorbis, duration));
565
566 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure());
567
568 EXPECT_TRUE(decoder_->Start(base::TimeDelta::FromMilliseconds(0)));
569
570 EXPECT_TRUE(WaitForCondition(
571 base::Bind(&MediaCodecDecoderTest::is_stopped, base::Unretained(this)),
572 timeout));
573
574 EXPECT_TRUE(decoder_->IsStopped());
575 EXPECT_TRUE(decoder_->IsCompleted());
576
577 // It is hard to properly estimate minimum and maximum values because
578 // reported times are different from PTS.
579 EXPECT_EQ(25, pts_stat_.num_values());
580 }
581
582 TEST_F(MediaCodecDecoderTest, VideoPlayTillCompletion) {
583 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
584
585 CreateVideoDecoder();
586
587 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500);
588 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(600);
589 SetDataFactory(scoped_ptr<DataFactory>(new VideoFactory(duration)));
590
591 // Prefetch
592 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched,
593 base::Unretained(this)));
594
595 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched,
596 base::Unretained(this))));
597
598 decoder_->SetDemuxerConfigs(CreateVideoConfigs(duration));
599
600 SetVideoSurface();
601
602 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure());
603
604 EXPECT_TRUE(decoder_->Start(base::TimeDelta::FromMilliseconds(0)));
605
606 EXPECT_TRUE(WaitForCondition(
607 base::Bind(&MediaCodecDecoderTest::is_stopped, base::Unretained(this)),
608 timeout));
609
610 EXPECT_TRUE(decoder_->IsStopped());
611 EXPECT_TRUE(decoder_->IsCompleted());
612
613 EXPECT_EQ(26, pts_stat_.num_values());
614 EXPECT_EQ(data_factory_->last_pts(), pts_stat_.max());
615 }
616
617 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698