Commit bc6e9d5e authored by dongseong.hwang's avatar dongseong.hwang Committed by Commit bot

Optimize to copy from rotated video to canvas.

Perform this rotation on the canvas, rather than allocating a new bitmap and
copying.

BUG=91208, 47554

Review URL: https://codereview.chromium.org/619343003

Cr-Commit-Position: refs/heads/master@{#299094}
parent cce127ba
...@@ -327,42 +327,57 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, ...@@ -327,42 +327,57 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) { if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) {
NOTREACHED(); NOTREACHED();
} }
DCHECK(video_frame->visible_rect().width() == last_frame_.width() &&
video_frame->visible_rect().height() == last_frame_.height());
// TODO(rileya): Perform this rotation on the canvas, rather than allocating last_frame_timestamp_ = video_frame->timestamp();
// a new bitmap and copying. } else if (generator_) {
generator_->set_frame(video_frame);
}
paint.setXfermodeMode(mode);
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
bool need_transform =
video_rotation != VIDEO_ROTATION_0 ||
dest_rect.size() != video_frame->visible_rect().size() ||
!dest_rect.origin().IsOrigin();
if (need_transform) {
canvas->save();
canvas->translate(
SkFloatToScalar(dest_rect.x() + (dest_rect.width() * 0.5f)),
SkFloatToScalar(dest_rect.y() + (dest_rect.height() * 0.5f)));
SkScalar angle = SkFloatToScalar(0.0f);
switch (video_rotation) { switch (video_rotation) {
case VIDEO_ROTATION_0: case VIDEO_ROTATION_0:
break; break;
case VIDEO_ROTATION_90: case VIDEO_ROTATION_90:
last_frame_ = SkBitmapOperations::Rotate( angle = SkFloatToScalar(90.0f);
last_frame_, SkBitmapOperations::ROTATION_90_CW);
break; break;
case VIDEO_ROTATION_180: case VIDEO_ROTATION_180:
last_frame_ = SkBitmapOperations::Rotate( angle = SkFloatToScalar(180.0f);
last_frame_, SkBitmapOperations::ROTATION_180_CW);
break; break;
case VIDEO_ROTATION_270: case VIDEO_ROTATION_270:
last_frame_ = SkBitmapOperations::Rotate( angle = SkFloatToScalar(270.0f);
last_frame_, SkBitmapOperations::ROTATION_270_CW);
break; break;
} }
canvas->rotate(angle);
// We copied the frame into a new bitmap and threw out the old one, so we gfx::SizeF rotated_dest_size = dest_rect.size();
// no longer have a |generator_| around. This should be removed when the if (video_rotation == VIDEO_ROTATION_90 ||
// above TODO is addressed. video_rotation == VIDEO_ROTATION_270) {
if (video_rotation != VIDEO_ROTATION_0) rotated_dest_size =
generator_ = NULL; gfx::SizeF(rotated_dest_size.height(), rotated_dest_size.width());
last_frame_timestamp_ = video_frame->timestamp();
} else if (generator_) {
generator_->set_frame(video_frame);
} }
canvas->scale(
paint.setXfermodeMode(mode); SkFloatToScalar(rotated_dest_size.width() / last_frame_.width()),
SkFloatToScalar(rotated_dest_size.height() / last_frame_.height()));
// Paint using |last_frame_|. canvas->translate(-SkFloatToScalar(last_frame_.width() * 0.5f),
paint.setFilterLevel(SkPaint::kLow_FilterLevel); -SkFloatToScalar(last_frame_.height() * 0.5f));
canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); }
canvas->drawBitmap(last_frame_, 0, 0, &paint);
if (need_transform)
canvas->restore();
canvas->flush(); canvas->flush();
} }
......
...@@ -27,8 +27,8 @@ class MEDIA_EXPORT SkCanvasVideoRenderer { ...@@ -27,8 +27,8 @@ class MEDIA_EXPORT SkCanvasVideoRenderer {
SkCanvasVideoRenderer(); SkCanvasVideoRenderer();
~SkCanvasVideoRenderer(); ~SkCanvasVideoRenderer();
// Paints |video_frame| on |canvas|, scaling the result to fit dimensions // Paints |video_frame| on |canvas|, scaling and rotating the result to fit
// specified by |dest_rect|. // dimensions specified by |dest_rect|.
// //
// Black will be painted on |canvas| if |video_frame| is null. // Black will be painted on |canvas| if |video_frame| is null.
void Paint(const scoped_refptr<VideoFrame>& video_frame, void Paint(const scoped_refptr<VideoFrame>& video_frame,
......
...@@ -57,6 +57,7 @@ class SkCanvasVideoRendererTest : public testing::Test { ...@@ -57,6 +57,7 @@ class SkCanvasVideoRendererTest : public testing::Test {
Color color); Color color);
void PaintRotated(const scoped_refptr<VideoFrame>& video_frame, void PaintRotated(const scoped_refptr<VideoFrame>& video_frame,
SkCanvas* canvas, SkCanvas* canvas,
const gfx::RectF& dest_rect,
Color color, Color color,
SkXfermode::Mode mode, SkXfermode::Mode mode,
VideoRotation video_rotation); VideoRotation video_rotation);
...@@ -206,13 +207,18 @@ void SkCanvasVideoRendererTest::Paint( ...@@ -206,13 +207,18 @@ void SkCanvasVideoRendererTest::Paint(
const scoped_refptr<VideoFrame>& video_frame, const scoped_refptr<VideoFrame>& video_frame,
SkCanvas* canvas, SkCanvas* canvas,
Color color) { Color color) {
PaintRotated( PaintRotated(video_frame,
video_frame, canvas, color, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_0); canvas,
kNaturalRect,
color,
SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_0);
} }
void SkCanvasVideoRendererTest::PaintRotated( void SkCanvasVideoRendererTest::PaintRotated(
const scoped_refptr<VideoFrame>& video_frame, const scoped_refptr<VideoFrame>& video_frame,
SkCanvas* canvas, SkCanvas* canvas,
const gfx::RectF& dest_rect,
Color color, Color color,
SkXfermode::Mode mode, SkXfermode::Mode mode,
VideoRotation video_rotation) { VideoRotation video_rotation) {
...@@ -229,8 +235,7 @@ void SkCanvasVideoRendererTest::PaintRotated( ...@@ -229,8 +235,7 @@ void SkCanvasVideoRendererTest::PaintRotated(
media::FillYUV(video_frame.get(), 29, 255, 107); media::FillYUV(video_frame.get(), 29, 255, 107);
break; break;
} }
renderer_.Paint( renderer_.Paint(video_frame, canvas, dest_rect, 0xFF, mode, video_rotation);
video_frame, canvas, kNaturalRect, 0xFF, mode, video_rotation);
} }
void SkCanvasVideoRendererTest::Copy( void SkCanvasVideoRendererTest::Copy(
...@@ -251,6 +256,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrame) { ...@@ -251,6 +256,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrame) {
PaintRotated( PaintRotated(
VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(), VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
target_canvas(), target_canvas(),
kNaturalRect,
kNone, kNone,
SkXfermode::kSrcOver_Mode, SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_0); VIDEO_ROTATION_0);
...@@ -263,6 +269,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrameSrcMode) { ...@@ -263,6 +269,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrameSrcMode) {
PaintRotated( PaintRotated(
VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(), VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(),
target_canvas(), target_canvas(),
kNaturalRect,
kNone, kNone,
SkXfermode::kSrc_Mode, SkXfermode::kSrc_Mode,
VIDEO_ROTATION_0); VIDEO_ROTATION_0);
...@@ -367,9 +374,9 @@ TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) { ...@@ -367,9 +374,9 @@ TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) {
TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight)); SkCanvas canvas(AllocBitmap(kWidth, kHeight));
const gfx::Rect crop_rect = cropped_frame()->visible_rect();
PaintRotated(cropped_frame(), PaintRotated(cropped_frame(),
&canvas, &canvas,
kNaturalRect,
kNone, kNone,
SkXfermode::kSrcOver_Mode, SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_90); VIDEO_ROTATION_90);
...@@ -382,9 +389,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) { ...@@ -382,9 +389,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) {
TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight)); SkCanvas canvas(AllocBitmap(kWidth, kHeight));
const gfx::Rect crop_rect = cropped_frame()->visible_rect();
PaintRotated(cropped_frame(), PaintRotated(cropped_frame(),
&canvas, &canvas,
kNaturalRect,
kNone, kNone,
SkXfermode::kSrcOver_Mode, SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_180); VIDEO_ROTATION_180);
...@@ -397,9 +404,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) { ...@@ -397,9 +404,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) {
TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight)); SkCanvas canvas(AllocBitmap(kWidth, kHeight));
const gfx::Rect crop_rect = cropped_frame()->visible_rect();
PaintRotated(cropped_frame(), PaintRotated(cropped_frame(),
&canvas, &canvas,
kNaturalRect,
kNone, kNone,
SkXfermode::kSrcOver_Mode, SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_270); VIDEO_ROTATION_270);
...@@ -410,4 +417,93 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) { ...@@ -410,4 +417,93 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) {
EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, 0, kHeight - 1)); EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, 0, kHeight - 1));
} }
TEST_F(SkCanvasVideoRendererTest, Video_Translate) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight));
FillCanvas(&canvas, SK_ColorMAGENTA);
PaintRotated(cropped_frame(),
&canvas,
gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
kNone,
SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_0);
// Check the corners of quadrant 2 and 4.
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, 0));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, (kWidth / 2) - 1, 0));
EXPECT_EQ(SK_ColorMAGENTA,
GetColorAt(&canvas, (kWidth / 2) - 1, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth / 2, kHeight / 2));
EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, kWidth - 1, kHeight / 2));
EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth / 2, kHeight - 1));
}
TEST_F(SkCanvasVideoRendererTest, Video_Translate_Rotation_90) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight));
FillCanvas(&canvas, SK_ColorMAGENTA);
const gfx::Rect crop_rect = cropped_frame()->visible_rect();
PaintRotated(cropped_frame(),
&canvas,
gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
kNone,
SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_90);
// Check the corners of quadrant 2 and 4.
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, 0));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, (kWidth / 2) - 1, 0));
EXPECT_EQ(SK_ColorMAGENTA,
GetColorAt(&canvas, (kWidth / 2) - 1, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth / 2, kHeight / 2));
EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth - 1, kHeight / 2));
EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, kWidth / 2, kHeight - 1));
}
TEST_F(SkCanvasVideoRendererTest, Video_Translate_Rotation_180) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight));
FillCanvas(&canvas, SK_ColorMAGENTA);
PaintRotated(cropped_frame(),
&canvas,
gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
kNone,
SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_180);
// Check the corners of quadrant 2 and 4.
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, 0));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, (kWidth / 2) - 1, 0));
EXPECT_EQ(SK_ColorMAGENTA,
GetColorAt(&canvas, (kWidth / 2) - 1, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, kWidth / 2, kHeight / 2));
EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth - 1, kHeight / 2));
EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, kWidth / 2, kHeight - 1));
}
TEST_F(SkCanvasVideoRendererTest, Video_Translate_Rotation_270) {
SkCanvas canvas(AllocBitmap(kWidth, kHeight));
FillCanvas(&canvas, SK_ColorMAGENTA);
PaintRotated(cropped_frame(),
&canvas,
gfx::Rect(kWidth / 2, kHeight / 2, kWidth / 2, kHeight / 2),
kNone,
SkXfermode::kSrcOver_Mode,
VIDEO_ROTATION_270);
// Check the corners of quadrant 2 and 4.
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, 0));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, (kWidth / 2) - 1, 0));
EXPECT_EQ(SK_ColorMAGENTA,
GetColorAt(&canvas, (kWidth / 2) - 1, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorMAGENTA, GetColorAt(&canvas, 0, (kHeight / 2) - 1));
EXPECT_EQ(SK_ColorRED, GetColorAt(&canvas, kWidth / 2, kHeight / 2));
EXPECT_EQ(SK_ColorBLUE, GetColorAt(&canvas, kWidth - 1, kHeight / 2));
EXPECT_EQ(SK_ColorGREEN, GetColorAt(&canvas, kWidth - 1, kHeight - 1));
EXPECT_EQ(SK_ColorBLACK, GetColorAt(&canvas, kWidth / 2, kHeight - 1));
}
} // namespace media } // namespace media
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment