diff mbox

[FFmpeg-devel,7/8] avcodec/decode: flush the internal bsfs instead of constantly reinitalizing them

Message ID 20180727145749.9436-7-jamrial@gmail.com
State New
Headers show

Commit Message

James Almer July 27, 2018, 2:57 p.m. UTC
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(-)
diff mbox

Patch

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index db364ca700..2e82f6b506 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -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);
diff --git a/libavcodec/decode.h b/libavcodec/decode.h
index 15271c529a..c3e0e82f4c 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -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);
 
 /**
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 4f9a2b76ef..d95a4fe71c 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -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);
     }