Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Christophe Gisquet <christophe.gisquet@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Subject: [FFmpeg-devel] [PATCH 5/7] proresdec2: use VLC for small runs and levels
Date: Fri,  8 Sep 2023 10:15:06 +0200
Message-ID: <20230908081508.510-5-christophe.gisquet@gmail.com> (raw)
In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com>

Basically, the catch-all codebook is for on average long codewords,
and with a distribution such that the 3-step VLC reading is not
efficient. Furthermore, the complete unrolling make the actual code
smaller than the macro, and as the maximum codelength is smaller,
smaller amounts of bits, optimized for run and for level, can be read.
---
 libavcodec/proresdec2.c | 53 +++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 29 deletions(-)

diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c
index e3cef402d7..02e1d82d00 100644
--- a/libavcodec/proresdec2.c
+++ b/libavcodec/proresdec2.c
@@ -132,7 +132,7 @@ static void unpack_alpha_12(GetBitContext *gb, uint16_t *dst, int num_coeffs,
 #define AC_BITS 12
 #define PRORES_LEV_BITS 9
 
-static const uint8_t ac_info[] = { 0x04, 0x0A, 0x05, 0x06, 0x28, 0x4C };
+static const uint8_t ac_info[] = { 0x04, 0x0A, 0x05, 0x06, 0x28, 0x29 };
 static VLC ac_vlc[6];
 
 static av_cold void init_vlcs(void)
@@ -152,9 +152,7 @@ static av_cold void init_vlcs(void)
         switch_val  = (switch_bits+1) << rice_order;
 
         // Values are actually transformed, but this is more a wrapping
-        ac_codes[0] = 0;
-        ac_bits[0] = 0;
-        for (ac = 0; ac < (1<<AC_BITS)-1; ac++) {
+        for (ac = 0; ac <1<<AC_BITS; ac++) {
             int exponent, bits, val = ac;
             unsigned int code;
 
@@ -171,8 +169,8 @@ static av_cold void init_vlcs(void)
                 code = 1;
             }
             if (bits > max_bits) max_bits = bits;
-            ac_bits [ac+1] = bits;
-            ac_codes[ac+1] = code;
+            ac_bits [ac] = bits;
+            ac_codes[ac] = code;
         }
 
         ff_free_vlc(ac_vlc+i);
@@ -507,12 +505,9 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons
             bits = exp_order - switch_bits + (q<<1);                    \
             val = READ_BITS(gb, bits) - (1 << exp_order) +              \
                 ((switch_bits + 1) << rice_order);                      \
-        } else if (rice_order) {                                        \
-            skip_remaining(gb, q+1);                                    \
-            val = (q << rice_order) + get_bits(gb, rice_order);         \
         } else {                                                        \
-            val = q;                                                    \
             skip_remaining(gb, q+1);                                    \
+            val = rice_order ? (q << rice_order) + get_bits(gb, rice_order) : q;\
         }                                                               \
     } while (0)
 
@@ -527,12 +522,10 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons
         if (q > switch_bits) { /* exp golomb */                         \
             bits = (q<<1) + (int)diff;                                  \
             val = READ_BITS(gb, bits) + (int)offset;                    \
-        } else if (rice_order) {                                        \
-            skip_remaining(gb, q+1);                                    \
-            val = (q << rice_order) + get_bits(gb, rice_order);         \
         } else {                                                        \
-            val = q;                                                    \
             skip_remaining(gb, q+1);                                    \
+            val = rice_order ? (q << rice_order) + show_bits(gb, rice_order) : q;   \
+            skip_remaining(gb, rice_order);                             \
         }                                                               \
     } while (0)
 
@@ -571,14 +564,6 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out,
     return 0;
 }
 
