From 551fc5c3fa562cfbef1e81b707c163b7833c1a72 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 19 May 2016 19:19:20 +0200 Subject: hwcontext_vaapi: implement device creation --- libavutil/hwcontext_vaapi.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'libavutil/hwcontext_vaapi.c') diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 1a385ba514..4563e147f6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -16,6 +16,21 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + +#if HAVE_VAAPI_X11 +# include +#endif +#if HAVE_VAAPI_DRM +# include +#endif + +#include +#if HAVE_UNISTD_H +# include +#endif + + #include "avassert.h" #include "buffer.h" #include "common.h" @@ -26,6 +41,14 @@ #include "pixdesc.h" #include "pixfmt.h" +typedef struct VAAPIDevicePriv { +#if HAVE_VAAPI_X11 + Display *x11_display; +#endif + + int drm_fd; +} VAAPIDevicePriv; + typedef struct VAAPISurfaceFormat { enum AVPixelFormat pix_fmt; VAImageFormat image_format; @@ -823,6 +846,105 @@ fail: return err; } +static void vaapi_device_free(AVHWDeviceContext *ctx) +{ + AVVAAPIDeviceContext *hwctx = ctx->hwctx; + VAAPIDevicePriv *priv = ctx->user_opaque; + + if (hwctx->display) + vaTerminate(hwctx->display); + +#if HAVE_VAAPI_X11 + if (priv->x11_display) + XCloseDisplay(priv->x11_display); +#endif + + if (priv->drm_fd >= 0) + close(priv->drm_fd); + + av_freep(&priv); +} + +static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + AVVAAPIDeviceContext *hwctx = ctx->hwctx; + VAAPIDevicePriv *priv; + VADisplay display = 0; + VAStatus vas; + int major, minor; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) + return AVERROR(ENOMEM); + + priv->drm_fd = -1; + + ctx->user_opaque = priv; + ctx->free = vaapi_device_free; + +#if HAVE_VAAPI_X11 + if (!display && !(device && device[0] == '/')) { + // Try to open the device as an X11 display. + priv->x11_display = XOpenDisplay(device); + if (!priv->x11_display) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display " + "%s.\n", XDisplayName(device)); + } else { + display = vaGetDisplay(priv->x11_display); + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from X11 display %s.\n", XDisplayName(device)); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "X11 display %s.\n", XDisplayName(device)); + } + } +#endif + +#if HAVE_VAAPI_DRM + if (!display && device) { + // Try to open the device as a DRM path. + priv->drm_fd = open(device, O_RDWR); + if (priv->drm_fd < 0) { + av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n", + device); + } else { + display = vaGetDisplayDRM(priv->drm_fd); + if (!display) { + av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display " + "from DRM device %s.\n", device); + return AVERROR_UNKNOWN; + } + + av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via " + "DRM device %s.\n", device); + } + } +#endif + + if (!display) { + av_log(ctx, AV_LOG_ERROR, "No VA display found for " + "device: %s.\n", device ? device : ""); + return AVERROR(EINVAL); + } + + hwctx->display = display; + + vas = vaInitialize(display, &major, &minor); + if (vas != VA_STATUS_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI " + "connection: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: " + "version %d.%d\n", major, minor); + + return 0; +} + const HWContextType ff_hwcontext_type_vaapi = { .type = AV_HWDEVICE_TYPE_VAAPI, .name = "VAAPI", @@ -833,6 +955,7 @@ const HWContextType ff_hwcontext_type_vaapi = { .frames_hwctx_size = sizeof(AVVAAPIFramesContext), .frames_priv_size = sizeof(VAAPIFramesContext), + .device_create = &vaapi_device_create, .device_init = &vaapi_device_init, .device_uninit = &vaapi_device_uninit, .frames_get_constraints = &vaapi_frames_get_constraints, -- cgit v1.2.3