[FFmpeg-cvslog] libavcodec/qsv.c: Issue fixed: QSV engine does not release display handler under linux platform.

Ivan Uskov git at videolan.org
Tue Jul 14 02:13:09 CEST 2015


ffmpeg | branch: master | Ivan Uskov <ivan.uskov at nablet.com> | Mon Jul 13 10:17:54 2015 -0400| [ce91bab70f69acc1a7e5705af95cc6fa89765825] | committer: Michael Niedermayer

libavcodec/qsv.c: Issue fixed: QSV engine does not release display handler under linux platform.

Reviewed-by: Gwenole Beauchesne <gb.devel at gmail.com>
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=ce91bab70f69acc1a7e5705af95cc6fa89765825
---

 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 697af87..4c8e6b0 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 ee48a0f..3d949dc 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 67e8ef0..52df028 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 373cc72..210e9a9 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 3f37639..576bf68 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 8195d9b..4789675 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;



More information about the ffmpeg-cvslog mailing list