| 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 |