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

Unified Diff: media/blink/skcanvas_video_renderer.cc

Issue 1153623002: media: SkCanvasVideoRenderer support for YUV native videoframes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Set the color format. Created 5 years, 6 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/blink/skcanvas_video_renderer.h ('k') | media/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/blink/skcanvas_video_renderer.cc
diff --git a/media/blink/skcanvas_video_renderer.cc b/media/blink/skcanvas_video_renderer.cc
index 2d3a416b3fd80fa4dc4d69e73ad2fd833e0cb9d2..f8d6e876ad9c88414ed7d9273ffcdf55400dec6c 100644
--- a/media/blink/skcanvas_video_renderer.cc
+++ b/media/blink/skcanvas_video_renderer.cc
@@ -12,9 +12,13 @@
#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/core/SkImage.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/GrPaint.h"
+#include "third_party/skia/include/gpu/GrTexture.h"
#include "third_party/skia/include/gpu/GrTextureProvider.h"
+#include "third_party/skia/include/gpu/SkGr.h"
#include "third_party/skia/include/gpu/SkGrPixelRef.h"
#include "ui/gfx/skbitmap_operations.h"
@@ -84,9 +88,75 @@ bool AllocateSkBitmapTexture(GrContext* gr,
return true;
}
-bool CopyVideoFrameTextureToSkBitmapTexture(VideoFrame* video_frame,
- SkBitmap* bitmap,
- const Context3D& context_3d) {
+class SyncPointClientImpl : public VideoFrame::SyncPointClient {
+ public:
+ explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
+ ~SyncPointClientImpl() override {}
+ uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); }
+ void WaitSyncPoint(uint32 sync_point) override {
+ gl_->WaitSyncPointCHROMIUM(sync_point);
+ }
+
+ private:
+ gpu::gles2::GLES2Interface* gl_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SyncPointClientImpl);
+};
+
+scoped_ptr<SkImage> CreateSkImageFromVideoFrameYUVTextures(
+ VideoFrame* video_frame,
+ const Context3D& context_3d) {
+ // Support only TEXTURE_YUV_420.
+ DCHECK(video_frame->storage_type() == VideoFrame::STORAGE_TEXTURE);
+ DCHECK_EQ(media::VideoFrame::I420, video_frame->format());
+ DCHECK_EQ(3u, media::VideoFrame::NumPlanes(video_frame->format()));
+
+ gpu::gles2::GLES2Interface* gl = context_3d.gl;
+ DCHECK(gl);
+ gfx::Size ya_tex_size = video_frame->coded_size();
+ gfx::Size uv_tex_size((ya_tex_size.width() + 1) / 2,
+ (ya_tex_size.height() + 1) / 2);
+
+ unsigned source_textures[3] = {0};
+ for (size_t i = 0; i < media::VideoFrame::NumPlanes(video_frame->format());
+ ++i) {
+ // Get the texture from the mailbox and wrap it in a GrTexture.
+ const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i);
+ DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
+ mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES ||
+ mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB);
+ gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point);
+ source_textures[i] = gl->CreateAndConsumeTextureCHROMIUM(
+ mailbox_holder.texture_target, mailbox_holder.mailbox.name);
+ }
+ GrBackendObject handles[3] = {
+ source_textures[0], source_textures[1], source_textures[2]};
+
+ SkISize yuvSizes[] = {
+ {ya_tex_size.width(), ya_tex_size.height()},
+ {uv_tex_size.width(), uv_tex_size.height()},
+ {uv_tex_size.width(), uv_tex_size.height()},
+ };
+
+ // TODO(dcastagna): Skia currently doesn't support Rec709 YUV conversion.
+ DCHECK(!CheckColorSpace(video_frame, VideoFrame::COLOR_SPACE_HD_REC709));
+ SkYUVColorSpace color_space = kRec601_SkYUVColorSpace;
+ if (CheckColorSpace(video_frame, VideoFrame::COLOR_SPACE_JPEG))
+ color_space = kJPEG_SkYUVColorSpace;
+
+ SkImage* img = SkImage::NewFromYUVTexturesCopy(context_3d.gr_context,
+ color_space, handles, yuvSizes,
+ kTopLeft_GrSurfaceOrigin);
+ DCHECK(img);
+ gl->DeleteTextures(3, source_textures);
+ SyncPointClientImpl client(gl);
+ video_frame->UpdateReleaseSyncPoint(&client);
+ return make_scoped_ptr(img);
+}
+
+bool CopyVideoFrameSingleTextureToSkBitmap(VideoFrame* video_frame,
+ SkBitmap* bitmap,
+ const Context3D& context_3d) {
// Check if we could reuse existing texture based bitmap.
// Otherwise, release existing texture based bitmap and allocate
// a new one based on video size.
@@ -100,31 +170,17 @@ bool CopyVideoFrameTextureToSkBitmapTexture(VideoFrame* video_frame,
unsigned texture_id =
static_cast<unsigned>((bitmap->getTexture())->getTextureHandle());
- // If CopyVideoFrameTextureToGLTexture() changes the state of the
+ // If CopyVideoFrameSingleTextureToGLTexture() changes the state of the
// |texture_id|, it's needed to invalidate the state cached in skia,
// but currently the state isn't changed.
- SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture(
+
+ SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
context_3d.gl, video_frame, texture_id, GL_RGBA, GL_UNSIGNED_BYTE, true,
false);
bitmap->notifyPixelsChanged();
return true;
}
-class SyncPointClientImpl : public VideoFrame::SyncPointClient {
- public:
- explicit SyncPointClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
- ~SyncPointClientImpl() override {}
- uint32 InsertSyncPoint() override { return gl_->InsertSyncPointCHROMIUM(); }
- void WaitSyncPoint(uint32 sync_point) override {
- gl_->WaitSyncPointCHROMIUM(sync_point);
- }
-
- private:
- gpu::gles2::GLES2Interface* gl_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(SyncPointClientImpl);
-};
-
} // anonymous namespace
// Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
@@ -290,16 +346,23 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
accelerated_last_frame_.reset();
accelerated_generator_ = nullptr;
}
- if (!CopyVideoFrameTextureToSkBitmapTexture(
- video_frame.get(), &accelerated_last_frame_, context_3d)) {
- NOTREACHED();
- return;
- }
- DCHECK(video_frame->visible_rect().width() ==
- accelerated_last_frame_.width() &&
- video_frame->visible_rect().height() ==
- accelerated_last_frame_.height());
+ if (media::VideoFrame::NumPlanes(video_frame->format()) == 1) {
+ accelerated_last_image_.reset();
+ if (!CopyVideoFrameSingleTextureToSkBitmap(
+ video_frame.get(), &accelerated_last_frame_, context_3d)) {
+ NOTREACHED();
+ return;
+ }
+ DCHECK(video_frame->visible_rect().width() ==
+ accelerated_last_frame_.width() &&
+ video_frame->visible_rect().height() ==
+ accelerated_last_frame_.height());
+ } else {
+ accelerated_last_image_ = CreateSkImageFromVideoFrameYUVTextures(
+ video_frame.get(), context_3d);
+ DCHECK(accelerated_last_image_);
+ }
accelerated_last_frame_timestamp_ = video_frame->timestamp();
}
target_frame = &accelerated_last_frame_;
@@ -395,7 +458,11 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
canvas->translate(-SkFloatToScalar(target_frame->width() * 0.5f),
-SkFloatToScalar(target_frame->height() * 0.5f));
}
- canvas->drawBitmap(*target_frame, 0, 0, &paint);
+ if (accelerated_last_image_) {
+ canvas->drawImage(accelerated_last_image_.get(), 0, 0, &paint);
+ } else {
+ canvas->drawBitmap(*target_frame, 0, 0, &paint);
+ }
if (need_transform)
canvas->restore();
canvas->flush();
@@ -548,7 +615,7 @@ void SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
}
// static
-void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture(
+void SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
gpu::gles2::GLES2Interface* gl,
VideoFrame* video_frame,
unsigned int texture,
@@ -595,6 +662,7 @@ void SkCanvasVideoRenderer::ResetLastFrame() {
}
void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() {
+ accelerated_last_image_.reset();
accelerated_last_frame_.reset();
accelerated_generator_ = nullptr;
accelerated_last_frame_timestamp_ = media::kNoTimestamp();
« no previous file with comments | « media/blink/skcanvas_video_renderer.h ('k') | media/blink/webmediaplayer_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698