[FFmpeg-devel] [PATCH] avcodec/qsv: export session management functionality
wm4
nfxjfg at googlemail.com
Wed Apr 13 10:08:48 CEST 2016
On Thu, 7 Apr 2016 11:44:20 -0400
nablet developer <sdk at nablet.com> wrote:
> 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;
Why would this API need to be exported?
More information about the ffmpeg-devel
mailing list