Andreas Rheinhardt: > For lots of static VLCs, the number of bits is not read from > VLC.bits, but rather a compile-constant that is hardcoded > at the callsite of get_vlc2(). Only VLC.table is ever used > and not using it directly is just an unnecessary indirection. > > This commit adds helper functions and macros to avoid the VLC > structure when initializing VLC tables; there are 2x2 functions: > Two choices for init_sparse or from_lengths and two choices > for "overlong" initialization (as used when multiple VLCs are > initialized that share the same underlying table). > > Signed-off-by: Andreas Rheinhardt <andreas.rheinha...@outlook.com> > --- > libavcodec/vlc.c | 68 +++++++++++++++++++++++++++++++ > libavcodec/vlc.h | 102 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 170 insertions(+) > > diff --git a/libavcodec/vlc.c b/libavcodec/vlc.c > index 21b9fffe27..b5de0bd24e 100644 > --- a/libavcodec/vlc.c > +++ b/libavcodec/vlc.c > @@ -350,6 +350,74 @@ fail: > return AVERROR_INVALIDDATA; > } > > +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, > + const void *symbols, int > symbols_wrap, int symbols_size, > + int offset, int flags) > +{ > + VLC vlc = { .table = table, .table_allocated = table_size }; > + > + ff_vlc_init_from_lengths(&vlc, nb_bits, nb_codes, lens, lens_wrap, > + symbols, symbols_wrap, symbols_size, > + offset, flags | VLC_INIT_USE_STATIC, NULL); > +} > + > +av_cold const VLCElem *ff_vlc_init_tables_from_lengths(VLCInitState *state, > + int nb_bits, int > nb_codes, > + const int8_t *lens, > int lens_wrap, > + const void *symbols, > int symbols_wrap, int symbols_size, > + int offset, int flags) > +{ > + VLC vlc = { .table = state->table, .table_allocated = state->size }; > + > + ff_vlc_init_from_lengths(&vlc, nb_bits, nb_codes, lens, lens_wrap, > + symbols, symbols_wrap, symbols_size, > + offset, flags | VLC_INIT_STATIC_OVERLONG, NULL); > + > + state->table += vlc.table_size; > + state->size -= vlc.table_size; > + > + return vlc.table; > +} > + > +av_cold void ff_vlc_init_table_sparse(VLCElem table[], int table_size, > + 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, > + int flags) > +{ > + VLC vlc = { .table = table, .table_allocated = table_size }; > + > + ff_vlc_init_sparse(&vlc, nb_bits, nb_codes, > + bits, bits_wrap, bits_size, > + codes, codes_wrap, codes_size, > + symbols, symbols_wrap, symbols_size, > + flags | VLC_INIT_USE_STATIC); > +} > + > +av_cold const VLCElem *ff_vlc_init_tables_sparse(VLCInitState *state, > + 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, > + int flags) > +{ > + VLC vlc = { .table = state->table, .table_allocated = state->size }; > + > + ff_vlc_init_sparse(&vlc, nb_bits, nb_codes, > + bits, bits_wrap, bits_size, > + codes, codes_wrap, codes_size, > + symbols, symbols_wrap, symbols_size, > + flags | VLC_INIT_STATIC_OVERLONG); > + > + state->table += vlc.table_size; > + state->size -= vlc.table_size; > + > + return vlc.table; > +} > + > static void add_level(VLC_MULTI_ELEM *table, const int nb_elems, > const int num, const int numbits, > const VLCcode *buf, > diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h > index 3f7c033a78..679666801a 100644 > --- a/libavcodec/vlc.h > +++ b/libavcodec/vlc.h > @@ -19,8 +19,11 @@ > #ifndef AVCODEC_VLC_H > #define AVCODEC_VLC_H > > +#include <stddef.h> > #include <stdint.h> > > +#include "libavutil/macros.h" > + > #define VLC_MULTI_MAX_SYMBOLS 6 > > // When changing this, be sure to also update tableprint_vlc.h accordingly. > @@ -223,4 +226,103 @@ void ff_vlc_free(VLC *vlc); > NULL); \ > } while (0) > > +/** > + * For static VLCs, the number of bits can often be hardcoded > + * at each get_vlc2() callsite. Then using a full VLC would be uneconomical, > + * because only VLC.table would ever be accessed after initialization. > + * The following functions provide wrappers around the relevant ff_vlc_init_* > + * functions suitable for said task. > + * > + * The ff_vlc_init_tables_* functions are intended to be used for > initializing > + * a series of VLCs. The user initializes a VLCInitState with the details > + * about the underlying array of VLCElem; it is automatically updated by > + * the ff_vlc_init_tables_* functions (i.e. table is incremented and size > + * decremented by the number of elements of the current table). > + * The VLC_INIT_STATIC_OVERLONG flag is also automatically added. > + * These functions return a pointer to the table just initialized, > + * potentially to be used in arrays of pointer to VLC tables. > + * > + * The ff_vlc_init_table_* functions are intended to be used for initializing > + * a single VLC table, given by table and table_size. The VLC_INIT_USE_STATIC > + * flag is automatically added. > + */ > + > +typedef struct VLCInitState { > + VLCElem *table; ///< points to where the next VLC table will be placed > + unsigned size; ///< remaining number of elements in table > +} VLCInitState; > + > +#define VLC_INIT_STATE(_table) { .table = (_table), .size = > FF_ARRAY_ELEMS(_table) } > + > +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, > + const void *symbols, int symbols_wrap, > int symbols_size, > + int offset, int flags); > + > +const VLCElem *ff_vlc_init_tables_from_lengths(VLCInitState *state, > + int nb_bits, int nb_codes, > + const int8_t *lens, int > lens_wrap, > + const void *symbols, int > symbols_wrap, int symbols_size, > + int offset, int flags); > + > +void ff_vlc_init_table_sparse(VLCElem table[], int table_size, > + 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, > + int flags); > + > +const VLCElem *ff_vlc_init_tables_sparse(VLCInitState *state, > + 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, > + int flags); > + > +static inline > +const VLCElem *ff_vlc_init_tables(VLCInitState *state, > + int nb_bits, int nb_codes, > + const void *bits, int bits_wrap, int > bits_size, > + const void *codes, int codes_wrap, int > codes_size, > + int flags) > +{ > + return ff_vlc_init_tables_sparse(state, nb_bits, nb_codes, > + bits, bits_wrap, bits_size, > + codes, codes_wrap, codes_size, > + NULL, 0, 0, flags); > +} > + > +#define VLC_INIT_STATIC_SPARSE_TABLE(vlc_table, nb_bits, nb_codes, \ > + bits, bits_wrap, bits_size, \ > + codes, codes_wrap, codes_size, \ > + symbols, symbols_wrap, symbols_size, \ > + flags) \ > + ff_vlc_init_table_sparse(vlc_table, FF_ARRAY_ELEMS(vlc_table), \ > + (nb_bits), (nb_codes), \ > + (bits), (bits_wrap), (bits_size), \ > + (codes), (codes_wrap), (codes_size), \ > + (symbols), (symbols_wrap), (symbols_size), \ > + (flags)) > + > +#define VLC_INIT_STATIC_TABLE(vlc_table, nb_bits, nb_codes, \ > + bits, bits_wrap, bits_size, \ > + codes, codes_wrap, codes_size, \ > + flags) \ > + ff_vlc_init_table_sparse(vlc_table, FF_ARRAY_ELEMS(vlc_table), \ > + (nb_bits), (nb_codes), \ > + (bits), (bits_wrap), (bits_size), \ > + (codes), (codes_wrap), (codes_size), \ > + NULL, 0, 0, (flags)) > + > +#define VLC_INIT_STATIC_TABLE_FROM_LENGTHS(vlc_table, nb_bits, nb_codes, \ > + lens, lens_wrap, \ > + syms, syms_wrap, syms_size, \ > + offset, flags) \ > + ff_vlc_init_table_from_lengths(vlc_table, FF_ARRAY_ELEMS(vlc_table), \ > + (nb_bits), (nb_codes), \ > + (lens), (lens_wrap), \ > + (syms), (syms_wrap), (syms_size), \ > + (offset), (flags)) > + > #endif /* AVCODEC_VLC_H */
Will apply this patchset tonight (with the mobiclip bug fixed) unless there are objections. - Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".