]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/bitstream.c
avcodec/dvdsubdec: Fix off-by-one error
[ffmpeg] / libavcodec / bitstream.c
index 2d3f6067d39e82f9099c413f13d4f6597bc69e93..d041643eff6ec6ab947f409826a1259dbf29c913 100644 (file)
@@ -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 i, j, k, n, nb, inc;
     uint32_t code;
-    VLC_TYPE (*table)[2];
+    volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent a internal compiler error in gcc 4.2
 
     table_size = 1 << table_nb_bits;
     if (table_nb_bits > 30)
@@ -172,12 +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);
     if (table_index < 0)
         return table_index;
-    table = &vlc->table[table_index];
-
-    for (i = 0; i < table_size; i++) {
-        table[i][1] = 0; //bits
-        table[i][0] = -1; //codes
-    }
+    table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index];
 
     /* first pass: map codes and compute auxiliary table sizes */
     for (i = 0; i < nb_codes; i++) {
@@ -195,8 +190,9 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
                 inc = 1 << n;
             }
             for (k = 0; k < nb; k++) {
+                int bits = table[j][1];
                 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");
                     return AVERROR_INVALIDDATA;
                 }
@@ -231,12 +227,17 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
             if (index < 0)
                 return index;
             /* 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
-            av_assert0(table[j][0] == index);
             i = k-1;
         }
     }
+
+    for (i = 0; i < table_size; i++) {
+        if (table[i][1] == 0) //bits
+            table[i][0] = -1; //codes
+    }
+
     return table_index;
 }
 
@@ -267,7 +268,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
    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 *codes, int codes_wrap, int codes_size,
                        const void *symbols, int symbols_wrap, int symbols_size,
@@ -276,19 +277,16 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
     VLCcode *buf;
     int i, j, ret;
     VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34
-    void *state;
+    VLC localvlc, *vlc;
 
+    vlc = vlc_arg;
     vlc->bits = nb_bits;
     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));
         buf = localbuf;
+        localvlc = *vlc_arg;
+        vlc = &localvlc;
+        vlc->table_size = 0;
     } else {
         vlc->table           = NULL;
         vlc->table_allocated = 0;
@@ -341,9 +339,9 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
     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);
+        *vlc_arg = *vlc;
     } else {
         av_free(buf);
         if (ret < 0) {