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