[FFmpeg-devel] [PATCH] avformat/avcodec: Add DTS-UHD demuxer and parser, movenc support.

Roy Funderburk royffmpeg at funderburk.us
Wed Jun 14 21:24:13 EEST 2023

On 6/13/23 11:01 PM, Paul B Mahol wrote:
> On Wed, Jun 14, 2023 at 7:37 AM Paul B Mahol <onemda at gmail.com> wrote:
> Also there is no reason to use int for elements in tables when max value
> can be lower.
> Current table reading/handling code should be completely rewritten to use
> get_vlc2().
> And tables split so length of codes use uint8_t type.

I will split the tables into two arrays and make the first array uint8_t.

I was looking over the get_vlc2() function, and I don't believe it will be
able to replace the current dtsuhd_common.c's get_bits_var.

The current dtsuhd_common function and a sample table parameter:

    static const int uhd_table[2][8] = {
            // TABLE_BITS                     TABLE_ADD
        { 4, 4, 4, 4, 8, 8, 16, 32 }, { 0, 0, 0, 0, 16, 16, 272, 65808 } };
    static int get_bits_var(GetBitContext *gb, const int uhd_table[2][8])
        static const int bits_used[8] = { 1, 1, 1, 1, 2, 2, 3, 3 };
        int code = show_bits(gb, 3); /* value range is [0, 7] */

        skip_bits(gb, bits_used[code]);
        if (uhd_table[TABLE_BITS][code] == 0)
            return 0;
        return get_bits_long(gb, uhd_table[TABLE_BITS][code]) + uhd_table[TABLE_ADD][code];

It peeks ahead 3 bits, and uses them to read the three 8 element tables: bits_used,
uhd_table[0], uhd_table[1].  Skips "bits_used" bits, reads "uhd_table[0]" bits and
adds to that value the value from "uhd_table[1]"

get_vlc2 uses the GET_VLC macro which goes like this:

    #define GET_VLC(code, name, gb, table, bits, max_depth)         \
        do {                                                        \
            int n, nb_bits;                                         \
            unsigned int index;                                     \
            index = SHOW_UBITS(name, gb, bits);                     \
            code  = table[index].sym;                               \
            n     = table[index].len;                               \
            if (max_depth > 1 && n < 0) {                           \
                nb_bits = -n;                                       \
                index = SHOW_UBITS(name, gb, nb_bits) + code;       \
                code  = table[index].sym;                           \
                n     = table[index].len;                           \
            }                                                       \
            SKIP_BITS(name, gb, n);                                 \

The end result from this function is "code".  It needs to be the result of
reading "uhd_table[0][x]" bits added to the value from "uhd_table[1][x]".
But, that only way to get to that value would be in the last read of
    "index = SHOW_UBITS(name, gb, nb_bits) + code;"
And "index" is not returned from that macro.
Further, index has a maximum size of 32 bits, which is a problem for the next
line "code  = table[index].sym;".  That table would be 4Gigs, and we don't
even want the value from that table.

So that means we can't use the "if" block at all.

This means the best get_vlc2 could do is replace the "show_bits" and "skip_bits"
of the original dtsuhd get_bits_var function.  The last get_bits_long would
still be needed.

In that case, "table[index].len" would have to be from the table "bits_used"
and "table[index].sym would have to be from that table "uhd_table[0]".
get_vlc2() would return the bits to read for the call to get_bits_long.

But, when building the table using ff_init_vlc_from_lengths, there is this line
from that function in vlc.c:
    code += 1U << (32 - len);
    if (code > UINT32_MAX + 1ULL) {
        av_log(logctx, AV_LOG_ERROR, "Overdetermined VLC tree\n");

"len" comes from the an input table to that function "bits_used[8]" and that
table has duplicate entries.  Specifically several values of "1".  And that
quickly causes the "overdetermined" error.  Looking over the other functions
in vlc.c, those do not look as if they would work well with the dtsuhd_common
tables either.

More information about the ffmpeg-devel mailing list