Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / filters / skcanvas_video_renderer_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "media/base/video_frame.h"
6 #include "media/base/video_util.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "third_party/skia/include/core/SkCanvas.h"
9 #include "media/filters/skcanvas_video_renderer.h"
10
11 using media::VideoFrame;
12
13 namespace media {
14
15 static const int kWidth = 320;
16 static const int kHeight = 240;
17 static const gfx::Rect kNaturalRect(0, 0, kWidth, kHeight);
18
19 // Helper for filling a |canvas| with a solid |color|.
20 void FillCanvas(SkCanvas* canvas, SkColor color) {
21   canvas->clear(color);
22 }
23
24 // Helper for returning the color of a solid |canvas|.
25 SkColor GetColorAt(SkCanvas* canvas, int x, int y) {
26   SkBitmap bitmap;
27   if (!bitmap.tryAllocN32Pixels(1, 1))
28     return 0;
29   if (!canvas->readPixels(&bitmap, x, y))
30     return 0;
31   return bitmap.getColor(0, 0);
32 }
33
34 SkColor GetColor(SkCanvas* canvas) {
35   return GetColorAt(canvas, 0, 0);
36 }
37
38 class SkCanvasVideoRendererTest : public testing::Test {
39  public:
40   enum Color {
41     kNone,
42     kRed,
43     kGreen,
44     kBlue,
45   };
46
47   SkCanvasVideoRendererTest();
48   virtual ~SkCanvasVideoRendererTest();
49
50   // Paints to |canvas| using |renderer_| without any frame data.
51   void PaintWithoutFrame(SkCanvas* canvas);
52
53   // Paints the |video_frame| to the |canvas| using |renderer_|, setting the
54   // color of |video_frame| to |color| first.
55   void Paint(const scoped_refptr<VideoFrame>& video_frame,
56              SkCanvas* canvas,
57              Color color);
58   void PaintRotated(const scoped_refptr<VideoFrame>& video_frame,
59                     SkCanvas* canvas,
60                     Color color,
61                     SkXfermode::Mode mode,
62                     VideoRotation video_rotation);
63
64   void Copy(const scoped_refptr<VideoFrame>& video_frame, SkCanvas* canvas);
65
66   // Getters for various frame sizes.
67   scoped_refptr<VideoFrame> natural_frame() { return natural_frame_; }
68   scoped_refptr<VideoFrame> larger_frame() { return larger_frame_; }
69   scoped_refptr<VideoFrame> smaller_frame() { return smaller_frame_; }
70   scoped_refptr<VideoFrame> cropped_frame() { return cropped_frame_; }
71
72   // Standard canvas.
73   SkCanvas* target_canvas() { return &target_canvas_; }
74
75  private:
76   SkCanvasVideoRenderer renderer_;
77
78   scoped_refptr<VideoFrame> natural_frame_;
79   scoped_refptr<VideoFrame> larger_frame_;
80   scoped_refptr<VideoFrame> smaller_frame_;
81   scoped_refptr<VideoFrame> cropped_frame_;
82
83   SkCanvas target_canvas_;
84
85   DISALLOW_COPY_AND_ASSIGN(SkCanvasVideoRendererTest);
86 };
87
88 static SkBitmap AllocBitmap(int width, int height) {
89   SkBitmap bitmap;
90   bitmap.allocPixels(SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType));
91   bitmap.eraseColor(0);
92   return bitmap;
93 }
94
95 SkCanvasVideoRendererTest::SkCanvasVideoRendererTest()
96     : natural_frame_(VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight))),
97       larger_frame_(VideoFrame::CreateBlackFrame(
98           gfx::Size(kWidth * 2, kHeight * 2))),
99       smaller_frame_(VideoFrame::CreateBlackFrame(
100           gfx::Size(kWidth / 2, kHeight / 2))),
101       cropped_frame_(VideoFrame::CreateFrame(
102           VideoFrame::YV12,
103           gfx::Size(16, 16),
104           gfx::Rect(6, 6, 8, 6),
105           gfx::Size(8, 6),
106           base::TimeDelta::FromMilliseconds(4))),
107       target_canvas_(AllocBitmap(kWidth, kHeight)) {
108   // Give each frame a unique timestamp.
109   natural_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(1));
110   larger_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(2));
111   smaller_frame_->set_timestamp(base::TimeDelta::FromMilliseconds(3));
112
113   // Make sure the cropped video frame's aspect ratio matches the output device.
114   // Update cropped_frame_'s crop dimensions if this is not the case.
115   EXPECT_EQ(cropped_frame()->visible_rect().width() * kHeight,
116             cropped_frame()->visible_rect().height() * kWidth);
117
118   // Fill in the cropped frame's entire data with colors:
119   //
120   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
121   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
122   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
123   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
124   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
125   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
126   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
127   //   Bl Bl Bl Bl Bl Bl Bl Bl R  R  R  R  R  R  R  R
128   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
129   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
130   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
131   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
132   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
133   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
134   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
135   //   G  G  G  G  G  G  G  G  B  B  B  B  B  B  B  B
136   //
137   // The visible crop of the frame (as set by its visible_rect_) has contents:
138   //
139   //   Bl Bl R  R  R  R  R  R
140   //   Bl Bl R  R  R  R  R  R
141   //   G  G  B  B  B  B  B  B
142   //   G  G  B  B  B  B  B  B
143   //   G  G  B  B  B  B  B  B
144   //   G  G  B  B  B  B  B  B
145   //
146   // Each color region in the cropped frame is on a 2x2 block granularity, to
147   // avoid sharing UV samples between regions.
148
149   static const uint8 cropped_y_plane[] = {
150       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,
152       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
153       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
154       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
155       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
156       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
157       0,   0,   0,   0,   0,   0,   0,   0, 76, 76, 76, 76, 76, 76, 76, 76,
158     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,
160     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
161     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
162     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
163     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
164     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
165     149, 149, 149, 149, 149, 149, 149, 149, 29, 29, 29, 29, 29, 29, 29, 29,
166   };
167
168   static const uint8 cropped_u_plane[] = {
169     128, 128, 128, 128,  84,  84,  84,  84,
170     128, 128, 128, 128,  84,  84,  84,  84,
171     128, 128, 128, 128,  84,  84,  84,  84,
172     128, 128, 128, 128,  84,  84,  84,  84,
173      43,  43,  43,  43, 255, 255, 255, 255,
174      43,  43,  43,  43, 255, 255, 255, 255,
175      43,  43,  43,  43, 255, 255, 255, 255,
176      43,  43,  43,  43, 255, 255, 255, 255,
177   };
178   static const uint8 cropped_v_plane[] = {
179     128, 128, 128, 128, 255, 255, 255, 255,
180     128, 128, 128, 128, 255, 255, 255, 255,
181     128, 128, 128, 128, 255, 255, 255, 255,
182     128, 128, 128, 128, 255, 255, 255, 255,
183      21,  21,  21,  21, 107, 107, 107, 107,
184      21,  21,  21,  21, 107, 107, 107, 107,
185      21,  21,  21,  21, 107, 107, 107, 107,
186      21,  21,  21,  21, 107, 107, 107, 107,
187   };
188
189   media::CopyYPlane(cropped_y_plane, 16, 16, cropped_frame().get());
190   media::CopyUPlane(cropped_u_plane, 8, 8, cropped_frame().get());
191   media::CopyVPlane(cropped_v_plane, 8, 8, cropped_frame().get());
192 }
193
194 SkCanvasVideoRendererTest::~SkCanvasVideoRendererTest() {}
195
196 void SkCanvasVideoRendererTest::PaintWithoutFrame(SkCanvas* canvas) {
197   renderer_.Paint(NULL,
198                   canvas,
199                   kNaturalRect,
200                   0xFF,
201                   SkXfermode::kSrcOver_Mode,
202                   VIDEO_ROTATION_0);
203 }
204
205 void SkCanvasVideoRendererTest::Paint(
206     const scoped_refptr<VideoFrame>& video_frame,
207     SkCanvas* canvas,
208     Color color) {
209   PaintRotated(
210       video_frame, canvas, color, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_0);
211 }
212
213 void SkCanvasVideoRendererTest::PaintRotated(
214     const scoped_refptr<VideoFrame>& video_frame,
215     SkCanvas* canvas,
216     Color color,
217     SkXfermode::Mode mode,
218     VideoRotation video_rotation) {
219   switch (color) {
220     case kNone:
221       break;
222     case kRed:
223       media::FillYUV(video_frame.get(), 76, 84, 255);
224       break;
225     case kGreen:
226       media::FillYUV(video_frame.get(), 149, 43, 21);
227       break;
228     case kBlue:
229       media::FillYUV(video_frame.get(), 29, 255, 107);
230       break;
231   }
232   renderer_.Paint(
233       video_frame, canvas, kNaturalRect, 0xFF, mode, video_rotation);
234 }
235
236 void SkCanvasVideoRendererTest::Copy(
237     const scoped_refptr<VideoFrame>& video_frame,
238     SkCanvas* canvas) {
239   renderer_.Copy(video_frame, canvas);
240 }
241
242 TEST_F(SkCanvasVideoRendererTest, NoFrame) {
243   // Test that black gets painted over canvas.
244   FillCanvas(target_canvas(), SK_ColorRED);
245   PaintWithoutFrame(target_canvas());
246   EXPECT_EQ(SK_ColorBLACK, GetColor(target_canvas()));
247 }
248
249 TEST_F(SkCanvasVideoRendererTest, TransparentFrame) {
250   FillCanvas(target_canvas(), SK_ColorRED);
251   PaintRotated(
252       VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
253       target_canvas(),
254       kNone,
255       SkXfermode::kSrcOver_Mode,
256       VIDEO_ROTATION_0);
257   EXPECT_EQ(static_cast<SkColor>(SK_ColorRED), GetColor(target_canvas()));
258 }
259
260 TEST_F(SkCanvasVideoRendererTest, TransparentFrameSrcMode) {
261   FillCanvas(target_canvas(), SK_ColorRED);
262   // SRC mode completely overwrites the buffer.
263   PaintRotated(
264       VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
265       target_canvas(),
266       kNone,
267       SkXfermode::kSrc_Mode,
268       VIDEO_ROTATION_0);
269   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
270             GetColor(target_canvas()));
271 }
272
273 TEST_F(SkCanvasVideoRendererTest, CopyTransparentFrame) {
274   FillCanvas(target_canvas(), SK_ColorRED);
275   Copy(VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
276        target_canvas());
277   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
278             GetColor(target_canvas()));
279 }
280
281 TEST_F(SkCanvasVideoRendererTest, Natural) {
282   Paint(natural_frame(), target_canvas(), kRed);
283   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
284 }
285
286 TEST_F(SkCanvasVideoRendererTest, Larger) {
287   Paint(natural_frame(), target_canvas(), kRed);
288   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
289
290   Paint(larger_frame(), target_canvas(), kBlue);
291   EXPECT_EQ(SK_ColorBLUE, GetColor(target_canvas()));
292 }
293
294 TEST_F(SkCanvasVideoRendererTest, Smaller) {
295   Paint(natural_frame(), target_canvas(), kRed);
296   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
297
298   Paint(smaller_frame(), target_canvas(), kBlue);
299   EXPECT_EQ(SK_ColorBLUE, GetColor(target_canvas()));
300 }
301
302 TEST_F(SkCanvasVideoRendererTest, NoTimestamp) {
303   VideoFrame* video_frame = natural_frame().get();
304   video_frame->set_timestamp(media::kNoTimestamp());
305   Paint(video_frame, target_canvas(), kRed);
306   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
307 }
308
309 TEST_F(SkCanvasVideoRendererTest, SameVideoFrame) {
310   Paint(natural_frame(), target_canvas(), kRed);
311   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
312
313   // Slow paints can get cached, expect the old color value.
314   Paint(natural_frame(), target_canvas(), kBlue);
315   EXPECT_EQ(SK_ColorRED, GetColor(target_canvas()));
316 }
317
318 TEST_F(SkCanvasVideoRendererTest, CroppedFrame) {
319   Paint(cropped_frame(), target_canvas(), kNone);
320   // Check the corners.
321   EXPECT_EQ(SK_ColorBLACK, GetColorAt(target_canvas(), 0, 0));
322   EXPECT_EQ(SK_ColorRED,   GetColorAt(target_canvas(), kWidth - 1, 0));
323   EXPECT_EQ(SK_ColorGREEN, GetColorAt(target_canvas(), 0, kHeight - 1));
324   EXPECT_EQ(SK_ColorBLUE,  GetColorAt(target_canvas(), kWidth - 1,
325                                                        kHeight - 1));
326   // Check the interior along the border between color regions.  Note that we're
327   // bilinearly upscaling, so we'll need to take care to pick sample points that
328   // are just outside the "zone of resampling".
329   EXPECT_EQ(SK_ColorBLACK, GetColorAt(target_canvas(), kWidth  * 1 / 8 - 1,
330                                                        kHeight * 1 / 6 - 1));
331   EXPECT_EQ(SK_ColorRED,   GetColorAt(target_canvas(), kWidth  * 3 / 8,
332                                                        kHeight * 1 / 6 - 1));
333   EXPECT_EQ(SK_ColorGREEN, GetColorAt(target_canvas(), kWidth  * 1 / 8 - 1,
334                                                        kHeight * 3 / 6));
335   EXPECT_EQ(SK_ColorBLUE,  GetColorAt(target_canvas(), kWidth  * 3 / 8,
336                                                        kHeight * 3 / 6));
337 }
338
339 TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) {
340   SkCanvas canvas(AllocBitmap(kWidth, kHeight));
341   const gfx::Rect crop_rect = cropped_frame()->visible_rect();
342
343   // Force painting to a non-zero position on the destination bitmap, to check
344   // if the coordinates are calculated properly.
345   const int offset_x = 10;
346   const int offset_y = 15;
347   canvas.translate(offset_x, offset_y);
348
349   // Create a destination canvas with dimensions and scale which would not
350   // cause scaling.
351   canvas.scale(static_cast<SkScalar>(crop_rect.width()) / kWidth,
352                static_cast<SkScalar>(crop_rect.height()) / kHeight);
353
354   Paint(cropped_frame(), &canvas, kNone);
355
356   // Check the corners.
357   EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, offset_x, offset_y));
358   EXPECT_EQ(SK_ColorRED,
359             GetColorAt(&canvas, offset_x + crop_rect.width() - 1, offset_y));
360   EXPECT_EQ(SK_ColorGREEN,
361             GetColorAt(&canvas, offset_x, offset_y + crop_rect.height() - 1));
362   EXPECT_EQ(SK_ColorBLUE,
363             GetColorAt(&canvas,
364                        offset_x + crop_rect.width() - 1,
365                        offset_y + crop_rect.height() - 1));
366 }
367
368 TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) {
369   SkCanvas canvas(AllocBitmap(kWidth, kHeight));
370   const gfx::Rect crop_rect = cropped_frame()->visible_rect();
371   PaintRotated(cropped_frame(),
372                &canvas,
373                kNone,
374                SkXfermode::kSrcOver_Mode,
375                VIDEO_ROTATION_90);
376   // Check the corners.
377   EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, 0, 0));
378   EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth - 1, 0));
379   EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
380   EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, 0, kHeight - 1));
381 }
382
383 TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) {
384   SkCanvas canvas(AllocBitmap(kWidth, kHeight));
385   const gfx::Rect crop_rect = cropped_frame()->visible_rect();
386   PaintRotated(cropped_frame(),
387                &canvas,
388                kNone,
389                SkXfermode::kSrcOver_Mode,
390                VIDEO_ROTATION_180);
391   // Check the corners.
392   EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, 0, 0));
393   EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth - 1, 0));
394   EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
395   EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, 0, kHeight - 1));
396 }
397
398 TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) {
399   SkCanvas canvas(AllocBitmap(kWidth, kHeight));
400   const gfx::Rect crop_rect = cropped_frame()->visible_rect();
401   PaintRotated(cropped_frame(),
402                &canvas,
403                kNone,
404                SkXfermode::kSrcOver_Mode,
405                VIDEO_ROTATION_270);
406   // Check the corners.
407   EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, 0, 0));
408   EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, kWidth - 1, 0));
409   EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
410   EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, 0, kHeight - 1));
411 }
412
413 }  // namespace media