[FFmpeg-cvslog] avcodec/wmaprodec: Make decoders init-threadsafe
Andreas Rheinhardt
git at videolan.org
Tue May 11 01:21:08 EEST 2021
ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Wed May 5 23:40:09 2021 +0200| [3c3712ee2bd9e2ec2d6bd576c5f05e169c36ad5a] | committer: Andreas Rheinhardt
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 at outlook.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3c3712ee2bd9e2ec2d6bd576c5f05e169c36ad5a
---
libavcodec/wmaprodec.c | 75 ++++++++++++++++++++++++++------------------------
1 file 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,
};
More information about the ffmpeg-cvslog
mailing list