/* * API for creating VLC trees * Copyright (c) 2000, 2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * Copyright (c) 2010 Loren Merritt * * This file is part of FFmpeg. * * 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. * * 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedefstruct VLCcode {
uint8_t bits;
VLCBaseType symbol; /** codeword, with the first bit-to-be-read in the msb
* (even if intended for a little-endian bitstream reader) */
uint32_t code;
} VLCcode;
staticint vlc_common_init(VLC *vlc, int nb_bits, int nb_codes,
VLCcode **buf, int flags)
{
vlc->bits = nb_bits;
vlc->table_size = 0; if (flags & VLC_INIT_USE_STATIC) {
av_assert0(nb_codes <= LOCALBUF_ELEMS);
} else {
vlc->table = NULL;
vlc->table_allocated = 0;
} if (nb_codes > LOCALBUF_ELEMS) {
*buf = av_malloc_array(nb_codes, sizeof(VLCcode)); if (!*buf) return AVERROR(ENOMEM);
}
/** * Build VLC decoding tables suitable for use with get_vlc(). * * @param vlc the context to be initialized * * @param table_nb_bits max length of vlc codes to store directly in this table * (Longer codes are delegated to subtables.) * * @param nb_codes number of elements in codes[] * * @param codes descriptions of the vlc codes * These must be ordered such that codes going into the same subtable are contiguous. * Sorting by VLCcode.code is sufficient, though not necessary.
*/ staticint build_table(VLC *vlc, int table_nb_bits, int nb_codes,
VLCcode *codes, int flags)
{ int table_size, table_index;
VLCElem *table;
/* first pass: map codes and compute auxiliary table sizes */ for (int i = 0; i < nb_codes; i++) { int n = codes[i].bits;
uint32_t code = codes[i].code; int symbol = codes[i].symbol;
ff_dlog(NULL, "i=%d n=%d code=0x%"PRIx32"\n", i, n, code); if (n <= table_nb_bits) { /* no need to add another table */ int j = code >> (32 - table_nb_bits); int nb = 1 << (table_nb_bits - n); int inc = 1;
if (flags & VLC_INIT_OUTPUT_LE) {
j = bitswap_32(code);
inc = 1 << n;
} for (int k = 0; k < nb; k++) { int bits = table[j].len; int oldsym = table[j].sym;
ff_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); if ((bits || oldsym) && (bits != n || oldsym != symbol)) {
av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); return AVERROR_INVALIDDATA;
}
table[j].len = n;
table[j].sym = symbol;
j += inc;
}
} else { /* fill auxiliary table recursively */
uint32_t code_prefix; int index, subtable_bits, j, k;
n -= table_nb_bits;
code_prefix = code >> (32 - table_nb_bits);
subtable_bits = n;
codes[i].bits = n;
codes[i].code = code << table_nb_bits; for (k = i + 1; k < nb_codes; k++) {
n = codes[k].bits - table_nb_bits; if (n <= 0) break;
code = codes[k].code; if (code >> (32 - table_nb_bits) != code_prefix) break;
codes[k].bits = n;
codes[k].code = code << table_nb_bits;
subtable_bits = FFMAX(subtable_bits, n);
}
subtable_bits = FFMIN(subtable_bits, table_nb_bits);
j = (flags & VLC_INIT_OUTPUT_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix;
table[j].len = -subtable_bits;
ff_dlog(NULL, "%4x: n=%d (subtable)\n",
j, codes[i].bits + table_nb_bits);
index = build_table(vlc, subtable_bits, k-i, codes+i, flags); if (index < 0) return index; /* note: realloc has been done, so reload tables */
table = &vlc->table[table_index];
table[j].sym = index; if (table[j].sym != index) {
avpriv_request_sample(NULL, "strange codes"); return AVERROR_PATCHWELCOME;
}
i = k-1;
}
}
for (int i = 0; i < table_size; i++) { if (table[i].len == 0)
table[i].sym = -1;
}
return table_index;
}
staticint vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, int flags, VLCcode localbuf[LOCALBUF_ELEMS])
{ int ret = build_table(vlc, nb_bits, nb_codes, codes, flags);
if (flags & VLC_INIT_USE_STATIC) { if (vlc->table_size != vlc->table_allocated &&
!(flags & (VLC_INIT_STATIC_OVERLONG & ~VLC_INIT_USE_STATIC)))
av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated);
av_assert0(ret >= 0);
} else { if (codes != localbuf)
av_free(codes); if (ret < 0) {
av_freep(&vlc->table); return ret;
}
} return 0;
}
int ff_vlc_init_sparse(VLC *vlc, int nb_bits, int nb_codes, constvoid *bits, int bits_wrap, int bits_size, constvoid *codes, int codes_wrap, int codes_size, constvoid *symbols, int symbols_wrap, int symbols_size, int flags)
{
VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; int j, ret;
ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret;
av_assert0(symbols_size <= 2 || !symbols);
j = 0; #define COPY(condition)\ for (int i = 0; i < nb_codes; i++) { \ unsigned len; \
GET_DATA(len, bits, i, bits_wrap, bits_size); \ if (!(condition)) \ continue; \ if (len > 3*nb_bits || len > 32) { \
av_log(NULL, AV_LOG_ERROR, "Too long VLC (%u) in vlc_init\n", len);\ if (buf != localbuf) \
av_free(buf); \ return AVERROR(EINVAL); \
} \
buf[j].bits = len; \
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 " \ "vlc_init\n", buf[j].code, i); \ if (buf != localbuf) \
av_free(buf); \ return AVERROR(EINVAL); \
} \ if (flags & VLC_INIT_INPUT_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; \
j++; \
}
COPY(len > nb_bits); // qsort is the slowest part of vlc_init, and could probably be improved or avoided
AV_QSORT(buf, j, struct VLCcode, compare_vlcspec);
COPY(len && len <= nb_bits);
nb_codes = j;
int ff_vlc_init_from_lengths(VLC *vlc, int nb_bits, int nb_codes, const int8_t *lens, int lens_wrap, constvoid *symbols, int symbols_wrap, int symbols_size, int offset, int flags, void *logctx)
{
VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf;
uint64_t code; int ret, j, len_max = FFMIN(32, 3 * nb_bits);
ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret;
j = code = 0; for (int i = 0; i < nb_codes; i++, lens += lens_wrap) { int len = *lens; if (len > 0) { unsigned sym;
av_cold void ff_vlc_init_table_from_lengths(VLCElem table[], int table_size, int nb_bits, int nb_codes, const int8_t *lens, int lens_wrap, constvoid *symbols, int symbols_wrap, int symbols_size, int offset, int flags)
{
VLC vlc = { .table = table, .table_allocated = table_size };
av_cold void ff_vlc_init_table_sparse(VLCElem table[], int table_size, int nb_bits, int nb_codes, constvoid *bits, int bits_wrap, int bits_size, constvoid *codes, int codes_wrap, int codes_size, constvoid *symbols, int symbols_wrap, int symbols_size, int flags)
{
VLC vlc = { .table = table, .table_allocated = table_size };
av_cold const VLCElem *ff_vlc_init_tables_sparse(VLCInitState *state, int nb_bits, int nb_codes, constvoid *bits, int bits_wrap, int bits_size, constvoid *codes, int codes_wrap, int codes_size, constvoid *symbols, int symbols_wrap, int symbols_size, int flags)
{
VLC vlc = { .table = state->table, .table_allocated = state->size };
for (int n = nb_codes - count0; n < nb_codes; n++) {
minbits = FFMIN(minbits, buf[n].bits);
maxbits = FFMAX(maxbits, buf[n].bits);
}
av_assert0(maxbits <= numbits);
for (max = nb_codes; max > nb_codes - count0; max--) { // We can only add a code that fits with the shortest other code into the table // We assume the table is sorted by bits and we skip subtables which from our // point of view are basically random corrupted entries // If we have not a single useable vlc we end with max = nb_codes if (buf[max - 1].bits+minbits > numbits) break;
}
int ff_vlc_init_multi_from_lengths(VLC *vlc, VLC_MULTI *multi, int nb_bits, int nb_elems, int nb_codes, const int8_t *lens, int lens_wrap, constvoid *symbols, int symbols_wrap, int symbols_size, int offset, int flags, void *logctx)
{
VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf;
uint64_t code; int ret, j, len_max = FFMIN(32, 3 * nb_bits);
ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret;
multi->table = av_malloc(sizeof(*multi->table) << nb_bits); if (!multi->table) goto fail;
j = code = 0; for (int i = 0; i < nb_codes; i++, lens += lens_wrap) { int len = *lens; if (len > 0) { unsigned sym;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.