Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/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" | |
| 15 | |
| 16 namespace media { | |
| 17 | |
| 18 // Helper macro to skip the test if MediaCodecBridge isn't available. | |
| 19 #define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ | |
| 20 do { \ | |
| 21 if (!MediaCodecBridge::IsAvailable()) { \ | |
| 22 VLOG(0) << "Could not run test - not supported on device."; \ | |
| 23 return; \ | |
| 24 } \ | |
| 25 } while (0) | |
| 26 | |
| 27 namespace { | |
| 28 | |
| 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); | |
| 32 | |
| 33 class AudioFactory : public TestDataFactory { | |
| 34 public: | |
| 35 AudioFactory(const base::TimeDelta& duration); | |
| 36 DemuxerConfigs GetConfigs(); | |
| 37 | |
| 38 protected: | |
| 39 void ModifyAccessUnit(int index_in_chunk, AccessUnit* unit) override; | |
| 40 }; | |
| 41 | |
| 42 class VideoFactory : public TestDataFactory { | |
| 43 public: | |
| 44 VideoFactory(const base::TimeDelta& duration); | |
| 45 DemuxerConfigs GetConfigs(); | |
| 46 | |
| 47 protected: | |
| 48 void ModifyAccessUnit(int index_in_chunk, AccessUnit* unit) override; | |
| 49 }; | |
| 50 | |
| 51 AudioFactory::AudioFactory(const base::TimeDelta& duration) | |
| 52 : TestDataFactory("vorbis-packet-%d", duration, kAudioFramePeriod) { | |
| 53 } | |
| 54 | |
| 55 DemuxerConfigs AudioFactory::GetConfigs() { | |
| 56 return TestDataFactory::CreateAudioConfigs(kCodecVorbis, duration_); | |
| 57 } | |
| 58 | |
| 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); | |
| 64 } | |
| 65 | |
| 66 VideoFactory::VideoFactory(const base::TimeDelta& duration) | |
| 67 : TestDataFactory("h264-320x180-frame-%d", duration, kVideoFramePeriod) { | |
| 68 } | |
| 69 | |
| 70 DemuxerConfigs VideoFactory::GetConfigs() { | |
| 71 return TestDataFactory::CreateVideoConfigs(kCodecH264, duration_, | |
| 72 gfx::Size(320, 180)); | |
| 73 } | |
| 74 | |
| 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: | |
| 78 // | |
| 79 // Frames: I P B P | |
| 80 // Decoding order: 0 1 2 3 | |
| 81 // Presentation order: 0 2 1 4(3) | |
| 82 // | |
| 83 // I keep the last PTS to be 3 for simplicity. | |
| 84 | |
| 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_; | |
| 90 | |
| 91 if (index_in_chunk == 0) | |
| 92 unit->is_key_frame = true; | |
| 93 } | |
| 94 | |
| 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. | |
| 97 | |
| 98 template <typename T> | |
| 99 class Minimax { | |
| 100 public: | |
| 101 Minimax() : num_values_(0) {} | |
| 102 ~Minimax() {} | |
| 103 | |
| 104 void AddValue(const T& value) { | |
| 105 ++num_values_; | |
| 106 if (value < min_) | |
| 107 min_ = value; | |
| 108 else if (max_ < value) | |
| 109 max_ = value; | |
| 110 } | |
| 111 | |
| 112 const T& min() const { return min_; } | |
| 113 const T& max() const { return max_; } | |
| 114 int num_values() const { return num_values_; } | |
| 115 | |
| 116 private: | |
| 117 T min_; | |
| 118 T max_; | |
| 119 int num_values_; | |
| 120 }; | |
| 121 | |
| 122 } // namespace (anonymous) | |
| 123 | |
| 124 // The test fixture for MediaCodecDecoder | |
| 125 | |
| 126 class MediaCodecDecoderTest : public testing::Test { | |
| 127 public: | |
| 128 MediaCodecDecoderTest(); | |
| 129 ~MediaCodecDecoderTest() override; | |
| 130 | |
| 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_; } | |
| 135 | |
| 136 // Prefetch callback has to be public. | |
| 137 void SetPrefetched() { is_prefetched_ = true; } | |
| 138 | |
| 139 protected: | |
| 140 typedef base::Callback<bool()> Predicate; | |
| 141 | |
| 142 typedef base::Callback<void(const DemuxerData&)> DataAvailableCallback; | |
| 143 | |
| 144 // Waits for condition to become true or for timeout to expire. | |
| 145 // Returns true if the condition becomes true. | |
| 146 bool WaitForCondition(const Predicate& condition, | |
| 147 const base::TimeDelta& timeout = kDefaultTimeout); | |
| 148 | |
| 149 void SetDataFactory(scoped_refptr<TestDataFactory> factory) { | |
| 150 data_factory_ = factory; | |
| 151 } | |
| 152 | |
| 153 void CreateAudioDecoder(); | |
| 154 void CreateVideoDecoder(); | |
| 155 void SetVideoSurface(); | |
| 156 | |
| 157 // Decoder callbacks. | |
| 158 void OnDataRequested(); | |
| 159 void OnStarvation() { is_starved_ = true; } | |
| 160 void OnStopDone() { is_stopped_ = true; } | |
| 161 void OnError() {} | |
| 162 void OnUpdateCurrentTime(base::TimeDelta now_playing, | |
| 163 base::TimeDelta last_buffered) { | |
| 164 pts_stat_.AddValue(now_playing); | |
| 165 } | |
| 166 void OnVideoSizeChanged(const gfx::Size& video_size) {} | |
| 167 void OnVideoCodecCreated() {} | |
| 168 | |
| 169 scoped_ptr<MediaCodecDecoder> decoder_; | |
| 170 scoped_refptr<TestDataFactory> data_factory_; | |
| 171 Minimax<base::TimeDelta> pts_stat_; | |
| 172 | |
| 173 private: | |
| 174 bool is_timeout_expired() const { return is_timeout_expired_; } | |
| 175 void SetTimeoutExpired(bool value) { is_timeout_expired_ = value; } | |
| 176 | |
| 177 base::MessageLoop message_loop_; | |
| 178 bool is_timeout_expired_; | |
| 179 | |
| 180 bool is_prefetched_; | |
| 181 bool is_stopped_; | |
| 182 bool is_starved_; | |
| 183 | |
| 184 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 185 DataAvailableCallback data_available_cb_; | |
| 186 scoped_refptr<gfx::SurfaceTexture> surface_texture_; | |
| 187 | |
| 188 DISALLOW_COPY_AND_ASSIGN(MediaCodecDecoderTest); | |
| 189 }; | |
| 190 | |
| 191 MediaCodecDecoderTest::MediaCodecDecoderTest() | |
| 192 : is_timeout_expired_(false), | |
| 193 is_prefetched_(false), | |
| 194 is_stopped_(false), | |
| 195 is_starved_(false), | |
| 196 task_runner_(base::ThreadTaskRunnerHandle::Get()) { | |
| 197 } | |
| 198 | |
| 199 MediaCodecDecoderTest::~MediaCodecDecoderTest() { | |
| 200 } | |
|
qinmin
2015/06/18 00:24:40
this can go to the previous line
Tima Vaisburd
2015/06/18 19:34:04
Done.
| |
| 201 | |
| 202 bool MediaCodecDecoderTest::WaitForCondition(const Predicate& condition, | |
| 203 const base::TimeDelta& timeout) { | |
| 204 // Let the message_loop_ process events. | |
| 205 // We start the timer and RunUntilIdle() until it signals. | |
| 206 | |
| 207 SetTimeoutExpired(false); | |
| 208 | |
| 209 base::Timer timer(false, false); | |
| 210 timer.Start(FROM_HERE, timeout, | |
| 211 base::Bind(&MediaCodecDecoderTest::SetTimeoutExpired, | |
| 212 base::Unretained(this), true)); | |
| 213 | |
| 214 do { | |
| 215 if (condition.Run()) { | |
| 216 timer.Stop(); | |
| 217 return true; | |
| 218 } | |
| 219 message_loop_.RunUntilIdle(); | |
| 220 } while (!is_timeout_expired()); | |
| 221 | |
| 222 DCHECK(!timer.IsRunning()); | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 void MediaCodecDecoderTest::CreateAudioDecoder() { | |
| 227 decoder_ = scoped_ptr<MediaCodecDecoder>(new MediaCodecAudioDecoder( | |
| 228 task_runner_, base::Bind(&MediaCodecDecoderTest::OnDataRequested, | |
| 229 base::Unretained(this)), | |
| 230 base::Bind(&MediaCodecDecoderTest::OnStarvation, base::Unretained(this)), | |
| 231 base::Bind(&MediaCodecDecoderTest::OnStopDone, base::Unretained(this)), | |
| 232 base::Bind(&MediaCodecDecoderTest::OnError, base::Unretained(this)), | |
| 233 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime, | |
| 234 base::Unretained(this)))); | |
| 235 | |
| 236 data_available_cb_ = base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable, | |
| 237 base::Unretained(decoder_.get())); | |
| 238 } | |
| 239 | |
| 240 void MediaCodecDecoderTest::CreateVideoDecoder() { | |
| 241 decoder_ = scoped_ptr<MediaCodecDecoder>(new MediaCodecVideoDecoder( | |
| 242 task_runner_, base::Bind(&MediaCodecDecoderTest::OnDataRequested, | |
| 243 base::Unretained(this)), | |
| 244 base::Bind(&MediaCodecDecoderTest::OnStarvation, base::Unretained(this)), | |
| 245 base::Bind(&MediaCodecDecoderTest::OnStopDone, base::Unretained(this)), | |
| 246 base::Bind(&MediaCodecDecoderTest::OnError, base::Unretained(this)), | |
| 247 base::Bind(&MediaCodecDecoderTest::OnUpdateCurrentTime, | |
| 248 base::Unretained(this)), | |
| 249 base::Bind(&MediaCodecDecoderTest::OnVideoSizeChanged, | |
| 250 base::Unretained(this)), | |
| 251 base::Bind(&MediaCodecDecoderTest::OnVideoCodecCreated, | |
| 252 base::Unretained(this)))); | |
| 253 | |
| 254 data_available_cb_ = base::Bind(&MediaCodecDecoder::OnDemuxerDataAvailable, | |
| 255 base::Unretained(decoder_.get())); | |
| 256 } | |
| 257 | |
| 258 void MediaCodecDecoderTest::OnDataRequested() { | |
| 259 if (!data_factory_) | |
| 260 return; | |
| 261 | |
| 262 DemuxerData data; | |
| 263 base::TimeDelta delay; | |
| 264 data_factory_->CreateChunk(&data, &delay); | |
| 265 | |
| 266 task_runner_->PostDelayedTask(FROM_HERE, base::Bind(data_available_cb_, data), | |
| 267 delay); | |
| 268 } | |
| 269 | |
| 270 void MediaCodecDecoderTest::SetVideoSurface() { | |
| 271 surface_texture_ = gfx::SurfaceTexture::Create(0); | |
| 272 gfx::ScopedJavaSurface surface(surface_texture_.get()); | |
| 273 ASSERT_NE(nullptr, decoder_.get()); | |
| 274 MediaCodecVideoDecoder* video_decoder = | |
| 275 static_cast<MediaCodecVideoDecoder*>(decoder_.get()); | |
| 276 video_decoder->SetPendingSurface(surface.Pass()); | |
| 277 } | |
| 278 | |
| 279 TEST_F(MediaCodecDecoderTest, AudioPrefetch) { | |
| 280 CreateAudioDecoder(); | |
| 281 | |
| 282 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 283 SetDataFactory(scoped_refptr<TestDataFactory>(new AudioFactory(duration))); | |
| 284 | |
| 285 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 286 base::Unretained(this))); | |
| 287 | |
| 288 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 289 base::Unretained(this)))); | |
| 290 } | |
| 291 | |
| 292 TEST_F(MediaCodecDecoderTest, VideoPrefetch) { | |
| 293 CreateVideoDecoder(); | |
| 294 | |
| 295 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 296 SetDataFactory(scoped_refptr<TestDataFactory>(new VideoFactory(duration))); | |
| 297 | |
| 298 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 299 base::Unretained(this))); | |
| 300 | |
| 301 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 302 base::Unretained(this)))); | |
| 303 } | |
| 304 | |
| 305 TEST_F(MediaCodecDecoderTest, AudioConfigureNoParams) { | |
| 306 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 307 | |
| 308 CreateAudioDecoder(); | |
| 309 | |
| 310 // Cannot configure without config parameters. | |
| 311 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure()); | |
| 312 } | |
| 313 | |
| 314 TEST_F(MediaCodecDecoderTest, AudioConfigureValidParams) { | |
| 315 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 316 | |
| 317 CreateAudioDecoder(); | |
| 318 | |
| 319 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 320 scoped_refptr<AudioFactory> factory(new AudioFactory(duration)); | |
| 321 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 322 | |
| 323 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure()); | |
| 324 } | |
| 325 | |
| 326 TEST_F(MediaCodecDecoderTest, VideoConfigureNoParams) { | |
| 327 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 328 | |
| 329 CreateVideoDecoder(); | |
| 330 | |
| 331 // Cannot configure without config parameters. | |
| 332 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure()); | |
| 333 } | |
| 334 | |
| 335 TEST_F(MediaCodecDecoderTest, VideoConfigureNoSurface) { | |
| 336 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 337 | |
| 338 CreateVideoDecoder(); | |
| 339 | |
| 340 // decoder_->Configure() searches back for the key frame. | |
| 341 // We have to prefetch decoder. | |
| 342 | |
| 343 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 344 scoped_refptr<VideoFactory> factory(new VideoFactory(duration)); | |
| 345 SetDataFactory(factory); | |
| 346 | |
| 347 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 348 base::Unretained(this))); | |
| 349 | |
| 350 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 351 base::Unretained(this)))); | |
| 352 | |
| 353 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 354 | |
| 355 // Surface is not set, Configure() should fail. | |
| 356 | |
| 357 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure()); | |
| 358 } | |
| 359 | |
| 360 TEST_F(MediaCodecDecoderTest, VideoConfigureInvalidSurface) { | |
| 361 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 362 | |
| 363 CreateVideoDecoder(); | |
| 364 | |
| 365 // decoder_->Configure() searches back for the key frame. | |
| 366 // We have to prefetch decoder. | |
| 367 | |
| 368 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 369 scoped_refptr<VideoFactory> factory(new VideoFactory(duration)); | |
| 370 SetDataFactory(factory); | |
| 371 | |
| 372 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 373 base::Unretained(this))); | |
| 374 | |
| 375 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 376 base::Unretained(this)))); | |
| 377 | |
| 378 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 379 | |
| 380 // Prepare the surface. | |
| 381 scoped_refptr<gfx::SurfaceTexture> surface_texture( | |
| 382 gfx::SurfaceTexture::Create(0)); | |
| 383 gfx::ScopedJavaSurface surface(surface_texture.get()); | |
| 384 | |
| 385 // Release the surface texture. | |
| 386 surface_texture = NULL; | |
| 387 | |
| 388 MediaCodecVideoDecoder* video_decoder = | |
| 389 static_cast<MediaCodecVideoDecoder*>(decoder_.get()); | |
| 390 video_decoder->SetPendingSurface(surface.Pass()); | |
| 391 | |
| 392 EXPECT_EQ(MediaCodecDecoder::CONFIG_FAILURE, decoder_->Configure()); | |
| 393 } | |
| 394 | |
| 395 TEST_F(MediaCodecDecoderTest, VideoConfigureValidParams) { | |
| 396 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 397 | |
| 398 CreateVideoDecoder(); | |
| 399 | |
| 400 // decoder_->Configure() searches back for the key frame. | |
| 401 // We have to prefetch decoder. | |
| 402 | |
| 403 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 404 scoped_refptr<VideoFactory> factory(new VideoFactory(duration)); | |
| 405 SetDataFactory(factory); | |
| 406 | |
| 407 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 408 base::Unretained(this))); | |
| 409 | |
| 410 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 411 base::Unretained(this)))); | |
| 412 | |
| 413 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 414 | |
| 415 SetVideoSurface(); | |
| 416 | |
| 417 // Now we can expect Configure() to succeed. | |
| 418 | |
| 419 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure()); | |
| 420 } | |
| 421 | |
| 422 TEST_F(MediaCodecDecoderTest, AudioStartWithoutConfigure) { | |
| 423 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 424 | |
| 425 CreateAudioDecoder(); | |
| 426 | |
| 427 // Decoder has to be prefetched and configured before the start. | |
| 428 | |
| 429 // Wrong state: not prefetched | |
| 430 EXPECT_FALSE(decoder_->Start(base::TimeDelta::FromMilliseconds(0))); | |
| 431 | |
| 432 // Do the prefetch. | |
| 433 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 434 scoped_refptr<AudioFactory> factory(new AudioFactory(duration)); | |
| 435 SetDataFactory(factory); | |
| 436 | |
| 437 // Prefetch to avoid starvation at the beginning of playback. | |
| 438 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 439 base::Unretained(this))); | |
| 440 | |
| 441 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 442 base::Unretained(this)))); | |
| 443 | |
| 444 // Still, decoder is not configured. | |
| 445 EXPECT_FALSE(decoder_->Start(base::TimeDelta::FromMilliseconds(0))); | |
| 446 } | |
| 447 | |
| 448 TEST_F(MediaCodecDecoderTest, AudioPlayTillCompletion) { | |
| 449 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 450 | |
| 451 CreateAudioDecoder(); | |
| 452 | |
| 453 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 454 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(600); | |
| 455 scoped_refptr<AudioFactory> factory(new AudioFactory(duration)); | |
| 456 SetDataFactory(factory); | |
| 457 | |
| 458 // Prefetch to avoid starvation at the beginning of playback. | |
| 459 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 460 base::Unretained(this))); | |
| 461 | |
| 462 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 463 base::Unretained(this)))); | |
| 464 | |
| 465 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 466 | |
| 467 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure()); | |
| 468 | |
| 469 EXPECT_TRUE(decoder_->Start(base::TimeDelta::FromMilliseconds(0))); | |
| 470 | |
| 471 EXPECT_TRUE(WaitForCondition( | |
| 472 base::Bind(&MediaCodecDecoderTest::is_stopped, base::Unretained(this)), | |
| 473 timeout)); | |
| 474 | |
| 475 EXPECT_TRUE(decoder_->IsStopped()); | |
| 476 EXPECT_TRUE(decoder_->IsCompleted()); | |
| 477 | |
| 478 // It is hard to properly estimate minimum and maximum values because | |
| 479 // reported times are different from PTS. | |
| 480 EXPECT_EQ(25, pts_stat_.num_values()); | |
| 481 } | |
| 482 | |
| 483 TEST_F(MediaCodecDecoderTest, VideoPlayTillCompletion) { | |
| 484 SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); | |
| 485 | |
| 486 CreateVideoDecoder(); | |
| 487 | |
| 488 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(500); | |
| 489 base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(600); | |
| 490 scoped_refptr<VideoFactory> factory(new VideoFactory(duration)); | |
| 491 SetDataFactory(factory); | |
| 492 | |
| 493 // Prefetch | |
| 494 decoder_->Prefetch(base::Bind(&MediaCodecDecoderTest::SetPrefetched, | |
| 495 base::Unretained(this))); | |
| 496 | |
| 497 EXPECT_TRUE(WaitForCondition(base::Bind(&MediaCodecDecoderTest::is_prefetched, | |
| 498 base::Unretained(this)))); | |
| 499 | |
| 500 decoder_->SetDemuxerConfigs(factory->GetConfigs()); | |
| 501 | |
| 502 SetVideoSurface(); | |
| 503 | |
| 504 EXPECT_EQ(MediaCodecDecoder::CONFIG_OK, decoder_->Configure()); | |
| 505 | |
| 506 EXPECT_TRUE(decoder_->Start(base::TimeDelta::FromMilliseconds(0))); | |
| 507 | |
| 508 EXPECT_TRUE(WaitForCondition( | |
| 509 base::Bind(&MediaCodecDecoderTest::is_stopped, base::Unretained(this)), | |
| 510 timeout)); | |
| 511 | |
| 512 EXPECT_TRUE(decoder_->IsStopped()); | |
| 513 EXPECT_TRUE(decoder_->IsCompleted()); | |
| 514 | |
| 515 EXPECT_EQ(26, pts_stat_.num_values()); | |
| 516 EXPECT_EQ(data_factory_->last_pts(), pts_stat_.max()); | |
| 517 } | |
| 518 | |
| 519 } // namespace media | |
| OLD | NEW |