diff options
Diffstat (limited to 'libavcodec/qsv.c')
-rw-r--r-- | libavcodec/qsv.c | 121 |
1 files changed, 113 insertions, 8 deletions
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index e08518b..11d453d 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -1,20 +1,20 @@ /* * Intel MediaSDK QSV encoder/decoder shared code * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -85,8 +85,90 @@ int ff_qsv_error(int mfx_err) return AVERROR_UNKNOWN; } } +static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs) +{ + // 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 AVCODEC_QSV_LINUX_SESSION_HANDLE + // VAAPI display handle + 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; + + qs->fd_display = -1; + qs->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(avctx, AV_LOG_ERROR, + "mfx init: %s fd open failed\n", adapterpath); + continue; + } -int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, + va_dpy = vaGetDisplayDRM(fd); + if (!va_dpy) { + av_log(avctx, 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(avctx, AV_LOG_ERROR, + "mfx init: %s vaInitialize failed\n", adapterpath); + close(fd); + fd = -1; + continue; + } else { + av_log(avctx, AV_LOG_VERBOSE, + "mfx initialization: %s vaInitialize successful\n",adapterpath); + qs->fd_display = fd; + qs->va_display = va_dpy; + ret = MFXVideoCORE_SetHandle(qs->session, + (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)va_dpy); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error %d during set display handle\n", ret); + return ff_qsv_error(ret); + } + break; + } + } +#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE + return 0; +} +/** + * @brief Initialize a MSDK session + * + * Media SDK is based on sessions, so this is the prerequisite + * initialization for HW acceleration. For Windows the session is + * complete and ready to use, for Linux a display handle is + * required. For releases of Media Server Studio >= 2015 R4 the + * render nodes interface is preferred (/dev/dri/renderD). + * Using Media Server Studio 2015 R4 or newer is recommended + * but the older /dev/dri/card interface is also searched + * for broader compatibility. + * + * @param avctx ffmpeg metadata for this codec context + * @param session the MSDK session used + */ +int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins) { mfxIMPL impl = MFX_IMPL_AUTO_ANY; @@ -95,12 +177,16 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, const char *desc; int ret; - ret = MFXInit(impl, &ver, session); + ret = MFXInit(impl, &ver, &qs->session); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n"); return ff_qsv_error(ret); } + ret = ff_qsv_set_display_handle(avctx, qs); + if (ret < 0) + return ret; + if (load_plugins && *load_plugins) { while (*load_plugins) { mfxPluginUID uid; @@ -125,7 +211,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, } - ret = MFXVideoUSER_Load(*session, &uid, 1); + ret = MFXVideoUSER_Load(qs->session, &uid, 1); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n", plugin); @@ -142,7 +228,7 @@ load_plugin_fail: } } - MFXQueryIMPL(*session, &impl); + MFXQueryIMPL(qs->session, &impl); switch (MFX_IMPL_BASETYPE(impl)) { case MFX_IMPL_SOFTWARE: @@ -164,3 +250,22 @@ load_plugin_fail: return 0; } + +int ff_qsv_close_internal_session(QSVSession *qs) +{ + if (qs->session) { + MFXClose(qs->session); + qs->session = NULL; + } +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE + if (qs->va_display) { + vaTerminate(qs->va_display); + qs->va_display = NULL; + } + if (qs->fd_display > 0) { + close(qs->fd_display); + qs->fd_display = -1; + } +#endif + return 0; +} |