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..ead8d066516ac0065759807b46755c9b146bee8a 100644 |
--- a/media/filters/skcanvas_video_renderer.cc |
+++ b/media/filters/skcanvas_video_renderer.cc |
@@ -9,8 +9,12 @@ |
#include "media/base/yuv_convert.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" |
+#include "skia/ext/refptr.h" |
+ |
// Skia internal format depends on a platform. On Android it is ABGR, on others |
// it is ARGB. |
#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ |
@@ -209,6 +213,61 @@ void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
return; |
} |
+ // If we have an accelerated canvas, then we can use Ganesh's YUV conversion |
+ // filter, this is far faster than carrying this out on the CPU. |
+ if (GrContext* gr = canvas->getGrContext()) { |
+ DCHECK(IsYUVOrNative(video_frame->format())) |
+ << video_frame->format(); |
+ if (IsYUV(video_frame->format())) { |
+ DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), |
+ video_frame->stride(media::VideoFrame::kVPlane)); |
+ } |
+ |
+ DCHECK(video_frame->format() == VideoFrame::YV12); |
+ |
+ |
+ // Wrap our planes in SkBitmaps. |
+ SkBitmap bmps[3]; |
+ bmps[0].installPixels( |
+ SkImageInfo::MakeA8(video_frame->coded_size().width(), |
+ video_frame->coded_size().height()), |
+ video_frame->data(VideoFrame::kYPlane), |
+ video_frame->row_bytes(VideoFrame::kYPlane)); |
+ bmps[1].installPixels( |
+ SkImageInfo::MakeA8(video_frame->coded_size().width() / 2, |
+ video_frame->coded_size().height() / 2), |
+ video_frame->data(VideoFrame::kUPlane), |
+ video_frame->row_bytes(VideoFrame::kUPlane)); |
+ bmps[2].installPixels( |
+ SkImageInfo::MakeA8(video_frame->coded_size().width() / 2, |
+ video_frame->coded_size().height() / 2), |
+ video_frame->data(VideoFrame::kVPlane), |
+ video_frame->row_bytes(VideoFrame::kVPlane)); |
+ |
+ for (int i = 0; i < 3; ++i) |
+ bmps[i].setIsVolatile(true); |
+ |
+ GrTexture* planes[3]; |
+ |
+ planes[0] = GrLockAndRefCachedBitmapTexture(gr, bmps[0], NULL); |
+ planes[1] = GrLockAndRefCachedBitmapTexture(gr, bmps[1], NULL); |
+ planes[2] = GrLockAndRefCachedBitmapTexture(gr, bmps[2], NULL); |
+ |
+ skia::RefPtr<GrEffect> effect = skia::AdoptRef<GrEffect>( |
+ GrYUVtoRGBEffect::Create(planes[0], planes[1], planes[2])); |
+ |
+ if (effect) { |
+ GrPaint gp; |
+ gp.addColorEffect(effect.get()); |
+ gr->drawPaint(gp); |
+ } |
+ |
+ GrUnlockAndUnrefCachedBitmapTexture(planes[0]); |
+ GrUnlockAndUnrefCachedBitmapTexture(planes[1]); |
+ GrUnlockAndUnrefCachedBitmapTexture(planes[2]); |
+ return; |
+ } |
+ |
// Check if we should convert and update |last_frame_|. |
if (last_frame_.isNull() || |
video_frame->timestamp() != last_frame_timestamp_) { |