[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