[FFmpeg-devel] [PATCH 01/61] avcodec/vlc: Add functions to init static VLCElem[] without VLC
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Tue Oct 31 01:08:04 EET 2023
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.rheinhardt at 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
More information about the ffmpeg-devel
mailing list