diff options
author | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2021-05-05 23:40:09 +0200 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2021-05-10 22:12:02 +0200 |
commit | 3c3712ee2bd9e2ec2d6bd576c5f05e169c36ad5a (patch) | |
tree | 2efe587f1c94ecfbbdd332efa31709909edd2dfc /libavcodec | |
parent | a1b01483665716a617e454414be14a749f334f63 (diff) | |
download | ffmpeg-3c3712ee2bd9e2ec2d6bd576c5f05e169c36ad5a.tar.gz |
avcodec/wmaprodec: Make decoders init-threadsafe
In this case this actually fixes a potential data race: The static VLC
tables were reinitialized every time an AVCodecContext has been
initialized; while the mutex in avcodec_open2() ensured that the VLCs
could not be initialized concurrently by multiple threads, nothing
guaranteed that these VLCs are not read concurrently (when decoding a
packet with an already initialized AVCodecContext) while another thread
initializes them. This is undefined behaviour despite the values being
written coinciding with the earlier values.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/wmaprodec.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 4b2dceb5bc..e0d00d2d37 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -93,6 +93,7 @@ #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "internal.h" @@ -309,6 +310,38 @@ static av_cold int get_rate(AVCodecContext *avctx) return avctx->sample_rate; } +static av_cold void decode_init_static(void) +{ + INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE, + scale_huffbits, 1, 1, + scale_huffcodes, 2, 2, 616); + INIT_VLC_STATIC(&sf_rl_vlc, VLCBITS, HUFF_SCALE_RL_SIZE, + scale_rl_huffbits, 1, 1, + scale_rl_huffcodes, 4, 4, 1406); + INIT_VLC_STATIC(&coef_vlc[0], VLCBITS, HUFF_COEF0_SIZE, + coef0_huffbits, 1, 1, + coef0_huffcodes, 4, 4, 2108); + INIT_VLC_STATIC(&coef_vlc[1], VLCBITS, HUFF_COEF1_SIZE, + coef1_huffbits, 1, 1, + coef1_huffcodes, 4, 4, 3912); + INIT_VLC_STATIC(&vec4_vlc, VLCBITS, HUFF_VEC4_SIZE, + vec4_huffbits, 1, 1, + vec4_huffcodes, 2, 2, 604); + INIT_VLC_STATIC(&vec2_vlc, VLCBITS, HUFF_VEC2_SIZE, + vec2_huffbits, 1, 1, + vec2_huffcodes, 2, 2, 562); + INIT_VLC_STATIC(&vec1_vlc, VLCBITS, HUFF_VEC1_SIZE, + vec1_huffbits, 1, 1, + vec1_huffcodes, 2, 2, 562); + + /** calculate sine values for the decorrelation matrix */ + for (int i = 0; i < 33; i++) + sin64[i] = sin(i * M_PI / 64.0); + + for (int i = WMAPRO_BLOCK_MIN_BITS; i <= WMAPRO_BLOCK_MAX_BITS; i++) + ff_init_ff_sine_windows(i); +} + /** *@brief Initialize the decoder. *@param avctx codec context @@ -316,6 +349,7 @@ static av_cold int get_rate(AVCodecContext *avctx) */ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int num_stream) { + static AVOnce init_static_once = AV_ONCE_INIT; uint8_t *edata_ptr = avctx->extradata; unsigned int channel_mask; int i, bits, ret; @@ -460,34 +494,6 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu } } - INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE, - scale_huffbits, 1, 1, - scale_huffcodes, 2, 2, 616); - - INIT_VLC_STATIC(&sf_rl_vlc, VLCBITS, HUFF_SCALE_RL_SIZE, - scale_rl_huffbits, 1, 1, - scale_rl_huffcodes, 4, 4, 1406); - - INIT_VLC_STATIC(&coef_vlc[0], VLCBITS, HUFF_COEF0_SIZE, - coef0_huffbits, 1, 1, - coef0_huffcodes, 4, 4, 2108); - - INIT_VLC_STATIC(&coef_vlc[1], VLCBITS, HUFF_COEF1_SIZE, - coef1_huffbits, 1, 1, - coef1_huffcodes, 4, 4, 3912); - - INIT_VLC_STATIC(&vec4_vlc, VLCBITS, HUFF_VEC4_SIZE, - vec4_huffbits, 1, 1, - vec4_huffcodes, 2, 2, 604); - - INIT_VLC_STATIC(&vec2_vlc, VLCBITS, HUFF_VEC2_SIZE, - vec2_huffbits, 1, 1, - vec2_huffcodes, 2, 2, 562); - - INIT_VLC_STATIC(&vec1_vlc, VLCBITS, HUFF_VEC1_SIZE, - vec1_huffbits, 1, 1, - vec1_huffcodes, 2, 2, 562); - /** calculate number of scale factor bands and their offsets for every possible block size */ for (i = 0; i < num_possible_block_sizes; i++) { @@ -554,7 +560,6 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu /** init MDCT windows: simple sine window */ for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) { const int win_idx = WMAPRO_BLOCK_MAX_BITS - i; - ff_init_ff_sine_windows(win_idx); s->windows[WMAPRO_BLOCK_SIZES - i - 1] = ff_sine_windows[win_idx]; } @@ -566,15 +571,13 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu s->subwoofer_cutoffs[i] = av_clip(cutoff, 4, block_size); } - /** calculate sine values for the decorrelation matrix */ - for (i = 0; i < 33; i++) - sin64[i] = sin(i*M_PI / 64.0); - if (avctx->debug & FF_DEBUG_BITSTREAM) dump_context(s); avctx->channel_layout = channel_mask; + ff_thread_once(&init_static_once, decode_init_static); + return 0; } @@ -2018,10 +2021,10 @@ const AVCodec ff_wmapro_decoder = { .close = wmapro_decode_end, .decode = wmapro_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = wmapro_flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; const AVCodec ff_xma1_decoder = { @@ -2034,9 +2037,9 @@ const AVCodec ff_xma1_decoder = { .close = xma_decode_end, .decode = xma_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; const AVCodec ff_xma2_decoder = { @@ -2050,7 +2053,7 @@ const AVCodec ff_xma2_decoder = { .decode = xma_decode_packet, .flush = xma_flush, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; |