diff options
Diffstat (limited to 'libavcodec/bitstream.c')
-rw-r--r-- | libavcodec/bitstream.c | 128 |
1 files changed, 74 insertions, 54 deletions
diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index c7eba2913f..ed528fe4af 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -6,20 +6,20 @@ * * alternative bitstream reader & writer by Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -28,6 +28,8 @@ * bitstream api. */ +#include "libavutil/avassert.h" +#include "libavutil/qsort.h" #include "avcodec.h" #include "internal.h" #include "mathops.h" @@ -68,6 +70,8 @@ void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) if (length == 0) return; + av_assert0(length <= put_bits_left(pb)); + if (CONFIG_SMALL || words < 16 || put_bits_count(pb) & 7) { for (i = 0; i < words; i++) put_bits(pb, 16, AV_RB16(src + 2 * i)); @@ -94,9 +98,11 @@ void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) case 2: \ v = *(const uint16_t *)ptr; \ break; \ - default: \ + case 4: \ v = *(const uint32_t *)ptr; \ break; \ + default: \ + av_assert1(0); \ } \ } @@ -107,29 +113,20 @@ static int alloc_table(VLC *vlc, int size, int use_static) vlc->table_size += size; if (vlc->table_size > vlc->table_allocated) { - int err; if (use_static) - return AVERROR_BUG; + abort(); // cannot do anything, init_vlc() is used with too little memory vlc->table_allocated += (1 << vlc->bits); - if ((err = av_reallocp(&vlc->table, - sizeof(VLC_TYPE) * 2 * - vlc->table_allocated)) < 0) { + vlc->table = av_realloc_f(vlc->table, vlc->table_allocated, sizeof(VLC_TYPE) * 2); + if (!vlc->table) { vlc->table_allocated = 0; vlc->table_size = 0; - return err; + return AVERROR(ENOMEM); } + memset(vlc->table + vlc->table_allocated - (1 << vlc->bits), 0, sizeof(VLC_TYPE) * 2 << vlc->bits); } return index; } -static av_always_inline uint32_t bitswap_32(uint32_t x) -{ - return (uint32_t)ff_reverse[ x & 0xFF] << 24 | - (uint32_t)ff_reverse[(x >> 8) & 0xFF] << 16 | - (uint32_t)ff_reverse[(x >> 16) & 0xFF] << 8 | - (uint32_t)ff_reverse[ x >> 24]; -} - typedef struct VLCcode { uint8_t bits; uint16_t symbol; @@ -163,19 +160,16 @@ 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 an internal compiler error in gcc 4.2 table_size = 1 << table_nb_bits; + if (table_nb_bits > 30) + return -1; table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); ff_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++) { @@ -193,8 +187,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]; ff_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; } @@ -229,11 +224,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 i = k-1; } } + + for (i = 0; i < table_size; i++) { + if (table[i][1] == 0) //bits + table[i][0] = -1; //codes + } + return table_index; } @@ -256,15 +257,15 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, 'bits' or 'codes' tables. 'xxx_size' : gives the number of bytes of each entry of the 'bits' - or 'codes' tables. + or 'codes' tables. Currently 1,2 and 4 are supported. - 'wrap' and 'size' allows to use any memory configuration and types + 'wrap' and 'size' make it possible to use any memory configuration and types (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. '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, @@ -272,61 +273,80 @@ 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 + VLC localvlc, *vlc; + vlc = vlc_arg; vlc->bits = nb_bits; if (flags & INIT_VLC_USE_NEW_STATIC) { - if (vlc->table_size && vlc->table_size == vlc->table_allocated) { - return 0; - } else if (vlc->table_size) { - return AVERROR_BUG; - } + 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; vlc->table_size = 0; - } - ff_dlog(NULL, "build table nb_codes=%d\n", nb_codes); + buf = av_malloc_array((nb_codes + 1), sizeof(VLCcode)); + if (!buf) + return AVERROR(ENOMEM); + } - buf = av_malloc((nb_codes + 1) * sizeof(VLCcode)); - if (!buf) - return AVERROR(ENOMEM); - assert(symbols_size <= 2 || !symbols); + av_assert0(symbols_size <= 2 || !symbols); j = 0; -#define COPY(condition) \ +#define COPY(condition)\ for (i = 0; i < nb_codes; i++) { \ GET_DATA(buf[j].bits, bits, i, bits_wrap, bits_size); \ if (!(condition)) \ continue; \ + if (buf[j].bits > 3*nb_bits || buf[j].bits>32) { \ + av_log(NULL, AV_LOG_ERROR, "Too long VLC (%d) in init_vlc\n", buf[j].bits);\ + if (!(flags & INIT_VLC_USE_NEW_STATIC)) \ + av_free(buf); \ + return -1; \ + } \ GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size); \ + if (buf[j].code >= (1LL<<buf[j].bits)) { \ + av_log(NULL, AV_LOG_ERROR, "Invalid code %"PRIx32" for %d in " \ + "init_vlc\n", buf[j].code, i); \ + if (!(flags & INIT_VLC_USE_NEW_STATIC)) \ + av_free(buf); \ + return -1; \ + } \ if (flags & INIT_VLC_LE) \ buf[j].code = bitswap_32(buf[j].code); \ else \ buf[j].code <<= 32 - buf[j].bits; \ if (symbols) \ GET_DATA(buf[j].symbol, symbols, i, symbols_wrap, symbols_size) \ - else \ - buf[j].symbol = i; \ + else \ + buf[j].symbol = i; \ j++; \ } COPY(buf[j].bits > nb_bits); // qsort is the slowest part of init_vlc, and could probably be improved or avoided - qsort(buf, j, sizeof(VLCcode), compare_vlcspec); + AV_QSORT(buf, j, struct VLCcode, compare_vlcspec); COPY(buf[j].bits && buf[j].bits <= nb_bits); nb_codes = j; 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); + + av_assert0(ret >= 0); + *vlc_arg = *vlc; + } else { + av_free(buf); + if (ret < 0) { + av_freep(&vlc->table); + return ret; + } } - if ((flags & INIT_VLC_USE_NEW_STATIC) && - vlc->table_size != vlc->table_allocated) - av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", - vlc->table_size, vlc->table_allocated); return 0; } |