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

Unified Diff: media/renderers/video_renderer_impl_unittest.cc

Issue 1083383005: Connect the new video rendering path to the compositor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@vra
Patch Set: Update LoginCustomFlags histogram. Created 5 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') | tools/metrics/histograms/histograms.xml » ('j') | 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 9203d69ec664d4a43d18470b5c00d02cba5edd81..573ff3386d4bbf66a32edd19ea5faa910526d85c 100644
--- a/media/renderers/video_renderer_impl_unittest.cc
+++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -36,6 +36,9 @@ using ::testing::StrictMock;
namespace media {
+// Threshold for Render() callbacks used for testing; should not be zero.
+static const int kTestBackgroundRenderTimeoutMs = 25;
+
ACTION_P(RunClosure, closure) {
closure.Run();
}
@@ -45,7 +48,7 @@ MATCHER_P(HasTimestamp, ms, "") {
return arg->timestamp().InMilliseconds() == ms;
}
-class VideoRendererImplTest : public ::testing::Test {
+class VideoRendererImplTest : public testing::TestWithParam<bool> {
public:
VideoRendererImplTest()
: tick_clock_(new base::SimpleTestTickClock()),
@@ -64,10 +67,14 @@ class VideoRendererImplTest : public ::testing::Test {
renderer_.reset(new VideoRendererImpl(
message_loop_.message_loop_proxy(), null_video_sink_.get(),
decoders.Pass(), true, new MediaLog()));
-
+ if (GetParam())
+ renderer_->enable_new_video_renderer_for_testing();
renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
null_video_sink_->set_tick_clock_for_testing(tick_clock_);
+ // Disable background rendering for tests by default.
+ renderer_->SetBackgroundRenderingForTesting(false, base::TimeDelta());
+
// Start wallclock time at a non-zero value.
AdvanceWallclockTimeInMs(12345);
@@ -145,6 +152,11 @@ class VideoRendererImplTest : public ::testing::Test {
message_loop_.RunUntilIdle();
}
+ void SuspendRenderCallbacks() {
+ null_video_sink_->PauseRenderCallbacks(base::TimeTicks() +
+ base::TimeDelta::Max());
+ }
+
// Parses a string representation of video frames and generates corresponding
// VideoFrame objects in |decode_results_|.
//
@@ -266,6 +278,10 @@ class VideoRendererImplTest : public ::testing::Test {
time_ += base::TimeDelta::FromMilliseconds(time_ms);
}
+ bool has_ended() const {
+ return ended_event_.is_signaled();
+ }
+
protected:
// Fixture members.
scoped_ptr<VideoRendererImpl> renderer_;
@@ -344,21 +360,21 @@ class VideoRendererImplTest : public ::testing::Test {
DISALLOW_COPY_AND_ASSIGN(VideoRendererImplTest);
};
-TEST_F(VideoRendererImplTest, DoNothing) {
+TEST_P(VideoRendererImplTest, DoNothing) {
// Test that creation and deletion doesn't depend on calls to Initialize()
// and/or Destroy().
}
-TEST_F(VideoRendererImplTest, DestroyWithoutInitialize) {
+TEST_P(VideoRendererImplTest, DestroyWithoutInitialize) {
Destroy();
}
-TEST_F(VideoRendererImplTest, Initialize) {
+TEST_P(VideoRendererImplTest, Initialize) {
Initialize();
Destroy();
}
-TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
+TEST_P(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
Initialize();
QueueFrames("0 10 20 30");
EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
@@ -367,12 +383,28 @@ TEST_F(VideoRendererImplTest, InitializeAndStartPlayingFrom) {
Destroy();
}
-TEST_F(VideoRendererImplTest, DestroyWhileInitializing) {
+TEST_P(VideoRendererImplTest, InitializeAndEndOfStream) {
+ Initialize();
+ StartPlayingFrom(0);
+ WaitForPendingRead();
+ {
+ SCOPED_TRACE("Waiting for BUFFERING_HAVE_ENOUGH");
+ WaitableMessageLoopEvent event;
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH))
+ .WillOnce(RunClosure(event.GetClosure()));
+ SatisfyPendingReadWithEndOfStream();
+ event.RunAndWait();
+ }
+ EXPECT_FALSE(null_video_sink_->is_started());
+ Destroy();
+}
+
+TEST_P(VideoRendererImplTest, DestroyWhileInitializing) {
CallInitialize(NewExpectedStatusCB(PIPELINE_ERROR_ABORT), false, PIPELINE_OK);
Destroy();
}
-TEST_F(VideoRendererImplTest, DestroyWhileFlushing) {
+TEST_P(VideoRendererImplTest, DestroyWhileFlushing) {
Initialize();
QueueFrames("0 10 20 30");
EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
@@ -383,7 +415,7 @@ TEST_F(VideoRendererImplTest, DestroyWhileFlushing) {
Destroy();
}
-TEST_F(VideoRendererImplTest, Play) {
+TEST_P(VideoRendererImplTest, Play) {
Initialize();
QueueFrames("0 10 20 30");
EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
@@ -392,7 +424,7 @@ TEST_F(VideoRendererImplTest, Play) {
Destroy();
}
-TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) {
+TEST_P(VideoRendererImplTest, FlushWithNothingBuffered) {
Initialize();
StartPlayingFrom(0);
@@ -402,14 +434,13 @@ TEST_F(VideoRendererImplTest, FlushWithNothingBuffered) {
Destroy();
}
-TEST_F(VideoRendererImplTest, DecodeError_Playing) {
+TEST_P(VideoRendererImplTest, DecodeError_Playing) {
Initialize();
QueueFrames("0 10 20 30");
EXPECT_CALL(mock_cb_, FrameReceived(_)).Times(testing::AtLeast(1));
EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
StartPlayingFrom(0);
-
- WaitForPendingRead();
+ renderer_->OnTimeStateChanged(true);
QueueFrames("error");
SatisfyPendingRead();
@@ -417,14 +448,14 @@ TEST_F(VideoRendererImplTest, DecodeError_Playing) {
Destroy();
}
-TEST_F(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
+TEST_P(VideoRendererImplTest, DecodeError_DuringStartPlayingFrom) {
Initialize();
QueueFrames("error");
StartPlayingFrom(0);
Destroy();
}
-TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) {
+TEST_P(VideoRendererImplTest, StartPlayingFrom_Exact) {
Initialize();
QueueFrames("50 60 70 80 90");
@@ -434,7 +465,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_Exact) {
Destroy();
}
-TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
+TEST_P(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
Initialize();
QueueFrames("50 60 70 80 90");
@@ -444,7 +475,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_RightBefore) {
Destroy();
}
-TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
+TEST_P(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
Initialize();
QueueFrames("50 60 70 80 90");
@@ -454,7 +485,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_RightAfter) {
Destroy();
}
-TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
+TEST_P(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
// In low-delay mode only one frame is required to finish preroll.
InitializeWithLowDelay(true);
QueueFrames("0");
@@ -470,6 +501,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
QueueFrames("10");
SatisfyPendingRead();
+ renderer_->OnTimeStateChanged(true);
WaitableMessageLoopEvent event;
EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(10)))
.WillOnce(RunClosure(event.GetClosure()));
@@ -480,7 +512,7 @@ TEST_F(VideoRendererImplTest, StartPlayingFrom_LowDelay) {
}
// Verify that a late decoder response doesn't break invariants in the renderer.
-TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) {
+TEST_P(VideoRendererImplTest, DestroyDuringOutstandingRead) {
Initialize();
QueueFrames("0 10 20 30");
EXPECT_CALL(mock_cb_, FrameReceived(HasTimestamp(0)));
@@ -493,12 +525,12 @@ TEST_F(VideoRendererImplTest, DestroyDuringOutstandingRead) {
Destroy();
}
-TEST_F(VideoRendererImplTest, VideoDecoder_InitFailure) {
+TEST_P(VideoRendererImplTest, VideoDecoder_InitFailure) {
InitializeRenderer(DECODER_ERROR_NOT_SUPPORTED, false);
Destroy();
}
-TEST_F(VideoRendererImplTest, Underflow) {
+TEST_P(VideoRendererImplTest, Underflow) {
Initialize();
QueueFrames("0 10 20 30");
@@ -512,6 +544,8 @@ TEST_F(VideoRendererImplTest, Underflow) {
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.
{
@@ -554,4 +588,152 @@ TEST_F(VideoRendererImplTest, Underflow) {
Destroy();
}
+// Tests the case where the video started in the background and never received
+// any Render() calls and time never started progressing (so the sink should be
+// stopped immediately).
+TEST_P(VideoRendererImplTest, BackgroundRenderingStopsAfterFirstFrame) {
+ // This test is only for the new rendering path.
+ if (!GetParam())
+ return;
+
+ // By default, tests disable background rendering, so enable it now and give
+ // a short, but non-zero, timeout.
+ renderer_->SetBackgroundRenderingForTesting(
+ true, base::TimeDelta::FromMilliseconds(kTestBackgroundRenderTimeoutMs));
+
+ InitializeWithLowDelay(true);
+ QueueFrames("0");
+
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
+
+ // Pause callbacks forever, but don't start the sink. Ended should not fire.
+ SuspendRenderCallbacks();
+ StartPlayingFrom(0);
+ EXPECT_TRUE(IsReadPending());
+ SatisfyPendingReadWithEndOfStream();
+
+ {
+ SCOPED_TRACE("Waiting for sink to stop.");
+ WaitableMessageLoopEvent event;
+ null_video_sink_->set_stop_cb(event.GetClosure());
+ event.RunAndWait();
+ }
+
+ EXPECT_FALSE(has_ended());
+ Destroy();
+}
+
+// Tests the case where the video started in the background and never received
+// any Render() calls, but time is progressing.
+TEST_P(VideoRendererImplTest, BackgroundRenderingNeverStarted) {
+ // This test is only for the new rendering path.
+ if (!GetParam())
+ return;
+
+ // By default, tests disable background rendering, so enable it now and give
+ // a short, but non-zero, timeout.
+ renderer_->SetBackgroundRenderingForTesting(
+ true, base::TimeDelta::FromMilliseconds(kTestBackgroundRenderTimeoutMs));
+
+ Initialize();
+ QueueFrames("0 10 20 30");
+
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
+
+ // Start the sink and pause callbacks forever.
+ renderer_->OnTimeStateChanged(true);
+ SuspendRenderCallbacks();
+ StartPlayingFrom(0);
+ AdvanceTimeInMs(41);
+ AdvanceWallclockTimeInMs(kTestBackgroundRenderTimeoutMs);
+
+ // Eventually background rendering should request new buffers and at that
+ // point fire the ended event if rendering has completed.
+ WaitForPendingRead();
+ SatisfyPendingReadWithEndOfStream();
+ WaitForEnded();
+ Destroy();
+}
+
+// Tests the case where the video started in the background and never received
+// any Render() calls, but time is progressing and there's only a single frame
+// in the video.
+TEST_P(VideoRendererImplTest, BackgroundRenderingNeverStartedSingleFrame) {
+ // This test is only for the new rendering path.
+ if (!GetParam())
+ return;
+
+ // By default, tests disable background rendering, so enable it now and give
+ // a short, but non-zero, timeout.
+ renderer_->SetBackgroundRenderingForTesting(
+ true, base::TimeDelta::FromMilliseconds(kTestBackgroundRenderTimeoutMs));
+
+ Initialize();
+ QueueFrames("0");
+
+ EXPECT_CALL(mock_cb_, BufferingStateChange(BUFFERING_HAVE_ENOUGH));
+
+ // Start the sink and pause callbacks forever.
+ renderer_->OnTimeStateChanged(true);
+ SuspendRenderCallbacks();
+ StartPlayingFrom(0);
+
+ AdvanceWallclockTimeInMs(kTestBackgroundRenderTimeoutMs);
+
+ // Eventually background rendering should request new buffers and at that
+ // point fire the ended event if rendering has completed.
+ WaitForPendingRead();
+ SatisfyPendingReadWithEndOfStream();
+ WaitForEnded();
+ Destroy();
+}
+
+// Tests the case where the video started and received a single Render() call,
+// then the video was put into the background.
+TEST_P(VideoRendererImplTest, BackgroundRenderingRenderStartedThenStopped) {
+ // This test is only for the new rendering path.
+ if (!GetParam())
+ return;
+
+ // By default, tests disable background rendering, so enable it now and give
+ // a short, but non-zero, timeout.
+ renderer_->SetBackgroundRenderingForTesting(
+ true, base::TimeDelta::FromMilliseconds(kTestBackgroundRenderTimeoutMs));
+
+ Initialize();
+ QueueFrames("0 10 20 30");
+
+ // Start the sink and wait for the first callback.
+ {
+ 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);
+
+ // Suspend all future callbacks and synthetically advance the media time.
+ SuspendRenderCallbacks();
+ AdvanceTimeInMs(41);
+ AdvanceWallclockTimeInMs(kTestBackgroundRenderTimeoutMs);
+
+ // Eventually background rendering should request new buffers and at that
+ // point fire the ended event if rendering has completed.
+ WaitForPendingRead();
+ SatisfyPendingReadWithEndOfStream();
+ WaitForEnded();
+ Destroy();
+}
+
+INSTANTIATE_TEST_CASE_P(OldVideoRenderer,
+ VideoRendererImplTest,
+ testing::Values(false));
+INSTANTIATE_TEST_CASE_P(NewVideoRenderer,
+ VideoRendererImplTest,
+ testing::Values(true));
+
} // namespace media
« no previous file with comments | « media/renderers/video_renderer_impl.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698