[FFmpeg-devel] [PATCH 1/2] lavc/qsv: Fix MSDK initialization failure in system memory mode
Li, Zhong
zhong.li at intel.com
Tue Sep 10 10:22:04 EEST 2019
> From: Li, Zhong
> Sent: Wednesday, September 4, 2019 11:41 PM
> To: ffmpeg-devel at ffmpeg.org
> Cc: Li, Zhong <zhong.li at intel.com>
> Subject: [PATCH 1/2] lavc/qsv: Fix MSDK initialization failure in system memory
> mode
>
> 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
Will apply if no objection.
More information about the ffmpeg-devel
mailing list