[FFmpeg-devel] [PATCH 1/2] lavc/qsv: Fix MSDK initialization failure in system memory mode
Zhong Li
zhong.li at intel.com
Wed Sep 4 18:40:41 EEST 2019
MSDK does not create internal acceleration device on Linux,
So MFXVideoCORE_SetHandle() is necessary.
It has been added for ff_qsv_init_session_device().
But missed for ff_qsv_init_internal_session() due to commit
1f26a23 overwrited commit db89f45
Fix #7030
Signed-off-by: Zhong Li <zhong.li at intel.com>
---
libavcodec/qsv.c | 105 ++++++++++++++++++++++++++++++++++++++++++++--
libavcodec/qsv_internal.h | 27 +++++++++++-
libavcodec/qsvdec.c | 29 +++++++------
libavcodec/qsvdec.h | 2 +-
libavcodec/qsvenc.c | 17 ++++----
libavcodec/qsvenc.h | 2 +-
6 files changed, 151 insertions(+), 31 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 65ad070..126182b 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -348,7 +348,79 @@ load_plugin_fail:
}
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+//This code is only required for Linux since a display handle is required.
+//For Windows the session is complete and ready to use.
+//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.
+
+#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
+static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
+{
+ // 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;
+ }
+
+ 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) {
+ return ff_qsv_print_error(avctx, ret, "Error %d during set display handle\n");
+ }
+ break;
+ }
+ }
+ return 0;
+}
+#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
+
+int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
const char *load_plugins)
{
mfxIMPL impl = MFX_IMPL_AUTO_ANY;
@@ -357,18 +429,24 @@ 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)
return ff_qsv_print_error(avctx, ret,
"Error initializing an internal MFX session");
- ret = qsv_load_plugins(*session, load_plugins, avctx);
+#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
+ ret = ff_qsv_set_display_handle(avctx, qs);
+ if (ret < 0)
+ return ret;
+#endif
+
+ ret = qsv_load_plugins(qs->session, load_plugins, avctx);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
return ret;
}
- MFXQueryIMPL(*session, &impl);
+ MFXQueryIMPL(qs->session, &impl);
switch (MFX_IMPL_BASETYPE(impl)) {
case MFX_IMPL_SOFTWARE:
@@ -758,3 +836,22 @@ int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession,
*psession = session;
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;
+}
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index c50e9c7..7678114 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -21,6 +21,21 @@
#ifndef AVCODEC_QSV_INTERNAL_H
#define AVCODEC_QSV_INTERNAL_H
+#if CONFIG_VAAPI
+#define AVCODEC_QSV_LINUX_SESSION_HANDLE
+#endif //CONFIG_VAAPI
+
+#ifdef AVCODEC_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
+
#include <mfx/mfxvideo.h>
#include "libavutil/frame.h"
@@ -64,6 +79,14 @@ typedef struct QSVFrame {
struct QSVFrame *next;
} QSVFrame;
+typedef struct QSVSession {
+ mfxSession session;
+#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE
+ int fd_display;
+ VADisplay va_display;
+#endif
+} QSVSession;
+
typedef struct QSVFramesContext {
AVBufferRef *hw_frames_ctx;
void *logctx;
@@ -99,9 +122,11 @@ enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type);
enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct);
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
const char *load_plugins);
+int ff_qsv_close_internal_session(QSVSession *qs);
+
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
AVBufferRef *device_ref, const char *load_plugins);
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index eef4fe7..2fce478 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -62,9 +62,9 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
if (session) {
q->session = session;
} else if (hw_frames_ref) {
- if (q->internal_session) {
- MFXClose(q->internal_session);
- q->internal_session = NULL;
+ if (q->internal_qs.session) {
+ MFXClose(q->internal_qs.session);
+ q->internal_qs.session = NULL;
}
av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
@@ -72,7 +72,7 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
if (!q->frames_ctx.hw_frames_ctx)
return AVERROR(ENOMEM);
- ret = ff_qsv_init_session_frames(avctx, &q->internal_session,
+ ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
&q->frames_ctx, q->load_plugins,
q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY);
if (ret < 0) {
@@ -80,28 +80,28 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
return ret;
}
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
} else if (hw_device_ref) {
- if (q->internal_session) {
- MFXClose(q->internal_session);
- q->internal_session = NULL;
+ if (q->internal_qs.session) {
+ MFXClose(q->internal_qs.session);
+ q->internal_qs.session = NULL;
}
- ret = ff_qsv_init_session_device(avctx, &q->internal_session,
+ ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
hw_device_ref, q->load_plugins);
if (ret < 0)
return ret;
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
} else {
- if (!q->internal_session) {
- ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
+ if (!q->internal_qs.session) {
+ ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
q->load_plugins);
if (ret < 0)
return ret;
}
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
}
/* make sure the decoder is uninitialized */
@@ -529,8 +529,7 @@ int ff_qsv_decode_close(QSVContext *q)
av_fifo_free(q->async_fifo);
q->async_fifo = NULL;
- if (q->internal_session)
- MFXClose(q->internal_session);
+ ff_qsv_close_internal_session(&q->internal_qs);
av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
av_buffer_unref(&q->frames_ctx.mids_buf);
diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h
index c057bc6..64dc8d2 100644
--- a/libavcodec/qsvdec.h
+++ b/libavcodec/qsvdec.h
@@ -42,7 +42,7 @@ typedef struct QSVContext {
// the session we allocated internally, in case the caller did not provide
// one
- mfxSession internal_session;
+ QSVSession internal_qs;
QSVFramesContext frames_ctx;
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 9bf8574..207cdc1 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -954,7 +954,7 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
if (!q->frames_ctx.hw_frames_ctx)
return AVERROR(ENOMEM);
- ret = ff_qsv_init_session_frames(avctx, &q->internal_session,
+ ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session,
&q->frames_ctx, q->load_plugins,
q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY);
if (ret < 0) {
@@ -962,21 +962,21 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
return ret;
}
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
} else if (avctx->hw_device_ctx) {
- ret = ff_qsv_init_session_device(avctx, &q->internal_session,
+ ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session,
avctx->hw_device_ctx, q->load_plugins);
if (ret < 0)
return ret;
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
} else {
- ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
+ ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
q->load_plugins);
if (ret < 0)
return ret;
- q->session = q->internal_session;
+ q->session = q->internal_qs.session;
}
return 0;
@@ -1507,10 +1507,9 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
if (q->session)
MFXVideoENCODE_Close(q->session);
- if (q->internal_session)
- MFXClose(q->internal_session);
+
q->session = NULL;
- q->internal_session = NULL;
+ ff_qsv_close_internal_session(&q->internal_qs);
av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
av_buffer_unref(&q->frames_ctx.mids_buf);
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index f2f4d38..ec8b541 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -102,7 +102,7 @@ typedef struct QSVEncContext {
QSVFrame *work_frames;
mfxSession session;
- mfxSession internal_session;
+ QSVSession internal_qs;
int packet_size;
int width_align;
--
2.7.4
More information about the ffmpeg-devel
mailing list