OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "cc/resources/media/skcanvas_video_renderer.h" |
| 6 #include "media/base/media.h" |
5 #include "media/base/video_frame.h" | 7 #include "media/base/video_frame.h" |
6 #include "media/base/video_util.h" | 8 #include "media/base/video_util.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
8 #include "third_party/skia/include/core/SkCanvas.h" | 10 #include "third_party/skia/include/core/SkCanvas.h" |
9 #include "media/filters/skcanvas_video_renderer.h" | |
10 | 11 |
11 using media::VideoFrame; | 12 using media::VideoFrame; |
12 | 13 |
13 namespace media { | 14 namespace cc { |
14 | 15 |
15 static const int kWidth = 320; | 16 static const int kWidth = 320; |
16 static const int kHeight = 240; | 17 static const int kHeight = 240; |
17 static const gfx::Rect kNaturalRect(0, 0, kWidth, kHeight); | 18 static const gfx::Rect kNaturalRect(0, 0, kWidth, kHeight); |
18 | 19 |
19 // Helper for filling a |canvas| with a solid |color|. | 20 // Helper for filling a |canvas| with a solid |color|. |
20 void FillCanvas(SkCanvas* canvas, SkColor color) { | 21 void FillCanvas(SkCanvas* canvas, SkColor color) { |
21 canvas->clear(color); | 22 canvas->clear(color); |
22 } | 23 } |
23 | 24 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 | 79 |
79 static SkBitmap AllocBitmap(int width, int height) { | 80 static SkBitmap AllocBitmap(int width, int height) { |
80 SkBitmap bitmap; | 81 SkBitmap bitmap; |
81 bitmap.allocPixels(SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType)); | 82 bitmap.allocPixels(SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType)); |
82 bitmap.eraseColor(0); | 83 bitmap.eraseColor(0); |
83 return bitmap; | 84 return bitmap; |
84 } | 85 } |
85 | 86 |
86 SkCanvasVideoRendererTest::SkCanvasVideoRendererTest() | 87 SkCanvasVideoRendererTest::SkCanvasVideoRendererTest() |
87 : natural_frame_(VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight))), | 88 : natural_frame_(VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight))), |
88 larger_frame_(VideoFrame::CreateBlackFrame( | 89 larger_frame_( |
89 gfx::Size(kWidth * 2, kHeight * 2))), | 90 VideoFrame::CreateBlackFrame(gfx::Size(kWidth * 2, kHeight * 2))), |
90 smaller_frame_(VideoFrame::CreateBlackFrame( | 91 smaller_frame_( |
91 gfx::Size(kWidth / 2, kHeight / 2))), | 92 VideoFrame::CreateBlackFrame(gfx::Size(kWidth / 2, kHeight / 2))), |
92 cropped_frame_(VideoFrame::CreateFrame( | 93 cropped_frame_( |
93 VideoFrame::YV12, | 94 VideoFrame::CreateFrame(VideoFrame::YV12, |
94 gfx::Size(16, 16), | 95 gfx::Size(16, 16), |
95 gfx::Rect(6, 6, 8, 6), | 96 gfx::Rect(6, 6, 8, 6), |
96 gfx::Size(8, 6), | 97 gfx::Size(8, 6), |
97 base::TimeDelta::FromMilliseconds(4))), | 98 base::TimeDelta::FromMilliseconds(4))), |
98 target_canvas_(AllocBitmap(kWidth, kHeight)) { | 99 target_canvas_(AllocBitmap(kWidth, kHeight)) { |
| 100 media::InitializeMediaLibraryForTesting(); |
| 101 |
99 // Give each frame a unique timestamp. | 102 // Give each frame a unique timestamp. |
100 natural_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(1)); | 103 natural_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(1)); |
101 larger_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(2)); | 104 larger_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(2)); |
102 smaller_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(3)); | 105 smaller_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(3)); |
103 | 106 |
104 // Make sure the cropped video frame's aspect ratio matches the output device. | 107 // Make sure the cropped video frame's aspect ratio matches the output device. |
105 // Update cropped_frame_'s crop dimensions if this is not the case. | 108 // Update cropped_frame_'s crop dimensions if this is not the case. |
106 EXPECT_EQ(cropped_frame()->visible_rect().width() * kHeight, | 109 EXPECT_EQ(cropped_frame()->visible_rect().width() * kHeight, |
107 cropped_frame()->visible_rect().height() * kWidth); | 110 cropped_frame()->visible_rect().height() * kWidth); |
108 | 111 |
(...skipping 22 matching lines...) Expand all Loading... |
131 // Bl Bl R R R R R R | 134 // Bl Bl R R R R R R |
132 // G G B B B B B B | 135 // G G B B B B B B |
133 // G G B B B B B B | 136 // G G B B B B B B |
134 // G G B B B B B B | 137 // G G B B B B B B |
135 // G G B B B B B B | 138 // G G B B B B B B |
136 // | 139 // |
137 // Each color region in the cropped frame is on a 2x2 block granularity, to | 140 // Each color region in the cropped frame is on a 2x2 block granularity, to |
138 // avoid sharing UV samples between regions. | 141 // avoid sharing UV samples between regions. |
139 | 142 |
140 static const uint8 cropped_y_plane[] = { | 143 static const uint8 cropped_y_plane[] = { |
141 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 144 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
142 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 145 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
143 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 146 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
144 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 147 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
145 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 148 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
146 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 149 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
147 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 150 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
148 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, | 151 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76, 76, 76, 76, 76, 76, |
149 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 152 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
150 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 153 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
151 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 154 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
152 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 155 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
153 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 156 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
154 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 157 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
155 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 158 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
156 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, | 159 149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29, |
157 }; | 160 }; |
158 | 161 |
159 static const uint8 cropped_u_plane[] = { | 162 static const uint8 cropped_u_plane[] = { |
160 128, 128, 128, 128, 84, 84, 84, 84, | 163 128, 128, 128, 128, 84, 84, 84, 84, 128, 128, 128, 128, 84, |
161 128, 128, 128, 128, 84, 84, 84, 84, | 164 84, 84, 84, 128, 128, 128, 128, 84, 84, 84, 84, 128, 128, |
162 128, 128, 128, 128, 84, 84, 84, 84, | 165 128, 128, 84, 84, 84, 84, 43, 43, 43, 43, 255, 255, 255, |
163 128, 128, 128, 128, 84, 84, 84, 84, | 166 255, 43, 43, 43, 43, 255, 255, 255, 255, 43, 43, 43, 43, |
164 43, 43, 43, 43, 255, 255, 255, 255, | 167 255, 255, 255, 255, 43, 43, 43, 43, 255, 255, 255, 255, |
165 43, 43, 43, 43, 255, 255, 255, 255, | |
166 43, 43, 43, 43, 255, 255, 255, 255, | |
167 43, 43, 43, 43, 255, 255, 255, 255, | |
168 }; | 168 }; |
169 static const uint8 cropped_v_plane[] = { | 169 static const uint8 cropped_v_plane[] = { |
170 128, 128, 128, 128, 255, 255, 255, 255, | 170 128, 128, 128, 128, 255, 255, 255, 255, 128, 128, 128, 128, 255, |
171 128, 128, 128, 128, 255, 255, 255, 255, | 171 255, 255, 255, 128, 128, 128, 128, 255, 255, 255, 255, 128, 128, |
172 128, 128, 128, 128, 255, 255, 255, 255, | 172 128, 128, 255, 255, 255, 255, 21, 21, 21, 21, 107, 107, 107, |
173 128, 128, 128, 128, 255, 255, 255, 255, | 173 107, 21, 21, 21, 21, 107, 107, 107, 107, 21, 21, 21, 21, |
174 21, 21, 21, 21, 107, 107, 107, 107, | 174 107, 107, 107, 107, 21, 21, 21, 21, 107, 107, 107, 107, |
175 21, 21, 21, 21, 107, 107, 107, 107, | |
176 21, 21, 21, 21, 107, 107, 107, 107, | |
177 21, 21, 21, 21, 107, 107, 107, 107, | |
178 }; | 175 }; |
179 | 176 |
180 media::CopyYPlane(cropped_y_plane, 16, 16, cropped_frame()); | 177 media::CopyYPlane(cropped_y_plane, 16, 16, cropped_frame()); |
181 media::CopyUPlane(cropped_u_plane, 8, 8, cropped_frame()); | 178 media::CopyUPlane(cropped_u_plane, 8, 8, cropped_frame()); |
182 media::CopyVPlane(cropped_v_plane, 8, 8, cropped_frame()); | 179 media::CopyVPlane(cropped_v_plane, 8, 8, cropped_frame()); |
183 } | 180 } |
184 | 181 |
185 SkCanvasVideoRendererTest::~SkCanvasVideoRendererTest() {} | 182 SkCanvasVideoRendererTest::~SkCanvasVideoRendererTest() { |
| 183 } |
186 | 184 |
187 void SkCanvasVideoRendererTest::PaintWithoutFrame(SkCanvas* canvas) { | 185 void SkCanvasVideoRendererTest::PaintWithoutFrame(SkCanvas* canvas) { |
188 renderer_.Paint(NULL, canvas, kNaturalRect, 0xFF); | 186 renderer_.Paint(NULL, canvas, kNaturalRect, 0xFF, 0); |
189 } | 187 } |
190 | 188 |
191 void SkCanvasVideoRendererTest::Paint(VideoFrame* video_frame, | 189 void SkCanvasVideoRendererTest::Paint(VideoFrame* video_frame, |
192 SkCanvas* canvas, | 190 SkCanvas* canvas, |
193 Color color) { | 191 Color color) { |
194 switch (color) { | 192 switch (color) { |
195 case kNone: | 193 case kNone: |
196 break; | 194 break; |
197 case kRed: | 195 case kRed: |
198 media::FillYUV(video_frame, 76, 84, 255); | 196 media::FillYUV(video_frame, 76, 84, 255); |
199 break; | 197 break; |
200 case kGreen: | 198 case kGreen: |
201 media::FillYUV(video_frame, 149, 43, 21); | 199 media::FillYUV(video_frame, 149, 43, 21); |
202 break; | 200 break; |
203 case kBlue: | 201 case kBlue: |
204 media::FillYUV(video_frame, 29, 255, 107); | 202 media::FillYUV(video_frame, 29, 255, 107); |
205 break; | 203 break; |
206 } | 204 } |
207 renderer_.Paint(video_frame, canvas, kNaturalRect, 0xFF); | 205 renderer_.Paint(video_frame, canvas, kNaturalRect, 0xFF, 0); |
208 } | 206 } |
209 | 207 |
210 TEST_F(SkCanvasVideoRendererTest, NoFrame) { | 208 TEST_F(SkCanvasVideoRendererTest, NoFrame) { |
211 // Test that black gets painted over canvas. | 209 // Test that black gets painted over canvas. |
212 FillCanvas(target_canvas(), SK_ColorRED); | 210 FillCanvas(target_canvas(), SK_ColorRED); |
213 PaintWithoutFrame(target_canvas()); | 211 PaintWithoutFrame(target_canvas()); |
214 EXPECT_EQ(SK_ColorBLACK, GetColor(target_canvas())); | 212 EXPECT_EQ(SK_ColorBLACK, GetColor(target_canvas())); |
215 } | 213 } |
216 | 214 |
217 TEST_F(SkCanvasVideoRendererTest, TransparentFrame) { | 215 TEST_F(SkCanvasVideoRendererTest, TransparentFrame) { |
218 // Test that we don't blend with existing canvas contents. | 216 // Test that we don't blend with existing canvas contents. |
219 FillCanvas(target_canvas(), SK_ColorRED); | 217 FillCanvas(target_canvas(), SK_ColorRED); |
220 Paint(VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)), | 218 Paint(VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)), |
221 target_canvas(), | 219 target_canvas(), |
222 kNone); | 220 kNone); |
223 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), | 221 EXPECT_EQ(static_cast<SkColor>(SK_ColorRED), GetColor(target_canvas())); |
224 GetColor(target_canvas())); | |
225 } | 222 } |
226 | 223 |
227 TEST_F(SkCanvasVideoRendererTest, Natural) { | 224 TEST_F(SkCanvasVideoRendererTest, Natural) { |
228 Paint(natural_frame(), target_canvas(), kRed); | 225 Paint(natural_frame(), target_canvas(), kRed); |
229 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); | 226 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); |
230 } | 227 } |
231 | 228 |
232 TEST_F(SkCanvasVideoRendererTest, Larger) { | 229 TEST_F(SkCanvasVideoRendererTest, Larger) { |
233 Paint(natural_frame(), target_canvas(), kRed); | 230 Paint(natural_frame(), target_canvas(), kRed); |
234 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); | 231 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); |
(...skipping 23 matching lines...) Expand all Loading... |
258 | 255 |
259 // Slow paints can get cached, expect the old color value. | 256 // Slow paints can get cached, expect the old color value. |
260 Paint(natural_frame(), target_canvas(), kBlue); | 257 Paint(natural_frame(), target_canvas(), kBlue); |
261 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); | 258 EXPECT_EQ(SK_ColorRED, GetColor(target_canvas())); |
262 } | 259 } |
263 | 260 |
264 TEST_F(SkCanvasVideoRendererTest, CroppedFrame) { | 261 TEST_F(SkCanvasVideoRendererTest, CroppedFrame) { |
265 Paint(cropped_frame(), target_canvas(), kNone); | 262 Paint(cropped_frame(), target_canvas(), kNone); |
266 // Check the corners. | 263 // Check the corners. |
267 EXPECT_EQ(SK_ColorBLACK, GetColorAt(target_canvas(), 0, 0)); | 264 EXPECT_EQ(SK_ColorBLACK, GetColorAt(target_canvas(), 0, 0)); |
268 EXPECT_EQ(SK_ColorRED, GetColorAt(target_canvas(), kWidth - 1, 0)); | 265 EXPECT_EQ(SK_ColorRED, GetColorAt(target_canvas(), kWidth - 1, 0)); |
269 EXPECT_EQ(SK_ColorGREEN, GetColorAt(target_canvas(), 0, kHeight - 1)); | 266 EXPECT_EQ(SK_ColorGREEN, GetColorAt(target_canvas(), 0, kHeight - 1)); |
270 EXPECT_EQ(SK_ColorBLUE, GetColorAt(target_canvas(), kWidth - 1, | 267 EXPECT_EQ(SK_ColorBLUE, GetColorAt(target_canvas(), kWidth - 1, kHeight - 1)); |
271 kHeight - 1)); | |
272 // Check the interior along the border between color regions. Note that we're | 268 // Check the interior along the border between color regions. Note that we're |
273 // bilinearly upscaling, so we'll need to take care to pick sample points that | 269 // bilinearly upscaling, so we'll need to take care to pick sample points that |
274 // are just outside the "zone of resampling". | 270 // are just outside the "zone of resampling". |
275 EXPECT_EQ(SK_ColorBLACK, GetColorAt(target_canvas(), kWidth * 1 / 8 - 1, | 271 EXPECT_EQ( |
276 kHeight * 1 / 6 - 1)); | 272 SK_ColorBLACK, |
277 EXPECT_EQ(SK_ColorRED, GetColorAt(target_canvas(), kWidth * 3 / 8, | 273 GetColorAt(target_canvas(), kWidth * 1 / 8 - 1, kHeight * 1 / 6 - 1)); |
278 kHeight * 1 / 6 - 1)); | 274 EXPECT_EQ(SK_ColorRED, |
279 EXPECT_EQ(SK_ColorGREEN, GetColorAt(target_canvas(), kWidth * 1 / 8 - 1, | 275 GetColorAt(target_canvas(), kWidth * 3 / 8, kHeight * 1 / 6 - 1)); |
280 kHeight * 3 / 6)); | 276 EXPECT_EQ(SK_ColorGREEN, |
281 EXPECT_EQ(SK_ColorBLUE, GetColorAt(target_canvas(), kWidth * 3 / 8, | 277 GetColorAt(target_canvas(), kWidth * 1 / 8 - 1, kHeight * 3 / 6)); |
282 kHeight * 3 / 6)); | 278 EXPECT_EQ(SK_ColorBLUE, |
| 279 GetColorAt(target_canvas(), kWidth * 3 / 8, kHeight * 3 / 6)); |
283 } | 280 } |
284 | 281 |
285 TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) { | 282 TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) { |
286 SkCanvas canvas(AllocBitmap(kWidth, kHeight)); | 283 SkCanvas canvas(AllocBitmap(kWidth, kHeight)); |
287 const gfx::Rect crop_rect = cropped_frame()->visible_rect(); | 284 const gfx::Rect crop_rect = cropped_frame()->visible_rect(); |
288 | 285 |
289 // Force painting to a non-zero position on the destination bitmap, to check | 286 // Force painting to a non-zero position on the destination bitmap, to check |
290 // if the coordinates are calculated properly. | 287 // if the coordinates are calculated properly. |
291 const int offset_x = 10; | 288 const int offset_x = 10; |
292 const int offset_y = 15; | 289 const int offset_y = 15; |
(...skipping 11 matching lines...) Expand all Loading... |
304 EXPECT_EQ(SK_ColorRED, | 301 EXPECT_EQ(SK_ColorRED, |
305 GetColorAt(&canvas, offset_x + crop_rect.width() - 1, offset_y)); | 302 GetColorAt(&canvas, offset_x + crop_rect.width() - 1, offset_y)); |
306 EXPECT_EQ(SK_ColorGREEN, | 303 EXPECT_EQ(SK_ColorGREEN, |
307 GetColorAt(&canvas, offset_x, offset_y + crop_rect.height() - 1)); | 304 GetColorAt(&canvas, offset_x, offset_y + crop_rect.height() - 1)); |
308 EXPECT_EQ(SK_ColorBLUE, | 305 EXPECT_EQ(SK_ColorBLUE, |
309 GetColorAt(&canvas, | 306 GetColorAt(&canvas, |
310 offset_x + crop_rect.width() - 1, | 307 offset_x + crop_rect.width() - 1, |
311 offset_y + crop_rect.height() - 1)); | 308 offset_y + crop_rect.height() - 1)); |
312 } | 309 } |
313 | 310 |
314 } // namespace media | 311 } // namespace cc |
OLD | NEW |