[FFmpeg-devel] [RFC 3/4] vaapi: add new API to configure a VA pipeline.

Gwenole Beauchesne gb.devel at gmail.com
Wed Aug 19 18:01:36 CEST 2015


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"
+/**@}*/
+
+/**
+ * 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)
-- 
1.9.1



More information about the ffmpeg-devel mailing list