summaryrefslogtreecommitdiff
path: root/libavcodec/qsv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/qsv.c')
-rw-r--r--libavcodec/qsv.c121
1 files changed, 113 insertions, 8 deletions
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index ee6b262f31..4c8e6b01a9 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,13 +177,17 @@ 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);
}
- MFXQueryIMPL(*session, &impl);
+ ret = ff_qsv_set_display_handle(avctx, qs);
+ if (ret < 0)
+ return ret;
+
+ MFXQueryIMPL(qs->session, &impl);
switch (MFX_IMPL_BASETYPE(impl)) {
case MFX_IMPL_SOFTWARE:
@@ -141,7 +227,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);
@@ -162,3 +248,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;
+}