avcodec/bink: Make decoder init-threadsafe

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
Andreas Rheinhardt 2020-12-01 17:25:17 +01:00 committed by Andreas Rheinhardt
parent 8903c7f1fe
commit bd473d325d
1 changed files with 20 additions and 18 deletions

View File

@ -24,6 +24,7 @@
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/internal.h" #include "libavutil/internal.h"
#include "libavutil/mem_internal.h" #include "libavutil/mem_internal.h"
#include "libavutil/thread.h"
#define BITSTREAM_READER_LE #define BITSTREAM_READER_LE
#include "avcodec.h" #include "avcodec.h"
@ -1309,6 +1310,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
return pkt->size; 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 * Calculate quantization tables for version b
*/ */
@ -1343,11 +1357,10 @@ static av_cold void binkb_calc_quant(void)
static av_cold int decode_init(AVCodecContext *avctx) static av_cold int decode_init(AVCodecContext *avctx)
{ {
static AVOnce init_static_once = AV_ONCE_INIT;
BinkContext * const c = avctx->priv_data; BinkContext * const c = avctx->priv_data;
static VLC_TYPE table[16 * 128][2];
static int binkb_initialised = 0;
HpelDSPContext hdsp; HpelDSPContext hdsp;
int i, ret; int ret;
int flags; int flags;
c->version = avctx->codec_tag >> 24; c->version = avctx->codec_tag >> 24;
@ -1358,16 +1371,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
flags = AV_RL32(avctx->extradata); flags = AV_RL32(avctx->extradata);
c->has_alpha = flags & BINK_FLAG_ALPHA; c->has_alpha = flags & BINK_FLAG_ALPHA;
c->swap_planes = c->version >= 'h'; 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; c->avctx = avctx;
if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
@ -1389,11 +1392,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
return ret; return ret;
if (c->version == 'b') { if (c->version == 'b') {
if (!binkb_initialised) { static AVOnce binkb_init_once = AV_ONCE_INIT;
binkb_calc_quant(); ff_thread_once(&binkb_init_once, binkb_calc_quant);
binkb_initialised = 1;
}
} }
ff_thread_once(&init_static_once, bink_init_vlcs);
return 0; return 0;
} }
@ -1426,5 +1428,5 @@ const AVCodec ff_bink_decoder = {
.decode = decode_frame, .decode = decode_frame,
.flush = flush, .flush = flush,
.capabilities = AV_CODEC_CAP_DR1, .capabilities = AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
}; };