hwcontext_vaapi: implement device creation
authorAnton Khirnov <anton@khirnov.net>
Thu, 19 May 2016 17:19:20 +0000 (19:19 +0200)
committerAnton Khirnov <anton@khirnov.net>
Thu, 26 May 2016 13:40:34 +0000 (15:40 +0200)
libavutil/hwcontext_vaapi.c

index 1a385ba..4563e14 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config.h"
+
+#if HAVE_VAAPI_X11
+#   include <va/va_x11.h>
+#endif
+#if HAVE_VAAPI_DRM
+#   include <va/va_drm.h>
+#endif
+
+#include <fcntl.h>
+#if HAVE_UNISTD_H
+#   include <unistd.h>
+#endif
+
+
 #include "avassert.h"
 #include "buffer.h"
 #include "common.h"
 #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,