From ce91bab70f69acc1a7e5705af95cc6fa89765825 Mon Sep 17 00:00:00 2001 From: Ivan Uskov Date: Mon, 13 Jul 2015 10:17:54 -0400 Subject: [PATCH] libavcodec/qsv.c: Issue fixed: QSV engine does not release display handler under linux platform. Reviewed-by: Gwenole Beauchesne Signed-off-by: Michael Niedermayer --- libavcodec/qsv.c | 38 +++++++++++++++++++++++++++++++------- libavcodec/qsv_internal.h | 11 ++++++++++- libavcodec/qsvdec.c | 10 ++++------ libavcodec/qsvdec.h | 2 +- libavcodec/qsvenc.c | 11 +++++------ libavcodec/qsvenc.h | 2 +- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 697af872a6..4c8e6b01a9 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -85,7 +85,7 @@ int ff_qsv_error(int mfx_err) return AVERROR_UNKNOWN; } } -static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session) +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 @@ -99,6 +99,9 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session) 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++) { @@ -135,7 +138,9 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session) } else { av_log(avctx, AV_LOG_VERBOSE, "mfx initialization: %s vaInitialize successful\n",adapterpath); - ret = MFXVideoCORE_SetHandle(session, + 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, @@ -163,7 +168,7 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session) * @param avctx ffmpeg metadata for this codec context * @param session the MSDK session used */ -int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, +int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *load_plugins) { mfxIMPL impl = MFX_IMPL_AUTO_ANY; @@ -172,17 +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); } - ret = ff_qsv_set_display_handle(avctx, *session); + ret = ff_qsv_set_display_handle(avctx, qs); if (ret < 0) return ret; - MFXQueryIMPL(*session, &impl); + MFXQueryIMPL(qs->session, &impl); switch (MFX_IMPL_BASETYPE(impl)) { case MFX_IMPL_SOFTWARE: @@ -222,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); @@ -243,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; +} diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index ee48a0fb9d..3d949dc0fa 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -58,6 +58,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; + /** * Convert a libmfx error code into a ffmpeg error code. */ @@ -65,7 +73,8 @@ int ff_qsv_error(int mfx_err); int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id); -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); #endif /* AVCODEC_QSV_INTERNAL_H */ diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 67e8ef0ce5..52df028ce3 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -51,13 +51,13 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format) static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session) { if (!session) { - if (!q->internal_session) { - int ret = ff_qsv_init_internal_session(avctx, &q->internal_session, NULL); + if (!q->internal_qs.session) { + int ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, NULL); if (ret < 0) return ret; } - q->session = q->internal_session; + q->session = q->internal_qs.session; } else { q->session = session; } @@ -282,9 +282,7 @@ int ff_qsv_decode_close(QSVContext *q) av_freep(&cur); cur = q->work_frames; } - - if (q->internal_session) - MFXClose(q->internal_session); + ff_qsv_close_internal_session(&q->internal_qs); return 0; } diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 373cc72b2a..210e9a9786 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -40,7 +40,7 @@ typedef struct QSVContext { // the session we allocated internally, in case the caller did not provide // one - mfxSession internal_session; + QSVSession internal_qs; /** * a linked list of frames currently being used by QSV diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 3f376399c9..576bf68e18 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -217,12 +217,12 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) } if (!q->session) { - 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; } ret = init_video_param(avctx, q); @@ -460,10 +460,9 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) QSVFrame *cur; MFXVideoENCODE_Close(q->session); - if (q->internal_session) - MFXClose(q->internal_session); - q->session = NULL; - q->internal_session = NULL; + q->session = NULL; + + ff_qsv_close_internal_session(&q->internal_qs); cur = q->work_frames; while (cur) { diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 8195d9b049..4789675290 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -39,7 +39,7 @@ typedef struct QSVEncContext { QSVFrame *work_frames; mfxSession session; - mfxSession internal_session; + QSVSession internal_qs; int packet_size; int width_align;