| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdint.h> | 5 #include <stdint.h> |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 time_ += base::TimeDelta::FromMilliseconds(time_ms); | 272 time_ += base::TimeDelta::FromMilliseconds(time_ms); |
| 273 time_source_.StopTicking(); | 273 time_source_.StopTicking(); |
| 274 time_source_.SetMediaTime(time_); | 274 time_source_.SetMediaTime(time_); |
| 275 time_source_.StartTicking(); | 275 time_source_.StartTicking(); |
| 276 } | 276 } |
| 277 | 277 |
| 278 bool has_ended() const { | 278 bool has_ended() const { |
| 279 return ended_event_.is_signaled(); | 279 return ended_event_.is_signaled(); |
| 280 } | 280 } |
| 281 | 281 |
| 282 enum class UnderflowTestType { |
| 283 NORMAL, |
| 284 LOW_DELAY, |
| 285 CANT_READ_WITHOUT_STALLING |
| 286 }; |
| 287 void BasicUnderflowTest(UnderflowTestType type) { |
| 288 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
| 289 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
| 290 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
| 291 |
| 292 QueueFrames("0 30 60 90"); |
| 293 |
| 294 { |
| 295 WaitableMessageLoopEvent event; |
| 296 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 297 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 298 .WillOnce(RunClosure(event.GetClosure())); |
| 299 StartPlayingFrom(0); |
| 300 event.RunAndWait(); |
| 301 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 302 } |
| 303 |
| 304 renderer_->OnTimeStateChanged(true); |
| 305 |
| 306 // Advance time slightly, but enough to exceed the duration of the last |
| 307 // frame. |
| 308 // Frames should be dropped and we should NOT signal having nothing. |
| 309 { |
| 310 SCOPED_TRACE("Waiting for frame drops"); |
| 311 WaitableMessageLoopEvent event; |
| 312 |
| 313 // Note: Starting the TimeSource will cause the old VideoRendererImpl to |
| 314 // start rendering frames on its own thread, so the first frame may be |
| 315 // received. |
| 316 time_source_.StartTicking(); |
| 317 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); |
| 318 |
| 319 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); |
| 320 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) |
| 321 .WillOnce(RunClosure(event.GetClosure())); |
| 322 AdvanceTimeInMs(91); |
| 323 |
| 324 event.RunAndWait(); |
| 325 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 326 } |
| 327 |
| 328 // Advance time more. Now we should signal having nothing. And put |
| 329 // the last frame up for display. |
| 330 { |
| 331 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
| 332 WaitableMessageLoopEvent event; |
| 333 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 334 .WillOnce(RunClosure(event.GetClosure())); |
| 335 AdvanceTimeInMs(30); |
| 336 event.RunAndWait(); |
| 337 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 338 } |
| 339 |
| 340 // Receiving end of stream should signal having enough. |
| 341 { |
| 342 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
| 343 WaitableMessageLoopEvent event; |
| 344 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 345 .WillOnce(RunClosure(event.GetClosure())); |
| 346 SatisfyPendingReadWithEndOfStream(); |
| 347 event.RunAndWait(); |
| 348 } |
| 349 |
| 350 WaitForEnded(); |
| 351 Destroy(); |
| 352 } |
| 353 |
| 354 void UnderflowRecoveryTest(UnderflowTestType type) { |
| 355 InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY); |
| 356 if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING) |
| 357 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); |
| 358 |
| 359 QueueFrames("0 20 40 60"); |
| 360 { |
| 361 WaitableMessageLoopEvent event; |
| 362 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 363 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 364 .WillOnce(RunClosure(event.GetClosure())); |
| 365 StartPlayingFrom(0); |
| 366 event.RunAndWait(); |
| 367 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 368 } |
| 369 |
| 370 renderer_->OnTimeStateChanged(true); |
| 371 time_source_.StartTicking(); |
| 372 |
| 373 // Advance time, this should cause have nothing to be signaled. |
| 374 { |
| 375 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); |
| 376 WaitableMessageLoopEvent event; |
| 377 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) |
| 378 .WillOnce(RunClosure(event.GetClosure())); |
| 379 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); |
| 380 AdvanceTimeInMs(20); |
| 381 event.RunAndWait(); |
| 382 Mock::VerifyAndClearExpectations(&mock_cb_); |
| 383 } |
| 384 |
| 385 AdvanceTimeInMs(59); |
| 386 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); |
| 387 time_source_.StopTicking(); |
| 388 renderer_->OnTimeStateChanged(false); |
| 389 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); |
| 390 ASSERT_TRUE(IsReadPending()); |
| 391 |
| 392 // Queue some frames, satisfy reads, and make sure expired frames are gone |
| 393 // when the renderer paints the first frame. |
| 394 { |
| 395 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); |
| 396 WaitableMessageLoopEvent event; |
| 397 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); |
| 398 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
| 399 .WillOnce(RunClosure(event.GetClosure())); |
| 400 if (type == UnderflowTestType::NORMAL) |
| 401 QueueFrames("80 100 120 140 160"); |
| 402 else |
| 403 QueueFrames("40 60 80"); |
| 404 SatisfyPendingRead(); |
| 405 event.RunAndWait(); |
| 406 } |
| 407 |
| 408 Destroy(); |
| 409 } |
| 410 |
| 282 protected: | 411 protected: |
| 283 // Fixture members. | 412 // Fixture members. |
| 284 scoped_ptr<VideoRendererImpl> renderer_; | 413 scoped_ptr<VideoRendererImpl> renderer_; |
| 285 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. | 414 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. |
| 286 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. | 415 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. |
| 287 NiceMock<MockDemuxerStream> demuxer_stream_; | 416 NiceMock<MockDemuxerStream> demuxer_stream_; |
| 288 | 417 |
| 289 // Use StrictMock<T> to catch missing/extra callbacks. | 418 // Use StrictMock<T> to catch missing/extra callbacks. |
| 290 class MockCB { | 419 class MockCB { |
| 291 public: | 420 public: |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 | 665 |
| 537 Destroy(); | 666 Destroy(); |
| 538 } | 667 } |
| 539 | 668 |
| 540 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { | 669 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { |
| 541 InitializeRenderer(false, false); | 670 InitializeRenderer(false, false); |
| 542 Destroy(); | 671 Destroy(); |
| 543 } | 672 } |
| 544 | 673 |
| 545 TEST_F(VideoRendererImplTest, Underflow) { | 674 TEST_F(VideoRendererImplTest, Underflow) { |
| 546 Initialize(); | 675 BasicUnderflowTest(UnderflowTestType::NORMAL); |
| 547 QueueFrames("0 30 60 90"); | 676 } |
| 548 | 677 |
| 549 { | 678 TEST_F(VideoRendererImplTest, Underflow_LowDelay) { |
| 550 WaitableMessageLoopEvent event; | 679 BasicUnderflowTest(UnderflowTestType::LOW_DELAY); |
| 551 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 680 } |
| 552 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 553 .WillOnce(RunClosure(event.GetClosure())); | |
| 554 StartPlayingFrom(0); | |
| 555 event.RunAndWait(); | |
| 556 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 557 } | |
| 558 | 681 |
| 559 renderer_->OnTimeStateChanged(true); | 682 TEST_F(VideoRendererImplTest, Underflow_CantReadWithoutStalling) { |
| 683 BasicUnderflowTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); |
| 684 } |
| 560 | 685 |
| 561 // Advance time slightly, but enough to exceed the duration of the last frame. | 686 TEST_F(VideoRendererImplTest, UnderflowRecovery) { |
| 562 // Frames should be dropped and we should NOT signal having nothing. | 687 UnderflowRecoveryTest(UnderflowTestType::NORMAL); |
| 563 { | 688 } |
| 564 SCOPED_TRACE("Waiting for frame drops"); | |
| 565 WaitableMessageLoopEvent event; | |
| 566 | 689 |
| 567 // Note: Starting the TimeSource will cause the old VideoRendererImpl to | 690 TEST_F(VideoRendererImplTest, UnderflowRecovery_LowDelay) { |
| 568 // start rendering frames on its own thread, so the first frame may be | 691 UnderflowRecoveryTest(UnderflowTestType::LOW_DELAY); |
| 569 // received. | 692 } |
| 570 time_source_.StartTicking(); | |
| 571 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); | |
| 572 | 693 |
| 573 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); | 694 TEST_F(VideoRendererImplTest, UnderflowRecovery_CantReadWithoutStalling) { |
| 574 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) | 695 UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING); |
| 575 .WillOnce(RunClosure(event.GetClosure())); | |
| 576 AdvanceTimeInMs(91); | |
| 577 | |
| 578 event.RunAndWait(); | |
| 579 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 580 } | |
| 581 | |
| 582 // Advance time more. Now we should signal having nothing. And put | |
| 583 // the last frame up for display. | |
| 584 { | |
| 585 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | |
| 586 WaitableMessageLoopEvent event; | |
| 587 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | |
| 588 .WillOnce(RunClosure(event.GetClosure())); | |
| 589 AdvanceTimeInMs(30); | |
| 590 event.RunAndWait(); | |
| 591 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 592 } | |
| 593 | |
| 594 // Receiving end of stream should signal having enough. | |
| 595 { | |
| 596 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | |
| 597 WaitableMessageLoopEvent event; | |
| 598 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 599 .WillOnce(RunClosure(event.GetClosure())); | |
| 600 SatisfyPendingReadWithEndOfStream(); | |
| 601 event.RunAndWait(); | |
| 602 } | |
| 603 | |
| 604 WaitForEnded(); | |
| 605 Destroy(); | |
| 606 } | 696 } |
| 607 | 697 |
| 608 // Verifies that the sink is stopped after rendering the first frame if | 698 // Verifies that the sink is stopped after rendering the first frame if |
| 609 // playback hasn't started. | 699 // playback hasn't started. |
| 610 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { | 700 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { |
| 611 InitializeWithLowDelay(true); | 701 InitializeWithLowDelay(true); |
| 612 QueueFrames("0"); | 702 QueueFrames("0"); |
| 613 | 703 |
| 614 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 704 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 615 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 705 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 QueueFrames("0 10 20 30"); | 892 QueueFrames("0 10 20 30"); |
| 803 StartPlayingFrom(0); | 893 StartPlayingFrom(0); |
| 804 Flush(); | 894 Flush(); |
| 805 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 895 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
| 806 // This frame will be discarded. | 896 // This frame will be discarded. |
| 807 frame_ready_cbs_.front().Run(); | 897 frame_ready_cbs_.front().Run(); |
| 808 Destroy(); | 898 Destroy(); |
| 809 } | 899 } |
| 810 | 900 |
| 811 } // namespace media | 901 } // namespace media |
| OLD | NEW |