[FFmpeg-devel] [RFC 3/4] vaapi: add new API to configure a VA pipeline.
wm4
nfxjfg at googlemail.com
Wed Aug 19 18:50:04 CEST 2015
On Wed, 19 Aug 2015 18:01:36 +0200
Gwenole Beauchesne <gb.devel at gmail.com> wrote:
> Add av_vaapi_set_pipeline_params() interface to initialize the internal
> FFVAContext with a valid VA display, and optional parameters including
> a user-supplied VA context id.
>
> This is preparatory work for delegating VA pipeline (decoder) creation
> to libavcodec. Meanwhile, if this new interface is used, the user shall
> provide the VA context id and a valid AVCodecContext.get_buffer2() hook.
> Otherwise, the older vaapi_context approach is still supported.
>
> This is an API change. The whole vaapi_context structure is no longer
> needed, and thus deprecated.
>
> Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
> ---
> doc/APIchanges | 6 ++--
> libavcodec/vaapi.c | 87 ++++++++++++++++++++++++++++++++++++++++-----
> libavcodec/vaapi.h | 49 +++++++++++++++++++++++--
> libavcodec/vaapi_internal.h | 4 +++
> 4 files changed, 134 insertions(+), 12 deletions(-)
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index aa92b69..fcdaa26 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -16,8 +16,10 @@ libavutil: 2014-08-09
> API changes, most recent first:
>
> 2015-xx-xx - lavc 56.58.100 - vaapi.h
> - Deprecate old VA-API context (vaapi_context) fields that were only
> - set and used by libavcodec. They are all managed internally now.
> + Add new API to configure the hwaccel/vaapi pipeline, currently
> + useful for decoders: av_vaapi_set_pipeline_params()
> + Deprecate old VA-API context (vaapi_context) structure, which is no
> + longer used for initializing a VA-API decode pipeline.
>
> 2015-xx-xx - lavu 54.31.100 - pixfmt.h
> Add a unique pixel format for VA-API (AV_PIX_FMT_VAAPI) that
> diff --git a/libavcodec/vaapi.c b/libavcodec/vaapi.c
> index c081bb5..afddbb3 100644
> --- a/libavcodec/vaapi.c
> +++ b/libavcodec/vaapi.c
> @@ -41,24 +41,95 @@ static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int
> }
> }
>
> +/** @name VA-API pipeline parameters (internal) */
> +/**@{*/
> +/** Pipeline configuration flags (AV_HWACCEL_FLAG_*|AV_VAAPI_PIPELINE_FLAG_*) */
> +#define AV_VAAPI_PIPELINE_PARAM_FLAGS "flags"
> +/** User-supplied VA display handle */
> +#define AV_VAAPI_PIPELINE_PARAM_DISPLAY "display"
> +/**@}*/
> +
> +#define OFFSET(x) offsetof(FFVAContext, x)
> +static const AVOption FFVAContextOptions[] = {
> + { AV_VAAPI_PIPELINE_PARAM_FLAGS, "flags", OFFSET(flags),
> + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT32_MAX },
> + { AV_VAAPI_PIPELINE_PARAM_DISPLAY, "VA display", OFFSET(user_display),
> + AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, UINTPTR_MAX },
> + { AV_VAAPI_PIPELINE_PARAM_CONTEXT, "VA context id", OFFSET(user_context_id),
> + AV_OPT_TYPE_INT, { .i64 = VA_INVALID_ID }, 0, UINT32_MAX },
> + { NULL, }
> +};
> +#undef OFFSET
> +
> +static const AVClass FFVAContextClass = {
> + .class_name = "FFVAContext",
> + .item_name = av_default_item_name,
> + .option = FFVAContextOptions,
> + .version = LIBAVUTIL_VERSION_INT,
> +};
> +
> +int av_vaapi_set_pipeline_params(AVCodecContext *avctx, VADisplay display,
> + uint32_t flags, AVDictionary **params)
> +{
> + int ret;
> +
> + if (!display) {
> + av_log(avctx, AV_LOG_ERROR, "No valid VA display supplied.\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (params && *params)
> + av_dict_copy(&avctx->internal->hwaccel_config, *params, 0);
> +
> + ret = av_dict_set_int(&avctx->internal->hwaccel_config,
> + AV_VAAPI_PIPELINE_PARAM_FLAGS, flags, 0);
> + if (ret != 0)
> + return ret;
> +
> + return av_dict_set_int(&avctx->internal->hwaccel_config,
> + AV_VAAPI_PIPELINE_PARAM_DISPLAY,
> + (int64_t)(intptr_t)display, 0);
> +}
> +
> 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;
> + int ret;
>
> - if (!user_vactx) {
> - av_log(avctx, AV_LOG_ERROR, "Hardware acceleration context (hwaccel_context) does not exist.\n");
> - return AVERROR(ENOSYS);
> - }
> + vactx->klass = &FFVAContextClass;
> + av_opt_set_defaults(vactx);
>
> - vactx->display = user_vactx->display;
> - vactx->config_id = user_vactx->config_id;
> - vactx->context_id = user_vactx->context_id;
> +#if FF_API_VAAPI_CONTEXT
> +FF_DISABLE_DEPRECATION_WARNINGS
> + if (avctx->hwaccel_context) {
> + const struct vaapi_context * const user_vactx = avctx->hwaccel_context;
> + vactx->user_display = (uintptr_t)user_vactx->display;
> + vactx->user_context_id = user_vactx->context_id;
> + }
> +FF_ENABLE_DEPRECATION_WARNINGS
> +#endif
>
> + vactx->context_id = VA_INVALID_ID;
> vactx->pic_param_buf_id = VA_INVALID_ID;
> vactx->iq_matrix_buf_id = VA_INVALID_ID;
> vactx->bitplane_buf_id = VA_INVALID_ID;
>
> + ret = av_opt_set_dict(vactx, &avctx->internal->hwaccel_config);
> + if (ret != 0)
> + return ret;
> +
> + vactx->display = (void *)(uintptr_t)vactx->user_display;
> + vactx->context_id = vactx->user_context_id;
> +
> + if (!vactx->display) {
> + av_log(avctx, AV_LOG_ERROR, "No valid VA display found.\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (vactx->context_id != VA_INVALID_ID && !avctx->get_buffer2) {
> + av_log(avctx, AV_LOG_ERROR, "No AVCodecContext.get_buffer2() hooked defined.\n");
> + return AVERROR(EINVAL);
> + }
> return 0;
> }
>
> diff --git a/libavcodec/vaapi.h b/libavcodec/vaapi.h
> index 4448a2e..43f8381 100644
> --- a/libavcodec/vaapi.h
> +++ b/libavcodec/vaapi.h
> @@ -32,7 +32,9 @@
>
> #include <stdint.h>
> #include <libavutil/attributes.h>
> +#include <va/va.h>
> #include "version.h"
> +#include "avcodec.h"
>
> /**
> * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding
> @@ -48,7 +50,11 @@
> * during initialization or through each AVCodecContext.get_buffer()
> * function call. In any case, they must be valid prior to calling
> * decoding functions.
> + *
> + * This structure is deprecated. Please refer to pipeline parameters
> + * and associated accessors, e.g. av_vaapi_set_pipeline_params().
> */
> +#if FF_API_VAAPI_CONTEXT
> struct vaapi_context {
> /**
> * Window system dependent data
> @@ -56,6 +62,7 @@ struct vaapi_context {
> * - encoding: unused
> * - decoding: Set by user
> */
> + attribute_deprecated
> void *display;
>
> /**
> @@ -64,6 +71,7 @@ struct vaapi_context {
> * - encoding: unused
> * - decoding: Set by user
> */
> + attribute_deprecated
> uint32_t config_id;
>
> /**
> @@ -72,9 +80,9 @@ struct vaapi_context {
> * - encoding: unused
> * - decoding: Set by user
> */
> + attribute_deprecated
> uint32_t context_id;
>
> -#if FF_API_VAAPI_CONTEXT
> /**
> * VAPictureParameterBuffer ID
> *
> @@ -181,8 +189,45 @@ struct vaapi_context {
> */
> attribute_deprecated
> uint32_t slice_data_size;
> -#endif
> };
> +#endif
> +
> +/** @name VA-API pipeline parameters */
> +/**@{*/
> +/**
> + * VA context id (uint32_t) [default: VA_INVALID_ID]
> + *
> + * This defines the VA context id to use for decoding. If set, then
> + * the user allocates and owns the handle, and shall supply VA surfaces
> + * through an appropriate hook to AVCodecContext.get_buffer2().
> + */
> +#define AV_VAAPI_PIPELINE_PARAM_CONTEXT "context"
I don't understand this. Wouldn't it also be possible to use a
user-defined get_buffer2 function, but with a context created by
libavcodec?
> +/**@}*/
> +
> +/**
> + * Defines VA processing pipeline parameters
> + *
> + * This function binds the supplied VA @a display to a codec context
> + * @a avctx.
> + *
> + * The user retains full ownership of the display, and thus shall
> + * ensure the VA-API subsystem was initialized with vaInitialize(),
> + * make due diligence to keep it live until it is no longer needed,
> + * and dispose the associated resources with vaTerminate() whenever
> + * appropriate.
> + *
> + * @note This function has no effect if it is called outside of an
> + * AVCodecContext.get_format() hook.
> + *
> + * @param[in] avctx the codec context being used for decoding the stream
> + * @param[in] display the VA display handle to use for decoding
> + * @param[in] flags zero or more OR'd AV_HWACCEL_FLAG_* or
> + * AV_VAAPI_PIPELINE_FLAG_* flags
> + * @param[in] params optional parameters to configure the pipeline
> + * @return 0 on success, an AVERROR code on failure.
> + */
> +int av_vaapi_set_pipeline_params(AVCodecContext *avctx, VADisplay display,
> + uint32_t flags, AVDictionary **params);
>
> /* @} */
>
> diff --git a/libavcodec/vaapi_internal.h b/libavcodec/vaapi_internal.h
> index 29f46ab..958246c 100644
> --- a/libavcodec/vaapi_internal.h
> +++ b/libavcodec/vaapi_internal.h
> @@ -36,6 +36,10 @@
> */
>
> typedef struct {
> + const void *klass;
> + uint32_t flags; ///< Pipeline flags
> + uint64_t user_display; ///< User-supplied VA display
> + uint32_t user_context_id; ///< User-supplied VA context ID
> VADisplay display; ///< Windowing system dependent handle
> VAConfigID config_id; ///< Configuration ID
> VAContextID context_id; ///< Context ID (video decode pipeline)
More information about the ffmpeg-devel
mailing list