| 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();
|
|
|