int ff_init_vlc_sparse(VLC *vlc, 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)

{

    VLCcode *buf;

    int i, j, ret;



    vlc->bits = nb_bits;

    if (flags & INIT_VLC_USE_NEW_STATIC) {

        VLC dyn_vlc = *vlc;



        if (vlc->table_size)

            return 0;



        ret = ff_init_vlc_sparse(&dyn_vlc, nb_bits, nb_codes,

                                 bits, bits_wrap, bits_size,

                                 codes, codes_wrap, codes_size,

                                 symbols, symbols_wrap, symbols_size,

                                 flags & ~INIT_VLC_USE_NEW_STATIC);

        av_assert0(ret >= 0);

        av_assert0(dyn_vlc.table_size <= vlc->table_allocated);

        if (dyn_vlc.table_size < vlc->table_allocated)

            av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", dyn_vlc.table_size, vlc->table_allocated);

        memcpy(vlc->table, dyn_vlc.table, dyn_vlc.table_size * sizeof(*vlc->table));

        vlc->table_size = dyn_vlc.table_size;

        ff_free_vlc(&dyn_vlc);

        return 0;

    } else {

        vlc->table           = NULL;

        vlc->table_allocated = 0;

        vlc->table_size      = 0;

    }



    av_dlog(NULL, "build table nb_codes=%d\n", nb_codes);



    buf = av_malloc((nb_codes + 1) * sizeof(VLCcode));





    av_assert0(symbols_size <= 2 || !symbols);

    j = 0;

#define COPY(condition)\

    for (i = 0; i < nb_codes; i++) {                                        \

        GET_DATA(buf[j].bits, bits, i, bits_wrap, bits_size);               \

        if (!(condition))                                                   \

            continue;                                                       \

        if (buf[j].bits > 3*nb_bits || buf[j].bits>32) {                    \

            av_log(NULL, AV_LOG_ERROR, "Too long VLC (%d) in init_vlc\n", buf[j].bits);\

            av_free(buf);                                                   \

            return -1;                                                      \

        }                                                                   \

        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 in init_vlc\n");       \

            av_free(buf);                                                   \

            return -1;                                                      \

        }                                                                   \

        if (flags & INIT_VLC_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(buf[j].bits > nb_bits);

    // qsort is the slowest part of init_vlc, and could probably be improved or avoided

    qsort(buf, j, sizeof(VLCcode), compare_vlcspec);

    COPY(buf[j].bits && buf[j].bits <= nb_bits);

    nb_codes = j;



    ret = build_table(vlc, nb_bits, nb_codes, buf, flags);



    av_free(buf);

    if (ret < 0) {

        av_freep(&vlc->table);

        return ret;

    }

    return 0;

}