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.
6 #include "base/logging.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "base/timer/timer.h"
9 #include "media/base/android/media_codec_audio_decoder.h"
10 #include "media/base/android/media_codec_bridge.h"
11 #include "media/base/android/media_codec_video_decoder.h"
12 #include "media/base/android/test_data_factory.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/gl/android/surface_texture.h"
18 // Helper macro to skip the test if MediaCodecBridge isn't available.
19 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \
21 if (!MediaCodecBridge::IsAvailable()) { \
22 VLOG(0) << "Could not run test - not supported on device."; \
29 const base::TimeDelta kDefaultTimeout
= base::TimeDelta::FromMilliseconds(200);
30 const base::TimeDelta kAudioFramePeriod
= base::TimeDelta::FromMilliseconds(20);
31 const base::TimeDelta kVideoFramePeriod
= base::TimeDelta::FromMilliseconds(20);
33 class AudioFactory
: public TestDataFactory
{
35 AudioFactory(const base::TimeDelta
& duration
);
36 DemuxerConfigs
GetConfigs() const override
;
39 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
;
42 class VideoFactory
: public TestDataFactory
{
44 VideoFactory(const base::TimeDelta
& duration
);
45 DemuxerConfigs
GetConfigs() const override
;
48 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
;
51 AudioFactory::AudioFactory(const base::TimeDelta
& duration
)
52 : TestDataFactory("vorbis-packet-%d", duration
, kAudioFramePeriod
) {
55 DemuxerConfigs
AudioFactory::GetConfigs() const {
56 return TestDataFactory::CreateAudioConfigs(kCodecVorbis
, duration_
);
59 void AudioFactory::ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) {
60 // Vorbis needs 4 extra bytes padding on Android to decode properly. Check
61 // NuMediaExtractor.cpp in Android source code.
62 uint8 padding
[4] = {0xff, 0xff, 0xff, 0xff};
63 unit
->data
.insert(unit
->data
.end(), padding
, padding
+ 4);
66 VideoFactory::VideoFactory(const base::TimeDelta
& duration
)
67 : TestDataFactory("h264-320x180-frame-%d", duration
, kVideoFramePeriod
) {
70 DemuxerConfigs
VideoFactory::GetConfigs() const {
71 return TestDataFactory::CreateVideoConfigs(kCodecH264
, duration_
,
75 void VideoFactory::ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) {
76 // The frames are taken from High profile and some are B-frames.
77 // The first 4 frames appear in the file in the following order:
80 // Decoding order: 0 1 2 3
81 // Presentation order: 0 2 1 4(3)
83 // I keep the last PTS to be 3 for simplicity.
85 // Swap pts for second and third frames.
86 if (index_in_chunk
== 1) // second frame
87 unit
->timestamp
+= frame_period_
;
88 if (index_in_chunk
== 2) // third frame
89 unit
->timestamp
-= frame_period_
;
91 if (index_in_chunk
== 0)
92 unit
->is_key_frame
= true;
95 // Class that computes statistics: number of calls, minimum and maximum values.
96 // It is used for PTS statistics to verify that playback did actually happen.
101 Minimax() : num_values_(0) {}
104 void AddValue(const T
& value
) {
108 else if (max_
< value
)
112 const T
& min() const { return min_
; }
113 const T
& max() const { return max_
; }
114 int num_values() const { return num_values_
; }
122 } // namespace (anonymous)
124 // The test fixture for MediaCodecDecoder
126 class MediaCodecDecoderTest
: public testing::Test
{
128 MediaCodecDecoderTest();
129 ~MediaCodecDecoderTest() override
;
131 // Conditions we wait for.
132 bool is_prefetched() const { return is_prefetched_
; }
133 bool is_stopped() const { return is_stopped_
; }
134 bool is_starved() const { return is_starved_
; }
136 void SetPrefetched(bool value
) { is_prefetched_
= value
; }
137 void SetStopped(bool value
) { is_stopped_
= value
; }
138 void SetStarved(bool value
) { is_starved_
= value
; }
141 typedef base::Callback
<bool()> Predicate
;
143 typedef base::Callback
<void(const DemuxerData
&)> DataAvailableCallback
;
145 // Waits for condition to become true or for timeout to expire.
146 // Returns true if the condition becomes true.
147 bool WaitForCondition(const Predicate
& condition
,
148 const base::TimeDelta
& timeout
= kDefaultTimeout
);
150 void SetDataFactory(scoped_ptr
<TestDataFactory
> factory
) {
151 data_factory_
= factory
.Pass();
154 DemuxerConfigs
GetConfigs() const {
155 // ASSERT_NE does not compile here because it expects void return value.
156 EXPECT_NE(nullptr, data_factory_
.get());
157 return data_factory_
->GetConfigs();
160 void CreateAudioDecoder();
161 void CreateVideoDecoder();
162 void SetVideoSurface();
163 void SetStopRequestAtTime(const base::TimeDelta
& time
) {
164 stop_request_time_
= time
;
167 // Decoder callbacks.
168 void OnDataRequested();
169 void OnStarvation() { is_starved_
= true; }
170 void OnStopDone() { is_stopped_
= true; }
172 void OnUpdateCurrentTime(base::TimeDelta now_playing
,
173 base::TimeDelta last_buffered
) {
174 pts_stat_
.AddValue(now_playing
);
176 if (stop_request_time_
!= kNoTimestamp() &&
177 now_playing
>= stop_request_time_
) {
178 stop_request_time_
= kNoTimestamp();
179 decoder_
->RequestToStop();
183 void OnVideoSizeChanged(const gfx::Size
& video_size
) {}
184 void OnVideoCodecCreated() {}
186 scoped_ptr
<MediaCodecDecoder
> decoder_
;
187 scoped_ptr
<TestDataFactory
> data_factory_
;
188 Minimax
<base::TimeDelta
> pts_stat_
;
191 bool is_timeout_expired() const { return is_timeout_expired_
; }
192 void SetTimeoutExpired(bool value
) { is_timeout_expired_
= value
; }
194 base::MessageLoop message_loop_
;
195 bool is_timeout_expired_
;
200 base::TimeDelta stop_request_time_
;
202 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
203 DataAvailableCallback data_available_cb_
;
204 scoped_refptr
<gfx::SurfaceTexture
> surface_texture_
;
206 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoderTest
);
209 MediaCodecDecoderTest::MediaCodecDecoderTest()
210 : is_timeout_expired_(false),
211 is_prefetched_(false),
214 stop_request_time_(kNoTimestamp()),
215 task_runner_(base::ThreadTaskRunnerHandle::Get()) {
218 MediaCodecDecoderTest::~MediaCodecDecoderTest() {}
220 bool MediaCodecDecoderTest::WaitForCondition(const Predicate
& condition
,
221 const base::TimeDelta
& timeout
) {
222 // Let the message_loop_ process events.
223 // We start the timer and RunUntilIdle() until it signals.
225 SetTimeoutExpired(false);
227 base::Timer
timer(false, false);
228 timer
.Start(FROM_HERE
, timeout
,
229 base::Bind(&MediaCodecDecoderTest::SetTimeoutExpired
,
230 base::Unretained(this), true));
233 if (condition
.Run()) {
237 message_loop_
.RunUntilIdle();
238 } while (!is_timeout_expired());
240 DCHECK(!timer
.IsRunning());
244 void MediaCodecDecoderTest::CreateAudioDecoder() {
245 decoder_
= scoped_ptr
<MediaCodecDecoder
>(new MediaCodecAudioDecoder(
246 task_runner_
, base::Bind(&MediaCodecDecoderTest::OnDataRequested
,
247 base::Unretained(this)),
248 base::Bind(&MediaCodecDecoderTest::OnStarvation
, base::Unretained(this)),
249 base::Bind(&MediaCodecDecoderTest::OnStopDone
, base::Unretained(this)),
250 base::Bind(&MediaCodecDecoderTest::OnError
, base::Unretained(this)),
251 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime
,
252 base::Unretained(this))));
254 data_available_cb_
= base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable
,
255 base::Unretained(decoder_
.get()));
258 void MediaCodecDecoderTest::CreateVideoDecoder() {
259 decoder_
= scoped_ptr
<MediaCodecDecoder
>(new MediaCodecVideoDecoder(
260 task_runner_
, base::Bind(&MediaCodecDecoderTest::OnDataRequested
,
261 base::Unretained(this)),
262 base::Bind(&MediaCodecDecoderTest::OnStarvation
, base::Unretained(this)),
263 base::Bind(&MediaCodecDecoderTest::OnStopDone
, base::Unretained(this)),
264 base::Bind(&MediaCodecDecoderTest::OnError
, base::Unretained(this)),
265 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime
,
266 base::Unretained(this)),
267 base::Bind(&MediaCodecDecoderTest::OnVideoSizeChanged
,
268 base::Unretained(this)),
269 base::Bind(&MediaCodecDecoderTest::OnVideoCodecCreated
,
270 base::Unretained(this))));
272 data_available_cb_
= base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable
,
273 base::Unretained(decoder_
.get()));
276 void MediaCodecDecoderTest::OnDataRequested() {
281 base::TimeDelta delay
;
282 if (!data_factory_
->CreateChunk(&data
, &delay
))
285 task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(data_available_cb_
, data
),
289 void MediaCodecDecoderTest::SetVideoSurface() {
290 surface_texture_
= gfx::SurfaceTexture::Create(0);
291 gfx::ScopedJavaSurface
surface(surface_texture_
.get());
292 ASSERT_NE(nullptr, decoder_
.get());
293 MediaCodecVideoDecoder
* video_decoder
=
294 static_cast<MediaCodecVideoDecoder
*>(decoder_
.get());
295 video_decoder
->SetPendingSurface(surface
.Pass());
298 TEST_F(MediaCodecDecoderTest
, AudioPrefetch
) {
299 CreateAudioDecoder();
301 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
302 SetDataFactory(scoped_ptr
<TestDataFactory
>(new AudioFactory(duration
)));
304 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
305 base::Unretained(this), true));
307 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
308 base::Unretained(this))));
311 TEST_F(MediaCodecDecoderTest
, VideoPrefetch
) {
312 CreateVideoDecoder();
314 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
315 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
317 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
318 base::Unretained(this), true));
320 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
321 base::Unretained(this))));
324 TEST_F(MediaCodecDecoderTest
, AudioConfigureNoParams
) {
325 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
327 CreateAudioDecoder();
329 // Cannot configure without config parameters.
330 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
333 TEST_F(MediaCodecDecoderTest
, AudioConfigureValidParams
) {
334 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
336 CreateAudioDecoder();
338 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
339 scoped_ptr
<AudioFactory
> factory(new AudioFactory(duration
));
340 decoder_
->SetDemuxerConfigs(factory
->GetConfigs());
342 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
345 TEST_F(MediaCodecDecoderTest
, VideoConfigureNoParams
) {
346 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
348 CreateVideoDecoder();
350 // Cannot configure without config parameters.
351 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
354 TEST_F(MediaCodecDecoderTest
, VideoConfigureNoSurface
) {
355 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
357 CreateVideoDecoder();
359 // decoder_->Configure() searches back for the key frame.
360 // We have to prefetch decoder.
362 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
363 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
365 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
366 base::Unretained(this), true));
368 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
369 base::Unretained(this))));
371 decoder_
->SetDemuxerConfigs(GetConfigs());
373 // Surface is not set, Configure() should fail.
375 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
378 TEST_F(MediaCodecDecoderTest
, VideoConfigureInvalidSurface
) {
379 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
381 CreateVideoDecoder();
383 // decoder_->Configure() searches back for the key frame.
384 // We have to prefetch decoder.
386 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
387 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
389 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
390 base::Unretained(this), true));
392 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
393 base::Unretained(this))));
395 decoder_
->SetDemuxerConfigs(GetConfigs());
397 // Prepare the surface.
398 scoped_refptr
<gfx::SurfaceTexture
> surface_texture(
399 gfx::SurfaceTexture::Create(0));
400 gfx::ScopedJavaSurface
surface(surface_texture
.get());
402 // Release the surface texture.
403 surface_texture
= NULL
;
405 MediaCodecVideoDecoder
* video_decoder
=
406 static_cast<MediaCodecVideoDecoder
*>(decoder_
.get());
407 video_decoder
->SetPendingSurface(surface
.Pass());
409 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
412 TEST_F(MediaCodecDecoderTest
, VideoConfigureValidParams
) {
413 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
415 CreateVideoDecoder();
417 // decoder_->Configure() searches back for the key frame.
418 // We have to prefetch decoder.
420 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
421 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
423 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
424 base::Unretained(this), true));
426 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
427 base::Unretained(this))));
429 decoder_
->SetDemuxerConfigs(GetConfigs());
433 // Now we can expect Configure() to succeed.
435 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
438 TEST_F(MediaCodecDecoderTest
, AudioStartWithoutConfigure
) {
439 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
441 CreateAudioDecoder();
443 // Decoder has to be prefetched and configured before the start.
445 // Wrong state: not prefetched
446 EXPECT_FALSE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
449 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
450 SetDataFactory(scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
452 // Prefetch to avoid starvation at the beginning of playback.
453 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
454 base::Unretained(this), true));
456 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
457 base::Unretained(this))));
459 // Still, decoder is not configured.
460 EXPECT_FALSE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
463 TEST_F(MediaCodecDecoderTest
, AudioPlayTillCompletion
) {
464 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
466 CreateAudioDecoder();
468 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
469 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(600);
471 SetDataFactory(scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
473 // Prefetch to avoid starvation at the beginning of playback.
474 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
475 base::Unretained(this), true));
477 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
478 base::Unretained(this))));
480 decoder_
->SetDemuxerConfigs(GetConfigs());
482 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
484 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
486 EXPECT_TRUE(WaitForCondition(
487 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
490 EXPECT_TRUE(decoder_
->IsStopped());
491 EXPECT_TRUE(decoder_
->IsCompleted());
493 // It is hard to properly estimate minimum and maximum values because
494 // reported times are different from PTS.
495 EXPECT_EQ(25, pts_stat_
.num_values());
498 TEST_F(MediaCodecDecoderTest
, VideoPlayTillCompletion
) {
499 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
501 CreateVideoDecoder();
503 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
504 // The first output frame might come out with significant delay. Apparently
505 // the codec does initial configuration at this time. We increase the timeout
506 // to leave a room of 1 second for this initial configuration.
507 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1500);
508 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
511 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
512 base::Unretained(this), true));
514 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
515 base::Unretained(this))));
517 decoder_
->SetDemuxerConfigs(GetConfigs());
521 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
523 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
525 EXPECT_TRUE(WaitForCondition(
526 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
529 EXPECT_TRUE(decoder_
->IsStopped());
530 EXPECT_TRUE(decoder_
->IsCompleted());
532 EXPECT_EQ(26, pts_stat_
.num_values());
533 EXPECT_EQ(data_factory_
->last_pts(), pts_stat_
.max());
536 TEST_F(MediaCodecDecoderTest
, VideoStopAndResume
) {
537 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
539 CreateVideoDecoder();
541 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
542 base::TimeDelta stop_request_time
= base::TimeDelta::FromMilliseconds(200);
543 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1000);
545 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
548 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
549 base::Unretained(this), true));
551 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
552 base::Unretained(this))));
554 decoder_
->SetDemuxerConfigs(GetConfigs());
558 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
560 SetStopRequestAtTime(stop_request_time
);
562 // Start from the beginning.
563 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
565 EXPECT_TRUE(WaitForCondition(
566 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
569 EXPECT_TRUE(decoder_
->IsStopped());
570 EXPECT_FALSE(decoder_
->IsCompleted());
572 base::TimeDelta last_pts
= pts_stat_
.max();
574 EXPECT_GE(last_pts
, stop_request_time
);
576 // Resume playback from last_pts:
578 SetPrefetched(false);
582 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
583 base::Unretained(this), true));
585 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
586 base::Unretained(this))));
589 EXPECT_TRUE(decoder_
->Start(last_pts
));
591 // Wait till completion.
592 EXPECT_TRUE(WaitForCondition(
593 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
596 EXPECT_TRUE(decoder_
->IsStopped());
597 EXPECT_TRUE(decoder_
->IsCompleted());
599 // We should not skip frames in this process.
600 EXPECT_EQ(26, pts_stat_
.num_values());
601 EXPECT_EQ(data_factory_
->last_pts(), pts_stat_
.max());
604 TEST_F(MediaCodecDecoderTest
, AudioStarvationAndStop
) {
605 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
607 CreateAudioDecoder();
609 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(200);
610 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(400);
612 AudioFactory
* factory
= new AudioFactory(duration
);
613 factory
->SetStarvationMode(true);
614 SetDataFactory(scoped_ptr
<AudioFactory
>(factory
));
617 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
618 base::Unretained(this), true));
620 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
621 base::Unretained(this))));
624 decoder_
->SetDemuxerConfigs(GetConfigs());
626 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
629 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
631 // Wait for starvation.
632 EXPECT_TRUE(WaitForCondition(
633 base::Bind(&MediaCodecDecoderTest::is_starved
, base::Unretained(this)),
636 EXPECT_FALSE(decoder_
->IsStopped());
637 EXPECT_FALSE(decoder_
->IsCompleted());
639 EXPECT_GT(pts_stat_
.num_values(), 0);
641 // After starvation we should be able to stop decoder.
642 decoder_
->RequestToStop();
644 EXPECT_TRUE(WaitForCondition(
645 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this))));
647 EXPECT_TRUE(decoder_
->IsStopped());
648 EXPECT_FALSE(decoder_
->IsCompleted());