Removal of UpdateMultivaluedField() as we now don't have multiple values for name...
[chromium-blink-merge.git] / media / blink / video_frame_compositor_unittest.cc
blobde5b7b0005e08c0c25fbb0cf8895db0e757aeb0c
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_FALSE(
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 // The first UpdateCurrentFrame() after a background render, which starting
289 // the sink does automatically, won't report a dropped frame.
290 EXPECT_FALSE(
291 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
293 // Another call should trigger a dropped frame callback.
294 EXPECT_CALL(*this, OnFrameDropped());
295 EXPECT_FALSE(
296 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
298 // Ensure it always happens until the frame is rendered.
299 EXPECT_CALL(*this, OnFrameDropped());
300 EXPECT_FALSE(
301 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
303 // Call GetCurrentFrame() but not PutCurrentFrame()
304 compositor()->GetCurrentFrame();
306 // The frame should still register as dropped until PutCurrentFrame is called.
307 EXPECT_CALL(*this, OnFrameDropped());
308 EXPECT_FALSE(
309 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
311 RenderFrame();
312 EXPECT_FALSE(
313 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
315 StopVideoRendererSink(true);
318 TEST_F(VideoFrameCompositorTest, VideoLayerShutdownWhileRendering) {
319 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(nullptr));
320 StartVideoRendererSink();
321 compositor_->SetVideoFrameProviderClient(nullptr);
322 StopVideoRendererSink(false);
325 TEST_F(VideoFrameCompositorTest, StartFiresBackgroundRender) {
326 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
327 EXPECT_CALL(*this, Render(_, _, true)).WillRepeatedly(Return(opaque_frame));
328 StartVideoRendererSink();
329 StopVideoRendererSink(true);
332 TEST_F(VideoFrameCompositorTest, BackgroundRenderTicks) {
333 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
334 compositor_->set_background_rendering_for_testing(true);
336 base::RunLoop run_loop;
337 EXPECT_CALL(*this, Render(_, _, true))
338 .WillOnce(Return(opaque_frame))
339 .WillOnce(
340 DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame)));
341 StartVideoRendererSink();
342 run_loop.Run();
344 // UpdateCurrentFrame() calls should indicate they are not synthetic.
345 EXPECT_CALL(*this, Render(_, _, false)).WillOnce(Return(opaque_frame));
346 EXPECT_FALSE(
347 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
349 // Background rendering should tick another render callback.
350 StopVideoRendererSink(true);
353 TEST_F(VideoFrameCompositorTest,
354 UpdateCurrentFrameWorksWhenBackgroundRendered) {
355 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame();
356 compositor_->set_background_rendering_for_testing(true);
358 // Background render a frame that succeeds immediately.
359 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(opaque_frame));
360 StartVideoRendererSink();
362 // The background render completes immediately, so the next call to
363 // UpdateCurrentFrame is expected to return true to account for the frame
364 // rendered in the background.
365 EXPECT_CALL(*this, Render(_, _, false))
366 .WillOnce(Return(scoped_refptr<VideoFrame>(opaque_frame)));
367 EXPECT_TRUE(
368 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
369 RenderFrame();
371 // Second call to UpdateCurrentFrame will return false as no new frame has
372 // been created since the last call.
373 EXPECT_CALL(*this, Render(_, _, false))
374 .WillOnce(Return(scoped_refptr<VideoFrame>(opaque_frame)));
375 EXPECT_FALSE(
376 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
378 StopVideoRendererSink(true);
381 TEST_F(VideoFrameCompositorTest, GetCurrentFrameAndUpdateIfStale) {
382 scoped_refptr<VideoFrame> opaque_frame_1 = CreateOpaqueFrame();
383 scoped_refptr<VideoFrame> opaque_frame_2 = CreateOpaqueFrame();
384 compositor_->set_background_rendering_for_testing(true);
386 // |current_frame_| should be null at this point since we don't have a client
387 // or a callback.
388 ASSERT_FALSE(compositor()->GetCurrentFrameAndUpdateIfStale());
390 // Starting the video renderer should return a single frame.
391 EXPECT_CALL(*this, Render(_, _, true)).WillOnce(Return(opaque_frame_1));
392 StartVideoRendererSink();
394 // Since we have a client, this call should not call background render, even
395 // if a lot of time has elapsed between calls.
396 tick_clock_->Advance(base::TimeDelta::FromSeconds(1));
397 ASSERT_EQ(opaque_frame_1, compositor()->GetCurrentFrameAndUpdateIfStale());
399 // An update current frame call should stop background rendering.
400 EXPECT_CALL(*this, Render(_, _, false)).WillOnce(Return(opaque_frame_2));
401 EXPECT_TRUE(
402 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks()));
404 // This call should still not call background render.
405 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
407 testing::Mock::VerifyAndClearExpectations(this);
409 // Clear our client, which means no mock function calls for Client.
410 compositor()->SetVideoFrameProviderClient(nullptr);
412 // This call should still not call background render, because we aren't in the
413 // background rendering state yet.
414 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
416 // Wait for background rendering to tick again.
417 base::RunLoop run_loop;
418 EXPECT_CALL(*this, Render(_, _, true))
419 .WillOnce(
420 DoAll(RunClosure(run_loop.QuitClosure()), Return(opaque_frame_1)))
421 .WillOnce(Return(opaque_frame_2));
422 run_loop.Run();
424 // This call should still not call background render, because not enough time
425 // has elapsed since the last background render call.
426 ASSERT_EQ(opaque_frame_1, compositor()->GetCurrentFrameAndUpdateIfStale());
428 // Advancing the tick clock should allow a new frame to be requested.
429 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
430 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale());
432 // Background rendering should tick another render callback.
433 StopVideoRendererSink(false);
436 } // namespace media