-// adaptive codebook switching lut according to previous run values
-static const char run_to_cb[16][4] = {
-    { 2, 0, -1,  1 }, { 2, 0, -1,  1 }, { 1, 0, 0,  0 }, { 1, 0,  0,  0 }, { 0, 0, 1, -1 },
-    { 1, 1,  1,  0 }, { 1, 1,  1,  0 }, { 1, 1, 1,  0 }, { 1, 1,  1,  0 },
-    { 0, 1,  2, -2 }, { 0, 1,  2, -2 }, { 0, 1, 2, -2 }, { 0, 1,  2, -2 }, { 0, 1, 2, -2 }, { 0, 1, 2, -2 },
-    { 0, 2,  3, -4 }
-};
-
 static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb,
                                              int16_t *out, int blocks_per_slice)
 {
@@ -595,22 +580,32 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex
     block_mask = blocks_per_slice - 1;
 
     for (pos = block_mask;;) {
-        static const uint8_t ctx_to_tbl[] = { 0, 1, 2, 3, 0, 4, 4, 4, 4, 5 };
-        const VLC* tbl = ac_vlc + ctx_to_tbl[FFMIN(level, 9)];
-        unsigned int runcb = FFMIN(run,  15);
         bits_rem = get_bits_left(gb);
-        if (!bits_rem || (bits_rem < 16 && !show_bits(gb, bits_rem)))
+        if (!bits_rem || (bits_rem < 14 && !show_bits(gb, bits_rem)))
             break;
 
-        DECODE_CODEWORD2(run, run_to_cb[runcb][0], run_to_cb[runcb][1],
-                              run_to_cb[runcb][2], run_to_cb[runcb][3]);
+        if (run < 15) {
+            static const uint8_t ctx_to_tbl[] = { 3, 3, 2, 2, 0, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4 };
+            const VLC* tbl = ac_vlc + ctx_to_tbl[run];
+            run = get_vlc2(gb, tbl->table, PRORES_LEV_BITS, 3);
+        } else {
+            unsigned int bits = 21 - 2*av_log2(show_bits(gb, 10));
+            run = READ_BITS(gb, bits) - 4; // up to 17 bits
+        }
         pos += run + 1;
         if (pos >= max_coeffs) {
             av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs);
             return AVERROR_INVALIDDATA;
         }
 
-        level = get_vlc2(gb, tbl->table, PRORES_LEV_BITS, 3);
+        if (level < 9) {
+            static const uint8_t ctx_to_tbl[] = { 0, 1, 2, 3, 0, 4, 4, 4, 4 };
+            const VLC* tbl = ac_vlc + ctx_to_tbl[level];
+            level = 1+get_vlc2(gb, tbl->table, PRORES_LEV_BITS, 3);
+        } else {
+            unsigned int bits = 25 - 2*av_log2(show_bits(gb, 12));
+            level = READ_BITS(gb, bits) - 4 + 1; // up to 21 bits
+        }
 
         i = pos >> log2_block_count;
 
-- 
2.42.0

_______________________________________________
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".

  parent reply	other threads:[~2023-09-08  8:16 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-08  8:15 [FFmpeg-devel] [PATCH 1/7] proresdec2: port and fix for cached reader Christophe Gisquet
2023-09-08  8:15 ` [FFmpeg-devel] [PATCH 2/7] proresdec2: store precomputed EC parameters Christophe Gisquet
2023-09-08  8:39   ` Andreas Rheinhardt
2023-09-08  8:15 ` [FFmpeg-devel] [PATCH 3/7] proresdec2: use VLC for level instead of EC switch Christophe Gisquet
2023-09-08  8:44   ` Andreas Rheinhardt
2023-09-08  9:58     ` Andreas Rheinhardt
2023-09-10 15:28       ` Christophe Gisquet
2023-09-10 15:41         ` Andreas Rheinhardt
2023-09-10 15:56           ` Christophe Gisquet
2023-09-08  8:15 ` [FFmpeg-devel] [PATCH 4/7] proresdec2: offset VLCs by 1 to avoid 1 add Christophe Gisquet
2023-09-08  8:15 ` Christophe Gisquet [this message]
2023-09-08  8:15 ` [FFmpeg-devel] [PATCH 6/7] proresdec2: remove a useless DC codebook entry Christophe Gisquet
2023-09-08  9:08   ` Andreas Rheinhardt
2023-09-08  8:15 ` [FFmpeg-devel] [PATCH 7/7] prores: use VLC LUTs Christophe Gisquet
2023-09-08  9:20   ` Andreas Rheinhardt
2023-09-08  9:58     ` Christophe Gisquet
2023-09-08  8:20 ` [FFmpeg-devel] [PATCH 1/7] proresdec2: port and fix for cached reader Christophe Gisquet
2023-09-08  8:30   ` Andreas Rheinhardt
2023-09-08  8:34     ` Andreas Rheinhardt
2023-09-11 20:54   ` Christophe Gisquet
2023-09-08  8:36 ` Andreas Rheinhardt
2023-09-08 21:00 ` Michael Niedermayer

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=20230908081508.510-5-christophe.gisquet@gmail.com \
    --to=christophe.gisquet@gmail.com \
    --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