[FFmpeg-devel] [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when using system memory

Huang, Zhengxu zhengxu.maxwell at gmail.com
Mon Jan 9 04:05:23 EET 2017


-------------- next part --------------
From 37629f14294125c7396e5e12970d75e895b1caba Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxwell at gmail.com>
Date: Mon, 19 Dec 2016 01:27:06 -0500
Subject: [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when
 using system memory

Description: ./ffmpeg -c:v h264_qsv -i in -c:v h264 output.h264 does not
work because the qsv decode will failed.

Root cuase: when using the system rather than the hwaccel,ff_qsv_init_internal_session
does not set the vaDisplay handle for the session. The qsv decode will failed.

Solution: when creating the internal session , call the HwContext API to get session and
release all resource when close the decoder.

Signed-off-by: ChaoX A Liu <chaox.a.liu at gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxwell at gmail.com>
Signed-off-by: Andrew, Zhang <huazh407 at gmail.com>
---
 libavcodec/qsv.c          |  6 ++---
 libavcodec/qsv_internal.h |  5 ++++
 libavcodec/qsvdec.c       | 59 ++++++++++++++++++++++++++++++++++++++++++++---
 libavcodec/qsvdec.h       |  1 +
 4 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index aac6ce6..a932fc3 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -120,7 +120,7 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc)
     }
 }
 
-static int qsv_load_plugins(mfxSession session, const char *load_plugins,
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins,
                             void *logctx)
 {
     if (!load_plugins || !*load_plugins)
@@ -185,7 +185,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
         return ff_qsv_error(ret);
     }
 
-    ret = qsv_load_plugins(*session, load_plugins, avctx);
+    ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
         return ret;
@@ -329,7 +329,7 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *psession,
         }
     }
 
-    ret = qsv_load_plugins(session, load_plugins, avctx);
+    ret = ff_qsv_load_plugins(session, load_plugins, avctx);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
         return ret;
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 5d2a216..13f23ef 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -50,6 +50,10 @@ typedef struct QSVFrame {
     struct QSVFrame *next;
 } QSVFrame;
 
+typedef struct QSVDeviceContext {
+    AVBufferRef *hw_device_ctx;
+} QSVDeviceContext;
+
 typedef struct QSVFramesContext {
     AVBufferRef *hw_frames_ctx;
     mfxFrameInfo info;
@@ -73,5 +77,6 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
 int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session,
                                   QSVFramesContext *qsv_frames_ctx,
                                   const char *load_plugins, int opaque);
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins, void *logctx);
 
 #endif /* AVCODEC_QSV_INTERNAL_H */
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 258042d..ccd5e26 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -41,6 +41,58 @@
 #include "qsv_internal.h"
 #include "qsvdec.h"
 
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
+                                 QSVContext *q, const char *load_plugins)
+{
+    mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+    mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+    const char *desc;
+    int ret;
+    AVHWDeviceContext *device_hw;
+    AVQSVDeviceContext *hwctx;
+    AVBufferRef *hw_device_ctx;
+
+    ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, NULL, 0);
+    if (ret < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+        return ret;
+    }
+    device_hw = (AVHWDeviceContext*)hw_device_ctx->data;
+    hwctx = device_hw->hwctx;
+
+    *session = hwctx->session;
+
+    q->device_ctx.hw_device_ctx = hw_device_ctx;
+
+    ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
+        return ret;
+    }
+    MFXQueryIMPL(*session, &impl);
+
+    switch (MFX_IMPL_BASETYPE(impl)) {
+    case MFX_IMPL_SOFTWARE:
+        desc = "software";
+        break;
+    case MFX_IMPL_HARDWARE:
+    case MFX_IMPL_HARDWARE2:
+    case MFX_IMPL_HARDWARE3:
+    case MFX_IMPL_HARDWARE4:
+        desc = "hardware accelerated";
+        break;
+    default:
+        desc = "unknown";
+    }
+
+    av_log(avctx, AV_LOG_VERBOSE,
+           "Initialized an internal MFX session using %s implementation\n",
+           desc);
+
+    return 0;
+}
+
 static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session,
                             AVBufferRef *hw_frames_ref)
 {
@@ -70,13 +122,13 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
         q->session = q->internal_session;
     } else {
         if (!q->internal_session) {
-            ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
+            ret = qsv_init_internal_session(avctx, &q->session, q,
                                                q->load_plugins);
             if (ret < 0)
                 return ret;
         }
-
-        q->session = q->internal_session;
+        /* the session will close when unref the hw_device_ctx */
+       // q->session = q->internal_session;
     }
 
     /* make sure the decoder is uninitialized */
@@ -428,6 +480,7 @@ int ff_qsv_decode_close(QSVContext *q)
         MFXClose(q->internal_session);
 
     av_buffer_unref(&q->frames_ctx.hw_frames_ctx);
+    av_buffer_unref(&q->device_ctx.hw_device_ctx);
     av_freep(&q->frames_ctx.mids);
     q->frames_ctx.nb_mids = 0;
 
diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h
index 41fb716..ae810bc 100644
--- a/libavcodec/qsvdec.h
+++ b/libavcodec/qsvdec.h
@@ -44,6 +44,7 @@ typedef struct QSVContext {
     mfxSession internal_session;
 
     QSVFramesContext frames_ctx;
+    QSVDeviceContext device_ctx;
 
     /**
      * a linked list of frames currently being used by QSV
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list