diff mbox series

[FFmpeg-devel,210/217] avcodec/bink: Make decoder init-threadsafe

Message ID 20201202042244.519127-76-andreas.rheinhardt@gmail.com
State New
Headers show
Series [FFmpeg-devel,01/45] avcodec/a64multienc: Fix memleak upon init failure
Related show

Checks

Context Check Description
andriy/x86 warning Failed to apply patch

Commit Message

Andreas Rheinhardt Dec. 2, 2020, 4:22 a.m. UTC
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavcodec/bink.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/bink.c b/libavcodec/bink.c
index ec164d0165..f1fa9c0071 100644
--- a/libavcodec/bink.c
+++ b/libavcodec/bink.c
@@ -23,6 +23,7 @@ 
 #include "libavutil/attributes.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
+#include "libavutil/thread.h"
 
 #define BITSTREAM_READER_LE
 #include "avcodec.h"
@@ -1308,6 +1309,19 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
     return pkt->size;
 }
 
+static av_cold void bink_init_vlcs(void)
+{
+    for (int i = 0; i < 16; i++) {
+        static VLC_TYPE table[16 * 128][2];
+        const int maxbits = bink_tree_lens[i][15];
+        bink_trees[i].table = table + i*128;
+        bink_trees[i].table_allocated = 1 << maxbits;
+        init_vlc(&bink_trees[i], maxbits, 16,
+                 bink_tree_lens[i], 1, 1,
+                 bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE);
+    }
+}
+
 /**
  * Calculate quantization tables for version b
  */
@@ -1342,11 +1356,10 @@  static av_cold void binkb_calc_quant(void)
 
 static av_cold int decode_init(AVCodecContext *avctx)
 {
+    static AVOnce init_static_once = AV_ONCE_INIT;
     BinkContext * const c = avctx->priv_data;
-    static VLC_TYPE table[16 * 128][2];
-    static int binkb_initialised = 0;
     HpelDSPContext hdsp;
-    int i, ret;
+    int ret;
     int flags;
 
     c->version = avctx->codec_tag >> 24;
@@ -1357,16 +1370,6 @@  static av_cold int decode_init(AVCodecContext *avctx)
     flags = AV_RL32(avctx->extradata);
     c->has_alpha = flags & BINK_FLAG_ALPHA;
     c->swap_planes = c->version >= 'h';
-    if (!bink_trees[15].table) {
-        for (i = 0; i < 16; i++) {
-            const int maxbits = bink_tree_lens[i][15];
-            bink_trees[i].table = table + i*128;
-            bink_trees[i].table_allocated = 1 << maxbits;
-            init_vlc(&bink_trees[i], maxbits, 16,
-                     bink_tree_lens[i], 1, 1,
-                     bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE);
-        }
-    }
     c->avctx = avctx;
 
     if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
@@ -1388,11 +1391,10 @@  static av_cold int decode_init(AVCodecContext *avctx)
         return ret;
 
     if (c->version == 'b') {
-        if (!binkb_initialised) {
-            binkb_calc_quant();
-            binkb_initialised = 1;
-        }
+        static AVOnce binkb_init_once = AV_ONCE_INIT;
+        ff_thread_once(&binkb_init_once, binkb_calc_quant);
     }
+    ff_thread_once(&init_static_once, bink_init_vlcs);
 
     return 0;
 }
@@ -1425,5 +1427,5 @@  AVCodec ff_bink_decoder = {
     .decode         = decode_frame,
     .flush          = flush,
     .capabilities   = AV_CODEC_CAP_DR1,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };