Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1221)

Unified Diff: media/filters/skcanvas_video_renderer.cc

Issue 512733003: Do YUV conversion on the GPU when copying video frames into a GPU-accelerated canvas. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/skcanvas_video_renderer.cc
diff --git a/media/filters/skcanvas_video_renderer.cc b/media/filters/skcanvas_video_renderer.cc
index 003c1951a9b4010e93e612a347d645b22aa3f66a..3cdf25ac61b7a8d2248abfd49d9984187af627dd 100644
--- a/media/filters/skcanvas_video_renderer.cc
+++ b/media/filters/skcanvas_video_renderer.cc
@@ -7,8 +7,11 @@
#include "base/logging.h"
#include "media/base/video_frame.h"
#include "media/base/yuv_convert.h"
+#include "skia/ext/refptr.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/gpu/SkGr.h"
+#include "third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.h"
#include "ui/gfx/skbitmap_operations.h"
// Skia internal format depends on a platform. On Android it is ABGR, on others
@@ -181,7 +184,8 @@ static void ConvertVideoFrameToBitmap(
}
SkCanvasVideoRenderer::SkCanvasVideoRenderer()
- : last_frame_timestamp_(media::kNoTimestamp()) {
+ : last_frame_timestamp_(media::kNoTimestamp()),
+ yuv_planes_timestamp_(media::kNoTimestamp()) {
}
SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
@@ -209,6 +213,15 @@ void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame,
return;
}
+ // If we have a hardware accelerated canvas, we can try to do YUV conversion
+ // directly from our frame to the output canvas.
+ if (canvas->getGrContext() &&
+ HardwarePaint(
+ video_frame, canvas->getGrContext(), dest, mode, video_rotation)) {
+ // If HardwarePaint() succeeded, then we're all done!
+ return;
+ }
+
// Check if we should convert and update |last_frame_|.
if (last_frame_.isNull() ||
video_frame->timestamp() != last_frame_timestamp_) {
@@ -251,4 +264,92 @@ void SkCanvasVideoRenderer::Copy(media::VideoFrame* video_frame,
media::VIDEO_ROTATION_0);
}
+bool SkCanvasVideoRenderer::HardwarePaint(media::VideoFrame* video_frame,
+ GrContext* gr,
+ const SkRect& dest_rect,
+ SkXfermode::Mode mode,
+ VideoRotation video_rotation) {
+ if (!IsYUV(video_frame->format()) ||
+ video_frame->format() == VideoFrame::YV12A)
+ return false;
+
+ DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
+ video_frame->stride(media::VideoFrame::kVPlane));
+
+ // Wrap our planes in SkBitmaps.
+ if (video_frame->timestamp() != yuv_planes_timestamp_) {
+ yuv_planes_[0].installPixels(
+ SkImageInfo::MakeA8(video_frame->coded_size().width(),
+ video_frame->coded_size().height()),
+ video_frame->data(VideoFrame::kYPlane),
+ video_frame->stride(VideoFrame::kYPlane));
+ yuv_planes_[1].installPixels(
+ SkImageInfo::MakeA8(video_frame->coded_size().width() / 2,
+ video_frame->coded_size().height() / 2),
+ video_frame->data(VideoFrame::kUPlane),
+ video_frame->stride(VideoFrame::kUPlane));
+ yuv_planes_[2].installPixels(
+ SkImageInfo::MakeA8(video_frame->coded_size().width() / 2,
+ video_frame->coded_size().height() / 2),
+ video_frame->data(VideoFrame::kVPlane),
+ video_frame->stride(VideoFrame::kVPlane));
+ }
+
+ // Populate GrTextures from the bitmaps. We let Ganesh handle caching here.
+ GrTexture* planes[3];
+ planes[0] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[0], NULL);
+ planes[1] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[1], NULL);
+ planes[2] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[2], NULL);
+
+ skia::RefPtr<GrEffect> effect = skia::AdoptRef<GrEffect>(
+ GrYUVtoRGBEffect::Create(planes[0], planes[1], planes[2]));
+
+ if (!effect)
+ return false;
+
+ SkXfermode::Coeff src, dest;
+ if (!SkXfermode::ModeAsCoeff(mode, &src, &dest))
+ return false;
+
+ GrPaint paint;
+ paint.addColorEffect(effect.get());
+ paint.setBlendFunc(sk_blend_to_grblend(src), sk_blend_to_grblend(dest));
+
+ GrContext::AutoMatrix auto_matrix;
+ auto_matrix.setIdentity(gr, &paint);
+ SkMatrix rotation;
+
+ switch (video_rotation) {
+ case VIDEO_ROTATION_0:
+ rotation.reset();
+ break;
+ case VIDEO_ROTATION_90:
+ rotation.setRotate(90);
+ rotation.postTranslate(video_frame->coded_size().height(), 0);
+ break;
+ case VIDEO_ROTATION_180:
+ rotation.setRotate(180);
+ rotation.postTranslate(video_frame->coded_size().width(),
+ video_frame->coded_size().height());
+ break;
+ case VIDEO_ROTATION_270:
+ rotation.setRotate(270);
+ rotation.postTranslate(0, video_frame->coded_size().width());
+ break;
+ }
+
+ gr->concatMatrix(rotation);
+ gr->drawRect(paint, dest_rect);
+
+ GrUnlockAndUnrefCachedBitmapTexture(planes[0]);
+ GrUnlockAndUnrefCachedBitmapTexture(planes[1]);
+ GrUnlockAndUnrefCachedBitmapTexture(planes[2]);
+
+ gr->flush();
+
+ yuv_planes_timestamp_ = video_frame->timestamp();
+
+ return true;
+}
+
} // namespace media
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698