This can be used to refine the parameters of lavc-created hardware frames
contexts - this is useful for APIs which require some use information to
to be supplied at create time, such as DXVA2 and D3D11VA.  (Suggested by
wm4 <nfx...@googlemail.com>).

Also adds a field extra_hw_frames, which supports simple cases where the
only modification to the default parameters required is to increase the
size of a fixed-size pool.
---
As discussed quite a while ago.


 doc/APIchanges             |  3 +++
 libavcodec/avcodec.h       | 36 ++++++++++++++++++++++++++++++++++++
 libavcodec/decode.c        | 24 ++++++++++++++++++++++++
 libavcodec/internal.h      | 17 +++++++++++++++++
 libavcodec/options_table.h |  1 +
 5 files changed, 81 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 463247f48..c111d08ad 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil:     2017-03-23
 
 API changes, most recent first:
 
+2017-xx-xx - xxxxxxx - lavc 58.x+1.0 - avcodec.h
+  Add AVCodecContext.init_hw_frames and AVCodecContext.extra_hw_frames.
+
 2017-xx-xx - xxxxxxx - lavu 56.4.0 - imgutils.h
   Add av_image_fill_black().
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 162f1abe4..847b7f139 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2725,6 +2725,42 @@ typedef struct AVCodecContext {
      *             AVCodecContext.get_format callback)
      */
     int hwaccel_flags;
+
+    /**
+     * Video decoding only.  If set by the user, this will be called when
+     * new hardware frames need to be allocated following a get_format()
+     * callback which indicated that hardware decoding should be used but
+     * did not set s->hw_frames_ctx.
+     *
+     * When called, s->hw_frames_ctx will be allocated on the device in
+     * s->hw_device_ctx and have basic parameters set (required pool size,
+     * frame dimensions and surface format).  The user can then further
+     * refine the parameters as required for their use-case - for example,
+     * by setting API-specific values in AVHWFramesContext.hwctx, or by
+     * increasing the size of allocated frames to meet some external
+     * constraint.  Do not call av_hwframe_ctx_init() from this callback -
+     * it will be called later by lavc.
+     *
+     * This function should normally return zero.  If it encounters some
+     * error (e.g. if the user knows that frames of the requested form will
+     * not be usable), it must return a negative error code and decoder
+     * initialisation will then fail, returning control to the user.
+     */
+    int (*init_hw_frames)(struct AVCodecContext *s);
+
+    /**
+     * Video decoding only.  Sets the number of extra hardware frames which
+     * the decoder will allocate for use by the caller.  This is only used
+     * if hw_device_ctx is set.
+     *
+     * Some hardware decoders require all frames that they will use for
+     * output to be defined in advance before decoding starts.  For such
+     * decoders, the hardware frame pool must therefore be of a fixed size.
+     * The extra frames set here are on top of any number that the decoder
+     * needs internally in order to operate normally (for example, frames
+     * used as reference pictures).
+     */
+    int extra_hw_frames;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index c76ee6696..6d6088eaa 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -767,6 +767,30 @@ int ff_get_format(AVCodecContext *avctx, const enum 
AVPixelFormat *fmt)
     return ret;
 }
 
+int ff_init_hw_frames(AVCodecContext *avctx)
+{
+    AVHWFramesContext *frames;
+    int err;
+
+    // Must already be set by caller.
+    av_assert0(avctx->hw_frames_ctx);
+
+    frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+
+    if (avctx->init_hw_frames) {
+        err = avctx->init_hw_frames(avctx);
+        if (err < 0)
+            return err;
+    } else if (frames->initial_pool_size == 0) {
+        // Dynamically allocation is necessarily supported.
+    } else {
+        if (avctx->extra_hw_frames >= 0)
+            frames->initial_pool_size += avctx->extra_hw_frames;
+    }
+
+    return 0;
+}
+
 static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
 {
     FramePool *pool = avctx->internal->pool;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 403fb4a09..023d94285 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -276,6 +276,23 @@ int ff_side_data_update_matrix_encoding(AVFrame *frame,
 int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt);
 
 /**
+ * Perform any additional setup required for hardware frames.
+ *
+ * This calls avctx->init_hw_frames() if set, and in that case all setup
+ * will be performed by the user.
+ * If unset, it will set default values which may be influenced by other
+ * user settings (such as avctx->extra_hw_frames).
+ *
+ * avctx->hw_frames_ctx must be set before calling this function.
+ * Inside avctx->hw_frames_ctx, the fields format, sw_format, width and
+ * height must be set.  If dynamically allocated pools are not supported,
+ * then initial_pool_size must also be set, to the minimum hardware frame
+ * pool size necessary for decode (taking into account reference frames
+ * and delay as appropriate).
+ */
+int ff_init_hw_frames(AVCodecContext *avctx);
+
+/**
  * Set various frame properties from the codec context / packet data.
  */
 int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame);
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 925ef376f..4b0a8344d 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -419,6 +419,7 @@ static const AVOption avcodec_options[] = {
 {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), 
AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E },
 #endif
 {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_INT, { .i64 = 1 
}, 0, 1, V | D },
+{"extra_hw_frames", "Number of extra hardware frames to allocate for the 
user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
V|D },
 {NULL},
 };
 
-- 
2.11.0

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to