From: Michael Niedermayer <michael@niedermayer.cc> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH 4/4] avcodec/ffv1: RC/RLE/LRU coder for remap table Date: Thu, 20 Mar 2025 02:19:16 +0100 Message-ID: <20250320011916.2549051-4-michael@niedermayer.cc> (raw) In-Reply-To: <20250320011916.2549051-1-michael@niedermayer.cc> 8% overall compression gain for 32bit float data which originates from 16bit floats Sponsored-by: Sovereign Tech Fund Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/ffv1.h | 2 ++ libavcodec/ffv1dec.c | 22 +++++++++++++- libavcodec/ffv1enc.c | 70 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 84 insertions(+), 10 deletions(-) diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index d19c8e3ed42..64be996322c 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -54,6 +54,8 @@ #define AC_RANGE_CUSTOM_TAB 2 #define AC_RANGE_DEFAULT_TAB_FORCE -2 +#define NLRU 33 + typedef struct VlcState { uint32_t error_sum; int16_t drift; diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index d45aabbbde8..c758040e1a8 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -242,7 +242,7 @@ static int decode_slice_header(const FFV1Context *f, } if (f->combined_version >= 0x40004) { sc->remap = ff_ffv1_get_symbol(c, state, 0); - if (sc->remap > 2U || + if (sc->remap > 3U || sc->remap && !f->flt) { av_log(f->avctx, AV_LOG_ERROR, "unsupported remap %d\n", sc->remap); return AVERROR_INVALIDDATA; @@ -285,12 +285,30 @@ static int decode_remap(FFV1Context *f, FFV1SliceContext *sc) int lu = 0; uint8_t state[2][32]; int64_t i; + int lru[NLRU]; memset(state, 128, sizeof(state)); + + for(int i = 0; i<NLRU; i++) + lru[i] = i; + for (i=0; i <= end ; i++) { unsigned run = get_symbol_inline(&sc->c, state[lu], 0); + if (sc->remap == 3 && !lu) { + if (run < NLRU) { + unsigned v = lru[run]; + memmove(lru+1, lru, sizeof(int)*run); + run = v; + } else { + memmove(lru+1, lru, sizeof(int)*(NLRU-1)); + run -= NLRU; + } + lru[0] = run; + } if (run > end - i + 1) return AVERROR_INVALIDDATA; if (lu) { + if (run > 65536 - j) + return AVERROR_INVALIDDATA; lu ^= !run; while (run--) { if (end == 0xFFFF) { @@ -305,6 +323,8 @@ static int decode_remap(FFV1Context *f, FFV1SliceContext *sc) if (end == 0xFFFF) { sc->fltmap [p][j++] = i ^ ((i& 0x8000) ? 0 : flip); } else { + if (j > 65535) + return AVERROR_INVALIDDATA; sc->fltmap32[p][j++] = i ^ ((i&0x80000000) ? 0 : flip); } } diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 12f3952453b..5b4556e63dd 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -949,7 +949,7 @@ av_cold int ff_ffv1_encode_setup_plane_info(AVCodecContext *avctx, av_assert0(s->bits_per_raw_sample >= 8); if (s->remap_mode < 0) - s->remap_mode = s->flt ? 2 : 0; + s->remap_mode = s->flt ? (s->bits_per_raw_sample == 32 ? 3 : 2) : 0; if (s->remap_mode == 0 && s->bits_per_raw_sample == 32) { av_log(avctx, AV_LOG_ERROR, "32bit requires remap\n"); return AVERROR(EINVAL); @@ -1179,24 +1179,53 @@ static void encode_histogram_remap(FFV1Context *f, FFV1SliceContext *sc) int lu = 0; uint8_t state[2][32]; int run = 0; + + int lru[NLRU]; + + for(int i = 0; i<NLRU; i++) + lru[i] = i; + memset(state, 128, sizeof(state)); - for (int i= 0; i<65536; i++) { + for (int i= 0; i<=65536; i++) { int ri = i ^ ((i&0x8000) ? 0 : flip); - int u = sc->fltmap[p][ri]; - sc->fltmap[p][ri] = j; + int u; + if (i < 65536) { + u = sc->fltmap[p][ri]; + sc->fltmap[p][ri] = j; + } else { + if (!run) + break; + u = !lu; + } j+= u; if (lu == u) { run ++; } else { - put_symbol_inline(&sc->c, state[lu], run, 0, NULL, NULL); + unsigned v = run; + if (sc->remap == 3 && !lu) { + int r; + for(r = 0; r < NLRU; r++) { + if (v == lru[r]) { + memmove(lru+1, lru, sizeof(int)*r); + lru[0] = v; + v = r; + break; + } + } + if (r == NLRU) { + memmove(lru+1, lru, sizeof(int)*(NLRU-1)); + lru[0] = v; + v += NLRU; + } + //TODO escape handling + } + put_symbol_inline(&sc->c, state[lu], v, 0, NULL, NULL); if (run == 0) lu = u; run = 0; } } - if (run) - put_symbol(&sc->c, state[lu], run, 0); } } @@ -1271,6 +1300,10 @@ static void encode_float32_remap(FFV1Context *f, FFV1SliceContext *sc, int run = 0; int64_t last_val = -1; int compact_index = -1; + int lru[NLRU]; + + for(int i = 0; i<NLRU; i++) + lru[i] = i; memset(state, 128, sizeof(state)); for (int i= 0; i<pixel_num+1; i++) { @@ -1300,8 +1333,25 @@ static void encode_float32_remap(FFV1Context *f, FFV1SliceContext *sc, continue; } } else { + int v = val - last_val - 1; av_assert2(run == 0); - put_symbol_inline(&sc->c, state[lu], val - last_val - 1, 0, NULL, NULL); + if (sc->remap == 3) { + int r; + for(r = 0; r < NLRU; r++) { + if (v == lru[r]) { + memmove(lru+1, lru, sizeof(int)*r); + lru[0] = v; + v = r; + break; + } + } + if (r == NLRU) { + memmove(lru+1, lru, sizeof(int)*(NLRU-1)); + lru[0] = v; + v += NLRU; + } + } + put_symbol_inline(&sc->c, state[lu], v, 0, NULL, NULL); if (val - last_val == 1) lu ^= 1; last_val = val; @@ -1706,7 +1756,7 @@ static const AVOption options[] = { { .i64 = QTABLE_GT8BIT }, INT_MIN, INT_MAX, VE, .unit = "qtable" }, { "rawlsb", "number of LSBs stored RAW", OFFSET(rawlsb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, VE }, - { "remap_mode", "Remap Mode", OFFSET(remap_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 2, VE, .unit = "remap_mode" }, + { "remap_mode", "Remap Mode", OFFSET(remap_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 3, VE, .unit = "remap_mode" }, { "auto", "Automatic", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, .unit = "remap_mode" }, { "off", "Disabled", 0, AV_OPT_TYPE_CONST, @@ -1715,6 +1765,8 @@ static const AVOption options[] = { { .i64 = 1 }, INT_MIN, INT_MAX, VE, .unit = "remap_mode" }, { "flipdualrle", "Dual RLE", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, .unit = "remap_mode" }, + { "rlelru", "RLE/LRU", 0, AV_OPT_TYPE_CONST, + { .i64 = 3 }, INT_MIN, INT_MAX, VE, .unit = "remap_mode" }, { NULL } -- 2.48.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
prev parent reply other threads:[~2025-03-20 1:20 UTC|newest] Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-03-20 1:19 [FFmpeg-devel] [PATCH 1/4] avcodec/ffv1: Fix remap ordering Michael Niedermayer 2025-03-20 1:19 ` [FFmpeg-devel] [PATCH 2/4] avcodec/ffv1: 32-bit float sample support Michael Niedermayer 2025-03-20 1:19 ` [FFmpeg-devel] [PATCH 3/4] avcodec/ffv1enc: remap allows using rice golomb with more bits Michael Niedermayer 2025-03-20 1:19 ` Michael Niedermayer [this message]
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250320011916.2549051-4-michael@niedermayer.cc \ --to=michael@niedermayer.cc \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git