avcodec/jpeg2000dec: Make decoder init-threadsafe

The JPEG-2000 decoder and encoder share common luts; the decoder
initializes them once, guarded by a dedicated AVOnce, whereas
the encoder initializes them always during init. This means that
the decoder is not init-threadsafe; in fact there is a potential
data race because these luts can be initialized while an active
decoder/encoder is using them.

Fix this and make the decoder init-threadsafe by making the
initialization function guard initialization itself with a dedicated
AVOnce.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
pull/362/head
Andreas Rheinhardt 4 years ago
parent b43e946b71
commit 3c26773ae2
  1. 9
      libavcodec/jpeg2000.c
  2. 12
      libavcodec/jpeg2000dec.c

@ -30,6 +30,7 @@
#include "libavutil/common.h" #include "libavutil/common.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "libavutil/thread.h"
#include "avcodec.h" #include "avcodec.h"
#include "internal.h" #include "internal.h"
#include "jpeg2000.h" #include "jpeg2000.h"
@ -157,7 +158,7 @@ static int getsgnctxno(int flag, uint8_t *xorbit)
return ctxlbltab[hcontrib][vcontrib]; return ctxlbltab[hcontrib][vcontrib];
} }
void av_cold ff_jpeg2000_init_tier1_luts(void) static void av_cold jpeg2000_init_tier1_luts(void)
{ {
int i, j; int i, j;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@ -169,6 +170,12 @@ void av_cold ff_jpeg2000_init_tier1_luts(void)
getsgnctxno(i + (j << 8), &ff_jpeg2000_xorbit_lut[i][j]); getsgnctxno(i + (j << 8), &ff_jpeg2000_xorbit_lut[i][j]);
} }
void av_cold ff_jpeg2000_init_tier1_luts(void)
{
static AVOnce init_static_once = AV_ONCE_INIT;
ff_thread_once(&init_static_once, jpeg2000_init_tier1_luts);
}
void ff_jpeg2000_set_significance(Jpeg2000T1Context *t1, int x, int y, void ff_jpeg2000_set_significance(Jpeg2000T1Context *t1, int x, int y,
int negative) int negative)
{ {

@ -34,7 +34,6 @@
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#include "libavutil/thread.h"
#include "avcodec.h" #include "avcodec.h"
#include "bytestream.h" #include "bytestream.h"
#include "internal.h" #include "internal.h"
@ -2473,18 +2472,12 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s)
return 0; return 0;
} }
static av_cold void jpeg2000_init_static_data(void)
{
ff_jpeg2000_init_tier1_luts();
}
static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) static av_cold int jpeg2000_decode_init(AVCodecContext *avctx)
{ {
static AVOnce init_static_once = AV_ONCE_INIT;
Jpeg2000DecoderContext *s = avctx->priv_data; Jpeg2000DecoderContext *s = avctx->priv_data;
ff_thread_once(&init_static_once, jpeg2000_init_static_data);
ff_jpeg2000dsp_init(&s->dsp); ff_jpeg2000dsp_init(&s->dsp);
ff_jpeg2000_init_tier1_luts();
return 0; return 0;
} }
@ -2588,5 +2581,6 @@ const AVCodec ff_jpeg2000_decoder = {
.decode = jpeg2000_decode_frame, .decode = jpeg2000_decode_frame,
.priv_class = &jpeg2000_class, .priv_class = &jpeg2000_class,
.max_lowres = 5, .max_lowres = 5,
.profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles) .profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles),
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
}; };

Loading…
Cancel
Save