[FFmpeg-devel] [PATCH 2/5] avutil/qsv: add hwcontext_qsv (QuickSync Video)

nablet developer sdk at nablet.com
Wed May 25 14:20:48 CEST 2016


Signed-off-by: nablet developer <sdk at nablet.com>
---
 libavutil/Makefile             |   3 +
 libavutil/hwcontext.c          |   3 +
 libavutil/hwcontext.h          |   1 +
 libavutil/hwcontext_internal.h |   1 +
 libavutil/hwcontext_qsv.c      | 255 +++++++++++++++++++++++++++++++++++++++++
 libavutil/hwcontext_qsv.h      |  45 ++++++++
 6 files changed, 308 insertions(+)
 create mode 100644 libavutil/hwcontext_qsv.c
 create mode 100644 libavutil/hwcontext_qsv.h

diff --git a/libavutil/Makefile b/libavutil/Makefile
index e358767..e9df0fb 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -36,6 +36,7 @@ HEADERS = adler32.h                                                     \
           hwcontext_cuda.h                                              \
           hwcontext_vaapi.h                                             \
           hwcontext_vdpau.h                                             \
+          hwcontext_qsv.h                                               \
           imgutils.h                                                    \
           intfloat.h                                                    \
           intreadwrite.h                                                \
@@ -157,6 +158,7 @@ OBJS-$(CONFIG_OPENCL)                   += opencl.o opencl_internal.o
 OBJS-$(CONFIG_QSV)                      += qsv_internal.o
 OBJS-$(CONFIG_VAAPI)                    += hwcontext_vaapi.o
 OBJS-$(CONFIG_VDPAU)                    += hwcontext_vdpau.o
+OBJS-$(CONFIG_QSV)                      += hwcontext_qsv.o
 
 OBJS += $(COMPAT_OBJS:%=../compat/%)
 
@@ -166,6 +168,7 @@ SLIBOBJS-$(HAVE_GNU_WINDRES)            += avutilres.o
 SKIPHEADERS-$(CONFIG_CUDA)             += hwcontext_cuda.h
 SKIPHEADERS-$(CONFIG_VAAPI)            += hwcontext_vaapi.h
 SKIPHEADERS-$(CONFIG_VDPAU)            += hwcontext_vdpau.h
