@@ -182,7 +182,7 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
return 0;
}
-static int bsfs_init(AVCodecContext *avctx)
+int ff_decode_bsfs_init(AVCodecContext *avctx)
{
AVCodecInternal *avci = avctx->internal;
DecodeFilterContext *s = &avci->filter;
@@ -688,10 +688,6 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
if (avpkt && !avpkt->size && avpkt->data)
return AVERROR(EINVAL);
- ret = bsfs_init(avctx);
- if (ret < 0)
- return ret;
-
av_packet_unref(avci->buffer_pkt);
if (avpkt && (avpkt->data || avpkt->side_data_elems)) {
ret = av_packet_ref(avci->buffer_pkt, avpkt);
@@ -751,10 +747,6 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr
if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))
return AVERROR(EINVAL);
- ret = bsfs_init(avctx);
- if (ret < 0)
- return ret;
-
if (avci->buffer_frame->buf[0]) {
av_frame_move_ref(frame, avci->buffer_frame);
} else {
@@ -1978,6 +1970,14 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
return ret;
}
+static void bsfs_flush(AVCodecContext *avctx)
+{
+ DecodeFilterContext *s = &avctx->internal->filter;
+
+ for (int i = 0; i < s->nb_bsfs; i++)
+ av_bsf_flush(s->bsfs[i]);
+}
+
void avcodec_flush_buffers(AVCodecContext *avctx)
{
avctx->internal->draining = 0;
@@ -1998,7 +1998,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
avctx->pts_correction_last_pts =
avctx->pts_correction_last_dts = INT64_MIN;
- ff_decode_bsfs_uninit(avctx);
+ bsfs_flush(avctx);
if (!avctx->refcounted_frames)
av_frame_unref(avctx->internal->to_free);
@@ -64,6 +64,8 @@ typedef struct FrameDecodeData {
*/
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt);
+int ff_decode_bsfs_init(AVCodecContext *avctx);
+
void ff_decode_bsfs_uninit(AVCodecContext *avctx);
/**
@@ -994,6 +994,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
#endif
+
+ ret = ff_decode_bsfs_init(avctx);
+ if (ret < 0)
+ goto free_and_end;
}
if (codec->priv_data_size > 0 && avctx->priv_data && codec->priv_class) {
av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class);
@@ -1032,6 +1036,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
av_packet_free(&avctx->internal->last_pkt_props);
av_packet_free(&avctx->internal->ds.in_pkt);
+ ff_decode_bsfs_uninit(avctx);
av_freep(&avctx->internal->pool);
}
Initialize the bsfs once when opening the codec and uninitialize them once when closing it, instead of at every codec flush/seek. Signed-off-by: James Almer <jamrial@gmail.com> --- I think i didn't miss any bsf with internal state that needs a flush() callback, but an extra pair of eyes (or more) to make sure would come in handy. In any case, the only bsfs where this matters are those used during decoding, which essentially means those autoinserted by decoders given that the ffmpeg cli doesn't allow -bsf as an input option. But you can't know what an API user may do, so better get them all right. libavcodec/decode.c | 20 ++++++++++---------- libavcodec/decode.h | 2 ++ libavcodec/utils.c | 5 +++++ 3 files changed, 17 insertions(+), 10 deletions(-)