[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