Chromium Code Reviews| 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 { kNormal, kLowDelay, kCantReadWithoutStalling }; | |
|
xhwang
2016/04/14 21:28:00
nit: use UPPER_CASE style for enums?
| |
| 283 void BasicUnderflowTest(UnderflowTestType type) { | |
| 284 InitializeWithLowDelay(type == UnderflowTestType::kLowDelay); | |
| 285 if (type == UnderflowTestType::kCantReadWithoutStalling) | |
| 286 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | |
| 287 | |
| 288 QueueFrames("0 30 60 90"); | |
| 289 | |
| 290 { | |
| 291 WaitableMessageLoopEvent event; | |
| 292 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | |
| 293 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 294 .WillOnce(RunClosure(event.GetClosure())); | |
| 295 StartPlayingFrom(0); | |
| 296 event.RunAndWait(); | |
| 297 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 298 } | |
| 299 | |
| 300 renderer_->OnTimeStateChanged(true); | |
| 301 | |
| 302 // Advance time slightly, but enough to exceed the duration of the last | |
| 303 // frame. | |
| 304 // Frames should be dropped and we should NOT signal having nothing. | |
| 305 { | |
| 306 SCOPED_TRACE("Waiting for frame drops"); | |
| 307 WaitableMessageLoopEvent event; | |
| 308 | |
| 309 // Note: Starting the TimeSource will cause the old VideoRendererImpl to | |
| 310 // start rendering frames on its own thread, so the first frame may be | |
| 311 // received. | |
| 312 time_source_.StartTicking(); | |
| 313 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); | |
| 314 | |
| 315 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); | |
| 316 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) | |
| 317 .WillOnce(RunClosure(event.GetClosure())); | |
| 318 AdvanceTimeInMs(91); | |
| 319 | |
| 320 event.RunAndWait(); | |
| 321 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 322 } | |
| 323 | |
| 324 // Advance time more. Now we should signal having nothing. And put | |
| 325 // the last frame up for display. | |
| 326 { | |
| 327 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | |
| 328 WaitableMessageLoopEvent event; | |
| 329 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | |
| 330 .WillOnce(RunClosure(event.GetClosure())); | |
| 331 AdvanceTimeInMs(30); | |
| 332 event.RunAndWait(); | |
| 333 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 334 } | |
| 335 | |
| 336 // Receiving end of stream should signal having enough. | |
| 337 { | |
| 338 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | |
| 339 WaitableMessageLoopEvent event; | |
| 340 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 341 .WillOnce(RunClosure(event.GetClosure())); | |
| 342 SatisfyPendingReadWithEndOfStream(); | |
| 343 event.RunAndWait(); | |
| 344 } | |
| 345 | |
| 346 WaitForEnded(); | |
| 347 Destroy(); | |
| 348 } | |
| 349 | |
| 350 void UnderflowRecoveryTest(UnderflowTestType type) { | |
| 351 InitializeWithLowDelay(type == UnderflowTestType::kLowDelay); | |
| 352 if (type == UnderflowTestType::kCantReadWithoutStalling) | |
| 353 ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false)); | |
| 354 | |
| 355 QueueFrames("0 20 40 60"); | |
| 356 { | |
| 357 WaitableMessageLoopEvent event; | |
| 358 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | |
| 359 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 360 .WillOnce(RunClosure(event.GetClosure())); | |
| 361 StartPlayingFrom(0); | |
| 362 event.RunAndWait(); | |
| 363 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 364 } | |
| 365 | |
| 366 renderer_->OnTimeStateChanged(true); | |
| 367 time_source_.StartTicking(); | |
| 368 | |
| 369 // Advance time, this should cause have nothing to be signaled. | |
| 370 { | |
| 371 SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING"); | |
| 372 WaitableMessageLoopEvent event; | |
| 373 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING)) | |
| 374 .WillOnce(RunClosure(event.GetClosure())); | |
| 375 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1); | |
| 376 AdvanceTimeInMs(20); | |
| 377 event.RunAndWait(); | |
| 378 Mock::VerifyAndClearExpectations(&mock_cb_); | |
| 379 } | |
| 380 | |
| 381 AdvanceTimeInMs(59); | |
| 382 EXPECT_EQ(3u, renderer_->frames_queued_for_testing()); | |
| 383 time_source_.StopTicking(); | |
| 384 renderer_->OnTimeStateChanged(false); | |
| 385 EXPECT_EQ(0u, renderer_->frames_queued_for_testing()); | |
| 386 ASSERT_TRUE(IsReadPending()); | |
| 387 | |
| 388 // Queue some frames, satisfy reads, and make sure expired frames are gone | |
| 389 // when the renderer paints the first frame. | |
| 390 { | |
| 391 SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH"); | |
| 392 WaitableMessageLoopEvent event; | |
| 393 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1); | |
| 394 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)) | |
| 395 .WillOnce(RunClosure(event.GetClosure())); | |
| 396 if (type == UnderflowTestType::kNormal) | |
| 397 QueueFrames("80 100 120 140 160"); | |
| 398 else | |
| 399 QueueFrames("40 60 80"); | |
| 400 SatisfyPendingRead(); | |
| 401 event.RunAndWait(); | |
| 402 } | |
| 403 | |
| 404 Destroy(); | |
| 405 } | |
| 406 | |
| 282 protected: | 407 protected: |
| 283 // Fixture members. | 408 // Fixture members. |
| 284 scoped_ptr<VideoRendererImpl> renderer_; | 409 scoped_ptr<VideoRendererImpl> renderer_; |
| 285 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. | 410 base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|. |
| 286 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. | 411 NiceMock<MockVideoDecoder>* decoder_; // Owned by |renderer_|. |
| 287 NiceMock<MockDemuxerStream> demuxer_stream_; | 412 NiceMock<MockDemuxerStream> demuxer_stream_; |
| 288 | 413 |
| 289 // Use StrictMock<T> to catch missing/extra callbacks. | 414 // Use StrictMock<T> to catch missing/extra callbacks. |
| 290 class MockCB { | 415 class MockCB { |
| 291 public: | 416 public: |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 | 661 |
| 537 Destroy(); | 662 Destroy(); |
| 538 } | 663 } |
| 539 | 664 |
| 540 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { | 665 TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) { |
| 541 InitializeRenderer(false, false); | 666 InitializeRenderer(false, false); |
| 542 Destroy(); | 667 Destroy(); |
| 543 } | 668 } |
| 544 | 669 |
| 545 TEST_F(VideoRendererImplTest, Underflow) { | 670 TEST_F(VideoRendererImplTest, Underflow) { |
| 546 Initialize(); | 671 BasicUnderflowTest(UnderflowTestType::kNormal); |
| 547 QueueFrames("0 30 60 90"); | 672 } |
| 548 | 673 |
| 549 { | 674 TEST_F(VideoRendererImplTest, Underflow_LowDelay) { |
| 550 WaitableMessageLoopEvent event; | 675 BasicUnderflowTest(UnderflowTestType::kLowDelay); |
| 551 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 676 } |
| 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 | 677 |
| 559 renderer_->OnTimeStateChanged(true); | 678 TEST_F(VideoRendererImplTest, Underflow_CantReadWithoutStalling) { |
| 679 BasicUnderflowTest(UnderflowTestType::kCantReadWithoutStalling); | |
| 680 } | |
| 560 | 681 |
| 561 // Advance time slightly, but enough to exceed the duration of the last frame. | 682 TEST_F(VideoRendererImplTest, UnderflowRecovery) { |
| 562 // Frames should be dropped and we should NOT signal having nothing. | 683 UnderflowRecoveryTest(UnderflowTestType::kNormal); |
| 563 { | 684 } |
| 564 SCOPED_TRACE("Waiting for frame drops"); | |
| 565 WaitableMessageLoopEvent event; | |
| 566 | 685 |
| 567 // Note: Starting the TimeSource will cause the old VideoRendererImpl to | 686 TEST_F(VideoRendererImplTest, UnderflowRecovery_LowDelay) { |
| 568 // start rendering frames on its own thread, so the first frame may be | 687 UnderflowRecoveryTest(UnderflowTestType::kLowDelay); |
| 569 // received. | 688 } |
| 570 time_source_.StartTicking(); | |
| 571 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0); | |
| 572 | 689 |
| 573 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0); | 690 TEST_F(VideoRendererImplTest, UnderflowRecovery_CantReadWithoutStalling) { |
| 574 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90))) | 691 UnderflowRecoveryTest(UnderflowTestType::kCantReadWithoutStalling); |
| 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 } | 692 } |
| 607 | 693 |
| 608 // Verifies that the sink is stopped after rendering the first frame if | 694 // Verifies that the sink is stopped after rendering the first frame if |
| 609 // playback hasn't started. | 695 // playback hasn't started. |
| 610 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { | 696 TEST_F(VideoRendererImplTest, RenderingStopsAfterFirstFrame) { |
| 611 InitializeWithLowDelay(true); | 697 InitializeWithLowDelay(true); |
| 612 QueueFrames("0"); | 698 QueueFrames("0"); |
| 613 | 699 |
| 614 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); | 700 EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0))); |
| 615 EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH)); | 701 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"); | 888 QueueFrames("0 10 20 30"); |
| 803 StartPlayingFrom(0); | 889 StartPlayingFrom(0); |
| 804 Flush(); | 890 Flush(); |
| 805 ASSERT_EQ(1u, frame_ready_cbs_.size()); | 891 ASSERT_EQ(1u, frame_ready_cbs_.size()); |
| 806 // This frame will be discarded. | 892 // This frame will be discarded. |
| 807 frame_ready_cbs_.front().Run(); | 893 frame_ready_cbs_.front().Run(); |
| 808 Destroy(); | 894 Destroy(); |
| 809 } | 895 } |
| 810 | 896 |
| 811 } // namespace media | 897 } // namespace media |
| OLD | NEW |