Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(739)

Unified Diff: media/renderers/video_renderer_impl_unittest.cc

Issue 1863373002: Fix underflow and av/sync issues in low delay and stall presence. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Clarified comment. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/renderers/video_renderer_impl.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/renderers/video_renderer_impl_unittest.cc
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc
index af589d83112c111f28e651cf2519ffe42718cb51..7f90a6388e2ffb6f1dbc402c3df4c5a7e6202243 100644
--- a/media/renderers/video_renderer_impl_unittest.cc
+++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -279,6 +279,135 @@ class VideoRendererImplTest
return ended_event_.is_signaled();
}
+ enum class UnderflowTestType {
+ NORMAL,
+ LOW_DELAY,
+ CANT_READ_WITHOUT_STALLING
+ };
+ void BasicUnderflowTest(UnderflowTestType type) {
+ InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY);
+ if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING)
+ ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
+
+ QueueFrames("0 30 60 90");
+
+ {
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
+ .WillOnce(RunClosure(event.GetClosure()));
+ StartPlayingFrom(0);
+ event.RunAndWait();
+ Mock::VerifyAndClearExpectations(&mock_cb_);
+ }
+
+ renderer_->OnTimeStateChanged(true);
+
+ // Advance time slightly, but enough to exceed the duration of the last
+ // frame.
+ // Frames should be dropped and we should NOT signal having nothing.
+ {
+ SCOPED_TRACE("Waiting for frame drops");
+ WaitableMessageLoopEvent event;
+
+ // Note: Starting the TimeSource will cause the old VideoRendererImpl to
+ // start rendering frames on its own thread, so the first frame may be
+ // received.
+ time_source_.StartTicking();
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
+
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
+ .WillOnce(RunClosure(event.GetClosure()));
+ AdvanceTimeInMs(91);
+
+ event.RunAndWait();
+ Mock::VerifyAndClearExpectations(&mock_cb_);
+ }
+
+ // Advance time more. Now we should signal having nothing. And put
+ // the last frame up for display.
+ {
+ SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
+ .WillOnce(RunClosure(event.GetClosure()));
+ AdvanceTimeInMs(30);
+ event.RunAndWait();
+ Mock::VerifyAndClearExpectations(&mock_cb_);
+ }
+
+ // Receiving end of stream should signal having enough.
+ {
+ SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
+ .WillOnce(RunClosure(event.GetClosure()));
+ SatisfyPendingReadWithEndOfStream();
+ event.RunAndWait();
+ }
+
+ WaitForEnded();
+ Destroy();
+ }
+
+ void UnderflowRecoveryTest(UnderflowTestType type) {
+ InitializeWithLowDelay(type == UnderflowTestType::LOW_DELAY);
+ if (type == UnderflowTestType::CANT_READ_WITHOUT_STALLING)
+ ON_CALL(*decoder_, CanReadWithoutStalling()).WillByDefault(Return(false));
+
+ QueueFrames("0 20 40 60");
+ {
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
+ .WillOnce(RunClosure(event.GetClosure()));
+ StartPlayingFrom(0);
+ event.RunAndWait();
+ Mock::VerifyAndClearExpectations(&mock_cb_);
+ }
+
+ renderer_->OnTimeStateChanged(true);
+ time_source_.StartTicking();
+
+ // Advance time, this should cause have nothing to be signaled.
+ {
+ SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
+ .WillOnce(RunClosure(event.GetClosure()));
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(20))).Times(1);
+ AdvanceTimeInMs(20);
+ event.RunAndWait();
+ Mock::VerifyAndClearExpectations(&mock_cb_);
+ }
+
+ AdvanceTimeInMs(59);
+ EXPECT_EQ(3u, renderer_->frames_queued_for_testing());
+ time_source_.StopTicking();
+ renderer_->OnTimeStateChanged(false);
+ EXPECT_EQ(0u, renderer_->frames_queued_for_testing());
+ ASSERT_TRUE(IsReadPending());
+
+ // Queue some frames, satisfy reads, and make sure expired frames are gone
+ // when the renderer paints the first frame.
+ {
+ SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(80))).Times(1);
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
+ .WillOnce(RunClosure(event.GetClosure()));
+ if (type == UnderflowTestType::NORMAL)
+ QueueFrames("80 100 120 140 160");
+ else
+ QueueFrames("40 60 80");
+ SatisfyPendingRead();
+ event.RunAndWait();
+ }
+
+ Destroy();
+ }
+
protected:
// Fixture members.
scoped_ptr<VideoRendererImpl> renderer_;
@@ -543,66 +672,27 @@ TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
}
TEST_F(VideoRendererImplTest, Underflow) {
- Initialize();
- QueueFrames("0 30 60 90");
-
- {
- WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
- EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
- .WillOnce(RunClosure(event.GetClosure()));
- StartPlayingFrom(0);
- event.RunAndWait();
- Mock::VerifyAndClearExpectations(&mock_cb_);
- }
-
- renderer_->OnTimeStateChanged(true);
-
- // Advance time slightly, but enough to exceed the duration of the last frame.
- // Frames should be dropped and we should NOT signal having nothing.
- {
- SCOPED_TRACE("Waiting for frame drops");
- WaitableMessageLoopEvent event;
-
- // Note: Starting the TimeSource will cause the old VideoRendererImpl to
- // start rendering frames on its own thread, so the first frame may be
- // received.
- time_source_.StartTicking();
- EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(30))).Times(0);
+ BasicUnderflowTest(UnderflowTestType::NORMAL);
+}
- EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(60))).Times(0);
- EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(90)))
- .WillOnce(RunClosure(event.GetClosure()));
- AdvanceTimeInMs(91);
+TEST_F(VideoRendererImplTest, Underflow_LowDelay) {
+ BasicUnderflowTest(UnderflowTestType::LOW_DELAY);
+}
- event.RunAndWait();
- Mock::VerifyAndClearExpectations(&mock_cb_);
- }
+TEST_F(VideoRendererImplTest, Underflow_CantReadWithoutStalling) {
+ BasicUnderflowTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING);
+}
- // Advance time more. Now we should signal having nothing. And put
- // the last frame up for display.
- {
- SCOPED_TRACE("Waiting for BUFFERING_HAVE_NOTHING");
- WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_NOTHING))
- .WillOnce(RunClosure(event.GetClosure()));
- AdvanceTimeInMs(30);
- event.RunAndWait();
- Mock::VerifyAndClearExpectations(&mock_cb_);
- }
+TEST_F(VideoRendererImplTest, UnderflowRecovery) {
+ UnderflowRecoveryTest(UnderflowTestType::NORMAL);
+}
- // Receiving end of stream should signal having enough.
- {
- SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
- WaitableMessageLoopEvent event;
- EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
- .WillOnce(RunClosure(event.GetClosure()));
- SatisfyPendingReadWithEndOfStream();
- event.RunAndWait();
- }
+TEST_F(VideoRendererImplTest, UnderflowRecovery_LowDelay) {
+ UnderflowRecoveryTest(UnderflowTestType::LOW_DELAY);
+}
- WaitForEnded();
- Destroy();
+TEST_F(VideoRendererImplTest, UnderflowRecovery_CantReadWithoutStalling) {
+ UnderflowRecoveryTest(UnderflowTestType::CANT_READ_WITHOUT_STALLING);
}
// Verifies that the sink is stopped after rendering the first frame if
« no previous file with comments | « media/renderers/video_renderer_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698