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

nablet developer sdk at nablet.com
Wed Apr 13 10:14:37 CEST 2016


> On 13 Apr 2016, at 14:08, wm4 <nfxjfg at googlemail.com> wrote:
> 
> On Thu,  7 Apr 2016 11:44:20 -0400
> nablet developer <sdk at nablet.com <mailto: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?

previously QuickSync was used only by libavcodec and its components - e.g. there are QSV encoder and decoders for AVC and MPEG-2. so it was OK that QuickSync initialisation and cleanup functions were local for libavcodec.

but right now we're adding QuickSync VPP component to libavfilter, so mentioned functions now become shared at least between libavcodec and libavfilter.
therefore, patch to add QSV VPP filter was rejected because it accessed libavcodec functions which were local, and it was suggested that such functions are need to be exported from libavcodec, so libavfilter can use them.

> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org <mailto:ffmpeg-devel at ffmpeg.org>
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel <http://ffmpeg.org/mailman/listinfo/ffmpeg-devel>


More information about the ffmpeg-devel mailing list