avcodec/mpeg4videodec: Fix data race when initializing VLCs

Both the MPEG-4 parser as well as the decoder initialized
several VLCs. There is a "static int done = 0;" in order to
guard against initializing these multiple times, but this does
not work when several threads try to initialize these VLCs
concurrently, which can happen when initializing several parsers
at the same time (they don't use the global lock that is used
for codecs without the FF_CODEC_CAP_INIT_THREADSAFE cap; actually,
they don't use any lock at all).

Since ff_mpeg4_decode_picture_header() now aborts early when called
from the parser, it no longer needs to have these VLCs initialized
at all. This commit therefore does exactly this.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2022-01-04 06:12:27 +01:00
parent f0194e860e
commit 832ead2ec4
3 changed files with 21 additions and 32 deletions

View File

@ -173,7 +173,6 @@ int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s);
int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
void ff_mpeg4_init_direct_mv(MpegEncContext *s);
void ff_mpeg4videodec_static_init(void);
int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size);

View File

@ -129,8 +129,6 @@ static av_cold int mpeg4video_parse_init(AVCodecParserContext *s)
{
struct Mp4vParseContext *pc = s->priv_data;
ff_mpeg4videodec_static_init();
pc->first_picture = 1;
pc->dec_ctx.m.quant_precision = 5;
pc->dec_ctx.m.slice_context_count = 1;

View File

@ -3386,34 +3386,6 @@ end:
return decode_vop_header(ctx, gb, parse_only);
}
av_cold void ff_mpeg4videodec_static_init(void) {
static int done = 0;
if (!done) {
static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3];
ff_mpeg4_init_rl_intra();
ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]);
ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]);
INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554);
INIT_VLC_RL(ff_rvlc_rl_inter, 1072);
INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072);
INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */,
&ff_mpeg4_DCtab_lum[0][1], 2, 1,
&ff_mpeg4_DCtab_lum[0][0], 2, 1, 512);
INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */,
&ff_mpeg4_DCtab_chrom[0][1], 2, 1,
&ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512);
INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15,
ff_sprite_trajectory_lens, 1,
NULL, 0, 0, 0, 0, 128);
INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4,
&ff_mb_type_b_tab[0][1], 2, 1,
&ff_mb_type_b_tab[0][0], 2, 1, 16);
done = 1;
}
}
int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
{
Mpeg4DecContext *ctx = avctx->priv_data;
@ -3525,6 +3497,8 @@ static int mpeg4_update_thread_context_for_user(AVCodecContext *dst,
static av_cold void mpeg4_init_static(void)
{
static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3];
INIT_VLC_STATIC_FROM_LENGTHS(&studio_luma_dc, STUDIO_INTRA_BITS, 19,
&ff_mpeg4_studio_dc_luma[0][1], 2,
&ff_mpeg4_studio_dc_luma[0][0], 2, 1,
@ -3547,7 +3521,25 @@ static av_cold void mpeg4_init_static(void)
0, INIT_VLC_STATIC_OVERLONG, NULL);
offset += studio_intra_tab[i].table_size;
}
ff_mpeg4videodec_static_init();
ff_mpeg4_init_rl_intra();
ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]);
ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]);
INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554);
INIT_VLC_RL(ff_rvlc_rl_inter, 1072);
INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072);
INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */,
&ff_mpeg4_DCtab_lum[0][1], 2, 1,
&ff_mpeg4_DCtab_lum[0][0], 2, 1, 512);
INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */,
&ff_mpeg4_DCtab_chrom[0][1], 2, 1,
&ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512);
INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15,
ff_sprite_trajectory_lens, 1,
NULL, 0, 0, 0, 0, 128);
INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4,
&ff_mb_type_b_tab[0][1], 2, 1,
&ff_mb_type_b_tab[0][0], 2, 1, 16);
}
static av_cold int decode_init(AVCodecContext *avctx)