1
mirror of https://git.videolan.org/git/ffmpeg.git synced 2024-09-07 16:40:10 +02:00

avcodec/on2avc: Use smaller tables for VLCs

The On2 audio decoder uses huge tables to initialize VLC tables. These
tables (mostly) use symbols tables in addition to the codes tables and
the lengths tables. This commit makes the codes tables redundant and
removes them: If all tables are permuted so that the codes are ordered
from left to right in the Huffman tree, the codes become redundant and
can be easily calculated at runtime from the lengths
(via ff_init_vlc_from_lengths()); this also avoids sorting the codes in
ff_init_vlc_sparse()*.

The symbols tables are always 16bit, the codes tables are 32bit, 16bit
or (rarely) 8bit, the lengths tables are always 8bit. Even though some
symbols tables have been used twice (which is no longer possible now
because different permutations need to be performed on the code tables
sharing the same symbol table in order to order them from left to right),
this nevertheless saves about 28KB.

*: If the initializations of the VLCs are repeated 2048 times
(interleaved with calls to free the VLCs which have not been timed), the
number of decicycles spent on each round of initializations improves
from 27669656 to 7356159.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
Andreas Rheinhardt 2020-10-25 12:48:41 +01:00
parent fefe2cbbf2
commit 71753c5235
3 changed files with 2225 additions and 5856 deletions

View File

@ -906,7 +906,7 @@ static av_cold void on2avc_free_vlcs(On2AVCContext *c)
static av_cold int on2avc_decode_init(AVCodecContext *avctx)
{
On2AVCContext *c = avctx->priv_data;
int i;
int i, ret;
if (avctx->channels > 2U) {
avpriv_request_sample(avctx, "Decoding more than 2 channels");
@ -956,25 +956,24 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx)
if (!c->fdsp)
return AVERROR(ENOMEM);
if (init_vlc(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS,
ff_on2avc_scale_diff_bits, 1, 1,
ff_on2avc_scale_diff_codes, 4, 4, 0)) {
ret = ff_init_vlc_from_lengths(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS,
ff_on2avc_scale_diff_bits, 1,
ff_on2avc_scale_diff_syms, 1, 1, 0, 0, avctx);
if (ret < 0)
goto vlc_fail;
}
for (i = 1; i < 16; i++) {
int idx = i - 1, codes_size = ff_on2avc_cb_codes_sizes[idx];
if (ff_init_vlc_sparse(&c->cb_vlc[i], 9, ff_on2avc_cb_elems[idx],
ff_on2avc_cb_bits[idx], 1, 1,
ff_on2avc_cb_codes[idx], codes_size, codes_size,
ff_on2avc_cb_syms[idx], 2, 2, 0)) {
int idx = i - 1;
ret = ff_init_vlc_from_lengths(&c->cb_vlc[i], 9, ff_on2avc_cb_elems[idx],
ff_on2avc_cb_bits[idx], 1,
ff_on2avc_cb_syms[idx], 2, 2, 0, 0, avctx);
if (ret < 0)
goto vlc_fail;
}
}
return 0;
vlc_fail:
av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n");
return AVERROR(ENOMEM);
return ret;
}
static av_cold int on2avc_decode_close(AVCodecContext *avctx)

File diff suppressed because it is too large Load Diff

View File

@ -38,13 +38,11 @@ extern const On2AVCMode ff_on2avc_modes_40[8];
extern const On2AVCMode ff_on2avc_modes_44[8];
#define ON2AVC_SCALE_DIFFS 121
extern const uint32_t ff_on2avc_scale_diff_codes[];
extern const uint8_t ff_on2avc_scale_diff_bits[];
extern const uint8_t ff_on2avc_scale_diff_syms[];
extern const uint8_t ff_on2avc_scale_diff_bits[];
extern const void * const ff_on2avc_cb_codes[];
extern const uint8_t * const ff_on2avc_cb_bits[];
extern const uint16_t * const ff_on2avc_cb_syms[];
extern const uint8_t ff_on2avc_cb_codes_sizes[];
extern const int ff_on2avc_cb_elems[];
extern const float ff_on2avc_window_long_32000[1024];