[FFmpeg-devel] [PATCH 4/4] vaapi: add interfaces to properly initialize context.

wm4 nfxjfg at googlemail.com
Mon Aug 17 22:26:16 CEST 2015


On Mon, 17 Aug 2015 19:17:53 +0200
Gwenole Beauchesne <gb.devel at gmail.com> wrote:

> Add av_vaapi_context_init() and av_vaapi_context_alloc() helper functions
> so that to properly initialize the vaapi_context structure, and allow for
> future extensions without breaking the API/ABI.
> 
> The new version and flags fields are inserted after the last known user
> initialized field, and actually useful field at all, i.e. VA context_id.
> This is safe because the vaapi_context structure was required to be zero
> initialized in the past. And, since those new helper functions and changes
> cause the AV_VAAPI_CONTEXT_VERSION to be bumped, we can track older struct
> requirements from within libavcodec.
> 
> Besides, it is now required by design, and actual usage, that the vaapi
> context structure be completely initialized once and for all before the
> AVCodecContext.get_format() function ever completes.
> 
> Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
> ---
>  libavcodec/vaapi.c          | 30 +++++++++++++++++++++++
>  libavcodec/vaapi.h          | 59 +++++++++++++++++++++++++++++++++++++++++----
>  libavcodec/vaapi_internal.h |  1 +
>  3 files changed, 85 insertions(+), 5 deletions(-)
> 
> diff --git a/libavcodec/vaapi.c b/libavcodec/vaapi.c
> index 1ae71a5..4d3e2f3 100644
> --- a/libavcodec/vaapi.c
> +++ b/libavcodec/vaapi.c
> @@ -41,11 +41,41 @@ static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int
>      }
>  }
>  
> +/* Allocates a vaapi_context structure */
> +struct vaapi_context *av_vaapi_context_alloc(unsigned int flags)
> +{
> +    struct vaapi_context *vactx;
> +
> +    vactx = av_malloc(sizeof(*vactx));
> +    if (!vactx)
> +        return NULL;
> +
> +    av_vaapi_context_init(vactx, AV_VAAPI_CONTEXT_VERSION, flags);
> +    return vactx;
> +}
> +
> +/* Initializes a vaapi_context structure with safe defaults */
> +void av_vaapi_context_init(struct vaapi_context *vactx, unsigned int version,
> +                           unsigned int flags)
> +{
> +    vactx->display      = NULL;
> +    vactx->config_id    = VA_INVALID_ID;
> +    vactx->context_id   = VA_INVALID_ID;
> +
> +    if (version > 0) {
> +        vactx->version  = version;
> +        vactx->flags    = flags;
> +    }
> +}
> +
>  int ff_vaapi_context_init(AVCodecContext *avctx)
>  {
>      FFVAContext * const vactx = ff_vaapi_get_context(avctx);
>      const struct vaapi_context * const user_vactx = avctx->hwaccel_context;
>  
> +    if (user_vactx->version > 0)
> +        vactx->flags            = user_vactx->flags;
> +
>      vactx->display              = user_vactx->display;
>      vactx->config_id            = user_vactx->config_id;
>      vactx->context_id           = user_vactx->context_id;
> diff --git a/libavcodec/vaapi.h b/libavcodec/vaapi.h
> index 4448a2e..1f032a0 100644
> --- a/libavcodec/vaapi.h
> +++ b/libavcodec/vaapi.h
> @@ -40,14 +40,16 @@
>   * @{
>   */
>  
> +#define AV_VAAPI_CONTEXT_VERSION 1
> +
>  /**
>   * This structure is used to share data between the FFmpeg library and
>   * the client video application.
> - * This shall be zero-allocated and available as
> - * AVCodecContext.hwaccel_context. All user members can be set once
> - * during initialization or through each AVCodecContext.get_buffer()
> - * function call. In any case, they must be valid prior to calling
> - * decoding functions.
> + *
> + * This shall be initialized with av_vaapi_context_init(), or
> + * indirectly through av_vaapi_context_alloc(), and made available as
> + * AVCodecContext.hwaccel_context. All user members must be properly
> + * initialized before AVCodecContext.get_format() completes.
>   */
>  struct vaapi_context {
>      /**
> @@ -74,6 +76,29 @@ struct vaapi_context {
>       */
>      uint32_t context_id;
>  
> +    /**
> +     * This field must be set to AV_VAAPI_CONTEXT_VERSION
> +     *
> +     * @since Version 1.
> +     *
> +     * - encoding: unused
> +     * - decoding: Set by user, through av_vaapi_context_init()
> +     */
> +    unsigned int version;

Not sure if I see any point in this. Normally, backwards-compatible ABI
additions can add fields in FFmpeg, but the API user doesn't get a way
to check whether a field is really there.

Or in other words, the level of ABI compatibility we target is that
newer libav* libs work with old application binaries, but not the other
way around.

> +
> +    /**
> +     * A bit field configuring the internal context used by libavcodec
> +     *
> +     * This is a combination of flags from common AV_HWACCEL_FLAG_xxx and
> +     * from VA-API specific AV_VAAPI_FLAG_xxx.
> +     *
> +     * @since Version 1.
> +     *
> +     * - encoding: unused
> +     * - decoding: Set by user, through av_vaapi_context_init()
> +     */
> +    unsigned int flags;

I'd say just leave it private, and the user can only initialize it with
av_vaapi_context_init().

> +
>  #if FF_API_VAAPI_CONTEXT
>      /**
>       * VAPictureParameterBuffer ID
> @@ -184,6 +209,30 @@ struct vaapi_context {
>  #endif
>  };
>  
> +/**
> + * Allocates a vaapi_context structure.
> + *
> + * This function allocates and initializes a vaapi_context with safe
> + * defaults, e.g. with proper invalid ids for VA config and context.
> + *
> + * The resulting structure can be deallocated with av_freep().
> + *
> + * @param[in]  flags    zero, or a combination of AV_HWACCEL_FLAG_xxx or
> + *     AV_VAAPI_FLAG_xxx flags OR'd altogether.
> + * @return Newly-allocated struct vaapi_context, or NULL on failure
> + */
> +struct vaapi_context *av_vaapi_context_alloc(unsigned int flags);
> +
> +/**
> + * Initializes a vaapi_context structure with safe defaults.
> + *
> + * @param[in]  version  this must be set to AV_VAAPI_CONTEXT_VERSION
> + * @param[in]  flags    zero, or a combination of AV_HWACCEL_FLAG_xxx or
> + *     AV_VAAPI_FLAG_xxx flags OR'd altogether.
> + */
> +void av_vaapi_context_init(struct vaapi_context *vactx, unsigned int version,
> +                           unsigned int flags);
> +
>  /* @} */
>  
>  #endif /* AVCODEC_VAAPI_H */
> diff --git a/libavcodec/vaapi_internal.h b/libavcodec/vaapi_internal.h
> index 29f46ab..a7c69e6 100644
> --- a/libavcodec/vaapi_internal.h
> +++ b/libavcodec/vaapi_internal.h
> @@ -36,6 +36,7 @@
>   */
>  
>  typedef struct {
> +    unsigned int flags;                 ///< Configuration flags
>      VADisplay display;                  ///< Windowing system dependent handle
>      VAConfigID config_id;               ///< Configuration ID
>      VAContextID context_id;             ///< Context ID (video decode pipeline)

This looks fine and all... but in the future it'd be nice if we had
something like av_vdpau_bind_context(), which actually takes care of
mapping the codec profiles and initializing the decoder.

I'm not sure through how many API iterations I want to go through
myself... (for vdpau hwaccel, we had at least 3 APIs now.)

If it's not much trouble, maybe you could consider going into this
direction?

The patch looks good, but a clear documentation whether the user is nor
is not allowed to allocate the struct directly is missing. If it's not
allowed, this would be a breaking API change, but maybe nothing which
requires a major bump.

doc/APIchanges needs additions in any case. (Patches 1 and 2 also do,
I forgot to mention this.)


More information about the ffmpeg-devel mailing list