diff mbox series

[FFmpeg-devel,01/61] avcodec/vlc: Add functions to init static VLCElem[] without VLC

Message ID GV1P250MB073754E215A199E7219CC13A8FC3A@GV1P250MB0737.EURP250.PROD.OUTLOOK.COM
State New
Headers show
Series [FFmpeg-devel,01/61] avcodec/vlc: Add functions to init static VLCElem[] without VLC | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Andreas Rheinhardt Sept. 26, 2023, 10:12 p.m. UTC
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@outlook.com>
---
 libavcodec/vlc.c |  68 +++++++++++++++++++++++++++++++
 libavcodec/vlc.h | 102 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 170 insertions(+)

Comments

Andreas Rheinhardt Oct. 30, 2023, 11:08 p.m. UTC | #1
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@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
diff mbox series

Patch

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 */