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 "media/base/android/test_statistics.h"
14 #include "media/base/buffers.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gl/android/surface_texture.h"
20 // Helper macro to skip the test if MediaCodecBridge isn't available.
21 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \
23 if (!MediaCodecBridge::IsAvailable()) { \
24 VLOG(0) << "Could not run test - not supported on device."; \
31 const base::TimeDelta kDefaultTimeout
= base::TimeDelta::FromMilliseconds(200);
32 const base::TimeDelta kAudioFramePeriod
=
33 base::TimeDelta::FromSecondsD(1024.0 / 44100); // 1024 samples @ 44100 Hz
34 const base::TimeDelta kVideoFramePeriod
= base::TimeDelta::FromMilliseconds(20);
36 class AudioFactory
: public TestDataFactory
{
38 AudioFactory(base::TimeDelta duration
);
39 DemuxerConfigs
GetConfigs() const override
;
42 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
;
45 class VideoFactory
: public TestDataFactory
{
47 VideoFactory(base::TimeDelta duration
);
48 DemuxerConfigs
GetConfigs() const override
;
51 void ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) override
;
54 AudioFactory::AudioFactory(base::TimeDelta duration
)
55 : TestDataFactory("aac-44100-packet-%d", duration
, kAudioFramePeriod
) {
58 DemuxerConfigs
AudioFactory::GetConfigs() const {
59 return TestDataFactory::CreateAudioConfigs(kCodecAAC
, duration_
);
62 void AudioFactory::ModifyAccessUnit(int index_in_chunk
, AccessUnit
* unit
) {
63 unit
->is_key_frame
= true;
66 VideoFactory::VideoFactory(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. Make first frame a key frame.
86 switch (index_in_chunk
) {
87 case 0: // first frame
88 unit
->is_key_frame
= true;
90 case 1: // second frame
91 unit
->timestamp
+= frame_period_
;
93 case 2: // third frame
94 unit
->timestamp
-= frame_period_
;
96 case 3: // fourth frame, do not modify
104 } // namespace (anonymous)
106 // The test fixture for MediaCodecDecoder
108 class MediaCodecDecoderTest
: public testing::Test
{
110 MediaCodecDecoderTest();
111 ~MediaCodecDecoderTest() override
;
113 // Conditions we wait for.
114 bool is_prefetched() const { return is_prefetched_
; }
115 bool is_stopped() const { return is_stopped_
; }
116 bool is_starved() const { return is_starved_
; }
118 void SetPrefetched(bool value
) { is_prefetched_
= value
; }
119 void SetStopped(bool value
) { is_stopped_
= value
; }
120 void SetStarved(bool value
) { is_starved_
= value
; }
123 typedef base::Callback
<bool()> Predicate
;
125 typedef base::Callback
<void(const DemuxerData
&)> DataAvailableCallback
;
127 // Waits for condition to become true or for timeout to expire.
128 // Returns true if the condition becomes true.
129 bool WaitForCondition(const Predicate
& condition
,
130 const base::TimeDelta
& timeout
= kDefaultTimeout
);
132 void SetDataFactory(scoped_ptr
<TestDataFactory
> factory
) {
133 data_factory_
= factory
.Pass();
136 DemuxerConfigs
GetConfigs() const {
137 // ASSERT_NE does not compile here because it expects void return value.
138 EXPECT_NE(nullptr, data_factory_
.get());
139 return data_factory_
->GetConfigs();
142 void CreateAudioDecoder();
143 void CreateVideoDecoder();
144 void SetVideoSurface();
145 void SetStopRequestAtTime(const base::TimeDelta
& time
) {
146 stop_request_time_
= time
;
149 // Decoder callbacks.
150 void OnDataRequested();
151 void OnStarvation() { is_starved_
= true; }
152 void OnStopDone() { is_stopped_
= true; }
154 void OnUpdateCurrentTime(base::TimeDelta now_playing
,
155 base::TimeDelta last_buffered
) {
156 // Add the |last_buffered| value for PTS. For video it is the same as
157 // |now_playing| and is equal to PTS, for audio |last_buffered| should
159 pts_stat_
.AddValue(last_buffered
);
161 if (stop_request_time_
!= kNoTimestamp() &&
162 now_playing
>= stop_request_time_
) {
163 stop_request_time_
= kNoTimestamp();
164 decoder_
->RequestToStop();
168 void OnVideoSizeChanged(const gfx::Size
& video_size
) {}
169 void OnVideoCodecCreated() {}
171 scoped_ptr
<MediaCodecDecoder
> decoder_
;
172 scoped_ptr
<TestDataFactory
> data_factory_
;
173 Minimax
<base::TimeDelta
> pts_stat_
;
176 bool is_timeout_expired() const { return is_timeout_expired_
; }
177 void SetTimeoutExpired(bool value
) { is_timeout_expired_
= value
; }
179 base::MessageLoop message_loop_
;
180 bool is_timeout_expired_
;
185 base::TimeDelta stop_request_time_
;
187 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
188 DataAvailableCallback data_available_cb_
;
189 scoped_refptr
<gfx::SurfaceTexture
> surface_texture_
;
191 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoderTest
);
194 MediaCodecDecoderTest::MediaCodecDecoderTest()
195 : is_timeout_expired_(false),
196 is_prefetched_(false),
199 stop_request_time_(kNoTimestamp()),
200 task_runner_(base::ThreadTaskRunnerHandle::Get()) {
203 MediaCodecDecoderTest::~MediaCodecDecoderTest() {}
205 bool MediaCodecDecoderTest::WaitForCondition(const Predicate
& condition
,
206 const base::TimeDelta
& timeout
) {
207 // Let the message_loop_ process events.
208 // We start the timer and RunUntilIdle() until it signals.
210 SetTimeoutExpired(false);
212 base::Timer
timer(false, false);
213 timer
.Start(FROM_HERE
, timeout
,
214 base::Bind(&MediaCodecDecoderTest::SetTimeoutExpired
,
215 base::Unretained(this), true));
218 if (condition
.Run()) {
222 message_loop_
.RunUntilIdle();
223 } while (!is_timeout_expired());
225 DCHECK(!timer
.IsRunning());
229 void MediaCodecDecoderTest::CreateAudioDecoder() {
230 decoder_
= scoped_ptr
<MediaCodecDecoder
>(new MediaCodecAudioDecoder(
231 task_runner_
, base::Bind(&MediaCodecDecoderTest::OnDataRequested
,
232 base::Unretained(this)),
233 base::Bind(&MediaCodecDecoderTest::OnStarvation
, base::Unretained(this)),
234 base::Bind(&MediaCodecDecoderTest::OnStopDone
, base::Unretained(this)),
235 base::Bind(&MediaCodecDecoderTest::OnError
, base::Unretained(this)),
236 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime
,
237 base::Unretained(this))));
239 data_available_cb_
= base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable
,
240 base::Unretained(decoder_
.get()));
243 void MediaCodecDecoderTest::CreateVideoDecoder() {
244 decoder_
= scoped_ptr
<MediaCodecDecoder
>(new MediaCodecVideoDecoder(
245 task_runner_
, base::Bind(&MediaCodecDecoderTest::OnDataRequested
,
246 base::Unretained(this)),
247 base::Bind(&MediaCodecDecoderTest::OnStarvation
, base::Unretained(this)),
248 base::Bind(&MediaCodecDecoderTest::OnStopDone
, base::Unretained(this)),
249 base::Bind(&MediaCodecDecoderTest::OnError
, base::Unretained(this)),
250 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime
,
251 base::Unretained(this)),
252 base::Bind(&MediaCodecDecoderTest::OnVideoSizeChanged
,
253 base::Unretained(this)),
254 base::Bind(&MediaCodecDecoderTest::OnVideoCodecCreated
,
255 base::Unretained(this))));
257 data_available_cb_
= base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable
,
258 base::Unretained(decoder_
.get()));
261 void MediaCodecDecoderTest::OnDataRequested() {
266 base::TimeDelta delay
;
267 if (!data_factory_
->CreateChunk(&data
, &delay
))
270 task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(data_available_cb_
, data
),
274 void MediaCodecDecoderTest::SetVideoSurface() {
275 surface_texture_
= gfx::SurfaceTexture::Create(0);
276 gfx::ScopedJavaSurface
surface(surface_texture_
.get());
277 ASSERT_NE(nullptr, decoder_
.get());
278 MediaCodecVideoDecoder
* video_decoder
=
279 static_cast<MediaCodecVideoDecoder
*>(decoder_
.get());
280 video_decoder
->SetPendingSurface(surface
.Pass());
283 TEST_F(MediaCodecDecoderTest
, AudioPrefetch
) {
284 CreateAudioDecoder();
286 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
287 SetDataFactory(scoped_ptr
<TestDataFactory
>(new AudioFactory(duration
)));
289 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
290 base::Unretained(this), true));
292 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
293 base::Unretained(this))));
296 TEST_F(MediaCodecDecoderTest
, VideoPrefetch
) {
297 CreateVideoDecoder();
299 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
300 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
302 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
303 base::Unretained(this), true));
305 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
306 base::Unretained(this))));
309 TEST_F(MediaCodecDecoderTest
, AudioConfigureNoParams
) {
310 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
312 CreateAudioDecoder();
314 // Cannot configure without config parameters.
315 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
318 TEST_F(MediaCodecDecoderTest
, AudioConfigureValidParams
) {
319 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
321 CreateAudioDecoder();
323 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
324 scoped_ptr
<AudioFactory
> factory(new AudioFactory(duration
));
325 decoder_
->SetDemuxerConfigs(factory
->GetConfigs());
327 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
330 TEST_F(MediaCodecDecoderTest
, VideoConfigureNoParams
) {
331 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
333 CreateVideoDecoder();
335 // Cannot configure without config parameters.
336 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
339 TEST_F(MediaCodecDecoderTest
, VideoConfigureNoSurface
) {
340 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
342 CreateVideoDecoder();
344 // decoder_->Configure() searches back for the key frame.
345 // We have to prefetch decoder.
347 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
348 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
350 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
351 base::Unretained(this), true));
353 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
354 base::Unretained(this))));
356 decoder_
->SetDemuxerConfigs(GetConfigs());
358 // Surface is not set, Configure() should fail.
360 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
363 TEST_F(MediaCodecDecoderTest
, VideoConfigureInvalidSurface
) {
364 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
366 CreateVideoDecoder();
368 // decoder_->Configure() searches back for the key frame.
369 // We have to prefetch decoder.
371 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
372 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
374 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
375 base::Unretained(this), true));
377 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
378 base::Unretained(this))));
380 decoder_
->SetDemuxerConfigs(GetConfigs());
382 // Prepare the surface.
383 scoped_refptr
<gfx::SurfaceTexture
> surface_texture(
384 gfx::SurfaceTexture::Create(0));
385 gfx::ScopedJavaSurface
surface(surface_texture
.get());
387 // Release the surface texture.
388 surface_texture
= NULL
;
390 MediaCodecVideoDecoder
* video_decoder
=
391 static_cast<MediaCodecVideoDecoder
*>(decoder_
.get());
392 video_decoder
->SetPendingSurface(surface
.Pass());
394 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE
, decoder_
->Configure());
397 TEST_F(MediaCodecDecoderTest
, VideoConfigureValidParams
) {
398 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
400 CreateVideoDecoder();
402 // decoder_->Configure() searches back for the key frame.
403 // We have to prefetch decoder.
405 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
406 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
408 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
409 base::Unretained(this), true));
411 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
412 base::Unretained(this))));
414 decoder_
->SetDemuxerConfigs(GetConfigs());
418 // Now we can expect Configure() to succeed.
420 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
423 TEST_F(MediaCodecDecoderTest
, AudioStartWithoutConfigure
) {
424 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
426 CreateAudioDecoder();
428 // Decoder has to be prefetched and configured before the start.
430 // Wrong state: not prefetched
431 EXPECT_FALSE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
434 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
435 SetDataFactory(scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
437 // Prefetch to avoid starvation at the beginning of playback.
438 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
439 base::Unretained(this), true));
441 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
442 base::Unretained(this))));
444 // Still, decoder is not configured.
445 EXPECT_FALSE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
448 TEST_F(MediaCodecDecoderTest
, AudioPlayTillCompletion
) {
449 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
451 CreateAudioDecoder();
453 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
454 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1500);
456 SetDataFactory(scoped_ptr
<AudioFactory
>(new AudioFactory(duration
)));
458 // Prefetch to avoid starvation at the beginning of playback.
459 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
460 base::Unretained(this), true));
462 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
463 base::Unretained(this))));
465 decoder_
->SetDemuxerConfigs(GetConfigs());
467 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
469 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
471 EXPECT_TRUE(WaitForCondition(
472 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
475 EXPECT_TRUE(decoder_
->IsStopped());
476 EXPECT_TRUE(decoder_
->IsCompleted());
478 // Last buffered timestamp should be no less than PTS.
479 EXPECT_EQ(22, pts_stat_
.num_values());
480 EXPECT_LE(data_factory_
->last_pts(), pts_stat_
.max());
483 TEST_F(MediaCodecDecoderTest
, VideoPlayTillCompletion
) {
484 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
486 CreateVideoDecoder();
488 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
489 // The first output frame might come out with significant delay. Apparently
490 // the codec does initial configuration at this time. We increase the timeout
491 // to leave a room of 1 second for this initial configuration.
492 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1500);
493 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
496 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
497 base::Unretained(this), true));
499 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
500 base::Unretained(this))));
502 decoder_
->SetDemuxerConfigs(GetConfigs());
506 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
508 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
510 EXPECT_TRUE(WaitForCondition(
511 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
514 EXPECT_TRUE(decoder_
->IsStopped());
515 EXPECT_TRUE(decoder_
->IsCompleted());
517 EXPECT_EQ(26, pts_stat_
.num_values());
518 EXPECT_EQ(data_factory_
->last_pts(), pts_stat_
.max());
521 TEST_F(MediaCodecDecoderTest
, VideoStopAndResume
) {
522 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
524 CreateVideoDecoder();
526 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(500);
527 base::TimeDelta stop_request_time
= base::TimeDelta::FromMilliseconds(200);
528 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(1000);
530 SetDataFactory(scoped_ptr
<VideoFactory
>(new VideoFactory(duration
)));
533 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
534 base::Unretained(this), true));
536 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
537 base::Unretained(this))));
539 decoder_
->SetDemuxerConfigs(GetConfigs());
543 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
545 SetStopRequestAtTime(stop_request_time
);
547 // Start from the beginning.
548 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
550 EXPECT_TRUE(WaitForCondition(
551 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
554 EXPECT_TRUE(decoder_
->IsStopped());
555 EXPECT_FALSE(decoder_
->IsCompleted());
557 base::TimeDelta last_pts
= pts_stat_
.max();
559 EXPECT_GE(last_pts
, stop_request_time
);
561 // Resume playback from last_pts:
563 SetPrefetched(false);
567 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
568 base::Unretained(this), true));
570 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
571 base::Unretained(this))));
574 EXPECT_TRUE(decoder_
->Start(last_pts
));
576 // Wait till completion.
577 EXPECT_TRUE(WaitForCondition(
578 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this)),
581 EXPECT_TRUE(decoder_
->IsStopped());
582 EXPECT_TRUE(decoder_
->IsCompleted());
584 // We should not skip frames in this process.
585 EXPECT_EQ(26, pts_stat_
.num_values());
586 EXPECT_EQ(data_factory_
->last_pts(), pts_stat_
.max());
589 TEST_F(MediaCodecDecoderTest
, AudioStarvationAndStop
) {
590 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE();
592 CreateAudioDecoder();
594 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(200);
595 base::TimeDelta timeout
= base::TimeDelta::FromMilliseconds(400);
597 AudioFactory
* factory
= new AudioFactory(duration
);
598 factory
->SetStarvationMode(true);
599 SetDataFactory(scoped_ptr
<AudioFactory
>(factory
));
602 decoder_
->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched
,
603 base::Unretained(this), true));
605 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched
,
606 base::Unretained(this))));
609 decoder_
->SetDemuxerConfigs(GetConfigs());
611 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK
, decoder_
->Configure());
614 EXPECT_TRUE(decoder_
->Start(base::TimeDelta::FromMilliseconds(0)));
616 // Wait for starvation.
617 EXPECT_TRUE(WaitForCondition(
618 base::Bind(&MediaCodecDecoderTest::is_starved
, base::Unretained(this)),
621 EXPECT_FALSE(decoder_
->IsStopped());
622 EXPECT_FALSE(decoder_
->IsCompleted());
624 EXPECT_GT(pts_stat_
.num_values(), 0);
626 // After starvation we should be able to stop decoder.
627 decoder_
->RequestToStop();
629 EXPECT_TRUE(WaitForCondition(
630 base::Bind(&MediaCodecDecoderTest::is_stopped
, base::Unretained(this))));
632 EXPECT_TRUE(decoder_
->IsStopped());
633 EXPECT_FALSE(decoder_
->IsCompleted());