diff options
author | dongseong.hwang <dongseong.hwang@intel.com> | 2014-10-10 04:53:54 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-10 11:54:12 +0000 |
commit | bc6e9d5eeef32478690947cb1fdc2e48439acb3d (patch) | |
tree | bada80aa5786995433e0272dd6951aa7b78ce254 /media | |
parent | cce127badb2d4150e8458921e393721c80b23981 (diff) | |
download | chromium_src-bc6e9d5eeef32478690947cb1fdc2e48439acb3d.zip chromium_src-bc6e9d5eeef32478690947cb1fdc2e48439acb3d.tar.gz chromium_src-bc6e9d5eeef32478690947cb1fdc2e48439acb3d.tar.bz2 |
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}
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/skcanvas_video_renderer.cc | 61 | ||||
-rw-r--r-- | media/filters/skcanvas_video_renderer.h | 4 | ||||
-rw-r--r-- | media/filters/skcanvas_video_renderer_unittest.cc | 110 |
3 files changed, 143 insertions, 32 deletions
diff --git a/media/filters/skcanvas_video_renderer.cc b/media/filters/skcanvas_video_renderer.cc index 4113ccb..6c73a17 100644 --- a/media/filters/skcanvas_video_renderer.cc +++ b/media/filters/skcanvas_video_renderer.cc @@ -327,42 +327,57 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) { 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 - // a new bitmap and copying. + last_frame_timestamp_ = video_frame->timestamp(); + } 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) { case VIDEO_ROTATION_0: break; case VIDEO_ROTATION_90: - last_frame_ = SkBitmapOperations::Rotate( - last_frame_, SkBitmapOperations::ROTATION_90_CW); + angle = SkFloatToScalar(90.0f); break; case VIDEO_ROTATION_180: - last_frame_ = SkBitmapOperations::Rotate( - last_frame_, SkBitmapOperations::ROTATION_180_CW); + angle = SkFloatToScalar(180.0f); break; case VIDEO_ROTATION_270: - last_frame_ = SkBitmapOperations::Rotate( - last_frame_, SkBitmapOperations::ROTATION_270_CW); + angle = SkFloatToScalar(270.0f); break; } + canvas->rotate(angle); - // We copied the frame into a new bitmap and threw out the old one, so we - // no longer have a |generator_| around. This should be removed when the - // above TODO is addressed. - if (video_rotation != VIDEO_ROTATION_0) - generator_ = NULL; - - last_frame_timestamp_ = video_frame->timestamp(); - } else if (generator_) { - generator_->set_frame(video_frame); + gfx::SizeF rotated_dest_size = dest_rect.size(); + if (video_rotation == VIDEO_ROTATION_90 || + video_rotation == VIDEO_ROTATION_270) { + rotated_dest_size = + gfx::SizeF(rotated_dest_size.height(), rotated_dest_size.width()); + } + canvas->scale( + SkFloatToScalar(rotated_dest_size.width() / last_frame_.width()), + SkFloatToScalar(rotated_dest_size.height() / last_frame_.height())); + canvas->translate(-SkFloatToScalar(last_frame_.width() * 0.5f), + -SkFloatToScalar(last_frame_.height() * 0.5f)); } - - paint.setXfermodeMode(mode); - - // Paint using |last_frame_|. - paint.setFilterLevel(SkPaint::kLow_FilterLevel); - canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); + canvas->drawBitmap(last_frame_, 0, 0, &paint); + if (need_transform) + canvas->restore(); canvas->flush(); } diff --git a/media/filters/skcanvas_video_renderer.h b/media/filters/skcanvas_video_renderer.h index a446073..146e7cd 100644 --- a/media/filters/skcanvas_video_renderer.h +++ b/media/filters/skcanvas_video_renderer.h @@ -27,8 +27,8 @@ class MEDIA_EXPORT SkCanvasVideoRenderer { SkCanvasVideoRenderer(); ~SkCanvasVideoRenderer(); - // Paints |video_frame| on |canvas|, scaling the result to fit dimensions - // specified by |dest_rect|. + // Paints |video_frame| on |canvas|, scaling and rotating the result to fit + // dimensions specified by |dest_rect|. // // Black will be painted on |canvas| if |video_frame| is null. void Paint(const scoped_refptr<VideoFrame>& video_frame, diff --git a/media/filters/skcanvas_video_renderer_unittest.cc b/media/filters/skcanvas_video_renderer_unittest.cc index e11c296..4bd2a18 100644 --- a/media/filters/skcanvas_video_renderer_unittest.cc +++ b/media/filters/skcanvas_video_renderer_unittest.cc @@ -57,6 +57,7 @@ class SkCanvasVideoRendererTest : public testing::Test { Color color); void PaintRotated(const scoped_refptr<VideoFrame>& video_frame, SkCanvas* canvas, + const gfx::RectF& dest_rect, Color color, SkXfermode::Mode mode, VideoRotation video_rotation); @@ -206,13 +207,18 @@ void SkCanvasVideoRendererTest::Paint( const scoped_refptr<VideoFrame>& video_frame, SkCanvas* canvas, Color color) { - PaintRotated( - video_frame, canvas, color, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_0); + PaintRotated(video_frame, + canvas, + kNaturalRect, + color, + SkXfermode::kSrcOver_Mode, + VIDEO_ROTATION_0); } void SkCanvasVideoRendererTest::PaintRotated( const scoped_refptr<VideoFrame>& video_frame, SkCanvas* canvas, + const gfx::RectF& dest_rect, Color color, SkXfermode::Mode mode, VideoRotation video_rotation) { @@ -229,8 +235,7 @@ void SkCanvasVideoRendererTest::PaintRotated( media::FillYUV(video_frame.get(), 29, 255, 107); break; } - renderer_.Paint( - video_frame, canvas, kNaturalRect, 0xFF, mode, video_rotation); + renderer_.Paint(video_frame, canvas, dest_rect, 0xFF, mode, video_rotation); } void SkCanvasVideoRendererTest::Copy( @@ -251,6 +256,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrame) { PaintRotated( VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(), target_canvas(), + kNaturalRect, kNone, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_0); @@ -263,6 +269,7 @@ TEST_F(SkCanvasVideoRendererTest, TransparentFrameSrcMode) { PaintRotated( VideoFrame::CreateTransparentFrame(gfx::Size(kWidth, kHeight)).get(), target_canvas(), + kNaturalRect, kNone, SkXfermode::kSrc_Mode, VIDEO_ROTATION_0); @@ -367,9 +374,9 @@ TEST_F(SkCanvasVideoRendererTest, CroppedFrame_NoScaling) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) { SkCanvas canvas(AllocBitmap(kWidth, kHeight)); - const gfx::Rect crop_rect = cropped_frame()->visible_rect(); PaintRotated(cropped_frame(), &canvas, + kNaturalRect, kNone, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_90); @@ -382,9 +389,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_90) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) { SkCanvas canvas(AllocBitmap(kWidth, kHeight)); - const gfx::Rect crop_rect = cropped_frame()->visible_rect(); PaintRotated(cropped_frame(), &canvas, + kNaturalRect, kNone, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_180); @@ -397,9 +404,9 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_180) { TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) { SkCanvas canvas(AllocBitmap(kWidth, kHeight)); - const gfx::Rect crop_rect = cropped_frame()->visible_rect(); PaintRotated(cropped_frame(), &canvas, + kNaturalRect, kNone, SkXfermode::kSrcOver_Mode, VIDEO_ROTATION_270); @@ -410,4 +417,93 @@ TEST_F(SkCanvasVideoRendererTest, Video_Rotation_270) { 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 |