[FFmpeg-devel] [PATCH] avcodec/qsv: export session management functionality

nablet developer sdk at nablet.com
Thu Apr 7 17:44:20 CEST 2016


Signed-off-by: nablet developer <sdk at nablet.com>
---
 libavcodec/qsv.c          | 64 +++++++++++++++++++++--------------------------
 libavcodec/qsv.h          | 53 +++++++++++++++++++++++++++++++++++++++
 libavcodec/qsv_api.c      | 26 +++++++++++++++++++
 libavcodec/qsv_internal.h | 15 +----------
 libavcodec/qsvdec.c       | 13 +++++-----
 libavcodec/qsvdec.h       |  3 ++-
 libavcodec/qsvenc.c       | 16 ++++++------
 libavcodec/qsvenc.h       |  2 +-
 8 files changed, 125 insertions(+), 67 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 4c8e6b0..81d1f0c 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -18,14 +18,19 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <mfx/mfxvideo.h>
-#include <mfx/mfxplugin.h>
-
 #include <stdio.h>
 #include <string.h>
 
 #include "libavutil/avstring.h"
 #include "libavutil/error.h"
+#include "libavutil/log.h"
+
+#include "qsv.h"
+
+#if CONFIG_QSV
+
+#include <mfx/mfxvideo.h>
+#include <mfx/mfxplugin.h>
 
 #include "avcodec.h"
 #include "qsv_internal.h"
@@ -51,7 +56,7 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
     return AVERROR(ENOSYS);
 }
 
-int ff_qsv_error(int mfx_err)
+int av_qsv_error(int mfx_err)
 {
     switch (mfx_err) {
     case MFX_ERR_NONE:
@@ -85,7 +90,7 @@ int ff_qsv_error(int mfx_err)
         return AVERROR_UNKNOWN;
     }
 }
