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

Unified Diff: content/common/gpu/media/vaapi_picture_provider_drm.cc

Issue 490233002: VaapiVideoAccelerator: make Vaapi accelerator work with ozone (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Missing modifications in video accelerators Created 6 years, 2 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
Index: content/common/gpu/media/vaapi_picture_provider_drm.cc
diff --git a/content/common/gpu/media/vaapi_picture_provider_drm.cc b/content/common/gpu/media/vaapi_picture_provider_drm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d71096caacecbe5ff6bf1d64ceb28d761372dcc1
--- /dev/null
+++ b/content/common/gpu/media/vaapi_picture_provider_drm.cc
@@ -0,0 +1,274 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/vaapi_picture_provider_drm.h"
+#include "third_party/libva/va/drm/va_drm.h"
+#include "third_party/libva/va/va_drmcommon.h"
+#include "third_party/libva/va/va_vpp.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_egl.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/ozone/public/native_pixmap.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace content {
+
+#define LOG_VA_ERROR_AND_RETURN(input, err_msg) \
+ do { \
+ VAStatus va_status = input; \
+ if (va_status != VA_STATUS_SUCCESS) { \
+ DVLOG(1) << err_msg << " : " << vaErrorStr(va_status); \
+ return false; \
+ } \
+ } while (0)
+
+class DrmPicture : public VaapiPictureProvider::Picture {
+ public:
+ DrmPicture(DrmVaapiPictureProvider* provider,
+ VADisplay va_display,
+ const base::Callback<bool(void)> make_context_current,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size)
+ : Picture(picture_buffer_id, texture_id, size),
+ provider_(provider),
+ va_display_(va_display),
+ make_context_current_(make_context_current),
+ va_surface_(VA_INVALID_SURFACE) {}
+
+ virtual ~DrmPicture() {
+ if (gl_image_ && make_context_current_.Run()) {
+ // ReleaseTexImage on a GLImageEGL does nothing, to deassociate
+ // the renderer's texture from the image, just set the storage
+ // of that texture to NULL
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id());
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ size().width(),
+ size().height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+
+ gl_image_->Destroy(true);
+
+ CHECK_EQ(glGetError(), GL_NO_ERROR);
Pawel Osciak 2014/10/08 08:17:22 I think this is not critical enough to crash the p
llandwerlin-old 2014/10/08 09:31:18 Acknowledged.
+ }
+
+ if (va_surface_ != VA_INVALID_SURFACE)
+ vaDestroySurfaces(va_display_, &va_surface_, 1);
+ }
+
+ bool Initialize() {
+ VASurfaceAttrib va_attribs[2];
+ VASurfaceAttribExternalBuffers va_attrib_extbuf;
+
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ pixmap_ =
+ factory->CreateNativePixmap(size(), ui::SurfaceFactoryOzone::RGBA_8888);
Pawel Osciak 2014/10/08 08:17:22 Check for NULL?
llandwerlin-old 2014/10/08 09:31:18 Acknowledged.
+ unsigned long buffer_fd = pixmap_->GetDmaBufFd();
Pawel Osciak 2014/10/08 08:17:22 fd is an int... We should also check for -1.
llandwerlin-old 2014/10/08 09:31:18 Acknowledged.
+
+ va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX;
+ va_attrib_extbuf.width = size().width();
+ va_attrib_extbuf.height = size().height();
+ va_attrib_extbuf.data_size = size().height() * pixmap_->GetStride();
+ va_attrib_extbuf.num_planes = 1;
+ va_attrib_extbuf.pitches[0] = pixmap_->GetStride();
+ va_attrib_extbuf.offsets[0] = 0;
+ va_attrib_extbuf.buffers = &buffer_fd;
+ va_attrib_extbuf.num_buffers = 1;
+ va_attrib_extbuf.flags = 0;
+ va_attrib_extbuf.private_data = NULL;
+
+ va_attribs[0].type = VASurfaceAttribMemoryType;
+ va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+ va_attribs[0].value.type = VAGenericValueTypeInteger;
+ va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+
+ va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor;
+ va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+ va_attribs[1].value.type = VAGenericValueTypePointer;
+ va_attribs[1].value.value.p = &va_attrib_extbuf;
+
+ LOG_VA_ERROR_AND_RETURN(vaCreateSurfaces(va_display_,
+ VA_RT_FORMAT_RGB32,
+ size().width(),
+ size().height(),
+ &va_surface_,
+ 1,
+ va_attribs,
+ arraysize(va_attribs)),
+ "Couldn't create surface");
+
+ if (!make_context_current_.Run())
+ return false;
+
+ gl_image_ = new gfx::GLImageEGL(size());
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ if (!gl_image_->Initialize(
+ EGL_NATIVE_PIXMAP_KHR, pixmap_->GetEGLClientBuffer(), attrs))
+ return false;
+
+ return true;
+ }
+
+ virtual bool PutSurface(VASurfaceID va_surface_id) OVERRIDE {
+ if (!provider_->PutSurfaceIntoPicture(va_surface_id, va_surface_, size()))
+ return false;
+
+ if (!make_context_current_.Run())
+ return false;
+
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id());
+ return gl_image_->BindTexImage(GL_TEXTURE_2D);
+ }
+
+ private:
+ DrmVaapiPictureProvider* provider_;
+ VADisplay va_display_;
+ base::Callback<bool(void)> make_context_current_;
+ VASurfaceID va_surface_;
+ scoped_refptr<ui::NativePixmap> pixmap_;
+ scoped_refptr<gfx::GLImageEGL> gl_image_;
+};
+
+DrmVaapiPictureProvider::DrmVaapiPictureProvider(
+ VADisplay va_display,
+ const base::Callback<bool(void)> make_context_current)
+ : make_context_current_(make_context_current),
+ va_display_(va_display),
+ vpp_config_(VA_INVALID_ID),
+ vpp_context_(VA_INVALID_ID),
+ vpp_buffer_(VA_INVALID_ID) {
+}
+
+DrmVaapiPictureProvider::~DrmVaapiPictureProvider() {
+ DeinitializeVpp();
+}
+
+scoped_ptr<VaapiPictureProvider::Picture>
+DrmVaapiPictureProvider::CreatePicture(int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size) {
+ DrmPicture* drm_picture = new DrmPicture(this,
Pawel Osciak 2014/10/08 08:17:22 Could we create a scoped_ptr directly here? scoped
llandwerlin-old 2014/10/08 09:31:18 The problem is that I can't access the Initialize
Pawel Osciak 2014/10/26 13:06:46 Could you pass fb_config_ to the constructor of TF
llandwerlin-old 2014/10/29 13:52:47 Acknowledged.
+ va_display_,
+ make_context_current_,
+ picture_buffer_id,
+ texture_id,
+ size);
+ scoped_ptr<VaapiPictureProvider::Picture> picture(drm_picture);
Pawel Osciak 2014/10/08 08:17:22 Do we need the qualifier here if we are child of V
llandwerlin-old 2014/10/08 09:31:18 I'll check, thanks.
llandwerlin-old 2014/10/13 16:53:00 Yep, we do...
+
+ if (!drm_picture->Initialize())
+ picture.reset();
+
+ return picture.Pass();
+}
+
+bool DrmVaapiPictureProvider::PutSurfaceIntoPicture(
+ VASurfaceID va_surface_id_src,
+ VASurfaceID va_surface_id_dest,
+ const gfx::Size& dest_size) {
+ VAProcPipelineParameterBuffer* pipeline_param;
+ VARectangle input_region, output_region;
+
+ LOG_VA_ERROR_AND_RETURN(
+ vaMapBuffer(va_display_, vpp_buffer_, (void**)&pipeline_param),
+ "Couldn't map buffer");
+
+ memset(pipeline_param, 0, sizeof *pipeline_param);
+
+ input_region.x = input_region.y = 0;
+ input_region.width = coded_picture_size_.width();
+ input_region.height = coded_picture_size_.height();
+ pipeline_param->surface_region = &input_region;
+ pipeline_param->surface = va_surface_id_src;
+ pipeline_param->surface_color_standard = VAProcColorStandardNone;
+
+ output_region.x = output_region.y = 0;
+ output_region.width = dest_size.width();
+ output_region.height = dest_size.height();
+ pipeline_param->output_region = &output_region;
+ pipeline_param->output_background_color = 0xff000000;
+ pipeline_param->output_color_standard = VAProcColorStandardNone;
+
+ LOG_VA_ERROR_AND_RETURN(vaUnmapBuffer(va_display_, vpp_buffer_),
+ "Couldn't unmap buffer");
+
+ LOG_VA_ERROR_AND_RETURN(
+ vaBeginPicture(va_display_, vpp_context_, va_surface_id_dest),
+ "Couldn't begin picture");
+
+ LOG_VA_ERROR_AND_RETURN(
+ vaRenderPicture(va_display_, vpp_context_, &vpp_buffer_, 1),
+ "Couldn't render picture");
+
+ LOG_VA_ERROR_AND_RETURN(vaEndPicture(va_display_, vpp_context_),
+ "Couldn't end picture");
+ return true;
+}
+
+bool DrmVaapiPictureProvider::SetCodedSurfacesSize(const gfx::Size& size) {
Pawel Osciak 2014/10/08 08:17:22 I realized, could we just do this on PutSurfaceInt
llandwerlin-old 2014/10/08 09:31:18 Acknowledged.
+ DeinitializeVpp();
+ return InitializeVpp(size);
+}
+
+bool DrmVaapiPictureProvider::Initialize() {
+ return true;
+}
+
+bool DrmVaapiPictureProvider::InitializeVpp(const gfx::Size& size) {
+ LOG_VA_ERROR_AND_RETURN(vaCreateConfig(va_display_,
+ VAProfileNone,
+ VAEntrypointVideoProc,
+ NULL,
+ 0,
+ &vpp_config_),
+ "Couldn't create config");
+
+ LOG_VA_ERROR_AND_RETURN(vaCreateContext(va_display_,
+ vpp_config_,
+ size.width(),
+ size.height(),
+ 0,
+ NULL,
+ 0,
+ &vpp_context_),
+ "Couldn't create context");
+
+ LOG_VA_ERROR_AND_RETURN(vaCreateBuffer(va_display_,
+ vpp_context_,
+ VAProcPipelineParameterBufferType,
+ sizeof(VAProcPipelineParameterBuffer),
+ 1,
+ NULL,
+ &vpp_buffer_),
+ "Couldn't create buffer");
+
+ coded_picture_size_ = size;
+
+ return true;
+}
+
+void DrmVaapiPictureProvider::DeinitializeVpp() {
+ if (vpp_buffer_ != VA_INVALID_ID) {
+ vaDestroyBuffer(va_display_, vpp_buffer_);
+ vpp_buffer_ = VA_INVALID_ID;
+ }
+ if (vpp_context_ != VA_INVALID_ID) {
+ vaDestroyContext(va_display_, vpp_context_);
+ vpp_context_ = VA_INVALID_ID;
+ }
+ if (vpp_config_ != VA_INVALID_ID) {
+ vaDestroyConfig(va_display_, vpp_config_);
+ vpp_config_ = VA_INVALID_ID;
+ }
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698