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

Unified Diff: media/blink/skcanvas_video_renderer.cc

Issue 1144323003: media: Refactor SkCanvasVideoRenderer to use SkImages and not SkBitmaps. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix an incomplete comment. Created 5 years, 7 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/skcanvas_video_renderer_unittest.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 f86e118d753d49dbb135b1ac3a742487ff75477a..110b7027be2caba9f66649495c66fc48d79db549 100644
--- a/media/blink/skcanvas_video_renderer.cc
+++ b/media/blink/skcanvas_video_renderer.cc
@@ -12,11 +12,11 @@
#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/GrTextureProvider.h"
#include "third_party/skia/include/gpu/SkGrPixelRef.h"
-#include "ui/gfx/skbitmap_operations.h"
// Skia internal format depends on a platform. On Android it is ABGR, on others
// it is ARGB.
@@ -36,11 +36,11 @@ namespace media {
namespace {
-// This class keeps two temporary resources; software bitmap, hardware bitmap.
-// If both bitmap are created and then only software bitmap is updated every
-// frame, hardware bitmap outlives until the media player dies. So we delete
-// a temporary resource if it is not used for 3 sec.
-const int kTemporaryResourceDeletionDelay = 3; // Seconds;
+bool IsCanvasDrawingOnPicture(SkCanvas* canvas) {
+ SkImageInfo info;
+ size_t rowBytes;
+ return !canvas->getGrContext() && !canvas->peekPixels(&info, &rowBytes);
+}
bool IsYUV(media::VideoFrame::Format format) {
switch (format) {
@@ -75,66 +75,6 @@ bool IsYUVOrNative(media::VideoFrame::Format format) {
return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE;
}
-bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap,
- const gfx::Size& size) {
- return bitmap->getTexture() && bitmap->width() == size.width() &&
- bitmap->height() == size.height();
-}
-
-bool AllocateSkBitmapTexture(GrContext* gr,
- SkBitmap* bitmap,
- const gfx::Size& size) {
- DCHECK(gr);
- GrTextureDesc desc;
- // Use kRGBA_8888_GrPixelConfig, not kSkia8888_GrPixelConfig, to avoid
- // RGBA to BGRA conversion.
- desc.fConfig = kRGBA_8888_GrPixelConfig;
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fSampleCnt = 0;
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
- desc.fWidth = size.width();
- desc.fHeight = size.height();
- skia::RefPtr<GrTexture> texture = skia::AdoptRef(
- gr->textureProvider()->refScratchTexture(
- desc, GrTextureProvider::kExact_ScratchTexMatch));
- if (!texture.get())
- return false;
-
- SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
- SkGrPixelRef* pixel_ref = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
- if (!pixel_ref)
- return false;
- bitmap->setInfo(info);
- bitmap->setPixelRef(pixel_ref)->unref();
- return true;
-}
-
-bool CopyVideoFrameTextureToSkBitmapTexture(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.
- if (!IsSkBitmapProperlySizedTexture(bitmap,
- video_frame->visible_rect().size())) {
- if (!AllocateSkBitmapTexture(context_3d.gr_context, bitmap,
- video_frame->visible_rect().size())) {
- return false;
- }
- }
-
- unsigned texture_id =
- static_cast<unsigned>((bitmap->getTexture())->getTextureHandle());
- // If CopyVideoFrameTextureToGLTexture() 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(
- 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) {}
@@ -150,6 +90,35 @@ class SyncPointClientImpl : public VideoFrame::SyncPointClient {
DISALLOW_IMPLICIT_CONSTRUCTORS(SyncPointClientImpl);
};
+// Creates a SkImage from a |video_frame| backed by native resources.
+// The SkImage will not take ownership of the underlying resources and the
+// caller will have to delete them after the SkImage is used.
+// |source_textures| is a pointer to an array that will be filled with
+// texture ids backing the returned image.
+SkImage* NewSkImageFromVideoFrameNative(
+ const scoped_refptr<VideoFrame>& video_frame,
+ const Context3D& context_3d,
+ unsigned* source_textures) {
+ // TODO(dcastagna): Add support for YUV420.
+ DCHECK_EQ(VideoFrame::TEXTURE_RGBA, video_frame->texture_format());
+
+ // Get the texture from the mailbox and wrap it in a GrTexture.
+ const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0);
+ DCHECK(mailbox_holder.texture_target == GL_TEXTURE_2D ||
+ mailbox_holder.texture_target == GL_TEXTURE_RECTANGLE_ARB);
reveman 2015/05/27 17:54:20 GL_TEXTURE_EXTERNAL_OES? required for SurfaceTextu
Daniele Castagna 2015/05/27 18:12:35 Done.
+ gpu::gles2::GLES2Interface* gl = context_3d.gl;
+ gl->WaitSyncPointCHROMIUM(mailbox_holder.sync_point);
+ *source_textures = gl->CreateAndConsumeTextureCHROMIUM(
+ mailbox_holder.texture_target, mailbox_holder.mailbox.name);
+ GrBackendTextureDesc desc;
+ desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+ desc.fWidth = video_frame->coded_size().width();
+ desc.fHeight = video_frame->coded_size().height();
+ desc.fConfig = kRGBA_8888_GrPixelConfig;
+ desc.fTextureHandle = *source_textures;
+ return SkImage::NewFromTexture(context_3d.gr_context, desc);
+}
+
} // anonymous namespace
// Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU.
@@ -255,24 +224,11 @@ class VideoImageGenerator : public SkImageGenerator {
DISALLOW_IMPLICIT_CONSTRUCTORS(VideoImageGenerator);
};
-SkCanvasVideoRenderer::SkCanvasVideoRenderer()
- : last_frame_timestamp_(media::kNoTimestamp()),
- frame_deleting_timer_(
- FROM_HERE,
- base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay),
- this,
- &SkCanvasVideoRenderer::ResetLastFrame),
- accelerated_generator_(nullptr),
- accelerated_last_frame_timestamp_(media::kNoTimestamp()),
- accelerated_frame_deleting_timer_(
- FROM_HERE,
- base::TimeDelta::FromSeconds(kTemporaryResourceDeletionDelay),
- this,
- &SkCanvasVideoRenderer::ResetAcceleratedLastFrame) {
- last_frame_.setIsVolatile(true);
+SkCanvasVideoRenderer::SkCanvasVideoRenderer() {
}
-SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
+SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {
+}
void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
SkCanvas* canvas,
@@ -300,84 +256,16 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
return;
}
- SkBitmap* target_frame = nullptr;
-
+ unsigned texture_id_ = 0;
reveman 2015/05/27 17:54:20 nit: texture_id
Daniele Castagna 2015/05/27 18:12:35 Done.
+ SkImage* target_frame = nullptr;
if (video_frame->format() == VideoFrame::NATIVE_TEXTURE) {
- // Draw HW Video on both SW and HW Canvas.
- // In SW Canvas case, rely on skia drawing Ganesh SkBitmap on SW SkCanvas.
- if (accelerated_last_frame_.isNull() ||
- video_frame->timestamp() != accelerated_last_frame_timestamp_) {
- DCHECK(context_3d.gl);
- DCHECK(context_3d.gr_context);
- if (accelerated_generator_) {
- // Reset SkBitmap used in SWVideo-to-HWCanvas path.
- 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());
-
- accelerated_last_frame_timestamp_ = video_frame->timestamp();
- }
- target_frame = &accelerated_last_frame_;
- accelerated_frame_deleting_timer_.Reset();
- } else if (canvas->getGrContext()) {
- DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE);
- if (accelerated_last_frame_.isNull() ||
- video_frame->timestamp() != accelerated_last_frame_timestamp_) {
- // Draw SW Video on HW Canvas.
- if (!accelerated_generator_ && !accelerated_last_frame_.isNull()) {
- // Reset SkBitmap used in HWVideo-to-HWCanvas path.
- accelerated_last_frame_.reset();
- }
- accelerated_generator_ = new VideoImageGenerator(video_frame);
-
- // Note: This takes ownership of |accelerated_generator_|.
- if (!SkInstallDiscardablePixelRef(accelerated_generator_,
- &accelerated_last_frame_)) {
- NOTREACHED();
- return;
- }
- DCHECK(video_frame->visible_rect().width() ==
- accelerated_last_frame_.width() &&
- video_frame->visible_rect().height() ==
- accelerated_last_frame_.height());
-
- accelerated_last_frame_timestamp_ = video_frame->timestamp();
- } else if (accelerated_generator_) {
- accelerated_generator_->set_frame(video_frame);
- }
- target_frame = &accelerated_last_frame_;
- accelerated_frame_deleting_timer_.Reset();
+ DCHECK(context_3d.gr_context);
+ DCHECK(context_3d.gl);
+ target_frame =
+ NewSkImageFromVideoFrameNative(video_frame, context_3d, &texture_id_);
} else {
- // Draw SW Video on SW Canvas.
- DCHECK(video_frame->format() != VideoFrame::NATIVE_TEXTURE);
- if (last_frame_.isNull() ||
- video_frame->timestamp() != last_frame_timestamp_) {
- // Check if |bitmap| needs to be (re)allocated.
- if (last_frame_.isNull() ||
- last_frame_.width() != video_frame->visible_rect().width() ||
- last_frame_.height() != video_frame->visible_rect().height()) {
- last_frame_.allocN32Pixels(video_frame->visible_rect().width(),
- video_frame->visible_rect().height());
- last_frame_.setIsVolatile(true);
- }
- last_frame_.lockPixels();
- ConvertVideoFrameToRGBPixels(
- video_frame, last_frame_.getPixels(), last_frame_.rowBytes());
- last_frame_.notifyPixelsChanged();
- last_frame_.unlockPixels();
- last_frame_timestamp_ = video_frame->timestamp();
- }
- target_frame = &last_frame_;
- frame_deleting_timer_.Reset();
+ VideoImageGenerator* generator = new VideoImageGenerator(video_frame);
+ target_frame = SkImage::NewFromGenerator(generator);
}
paint.setXfermodeMode(mode);
@@ -420,14 +308,21 @@ 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);
+ canvas->drawImage(target_frame, 0, 0, &paint);
if (need_transform)
canvas->restore();
canvas->flush();
- // SkCanvas::flush() causes the generator to generate SkImage, so delete
- // |video_frame| not to be outlived.
- if (canvas->getGrContext() && accelerated_generator_)
- accelerated_generator_->set_frame(nullptr);
+ SkSafeSetNull(target_frame);
+ // When target_frame is created from a backend texture, calling
+ // textureSkCanvas::flush() causes Skia to use all the resources backing the
+ // SkImage and the underlying texture can be delete.
+ // TODO(dcastagna): release the texture in a callback once Skia API exposes
+ // the functionality.
+ if (texture_id_) {
+ DCHECK(!IsCanvasDrawingOnPicture(canvas));
+ DCHECK(context_3d.gl);
+ context_3d.gl->DeleteTextures(1, &texture_id_);
+ }
}
void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame,
@@ -614,15 +509,4 @@ void SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture(
video_frame->UpdateReleaseSyncPoint(&client);
}
-void SkCanvasVideoRenderer::ResetLastFrame() {
- last_frame_.reset();
- last_frame_timestamp_ = media::kNoTimestamp();
-}
-
-void SkCanvasVideoRenderer::ResetAcceleratedLastFrame() {
- accelerated_last_frame_.reset();
- accelerated_generator_ = nullptr;
- accelerated_last_frame_timestamp_ = media::kNoTimestamp();
-}
-
} // namespace media
« no previous file with comments | « media/blink/skcanvas_video_renderer.h ('k') | media/blink/skcanvas_video_renderer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698