From patchwork Fri Sep 8 08:15:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43653 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324507pzb; Fri, 8 Sep 2023 01:15:29 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHmnEvJId2MF+LK27VbPSt6iSaM1QiUILDjmSRuUXmPMMAjWlLWd/R8ChZNPrKrWpg8ce+2 X-Received: by 2002:aa7:d793:0:b0:525:5a65:6dfa with SMTP id s19-20020aa7d793000000b005255a656dfamr1356600edq.14.1694160929106; Fri, 08 Sep 2023 01:15:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160929; cv=none; d=google.com; s=arc-20160816; b=k2GSqKl4pgAF9/jlh/E2tK6LYnZgBN4nExQQtF/1KYwxusQWFgSRluVLAY7/JTFj4O swRq379n8y3T1YtWRSyNw99Tll3QmygTuTi6MhQXfnnqh9OwbzWCXav+MeE2XK5ab8F0 YMX+kAqnh662otn//o0CTmWcxJolc+5Y27Lz4t902YB6Z6hULSYzdmqOFSGQQwTaXj6L 47bV6kzWflMVu6q43OhMHMyyXfAYTd+5681DW04mBukdlPjNIFiD4pzsxnrF7hF/H9YA YtpZRMe5bWVVuNlQDcrgSlptYW+uhw/pOQhHHse2kjRW8xAgXp0/gE7YbAXFaWJaFHsm zkLQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :delivered-to; bh=KsDklUn9nytZ/mPh9I17gJ4ZuQ/AM2gcw9lNLzGQKG0=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=EpVMXzyzHIcjdcdmLRk3f9hMHIsmcXpwXVU5M3Ruo2Zqhr3vBYMf7BH45LNDBIrVz9 3iY9nD4sgp7SiFYSPP1L8qTTWps79absfG4XFGOiGA+Ah8oUbVQGJPiJIujyJB7xoc+d 6JZjEcdou0cTU1393DMJxZcvuT93yFSsGO90qLMODQZMMKGdJdIAtN84q+VfpWVEkXab WiS+BmGSfAvXjERag4lYE1UuVIIsLmOLlQp5bEX3O+4fyjYJTk2E+4FXRJhC6PoO552G J5AgwiUbNoPA3rKz3mFB1tSlTs2uPebCJS3cUID0ueSUNjo46XcmDfX1beG8tAlsJBS/ iSeQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id d13-20020aa7d5cd000000b0052683dac6adsi1013827eds.244.2023.09.08.01.15.28; Fri, 08 Sep 2023 01:15:29 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7D3A268C7FE; Fri, 8 Sep 2023 11:15:24 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2213668C684 for ; Fri, 8 Sep 2023 11:15:18 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 78A3DB0057C for ; Fri, 8 Sep 2023 10:15:17 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:02 +0200 Message-ID: <20230908081508.510-1-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/7] proresdec2: port and fix for cached reader X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: hBZdfYWO0Onc Summary of changes - move back to regular, non-macro, get_bits API - reduce the lookup to switch the coding method - shorter reads wherever possible, in particular for the end of bitstream (16 bits instead of 32, as per the above) There are cases that really need longer lengths (larger EG codes) of up to 27 bits. Win64: 6.10 -> 4.87 (~20% speedup) Reference for an hypothetical 32bits version of the cached reader: Win32: 11.4 -> 9.8 (14%, because iDCT is not SIMDed) --- libavcodec/proresdec2.c | 53 ++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 9297860946..6e243cfc17 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -24,9 +24,7 @@ * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'apco' (Proxy), 'ap4h' (4444), 'ap4x' (4444 XQ) */ -//#define DEBUG - -#define LONG_BITSTREAM_READER +#define CACHED_BITSTREAM_READER 1 #include "config_components.h" @@ -422,35 +420,37 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons return pic_data_size; } -#define DECODE_CODEWORD(val, codebook, SKIP) \ +/* bitstream_read may fail on 32bits ARCHS for >24 bits, so use long version there */ +#if 0 //BITSTREAM_BITS == 32 +# define READ_BITS get_bits_long +#else +# define READ_BITS get_bits +#endif + +#define DECODE_CODEWORD(val, codebook) \ do { \ unsigned int rice_order, exp_order, switch_bits; \ unsigned int q, buf, bits; \ \ - UPDATE_CACHE(re, gb); \ - buf = GET_CACHE(re, gb); \ + buf = show_bits(gb, 14); \ \ /* number of bits to switch between rice and exp golomb */ \ switch_bits = codebook & 3; \ rice_order = codebook >> 5; \ exp_order = (codebook >> 2) & 7; \ \ - q = 31 - av_log2(buf); \ + q = 13 - av_log2(buf); \ \ if (q > switch_bits) { /* exp golomb */ \ bits = exp_order - switch_bits + (q<<1); \ - if (bits > FFMIN(MIN_CACHE_BITS, 31)) \ - return AVERROR_INVALIDDATA; \ - val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) + \ + val = READ_BITS(gb, bits) - (1 << exp_order) + \ ((switch_bits + 1) << rice_order); \ - SKIP(re, gb, bits); \ } else if (rice_order) { \ - SKIP_BITS(re, gb, q+1); \ - val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order); \ - SKIP(re, gb, rice_order); \ + skip_remaining(gb, q+1); \ + val = (q << rice_order) + get_bits(gb, rice_order); \ } else { \ val = q; \ - SKIP(re, gb, q+1); \ + skip_remaining(gb, q+1); \ } \ } while (0) @@ -466,9 +466,7 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, int16_t prev_dc; int code, i, sign; - OPEN_READER(re, gb); - - DECODE_CODEWORD(code, FIRST_DC_CB, LAST_SKIP_BITS); + DECODE_CODEWORD(code, FIRST_DC_CB); prev_dc = TOSIGNED(code); out[0] = prev_dc; @@ -477,13 +475,12 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, code = 5; sign = 0; for (i = 1; i < blocks_per_slice; i++, out += 64) { - DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)], LAST_SKIP_BITS); + DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]); if(code) sign ^= -(code & 1); else sign = 0; prev_dc += (((code + 1) >> 1) ^ sign) - sign; out[0] = prev_dc; } - CLOSE_READER(re, gb); return 0; } @@ -497,11 +494,9 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex const ProresContext *ctx = avctx->priv_data; int block_mask, sign; unsigned pos, run, level; - int max_coeffs, i, bits_left; + int max_coeffs, i, bits_rem; int log2_block_count = av_log2(blocks_per_slice); - OPEN_READER(re, gb); - UPDATE_CACHE(re, gb); \ run = 4; level = 2; @@ -509,28 +504,26 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex block_mask = blocks_per_slice - 1; for (pos = block_mask;;) { - bits_left = gb->size_in_bits - re_index; - if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left))) + bits_rem = get_bits_left(gb); + if (!bits_rem || (bits_rem < 16 && !show_bits(gb, bits_rem))) break; - DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)], LAST_SKIP_BITS); + DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)]); 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; } - DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)], SKIP_BITS); + DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]); level += 1; i = pos >> log2_block_count; - sign = SHOW_SBITS(re, gb, 1); - SKIP_BITS(re, gb, 1); + sign = -get_bits1(gb); out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign); } - CLOSE_READER(re, gb); return 0; } From patchwork Fri Sep 8 08:15:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43654 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324597pzb; Fri, 8 Sep 2023 01:15:41 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGKSq3CZcFJV6fhmBlf5/Mt8hgvmrWcq3k7pyE7MCu/5PpsRdKhxY4bzeOE+zxMpaVK5ZNh X-Received: by 2002:a17:906:5199:b0:9a1:d087:e0bd with SMTP id y25-20020a170906519900b009a1d087e0bdmr1356363ejk.6.1694160941436; Fri, 08 Sep 2023 01:15:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160941; cv=none; d=google.com; s=arc-20160816; b=q2euWOyBm09OkitcrZ6zxomGBAdqlbbFwSSni71hH2A7yShgmm/14K0H0oDXYywqDe vbsBraCvZKLfAombSnf9xJXK+UuPeUSP1u/Y2KHLsbrKkcEr0Pi/zYdW95R9uWdzrU3a ZefSfU/UjQaSejdCTboDjcfPOWyIzOYGqRA8sj0XcMMqwG2o9ttbqRESQScJQUeCEfDJ 2xaenoQNioVH74mWWuOpJHhKwK86Fg0FPUP/0TppPQP08x5iT2INDLVo9A31GS3NzRLK lxfcEdsXGJZ0hh6FT0tIqU22erCF9adV6Izeo5IqIMy2sNaCEx5tNXyMjwXfely6ZfHl u/Ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=yhaAQJ1gPxaX5pmdHrLu35Nr1QIBe4sgqJ1T4PaiMJ8=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=RPEorOlVLMgWHgd8DiIXz7rsf/gYEDHzpQ/Hv5oGPiEY+KK9Vu43rwNw4n4ygPy3Qg zUoLgymCXCPOObVx+26h/FtQiV2LZWNpplPVgts3OFNBytTyktnWWD6Zu5OXjbEubKK3 JVmI8i4HPiiAPOrH8EXHzvUM4KsAWpV3gEZfPWhi9TJTtxDYjjJY7lvu4EVcNsvRgf1C X+zyxolHqYsXehsdhR3Tb6zUkXCEyTnFEnrI/fwULdIsaAshQw116xDcRMBCBmup5c7O vCo8B7CjqTIMEVtzyQiNwTT5CpA0V8uhrnHlPFkpAK26bShsslTaW0JeZjhv4pwd22VH kfOw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id rs10-20020a170907036a00b00992acfbcee1si863790ejb.851.2023.09.08.01.15.41; Fri, 08 Sep 2023 01:15:41 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AF1D968C882; Fri, 8 Sep 2023 11:15:27 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 262C668C7FE for ; Fri, 8 Sep 2023 11:15:19 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id AE89FB00563 for ; Fri, 8 Sep 2023 10:15:17 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:03 +0200 Message-ID: <20230908081508.510-2-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/7] proresdec2: store precomputed EC parameters X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: uip2BNYBuv6Z Having the various orders and offsets stored in a codebook is compact but causes additional computations. Using instead a table for the precomputed results achieve some speedups at the cost of ~132 bytes. Around 5% speedup. --- libavcodec/proresdec2.c | 54 +++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 6e243cfc17..65e8b01755 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -427,6 +427,7 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons # define READ_BITS get_bits #endif +/* Kept for reference and because clearer for first DC */ #define DECODE_CODEWORD(val, codebook) \ do { \ unsigned int rice_order, exp_order, switch_bits; \ @@ -454,18 +455,41 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons } \ } while (0) +/* number of bits to switch between rice and exp golomb */ +#define DECODE_CODEWORD2(val, switch_bits, rice_order, diff, offset) \ + do { \ + unsigned int q, buf, bits; \ + \ + buf = show_bits(gb, 14); \ + q = 13 - av_log2(buf); \ + \ + 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); \ + } \ + } while (0) + + #define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1))) #define FIRST_DC_CB 0xB8 -static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70}; +static const char dc_codebook[7][4] = { + { 0, 0, 1, -1 }, { 0, 1, 2, -2 }, { 0, 1, 2, -2 }, + { 1, 2, 2, 0 }, { 1, 2, 2, 0 }, { 0, 3, 4, -8 }, { 0, 3, 4, -8 } +}; static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, int blocks_per_slice) { int16_t prev_dc; int code, i, sign; - DECODE_CODEWORD(code, FIRST_DC_CB); prev_dc = TOSIGNED(code); out[0] = prev_dc; @@ -475,7 +499,9 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, code = 5; sign = 0; for (i = 1; i < blocks_per_slice; i++, out += 64) { - DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]); + unsigned int dccb = FFMIN(code, 6U); + DECODE_CODEWORD2(code, dc_codebook[dccb][0], dc_codebook[dccb][1], + dc_codebook[dccb][2], dc_codebook[dccb][3]); if(code) sign ^= -(code & 1); else sign = 0; prev_dc += (((code + 1) >> 1) ^ sign) - sign; @@ -485,8 +511,18 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, } // adaptive codebook switching lut according to previous run/level values -static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C }; -static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C }; +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 const char lev_to_cb[10][4] = { + { 0, 0, 1, -1 }, { 2, 0, 0, -1 }, { 1, 0, 0, 0 }, { 2, 0, -1, 1 }, { 0, 0, 1, -1 }, + { 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) @@ -504,18 +540,22 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex block_mask = blocks_per_slice - 1; for (pos = block_mask;;) { + unsigned int runcb = FFMIN(run, 15); + unsigned int levcb = FFMIN(level, 9); bits_rem = get_bits_left(gb); if (!bits_rem || (bits_rem < 16 && !show_bits(gb, bits_rem))) break; - DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)]); + DECODE_CODEWORD2(run, run_to_cb[runcb][0], run_to_cb[runcb][1], + run_to_cb[runcb][2], run_to_cb[runcb][3]); 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; } - DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]); + DECODE_CODEWORD2(level, lev_to_cb[levcb][0], lev_to_cb[levcb][1], + lev_to_cb[levcb][2], lev_to_cb[levcb][3]); level += 1; i = pos >> log2_block_count; From patchwork Fri Sep 8 08:15:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43655 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324673pzb; Fri, 8 Sep 2023 01:15:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFdn8t59pSQVEamHlx04nHepiU9bqW9nwfpySt7gkOGhVww4cGSpX7OJBRvIm1yNcYIr2N2 X-Received: by 2002:a17:906:cc0c:b0:9a9:fcfa:b6a7 with SMTP id ml12-20020a170906cc0c00b009a9fcfab6a7mr627701ejb.36.1694160951341; Fri, 08 Sep 2023 01:15:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160951; cv=none; d=google.com; s=arc-20160816; b=sM77wN/2Naj0siWi+CjtMmtNCBtITLKvpDlKneSZpIUt96uFqDIdI6gPio99OGnrv5 4b5RE0M7QSOBNsNyROEpYaigr6wYst+ok7qziAB496SHHqDCZe+rqocS/w+QwzTDej6K VvNEdggaYkcANlPcuL2iA6nQXKXArt+v+rAKaBUjQwmYhh6I/hbbp+mwolFD2uhOujQ+ 5un6y6nxy6dJyNlwRVD6xI96JU1zaOto7yoxOBFqpBWTGEszCV8w1x1qpw7I7XZe17Yy iJCuAtQtRBdfSgKZPRpM6SKtcOmmnnRAxERBLeRORfLny4/kW3BJt265sJGC10gASjMy 4TSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=KRpXAGk5akL7x19Fr5TDrd8g1Gft8NRT57bWGfIpHQM=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=I2Nb0fyGdr2tINAYAAPAEXQcCPSUEGMsTEJzi5Ks2xPn+gdB/gvzGfdhAVdMA5k5OE VM24uuTIcxWbUHPvcvmQpytTZjcpOQg5/gJ+PstPYfPnfpywAQSNN9YurJeJkMgnb/TN 2I5aJ6sv9dzsKaTz4HYZelKeMqxY8fRFKyPx/LLGphbMAasnCDvgwxzGwqL6OYnxZ/vc LcTFOmcXHx+CuNE/zpROHtvWy2IHklcbEMlc8n4VhZnT5Go2btyP9b5EYmMNRn9o2Kt8 r+C5YW50sT1yOvThw59SPWCJJhivfiot/17Zur1TKGbnliK4C76NidbIgSwIWOzEjDIX 2pXA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id um2-20020a170906cf8200b0099c93638298si897385ejb.230.2023.09.08.01.15.51; Fri, 08 Sep 2023 01:15:51 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DBFC568C886; Fri, 8 Sep 2023 11:15:28 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 60B5168C857 for ; Fri, 8 Sep 2023 11:15:20 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id E331AB00583 for ; Fri, 8 Sep 2023 10:15:18 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:04 +0200 Message-ID: <20230908081508.510-3-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/7] proresdec2: use VLC for level instead of EC switch X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 0nAI8ZOOlqKS x86/x64: 61/52 -> 55/46 Around 7-10% speedup. Run and DC do not lend themselves to such changes, likely because their distribution is less skewed, and need larger average vlc read iterations. --- libavcodec/proresdec.h | 1 + libavcodec/proresdec2.c | 77 ++++++++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/libavcodec/proresdec.h b/libavcodec/proresdec.h index 1e48752e6f..7ebacaeb21 100644 --- a/libavcodec/proresdec.h +++ b/libavcodec/proresdec.h @@ -22,6 +22,7 @@ #ifndef AVCODEC_PRORESDEC_H #define AVCODEC_PRORESDEC_H +#define CACHED_BITSTREAM_READER 1 #include "get_bits.h" #include "blockdsp.h" #include "proresdsp.h" diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 65e8b01755..91c689d9ef 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -24,17 +24,17 @@ * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'apco' (Proxy), 'ap4h' (4444), 'ap4x' (4444 XQ) */ -#define CACHED_BITSTREAM_READER 1 +//#define DEBUG #include "config_components.h" #include "libavutil/internal.h" #include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "codec_internal.h" #include "decode.h" -#include "get_bits.h" #include "hwaccel_internal.h" #include "hwconfig.h" #include "idctdsp.h" @@ -129,8 +129,64 @@ 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 VLC ac_vlc[6]; + +static av_cold void init_vlcs(void) +{ + int i; + for (i = 0; i < sizeof(ac_info); i++) { + uint32_t ac_codes[1<> 5; /* rice code order */ + exp_order = (codebook >> 2) & 7; /* exp golomb code order */ + + switch_val = (switch_bits+1) << rice_order; + + // Values are actually transformed, but this is more a wrapping + for (ac = 0; ac <1<= switch_val) { + val += (1 << exp_order) - switch_val; + exponent = av_log2(val); + bits = exponent+1+switch_bits-exp_order/*0*/ + exponent+1/*val*/; + code = val; + } else if (rice_order) { + bits = (val >> rice_order)/*0*/ + 1/*1*/ + rice_order/*val*/; + code = (1 << rice_order) | val; + } else { + bits = val/*0*/ + 1/*1*/; + code = 1; + } + if (bits > max_bits) max_bits = bits; + ac_bits [ac] = bits; + ac_codes[ac] = code; + } + + ff_free_vlc(ac_vlc+i); + + if (init_vlc(ac_vlc+i, PRORES_LEV_BITS, 1<priv_data; uint8_t idct_permutation[64]; @@ -184,6 +240,9 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->pix_fmt = AV_PIX_FMT_NONE; + // init dc_tables + ff_thread_once(&init_static_once, init_vlcs); + if (avctx->bits_per_raw_sample == 10){ ctx->unpack_alpha = unpack_alpha_10; } else if (avctx->bits_per_raw_sample == 12){ @@ -510,7 +569,7 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, return 0; } -// adaptive codebook switching lut according to previous run/level values +// 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 }, @@ -518,12 +577,6 @@ static const char run_to_cb[16][4] = { { 0, 2, 3, -4 } }; -static const char lev_to_cb[10][4] = { - { 0, 0, 1, -1 }, { 2, 0, 0, -1 }, { 1, 0, 0, 0 }, { 2, 0, -1, 1 }, { 0, 0, 1, -1 }, - { 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) { @@ -540,8 +593,9 @@ 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); - unsigned int levcb = FFMIN(level, 9); bits_rem = get_bits_left(gb); if (!bits_rem || (bits_rem < 16 && !show_bits(gb, bits_rem))) break; @@ -554,8 +608,7 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex return AVERROR_INVALIDDATA; } - DECODE_CODEWORD2(level, lev_to_cb[levcb][0], lev_to_cb[levcb][1], - lev_to_cb[levcb][2], lev_to_cb[levcb][3]); + level = get_vlc2(gb, tbl->table, PRORES_LEV_BITS, 3); level += 1; i = pos >> log2_block_count; From patchwork Fri Sep 8 08:15:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43656 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324751pzb; Fri, 8 Sep 2023 01:16:01 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGY5aq7VYM1VXB70KqyGE6prb6dXSzKl+rjqA5NZxM8FoBaqRLrsGPV0iP/8Xg0rbCaI5yn X-Received: by 2002:ac2:4f09:0:b0:501:2071:6784 with SMTP id k9-20020ac24f09000000b0050120716784mr1765733lfr.10.1694160960851; Fri, 08 Sep 2023 01:16:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160960; cv=none; d=google.com; s=arc-20160816; b=J8M2iM1DLbmzcbZzu+BoDztsjNfdutzQRqBgR2NrMOD1CnTrKqbTYV8lDo8vGpP72W 0FzXfFRP2soIH+5cYu8mQQbYLfKRoexWtRzosKSCBx6NnL2bSaIlKLIquejg0+9Yvxju 4+a2WgzuF26USZ/fachAAiSZUoNY7somERtdcDm/X8K7ceYfFc95fzxHb0RQ+wBtQDHx onVgkcrRrMoitpvXJn2NgbyXzBN/3T/legN2nDyaX0lSewekt3Ni1uK74LrVtufOI9UC cYha+joMbHY4QyzDrpdiyK6uuN2gL8ZIO4ZhmN/XIQzxNek9SyjFnfuv7LSyFAX6VYV3 B4uQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=/45aoR6i08T6xruAMlPc6pvFRQPbmnqoRv/CkGDDfQk=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=xHJDolDXH0VmwvHh608OPONQx/cQxNED69tl8+aKVoUrR3eLhgvBewEpVvQ13y/Ble OyPK+UVar3MHrN8W/MbAl39nhdX5kDF/sulxXW56j0DWMse4DlHC5C7BTHE4R8A238FM IiENclTwS0/XLcy2TOVWvrbw/NM8/jbVj97aAwYrU/46FMYX4ROiXQChUeBelogFfJKr Iheq3eDoYKP12iXZnS1cROTZrBdsvnSTm8pd4ZFLIYAJ3PuKNXZQLO2PK7jbi2fv1AfF O9VYnx9arxrMy4zWCttfEdg/ubNRx1mmqX8JbUK+VnVOoc/WxUssbepSzU8mB4Rmj3VF qYYg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q5-20020aa7cc05000000b005233ded4188si1021937edt.432.2023.09.08.01.16.00; Fri, 08 Sep 2023 01:16:00 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E4E8F68C894; Fri, 8 Sep 2023 11:15:29 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7EEDC68C7D9 for ; Fri, 8 Sep 2023 11:15:21 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 2270EB00571 for ; Fri, 8 Sep 2023 10:15:20 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:05 +0200 Message-ID: <20230908081508.510-4-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/7] proresdec2: offset VLCs by 1 to avoid 1 add X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: d/U83E76r4p8 Pretty harmless, but not much gained either. --- libavcodec/proresdec2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 91c689d9ef..e3cef402d7 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -152,7 +152,9 @@ static av_cold void init_vlcs(void) switch_val = (switch_bits+1) << rice_order; // Values are actually transformed, but this is more a wrapping - for (ac = 0; ac <1< max_bits) max_bits = bits; - ac_bits [ac] = bits; - ac_codes[ac] = code; + ac_bits [ac+1] = bits; + ac_codes[ac+1] = code; } ff_free_vlc(ac_vlc+i); @@ -609,7 +611,6 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex } level = get_vlc2(gb, tbl->table, PRORES_LEV_BITS, 3); - level += 1; i = pos >> log2_block_count; From patchwork Fri Sep 8 08:15:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43657 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324807pzb; Fri, 8 Sep 2023 01:16:10 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFfOgovtS6v2JCfEkIjTTJzYLjusv+7yvWOcC5ZJgobybu0NLT7qZ+dFK94XIpbnKHZBjtc X-Received: by 2002:a05:6402:35c5:b0:52b:db44:79e3 with SMTP id z5-20020a05640235c500b0052bdb4479e3mr5596419edc.4.1694160970104; Fri, 08 Sep 2023 01:16:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160970; cv=none; d=google.com; s=arc-20160816; b=Bh2ZgghMTUirMlPtjgDNgqxthXOE6rhnsXwhRpaRfrIu9lnFpplT/LHeq8/Ihv6i/Q JFfc4GOJvnHmCXWrqpbe8DbDNwpHVVb1Ho1KD70qwas7IYzA8eY5iUCO9TRSqCf6NFbN 3RGkSiTGe03i/KmEtBzy5CTsC9BU9cTV7rhP1FkMyY4I8hWTzWUpaoUF2GUwSipp0iam xKOtUIzwhqgb30aria7r9o8h2IjfHW3RucQWCpMnssDtsy/Qo2/R/mz/8AJBOS4Z4+wt ymOUWU41rddinC1LEc6Io9L8J1sA4pc+XC8FiKDtAFQ/gX0u6K6xfDG3TrroY0WZJgrm Ky2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=3HnfRUWrRlAfRxxm0EnDM1B816ydvg6Bn5wcEyVmDr4=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=gPbo1nH0XjaetnXjjg2dpvm9LwWWTOXrsn/OV+Uf7N7ljthnihaX+Id2ZZsv2ivzQu a8JZgV7gugXceeFeVJWw4uPFssxy2JaHo4RXVA38l3tZGKXSykzuuKjYcsIKcf7ryfNi wTfucxcBbVoWDcrUfI6QXreJG79bV4wEf46lyXKP72VQp34+5f8R3HfOyJgieMrAAB5W a7yGvhLLfarhEF7OiJO8+AXpP88gJrcEKS/JgLT5joSEVDYmP1B/RTYi1DptrWyeYqsa Yad6322cGdEQ4NTaVYbtJLurEsOm3fYawZoohoxklHI9/oBm4Pn5pdLeqdrTEPZuCYk2 IJKg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q22-20020a056402033600b005221f19435asi1068544edw.273.2023.09.08.01.16.09; Fri, 08 Sep 2023 01:16:10 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E57E668C88D; Fri, 8 Sep 2023 11:15:30 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B533668C884 for ; Fri, 8 Sep 2023 11:15:22 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 475DDB0051B for ; Fri, 8 Sep 2023 10:15:21 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:06 +0200 Message-ID: <20230908081508.510-5-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/7] proresdec2: use VLC for small runs and levels X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: hoStb3SKrNu5 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< 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; From patchwork Fri Sep 8 08:15:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43658 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324859pzb; Fri, 8 Sep 2023 01:16:20 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH8py9nQeAX0Jyxlju4Cx1QGgKmiLvkg/+CzHH1d29bSar9FkF8KmQR1/EHfS4QIDMT4Tsc X-Received: by 2002:aa7:c502:0:b0:52c:b469:bb01 with SMTP id o2-20020aa7c502000000b0052cb469bb01mr1176611edq.38.1694160979675; Fri, 08 Sep 2023 01:16:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160979; cv=none; d=google.com; s=arc-20160816; b=XcFujCQOl/lanOOupi2U0HZBv9dZHfzkS3s5DjS3fnJ3S+xB+0qrcuYUKBoDKL+kBf YdNM32qIuRFqDnOXETT5Vk7vD6MdTLVth+XeIF/+kKYZtmPyiSj33qP3lS2CAkg1OBR4 37Vd5w/fhiJU6a3kdWHAb6PQmtZPpo7U0C3wYGJjHqSDg0cQKoy8w/5NLEdQSz1DfMjm wvDsF1s9mvspwNBC9YvJ5DrzazB49DoVPnmdE7LdVm/SF0cuhl7oKsB2XS8AHJtOUPIO hsdpdPktdiTtZUITxCSx1p/0UcoQw9+Xo8utKgI0JYYKFceVfU4v7PGNypTDvQA5YxLG 5rjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=JRqfj6sVsDDfI0B2YowX4e0Nf68iQ7I75kwBWllYAJw=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=ozsZqesC35IMg/HbvMPK4Tfi2tQuLCsQNe1hUdQmwxUf5RdFt4ll+pM5NUvIU0BQkI vSlH/oDjdmxA9J8FxHtf3lWGnS4g1GRn8R+UfIHuZ9+gnB85qiQWs92jR0/IwsOTVdeD 2brMJCy+ZN2b12SsoYuh9HZWRfWEVer3uK4SIw/wJ+v27v/tT4xzcJUu017sLx1i917z RclupgAFvKgiHLoqOQvFeLJ52VnQXCjoq9r34KCsWQ65QraUL9Nb5Lr+FkVmomHHdexr PrdvAFKYc1nn5OEO4jdMw5xGRDRTa+o39MFWXTYk80BEUAVd2s7BVASI0kyv5aDoS0cK eerg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id i3-20020aa7c703000000b005232901160dsi1048207edq.485.2023.09.08.01.16.19; Fri, 08 Sep 2023 01:16:19 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E487968C897; Fri, 8 Sep 2023 11:15:31 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1CE4168C88A for ; Fri, 8 Sep 2023 11:15:24 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id 7F33EB0053D for ; Fri, 8 Sep 2023 10:15:22 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:07 +0200 Message-ID: <20230908081508.510-6-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 6/7] proresdec2: remove a useless DC codebook entry X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: PmOmfS1CJHuj --- libavcodec/proresdec2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 02e1d82d00..b20021c622 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -534,9 +534,9 @@ static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, cons #define FIRST_DC_CB 0xB8 -static const char dc_codebook[7][4] = { +static const char dc_codebook[6][4] = { { 0, 0, 1, -1 }, { 0, 1, 2, -2 }, { 0, 1, 2, -2 }, - { 1, 2, 2, 0 }, { 1, 2, 2, 0 }, { 0, 3, 4, -8 }, { 0, 3, 4, -8 } + { 1, 2, 2, 0 }, { 1, 2, 2, 0 }, { 0, 3, 4, -8 } }; static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, @@ -553,7 +553,7 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, code = 5; sign = 0; for (i = 1; i < blocks_per_slice; i++, out += 64) { - unsigned int dccb = FFMIN(code, 6U); + unsigned int dccb = FFMIN(code, 5U); DECODE_CODEWORD2(code, dc_codebook[dccb][0], dc_codebook[dccb][1], dc_codebook[dccb][2], dc_codebook[dccb][3]); if(code) sign ^= -(code & 1); From patchwork Fri Sep 8 08:15:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 43659 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4e27:b0:149:dfde:5c0a with SMTP id gk39csp324922pzb; Fri, 8 Sep 2023 01:16:29 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGoezY8HjWuJb+FlDzDmGYdkHYyUxIol/S9BJp4mJUKWlWKLEknQH1cA+XWSSf9lI5tZyZC X-Received: by 2002:aa7:c999:0:b0:529:fa63:ef80 with SMTP id c25-20020aa7c999000000b00529fa63ef80mr1314571edt.28.1694160989157; Fri, 08 Sep 2023 01:16:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1694160989; cv=none; d=google.com; s=arc-20160816; b=smHPFhdifWKWx/l+MmAC4UUbfIFEpPAJp8iJq2RgrOZxxCiT+WckeTrEENtLv3Cszp 2cNKalNqNMHjVd8fre4NN2KZKrL4kpgnQub6XJgoUszvPknknCmyZco9vqla1u9PCNrV U4jqLmQf9wHel/nQdrnH+MTNHKKGDXDzYWiM5dycG60yeXKMWnJ/5ysDA2xIrimVthu3 JabCqxhHxK820MU3QgxWdrlehSCMoFfS4dOXMvT5CLfkE12X5e/8XbZ8lXYKsso+osjc MkT5bPk5mblTqOJYSEpDuwGLqENLO0lydfxio/U/aJWQZUy4CdTvPZjl8a5tsZJmmIAz bYfw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=3k0SOsy2hofwhaZzrmIH5rCNUpo7ffeRzyd1daAJU7M=; fh=YOA8vD9MJZuwZ71F/05pj6KdCjf6jQRmzLS+CATXUQk=; b=CnFeTtASI5UsAaQ9Na5gPJvJuDakFffRuCGuvA6HUoPw6AZX2ZIizQEtjPQVpbrTBj dn3OWLKpDsAb6SlubLl72mRNXDDBObTs2FP92ZVP9jEqXKs1d7L6F3hoTr5D7wwI4z3e 1VaCnlcwEFH3FoISbwD59UDCLi9vJy1H/aA45GczIw3UCLlITh7NN8fVOryeQIt06dsb mPxGcvMWCBQgxOiYO8xNidRNdzQLT24Qa4p0lgfEXwVx2HmL0JP7ft6JRn9tWI22M3m8 2tLF4h84mfpzn/L0POQH4ASExvDD3+LJpaWmcZZTYBQwTKzGSvSTeAziIHljpJidFRFh Ks6A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id u5-20020a056402110500b00523372ace05si1029364edv.530.2023.09.08.01.16.28; Fri, 08 Sep 2023 01:16:29 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D712968C8B7; Fri, 8 Sep 2023 11:15:32 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp1-g21.free.fr (unknown [212.27.42.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0F79D68C896 for ; Fri, 8 Sep 2023 11:15:25 +0300 (EEST) Received: from localhost.localdomain (unknown [IPv6:2a01:e0a:8a7:6440:5540:d7b2:7ae2:c181]) (Authenticated sender: christophe.gisquet@free.fr) by smtp1-g21.free.fr (Postfix) with ESMTPSA id A51EBB00535 for ; Fri, 8 Sep 2023 10:15:23 +0200 (CEST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Fri, 8 Sep 2023 10:15:08 +0200 Message-ID: <20230908081508.510-7-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230908081508.510-1-christophe.gisquet@gmail.com> References: <20230908081508.510-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 7/7] prores: use VLC LUTs X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: v4b1jl8JjLSe One indirection less, around 1% speedup. --- libavcodec/proresdec2.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index b20021c622..85f81d92d3 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -561,12 +561,18 @@ static av_always_inline int decode_dc_coeffs(GetBitContext *gb, int16_t *out, prev_dc += (((code + 1) >> 1) ^ sign) - sign; out[0] = prev_dc; } - return 0; + return 0; } +#include "libavutil/timer.h" + + static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb, int16_t *out, int blocks_per_slice) { + static VLC* lvl_vlc[9] = { &ac_vlc[0], &ac_vlc[1], &ac_vlc[2], &ac_vlc[3], &ac_vlc[0], &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], }; + static VLC* run_vlc[15] = { &ac_vlc[3], &ac_vlc[3], &ac_vlc[2], &ac_vlc[2], &ac_vlc[0], &ac_vlc[5], &ac_vlc[5], &ac_vlc[5], &ac_vlc[5], + &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], &ac_vlc[4], }; const ProresContext *ctx = avctx->priv_data; int block_mask, sign; unsigned pos, run, level; @@ -585,9 +591,7 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex break; 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); + run = get_vlc2(gb, run_vlc[run]->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 @@ -599,9 +603,7 @@ static av_always_inline int decode_ac_coeffs(AVCodecContext *avctx, GetBitContex } 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); + level = 1+get_vlc2(gb, lvl_vlc[level]->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