-static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
+static int ff_qsv_set_display_handle(AVClass *avccl, struct AVQSVSession *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
@@ -115,14 +120,14 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
 
         fd = open(adapterpath, O_RDWR);
         if (fd < 0) {
-            av_log(avctx, AV_LOG_ERROR,
+            av_log(avccl, 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,
+            av_log(avccl, AV_LOG_ERROR,
                 "mfx init: %s vaGetDisplayDRM failed\n", adapterpath);
             close(fd);
             continue;
@@ -130,22 +135,22 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
 
         va_res = vaInitialize(va_dpy, &major_version, &minor_version);
         if (VA_STATUS_SUCCESS != va_res) {
-            av_log(avctx, AV_LOG_ERROR,
+            av_log(avccl, AV_LOG_ERROR,
                 "mfx init: %s vaInitialize failed\n", adapterpath);
             close(fd);
             fd = -1;
             continue;
         } else {
-            av_log(avctx, AV_LOG_VERBOSE,
+            av_log(avccl, 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) {
-                av_log(avctx, AV_LOG_ERROR,
+                av_log(avccl, AV_LOG_ERROR,
                 "Error %d during set display handle\n", ret);
-                return ff_qsv_error(ret);
+                return av_qsv_error(ret);
             }
             break;
         }
@@ -153,22 +158,7 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs)
 #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE
     return 0;
 }
-/**
- * @brief Initialize a MSDK session
- *
- * Media SDK is based on sessions, so this is the prerequisite
- * initialization for HW acceleration.  For Windows the session is
- * complete and ready to use, for Linux a display handle is
- * required.  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.
- *
- * @param avctx    ffmpeg metadata for this codec context
- * @param session  the MSDK session used
- */
-int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
+int av_qsv_init_session(AVClass *avccl, struct AVQSVSession *qs,
                                  const char *load_plugins)
 {
     mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
@@ -179,11 +169,11 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
 
     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);
+        av_log(avccl, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
+        return av_qsv_error(ret);
     }
 
-    ret = ff_qsv_set_display_handle(avctx, qs);
+    ret = ff_qsv_set_display_handle(avccl, qs);
     if (ret < 0)
         return ret;
 
@@ -212,7 +202,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
             if (!plugin)
                 return AVERROR(ENOMEM);
             if (strlen(plugin) != 2 * sizeof(uid.Data)) {
-                av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
+                av_log(avccl, AV_LOG_ERROR, "Invalid plugin UID length\n");
                 err = AVERROR(EINVAL);
                 goto load_plugin_fail;
             }
@@ -220,7 +210,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
             for (i = 0; i < sizeof(uid.Data); i++) {
                 err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
                 if (err != 1) {
-                    av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID\n");
+                    av_log(avccl, AV_LOG_ERROR, "Invalid plugin UID\n");
                     err = AVERROR(EINVAL);
                     goto load_plugin_fail;
                 }
@@ -229,9 +219,9 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
 
             ret = MFXVideoUSER_Load(qs->session, &uid, 1);
             if (ret < 0) {
-                av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
+                av_log(avccl, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
                        plugin);
-                err = ff_qsv_error(ret);
+                err = av_qsv_error(ret);
                 goto load_plugin_fail;
             }
 
@@ -242,14 +232,14 @@ load_plugin_fail:
         }
     }
 
-    av_log(avctx, AV_LOG_VERBOSE,
+    av_log(avccl, AV_LOG_VERBOSE,
            "Initialized an internal MFX session using %s implementation\n",
            desc);
 
     return 0;
 }
 
-int ff_qsv_close_internal_session(QSVSession *qs)
+int av_qsv_close_session(AVQSVSession *qs)
 {
     if (qs->session) {
         MFXClose(qs->session);
@@ -267,3 +257,5 @@ int ff_qsv_close_internal_session(QSVSession *qs)
 #endif
     return 0;
 }
+#endif //CONFIG_QSV
+
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
index b77158e..a44e20f 100644
--- a/libavcodec/qsv.h
+++ b/libavcodec/qsv.h
@@ -98,10 +98,63 @@ typedef struct AVQSVContext {
 } AVQSVContext;
 
 /**
+ * This struct is used for handling QSV session parameters
+ */
+typedef struct AVQSVSession {
+    /**
+     * QSV session handle
+     */
+    mfxSession session;
+
+    /**
+     * display descriptor
+     */
+    int    fd_display;
+    /**
+     * display handler
+     */
+    void * va_display;
+} AVQSVSession;
+
+/**
  * Allocate a new context.
  *
  * It must be freed by the caller with av_free().
  */
 AVQSVContext *av_qsv_alloc_context(void);
 
+/**
+ * Initialize a MSDK session
+ *
+ * Media SDK is based on sessions, so this is the prerequisite
+ * initialization for HW acceleration.  For Windows the session is
+ * complete and ready to use, for Linux a display handle is
+ * required.  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.
+ *
+ * @param avccl pointer to AVClass, uses for logging
+ * @param qs    the MSDK session used
+ * @param load_plugins  list of hexadecimal plug-in UIDs delimeted by colons.
+ */
+int av_qsv_init_session(AVClass *avccl, AVQSVSession *qs,
+                        const char *load_plugins);
+
+/**
+ * Close a MSDK session
+ *
+ * @param qs the MSDK session used
+ */
+int av_qsv_close_session(AVQSVSession *qs);
+
+/**
+ * Translate native MSDK error code to AVERROR code
+ *
+ * @param mfx_err native MSDK error code
+ * @return one of AVERROR codes
+ */
+int av_qsv_error(int mfx_err);
+
 #endif /* AVCODEC_QSV_H */
diff --git a/libavcodec/qsv_api.c b/libavcodec/qsv_api.c
index 327ff7d..9b76073 100644
--- a/libavcodec/qsv_api.c
+++ b/libavcodec/qsv_api.c
@@ -32,11 +32,37 @@ AVQSVContext *av_qsv_alloc_context(void)
     return av_mallocz(sizeof(AVQSVContext));
 }
 #else
+struct AVQSVSession;
+struct AVQSVContext;
 
 struct AVQSVContext *av_qsv_alloc_context(void);
+int av_qsv_init_session(AVClass *avccl, struct AVQSVSession *qs,
+                        const char *load_plugins);
+int av_qsv_close_session(struct AVQSVSession *qs);
+int av_qsv_error(int mfx_err);
+
 
 struct AVQSVContext *av_qsv_alloc_context(void)
 {
     return NULL;
 }
+
+int av_qsv_init_session(AVClass *avccl, struct AVQSVSession *qs,
+                        const char *load_plugins)
+{
+    av_log(avccl, AV_LOG_ERROR,
+           "The libmfx is not linked. Recompile FFmpeg with libmfx enabled\n");
+    return AVERROR(ENOSYS);
+}
+
+int av_qsv_close_session(struct AVQSVSession *qs)
+{
+    return AVERROR(ENOSYS);
+}
+
+int av_qsv_error(int mfx_err)
+{
+    return AVERROR(ENOSYS);
+}
+
 #endif
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index f289a2b..c19a4ba 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -53,6 +53,7 @@
     (MFX_VERSION_MAJOR > (MAJOR) ||         \
      MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
 
+
 typedef struct QSVFrame {
     AVFrame *frame;
     mfxFrameSurface1 *surface;
@@ -65,23 +66,9 @@ 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.
  */
-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, 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 9125700..64406ff 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -34,7 +34,6 @@
 
 #include "avcodec.h"
 #include "internal.h"
-#include "qsv.h"
 #include "qsv_internal.h"
 #include "qsvdec.h"
 
@@ -75,8 +74,8 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt
     }
     if (!q->session) {
         if (!q->internal_qs.session) {
-            ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
-                                               q->load_plugins);
+            ret = av_qsv_init_session((AVClass*)&avctx->av_class, &q->internal_qs,
+                                      q->load_plugins);
             if (ret < 0)
                 return ret;
         }
@@ -108,7 +107,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt
         return avpkt->size;
     } else if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Decode header error %d\n", ret);
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
     param.IOPattern   = q->iopattern;
     param.AsyncDepth  = q->async_depth;
@@ -126,7 +125,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt
             av_log(avctx, AV_LOG_ERROR,
                    "Error initializing the MFX video decoder %d\n", ret);
         }
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
 
     avctx->profile      = param.mfx.CodecProfile;
@@ -405,7 +404,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
 
     if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
     n_out_frames = av_fifo_size(q->async_fifo) / (sizeof(out_frame)+sizeof(sync));
 
@@ -573,7 +572,7 @@ int ff_qsv_decode_close(QSVContext *q)
 
     q->session = NULL;
 
-    ff_qsv_close_internal_session(&q->internal_qs);
+    av_qsv_close_session(&q->internal_qs);
 
     av_fifo_free(q->async_fifo);
     q->async_fifo = NULL;
diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h
index 97a3315..51beb87 100644
--- a/libavcodec/qsvdec.h
+++ b/libavcodec/qsvdec.h
@@ -33,6 +33,7 @@
 #include "libavutil/pixfmt.h"
 
 #include "avcodec.h"
+#include "qsv.h"
 #include "qsv_internal.h"
 
 typedef struct QSVContext {
@@ -41,7 +42,7 @@ typedef struct QSVContext {
 
     // the session we allocated internally, in case the caller did not provide
     // one
-    QSVSession internal_qs;
+    AVQSVSession internal_qs;
 
     /**
      * a linked list of frames currently being used by QSV
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index be54bf9..f59e88f 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -603,7 +603,7 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
 
     ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
     if (ret < 0)
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
 
     q->packet_size = q->param.mfx.BufferSizeInKB * 1000;
 
@@ -696,8 +696,8 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
     }
 
     if (!q->session) {
-        ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
-                                           q->load_plugins);
+        ret = av_qsv_init_session((AVClass*)&avctx->av_class, &q->internal_qs,
+                                   q->load_plugins);
         if (ret < 0)
             return ret;
 
@@ -713,13 +713,13 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
         av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
     } else if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error %d querying encoder params\n", ret);
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
 
     ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
 
     if (opaque_alloc) {
@@ -762,7 +762,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
         av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
     } else if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
 
     ret = qsv_retrieve_enc_params(avctx, q);
@@ -976,7 +976,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
         if (ret == MFX_ERR_MORE_DATA)
             return 0;
         av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
-        return ff_qsv_error(ret);
+        return av_qsv_error(ret);
     }
 
     if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
@@ -1074,7 +1074,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
         MFXVideoENCODE_Close(q->session);
     q->session = NULL;
 
-    ff_qsv_close_internal_session(&q->internal_qs);
+    av_qsv_close_session(&q->internal_qs);
 
     cur = q->work_frames;
     while (cur) {
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 2d7bd32..6ce2719 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -79,7 +79,7 @@ typedef struct QSVEncContext {
     QSVFrame *work_frames;
 
     mfxSession session;
-    QSVSession internal_qs;
+    AVQSVSession internal_qs;
 
     int packet_size;
     int width_align;
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list