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. 4 5 #include <utility> 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/callback_helpers.h" 10 #include "base/debug/stack_trace.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/stl_util.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/synchronization/lock.h" 15 #include "base/timer/timer.h" 16 #include "media/base/data_buffer.h" 17 #include "media/base/gmock_callback_support.h" 18 #include "media/base/limits.h" 19 #include "media/base/mock_filters.h" 20 #include "media/base/test_helpers.h" 21 #include "media/base/video_frame.h" 22 #include "media/filters/video_renderer_base.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 using ::testing::_; 26 using ::testing::AnyNumber; 27 using ::testing::InSequence; 28 using ::testing::Invoke; 29 using ::testing::NiceMock; 30 using ::testing::NotNull; 31 using ::testing::Return; 32 using ::testing::StrictMock; 33 34 namespace media { 35 36 static const int kFrameDurationInMs = 10; 37 static const int kVideoDurationInMs = kFrameDurationInMs * 100; 38 39 class VideoRendererBaseTest : public ::testing::Test { 40 public: 41 VideoRendererBaseTest() 42 : decoder_(new MockVideoDecoder()), 43 demuxer_stream_(DemuxerStream::VIDEO) { 44 ScopedVector<VideoDecoder> decoders; 45 decoders.push_back(decoder_); 46 47 renderer_.reset(new VideoRendererBase( 48 message_loop_.message_loop_proxy(), 49 decoders.Pass(), 50 media::SetDecryptorReadyCB(), 51 base::Bind(&VideoRendererBaseTest::OnPaint, base::Unretained(this)), 52 base::Bind(&VideoRendererBaseTest::OnSetOpaque, base::Unretained(this)), 53 true)); 54 55 demuxer_stream_.set_video_decoder_config(TestVideoConfig::Normal()); 56 57 // We expect these to be called but we don't care how/when. 58 EXPECT_CALL(demuxer_stream_, Read(_)) 59 .WillRepeatedly(RunCallback<0>(DemuxerStream::kOk, 60 DecoderBuffer::CreateEOSBuffer())); 61 EXPECT_CALL(*decoder_, Stop(_)) 62 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::StopRequested)); 63 EXPECT_CALL(statistics_cb_object_, OnStatistics(_)) 64 .Times(AnyNumber()); 65 EXPECT_CALL(*this, OnTimeUpdate(_)) 66 .Times(AnyNumber()); 67 EXPECT_CALL(*this, OnSetOpaque(_)) 68 .Times(AnyNumber()); 69 } 70 71 virtual ~VideoRendererBaseTest() {} 72 73 // Callbacks passed into VideoRendererBase(). 74 MOCK_CONST_METHOD1(OnSetOpaque, void(bool)); 75 76 // Callbacks passed into Initialize(). 77 MOCK_METHOD1(OnTimeUpdate, void(base::TimeDelta)); 78 MOCK_METHOD1(OnNaturalSizeChanged, void(const gfx::Size&)); 79 80 void Initialize() { 81 InitializeWithDuration(kVideoDurationInMs); 82 } 83 84 void InitializeWithDuration(int duration_ms) { 85 duration_ = base::TimeDelta::FromMilliseconds(duration_ms); 86 87 // Monitor decodes from the decoder. 88 EXPECT_CALL(*decoder_, Decode(_, _)) 89 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FrameRequested)); 90 91 EXPECT_CALL(*decoder_, Reset(_)) 92 .WillRepeatedly(Invoke(this, &VideoRendererBaseTest::FlushRequested)); 93 94 InSequence s; 95 96 EXPECT_CALL(*decoder_, Initialize(_, _)) 97 .WillOnce(RunCallback<1>(PIPELINE_OK)); 98 99 // Set playback rate before anything else happens. 100 renderer_->SetPlaybackRate(1.0f); 101 102 // Initialize, we shouldn't have any reads. 103 InitializeRenderer(PIPELINE_OK); 104 105 // We expect the video size to be set. 106 EXPECT_CALL(*this, 107 OnNaturalSizeChanged(TestVideoConfig::NormalCodedSize())); 108 109 // Start prerolling. 110 QueuePrerollFrames(0); 111 Preroll(0, PIPELINE_OK); 112 } 113 114 void InitializeRenderer(PipelineStatus expected) { 115 SCOPED_TRACE(base::StringPrintf("InitializeRenderer(%d)", expected)); 116 WaitableMessageLoopEvent event; 117 CallInitialize(event.GetPipelineStatusCB()); 118 event.RunAndWaitForStatus(expected); 119 } 120 121 void CallInitialize(const PipelineStatusCB& status_cb) { 122 renderer_->Initialize( 123 &demuxer_stream_, 124 status_cb, 125 base::Bind(&MockStatisticsCB::OnStatistics, 126 base::Unretained(&statistics_cb_object_)), 127 base::Bind(&VideoRendererBaseTest::OnTimeUpdate, 128 base::Unretained(this)), 129 base::Bind(&VideoRendererBaseTest::OnNaturalSizeChanged, 130 base::Unretained(this)), 131 ended_event_.GetClosure(), 132 error_event_.GetPipelineStatusCB(), 133 base::Bind(&VideoRendererBaseTest::GetTime, base::Unretained(this)), 134 base::Bind(&VideoRendererBaseTest::GetDuration, 135 base::Unretained(this))); 136 } 137 138 void Play() { 139 SCOPED_TRACE("Play()"); 140 WaitableMessageLoopEvent event; 141 renderer_->Play(event.GetClosure()); 142 event.RunAndWait(); 143 } 144 145 void Preroll(int timestamp_ms, PipelineStatus expected) { 146 SCOPED_TRACE(base::StringPrintf("Preroll(%d, %d)", timestamp_ms, expected)); 147 WaitableMessageLoopEvent event; 148 renderer_->Preroll( 149 base::TimeDelta::FromMilliseconds(timestamp_ms), 150 event.GetPipelineStatusCB()); 151 event.RunAndWaitForStatus(expected); 152 } 153 154 void Pause() { 155 SCOPED_TRACE("Pause()"); 156 WaitableMessageLoopEvent event; 157 renderer_->Pause(event.GetClosure()); 158 event.RunAndWait(); 159 } 160 161 void Flush() { 162 SCOPED_TRACE("Flush()"); 163 WaitableMessageLoopEvent event; 164 renderer_->Flush(event.GetClosure()); 165 event.RunAndWait(); 166 } 167 168 void Stop() { 169 SCOPED_TRACE("Stop()"); 170 WaitableMessageLoopEvent event; 171 renderer_->Stop(event.GetClosure()); 172 event.RunAndWait(); 173 } 174 175 void Shutdown() { 176 Pause(); 177 Flush(); 178 Stop(); 179 } 180 181 // Queues a VideoFrame with |next_frame_timestamp_|. 182 void QueueNextFrame() { 183 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 184 DCHECK_LT(next_frame_timestamp_.InMicroseconds(), 185 duration_.InMicroseconds()); 186 187 gfx::Size natural_size = TestVideoConfig::NormalCodedSize(); 188 scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 189 VideoFrame::RGB32, natural_size, gfx::Rect(natural_size), natural_size, 190 next_frame_timestamp_); 191 decode_results_.push_back(std::make_pair( 192 VideoDecoder::kOk, frame)); 193 next_frame_timestamp_ += 194 base::TimeDelta::FromMilliseconds(kFrameDurationInMs); 195 } 196 197 void QueueEndOfStream() { 198 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 199 decode_results_.push_back(std::make_pair( 200 VideoDecoder::kOk, VideoFrame::CreateEmptyFrame())); 201 } 202 203 void QueueDecodeError() { 204 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 205 scoped_refptr<VideoFrame> null_frame; 206 decode_results_.push_back(std::make_pair( 207 VideoDecoder::kDecodeError, null_frame)); 208 } 209 210 void QueueAbortedRead() { 211 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 212 scoped_refptr<VideoFrame> null_frame; 213 decode_results_.push_back(std::make_pair( 214 VideoDecoder::kOk, null_frame)); 215 } 216 217 void QueuePrerollFrames(int timestamp_ms) { 218 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 219 next_frame_timestamp_ = base::TimeDelta(); 220 base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds(timestamp_ms); 221 while (next_frame_timestamp_ < timestamp) { 222 QueueNextFrame(); 223 } 224 225 // Queue the frame at |timestamp| plus additional ones for prerolling. 226 for (int i = 0; i < limits::kMaxVideoFrames; ++i) { 227 QueueNextFrame(); 228 } 229 } 230 231 void ResetCurrentFrame() { 232 base::AutoLock l(lock_); 233 current_frame_ = NULL; 234 } 235 236 scoped_refptr<VideoFrame> GetCurrentFrame() { 237 base::AutoLock l(lock_); 238 return current_frame_; 239 } 240 241 int GetCurrentTimestampInMs() { 242 scoped_refptr<VideoFrame> frame = GetCurrentFrame(); 243 if (!frame.get()) 244 return -1; 245 return frame->GetTimestamp().InMilliseconds(); 246 } 247 248 void WaitForError(PipelineStatus expected) { 249 SCOPED_TRACE(base::StringPrintf("WaitForError(%d)", expected)); 250 error_event_.RunAndWaitForStatus(expected); 251 } 252 253 void WaitForEnded() { 254 SCOPED_TRACE("WaitForEnded()"); 255 ended_event_.RunAndWait(); 256 } 257 258 void WaitForPendingRead() { 259 SCOPED_TRACE("WaitForPendingRead()"); 260 if (!read_cb_.is_null()) 261 return; 262 263 DCHECK(wait_for_pending_read_cb_.is_null()); 264 265 WaitableMessageLoopEvent event; 266 wait_for_pending_read_cb_ = event.GetClosure(); 267 event.RunAndWait(); 268 269 DCHECK(!read_cb_.is_null()); 270 DCHECK(wait_for_pending_read_cb_.is_null()); 271 } 272 273 void SatisfyPendingRead() { 274 CHECK(!read_cb_.is_null()); 275 CHECK(!decode_results_.empty()); 276 277 base::Closure closure = base::Bind( 278 read_cb_, decode_results_.front().first, 279 decode_results_.front().second); 280 281 read_cb_.Reset(); 282 decode_results_.pop_front(); 283 284 message_loop_.PostTask(FROM_HERE, closure); 285 } 286 287 void AdvanceTimeInMs(int time_ms) { 288 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 289 base::AutoLock l(lock_); 290 time_ += base::TimeDelta::FromMilliseconds(time_ms); 291 DCHECK_LE(time_.InMicroseconds(), duration_.InMicroseconds()); 292 } 293 294 protected: 295 // Fixture members. 296 scoped_ptr<VideoRendererBase> renderer_; 297 MockVideoDecoder* decoder_; // Owned by |renderer_|. 298 NiceMock<MockDemuxerStream> demuxer_stream_; 299 MockStatisticsCB statistics_cb_object_; 300 301 private: 302 base::TimeDelta GetTime() { 303 base::AutoLock l(lock_); 304 return time_; 305 } 306 307 base::TimeDelta GetDuration() { 308 return duration_; 309 } 310 311 void OnPaint(const scoped_refptr<VideoFrame>& frame) { 312 base::AutoLock l(lock_); 313 current_frame_ = frame; 314 } 315 316 void FrameRequested(const scoped_refptr<DecoderBuffer>& buffer, 317 const VideoDecoder::DecodeCB& read_cb) { 318 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 319 CHECK(read_cb_.is_null()); 320 read_cb_ = read_cb; 321 322 // Wake up WaitForPendingRead() if needed. 323 if (!wait_for_pending_read_cb_.is_null()) 324 base::ResetAndReturn(&wait_for_pending_read_cb_).Run(); 325 326 if (decode_results_.empty()) 327 return; 328 329 SatisfyPendingRead(); 330 } 331 332 void FlushRequested(const base::Closure& callback) { 333 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 334 decode_results_.clear(); 335 if (!read_cb_.is_null()) { 336 QueueAbortedRead(); 337 SatisfyPendingRead(); 338 } 339 340 message_loop_.PostTask(FROM_HERE, callback); 341 } 342 343 void StopRequested(const base::Closure& callback) { 344 DCHECK_EQ(&message_loop_, base::MessageLoop::current()); 345 decode_results_.clear(); 346 if (!read_cb_.is_null()) { 347 QueueAbortedRead(); 348 SatisfyPendingRead(); 349 } 350 351 message_loop_.PostTask(FROM_HERE, callback); 352 } 353 354 base::MessageLoop message_loop_; 355 356 // Used to protect |time_| and |current_frame_|. 357 base::Lock lock_; 358 base::TimeDelta time_; 359 scoped_refptr<VideoFrame> current_frame_; 360 361 // Used for satisfying reads. 362 VideoDecoder::DecodeCB read_cb_; 363 base::TimeDelta next_frame_timestamp_; 364 base::TimeDelta duration_; 365 366 WaitableMessageLoopEvent error_event_; 367 WaitableMessageLoopEvent ended_event_; 368 369 // Run during FrameRequested() to unblock WaitForPendingRead(). 370 base::Closure wait_for_pending_read_cb_; 371 372 std::deque<std::pair< 373 VideoDecoder::Status, scoped_refptr<VideoFrame> > > decode_results_; 374 375 DISALLOW_COPY_AND_ASSIGN(VideoRendererBaseTest); 376 }; 377 378 TEST_F(VideoRendererBaseTest, DoNothing) { 379 // Test that creation and deletion doesn't depend on calls to Initialize() 380 // and/or Stop(). 381 } 382 383 TEST_F(VideoRendererBaseTest, StopWithoutInitialize) { 384 Stop(); 385 } 386 387 TEST_F(VideoRendererBaseTest, Initialize) { 388 Initialize(); 389 EXPECT_EQ(0, GetCurrentTimestampInMs()); 390 Shutdown(); 391 } 392 393 static void ExpectNotCalled(PipelineStatus) { 394 base::debug::StackTrace stack; 395 ADD_FAILURE() << "Expected callback not to be called\n" << stack.ToString(); 396 } 397 398 TEST_F(VideoRendererBaseTest, StopWhileInitializing) { 399 EXPECT_CALL(*decoder_, Initialize(_, _)) 400 .WillOnce(RunCallback<1>(PIPELINE_OK)); 401 CallInitialize(base::Bind(&ExpectNotCalled)); 402 Stop(); 403 404 // ~VideoRendererBase() will CHECK() if we left anything initialized. 405 } 406 407 TEST_F(VideoRendererBaseTest, StopWhileFlushing) { 408 Initialize(); 409 Pause(); 410 renderer_->Flush(base::Bind(&ExpectNotCalled, PIPELINE_OK)); 411 Stop(); 412 413 // ~VideoRendererBase() will CHECK() if we left anything initialized. 414 } 415 416 TEST_F(VideoRendererBaseTest, Play) { 417 Initialize(); 418 Play(); 419 Shutdown(); 420 } 421 422 TEST_F(VideoRendererBaseTest, EndOfStream_DefaultFrameDuration) { 423 Initialize(); 424 Play(); 425 426 // Verify that the ended callback fires when the default last frame duration 427 // has elapsed. 428 int end_timestamp = kFrameDurationInMs * limits::kMaxVideoFrames + 429 VideoRendererBase::kMaxLastFrameDuration().InMilliseconds(); 430 EXPECT_LT(end_timestamp, kVideoDurationInMs); 431 432 QueueEndOfStream(); 433 AdvanceTimeInMs(end_timestamp); 434 WaitForEnded(); 435 436 Shutdown(); 437 } 438 439 TEST_F(VideoRendererBaseTest, EndOfStream_ClipDuration) { 440 int duration = kVideoDurationInMs + kFrameDurationInMs / 2; 441 InitializeWithDuration(duration); 442 Play(); 443 444 // Render all frames except for the last |limits::kMaxVideoFrames| frames 445 // and deliver all the frames between the start and |duration|. The preroll 446 // inside Initialize() makes this a little confusing, but |timestamp| is 447 // the current render time and QueueNextFrame() delivers a frame with a 448 // timestamp that is |timestamp| + limits::kMaxVideoFrames * 449 // kFrameDurationInMs. 450 int timestamp = kFrameDurationInMs; 451 int end_timestamp = duration - limits::kMaxVideoFrames * kFrameDurationInMs; 452 for (; timestamp < end_timestamp; timestamp += kFrameDurationInMs) { 453 QueueNextFrame(); 454 } 455 456 // Queue the end of stream frame and wait for the last frame to be rendered. 457 QueueEndOfStream(); 458 AdvanceTimeInMs(duration); 459 WaitForEnded(); 460 461 Shutdown(); 462 } 463 464 TEST_F(VideoRendererBaseTest, DecodeError_Playing) { 465 Initialize(); 466 Play(); 467 468 QueueDecodeError(); 469 AdvanceTimeInMs(kVideoDurationInMs); 470 WaitForError(PIPELINE_ERROR_DECODE); 471 Shutdown(); 472 } 473 474 TEST_F(VideoRendererBaseTest, DecodeError_DuringPreroll) { 475 Initialize(); 476 Pause(); 477 Flush(); 478 479 QueueDecodeError(); 480 Preroll(kFrameDurationInMs * 6, PIPELINE_ERROR_DECODE); 481 Shutdown(); 482 } 483 484 TEST_F(VideoRendererBaseTest, Preroll_Exact) { 485 Initialize(); 486 Pause(); 487 Flush(); 488 QueuePrerollFrames(kFrameDurationInMs * 6); 489 490 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); 491 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); 492 Shutdown(); 493 } 494 495 TEST_F(VideoRendererBaseTest, Preroll_RightBefore) { 496 Initialize(); 497 Pause(); 498 Flush(); 499 QueuePrerollFrames(kFrameDurationInMs * 6); 500 501 Preroll(kFrameDurationInMs * 6 - 1, PIPELINE_OK); 502 EXPECT_EQ(kFrameDurationInMs * 5, GetCurrentTimestampInMs()); 503 Shutdown(); 504 } 505 506 TEST_F(VideoRendererBaseTest, Preroll_RightAfter) { 507 Initialize(); 508 Pause(); 509 Flush(); 510 QueuePrerollFrames(kFrameDurationInMs * 6); 511 512 Preroll(kFrameDurationInMs * 6 + 1, PIPELINE_OK); 513 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); 514 Shutdown(); 515 } 516 517 TEST_F(VideoRendererBaseTest, PlayAfterPreroll) { 518 Initialize(); 519 Pause(); 520 Flush(); 521 QueuePrerollFrames(kFrameDurationInMs * 4); 522 523 Preroll(kFrameDurationInMs * 4, PIPELINE_OK); 524 EXPECT_EQ(kFrameDurationInMs * 4, GetCurrentTimestampInMs()); 525 526 Play(); 527 // Advance time past prerolled time to trigger a Read(). 528 AdvanceTimeInMs(5 * kFrameDurationInMs); 529 WaitForPendingRead(); 530 Shutdown(); 531 } 532 533 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Initialized) { 534 Initialize(); 535 EXPECT_TRUE(GetCurrentFrame().get()); // Due to prerolling. 536 Shutdown(); 537 } 538 539 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Playing) { 540 Initialize(); 541 Play(); 542 EXPECT_TRUE(GetCurrentFrame().get()); 543 Shutdown(); 544 } 545 546 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Paused) { 547 Initialize(); 548 Play(); 549 Pause(); 550 EXPECT_TRUE(GetCurrentFrame().get()); 551 Shutdown(); 552 } 553 554 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Flushed) { 555 Initialize(); 556 Play(); 557 Pause(); 558 559 // Frame shouldn't be updated. 560 ResetCurrentFrame(); 561 Flush(); 562 EXPECT_FALSE(GetCurrentFrame().get()); 563 564 Shutdown(); 565 } 566 567 TEST_F(VideoRendererBaseTest, GetCurrentFrame_EndOfStream) { 568 Initialize(); 569 Play(); 570 Pause(); 571 Flush(); 572 573 // Preroll only end of stream frames. 574 QueueEndOfStream(); 575 576 // Frame shouldn't be updated. 577 ResetCurrentFrame(); 578 Preroll(0, PIPELINE_OK); 579 EXPECT_FALSE(GetCurrentFrame().get()); 580 581 // Start playing, we should immediately get notified of end of stream. 582 Play(); 583 WaitForEnded(); 584 585 Shutdown(); 586 } 587 588 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Shutdown) { 589 Initialize(); 590 591 // Frame shouldn't be updated. 592 ResetCurrentFrame(); 593 Shutdown(); 594 EXPECT_FALSE(GetCurrentFrame().get()); 595 } 596 597 // Stop() is called immediately during an error. 598 TEST_F(VideoRendererBaseTest, GetCurrentFrame_Error) { 599 Initialize(); 600 601 // Frame shouldn't be updated. 602 ResetCurrentFrame(); 603 Stop(); 604 EXPECT_FALSE(GetCurrentFrame().get()); 605 } 606 607 // Verify that a late decoder response doesn't break invariants in the renderer. 608 TEST_F(VideoRendererBaseTest, StopDuringOutstandingRead) { 609 Initialize(); 610 Play(); 611 612 // Advance time a bit to trigger a Read(). 613 AdvanceTimeInMs(kFrameDurationInMs); 614 WaitForPendingRead(); 615 616 WaitableMessageLoopEvent event; 617 renderer_->Stop(event.GetClosure()); 618 619 event.RunAndWait(); 620 } 621 622 TEST_F(VideoRendererBaseTest, AbortPendingRead_Playing) { 623 Initialize(); 624 Play(); 625 626 // Advance time a bit to trigger a Read(). 627 AdvanceTimeInMs(kFrameDurationInMs); 628 WaitForPendingRead(); 629 630 QueueAbortedRead(); 631 SatisfyPendingRead(); 632 633 Pause(); 634 Flush(); 635 QueuePrerollFrames(kFrameDurationInMs * 6); 636 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); 637 EXPECT_EQ(kFrameDurationInMs * 6, GetCurrentTimestampInMs()); 638 Shutdown(); 639 } 640 641 TEST_F(VideoRendererBaseTest, AbortPendingRead_Flush) { 642 Initialize(); 643 Play(); 644 645 // Advance time a bit to trigger a Read(). 646 AdvanceTimeInMs(kFrameDurationInMs); 647 WaitForPendingRead(); 648 649 Pause(); 650 Flush(); 651 Shutdown(); 652 } 653 654 TEST_F(VideoRendererBaseTest, AbortPendingRead_Preroll) { 655 Initialize(); 656 Pause(); 657 Flush(); 658 659 QueueAbortedRead(); 660 Preroll(kFrameDurationInMs * 6, PIPELINE_OK); 661 Shutdown(); 662 } 663 664 TEST_F(VideoRendererBaseTest, VideoDecoder_InitFailure) { 665 InSequence s; 666 667 EXPECT_CALL(*decoder_, Initialize(_, _)) 668 .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)); 669 InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED); 670 671 Stop(); 672 } 673 674 } // namespace media 675