Signed-off-by: nablet developer <s...@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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel