Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / blink / video_frame_compositor_unittest.cc
bloba6b9ee1181894dfac3d73aa24110c3d03a78664b
1 // Copyright 2014 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.
5 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "cc/layers/video_frame_provider.h"
10 #include "media/base/video_frame.h"
11 #include "media/blink/video_frame_compositor.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 using testing::_;
16 using testing::DoAll;
17 using testing::Return;
19 namespace media {
21 ACTION_P(RunClosure, closure) {
22 closure.Run();
25 class VideoFrameCompositorTest : public testing::Test,
26 public cc::VideoFrameProvider::Client,
27 public VideoRendererSink::RenderCallback {
28 public:
29 VideoFrameCompositorTest()
30 : tick_clock_(new base::SimpleTestTickClock()),
31 compositor_(new VideoFrameCompositor(
32 message_loop.task_runner(),
33 base::Bind(&VideoFrameCompositorTest::NaturalSizeChanged,
34 base::Unretained(this)),
35 base::Bind(&VideoFrameCompositorTest::OpacityChanged,
36 base::Unretained(this)))),
37 did_receive_frame_count_(0),
38 natural_size_changed_count_(0),
39 opacity_changed_count_(0),
40 opaque_(false) {
41 compositor_->SetVideoFrameProviderClient(this);
42 compositor_->set_tick_clock_for_testing(
43 scoped_ptr<base::TickClock>(tick_clock_));
44 // Disable background rendering by default.
45 compositor_->set_background_rendering_for_testing(false);
48 ~VideoFrameCompositorTest() override {
49 compositor_->SetVideoFrameProviderClient(nullptr);
52 scoped_refptr<VideoFrame> CreateOpaqueFrame() {
53 gfx::Size size(8, 8);
54 return VideoFrame::CreateFrame(PIXEL_FORMAT_YV12, size, gfx::Rect(size),
55 size, base::TimeDelta());
58 VideoFrameCompositor* compositor() { return compositor_.get(); }
59 int did_receive_frame_count() { return did_receive_frame_count_; }
60 int natural_size_changed_count() { return natural_size_changed_count_; }
61 gfx::Size natural_size() { return natural_size_; }
63 int opacity_changed_count() { return opacity_changed_count_; }
64 bool opaque() { return opaque_; }
66 protected:
67 // cc::VideoFrameProvider::Client implementation.
68 void StopUsingProvider() override {}
69 MOCK_METHOD0(StartRendering, void());
70 MOCK_METHOD0(StopRendering, void());
71 void DidReceiveFrame() override { ++did_receive_frame_count_; }
72 void DidUpdateMatrix(const float* matrix) override {}
74 // VideoRendererSink::RenderCallback implementation.
75 MOCK_METHOD3(Render,
76 scoped_refptr<VideoFrame>(base::TimeTicks,
77 base::TimeTicks,
78 bool));
79 MOCK_METHOD0(OnFrameDropped, void());
81 void NaturalSizeChanged(gfx::Size natural_size) {
82 ++natural_size_changed_count_;
83 natural_size_ = natural_size;
86 void OpacityChanged(bool opaque) {
87 ++opacity_changed_count_;
88 opaque_ = opaque;
91 void StartVideoRendererSink() {
92 EXPECT_CALL(*this, StartRendering());
93 const bool had_current_frame = !!compositor_->GetCurrentFrame();
94 compositor()->Start(this);
95 // If we previously had a frame, we should still have one now.
96 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame());
97 message_loop.RunUntilIdle();
100 void StopVideoRendererSink(bool have_client) {
101 if (have_client)
102 EXPECT_CALL(*this, StopRendering());
103 const bool had_current_frame = !!compositor_->GetCurrentFrame();
104 compositor()->Stop();
105 // If we previously had a frame, we should still have one now.
106 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame());
107 message_loop.RunUntilIdle();
110 void RenderFrame() {
111 compositor()->GetCurrentFrame();
112 compositor()->PutCurrentFrame();
115 base::MessageLoop message_loop;
116 base::SimpleTestTickClock* tick_clock_; // Owned by |compositor_|
117 scoped_ptr<VideoFrameCompositor> compositor_;
119 int did_receive_frame_count_;
120 int natural_size_changed_count_;
121 gfx::Size natural_size_;
122 int opacity_changed_count_;
123 bool opaque_;
125 DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest);
128 TEST_F(VideoFrameCompositorTest, InitialValues) {
129 EXPECT_FALSE(compositor()->GetCurrentFrame().get());
132 TEST_F(VideoFrameCompositorTest, PaintFrameUsingOldRenderingPath) {
133 scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame();
135 // Should notify compositor synchronously.
136 EXPECT_EQ(0, did_receive_frame_count());
137 compositor()->PaintFrameUsingOldRenderingPath(expected);
138 scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame();
139 EXPECT_EQ(expected, actual);
140 EXPECT_EQ(1, did_receive_frame_count());
143 TEST_F(VideoFrameCompositorTest, NaturalSizeChanged) {
144 gfx::Size initial_size(8, 8);
145 scoped_refptr<VideoFrame> initial_frame =
146 VideoFrame::CreateBlackFrame(initial_size);
148 gfx::Size larger_size(16, 16);
149 scoped_refptr<VideoFrame> larger_frame =
150 VideoFrame::CreateBlackFrame(larger_size);
152 gfx::Size empty_size(0, 0);
154 // Initial expectations.
155 EXPECT_EQ(empty_size, natural_size());
156 EXPECT_EQ(0, natural_size_changed_count());
158 // Callback isn't fired for the first frame.
159 compositor()->PaintFrameUsingOldRenderingPath(initial_frame);
160 EXPECT_EQ(empty_size, natural_size());
161 EXPECT_EQ(0, natural_size_changed_count());
163 // Callback should be fired once.
164 compositor()->PaintFrameUsingOldRenderingPath(larger_frame);
165 EXPECT_EQ(larger_size, natural_size());
166 EXPECT_EQ(1, natural_size_changed_count());
168 compositor()->PaintFrameUsingOldRenderingPath(larger_frame);
169 EXPECT_EQ(larger_size, natural_size());
170 EXPECT_EQ(1, natural_size_changed_count());
172 // Callback is fired once more when switching back to initial size.
173 compositor()->PaintFrameUsingOldRenderingPath(initial_frame);
174 EXPECT_EQ(initial_size, natural_size());
175 EXPECT_EQ(2, natural_size_changed_count());
177 compositor()->PaintFrameUsingOldRenderingPath(initial_frame);
178 EXPECT_EQ(initial_size, natural_size());
179 EXPECT_EQ(2, natural_size_changed_count());
181 natural_size_changed_count_ = 0;
182 natural_size_ = empty_size;
183 compositor()->clear_current_frame_for_testing();
185 EXPECT_CALL(*this, Render(_, _, _))
186 .WillOnce(Return(initial_frame))
187 .WillOnce(Return(larger_frame))
188 .WillOnce(Return(initial_frame))
189 .WillOnce(Return(initial_frame));
190 StartVideoRendererSink();
192 // Starting the sink will issue one Render() call, ensure the callback isn't
193 // fired for the first frame.
194 EXPECT_EQ(0, natural_size_changed_count());
195 EXPECT_EQ(empty_size, natural_size());
197 // Once another frame is received with a different size it should fire.
198 EXPECT_TRUE(
199 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
200 RenderFrame();
201 EXPECT_EQ(larger_size, natural_size());
202 EXPECT_EQ(1, natural_size_changed_count());
204 EXPECT_TRUE(
205 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
206 RenderFrame();
207 EXPECT_EQ(initial_size, natural_size());
208 EXPECT_EQ(2, natural_size_changed_count());
210 EXPECT_FALSE(
211 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
212 EXPECT_EQ(initial_size, natural_size());
213 EXPECT_EQ(2, natural_size_changed_count());
214 RenderFrame();
216 StopVideoRendererSink(true);
219 TEST_F(VideoFrameCompositorTest, OpacityChanged) {
220 gfx::Size size(8, 8);
221 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
222 scoped_refptr<VideoFrame> not_opaque_frame = VideoFrame::CreateFrame(
223 PIXEL_FORMAT_YV12A, size, gfx::Rect(size), size, base::TimeDelta());
225 // Initial expectations.
226 EXPECT_FALSE(opaque());
227 EXPECT_EQ(0, opacity_changed_count());
229 // Callback is fired for the first frame.
230 compositor()->PaintFrameUsingOldRenderingPath(not_opaque_frame);
231 EXPECT_FALSE(opaque());
232 EXPECT_EQ(1, opacity_changed_count());
234 // Callback shouldn't be first subsequent times with same opaqueness.
235 compositor()->PaintFrameUsingOldRenderingPath(not_opaque_frame);
236 EXPECT_FALSE(opaque());
237 EXPECT_EQ(1, opacity_changed_count());
239 // Callback is fired when using opacity changes.
240 compositor()->PaintFrameUsingOldRenderingPath(opaque_frame);
241 EXPECT_TRUE(opaque());
242 EXPECT_EQ(2, opacity_changed_count());
244 // Callback shouldn't be first subsequent times with same opaqueness.
245 compositor()->PaintFrameUsingOldRenderingPath(opaque_frame);
246 EXPECT_TRUE(opaque());
247 EXPECT_EQ(2, opacity_changed_count());
249 opacity_changed_count_ = 0;
250 compositor()->clear_current_frame_for_testing();
252 EXPECT_CALL(*this, Render(_, _, _))
253 .WillOnce(Return(not_opaque_frame))
254 .WillOnce(Return(not_opaque_frame))
255 .WillOnce(Return(opaque_frame))
256 .WillOnce(Return(opaque_frame));
257 StartVideoRendererSink();
258 EXPECT_FALSE(opaque());
259 EXPECT_EQ(1, opacity_changed_count());
261 EXPECT_TRUE(
262 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
263 RenderFrame();
264 EXPECT_FALSE(opaque());
265 EXPECT_EQ(1, opacity_changed_count());
267 EXPECT_TRUE(
268 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
269 RenderFrame();
270 EXPECT_TRUE(opaque());
271 EXPECT_EQ(2, opacity_changed_count());
273 EXPECT_FALSE(
274 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
275 EXPECT_TRUE(opaque());
276 EXPECT_EQ(2, opacity_changed_count());
277 RenderFrame();
279 StopVideoRendererSink(true);
282 TEST_F(VideoFrameCompositorTest, VideoRendererSinkFrameDropped) {
283 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
285 EXPECT_CALL(*this, Render(_, _, _)).WillRepeatedly(Return(opaque_frame));
286 StartVideoRendererSink();
288 EXPECT_TRUE(
289 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
291 // Another call should trigger a dropped frame callback.
292 EXPECT_CALL(*this, OnFrameDropped());
293 EXPECT_FALSE(
294 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
296 // Ensure it always happens until the frame is rendered.
297 EXPECT_CALL(*this, OnFrameDropped());
298 EXPECT_FALSE(
299 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
301 // Call GetCurrentFrame() but not PutCurrentFrame()
302 compositor()->GetCurrentFrame();
304 // The frame should still register as dropped until PutCurrentFrame is called.
305 EXPECT_CALL(*this, OnFrameDropped());
306 EXPECT_FALSE(
307 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
309 RenderFrame();
310 EXPECT_FALSE(
311 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
313 StopVideoRendererSink(true);
316 TEST_F(VideoFrameCompositorTest, VideoLayerShutdownWhileRendering) {
317 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(nullptr));
318 StartVideoRendererSink();
319 compositor_->SetVideoFrameProviderClient(nullptr);
320 StopVideoRendererSink(false);
323 TEST_F(VideoFrameCompositorTest, StartFiresBackgroundRender) {
324 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
325 EXPECT_CALL(*this, Render(_, _, true)).WillRepeatedly(Return(opaque_frame));
326 StartVideoRendererSink();
327 StopVideoRendererSink(true);
330 TEST_F(VideoFrameCompositorTest, BackgroundRenderTicks) {
331 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
332 compositor_->set_background_rendering_for_testing(true);
334 base::RunLoop run_loop;
335 EXPECT_CALL(*this, Render(_, _, true))
336 .WillOnce(Return(opaque_frame))
337 .WillOnce(
338 DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame)));
339 StartVideoRendererSink();
340 run_loop.Run();
342 // UpdateCurrentFrame() calls should indicate they are not synthetic.
343 EXPECT_CALL(*this, Render(_, _, false)).WillOnce(Return(opaque_frame));
344 EXPECT_FALSE(
345 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
347 // Background rendering should tick another render callback.
348 StopVideoRendererSink(true);
351 TEST_F(VideoFrameCompositorTest,
352 UpdateCurrentFrameWorksWhenBackgroundRendered) {
353 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
354 compositor_->set_background_rendering_for_testing(true);
356 // Background render a frame that succeeds immediately.
357 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(opaque_frame));
358 StartVideoRendererSink();
360 // The background render completes immediately, so the next call to
361 // UpdateCurrentFrame is expected to return true to account for the frame
362 // rendered in the background.
363 EXPECT_CALL(*this, Render(_, _, false))
364 .WillOnce(Return(scoped_refptr<VideoFrame>(opaque_frame)));
365 EXPECT_TRUE(
366 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
367 RenderFrame();
369 // Second call to UpdateCurrentFrame will return false as no new frame has
370 // been created since the last call.
371 EXPECT_CALL(*this, Render(_, _, false))
372 .WillOnce(Return(scoped_refptr<VideoFrame>(opaque_frame)));
373 EXPECT_FALSE(
374 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
376 StopVideoRendererSink(true);
379 TEST_F(VideoFrameCompositorTest, GetCurrentFrameAndUpdateIfStale) {
380 scoped_refptr<VideoFrame> opaque_frame_1 = CreateOpaqueFrame();
381 scoped_refptr<VideoFrame> opaque_frame_2 = CreateOpaqueFrame();
382 compositor_->set_background_rendering_for_testing(true);
384 // |current_frame_| should be null at this point since we don't have a client
385 // or a callback.
386 ASSERT_FALSE(compositor()->GetCurrentFrameAndUpdateIfStale());
388 // Starting the video renderer should return a single frame.
389 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(opaque_frame_1));
390 StartVideoRendererSink();
392 // Since we have a client, this call should not call background render, even
393 // if a lot of time has elapsed between calls.
394 tick_clock_->Advance(base::TimeDelta::FromSeconds(1));
395 ASSERT_EQ(opaque_frame_1, compositor()->GetCurrentFrameAndUpdateIfStale());
397 // An update current frame call should stop background rendering.
398 EXPECT_CALL(*this, Render(_, _, false)).WillOnce(Return(opaque_frame_2));
399 EXPECT_TRUE(
400 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
402 // This call should still not call background render.
403 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
405 testing::Mock::VerifyAndClearExpectations(this);
407 // Clear our client, which means no mock function calls for Client.
408 compositor()->SetVideoFrameProviderClient(nullptr);
410 // This call should still not call background render, because we aren't in the
411 // background rendering state yet.
412 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
414 // Wait for background rendering to tick again.
415 base::RunLoop run_loop;
416 EXPECT_CALL(*this, Render(_, _, true))
417 .WillOnce(
418 DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame_1)))
419 .WillOnce(Return(opaque_frame_2));
420 run_loop.Run();
422 // This call should still not call background render, because not enough time
423 // has elapsed since the last background render call.
424 ASSERT_EQ(opaque_frame_1, compositor()->GetCurrentFrameAndUpdateIfStale());
426 // Advancing the tick clock should allow a new frame to be requested.
427 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
428 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
430 // Background rendering should tick another render callback.
431 StopVideoRendererSink(false);
434 } // namespace media