summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordongseong.hwang <dongseong.hwang@intel.com>2014-10-10 04:53:54 -0700
committerCommit bot <commit-bot@chromium.org>2014-10-10 11:54:12 +0000
commitbc6e9d5eeef32478690947cb1fdc2e48439acb3d (patch)
treebada80aa5786995433e0272dd6951aa7b78ce254 /media
parentcce127badb2d4150e8458921e393721c80b23981 (diff)
downloadchromium_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.cc61
-rw-r--r--media/filters/skcanvas_video_renderer.h4
-rw-r--r--media/filters/skcanvas_video_renderer_unittest.cc110
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