summaryrefslogtreecommitdiff
path: root/libavcodec/clearvideo.c
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2020-10-25 22:17:28 +0100
committerAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2020-12-08 17:51:45 +0100
commit1d3ec27bd54ceb5108ad9f9ed430266ccc4cbc71 (patch)
tree2772c6604b601071e3e8d19d3e203385eea1fc1b /libavcodec/clearvideo.c
parente97081a62471c41522ddb2af534ed7ce9b3a6893 (diff)
downloadffmpeg-1d3ec27bd54ceb5108ad9f9ed430266ccc4cbc71.tar.gz
avcodec/clearvideo: Avoid huge VLC length tables
After the motion vector and bias values tables have been reordered so that the codes are ordered from left to right, it emerged that the length of these entries are actually ascending for every table. Therefore it is possible to encode them in a run-length style and create the actual length tables during runtime. This commit implements this. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Diffstat (limited to 'libavcodec/clearvideo.c')
-rw-r--r--libavcodec/clearvideo.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c
index f1dcb03f0e..39e3991053 100644
--- a/libavcodec/clearvideo.c
+++ b/libavcodec/clearvideo.c
@@ -646,9 +646,31 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
return mb_ret < 0 ? mb_ret : buf_size;
}
+static av_cold int build_vlc(VLC *vlc, const uint8_t counts[16],
+ const uint16_t **syms)
+{
+ uint8_t lens[MAX_VLC_ENTRIES];
+ unsigned num = 0;
+ int ret;
+
+ for (int i = 0; i < 16; i++) {
+ unsigned count = counts[i];
+ if (count == 255) /* Special case for Y_3 table */
+ count = 303;
+ for (count += num; num < count; num++)
+ lens[num] = i + 1;
+ }
+ ret = ff_init_vlc_from_lengths(vlc, 9, num, lens, 1, *syms, 2, 2, 0, 0, NULL);
+ if (ret < 0)
+ return ret;
+ *syms += num;
+ return 0;
+}
+
static av_cold int clv_decode_init(AVCodecContext *avctx)
{
CLVContext *const c = avctx->priv_data;
+ const uint16_t *mv_syms = clv_mv_syms, *bias_syms = clv_bias_syms;
int ret, w, h;
if (avctx->extradata_size == 110) {
@@ -704,14 +726,13 @@ static av_cold int clv_decode_init(AVCodecContext *avctx)
return ret;
}
- for (int i = 0, j = 0;; i++) {
+ for (int i = 0, j = 0, k = 0;; i++) {
if (0x36F & (1 << i)) {
c->lev[i].mv_esc = clv_mv_escape[i];
- ret = ff_init_vlc_from_lengths(&c->lev[i].mv_cb, 9, clv_mv_sizes[i],
- clv_mv_bits[i], 1,
- clv_mv_syms[i], 2, 2, 0, 0, avctx);
+ ret = build_vlc(&c->lev[i].mv_cb, clv_mv_len_counts[k], &mv_syms);
if (ret < 0)
return ret;
+ k++;
}
if (i == FF_ARRAY_ELEMS(c->lev) - 1)
break;
@@ -723,9 +744,8 @@ static av_cold int clv_decode_init(AVCodecContext *avctx)
return ret;
c->lev[i + 1].bias_esc = 0x100;
- ret = ff_init_vlc_from_lengths(&c->lev[i + 1].bias_cb, 9, clv_bias_sizes[j],
- clv_bias_bits[j], 1,
- clv_bias_syms[j], 2, 2, 0, 0, avctx);
+ ret = build_vlc(&c->lev[i + 1].bias_cb,
+ clv_bias_len_counts[j], &bias_syms);
if (ret < 0)
return ret;
j++;