| 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 2b4b33349aa12a3d77ed7680c06f18ad6e1bd775..5c69facc458f79dc5c12598c2ad1ceae77568550 100644
|
| --- a/content/common/gpu/media/vaapi_wrapper.cc
|
| +++ b/content/common/gpu/media/vaapi_wrapper.cc
|
| @@ -12,16 +12,29 @@
|
| #include "base/numerics/safe_conversions.h"
|
| // Auto-generated for dlopen libva libraries
|
| #include "content/common/gpu/media/va_stubs.h"
|
| +#include "content/common/gpu/media/vaapi_picture.h"
|
| #include "third_party/libyuv/include/libyuv.h"
|
| +#include "ui/gl/gl_bindings.h"
|
| +#if defined(USE_X11)
|
| +#include "content/common/gpu/media/vaapi_tfp_picture.h"
|
| +#include "ui/gfx/x/x11_types.h"
|
| +#else
|
| +#include "content/common/gpu/media/vaapi_drm_picture.h"
|
| +#include "third_party/libva/va/drm/va_drm.h"
|
| +#include "third_party/libva/va/va_drmcommon.h"
|
| +#include "ui/ozone/public/ozone_platform.h"
|
| +#include "ui/ozone/public/surface_factory_ozone.h"
|
| +#endif // USE_X11
|
|
|
| using content_common_gpu_media::kModuleVa;
|
| +#if defined(USE_X11)
|
| +using content_common_gpu_media::kModuleVa_x11;
|
| +#else
|
| +using content_common_gpu_media::kModuleVa_drm;
|
| +#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 { \
|
| LOG(ERROR) << err_msg \
|
| @@ -43,8 +56,14 @@ static const base::FilePath::CharType kVaLib[] =
|
| } \
|
| } while (0)
|
|
|
| +namespace gfx {
|
| +class GLContextGLX;
|
| +}
|
| +
|
| namespace content {
|
|
|
| +class VaapiWrapper;
|
| +
|
| // Config attributes common for both encode and decode.
|
| static const VAConfigAttrib kCommonVAConfigAttribs[] = {
|
| {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
|
| @@ -122,9 +141,10 @@ static VAProfile ProfileToVAProfile(
|
| return va_profile;
|
| }
|
|
|
| -VASurface::VASurface(VASurfaceID va_surface_id, const ReleaseCB& release_cb)
|
| - : va_surface_id_(va_surface_id),
|
| - release_cb_(release_cb) {
|
| +VASurface::VASurface(VASurfaceID va_surface_id,
|
| + const gfx::Size& size,
|
| + const ReleaseCB& release_cb)
|
| + : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) {
|
| DCHECK(!release_cb_.is_null());
|
| }
|
|
|
| @@ -135,37 +155,38 @@ VASurface::~VASurface() {
|
| VaapiWrapper::VaapiWrapper()
|
| : va_display_(NULL),
|
| va_config_id_(VA_INVALID_ID),
|
| - va_context_id_(VA_INVALID_ID) {
|
| + va_context_id_(VA_INVALID_ID),
|
| + va_vpp_config_id_(VA_INVALID_ID),
|
| + va_vpp_context_id_(VA_INVALID_ID),
|
| + va_vpp_buffer_id_(VA_INVALID_ID) {
|
| }
|
|
|
| VaapiWrapper::~VaapiWrapper() {
|
| DestroyPendingBuffers();
|
| DestroyCodedBuffers();
|
| DestroySurfaces();
|
| + DeinitializeVpp();
|
| Deinitialize();
|
| }
|
|
|
| scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
|
| CodecMode mode,
|
| media::VideoCodecProfile profile,
|
| - Display* x_display,
|
| 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))
|
| - vaapi_wrapper.reset();
|
| + if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb))
|
| + vaapi_wrapper = NULL;
|
|
|
| return vaapi_wrapper.Pass();
|
| }
|
|
|
| std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles(
|
| - Display* x_display,
|
| const base::Closure& report_error_to_uma_cb) {
|
| std::vector<media::VideoCodecProfile> supported_profiles;
|
|
|
| scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper());
|
| - if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) {
|
| + if (!wrapper->VaInitialize(report_error_to_uma_cb)) {
|
| return supported_profiles;
|
| }
|
|
|
| @@ -200,8 +221,7 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
|
| DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
|
| }
|
|
|
| -bool VaapiWrapper::VaInitialize(Display* x_display,
|
| - const base::Closure& report_error_to_uma_cb) {
|
| +bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
|
| static bool vaapi_functions_initialized = PostSandboxInitialization();
|
| if (!vaapi_functions_initialized) {
|
| LOG(ERROR) << "Failed to initialize VAAPI libs";
|
| @@ -212,7 +232,15 @@ bool VaapiWrapper::VaInitialize(Display* x_display,
|
|
|
| base::AutoLock auto_lock(va_lock_);
|
|
|
| - va_display_ = vaGetDisplay(x_display);
|
| +#if defined(USE_X11)
|
| + va_display_ = vaGetDisplay(gfx::GetXDisplay());
|
| +#else
|
| + ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
|
| + ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
|
| +
|
| + va_display_ = vaGetDisplayDRM(factory->GetDrmFd());
|
| +#endif // USE_X11
|
| +
|
| if (!vaDisplayIsValid(va_display_)) {
|
| LOG(ERROR) << "Could not get a valid VA display";
|
| return false;
|
| @@ -308,9 +336,8 @@ bool VaapiWrapper::AreAttribsSupported(
|
|
|
| bool VaapiWrapper::Initialize(CodecMode mode,
|
| media::VideoCodecProfile profile,
|
| - Display* x_display,
|
| const base::Closure& report_error_to_uma_cb) {
|
| - if (!VaInitialize(x_display, report_error_to_uma_cb))
|
| + if (!VaInitialize(report_error_to_uma_cb))
|
| return false;
|
| std::vector<VAProfile> supported_va_profiles;
|
| if (!GetSupportedVaProfiles(&supported_va_profiles))
|
| @@ -364,7 +391,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_);
|
| @@ -423,6 +450,67 @@ void VaapiWrapper::DestroySurfaces() {
|
| va_context_id_ = VA_INVALID_ID;
|
| }
|
|
|
| +scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface(
|
| + unsigned int va_format,
|
| + const gfx::Size& size,
|
| + VASurfaceAttrib* va_attribs,
|
| + size_t num_va_attribs) {
|
| + base::AutoLock auto_lock(va_lock_);
|
| + VASurfaceID va_surface_id;
|
| + scoped_refptr<VASurface> va_surface;
|
| +
|
| + VAStatus va_res = vaCreateSurfaces(va_display_,
|
| + va_format,
|
| + size.width(),
|
| + size.height(),
|
| + &va_surface_id,
|
| + 1,
|
| + va_attribs,
|
| + num_va_attribs);
|
| + VA_SUCCESS_OR_RETURN(
|
| + va_res, "Failed to create unowned VASurface", va_surface);
|
| +
|
| + va_surface = new VASurface(
|
| + va_surface_id,
|
| + size,
|
| + base::Bind(&VaapiWrapper::DestroyUnownedSurface, AsWeakPtr()));
|
| +
|
| + return va_surface;
|
| +}
|
| +
|
| +linked_ptr<VaapiPicture> VaapiWrapper::CreatePicture(
|
| + gfx::GLContext* gl_context,
|
| + const base::Callback<bool(void)> make_context_current,
|
| + int32 picture_buffer_id,
|
| + uint32 texture_id,
|
| + const gfx::Size& size) {
|
| + linked_ptr<VaapiPicture> picture;
|
| +#if defined(USE_X11)
|
| + picture.reset(
|
| + new VaapiTFPPicture(AsWeakPtr(),
|
| + reinterpret_cast<gfx::GLContextGLX*>(gl_context),
|
| + make_context_current,
|
| + picture_buffer_id,
|
| + texture_id,
|
| + size));
|
| +#else
|
| + picture.reset(new VaapiDrmPicture(
|
| + AsWeakPtr(), make_context_current, picture_buffer_id, texture_id, size));
|
| +#endif // USE_X11
|
| +
|
| + if (!picture->Initialize())
|
| + picture.reset();
|
| +
|
| + return picture;
|
| +}
|
| +
|
| +void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface) {
|
| + base::AutoLock auto_lock(va_lock_);
|
| +
|
| + VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface, 1);
|
| + VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on output surface failed");
|
| +}
|
| +
|
| bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
|
| size_t size,
|
| void* buffer) {
|
| @@ -574,25 +662,6 @@ bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
|
| return result;
|
| }
|
|
|
| -bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
|
| - Pixmap x_pixmap,
|
| - gfx::Size dest_size) {
|
| - base::AutoLock auto_lock(va_lock_);
|
| -
|
| - VAStatus va_res = vaSyncSurface(va_display_, 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_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
|
| - return true;
|
| -}
|
| -
|
| bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
|
| VAImage* image,
|
| void** mem) {
|
| @@ -733,10 +802,163 @@ bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
|
| return buffer_segment == NULL;
|
| }
|
|
|
| +bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src,
|
| + const gfx::Size& src_size,
|
| + VASurfaceID va_surface_id_dest,
|
| + const gfx::Size& dest_size) {
|
| + base::AutoLock auto_lock(va_lock_);
|
| +
|
| + // Initialize the post processing engine if not already done.
|
| + if (va_vpp_buffer_id_ == VA_INVALID_ID)
|
| + if (!InitializeVpp_Locked())
|
| + return false;
|
| +
|
| + VAProcPipelineParameterBuffer* pipeline_param;
|
| + VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_,
|
| + va_vpp_buffer_id_,
|
| + reinterpret_cast<void**>(&pipeline_param)),
|
| + "Couldn't map vpp buffer",
|
| + false);
|
| +
|
| + memset(pipeline_param, 0, sizeof *pipeline_param);
|
| +
|
| + VARectangle input_region;
|
| + input_region.x = input_region.y = 0;
|
| + input_region.width = src_size.width();
|
| + input_region.height = src_size.height();
|
| + pipeline_param->surface_region = &input_region;
|
| + pipeline_param->surface = va_surface_id_src;
|
| + pipeline_param->surface_color_standard = VAProcColorStandardNone;
|
| +
|
| + VARectangle output_region;
|
| + 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;
|
| +
|
| + VA_SUCCESS_OR_RETURN(vaUnmapBuffer(va_display_, va_vpp_buffer_id_),
|
| + "Couldn't unmap vpp buffer",
|
| + false);
|
| +
|
| + VA_SUCCESS_OR_RETURN(
|
| + vaBeginPicture(va_display_, va_vpp_context_id_, va_surface_id_dest),
|
| + "Couldn't begin picture",
|
| + false);
|
| +
|
| + VA_SUCCESS_OR_RETURN(
|
| + vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1),
|
| + "Couldn't render picture",
|
| + false);
|
| +
|
| + VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_),
|
| + "Couldn't end picture",
|
| + false);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool VaapiWrapper::InitializeVpp_Locked() {
|
| + va_lock_.AssertAcquired();
|
| +
|
| + VA_SUCCESS_OR_RETURN(vaCreateConfig(va_display_,
|
| + VAProfileNone,
|
| + VAEntrypointVideoProc,
|
| + NULL,
|
| + 0,
|
| + &va_vpp_config_id_),
|
| + "Couldn't create config",
|
| + false);
|
| +
|
| + // The size of the picture for the context is irrelevant in the case
|
| + // of the VPP, just passing 1x1.
|
| + VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_,
|
| + va_vpp_config_id_,
|
| + 1,
|
| + 1,
|
| + 0,
|
| + NULL,
|
| + 0,
|
| + &va_vpp_context_id_),
|
| + "Couldn't create context",
|
| + false);
|
| +
|
| + VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_,
|
| + va_vpp_context_id_,
|
| + VAProcPipelineParameterBufferType,
|
| + sizeof(VAProcPipelineParameterBuffer),
|
| + 1,
|
| + NULL,
|
| + &va_vpp_buffer_id_),
|
| + "Couldn't create buffer",
|
| + false);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void VaapiWrapper::DeinitializeVpp() {
|
| + base::AutoLock auto_lock(va_lock_);
|
| + DeinitializeVpp_Locked();
|
| +}
|
| +
|
| +void VaapiWrapper::DeinitializeVpp_Locked() {
|
| + va_lock_.AssertAcquired();
|
| +
|
| + if (va_vpp_buffer_id_ != VA_INVALID_ID) {
|
| + vaDestroyBuffer(va_display_, va_vpp_buffer_id_);
|
| + va_vpp_buffer_id_ = VA_INVALID_ID;
|
| + }
|
| + if (va_vpp_context_id_ != VA_INVALID_ID) {
|
| + vaDestroyContext(va_display_, va_vpp_context_id_);
|
| + va_vpp_context_id_ = VA_INVALID_ID;
|
| + }
|
| + if (va_vpp_config_id_ != VA_INVALID_ID) {
|
| + vaDestroyConfig(va_display_, va_vpp_config_id_);
|
| + va_vpp_config_id_ = VA_INVALID_ID;
|
| + }
|
| +}
|
| +
|
| +#if defined(USE_X11)
|
| +bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
|
| + Pixmap x_pixmap,
|
| + gfx::Size dest_size) {
|
| + base::AutoLock auto_lock(va_lock_);
|
| +
|
| + VAStatus va_res = vaSyncSurface(va_display_, 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_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
|
| + return true;
|
| +}
|
| +#endif // USE_X11
|
| +
|
| // static
|
| bool VaapiWrapper::PostSandboxInitialization() {
|
| StubPathMap paths;
|
| - paths[kModuleVa].push_back(kVaLib);
|
| +
|
| + paths[kModuleVa].push_back("libva.so.1");
|
| +
|
| +#if defined(USE_X11)
|
| + paths[kModuleVa_x11].push_back("libva-x11.so.1");
|
| +#else
|
| + paths[kModuleVa_drm].push_back("libva-drm.so.1");
|
| +#endif
|
|
|
| return InitializeStubs(paths);
|
| }
|
|
|