* bitstream api.
*/
+#include "libavutil/atomic.h"
#include "libavutil/avassert.h"
#include "avcodec.h"
#include "mathops.h"
{
VLCcode *buf;
int i, j, ret;
+ VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34
+ void *state;
vlc->bits = nb_bits;
if (flags & INIT_VLC_USE_NEW_STATIC) {
- VLC dyn_vlc = *vlc;
-
- if (vlc->table_size)
- return 0;
-
- ret = ff_init_vlc_sparse(&dyn_vlc, nb_bits, nb_codes,
- bits, bits_wrap, bits_size,
- codes, codes_wrap, codes_size,
- symbols, symbols_wrap, symbols_size,
- flags & ~INIT_VLC_USE_NEW_STATIC);
- av_assert0(ret >= 0);
- av_assert0(dyn_vlc.table_size <= vlc->table_allocated);
- if (dyn_vlc.table_size < vlc->table_allocated)
- av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", dyn_vlc.table_size, vlc->table_allocated);
- memcpy(vlc->table, dyn_vlc.table, dyn_vlc.table_size * sizeof(*vlc->table));
- vlc->table_size = dyn_vlc.table_size;
- ff_free_vlc(&dyn_vlc);
- return 0;
+ 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));
+ buf = localbuf;
} else {
vlc->table = NULL;
vlc->table_allocated = 0;
vlc->table_size = 0;
- }
- av_dlog(NULL, "build table nb_codes=%d\n", nb_codes);
+ buf = av_malloc((nb_codes + 1) * sizeof(VLCcode));
+ if (!buf)
+ return AVERROR(ENOMEM);
+ }
- buf = av_malloc((nb_codes + 1) * sizeof(VLCcode));
- if (!buf)
- return AVERROR(ENOMEM);
av_assert0(symbols_size <= 2 || !symbols);
j = 0;
ret = build_table(vlc, nb_bits, nb_codes, buf, flags);
- av_free(buf);
- if (ret < 0) {
- av_freep(&vlc->table);
- return ret;
+ if (flags & INIT_VLC_USE_NEW_STATIC) {
+ if(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);
+ } else {
+ av_free(buf);
+ if (ret < 0) {
+ av_freep(&vlc->table);
+ return ret;
+ }
}
return 0;
}