+SKIPHEADERS-$(CONFIG_QSV)              += hwcontext_qsv.h
 SKIPHEADERS-$(HAVE_ATOMICS_GCC)        += atomic_gcc.h
 SKIPHEADERS-$(HAVE_ATOMICS_SUNCC)      += atomic_suncc.h
 SKIPHEADERS-$(HAVE_ATOMICS_WIN32)      += atomic_win32.h
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 619f21e..60a67d0 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -38,6 +38,9 @@ static const HWContextType *hw_table[] = {
 #if CONFIG_VDPAU
     &ff_hwcontext_type_vdpau,
 #endif
+#if CONFIG_QSV
+    &ff_hwcontext_type_qsv,
+#endif
     NULL,
 };
 
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 44be197..234dd95 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -28,6 +28,7 @@ enum AVHWDeviceType {
     AV_HWDEVICE_TYPE_VDPAU,
     AV_HWDEVICE_TYPE_CUDA,
     AV_HWDEVICE_TYPE_VAAPI,
+    AV_HWDEVICE_TYPE_QSV,
 };
 
 typedef struct AVHWDeviceInternal AVHWDeviceInternal;
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index f18b616..914c39a 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -99,5 +99,6 @@ struct AVHWFramesInternal {
 extern const HWContextType ff_hwcontext_type_cuda;
 extern const HWContextType ff_hwcontext_type_vaapi;
 extern const HWContextType ff_hwcontext_type_vdpau;
+extern const HWContextType ff_hwcontext_type_qsv;
 
 #endif /* AVUTIL_HWCONTEXT_INTERNAL_H */
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
new file mode 100644
index 0000000..a86c20e
--- /dev/null
+++ b/libavutil/hwcontext_qsv.c
@@ -0,0 +1,255 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "buffer.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_internal.h"
+#include "hwcontext_qsv.h"
+#include "qsv_internal.h"
+#include "mem.h"
+#include "pixdesc.h"
+#include "pixfmt.h"
+
+#include "libavutil/avstring.h"
+
+#ifdef CONFIG_VAAPI
+#define AVUTIL_QSV_LINUX_SESSION_HANDLE
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <va/va.h>
+#include <va/va_drm.h>
+
+#endif /* CONFIG_VAAPI */
+
+#define QSV_VERSION_MAJOR 1
+#define QSV_VERSION_MINOR 9
+
+typedef struct QSVDeviceContext {
+
+#ifdef AVUTIL_QSV_LINUX_SESSION_HANDLE
+    int       fd_display;
+    VADisplay va_display;
+#endif
+
+} QSVDeviceContext;
+
+static int qsv_set_display_handle(AVHWDeviceContext *hwdev)
+{
+    // this code is only required for Linux.  It searches for a valid
+    // display handle.  First in /dev/dri/renderD then in /dev/dri/card
+#ifdef AVUTIL_QSV_LINUX_SESSION_HANDLE
+    // VAAPI display handle
+    QSVDeviceContext *ctx = hwdev->internal->priv;
+    AVQSVDeviceContext *hwctx = hwdev->hwctx;
+    int ret = 0;
+    VADisplay va_dpy = NULL;
+    VAStatus va_res = VA_STATUS_SUCCESS;
+    int major_version = 0, minor_version = 0;
+    int fd = -1;
+    char adapterpath[256];
+    int adapter_num;
+
+    ctx->fd_display = -1;
+    ctx->va_display = NULL;
+
+    //search for valid graphics device
+    for (adapter_num = 0;adapter_num < 6;adapter_num++) {
+
+        if (adapter_num<3) {
+            snprintf(adapterpath,sizeof(adapterpath),
+                "/dev/dri/renderD%d", adapter_num+128);
+        } else {
+            snprintf(adapterpath,sizeof(adapterpath),
+                "/dev/dri/card%d", adapter_num-3);
+        }
+
+        fd = open(adapterpath, O_RDWR);
+        if (fd < 0) {
+            av_log(hwdev, AV_LOG_ERROR,
+                "mfx init: %s fd open failed\n", adapterpath);
+            continue;
+        }
+
+        va_dpy = vaGetDisplayDRM(fd);
+        if (!va_dpy) {
+            av_log(hwdev, AV_LOG_ERROR,
+                "mfx init: %s vaGetDisplayDRM failed\n", adapterpath);
+            close(fd);
+            continue;
+        }
+
+        va_res = vaInitialize(va_dpy, &major_version, &minor_version);
+        if (VA_STATUS_SUCCESS != va_res) {
+            av_log(hwdev, AV_LOG_ERROR,
+                "mfx init: %s vaInitialize failed\n", adapterpath);
+            close(fd);
+            fd = -1;
+            continue;
+        } else {
+            av_log(hwdev, AV_LOG_VERBOSE,
+            "mfx initialization: %s vaInitialize successful\n",adapterpath);
+            ctx->fd_display = fd;
+            ctx->va_display = va_dpy;
+            ret = MFXVideoCORE_SetHandle(hwctx->session,
+                  (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy);
+            if (ret < 0) {
+                av_log(hwdev, AV_LOG_ERROR,
+                "Error %d during set display handle\n", ret);
+                return avpriv_qsv_error(ret);
+            }
+            break;
+        }
+    }
+#endif /* AVUTIL_QSV_LINUX_SESSION_HANDLE */
+    return 0;
+}
+
+static int qsv_load_plugins(AVHWDeviceContext *hwdev)
+{
+    AVQSVDeviceContext *hwctx = hwdev->hwctx;
+    const char * load_plugins = hwctx->load_plugins;
+
+    if (load_plugins && *load_plugins) {
+        while (*load_plugins) {
+            mfxPluginUID uid;
+            int i, ret, err = 0;
+
+            char *plugin = av_get_token(&load_plugins, ":");
+            if (!plugin)
+                return AVERROR(ENOMEM);
+            if (strlen(plugin) != 2 * sizeof(uid.Data)) {
+                av_log(hwdev, AV_LOG_ERROR, "Invalid plugin UID length\n");
+                err = AVERROR(EINVAL);
+                goto load_plugin_fail;
+            }
+
+            for (i = 0; i < sizeof(uid.Data); i++) {
+                err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
+                if (err != 1) {
+                    av_log(hwdev, AV_LOG_ERROR, "Invalid plugin UID\n");
+                    err = AVERROR(EINVAL);
+                    goto load_plugin_fail;
+                }
+
+            }
+
+            ret = MFXVideoUSER_Load(hwctx->session, &uid, 1);
+            if (ret < 0) {
+                av_log(hwdev, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
+                       plugin);
+                err = avpriv_qsv_error(ret);
+                goto load_plugin_fail;
+            }
+
+            if (*load_plugins)
+                load_plugins++;
+load_plugin_fail:
+            av_freep(&plugin);
+            if (err < 0)
+                return err;
+        }
+    }
+    return 0;
+}
+
+static int qsv_device_init(AVHWDeviceContext *hwdev)
+{
+    QSVDeviceContext *ctx = hwdev->internal->priv;
+    AVQSVDeviceContext *hwctx = hwdev->hwctx;
+
+    mfxIMPL impl = MFX_IMPL_AUTO_ANY;
+    mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+    const char *desc;
+    int ret;
+
+    ret = MFXInit(impl, &ver, &hwctx->session);
+    if (ret < 0) {
+        av_log(hwdev, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
+        return avpriv_qsv_error(ret);
+    }
+    ret = qsv_set_display_handle(hwdev);
+    if (ret < 0)
+        return ret;
+
+    ret = qsv_load_plugins(hwdev);
+    if (ret < 0)
+        return ret;
+
+    MFXQueryIMPL(hwctx->session, &impl);
+
+    switch (MFX_IMPL_BASETYPE(impl)) {
+    case MFX_IMPL_SOFTWARE:
+        desc = "software";
+        break;
+    case MFX_IMPL_HARDWARE:
+    case MFX_IMPL_HARDWARE2:
+    case MFX_IMPL_HARDWARE3:
+    case MFX_IMPL_HARDWARE4:
+        desc = "hardware accelerated";
+        break;
+    default:
+        desc = "unknown";
+    }
+
+    av_log(hwdev, AV_LOG_VERBOSE,
+           "Initialized an internal MFX session using %s implementation\n",
+           desc);
+
+    return 0;
+}
+
+static void qsv_device_uninit(AVHWDeviceContext *hwdev)
+{
+    QSVDeviceContext *ctx = hwdev->internal->priv;
+    AVQSVDeviceContext *hwctx = hwdev->hwctx;
+
+    if (hwctx->session) {
+        MFXClose(hwctx->session);
+        hwctx->session = NULL;
+    }
+#ifdef AVUTIL_QSV_LINUX_SESSION_HANDLE
+    if (ctx->va_display) {
+        vaTerminate(ctx->va_display);
+        ctx->va_display = NULL;
+    }
+    if (ctx->fd_display > 0) {
+        close(ctx->fd_display);
+        ctx->fd_display = -1;
+    }
+#endif
+}
+
+const HWContextType ff_hwcontext_type_qsv = {
+    .type                 = AV_HWDEVICE_TYPE_QSV,
+    .name                 = "QSV",
+
+    .device_hwctx_size    = sizeof(AVQSVDeviceContext),
+    .device_priv_size     = sizeof(QSVDeviceContext),
+
+    .device_init          = qsv_device_init,
+    .device_uninit        = qsv_device_uninit,
+
+    .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE },
+};
diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h
new file mode 100644
index 0000000..99a3501
--- /dev/null
+++ b/libavutil/hwcontext_qsv.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef AVUTIL_HWCONTEXT_QSV_H
+#define AVUTIL_HWCONTEXT_QSV_H
+
+#include <mfx/mfxvideo.h>
+#include <mfx/mfxplugin.h>
+
+#include "pixfmt.h"
+
+/**
+ * @file
+ * An API-specific header for AV_HWDEVICE_TYPE_QSV.
+ */
+
+/**
+ * This struct is allocated as AVHWDeviceContext.hwctx
+ */
+typedef struct AVQSVDeviceContext {
+    mfxSession session;
+    const char * load_plugins;
+} AVQSVDeviceContext;
+
+/**
+ * AVHWFramesContext.hwctx is currently not used
+ */
+
+#endif /* AVUTIL_HWCONTEXT_QSV_H */
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list