mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-02-08 15:50:18 +00:00
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>
This commit is contained in:
parent
a1b0148366
commit
3c3712ee2b
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user