summaryrefslogtreecommitdiff
path: root/libavcodec/bitstream.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/bitstream.c')
-rw-r--r--libavcodec/bitstream.c114
1 files changed, 70 insertions, 44 deletions
diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c
index 656ac47d96..562ca1cb82 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,9 @@
* bitstream api.
*/
+#include "libavutil/atomic.h"
+#include "libavutil/avassert.h"
+#include "libavutil/qsort.h"
#include "avcodec.h"
#include "internal.h"
#include "mathops.h"
@@ -68,6 +71,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));
@@ -107,17 +112,16 @@ 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;
}
@@ -163,19 +167,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 +194,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 +231,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;
}
@@ -258,13 +266,13 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
'xxx_size' : gives the number of bytes of each entry of the 'bits'
or 'codes' tables.
- '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 +280,79 @@ 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 %x 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;
}