[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