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

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

Issue 490233002: VaapiVideoAccelerator: make Vaapi accelerator work with ozone (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 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_wrapper.cc
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc
index 5e93b994db02dcf52301327e0c285b82a148e001..a4317e857987e13b9412b5316d5af13db5b0ba7e 100644
--- a/content/common/gpu/media/vaapi_wrapper.cc
+++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -8,20 +8,39 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/scoped_ptr_hash_map.h"
Pawel Osciak 2014/08/25 01:13:23 Unused?
#include "base/logging.h"
+#include "base/memory/scoped_vector.h"
Pawel Osciak 2014/08/25 01:13:24 Unused?
#include "base/numerics/safe_conversions.h"
// Auto-generated for dlopen libva libraries
#include "content/common/gpu/media/va_stubs.h"
#include "third_party/libyuv/include/libyuv.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_image.h"
+#if defined(USE_X11)
+#include "third_party/libva/va/va_x11.h"
+#include "ui/gl/gl_context_glx.h"
+#else
+#include <gbm.h>
+#include "third_party/libva/va/drm/va_drm.h"
+#include "third_party/libva/va/va_drmcommon.h"
+#include "ui/gl/gl_image_egl.h"
+#include "ui/ozone/public/native_pixmap.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+#include <va/va_vpp.h>
+#endif // USE_X11
+#include "ui/gl/scoped_binders.h"
using content_common_gpu_media::kModuleVa;
+#if defined(USE_X11)
+using content_common_gpu_media::kModuleVa_x11;
+#else
+using content_common_gpu_media::kModuleVa_ozone;
+#endif // USE_X11
using content_common_gpu_media::InitializeStubs;
using content_common_gpu_media::StubPathMap;
-// libva-x11 depends on libva, so dlopen libva-x11 is enough
-static const base::FilePath::CharType kVaLib[] =
- FILE_PATH_LITERAL("libva-x11.so.1");
-
#define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
do { \
DVLOG(1) << err_msg \
@@ -45,6 +64,558 @@ static const base::FilePath::CharType kVaLib[] =
namespace content {
+class VaapiWrapper::Backend : public base::RefCounted<VaapiWrapper::Backend> {
Pawel Osciak 2014/08/25 01:13:24 Please document all classes that are added.
+ protected:
+ virtual ~Backend() { Deinitialize(); }
+
+ public:
+ virtual VAStatus CreateSurfaces(VASurfaceID* surfaces,
+ uint32 num_surfaces,
+ const gfx::Size& size) = 0;
+
+ virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size) = 0;
+
+ virtual void DestroyPicture(Picture* picture) = 0;
+
+ virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display,
+ VASurfaceID va_surface_id,
+ Picture* picture) = 0;
+
+ virtual VADisplay GetDisplay() = 0;
+
+ virtual bool Initialize() = 0;
+
+ virtual void Deinitialize() {};
Pawel Osciak 2014/08/25 01:13:24 Does this need body?
+
+ static scoped_refptr<Backend> Create(
+ gfx::GLContext* gl_context,
+ const base::Callback<bool(void)> make_context_current);
+
+ private:
+ friend class base::RefCounted<VaapiWrapper::Backend>;
+};
+
+#if defined(USE_X11)
+class VaapiWrapper::TFPPicture : public VaapiWrapper::Picture {
+ public:
+ TFPPicture(scoped_refptr<Backend> backend,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size,
+ Pixmap x_pixmap,
+ GLXPixmap glx_pixmap)
+ : Picture(picture_buffer_id, texture_id, size),
+ backend_(backend),
+ x_pixmap_(x_pixmap),
+ glx_pixmap_(glx_pixmap) {}
+ virtual ~TFPPicture() { backend_->DestroyPicture(this); }
+
+ Pixmap x_pixmap() const { return x_pixmap_; }
+ GLXPixmap glx_pixmap() const { return glx_pixmap_; }
+
+ private:
+ scoped_refptr<Backend> backend_;
+ Pixmap x_pixmap_;
+ GLXPixmap glx_pixmap_;
+};
+
+class XFreeDeleter {
+ public:
+ void operator()(void* x) const { ::XFree(x); }
+};
+
+class VaapiWrapper::X11Backend : public VaapiWrapper::Backend {
+ private:
Pawel Osciak 2014/08/25 01:13:24 The proper order of members should start with publ
+ virtual ~X11Backend() {}
+
+ bool BindPicture(Picture* picture) {
+ TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture);
+
+ if (!make_context_current_.Run())
+ return false;
+
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D,
+ tfp_picture->texture_id());
+ glXBindTexImageEXT(
+ x_display_, tfp_picture->glx_pixmap(), GLX_FRONT_LEFT_EXT, NULL);
+
+ return true;
+ }
+
+ public:
+ X11Backend(gfx::GLContextGLX* glx_context,
+ const base::Callback<bool(void)> make_context_current)
+ : glx_context_(glx_context),
+ make_context_current_(make_context_current),
+ x_display_(glx_context_->display()),
+ va_display_(NULL) {}
+
+ virtual VAStatus CreateSurfaces(VASurfaceID* surfaces,
+ uint32 num_surfaces,
+ const gfx::Size& size) OVERRIDE {
+ return vaCreateSurfaces(GetDisplay(),
+ VA_RT_FORMAT_YUV420,
+ size.width(),
+ size.height(),
+ surfaces,
+ num_surfaces,
+ NULL,
+ 0);
+ }
+
+ virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size) OVERRIDE {
+ linked_ptr<TFPPicture> tfp_picture;
+
+ if (!make_context_current_.Run())
+ return tfp_picture;
+
+ XWindowAttributes win_attr;
+ int screen = DefaultScreen(x_display_);
+ XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
+ // TODO(posciak): pass the depth required by libva, not the RootWindow's
+ // depth
+ Pixmap x_pixmap = XCreatePixmap(x_display_,
+ RootWindow(x_display_, screen),
+ size.width(),
+ size.height(),
+ win_attr.depth);
+ if (!x_pixmap) {
+ DVLOG(1) << "Failed creating an X Pixmap for TFP";
+ return tfp_picture;
+ }
+
+ static const int pixmap_attr[] = {
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT,
+ GLX_TEXTURE_FORMAT_RGB_EXT, GL_NONE,
+ };
+
+ GLXPixmap glx_pixmap =
+ glXCreatePixmap(x_display_, fb_config_, x_pixmap, pixmap_attr);
+ if (!glx_pixmap) {
+ // x_pixmap_ will be freed in the destructor.
+ DVLOG(1) << "Failed creating a GLX Pixmap for TFP";
+ XFreePixmap(x_display_, x_pixmap);
+ return tfp_picture;
+ }
+
+ tfp_picture.reset(new TFPPicture(make_scoped_refptr(this),
+ picture_buffer_id,
+ texture_id,
+ size,
+ x_pixmap,
+ glx_pixmap));
+
+ return tfp_picture;
+ }
+
+ virtual void DestroyPicture(Picture* picture) OVERRIDE {
+ TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture);
Pawel Osciak 2014/08/25 01:13:23 Please do not cast to children. I think you can so
+
+ // Unbind surface from texture and deallocate resources.
+ if (tfp_picture->glx_pixmap() && make_context_current_.Run()) {
+ glXReleaseTexImageEXT(
+ x_display_, tfp_picture->glx_pixmap(), GLX_FRONT_LEFT_EXT);
+ glXDestroyPixmap(x_display_, tfp_picture->glx_pixmap());
+ }
+
+ if (tfp_picture->x_pixmap())
+ XFreePixmap(x_display_, tfp_picture->x_pixmap());
+ XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
+ }
+
+ virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display,
+ VASurfaceID va_surface_id,
+ Picture* picture) OVERRIDE {
+ TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture);
+ const gfx::Size& size = tfp_picture->size();
+
+ if (!BindPicture(picture))
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ return vaPutSurface(va_display,
+ va_surface_id,
+ tfp_picture->x_pixmap(),
+ 0,
+ 0,
+ size.width(),
+ size.height(),
+ 0,
+ 0,
+ size.width(),
+ size.height(),
+ NULL,
+ 0,
+ 0);
+ }
+
+ virtual VADisplay GetDisplay() OVERRIDE {
+ if (!va_display_)
+ va_display_ = vaGetDisplay(x_display_);
Pawel Osciak 2014/08/25 01:13:24 Why not just call this once in the constructor?
+ return va_display_;
+ }
+
+ virtual bool Initialize() OVERRIDE {
+ if (!make_context_current_.Run()) {
+ DVLOG(1) << "Couldn't make context current";
+ return false;
+ }
+
+ const int fbconfig_attr[] = {
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
+ GLX_Y_INVERTED_EXT, GL_TRUE,
+ GL_NONE,
+ };
+
+ int num_fbconfigs;
+ scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs(glXChooseFBConfig(
+ x_display_, DefaultScreen(x_display_), fbconfig_attr, &num_fbconfigs));
+
+ if (!glx_fb_configs) {
+ DVLOG(1) << "Couldn't get glx configs";
+ return false;
+ }
+ if (!num_fbconfigs) {
+ DVLOG(1) << "Couldn't get at least a glx config";
+ return false;
+ }
+
+ fb_config_ = glx_fb_configs.get()[0];
+ return true;
+ }
+
+ virtual void Deinitialize() OVERRIDE { va_display_ = NULL; }
+
+ private:
+ gfx::GLContextGLX* glx_context_;
+ base::Callback<bool(void)> make_context_current_;
+
+ Display* x_display_;
+ GLXFBConfig fb_config_;
+
+ VADisplay va_display_;
+};
+
+#else
+
+class VaapiWrapper::GbmPicture : public VaapiWrapper::Picture {
+ public:
+ GbmPicture(scoped_refptr<Backend> backend,
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size,
+ VASurfaceID va_surface,
+ scoped_refptr<ui::NativePixmap> pixmap,
+ scoped_refptr<gfx::GLImage> gl_image)
+ : Picture(picture_buffer_id, texture_id, size),
+ backend_(backend),
+ va_surface_(va_surface),
+ pixmap_(pixmap),
+ gl_image_(gl_image) {}
+ virtual ~GbmPicture() { backend_->DestroyPicture(this); }
+
+ scoped_refptr<ui::NativePixmap> pixmap() const { return pixmap_; }
Pawel Osciak 2014/08/25 01:13:24 Unused?
+ scoped_refptr<gfx::GLImage> gl_image() const { return gl_image_; }
+ VASurfaceID va_surface() const { return va_surface_; }
+
+ private:
+ scoped_refptr<Backend> backend_;
+ VASurfaceID va_surface_;
+ scoped_refptr<ui::NativePixmap> pixmap_;
+ scoped_refptr<gfx::GLImage> gl_image_;
+};
+
+class VaapiWrapper::GbmBackend : public VaapiWrapper::Backend {
+ private:
+ virtual ~GbmBackend() {}
+
+ public:
+ GbmBackend(const base::Callback<bool(void)> make_context_current)
+ : make_context_current_(make_context_current),
+ va_display_(NULL),
+ vpp_config_(VA_INVALID_ID),
+ vpp_context_(VA_INVALID_ID),
+ vpp_buffer_(VA_INVALID_ID) {}
+
+ virtual VAStatus CreateSurfaces(VASurfaceID* surfaces,
+ uint32 num_surfaces,
+ const gfx::Size& size) OVERRIDE {
+ DeinitializeVpp();
+ if (!InitializeVpp(size))
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ return vaCreateSurfaces(GetDisplay(),
+ VA_RT_FORMAT_YUV420,
+ size.width(),
+ size.height(),
+ surfaces,
+ num_surfaces,
+ NULL,
+ 0);
+ }
+
+ virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id,
+ uint32 texture_id,
+ const gfx::Size& size) OVERRIDE {
+ VASurfaceAttrib va_attribs[2];
+ VASurfaceAttribExternalBuffers va_attrib_extbuf;
+
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ scoped_refptr<ui::NativePixmap> pixmap =
+ factory->CreateNativePixmap(size, ui::SurfaceFactoryOzone::RGBA_8888);
+ unsigned long buffer_fd = pixmap->GetDmaBufFd();
+ VASurfaceID va_surface;
+
+ 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() * size.width() * 4;
+ va_attrib_extbuf.num_planes = 1;
+ va_attrib_extbuf.pitches[0] = 4 * size.width();
+ 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;
+
+ VAStatus status = vaCreateSurfaces(GetDisplay(),
+ VA_RT_FORMAT_RGB32,
+ size.width(),
+ size.height(),
+ &va_surface,
+ 1,
+ va_attribs,
+ 2);
Pawel Osciak 2014/08/25 01:13:24 arraysize(va_attribs)
+
+ linked_ptr<GbmPicture> gbm_picture;
+
+ if (status == VA_STATUS_SUCCESS) {
+ if (!make_context_current_.Run())
+ return gbm_picture;
+
+ EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+ gfx::GLImageEGL* gl_image = new gfx::GLImageEGL(size);
Pawel Osciak 2014/08/25 01:13:23 Could we have a scoper for this instead? Where do
+ gl_image->Initialize(
+ EGL_NATIVE_PIXMAP_KHR, pixmap->GetEGLClientBuffer(), attrs);
+
+ CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
Pawel Osciak 2014/08/25 01:13:23 Please don't use CHECK. This crashes the process.
+
+ gbm_picture.reset(new GbmPicture(this,
+ picture_buffer_id,
+ texture_id,
+ size,
+ va_surface,
+ pixmap,
+ gl_image));
+ }
+
+ return gbm_picture;
+ }
+
+ virtual void DestroyPicture(Picture* picture) OVERRIDE {
+ GbmPicture* gbm_picture = static_cast<GbmPicture*>(picture);
+ VASurfaceID va_surface = gbm_picture->va_surface();
+
+ if (!make_context_current_.Run())
+ return;
+
+ // ReleaseTexImage on a GLImageEGL does nothing, do deassociate
+ // the renderer texture from the image, just set the storage of
+ // that texture to NULL
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D,
+ gbm_picture->texture_id());
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGBA,
+ gbm_picture->size().width(),
+ gbm_picture->size().height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+
+ gbm_picture->gl_image()->Destroy(true);
+
+ CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
+
+ vaDestroySurfaces(GetDisplay(), &va_surface, 1);
+ }
+
+ virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display,
+ VASurfaceID va_surface_id,
+ Picture* picture) OVERRIDE {
+ GbmPicture* gbm_picture = static_cast<GbmPicture*>(picture);
Pawel Osciak 2014/08/25 01:13:23 We cannot cast to child. But you don't really need
+ VAProcPipelineParameterBuffer* pipeline_param;
+ VAStatus status;
+
+ status = vaMapBuffer(GetDisplay(), vpp_buffer_, (void**)&pipeline_param);
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ memset(pipeline_param, 0, sizeof *pipeline_param);
+
+ pipeline_param->surface = va_surface_id;
+ pipeline_param->surface_color_standard = VAProcColorStandardNone;
+
+ pipeline_param->output_background_color = 0xff000000;
+ pipeline_param->output_color_standard = VAProcColorStandardNone;
marcheu 2014/08/29 04:01:09 isn't this going to differ from the X11 path? IIRC
llandwerlin-old 2014/08/29 16:30:55 As far as I can tell the intel driver ignores this
+
+ status = vaUnmapBuffer(GetDisplay(), vpp_buffer_);
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ status =
+ vaBeginPicture(GetDisplay(), vpp_context_, gbm_picture->va_surface());
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ status = vaRenderPicture(GetDisplay(), vpp_context_, &vpp_buffer_, 1);
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ status = vaEndPicture(GetDisplay(), vpp_context_);
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ if (!make_context_current_.Run())
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D,
+ gbm_picture->texture_id());
+ gbm_picture->gl_image()->BindTexImage(GL_TEXTURE_2D);
+
+ CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
+
+ return VA_STATUS_SUCCESS;
+ }
+
+ virtual VADisplay GetDisplay() OVERRIDE {
+ if (!va_display_) {
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+ gbm_device* device =
+ reinterpret_cast<gbm_device*>(factory->GetNativeDisplay());
+
+ va_display_ = vaGetDisplayDRM(gbm_device_get_fd(device));
+ }
+
+ return va_display_;
+ }
+
+ virtual bool Initialize() OVERRIDE { return true; }
+
+ virtual void Deinitialize() OVERRIDE {
+ DeinitializeVpp();
+ va_display_ = NULL;
+ }
+
+ private:
+ bool InitializeVpp(const gfx::Size& size) {
+ VAStatus status;
+
+ status = vaCreateConfig(GetDisplay(),
+ VAProfileNone,
+ VAEntrypointVideoProc,
+ NULL,
+ 0,
+ &vpp_config_);
+ if (status != VA_STATUS_SUCCESS) {
+ DVLOG(1) << "Couldn't create VPP config";
+ return false;
+ }
+
+ status = vaCreateContext(GetDisplay(),
+ vpp_config_,
+ size.width(),
+ size.height(),
+ 0,
+ NULL,
+ 0,
+ &vpp_context_);
+ if (status != VA_STATUS_SUCCESS) {
+ DVLOG(1) << "Couldn't create VPP context";
+ DeinitializeVpp();
Pawel Osciak 2014/08/25 01:13:23 Isn't this called anyway on destruction via Deinit
+ return false;
+ }
+
+ status = vaCreateBuffer(GetDisplay(),
+ vpp_context_,
+ VAProcPipelineParameterBufferType,
+ sizeof(VAProcPipelineParameterBuffer),
+ 1,
+ NULL,
+ &vpp_buffer_);
+ if (status != VA_STATUS_SUCCESS) {
+ DVLOG(1) << "Couldn't create VPP pipeline buffer";
+ DeinitializeVpp();
+ return false;
+ }
+
+ return true;
+ }
+
+ bool IsVppInitialized() { return vpp_buffer_ != VA_INVALID_ID; }
+
+ void DeinitializeVpp() {
+ if (vpp_buffer_ != VA_INVALID_ID) {
+ vaDestroyBuffer(GetDisplay(), vpp_buffer_);
+ vpp_buffer_ = VA_INVALID_ID;
+ }
+ if (vpp_context_ != VA_INVALID_ID) {
+ vaDestroyContext(GetDisplay(), vpp_context_);
+ vpp_context_ = VA_INVALID_ID;
+ }
+ if (vpp_config_ != VA_INVALID_ID) {
+ vaDestroyConfig(GetDisplay(), vpp_config_);
+ vpp_config_ = VA_INVALID_ID;
+ }
+ }
+
+ base::Callback<bool(void)> make_context_current_;
+
+ VADisplay va_display_;
+
+ VAConfigID vpp_config_;
+ VAContextID vpp_context_;
+ VABufferID vpp_buffer_;
+};
+#endif // USE_X11
+
+scoped_refptr<VaapiWrapper::Backend> VaapiWrapper::Backend::Create(
+ gfx::GLContext* gl_context,
+ const base::Callback<bool(void)> make_context_current) {
+ scoped_refptr<Backend> backend;
+
+#if defined(USE_X11)
+ backend = new X11Backend(static_cast<gfx::GLContextGLX*>(gl_context),
+ make_context_current);
+#else
+ backend = new GbmBackend(make_context_current);
+#endif // USE_X11
+
+ if (!backend->Initialize())
+ backend = NULL;
+
+ return backend;
+}
+
// Config attributes common for both encode and decode.
static const VAConfigAttrib kCommonVAConfigAttribs[] = {
{VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
@@ -113,9 +684,7 @@ VASurface::~VASurface() {
}
VaapiWrapper::VaapiWrapper()
- : va_display_(NULL),
- va_config_id_(VA_INVALID_ID),
- va_context_id_(VA_INVALID_ID) {
+ : va_config_id_(VA_INVALID_ID), va_context_id_(VA_INVALID_ID) {
}
VaapiWrapper::~VaapiWrapper() {
@@ -128,12 +697,16 @@ VaapiWrapper::~VaapiWrapper() {
scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
CodecMode mode,
media::VideoCodecProfile profile,
- Display* x_display,
+ gfx::GLContext* gl_context,
+ const base::Callback<bool(void)>& make_context_current,
const base::Closure& report_error_to_uma_cb) {
scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
- if (!vaapi_wrapper->Initialize(
- mode, profile, x_display, report_error_to_uma_cb))
+ if (!vaapi_wrapper->Initialize(mode,
+ profile,
+ gl_context,
+ make_context_current,
+ report_error_to_uma_cb))
vaapi_wrapper.reset();
return vaapi_wrapper.Pass();
@@ -146,15 +719,17 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
VA_RENDER_MODE_LOCAL_GPU,
VA_DISPLAY_ATTRIB_SETTABLE};
- VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1);
+ VAStatus va_res = vaSetDisplayAttributes(backend_->GetDisplay(), &item, 1);
if (va_res != VA_STATUS_SUCCESS)
DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
}
-bool VaapiWrapper::Initialize(CodecMode mode,
- media::VideoCodecProfile profile,
- Display* x_display,
- const base::Closure& report_error_to_uma_cb) {
+bool VaapiWrapper::Initialize(
+ CodecMode mode,
+ media::VideoCodecProfile profile,
+ gfx::GLContext* gl_context,
+ const base::Callback<bool(void)>& make_context_current,
+ const base::Closure& report_error_to_uma_cb) {
static bool vaapi_functions_initialized = PostSandboxInitialization();
if (!vaapi_functions_initialized) {
DVLOG(1) << "Failed to initialize VAAPI libs";
@@ -165,13 +740,21 @@ bool VaapiWrapper::Initialize(CodecMode mode,
base::AutoLock auto_lock(va_lock_);
- va_display_ = vaGetDisplay(x_display);
Pawel Osciak 2014/08/25 01:13:24 Could we keep va_display_ in VaapiWrapper? We woul
- if (!vaDisplayIsValid(va_display_)) {
+ backend_ = VaapiWrapper::Backend::Create(gl_context, make_context_current);
+
+ if (!backend_.get()) {
+ DVLOG(1) << "Failed to initialize VAAPI backend";
+ return false;
+ }
+
+ // va_display_ = backend_->GetDisplay();
+ if (!vaDisplayIsValid(backend_->GetDisplay())) {
DVLOG(1) << "Could not get a valid VA display";
return false;
}
- VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_);
+ VAStatus va_res =
+ vaInitialize(backend_->GetDisplay(), &major_version_, &minor_version_);
VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false);
DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
@@ -181,13 +764,13 @@ bool VaapiWrapper::Initialize(CodecMode mode,
}
// Query the driver for supported profiles.
- int max_profiles = vaMaxNumProfiles(va_display_);
+ int max_profiles = vaMaxNumProfiles(backend_->GetDisplay());
std::vector<VAProfile> supported_profiles(
base::checked_cast<size_t>(max_profiles));
int num_supported_profiles;
va_res = vaQueryConfigProfiles(
- va_display_, &supported_profiles[0], &num_supported_profiles);
+ backend_->GetDisplay(), &supported_profiles[0], &num_supported_profiles);
VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false);
if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) {
DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles;
@@ -198,17 +781,17 @@ bool VaapiWrapper::Initialize(CodecMode mode,
VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles);
if (va_profile == VAProfileNone) {
- DVLOG(1) << "Unsupported profile";
+ DVLOG(1) << "Unsupported profile : " << profile;
return false;
}
// Query the driver for supported entrypoints.
- int max_entrypoints = vaMaxNumEntrypoints(va_display_);
+ int max_entrypoints = vaMaxNumEntrypoints(backend_->GetDisplay());
std::vector<VAEntrypoint> supported_entrypoints(
base::checked_cast<size_t>(max_entrypoints));
int num_supported_entrypoints;
- va_res = vaQueryConfigEntrypoints(va_display_,
+ va_res = vaQueryConfigEntrypoints(backend_->GetDisplay(),
va_profile,
&supported_entrypoints[0],
&num_supported_entrypoints);
@@ -247,8 +830,11 @@ bool VaapiWrapper::Initialize(CodecMode mode,
for (size_t i = 0; i < required_attribs.size(); ++i)
attribs[i].value = 0;
- va_res = vaGetConfigAttributes(
- va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
+ va_res = vaGetConfigAttributes(backend_->GetDisplay(),
+ va_profile,
+ entrypoint,
+ &attribs[0],
+ attribs.size());
VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
for (size_t i = 0; i < required_attribs.size(); ++i) {
@@ -263,7 +849,7 @@ bool VaapiWrapper::Initialize(CodecMode mode,
TryToSetVADisplayAttributeToLocalGPU();
- va_res = vaCreateConfig(va_display_,
+ va_res = vaCreateConfig(backend_->GetDisplay(),
va_profile,
entrypoint,
&required_attribs[0],
@@ -278,17 +864,17 @@ void VaapiWrapper::Deinitialize() {
base::AutoLock auto_lock(va_lock_);
if (va_config_id_ != VA_INVALID_ID) {
- VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
+ VAStatus va_res = vaDestroyConfig(backend_->GetDisplay(), va_config_id_);
VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed");
}
- if (va_display_) {
- VAStatus va_res = vaTerminate(va_display_);
+ if (backend_->GetDisplay()) {
+ VAStatus va_res = vaTerminate(backend_->GetDisplay());
VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
}
va_config_id_ = VA_INVALID_ID;
- va_display_ = NULL;
+ backend_ = NULL;
}
bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) {
@@ -296,7 +882,7 @@ bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) {
(major_version_ == major && minor_version_ < minor);
}
-bool VaapiWrapper::CreateSurfaces(gfx::Size size,
+bool VaapiWrapper::CreateSurfaces(const gfx::Size& size,
size_t num_surfaces,
std::vector<VASurfaceID>* va_surfaces) {
base::AutoLock auto_lock(va_lock_);
@@ -307,13 +893,8 @@ bool VaapiWrapper::CreateSurfaces(gfx::Size size,
va_surface_ids_.resize(num_surfaces);
// Allocate surfaces in driver.
- VAStatus va_res = vaCreateSurfaces(va_display_,
- VA_RT_FORMAT_YUV420,
- size.width(), size.height(),
- &va_surface_ids_[0],
- va_surface_ids_.size(),
- NULL, 0);
-
+ VAStatus va_res = backend_->CreateSurfaces(
+ &va_surface_ids_[0], va_surface_ids_.size(), size);
VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed");
if (va_res != VA_STATUS_SUCCESS) {
va_surface_ids_.clear();
@@ -321,9 +902,13 @@ bool VaapiWrapper::CreateSurfaces(gfx::Size size,
}
// And create a context associated with them.
- va_res = vaCreateContext(va_display_, va_config_id_,
- size.width(), size.height(), VA_PROGRESSIVE,
- &va_surface_ids_[0], va_surface_ids_.size(),
+ va_res = vaCreateContext(backend_->GetDisplay(),
+ va_config_id_,
+ size.width(),
+ size.height(),
+ VA_PROGRESSIVE,
+ &va_surface_ids_[0],
+ va_surface_ids_.size(),
&va_context_id_);
VA_LOG_ON_ERROR(va_res, "vaCreateContext failed");
@@ -341,13 +926,13 @@ void VaapiWrapper::DestroySurfaces() {
DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces";
if (va_context_id_ != VA_INVALID_ID) {
- VAStatus va_res = vaDestroyContext(va_display_, va_context_id_);
+ VAStatus va_res = vaDestroyContext(backend_->GetDisplay(), va_context_id_);
VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed");
}
if (!va_surface_ids_.empty()) {
- VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0],
- va_surface_ids_.size());
+ VAStatus va_res = vaDestroySurfaces(
+ backend_->GetDisplay(), &va_surface_ids_[0], va_surface_ids_.size());
VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed");
}
@@ -355,15 +940,26 @@ void VaapiWrapper::DestroySurfaces() {
va_context_id_ = VA_INVALID_ID;
}
+linked_ptr<VaapiWrapper::Picture> VaapiWrapper::CreatePicture(
+ int32 picture_buffer_id,
+ uint32 texture_id,
+ gfx::Size size) {
+ return backend_->CreatePicture(picture_buffer_id, texture_id, size);
+}
+
bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
size_t size,
void* buffer) {
base::AutoLock auto_lock(va_lock_);
VABufferID buffer_id;
- VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_,
- va_buffer_type, size,
- 1, buffer, &buffer_id);
+ VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(),
+ va_context_id_,
+ va_buffer_type,
+ size,
+ 1,
+ buffer,
+ &buffer_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
switch (va_buffer_type) {
@@ -388,7 +984,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
base::AutoLock auto_lock(va_lock_);
VABufferID buffer_id;
- VAStatus va_res = vaCreateBuffer(va_display_,
+ VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(),
va_context_id_,
VAEncMiscParameterBufferType,
sizeof(VAEncMiscParameterBuffer) + size,
@@ -398,10 +994,10 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
void* data_ptr = NULL;
- va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr);
+ va_res = vaMapBuffer(backend_->GetDisplay(), buffer_id, &data_ptr);
VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
if (va_res != VA_STATUS_SUCCESS) {
- vaDestroyBuffer(va_display_, buffer_id);
+ vaDestroyBuffer(backend_->GetDisplay(), buffer_id);
return false;
}
@@ -411,7 +1007,7 @@ bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr);
misc_param->type = misc_param_type;
memcpy(misc_param->data, buffer, size);
- va_res = vaUnmapBuffer(va_display_, buffer_id);
+ va_res = vaUnmapBuffer(backend_->GetDisplay(), buffer_id);
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
pending_va_bufs_.push_back(buffer_id);
@@ -422,12 +1018,14 @@ void VaapiWrapper::DestroyPendingBuffers() {
base::AutoLock auto_lock(va_lock_);
for (size_t i = 0; i < pending_va_bufs_.size(); ++i) {
- VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]);
+ VAStatus va_res =
+ vaDestroyBuffer(backend_->GetDisplay(), pending_va_bufs_[i]);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
}
for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) {
- VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]);
+ VAStatus va_res =
+ vaDestroyBuffer(backend_->GetDisplay(), pending_slice_bufs_[i]);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
}
@@ -437,7 +1035,7 @@ void VaapiWrapper::DestroyPendingBuffers() {
bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
base::AutoLock auto_lock(va_lock_);
- VAStatus va_res = vaCreateBuffer(va_display_,
+ VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(),
va_context_id_,
VAEncCodedBufferType,
size,
@@ -456,7 +1054,7 @@ void VaapiWrapper::DestroyCodedBuffers() {
for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin();
iter != coded_buffers_.end();
++iter) {
- VAStatus va_res = vaDestroyBuffer(va_display_, *iter);
+ VAStatus va_res = vaDestroyBuffer(backend_->GetDisplay(), *iter);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
}
@@ -471,13 +1069,13 @@ bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
DVLOG(4) << "Target VA surface " << va_surface_id;
// Get ready to execute for given surface.
- VAStatus va_res = vaBeginPicture(va_display_, va_context_id_,
- va_surface_id);
+ VAStatus va_res =
+ vaBeginPicture(backend_->GetDisplay(), va_context_id_, va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
if (pending_va_bufs_.size() > 0) {
// Commit parameter and slice buffers.
- va_res = vaRenderPicture(va_display_,
+ va_res = vaRenderPicture(backend_->GetDisplay(),
va_context_id_,
&pending_va_bufs_[0],
pending_va_bufs_.size());
@@ -485,7 +1083,7 @@ bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
}
if (pending_slice_bufs_.size() > 0) {
- va_res = vaRenderPicture(va_display_,
+ va_res = vaRenderPicture(backend_->GetDisplay(),
va_context_id_,
&pending_slice_bufs_[0],
pending_slice_bufs_.size());
@@ -494,7 +1092,7 @@ bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
// Instruct HW codec to start processing committed buffers.
// Does not block and the job is not finished after this returns.
- va_res = vaEndPicture(va_display_, va_context_id_);
+ va_res = vaEndPicture(backend_->GetDisplay(), va_context_id_);
VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
return true;
@@ -506,22 +1104,17 @@ bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
return result;
}
-bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
- Pixmap x_pixmap,
- gfx::Size dest_size) {
+bool VaapiWrapper::PutSurfaceIntoPicture(VASurfaceID va_surface_id,
+ Picture* picture) {
base::AutoLock auto_lock(va_lock_);
- VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
+ VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
- // Put the data into an X Pixmap.
- va_res = vaPutSurface(va_display_,
- va_surface_id,
- x_pixmap,
- 0, 0, dest_size.width(), dest_size.height(),
- 0, 0, dest_size.width(), dest_size.height(),
- NULL, 0, 0);
+ va_res = backend_->PutSurfaceIntoPicture(
+ backend_->GetDisplay(), va_surface_id, picture);
Pawel Osciak 2014/08/25 01:13:24 We don't need to pass to backend_ its own member.
VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
Pawel Osciak 2014/08/25 01:13:24 s/pixmap/picture/?
+
return true;
}
@@ -530,22 +1123,22 @@ bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
void** mem) {
base::AutoLock auto_lock(va_lock_);
- VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
+ VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
// Derive a VAImage from the VASurface
- va_res = vaDeriveImage(va_display_, va_surface_id, image);
+ va_res = vaDeriveImage(backend_->GetDisplay(), va_surface_id, image);
VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed");
if (va_res != VA_STATUS_SUCCESS)
return false;
// Map the VAImage into memory
- va_res = vaMapBuffer(va_display_, image->buf, mem);
+ va_res = vaMapBuffer(backend_->GetDisplay(), image->buf, mem);
VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
if (va_res == VA_STATUS_SUCCESS)
return true;
- va_res = vaDestroyImage(va_display_, image->image_id);
+ va_res = vaDestroyImage(backend_->GetDisplay(), image->image_id);
VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
return false;
@@ -554,10 +1147,10 @@ bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) {
base::AutoLock auto_lock(va_lock_);
- VAStatus va_res = vaUnmapBuffer(va_display_, image->buf);
+ VAStatus va_res = vaUnmapBuffer(backend_->GetDisplay(), image->buf);
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
- va_res = vaDestroyImage(va_display_, image->image_id);
+ va_res = vaDestroyImage(backend_->GetDisplay(), image->image_id);
VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
}
@@ -572,10 +1165,11 @@ bool VaapiWrapper::UploadVideoFrameToSurface(
base::AutoLock auto_lock(va_lock_);
VAImage image;
- VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image);
+ VAStatus va_res =
+ vaDeriveImage(backend_->GetDisplay(), va_surface_id, &image);
VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false);
base::ScopedClosureRunner vaimage_deleter(
- base::Bind(&DestroyVAImage, va_display_, image));
+ base::Bind(&DestroyVAImage, backend_->GetDisplay(), image));
if (image.format.fourcc != VA_FOURCC_NV12) {
DVLOG(1) << "Unsupported image format: " << image.format.fourcc;
@@ -588,7 +1182,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface(
}
void* image_ptr = NULL;
- va_res = vaMapBuffer(va_display_, image.buf, &image_ptr);
+ va_res = vaMapBuffer(backend_->GetDisplay(), image.buf, &image_ptr);
VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
DCHECK(image_ptr);
@@ -609,7 +1203,7 @@ bool VaapiWrapper::UploadVideoFrameToSurface(
image.height);
}
- va_res = vaUnmapBuffer(va_display_, image.buf);
+ va_res = vaUnmapBuffer(backend_->GetDisplay(), image.buf);
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
return ret == 0;
@@ -622,12 +1216,13 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
size_t* coded_data_size) {
base::AutoLock auto_lock(va_lock_);
- VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
+ VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), sync_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
VACodedBufferSegment* buffer_segment = NULL;
- va_res = vaMapBuffer(
- va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment));
+ va_res = vaMapBuffer(backend_->GetDisplay(),
+ buffer_id,
+ reinterpret_cast<void**>(&buffer_segment));
VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
DCHECK(target_ptr);
@@ -654,10 +1249,10 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
}
}
- va_res = vaUnmapBuffer(va_display_, buffer_id);
+ va_res = vaUnmapBuffer(backend_->GetDisplay(), buffer_id);
VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
- va_res = vaDestroyBuffer(va_display_, buffer_id);
+ va_res = vaDestroyBuffer(backend_->GetDisplay(), buffer_id);
VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
DCHECK(coded_buffers_.erase(buffer_id));
@@ -668,7 +1263,14 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
// static
bool VaapiWrapper::PostSandboxInitialization() {
StubPathMap paths;
- paths[kModuleVa].push_back(kVaLib);
+
+ paths[kModuleVa].push_back("libva.so.1");
+
+#ifdef USE_X11
+ paths[kModuleVa_x11].push_back("libva-x11.so.1");
+#else
+ paths[kModuleVa_ozone].push_back("libva-drm.so.1");
+#endif
return InitializeStubs(paths);
}

Powered by Google App Engine
This is Rietveld 408576698