[FFmpeg-devel] [PATCH 2/3] [WIP] avcodec: add HVQM4 Video decoder
Andreas Rheinhardt
andreas.rheinhardt at outlook.com
Mon Feb 14 19:58:44 EET 2022
Paul B Mahol:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/codec_desc.c | 7 +
> libavcodec/codec_id.h | 1 +
> libavcodec/hvqm4.c | 1719 +++++++++++++++++++++++++++++++++++++++
> 5 files changed, 1729 insertions(+)
> create mode 100644 libavcodec/hvqm4.c
>
> +static int read_trees(int index,
> + int length,
> + uint16_t code,
> + uint8_t *bits,
> + uint16_t *codes,
> + uint16_t *symbols,
> + GetBitContext *gb,
> + const uint32_t tree_signed,
> + const uint32_t tree_scale)
> +{
> + if (get_bits1(gb) == 0) { // leaf node
> + uint8_t byte = get_bits(gb, 8);
> + int16_t symbol = byte;
> +
> + if (tree_signed && byte > 0x7F)
Is the check "byte > 0x7F" actually is an improvement?
> + symbol = (int8_t)byte;
> +
> + symbol *= 1 << tree_scale;
> + bits[index] = length;
> + codes[index] = code;
> + symbols[index] = symbol;
> + index++;
> + return index;
> + } else { // recurse
> + index = read_trees(index, length + 1, code << 1, bits, codes, symbols, gb, tree_signed, tree_scale);
> + index = read_trees(index, length + 1, (code << 1) + 1, bits, codes, symbols, gb, tree_signed, tree_scale);
> + return index;
> + }
> +}
> +
> +static int build_huff(GBCWithVLC *buf, uint32_t is_signed, uint32_t scale)
> +{
> + const uint32_t tree_signed = is_signed;
> + const uint32_t tree_scale = scale;
> + uint8_t bits[256] = { 0 };
> + uint16_t codes[256] = { 0 };
> + uint16_t symbols[256] = { 0 };
> + VLC *vlc = buf->vlc;
> + int nb_codes;
> +
> + ff_free_vlc(vlc);
> + nb_codes = read_trees(0, 0, 0, bits, codes, symbols, &buf->gb, tree_signed, tree_scale);
> +
> + return ff_init_vlc_sparse(vlc, ff_log2(nb_codes) + 3, nb_codes, bits, 1, 1,
> + codes, 2, 2, symbols, 2, 2, 0);
> +}
> +
1. The above code does not check against stack overflow or buffer
overflow; you are also not checking that your codes fit into 16bits.
2. I also don't get where your ff_log2(nb_codes) + 3 comes from.
3. The nodes are stored from left to right in the tree, so using
ff_init_vlc_sparse() is unnecessary; ff_init_vlc_from_lengths() can be
used like this (untested):
struct HuffTree {
int nb_codes;
uint8_t bits[256];
uint16_t symbols[256];
} HuffTree;
static int read_trees(int length,
HuffTree *huff,
GetBitContext *gb,
const uint32_t tree_signed,
const uint32_t tree_scale)
{
int ret;
if (get_bits1(gb) == 0) { // leaf node
uint8_t byte = get_bits(gb, 8);
int16_t symbol = tree_signed ? (int8_t)byte : byte;
symbol *= 1 << tree_scale;
if (huff->nb_codes >= FF_ARRAY_ELEMS(huff->bits))
return AVERROR_INVALIDDATA;
huff->bits[huff->nb_codes] = length;
huff->symbols[huff->nb_codes] = symbol;
huff->nb_codes++;
return 0;
} else { // recurse
if (length == 16)
return AVERROR_INVALIDDATA;
ret = read_trees(length + 1, huff, gb, tree_signed, tree_scale);
if (ret < 0)
return ret;
return read_trees(length + 1, huff, gb, tree_signed, tree_scale);
}
}
static int build_huff(GBCWithVLC *buf, uint32_t is_signed, uint32_t scale)
{
const uint32_t tree_signed = is_signed;
const uint32_t tree_scale = scale;
HuffTree huff;
VLC *vlc = buf->vlc;
int ret;
huff.nb_codes = 0;
ff_free_vlc(vlc);
ret = read_trees(0, &huff, &buf->gb, tree_signed, tree_scale);
if (ret < 0)
return ret;
return ff_init_vlc_from_lengths(vlc, ff_log2(huff.nb_codes) + 3,
huff.nb_codes,
huff.bits, 1, huff.symbols, 2, 2,
0, 0, NULL);
}
4. Is it legal for the tree to consists of only the root (which then has
length zero)? Our code for generating VLCs can't handle this at the
moment; I always pondered adding support for it (and somewhere I have a
stash entry for it), but never did it.
- Andreas
More information about the ffmpeg-devel
mailing list