[libav-devel] [PATCH 6/7] avcodec/decode: flush the internal bsfs instead of constantly reinitalizing them

James Almer jamrial at gmail.com
Fri Jul 27 19:59:56 CEST 2018


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 at 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 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 --git a/libavcodec/decode.c b/libavcodec/decode.c
index 8635aec94..2dab7f2a7 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -156,7 +156,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;
@@ -449,10 +449,6 @@ int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacke
     if (avctx->internal->draining)
         return AVERROR_EOF;
 
-    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);
@@ -511,10 +507,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 {
@@ -1394,6 +1386,14 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
     return 0;
 }
 
+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;
@@ -1410,7 +1410,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
     else if (avctx->codec->flush)
         avctx->codec->flush(avctx);
 
-    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 37b2e45c6..4a76d7a85 100644
--- a/libavcodec/decode.h
+++ b/libavcodec/decode.h
@@ -69,6 +69,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 ba3457664..13d9e4e62 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -664,6 +664,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
             ret = AVERROR(EINVAL);
             goto free_and_end;
         }
+
+        ret = ff_decode_bsfs_init(avctx);
+        if (ret < 0)
+            goto free_and_end;
     }
 end:
     if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) {
@@ -706,6 +710,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);
     }
-- 
2.18.0



More information about the libav-devel mailing list