Commit e6f9fc4a authored by Michael Niedermayer's avatar Michael Niedermayer

avcodec/bitstream: try to make vlc init code inherently thread safe

also remove spinlock, it doesnt work on AIX
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent f7f96cf4
...@@ -163,7 +163,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ...@@ -163,7 +163,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
int table_size, table_index, index, code_prefix, symbol, subtable_bits; int table_size, table_index, index, code_prefix, symbol, subtable_bits;
int i, j, k, n, nb, inc; int i, j, k, n, nb, inc;
uint32_t code; uint32_t code;
VLC_TYPE (*table)[2]; volatile VLC_TYPE (*table)[2];
table_size = 1 << table_nb_bits; table_size = 1 << table_nb_bits;
if (table_nb_bits > 30) if (table_nb_bits > 30)
...@@ -172,7 +172,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ...@@ -172,7 +172,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size);
if (table_index < 0) if (table_index < 0)
return table_index; return table_index;
table = &vlc->table[table_index]; table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index];
/* first pass: map codes and compute auxiliary table sizes */ /* first pass: map codes and compute auxiliary table sizes */
for (i = 0; i < nb_codes; i++) { for (i = 0; i < nb_codes; i++) {
...@@ -190,8 +190,9 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ...@@ -190,8 +190,9 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
inc = 1 << n; inc = 1 << n;
} }
for (k = 0; k < nb; k++) { for (k = 0; k < nb; k++) {
int bits = table[j][1];
av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n);
if (table[j][1] /*bits*/ != 0) { if (bits != 0 && bits != n) {
av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); av_log(NULL, AV_LOG_ERROR, "incorrect codes\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
...@@ -226,7 +227,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ...@@ -226,7 +227,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
if (index < 0) if (index < 0)
return index; return index;
/* note: realloc has been done, so reload tables */ /* note: realloc has been done, so reload tables */
table = &vlc->table[table_index]; table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index];
table[j][0] = index; //code table[j][0] = index; //code
av_assert0(table[j][0] == index); av_assert0(table[j][0] == index);
i = k-1; i = k-1;
...@@ -268,7 +269,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, ...@@ -268,7 +269,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
'use_static' should be set to 1 for tables, which should be freed 'use_static' should be set to 1 for tables, which should be freed
with av_free_static(), 0 if ff_free_vlc() will be used. with av_free_static(), 0 if ff_free_vlc() will be used.
*/ */
int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes,
const void *bits, int bits_wrap, int bits_size, const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size, const void *codes, int codes_wrap, int codes_size,
const void *symbols, int symbols_wrap, int symbols_size, const void *symbols, int symbols_wrap, int symbols_size,
...@@ -277,19 +278,16 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, ...@@ -277,19 +278,16 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
VLCcode *buf; VLCcode *buf;
int i, j, ret; int i, j, ret;
VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34 VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34
void *state; VLC localvlc, *vlc;
vlc = vlc_arg;
vlc->bits = nb_bits; vlc->bits = nb_bits;
if (flags & INIT_VLC_USE_NEW_STATIC) { if (flags & INIT_VLC_USE_NEW_STATIC) {
while (state = avpriv_atomic_ptr_cas(&vlc->init_state, NULL, vlc)) {
if (state == vlc + 1) {
av_assert0(vlc->table_size && vlc->table_size == vlc->table_allocated);
return 0;
}
}
av_assert0(!vlc->table_size);
av_assert0(nb_codes + 1 <= FF_ARRAY_ELEMS(localbuf)); av_assert0(nb_codes + 1 <= FF_ARRAY_ELEMS(localbuf));
buf = localbuf; buf = localbuf;
localvlc = *vlc_arg;
vlc = &localvlc;
vlc->table_size = 0;
} else { } else {
vlc->table = NULL; vlc->table = NULL;
vlc->table_allocated = 0; vlc->table_allocated = 0;
...@@ -342,9 +340,9 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, ...@@ -342,9 +340,9 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
if (flags & INIT_VLC_USE_NEW_STATIC) { if (flags & INIT_VLC_USE_NEW_STATIC) {
if(vlc->table_size != vlc->table_allocated) if(vlc->table_size != vlc->table_allocated)
av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated);
state = avpriv_atomic_ptr_cas(&vlc->init_state, vlc, vlc+1);
av_assert0(state == vlc);
av_assert0(ret >= 0); av_assert0(ret >= 0);
*vlc_arg = *vlc;
} else { } else {
av_free(buf); av_free(buf);
if (ret < 0) { if (ret < 0) {
......
...@@ -64,7 +64,6 @@ typedef struct VLC { ...@@ -64,7 +64,6 @@ typedef struct VLC {
int bits; int bits;
VLC_TYPE (*table)[2]; ///< code, bits VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated; int table_size, table_allocated;
void * volatile init_state;
} VLC; } VLC;
typedef struct RL_VLC_ELEM { typedef struct RL_VLC_ELEM {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment