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/intfloat.h"
 | 
				
			||||||
#include "libavutil/intreadwrite.h"
 | 
					#include "libavutil/intreadwrite.h"
 | 
				
			||||||
#include "libavutil/mem_internal.h"
 | 
					#include "libavutil/mem_internal.h"
 | 
				
			||||||
 | 
					#include "libavutil/thread.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "avcodec.h"
 | 
					#include "avcodec.h"
 | 
				
			||||||
#include "internal.h"
 | 
					#include "internal.h"
 | 
				
			||||||
@ -309,6 +310,38 @@ static av_cold int get_rate(AVCodecContext *avctx)
 | 
				
			|||||||
    return avctx->sample_rate;
 | 
					    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.
 | 
					 *@brief Initialize the decoder.
 | 
				
			||||||
 *@param avctx codec context
 | 
					 *@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 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;
 | 
					    uint8_t *edata_ptr = avctx->extradata;
 | 
				
			||||||
    unsigned int channel_mask;
 | 
					    unsigned int channel_mask;
 | 
				
			||||||
    int i, bits, ret;
 | 
					    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
 | 
					    /** calculate number of scale factor bands and their offsets
 | 
				
			||||||
        for every possible block size */
 | 
					        for every possible block size */
 | 
				
			||||||
    for (i = 0; i < num_possible_block_sizes; i++) {
 | 
					    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 */
 | 
					    /** init MDCT windows: simple sine window */
 | 
				
			||||||
    for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
 | 
					    for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
 | 
				
			||||||
        const int win_idx = WMAPRO_BLOCK_MAX_BITS - 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];
 | 
					        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);
 | 
					        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)
 | 
					    if (avctx->debug & FF_DEBUG_BITSTREAM)
 | 
				
			||||||
        dump_context(s);
 | 
					        dump_context(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    avctx->channel_layout = channel_mask;
 | 
					    avctx->channel_layout = channel_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ff_thread_once(&init_static_once, decode_init_static);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2018,10 +2021,10 @@ const AVCodec ff_wmapro_decoder = {
 | 
				
			|||||||
    .close          = wmapro_decode_end,
 | 
					    .close          = wmapro_decode_end,
 | 
				
			||||||
    .decode         = wmapro_decode_packet,
 | 
					    .decode         = wmapro_decode_packet,
 | 
				
			||||||
    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
 | 
					    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
 | 
				
			||||||
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
 | 
					 | 
				
			||||||
    .flush          = wmapro_flush,
 | 
					    .flush          = wmapro_flush,
 | 
				
			||||||
    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 | 
					    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 | 
				
			||||||
                                                      AV_SAMPLE_FMT_NONE },
 | 
					                                                      AV_SAMPLE_FMT_NONE },
 | 
				
			||||||
 | 
					    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AVCodec ff_xma1_decoder = {
 | 
					const AVCodec ff_xma1_decoder = {
 | 
				
			||||||
@ -2034,9 +2037,9 @@ const AVCodec ff_xma1_decoder = {
 | 
				
			|||||||
    .close          = xma_decode_end,
 | 
					    .close          = xma_decode_end,
 | 
				
			||||||
    .decode         = xma_decode_packet,
 | 
					    .decode         = xma_decode_packet,
 | 
				
			||||||
    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
 | 
					    .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,
 | 
					    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 | 
				
			||||||
                                                      AV_SAMPLE_FMT_NONE },
 | 
					                                                      AV_SAMPLE_FMT_NONE },
 | 
				
			||||||
 | 
					    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AVCodec ff_xma2_decoder = {
 | 
					const AVCodec ff_xma2_decoder = {
 | 
				
			||||||
@ -2050,7 +2053,7 @@ const AVCodec ff_xma2_decoder = {
 | 
				
			|||||||
    .decode         = xma_decode_packet,
 | 
					    .decode         = xma_decode_packet,
 | 
				
			||||||
    .flush          = xma_flush,
 | 
					    .flush          = xma_flush,
 | 
				
			||||||
    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
 | 
					    .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,
 | 
					    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 | 
				
			||||||
                                                      AV_SAMPLE_FMT_NONE },
 | 
					                                                      AV_SAMPLE_FMT_NONE },
 | 
				
			||||||
 | 
					    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user