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 <[email protected]>).
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.
---
Updated to clarify failure behaviour, moved internal parts to hwaccel.h.
doc/APIchanges | 3 +++
libavcodec/avcodec.h | 38 ++++++++++++++++++++++++++++++++++++++
libavcodec/decode.c | 25 +++++++++++++++++++++++++
libavcodec/hwaccel.h | 19 +++++++++++++++++++
libavcodec/options_table.h | 1 +
5 files changed, 86 insertions(+)
diff --git a/doc/APIchanges b/doc/APIchanges
index ed90be890..be6cd1431 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.
+
2016-xx-xx - xxxxxxx - lavf 58.1.0 - avio.h
Add avio_read_partial().
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 162f1abe4..680a7b5e4 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2725,6 +2725,44 @@ 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
+ * initialisation of the current hwaccel will fail. If other output
+ * formats are available, get_format() may be called again to allow the
+ * user to select a different one.
+ */
+ 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..2f4ebd12a 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -34,6 +34,7 @@
#include "avcodec.h"
#include "bytestream.h"
#include "decode.h"
+#include "hwaccel.h"
#include "internal.h"
#include "thread.h"
@@ -767,6 +768,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/hwaccel.h b/libavcodec/hwaccel.h
index 60dbe81c8..24ab1192c 100644
--- a/libavcodec/hwaccel.h
+++ b/libavcodec/hwaccel.h
@@ -19,6 +19,25 @@
#ifndef AVCODEC_HWACCEL_H
#define AVCODEC_HWACCEL_H
+#include "avcodec.h"
+
#define HWACCEL_CAP_ASYNC_SAFE (1 << 0)
+/**
+ * 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);
+
#endif /* AVCODEC_HWACCEL_H */
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
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel