[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