OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/macros.h" | 6 #include "base/macros.h" |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
9 #include "base/test/simple_test_tick_clock.h" | 9 #include "base/test/simple_test_tick_clock.h" |
10 #include "cc/layers/video_frame_provider.h" | 10 #include "cc/layers/video_frame_provider.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 ACTION_P(RunClosure, closure) { | 22 ACTION_P(RunClosure, closure) { |
23 closure.Run(); | 23 closure.Run(); |
24 } | 24 } |
25 | 25 |
26 class VideoFrameCompositorTest : public testing::Test, | 26 class VideoFrameCompositorTest : public testing::Test, |
27 public cc::VideoFrameProvider::Client, | 27 public cc::VideoFrameProvider::Client, |
28 public VideoRendererSink::RenderCallback { | 28 public VideoRendererSink::RenderCallback { |
29 public: | 29 public: |
30 VideoFrameCompositorTest() | 30 VideoFrameCompositorTest() |
31 : tick_clock_(new base::SimpleTestTickClock()), | 31 : tick_clock_(new base::SimpleTestTickClock()), |
32 compositor_(new VideoFrameCompositor( | 32 compositor_(new VideoFrameCompositor(message_loop.task_runner())), |
33 message_loop.task_runner(), | 33 did_receive_frame_count_(0) { |
34 base::Bind(&VideoFrameCompositorTest::NaturalSizeChanged, | |
35 base::Unretained(this)), | |
36 base::Bind(&VideoFrameCompositorTest::OpacityChanged, | |
37 base::Unretained(this)))), | |
38 did_receive_frame_count_(0), | |
39 natural_size_changed_count_(0), | |
40 opacity_changed_count_(0), | |
41 opaque_(false) { | |
42 compositor_->SetVideoFrameProviderClient(this); | 34 compositor_->SetVideoFrameProviderClient(this); |
43 compositor_->set_tick_clock_for_testing( | 35 compositor_->set_tick_clock_for_testing( |
44 std::unique_ptr<base::TickClock>(tick_clock_)); | 36 std::unique_ptr<base::TickClock>(tick_clock_)); |
45 // Disable background rendering by default. | 37 // Disable background rendering by default. |
46 compositor_->set_background_rendering_for_testing(false); | 38 compositor_->set_background_rendering_for_testing(false); |
47 } | 39 } |
48 | 40 |
49 ~VideoFrameCompositorTest() override { | 41 ~VideoFrameCompositorTest() override { |
50 compositor_->SetVideoFrameProviderClient(nullptr); | 42 compositor_->SetVideoFrameProviderClient(nullptr); |
51 } | 43 } |
52 | 44 |
53 scoped_refptr<VideoFrame> CreateOpaqueFrame() { | 45 scoped_refptr<VideoFrame> CreateOpaqueFrame() { |
54 gfx::Size size(8, 8); | 46 gfx::Size size(8, 8); |
55 return VideoFrame::CreateFrame(PIXEL_FORMAT_YV12, size, gfx::Rect(size), | 47 return VideoFrame::CreateFrame(PIXEL_FORMAT_YV12, size, gfx::Rect(size), |
56 size, base::TimeDelta()); | 48 size, base::TimeDelta()); |
57 } | 49 } |
58 | 50 |
59 VideoFrameCompositor* compositor() { return compositor_.get(); } | 51 VideoFrameCompositor* compositor() { return compositor_.get(); } |
60 int did_receive_frame_count() { return did_receive_frame_count_; } | 52 int did_receive_frame_count() { return did_receive_frame_count_; } |
61 int natural_size_changed_count() { return natural_size_changed_count_; } | |
62 gfx::Size natural_size() { return natural_size_; } | |
63 | |
64 int opacity_changed_count() { return opacity_changed_count_; } | |
65 bool opaque() { return opaque_; } | |
66 | 53 |
67 protected: | 54 protected: |
68 // cc::VideoFrameProvider::Client implementation. | 55 // cc::VideoFrameProvider::Client implementation. |
69 void StopUsingProvider() override {} | 56 void StopUsingProvider() override {} |
70 MOCK_METHOD0(StartRendering, void()); | 57 MOCK_METHOD0(StartRendering, void()); |
71 MOCK_METHOD0(StopRendering, void()); | 58 MOCK_METHOD0(StopRendering, void()); |
72 void DidReceiveFrame() override { ++did_receive_frame_count_; } | 59 void DidReceiveFrame() override { ++did_receive_frame_count_; } |
73 | 60 |
74 // VideoRendererSink::RenderCallback implementation. | 61 // VideoRendererSink::RenderCallback implementation. |
75 MOCK_METHOD3(Render, | 62 MOCK_METHOD3(Render, |
76 scoped_refptr<VideoFrame>(base::TimeTicks, | 63 scoped_refptr<VideoFrame>(base::TimeTicks, |
77 base::TimeTicks, | 64 base::TimeTicks, |
78 bool)); | 65 bool)); |
79 MOCK_METHOD0(OnFrameDropped, void()); | 66 MOCK_METHOD0(OnFrameDropped, void()); |
80 | 67 |
81 void NaturalSizeChanged(gfx::Size natural_size) { | |
82 ++natural_size_changed_count_; | |
83 natural_size_ = natural_size; | |
84 } | |
85 | |
86 void OpacityChanged(bool opaque) { | |
87 ++opacity_changed_count_; | |
88 opaque_ = opaque; | |
89 } | |
90 | |
91 void StartVideoRendererSink() { | 68 void StartVideoRendererSink() { |
92 EXPECT_CALL(*this, StartRendering()); | 69 EXPECT_CALL(*this, StartRendering()); |
93 const bool had_current_frame = !!compositor_->GetCurrentFrame(); | 70 const bool had_current_frame = !!compositor_->GetCurrentFrame(); |
94 compositor()->Start(this); | 71 compositor()->Start(this); |
95 // If we previously had a frame, we should still have one now. | 72 // If we previously had a frame, we should still have one now. |
96 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame()); | 73 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame()); |
97 message_loop.RunUntilIdle(); | 74 message_loop.RunUntilIdle(); |
98 } | 75 } |
99 | 76 |
100 void StopVideoRendererSink(bool have_client) { | 77 void StopVideoRendererSink(bool have_client) { |
101 if (have_client) | 78 if (have_client) |
102 EXPECT_CALL(*this, StopRendering()); | 79 EXPECT_CALL(*this, StopRendering()); |
103 const bool had_current_frame = !!compositor_->GetCurrentFrame(); | 80 const bool had_current_frame = !!compositor_->GetCurrentFrame(); |
104 compositor()->Stop(); | 81 compositor()->Stop(); |
105 // If we previously had a frame, we should still have one now. | 82 // If we previously had a frame, we should still have one now. |
106 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame()); | 83 EXPECT_EQ(had_current_frame, !!compositor_->GetCurrentFrame()); |
107 message_loop.RunUntilIdle(); | 84 message_loop.RunUntilIdle(); |
108 } | 85 } |
109 | 86 |
110 void RenderFrame() { | 87 void RenderFrame() { |
111 compositor()->GetCurrentFrame(); | 88 compositor()->GetCurrentFrame(); |
112 compositor()->PutCurrentFrame(); | 89 compositor()->PutCurrentFrame(); |
113 } | 90 } |
114 | 91 |
115 base::MessageLoop message_loop; | 92 base::MessageLoop message_loop; |
116 base::SimpleTestTickClock* tick_clock_; // Owned by |compositor_| | 93 base::SimpleTestTickClock* tick_clock_; // Owned by |compositor_| |
117 std::unique_ptr<VideoFrameCompositor> compositor_; | 94 std::unique_ptr<VideoFrameCompositor> compositor_; |
118 | 95 |
119 int did_receive_frame_count_; | 96 int did_receive_frame_count_; |
120 int natural_size_changed_count_; | |
121 gfx::Size natural_size_; | |
122 int opacity_changed_count_; | |
123 bool opaque_; | |
124 | 97 |
125 DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest); | 98 DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest); |
126 }; | 99 }; |
127 | 100 |
128 TEST_F(VideoFrameCompositorTest, InitialValues) { | 101 TEST_F(VideoFrameCompositorTest, InitialValues) { |
129 EXPECT_FALSE(compositor()->GetCurrentFrame().get()); | 102 EXPECT_FALSE(compositor()->GetCurrentFrame().get()); |
130 } | 103 } |
131 | 104 |
132 TEST_F(VideoFrameCompositorTest, PaintFrameUsingOldRenderingPath) { | 105 TEST_F(VideoFrameCompositorTest, PaintFrameUsingOldRenderingPath) { |
133 scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame(); | 106 scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame(); |
134 | 107 |
135 // Should notify compositor synchronously. | 108 // Should notify compositor synchronously. |
136 EXPECT_EQ(0, did_receive_frame_count()); | 109 EXPECT_EQ(0, did_receive_frame_count()); |
137 compositor()->PaintFrameUsingOldRenderingPath(expected); | 110 compositor()->PaintFrameUsingOldRenderingPath(expected); |
138 scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame(); | 111 scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame(); |
139 EXPECT_EQ(expected, actual); | 112 EXPECT_EQ(expected, actual); |
140 EXPECT_EQ(1, did_receive_frame_count()); | 113 EXPECT_EQ(1, did_receive_frame_count()); |
141 } | 114 } |
142 | 115 |
143 TEST_F(VideoFrameCompositorTest, NaturalSizeChanged) { | |
144 gfx::Size initial_size(8, 8); | |
145 scoped_refptr<VideoFrame> initial_frame = | |
146 VideoFrame::CreateBlackFrame(initial_size); | |
147 | |
148 gfx::Size larger_size(16, 16); | |
149 scoped_refptr<VideoFrame> larger_frame = | |
150 VideoFrame::CreateBlackFrame(larger_size); | |
151 | |
152 gfx::Size empty_size(0, 0); | |
153 | |
154 // Initial expectations. | |
155 EXPECT_EQ(empty_size, natural_size()); | |
156 EXPECT_EQ(0, natural_size_changed_count()); | |
157 | |
158 // Callback is fired for the first frame. | |
159 compositor()->PaintFrameUsingOldRenderingPath(initial_frame); | |
160 EXPECT_EQ(initial_size, natural_size()); | |
161 EXPECT_EQ(1, natural_size_changed_count()); | |
162 | |
163 // Callback should be fired once. | |
164 compositor()->PaintFrameUsingOldRenderingPath(larger_frame); | |
165 EXPECT_EQ(larger_size, natural_size()); | |
166 EXPECT_EQ(2, natural_size_changed_count()); | |
167 | |
168 compositor()->PaintFrameUsingOldRenderingPath(larger_frame); | |
169 EXPECT_EQ(larger_size, natural_size()); | |
170 EXPECT_EQ(2, natural_size_changed_count()); | |
171 | |
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(3, natural_size_changed_count()); | |
176 | |
177 compositor()->PaintFrameUsingOldRenderingPath(initial_frame); | |
178 EXPECT_EQ(initial_size, natural_size()); | |
179 EXPECT_EQ(3, natural_size_changed_count()); | |
180 | |
181 natural_size_changed_count_ = 0; | |
182 natural_size_ = empty_size; | |
183 compositor()->clear_current_frame_for_testing(); | |
184 | |
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(); | |
191 | |
192 // Starting the sink will issue one Render() call, ensure the callback is | |
193 // fired for the first frame. | |
194 EXPECT_EQ(1, natural_size_changed_count()); | |
195 EXPECT_EQ(initial_size, natural_size()); | |
196 | |
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(2, natural_size_changed_count()); | |
203 | |
204 EXPECT_TRUE( | |
205 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | |
206 RenderFrame(); | |
207 EXPECT_EQ(initial_size, natural_size()); | |
208 EXPECT_EQ(3, natural_size_changed_count()); | |
209 | |
210 EXPECT_FALSE( | |
211 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | |
212 EXPECT_EQ(initial_size, natural_size()); | |
213 EXPECT_EQ(3, natural_size_changed_count()); | |
214 RenderFrame(); | |
215 | |
216 StopVideoRendererSink(true); | |
217 } | |
218 | |
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()); | |
224 | |
225 // Initial expectations. | |
226 EXPECT_FALSE(opaque()); | |
227 EXPECT_EQ(0, opacity_changed_count()); | |
228 | |
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()); | |
233 | |
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()); | |
238 | |
239 // Callback is fired when using opacity changes. | |
240 compositor()->PaintFrameUsingOldRenderingPath(opaque_frame); | |
241 EXPECT_TRUE(opaque()); | |
242 EXPECT_EQ(2, opacity_changed_count()); | |
243 | |
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()); | |
248 | |
249 opacity_changed_count_ = 0; | |
250 compositor()->clear_current_frame_for_testing(); | |
251 | |
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()); | |
260 | |
261 EXPECT_TRUE( | |
262 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | |
263 RenderFrame(); | |
264 EXPECT_FALSE(opaque()); | |
265 EXPECT_EQ(1, opacity_changed_count()); | |
266 | |
267 EXPECT_TRUE( | |
268 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | |
269 RenderFrame(); | |
270 EXPECT_TRUE(opaque()); | |
271 EXPECT_EQ(2, opacity_changed_count()); | |
272 | |
273 EXPECT_FALSE( | |
274 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | |
275 EXPECT_TRUE(opaque()); | |
276 EXPECT_EQ(2, opacity_changed_count()); | |
277 RenderFrame(); | |
278 | |
279 StopVideoRendererSink(true); | |
280 } | |
281 | |
282 TEST_F(VideoFrameCompositorTest, VideoRendererSinkFrameDropped) { | 116 TEST_F(VideoFrameCompositorTest, VideoRendererSinkFrameDropped) { |
283 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame(); | 117 scoped_refptr<VideoFrame> opaque_frame = CreateOpaqueFrame(); |
284 | 118 |
285 EXPECT_CALL(*this, Render(_, _, _)).WillRepeatedly(Return(opaque_frame)); | 119 EXPECT_CALL(*this, Render(_, _, _)).WillRepeatedly(Return(opaque_frame)); |
286 StartVideoRendererSink(); | 120 StartVideoRendererSink(); |
287 | 121 |
288 EXPECT_TRUE( | 122 EXPECT_TRUE( |
289 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); | 123 compositor()->UpdateCurrentFrame(base::TimeTicks(), base::TimeTicks())); |
290 | 124 |
291 // Another call should trigger a dropped frame callback. | 125 // Another call should trigger a dropped frame callback. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 | 259 |
426 // Advancing the tick clock should allow a new frame to be requested. | 260 // Advancing the tick clock should allow a new frame to be requested. |
427 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); | 261 tick_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
428 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale()); | 262 ASSERT_EQ(opaque_frame_2, compositor()->GetCurrentFrameAndUpdateIfStale()); |
429 | 263 |
430 // Background rendering should tick another render callback. | 264 // Background rendering should tick another render callback. |
431 StopVideoRendererSink(false); | 265 StopVideoRendererSink(false); |
432 } | 266 } |
433 | 267 |
434 } // namespace media | 268 } // namespace media |
OLD | NEW |