From patchwork Fri Jun 17 13:32:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36306 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp135442pzb; Fri, 17 Jun 2022 06:32:21 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vSfVOg9ZC2eFH8GJH7b6f5r2X6bTmQzZZJoReefer1fNJYjO0cguCQKIfSveAw9inXqhT9 X-Received: by 2002:a05:6402:2204:b0:435:274d:f04e with SMTP id cq4-20020a056402220400b00435274df04emr12760478edb.262.1655472741524; Fri, 17 Jun 2022 06:32:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655472741; cv=none; d=google.com; s=arc-20160816; b=Bu7zJAEUxKs6ZZAai8DM2MdsAkMbIcfwkvHBJky8Ru9HhZjNfDAQpgiBtQqSsUS0T2 5xx5JeEdIA6XWy8vfoPcz+5TexFmXXgQ8B/17F6GqfcpV6XSyUX0/FBC3EDQmO+GcbVn 0L9bQYZs9KQ9HjqkMg5RlRtgCRpeptUd+FmakUfMBT1mdQWn9bfBppSoHLepSOnhl3FS qlUPN9jHv5EyrUiCDmJ5PODdeyYBeCQsMxY5qBaurwe36zbwGAqBh45nxGkboUlQONof 1R5+aI2cB4oUJH0FV5J2Jz1KsYjaEQvYzyZwU+NcN7sf+H3EaYdOssm+HKFcw2KKPsQM a/CQ== 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=KFqyw98XENl8GiQ4Xkrv3vqXD6J5Qp/whVFHSDLrZ2A=; b=xKsuXzoNMVSZUQfxW90A8rG9kC3Dtlyw5y3EZmnGcUy5t9x3zAav16W5v4U3SJjYH3 PkwQ4ih32VwkEm+oX0y9jOnMubB1LWGqq3MSxr+4FWyl9irCig/dl4JPzfLlzLav0y1E 3BLLMcYU9POuSzvjWB1g59Cc0CDY1sAD++1wY7jN6cXY/jzgqucnoDLejbmzbX19amEJ OREHNvJKZ9xWxUamq8Hiqfh2fF2ipypLJyS3AiDzGD1zoNQiVV124WWgoIKqJnFgTMKz nK8yBMZFvblGdC1iAB5r8bBtjLvCCu5wtRFHoudzKG3bOs/Xd1LysR0mYTzbZ/HyJ+Gi tahg== 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 25-20020a170906015900b007075a3f9afbsi4510663ejh.377.2022.06.17.06.32.20; Fri, 17 Jun 2022 06:32:21 -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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9770168B8C7; Fri, 17 Jun 2022 16:32:16 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E867D68B69B for ; Fri, 17 Jun 2022 16:32:09 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 7D352240506 for ; Fri, 17 Jun 2022 15:32:09 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id kl4RPhJTiO79 for ; Fri, 17 Jun 2022 15:32:09 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id EFCF2240175 for ; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id D98053A0A3A; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 17 Jun 2022 15:32:02 +0200 Message-Id: <20220617133206.23643-1-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/5] get_bits: move check_marker() to mpegvideodec.h 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: 3VzjQK6rbd/y It is only used by mpegvideo-based decoders - specifically mpeg12, intelh263, ituh263, mpeg4video. --- libavcodec/get_bits.h | 10 ---------- libavcodec/intelh263dec.c | 1 + libavcodec/ituh263dec.c | 1 + libavcodec/mpegvideodec.h | 10 ++++++++++ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index d4e9276da1..498ce4ed35 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -610,16 +610,6 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n) } } -static inline int check_marker(void *logctx, GetBitContext *s, const char *msg) -{ - int bit = get_bits1(s); - if (!bit) - av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", - get_bits_count(s) - 1, s->size_in_bits, msg); - - return bit; -} - static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer, int bit_size, int is_le) { diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index e7e821d3b3..ded0a7f618 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -21,6 +21,7 @@ #include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "h263data.h" #include "h263dec.h" #include "mpegvideodata.h" diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index f01c942f04..af054360d8 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -48,6 +48,7 @@ #include "rv10dec.h" #include "mpeg4video.h" #include "mpegvideodata.h" +#include "mpegvideodec.h" #include "mpeg4videodec.h" // The defines below define the number of bits that are read at once for diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h index 1af8ebac36..10394a616c 100644 --- a/libavcodec/mpegvideodec.h +++ b/libavcodec/mpegvideodec.h @@ -67,4 +67,14 @@ static inline int mpeg_get_qscale(MpegEncContext *s) return qscale << 1; } +static inline int check_marker(void *logctx, GetBitContext *s, const char *msg) +{ + int bit = get_bits1(s); + if (!bit) + av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", + get_bits_count(s) - 1, s->size_in_bits, msg); + + return bit; +} + #endif /* AVCODEC_MPEGVIDEODEC_H */ From patchwork Fri Jun 17 13:32:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36309 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp135801pzb; Fri, 17 Jun 2022 06:32:55 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uBJ39aD++3CxQ9juoeD5+cTqq63a2yva0Do4KFBSz/7q18qi1k0U2isTYukHU/Kff6oi1Q X-Received: by 2002:a50:ed8a:0:b0:435:6582:6864 with SMTP id h10-20020a50ed8a000000b0043565826864mr2281615edr.417.1655472774898; Fri, 17 Jun 2022 06:32:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655472774; cv=none; d=google.com; s=arc-20160816; b=Iak2oJR1Uj/ALMjmcBLcqdLEivN7XSxLFM2lqZxGTJVWzf5LLW3hKujz/74sdEdb58 sBgzDirPFDu5AQyVa0WBS5H2w1P7zW4M20ulrlyG0bDCTqml82tqZjLDbOYF87FAiom3 Z+8ozt4RKiAH/cUWJm69gKlU/u/qckv3LgioNJOe5XKKQ4kRoqNro4WeJg7h/G+wgRrE 0hc9xXaF+yBW64sfuhp6AW7SBAR9DaNWSht37iQ8SW/euKVyXrQBd0rGBlIA4C3qbpeU D3rKSLk512kkwf80epwivJ578HCP1EciFvzVJ3LvmBZxoijSFtLBu8JKeAeSo5R1UCyh gw7A== 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=JzwIR5D1PP5NTtGR0s6foi1Lu/C1sHZ2MZMgPrQRz14=; b=aaA/h4OWmBPwSS8N6Lfu7EN4RTE4VZ7VayZEW6N4UmymmZcfW9lsesou1qva8kytoG j5mllxX5yZ616jlgODvVAf3yHCUGQjum5YEJudJEBv0jcBPnLiysXymhDqQtMbuw9259 UsDpeWU6FJs4oCG8RqWPuEei5Zb1O3xQXG8Q8ZGa9Fw901vaRnPx/ZNbmTO4+Pot2Ykb 3wf9d1PfUUhdCr8aT6ozWts7Q6cxjXkozbsNrKJ6sodafQjYAg0nr2ND+gTXnI+Tc5bI H1uQPtr4ovf+yiaJowDCVnNpM0T4d3e1JYg2X3O9mRgq1snr9TMTi34M1NRgOpEyZj4h kZQw== 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g18-20020a50ec12000000b0042de905c6dfsi5220089edr.522.2022.06.17.06.32.54; Fri, 17 Jun 2022 06:32:54 -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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 85F1768B8F0; Fri, 17 Jun 2022 16:32:20 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 35C9068B8CF for ; Fri, 17 Jun 2022 16:32:12 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id C3A2B24017C for ; Fri, 17 Jun 2022 15:32:11 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id pe3LK2vZXHyZ for ; Fri, 17 Jun 2022 15:32:10 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id F2F2724017E for ; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id DE04D3A11FE; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 17 Jun 2022 15:32:03 +0200 Message-Id: <20220617133206.23643-2-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220617133206.23643-1-anton@khirnov.net> References: <20220617133206.23643-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/5] lavc: add standalone cached bitstream 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: w/ZhuNBmE7Ol From: Alexandra Hájková The cached bitstream reader was originally written by Alexandra Hájková for Libav, with significant input from Kostya Shishkov and Luca Barbato. It was then committed to FFmpeg in ca079b09549, by merging it with the implementation of the current bitstream reader. This merge makes the code of get_bits.h significantly harder to read, since it now contains two different bitstream readers interleaved with #ifdefs. Additionally, the code was committed without proper authorship attribution. This commit re-adds the cached bitstream reader as a standalone header, as it was originally developed. It will be made useful in following commits. Integration by Anton Khirnov. Signed-off-by: Anton Khirnov --- libavcodec/bitstream.h | 490 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 libavcodec/bitstream.h diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h new file mode 100644 index 0000000000..85f1af28c8 --- /dev/null +++ b/libavcodec/bitstream.h @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2016 Alexandra Hájková + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * bitstream reader API header. + */ + +#ifndef AVCODEC_BITSTREAM_H +#define AVCODEC_BITSTREAM_H + +#include + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" + +#include "mathops.h" +#include "vlc.h" + +#ifndef UNCHECKED_BITSTREAM_READER +#define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER +#endif + +typedef struct BitstreamContext { + uint64_t bits; // stores bits read from the buffer + const uint8_t *buffer, *buffer_end; + const uint8_t *ptr; // pointer to the position inside a buffer + unsigned bits_left; // number of bits left in bits field + unsigned size_in_bits; +} BitstreamContext; + +static inline void refill_64(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return; +#endif + +#ifdef BITSTREAM_READER_LE + bc->bits = AV_RL64(bc->ptr); +#else + bc->bits = AV_RB64(bc->ptr); +#endif + bc->ptr += 8; + bc->bits_left = 64; +} + +static inline void refill_32(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return; +#endif + +#ifdef BITSTREAM_READER_LE + bc->bits = (uint64_t)AV_RL32(bc->ptr) << bc->bits_left | bc->bits; +#else + bc->bits = bc->bits | (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_left); +#endif + bc->ptr += 4; + bc->bits_left += 32; +} + +/** + * Initialize BitstreamContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int bitstream_init(BitstreamContext *bc, const uint8_t *buffer, + unsigned int bit_size) +{ + unsigned int buffer_size; + + if (bit_size > INT_MAX - 7 || !buffer) { + bc->buffer = NULL; + bc->ptr = NULL; + bc->bits_left = 0; + return AVERROR_INVALIDDATA; + } + + buffer_size = (bit_size + 7) >> 3; + + bc->buffer = buffer; + bc->buffer_end = buffer + buffer_size; + bc->ptr = bc->buffer; + bc->size_in_bits = bit_size; + bc->bits_left = 0; + bc->bits = 0; + + refill_64(bc); + + return 0; +} + +/** + * Initialize BitstreamContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow + */ +static inline int bitstream_init8(BitstreamContext *bc, const uint8_t *buffer, + unsigned int byte_size) +{ + if (byte_size > INT_MAX / 8) + return AVERROR_INVALIDDATA; + return bitstream_init(bc, buffer, byte_size * 8); +} + +/** + * Return number of bits already read. + */ +static inline int bitstream_tell(const BitstreamContext *bc) +{ + return (bc->ptr - bc->buffer) * 8 - bc->bits_left; +} + +/** + * Return buffer size in bits. + */ +static inline int bitstream_tell_size(const BitstreamContext *bc) +{ + return bc->size_in_bits; +} + +/** + * Return the number of the bits left in a buffer. + */ +static inline int bitstream_bits_left(const BitstreamContext *bc) +{ + return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_left; +} + +static inline uint64_t get_val(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret; + +#ifdef BITSTREAM_READER_LE + ret = bc->bits & ((UINT64_C(1) << n) - 1); + bc->bits >>= n; +#else + ret = bc->bits >> (64 - n); + bc->bits <<= n; +#endif + bc->bits_left -= n; + + return ret; +} + +/** + * Return one bit from the buffer. + */ +static inline unsigned int bitstream_read_bit(BitstreamContext *bc) +{ + if (!bc->bits_left) + refill_64(bc); + + return get_val(bc, 1); +} + +/** + * Return n bits from the buffer, n has to be in the 0-63 range. + */ +static inline uint64_t bitstream_read_63(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret = 0; +#ifdef BITSTREAM_READER_LE + uint64_t left = 0; +#endif + + if (!n) + return 0; + + if (n > bc->bits_left) { + n -= bc->bits_left; +#ifdef BITSTREAM_READER_LE + left = bc->bits_left; +#endif + ret = get_val(bc, bc->bits_left); + refill_64(bc); + } + +#ifdef BITSTREAM_READER_LE + ret = get_val(bc, n) << left | ret; +#else + ret = get_val(bc, n) | ret << n; +#endif + + return ret; +} + +/** + * Return n bits from the buffer, n has to be in the 0-32 range. + */ +static inline uint32_t bitstream_read(BitstreamContext *bc, unsigned int n) +{ + if (!n) + return 0; + + if (n > bc->bits_left) { + refill_32(bc); + if (bc->bits_left < 32) + bc->bits_left = n; + } + + return get_val(bc, n); +} + +/** + * Return n bits from the buffer as a signed integer. + * n has to be in the 0-32 range. + */ +static inline int32_t bitstream_read_signed(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(bitstream_read(bc, n), n); +} + +static inline unsigned int show_val(BitstreamContext *bc, unsigned int n) +{ +#ifdef BITSTREAM_READER_LE + return bc->bits & ((UINT64_C(1) << n) - 1); +#else + return bc->bits >> (64 - n); +#endif +} + +/** + * Return n bits from the buffer but do not change the buffer state. + * n has to be in the 0-32 range. + */ +static inline unsigned int bitstream_peek(BitstreamContext *bc, unsigned int n) +{ + if (n > bc->bits_left) + refill_32(bc); + + return show_val(bc, n); +} + +/** + * Return n bits from the buffer as a signed integer, + * do not change the buffer state. + * n has to be in the 0-32 range. + */ +static inline int bitstream_peek_signed(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(bitstream_peek(bc, n), n); +} + +static inline void skip_remaining(BitstreamContext *bc, unsigned int n) +{ +#ifdef BITSTREAM_READER_LE + bc->bits >>= n; +#else + bc->bits <<= n; +#endif + bc->bits_left -= n; +} + +/** + * Skip n bits in the buffer. + */ +static inline void bitstream_skip(BitstreamContext *bc, unsigned int n) +{ + if (n < bc->bits_left) + skip_remaining(bc, n); + else { + n -= bc->bits_left; + bc->bits = 0; + bc->bits_left = 0; + + if (n >= 64) { + unsigned int skip = n / 8; + + n -= skip * 8; + bc->ptr += skip; + } + refill_64(bc); + if (n) + skip_remaining(bc, n); + } +} + +/** + * Seek to the given bit position. + */ +static inline void bitstream_seek(BitstreamContext *bc, unsigned pos) +{ + bc->ptr = bc->buffer; + bc->bits = 0; + bc->bits_left = 0; + + bitstream_skip(bc, pos); +} + +/** + * Skip bits to a byte boundary. + */ +static inline const uint8_t *bitstream_align(BitstreamContext *bc) +{ + unsigned int n = -bitstream_tell(bc) & 7; + if (n) + bitstream_skip(bc, n); + return bc->buffer + (bitstream_tell(bc) >> 3); +} + +/** + * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). + * If MSB not set it is negative. + * @param n length in bits + */ +static inline int bitstream_read_xbits(BitstreamContext *bc, unsigned int n) +{ + int32_t cache = bitstream_peek(bc, 32); + int sign = ~cache >> 31; + skip_remaining(bc, n); + + return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; +} + +/** + * Return decoded truncated unary code for the values 0, 1, 2. + */ +static inline int bitstream_decode012(BitstreamContext *bc) +{ + if (!bitstream_read_bit(bc)) + return 0; + else + return bitstream_read_bit(bc) + 1; +} + +/** + * Return decoded truncated unary code for the values 2, 1, 0. + */ +static inline int bitstream_decode210(BitstreamContext *bc) +{ + if (bitstream_read_bit(bc)) + return 0; + else + return 2 - bitstream_read_bit(bc); +} + +/* Read sign bit and flip the sign of the provided value accordingly. */ +static inline int bitstream_apply_sign(BitstreamContext *bc, int val) +{ + int sign = bitstream_read_signed(bc, 1); + return (val ^ sign) - sign; +} + +static inline int bitstream_skip_1stop_8data(BitstreamContext *s) +{ + if (bitstream_bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + + while (bitstream_read(s, 1)) { + bitstream_skip(s, 8); + if (bitstream_bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/* Unwind the cache so a refill_32 can fill it again. */ +static inline void bitstream_unwind(BitstreamContext *bc) +{ + int unwind = 4; + int unwind_bits = unwind * 8; + + if (bc->bits_left < unwind_bits) + return; + + bc->bits >>= unwind_bits; + bc->bits <<= unwind_bits; + bc->bits_left -= unwind_bits; + bc->ptr -= unwind; +} + +/* Unget up to 32 bits. */ +static inline void bitstream_unget(BitstreamContext *bc, uint64_t value, + size_t amount) +{ + size_t cache_size = sizeof(bc->bits) * 8; + + if (bc->bits_left + amount > cache_size) + bitstream_unwind(bc); + + bc->bits = (bc->bits >> amount) | (value << (cache_size - amount)); + bc->bits_left += amount; +} + +/** + * Return the LUT element for the given bitstream configuration. + */ +static inline int set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, + VLC_TYPE (*table)[2]) +{ + unsigned idx; + + *nb_bits = -*n; + idx = bitstream_peek(bc, *nb_bits) + code; + *n = table[idx][1]; + + return table[idx][0]; +} + +/** + * Parse a vlc code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +static inline int bitstream_read_vlc(BitstreamContext *bc, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = bitstream_peek(bc, bits); + int code = table[idx][0]; + int n = table[idx][1]; + + if (max_depth > 1 && n < 0) { + skip_remaining(bc, bits); + code = set_idx(bc, code, &n, &nb_bits, table); + if (max_depth > 2 && n < 0) { + skip_remaining(bc, nb_bits); + code = set_idx(bc, code, &n, &nb_bits, table); + } + } + skip_remaining(bc, n); + + return code; +} + +#define BITSTREAM_RL_VLC(level, run, bc, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + unsigned int index = bitstream_peek(bc, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + bitstream_skip(bc, bits); \ + \ + nb_bits = -n; \ + \ + index = bitstream_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + bitstream_skip(bc, nb_bits); \ + nb_bits = -n; \ + \ + index = bitstream_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + bitstream_skip(bc, n); \ + } while (0) + +#endif /* AVCODEC_BITSTREAM_H */ From patchwork Fri Jun 17 13:32:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36308 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp135674pzb; Fri, 17 Jun 2022 06:32:43 -0700 (PDT) X-Google-Smtp-Source: AGRyM1v75a7zGDQGKZFkxsbBeC1DkECQq4ragkJYQR1glWNYJcx1uixHXQ84TvQtLGi9xiX2eoHj X-Received: by 2002:a17:906:1018:b0:718:dd3f:f28c with SMTP id 24-20020a170906101800b00718dd3ff28cmr9615449ejm.55.1655472763109; Fri, 17 Jun 2022 06:32:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655472763; cv=none; d=google.com; s=arc-20160816; b=wIPS6FA3Na7d2tLkg9VWNDJPCudC7q4BgGjEqt3XLvqKJpde5hZPpaK848Ag9eCuLj WN75LwcG7RvxFi08/URMxM8p7Tg/KId4yuiEdc1HdkAD6a1IofoFPHki6q1YaBdf1AXK LvxUxMsgjnkWhs55uapDoIRApAbfqSgdxh3G5yefqwXF3bLi92a8irIj124Gedh6fhOn Uzt2O1+yBZd+s0pt3l6fI3za/AImIzqeawezlradFLGGLjLD0YokyneBhO8v2PPzagUt OUzUEFHv22rjj9zpUu8KvhXCsEUHnYFPLf6Tg475IE4WQYIMtSEz06MiqxpcszK1Ty1W BEEg== 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=a3g4ADFCHgkKZqVO2bKIdZwZh5zA3Iq7mZXXwafVnlM=; b=hWzYjEuyswMN2uMnm8+HF5UxDGoalS6UMbJv2DWQTKx+qXNnTS//AkV0aWqsCNmti2 oxAMlNhFtbaXPWAR3w+AYOvnJItwBDU6j8BCPHdOdsPp7i2mHKhTg/2osoDOgdISUwO7 NUXVK9dMjF4inuxiNOwYoKRhy1bLEd4Jf02vWy5Yn/TQF+5D6AzMKotSrA+MdE9mJG4M j2IsKQ7ojtK5HB9DIOmjiq+Yn2cNKVZUAVZUrOl0TmRuULkU85zDo1wUFW/rTUvN1kq3 lWTuMaqQPdJjuclxJARgEGwTDb5fIyMM33wPTUyzv4Iup0cZ9qpbYh7yCgsqki2c65ig 2Vaw== 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q30-20020a50c35e000000b00434fe8a1fb2si1234852edb.559.2022.06.17.06.32.41; Fri, 17 Jun 2022 06:32:43 -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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9B61B68B69B; Fri, 17 Jun 2022 16:32:19 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5141B68B8C7 for ; Fri, 17 Jun 2022 16:32:11 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id DF6722400F5 for ; Fri, 17 Jun 2022 15:32:10 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id QA-dI-STn6WQ for ; Fri, 17 Jun 2022 15:32:09 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id F18A424017C for ; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id E35F63A1249; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 17 Jun 2022 15:32:04 +0200 Message-Id: <20220617133206.23643-3-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220617133206.23643-1-anton@khirnov.net> References: <20220617133206.23643-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/5] lavc/bitstream: templatize for BE/LE 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: 0NcNDaG0xi7M Allows using both BE and LE bitstream readers in the same file. --- libavcodec/bitstream.h | 379 ++---------------------------- libavcodec/bitstream_template.h | 392 ++++++++++++++++++++++++++++++++ tests/ref/fate/source | 1 + 3 files changed, 415 insertions(+), 357 deletions(-) create mode 100644 libavcodec/bitstream_template.h diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index 85f1af28c8..3fa63695d3 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -49,88 +49,6 @@ typedef struct BitstreamContext { unsigned size_in_bits; } BitstreamContext; -static inline void refill_64(BitstreamContext *bc) -{ -#if !UNCHECKED_BITSTREAM_READER - if (bc->ptr >= bc->buffer_end) - return; -#endif - -#ifdef BITSTREAM_READER_LE - bc->bits = AV_RL64(bc->ptr); -#else - bc->bits = AV_RB64(bc->ptr); -#endif - bc->ptr += 8; - bc->bits_left = 64; -} - -static inline void refill_32(BitstreamContext *bc) -{ -#if !UNCHECKED_BITSTREAM_READER - if (bc->ptr >= bc->buffer_end) - return; -#endif - -#ifdef BITSTREAM_READER_LE - bc->bits = (uint64_t)AV_RL32(bc->ptr) << bc->bits_left | bc->bits; -#else - bc->bits = bc->bits | (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_left); -#endif - bc->ptr += 4; - bc->bits_left += 32; -} - -/** - * Initialize BitstreamContext. - * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes - * larger than the actual read bits because some optimized bitstream - * readers read 32 or 64 bits at once and could read over the end - * @param bit_size the size of the buffer in bits - * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. - */ -static inline int bitstream_init(BitstreamContext *bc, const uint8_t *buffer, - unsigned int bit_size) -{ - unsigned int buffer_size; - - if (bit_size > INT_MAX - 7 || !buffer) { - bc->buffer = NULL; - bc->ptr = NULL; - bc->bits_left = 0; - return AVERROR_INVALIDDATA; - } - - buffer_size = (bit_size + 7) >> 3; - - bc->buffer = buffer; - bc->buffer_end = buffer + buffer_size; - bc->ptr = bc->buffer; - bc->size_in_bits = bit_size; - bc->bits_left = 0; - bc->bits = 0; - - refill_64(bc); - - return 0; -} - -/** - * Initialize BitstreamContext. - * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes - * larger than the actual read bits because some optimized bitstream - * readers read 32 or 64 bits at once and could read over the end - * @param byte_size the size of the buffer in bytes - * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow - */ -static inline int bitstream_init8(BitstreamContext *bc, const uint8_t *buffer, - unsigned int byte_size) -{ - if (byte_size > INT_MAX / 8) - return AVERROR_INVALIDDATA; - return bitstream_init(bc, buffer, byte_size * 8); -} - /** * Return number of bits already read. */ @@ -155,235 +73,6 @@ static inline int bitstream_bits_left(const BitstreamContext *bc) return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_left; } -static inline uint64_t get_val(BitstreamContext *bc, unsigned int n) -{ - uint64_t ret; - -#ifdef BITSTREAM_READER_LE - ret = bc->bits & ((UINT64_C(1) << n) - 1); - bc->bits >>= n; -#else - ret = bc->bits >> (64 - n); - bc->bits <<= n; -#endif - bc->bits_left -= n; - - return ret; -} - -/** - * Return one bit from the buffer. - */ -static inline unsigned int bitstream_read_bit(BitstreamContext *bc) -{ - if (!bc->bits_left) - refill_64(bc); - - return get_val(bc, 1); -} - -/** - * Return n bits from the buffer, n has to be in the 0-63 range. - */ -static inline uint64_t bitstream_read_63(BitstreamContext *bc, unsigned int n) -{ - uint64_t ret = 0; -#ifdef BITSTREAM_READER_LE - uint64_t left = 0; -#endif - - if (!n) - return 0; - - if (n > bc->bits_left) { - n -= bc->bits_left; -#ifdef BITSTREAM_READER_LE - left = bc->bits_left; -#endif - ret = get_val(bc, bc->bits_left); - refill_64(bc); - } - -#ifdef BITSTREAM_READER_LE - ret = get_val(bc, n) << left | ret; -#else - ret = get_val(bc, n) | ret << n; -#endif - - return ret; -} - -/** - * Return n bits from the buffer, n has to be in the 0-32 range. - */ -static inline uint32_t bitstream_read(BitstreamContext *bc, unsigned int n) -{ - if (!n) - return 0; - - if (n > bc->bits_left) { - refill_32(bc); - if (bc->bits_left < 32) - bc->bits_left = n; - } - - return get_val(bc, n); -} - -/** - * Return n bits from the buffer as a signed integer. - * n has to be in the 0-32 range. - */ -static inline int32_t bitstream_read_signed(BitstreamContext *bc, unsigned int n) -{ - return sign_extend(bitstream_read(bc, n), n); -} - -static inline unsigned int show_val(BitstreamContext *bc, unsigned int n) -{ -#ifdef BITSTREAM_READER_LE - return bc->bits & ((UINT64_C(1) << n) - 1); -#else - return bc->bits >> (64 - n); -#endif -} - -/** - * Return n bits from the buffer but do not change the buffer state. - * n has to be in the 0-32 range. - */ -static inline unsigned int bitstream_peek(BitstreamContext *bc, unsigned int n) -{ - if (n > bc->bits_left) - refill_32(bc); - - return show_val(bc, n); -} - -/** - * Return n bits from the buffer as a signed integer, - * do not change the buffer state. - * n has to be in the 0-32 range. - */ -static inline int bitstream_peek_signed(BitstreamContext *bc, unsigned int n) -{ - return sign_extend(bitstream_peek(bc, n), n); -} - -static inline void skip_remaining(BitstreamContext *bc, unsigned int n) -{ -#ifdef BITSTREAM_READER_LE - bc->bits >>= n; -#else - bc->bits <<= n; -#endif - bc->bits_left -= n; -} - -/** - * Skip n bits in the buffer. - */ -static inline void bitstream_skip(BitstreamContext *bc, unsigned int n) -{ - if (n < bc->bits_left) - skip_remaining(bc, n); - else { - n -= bc->bits_left; - bc->bits = 0; - bc->bits_left = 0; - - if (n >= 64) { - unsigned int skip = n / 8; - - n -= skip * 8; - bc->ptr += skip; - } - refill_64(bc); - if (n) - skip_remaining(bc, n); - } -} - -/** - * Seek to the given bit position. - */ -static inline void bitstream_seek(BitstreamContext *bc, unsigned pos) -{ - bc->ptr = bc->buffer; - bc->bits = 0; - bc->bits_left = 0; - - bitstream_skip(bc, pos); -} - -/** - * Skip bits to a byte boundary. - */ -static inline const uint8_t *bitstream_align(BitstreamContext *bc) -{ - unsigned int n = -bitstream_tell(bc) & 7; - if (n) - bitstream_skip(bc, n); - return bc->buffer + (bitstream_tell(bc) >> 3); -} - -/** - * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). - * If MSB not set it is negative. - * @param n length in bits - */ -static inline int bitstream_read_xbits(BitstreamContext *bc, unsigned int n) -{ - int32_t cache = bitstream_peek(bc, 32); - int sign = ~cache >> 31; - skip_remaining(bc, n); - - return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; -} - -/** - * Return decoded truncated unary code for the values 0, 1, 2. - */ -static inline int bitstream_decode012(BitstreamContext *bc) -{ - if (!bitstream_read_bit(bc)) - return 0; - else - return bitstream_read_bit(bc) + 1; -} - -/** - * Return decoded truncated unary code for the values 2, 1, 0. - */ -static inline int bitstream_decode210(BitstreamContext *bc) -{ - if (bitstream_read_bit(bc)) - return 0; - else - return 2 - bitstream_read_bit(bc); -} - -/* Read sign bit and flip the sign of the provided value accordingly. */ -static inline int bitstream_apply_sign(BitstreamContext *bc, int val) -{ - int sign = bitstream_read_signed(bc, 1); - return (val ^ sign) - sign; -} - -static inline int bitstream_skip_1stop_8data(BitstreamContext *s) -{ - if (bitstream_bits_left(s) <= 0) - return AVERROR_INVALIDDATA; - - while (bitstream_read(s, 1)) { - bitstream_skip(s, 8); - if (bitstream_bits_left(s) <= 0) - return AVERROR_INVALIDDATA; - } - - return 0; -} - /* Unwind the cache so a refill_32 can fill it again. */ static inline void bitstream_unwind(BitstreamContext *bc) { @@ -412,52 +101,28 @@ static inline void bitstream_unget(BitstreamContext *bc, uint64_t value, bc->bits_left += amount; } -/** - * Return the LUT element for the given bitstream configuration. - */ -static inline int set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, - VLC_TYPE (*table)[2]) -{ - unsigned idx; - - *nb_bits = -*n; - idx = bitstream_peek(bc, *nb_bits) + code; - *n = table[idx][1]; - - return table[idx][0]; -} - -/** - * Parse a vlc code. - * @param bits is the number of bits which will be read at once, must be - * identical to nb_bits in init_vlc() - * @param max_depth is the number of times bits bits must be read to completely - * read the longest vlc code - * = (max_vlc_length + bits - 1) / bits - * If the vlc code is invalid and max_depth=1, then no bits will be removed. - * If the vlc code is invalid and max_depth>1, then the number of bits removed - * is undefined. - */ -static inline int bitstream_read_vlc(BitstreamContext *bc, VLC_TYPE (*table)[2], - int bits, int max_depth) -{ - int nb_bits; - unsigned idx = bitstream_peek(bc, bits); - int code = table[idx][0]; - int n = table[idx][1]; - - if (max_depth > 1 && n < 0) { - skip_remaining(bc, bits); - code = set_idx(bc, code, &n, &nb_bits, table); - if (max_depth > 2 && n < 0) { - skip_remaining(bc, nb_bits); - code = set_idx(bc, code, &n, &nb_bits, table); - } - } - skip_remaining(bc, n); - - return code; -} +#define BITSTREAM_LE +#include "bitstream_template.h" + +#undef BITSTREAM_LE +#include "bitstream_template.h" + +#define bitstream_init bitstream_init_be +#define bitstream_init8 bitstream_init8_be +#define bitstream_read_bit bitstream_read_bit_be +#define bitstream_read_63 bitstream_read_63_be +#define bitstream_read bitstream_read_be +#define bitstream_read_signed bitstream_read_signed_be +#define bitstream_peek bitstream_peek_be +#define bitstream_peek_signed bitstream_peek_signed_be +#define bitstream_skip bitstream_skip_be +#define bitstream_seek bitstream_seek_be +#define bitstream_align bitstream_align_be +#define bitstream_read_xbits bitstream_read_xbits_be +#define bitstream_decode012 bitstream_decode012_be +#define bitstream_decode210 bitstream_decode210_be +#define bitstream_apply_sign bitstream_apply_sign_be +#define bitstream_read_vlc bitstream_read_vlc_be #define BITSTREAM_RL_VLC(level, run, bc, table, bits, max_depth) \ do { \ diff --git a/libavcodec/bitstream_template.h b/libavcodec/bitstream_template.h new file mode 100644 index 0000000000..14a420139c --- /dev/null +++ b/libavcodec/bitstream_template.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2016 Alexandra Hájková + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef BITSTREAM_LE +# define BS_SUFFIX le +#else +# define BS_SUFFIX be +#endif + +#define BS_JOIN(x, y) x ## _ ## y +#define BS_FUNC2(x, y) BS_JOIN(x, y) +#define BS_FUNC(x) BS_FUNC2(x, BS_SUFFIX) + +static inline void BS_FUNC(refill_64)(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return; +#endif + +#ifdef BITSTREAM_LE + bc->bits = AV_RL64(bc->ptr); +#else + bc->bits = AV_RB64(bc->ptr); +#endif + bc->ptr += 8; + bc->bits_left = 64; +} + +static inline void BS_FUNC(refill_32)(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return; +#endif + +#ifdef BITSTREAM_LE + bc->bits = (uint64_t)AV_RL32(bc->ptr) << bc->bits_left | bc->bits; +#else + bc->bits = bc->bits | (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_left); +#endif + bc->ptr += 4; + bc->bits_left += 32; +} + +/** + * Initialize BitstreamContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int BS_FUNC(bitstream_init)(BitstreamContext *bc, const uint8_t *buffer, + unsigned int bit_size) +{ + unsigned int buffer_size; + + if (bit_size > INT_MAX - 7 || !buffer) { + bc->buffer = NULL; + bc->ptr = NULL; + bc->bits_left = 0; + return AVERROR_INVALIDDATA; + } + + buffer_size = (bit_size + 7) >> 3; + + bc->buffer = buffer; + bc->buffer_end = buffer + buffer_size; + bc->ptr = bc->buffer; + bc->size_in_bits = bit_size; + bc->bits_left = 0; + bc->bits = 0; + + BS_FUNC(refill_64)(bc); + + return 0; +} + +/** + * Initialize BitstreamContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow + */ +static inline int BS_FUNC(bitstream_init8)(BitstreamContext *bc, const uint8_t *buffer, + unsigned int byte_size) +{ + if (byte_size > INT_MAX / 8) + return AVERROR_INVALIDDATA; + return BS_FUNC(bitstream_init)(bc, buffer, byte_size * 8); +} + +static inline uint64_t BS_FUNC(get_val)(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret; + +#ifdef BITSTREAM_LE + ret = bc->bits & ((UINT64_C(1) << n) - 1); + bc->bits >>= n; +#else + ret = bc->bits >> (64 - n); + bc->bits <<= n; +#endif + bc->bits_left -= n; + + return ret; +} + +/** + * Return one bit from the buffer. + */ +static inline unsigned int BS_FUNC(bitstream_read_bit)(BitstreamContext *bc) +{ + if (!bc->bits_left) + BS_FUNC(refill_64)(bc); + + return BS_FUNC(get_val)(bc, 1); +} + +/** + * Return n bits from the buffer, n has to be in the 0-63 range. + */ +static inline uint64_t BS_FUNC(bitstream_read_63)(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret = 0; +#ifdef BITSTREAM_LE + uint64_t left = 0; +#endif + + if (!n) + return 0; + + if (n > bc->bits_left) { + n -= bc->bits_left; +#ifdef BITSTREAM_LE + left = bc->bits_left; +#endif + ret = BS_FUNC(get_val)(bc, bc->bits_left); + BS_FUNC(refill_64)(bc); + } + +#ifdef BITSTREAM_LE + ret = get_val_le(bc, n) << left | ret; +#else + ret = get_val_be(bc, n) | ret << n; +#endif + + return ret; +} + +/** + * Return n bits from the buffer, n has to be in the 0-32 range. + */ +static inline uint32_t BS_FUNC(bitstream_read)(BitstreamContext *bc, unsigned int n) +{ + if (!n) + return 0; + + if (n > bc->bits_left) { + BS_FUNC(refill_32)(bc); + if (bc->bits_left < 32) + bc->bits_left = n; + } + + return BS_FUNC(get_val)(bc, n); +} + +/** + * Return n bits from the buffer as a signed integer. + * n has to be in the 0-32 range. + */ +static inline int32_t BS_FUNC(bitstream_read_signed)(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(BS_FUNC(bitstream_read)(bc, n), n); +} + +static inline unsigned int BS_FUNC(show_val)(BitstreamContext *bc, unsigned int n) +{ +#ifdef BITSTREAM_LE + return bc->bits & ((UINT64_C(1) << n) - 1); +#else + return bc->bits >> (64 - n); +#endif +} + +/** + * Return n bits from the buffer but do not change the buffer state. + * n has to be in the 0-32 range. + */ +static inline unsigned int BS_FUNC(bitstream_peek)(BitstreamContext *bc, unsigned int n) +{ + if (n > bc->bits_left) + BS_FUNC(refill_32)(bc); + + return BS_FUNC(show_val)(bc, n); +} + +/** + * Return n bits from the buffer as a signed integer, + * do not change the buffer state. + * n has to be in the 0-32 range. + */ +static inline int BS_FUNC(bitstream_peek_signed)(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(BS_FUNC(bitstream_peek)(bc, n), n); +} + +static inline void BS_FUNC(skip_remaining)(BitstreamContext *bc, unsigned int n) +{ +#ifdef BITSTREAM_LE + bc->bits >>= n; +#else + bc->bits <<= n; +#endif + bc->bits_left -= n; +} + +/** + * Skip n bits in the buffer. + */ +static inline void BS_FUNC(bitstream_skip)(BitstreamContext *bc, unsigned int n) +{ + if (n < bc->bits_left) + BS_FUNC(skip_remaining)(bc, n); + else { + n -= bc->bits_left; + bc->bits = 0; + bc->bits_left = 0; + + if (n >= 64) { + unsigned int skip = n / 8; + + n -= skip * 8; + bc->ptr += skip; + } + BS_FUNC(refill_64)(bc); + if (n) + BS_FUNC(skip_remaining)(bc, n); + } +} + +/** + * Seek to the given bit position. + */ +static inline void BS_FUNC(bitstream_seek)(BitstreamContext *bc, unsigned pos) +{ + bc->ptr = bc->buffer; + bc->bits = 0; + bc->bits_left = 0; + + BS_FUNC(bitstream_skip)(bc, pos); +} + +/** + * Skip bits to a byte boundary. + */ +static inline const uint8_t *BS_FUNC(bitstream_align)(BitstreamContext *bc) +{ + unsigned int n = -bitstream_tell(bc) & 7; + if (n) + BS_FUNC(bitstream_skip)(bc, n); + return bc->buffer + (bitstream_tell(bc) >> 3); +} + +/** + * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). + * If MSB not set it is negative. + * @param n length in bits + */ +static inline int BS_FUNC(bitstream_read_xbits)(BitstreamContext *bc, unsigned int n) +{ + int32_t cache = BS_FUNC(bitstream_peek)(bc, 32); + int sign = ~cache >> 31; + BS_FUNC(skip_remaining)(bc, n); + + return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; +} + +/** + * Return decoded truncated unary code for the values 0, 1, 2. + */ +static inline int BS_FUNC(bitstream_decode012)(BitstreamContext *bc) +{ + if (!BS_FUNC(bitstream_read_bit)(bc)) + return 0; + else + return BS_FUNC(bitstream_read_bit)(bc) + 1; +} + +/** + * Return decoded truncated unary code for the values 2, 1, 0. + */ +static inline int BS_FUNC(bitstream_decode210)(BitstreamContext *bc) +{ + if (BS_FUNC(bitstream_read_bit)(bc)) + return 0; + else + return 2 - BS_FUNC(bitstream_read_bit)(bc); +} + +/* Read sign bit and flip the sign of the provided value accordingly. */ +static inline int BS_FUNC(bitstream_apply_sign)(BitstreamContext *bc, int val) +{ + int sign = BS_FUNC(bitstream_read_signed)(bc, 1); + return (val ^ sign) - sign; +} + +static inline int BS_FUNC(bitstream_skip_1stop_8data)(BitstreamContext *s) +{ + if (bitstream_bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + + while (BS_FUNC(bitstream_read)(s, 1)) { + BS_FUNC(bitstream_skip)(s, 8); + if (bitstream_bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/** + * Return the LUT element for the given bitstream configuration. + */ +static inline int BS_FUNC(set_idx)(BitstreamContext *bc, int code, int *n, int *nb_bits, + VLC_TYPE (*table)[2]) +{ + unsigned idx; + + *nb_bits = -*n; + idx = BS_FUNC(bitstream_peek)(bc, *nb_bits) + code; + *n = table[idx][1]; + + return table[idx][0]; +} + +/** + * Parse a vlc code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +static inline int BS_FUNC(bitstream_read_vlc)(BitstreamContext *bc, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = BS_FUNC(bitstream_peek)(bc, bits); + int code = table[idx][0]; + int n = table[idx][1]; + + if (max_depth > 1 && n < 0) { + BS_FUNC(skip_remaining)(bc, bits); + code = BS_FUNC(set_idx)(bc, code, &n, &nb_bits, table); + if (max_depth > 2 && n < 0) { + BS_FUNC(skip_remaining)(bc, nb_bits); + code = BS_FUNC(set_idx)(bc, code, &n, &nb_bits, table); + } + } + BS_FUNC(skip_remaining)(bc, n); + + return code; +} + +#undef BS_FUNC +#undef BS_FUNC2 +#undef BS_JOIN +#undef BS_SUFFIX diff --git a/tests/ref/fate/source b/tests/ref/fate/source index 16ea7ef9c1..3b7ea9c379 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -21,6 +21,7 @@ Headers without standard inclusion guards: compat/djgpp/math.h compat/float/float.h compat/float/limits.h +libavcodec/bitstream_template.h tools/decode_simple.h Use of av_clip() where av_clip_uintp2() could be used: Use of av_clip() where av_clip_intp2() could be used: From patchwork Fri Jun 17 13:32:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36307 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp135545pzb; Fri, 17 Jun 2022 06:32:32 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vbhb2GEL+XQCR0NNcfP/JrBVjA8U10DlYiXiW2dr/tDZCNlJAhI0kZW5emzRKZTMR44CTl X-Received: by 2002:a17:906:739a:b0:713:3ac7:976f with SMTP id f26-20020a170906739a00b007133ac7976fmr9038238ejl.22.1655472751840; Fri, 17 Jun 2022 06:32:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655472751; cv=none; d=google.com; s=arc-20160816; b=AZ4MHVY6EdSf52yN5qIvS5dRpbalq2a2zqOG11zVD+myMTj+55CwxLIbtLO6yi6ulp sv0ybeaTy8BuSAhoxvETWYm3I5Z9qX8hkS/+SqLy3qyhr9QwKvNDpCNzYrHMTfWVW5SK 5y2i3Olv16oaw1O2QKyrwvbtjCKzUeDlMH6dGI/AuhwnQMxcZd25hfCpzolbG4kk7RMk htyZ8hKuiniglARa4fMQhIH9xAGYO5a/yv/bw/y1H0ghWInBAZ9fYZVyCiyR58QBfwKw 5TvyAeAeAJQrj1IpSJq1uI4A6XP8kWgYjF9UtHS34kgXFJWNI/k7XrN7cW2h/+0kGuLC 0KPw== 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=SbxtBQ4vHdEMvbi1nYcPu6NjUSs1+L8eqRrRUGGZDHE=; b=xAPXmwtF/rdlnRp2E5e/WqO4f6P3A1MxI4FkvSnVXxFm0p1plKNw1nfYYntHABgc2+ eU8AncENl7WMfpwyWVAYcAGBjb87fv5+VzbqICUJA/5wqFHQuNSgxhjvrZitpvQ9LSzT 6YSNU58qTU93MgVffuwuP23mnl1yXZy0aUOVNATOJsEGQ4KeOrXnzw/wO4Rp/XoCa+Gy TnRk9ohoBCWkXUgD9tosxPUMDreCU6lssFhx+ICJ957qc2IV57EGlqUxYulrwLEBhqxT Ci8jfJDJqsQyCa9iYU6wxyumQHDzwCvVDcTbFYVSCy6BItQ4/LhwPttBC7ItdVz9+oAC 2Uiw== 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m15-20020a170906720f00b0070a5f5366b9si4372645ejk.389.2022.06.17.06.32.31; Fri, 17 Jun 2022 06:32:31 -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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A71A068B8E4; Fri, 17 Jun 2022 16:32:18 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1CA0068B8B8 for ; Fri, 17 Jun 2022 16:32:11 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id A1F5A240175 for ; Fri, 17 Jun 2022 15:32:10 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id Go9dPUUtE6_c for ; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id E51512400F5 for ; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id E857F3A127F; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 17 Jun 2022 15:32:05 +0200 Message-Id: <20220617133206.23643-4-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220617133206.23643-1-anton@khirnov.net> References: <20220617133206.23643-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/5] lavc/bitstream: make skip_remaining() public 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: WiXLuIM4q8EV Also rename it to bitstream_skip_cache(), which is more descriptive and follows the naming conventions of tis API. --- libavcodec/bitstream.h | 1 + libavcodec/bitstream_template.h | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index 3fa63695d3..364245453b 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -116,6 +116,7 @@ static inline void bitstream_unget(BitstreamContext *bc, uint64_t value, #define bitstream_peek bitstream_peek_be #define bitstream_peek_signed bitstream_peek_signed_be #define bitstream_skip bitstream_skip_be +#define bitstream_skip_cache bitstream_skip_cache_be #define bitstream_seek bitstream_seek_be #define bitstream_align bitstream_align_be #define bitstream_read_xbits bitstream_read_xbits_be diff --git a/libavcodec/bitstream_template.h b/libavcodec/bitstream_template.h index 14a420139c..717473ca40 100644 --- a/libavcodec/bitstream_template.h +++ b/libavcodec/bitstream_template.h @@ -225,7 +225,12 @@ static inline int BS_FUNC(bitstream_peek_signed)(BitstreamContext *bc, unsigned return sign_extend(BS_FUNC(bitstream_peek)(bc, n), n); } -static inline void BS_FUNC(skip_remaining)(BitstreamContext *bc, unsigned int n) +/** + * Skip n bits from the cache. This may only be called if at least n bits are + * guaranteed to be in the cache, e.g. right after bitstream_peek(n). + * Otherwise use bitstream_skip(). + */ +static inline void BS_FUNC(bitstream_skip_cache)(BitstreamContext *bc, unsigned int n) { #ifdef BITSTREAM_LE bc->bits >>= n; @@ -241,7 +246,7 @@ static inline void BS_FUNC(skip_remaining)(BitstreamContext *bc, unsigned int n) static inline void BS_FUNC(bitstream_skip)(BitstreamContext *bc, unsigned int n) { if (n < bc->bits_left) - BS_FUNC(skip_remaining)(bc, n); + BS_FUNC(bitstream_skip_cache)(bc, n); else { n -= bc->bits_left; bc->bits = 0; @@ -255,7 +260,7 @@ static inline void BS_FUNC(bitstream_skip)(BitstreamContext *bc, unsigned int n) } BS_FUNC(refill_64)(bc); if (n) - BS_FUNC(skip_remaining)(bc, n); + BS_FUNC(bitstream_skip_cache)(bc, n); } } @@ -291,7 +296,7 @@ static inline int BS_FUNC(bitstream_read_xbits)(BitstreamContext *bc, unsigned i { int32_t cache = BS_FUNC(bitstream_peek)(bc, 32); int sign = ~cache >> 31; - BS_FUNC(skip_remaining)(bc, n); + BS_FUNC(bitstream_skip_cache)(bc, n); return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; } @@ -374,14 +379,14 @@ static inline int BS_FUNC(bitstream_read_vlc)(BitstreamContext *bc, VLC_TYPE (*t int n = table[idx][1]; if (max_depth > 1 && n < 0) { - BS_FUNC(skip_remaining)(bc, bits); + BS_FUNC(bitstream_skip_cache)(bc, bits); code = BS_FUNC(set_idx)(bc, code, &n, &nb_bits, table); if (max_depth > 2 && n < 0) { - BS_FUNC(skip_remaining)(bc, nb_bits); + BS_FUNC(bitstream_skip_cache)(bc, nb_bits); code = BS_FUNC(set_idx)(bc, code, &n, &nb_bits, table); } } - BS_FUNC(skip_remaining)(bc, n); + BS_FUNC(bitstream_skip_cache)(bc, n); return code; } From patchwork Fri Jun 17 13:32:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36310 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp135920pzb; Fri, 17 Jun 2022 06:33:07 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tVA0K/wCgv/n4vKcSjkjep+DDK+5JJ06aZoWbzIG+PTxz7duVlcmS4mB1aTlVtalj+BPYU X-Received: by 2002:a05:6402:c08:b0:42d:d005:13c1 with SMTP id co8-20020a0564020c0800b0042dd00513c1mr12306299edb.187.1655472787184; Fri, 17 Jun 2022 06:33:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655472787; cv=none; d=google.com; s=arc-20160816; b=KabNkchaERBW0hFZYyNDKc867qI4Gp//7KapQnlIgF0cKbzhP4eYH1mMR9UWgx+vpa yYzzv6EDHsKzfPKUfqmJwgU+SkbrdCrOodGYzyaxN7l/DDKkudjAuDCQHhEZTdzVddgb nVpH2elwkmxnZOakpoblcbwCDRd2ySmSUcvOu/dMeAlNIeo1qnomASJWXMHpWjOZBmXt 6Nsbd4EDaPdvuy/QfyYIqN5UhBzWi+ekzDOWczRriWDdu2cCm6Ur/74tS2Qtv4tajno2 ZNEsdMSvH93nIuIJURmLqfpEEMsurXUFH8/f20zfSfk264sGNK/kNj5x80ETnauaeIsN lRFg== 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=dL3pbnQc4az0jOwa0tnfLQLGLL+73Hx5YsgeP2Te7NY=; b=wsRzAdOJjpQP9mkjt9fGQ5SYqiNMsoNb8xuEuMGgTShas6vezGzKtKEy8LOBuQlpsL IKkPdJrJhPfeBLMUU4uUvTa+v+qOpIGpnB5wog1ZAoS5ldVIoJ8I8qiSUneI5ENhPkub IseAnVqlEFuiO/YOVnVJ1I69m6TSzi/9KNVZDSHmbBO6IaPiLUwXF//5beelw9b2okyq vF14O2Ut90QTNJ8vHWidT5Jvwlbdlih7bgjDyZYPqHFvgGexA8R+HCOzfluXLllxmx1t JQVZ7rwuHY5ZPp0142yoj7cGvkqyKI+S9Lm6V+DYKaQS2rONXiNYblVUvU6FsNieVbTU MnaQ== 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id g8-20020a1709065d0800b006e88d2e4fe2si450323ejt.967.2022.06.17.06.33.06; Fri, 17 Jun 2022 06:33:07 -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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7568668B8FB; Fri, 17 Jun 2022 16:32:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9EFE168B8E3 for ; Fri, 17 Jun 2022 16:32:13 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 3D27124017E for ; Fri, 17 Jun 2022 15:32:13 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id ehLmehTdWnHo for ; Fri, 17 Jun 2022 15:32:10 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 013682404FE for ; Fri, 17 Jun 2022 15:32:09 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id EDAC93A12AD; Fri, 17 Jun 2022 15:32:08 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Fri, 17 Jun 2022 15:32:06 +0200 Message-Id: <20220617133206.23643-5-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220617133206.23643-1-anton@khirnov.net> References: <20220617133206.23643-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/5] lavc/get_bits: add a compat wrapper for the cached bitstream 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: gepqUEhyGRLw Use that instead of the merged version. --- libavcodec/get_bits.h | 296 +++++++----------------------------------- 1 file changed, 50 insertions(+), 246 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 498ce4ed35..06192a25a7 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -59,12 +59,43 @@ #define CACHED_BITSTREAM_READER 0 #endif +#if CACHED_BITSTREAM_READER +#include "bitstream.h" + +#define MIN_CACHE_BITS 64 + +typedef BitstreamContext GetBitContext; + +#define get_bits_count bitstream_tell +#define get_bits_left bitstream_bits_left +#define skip_bits_long bitstream_skip +#define skip_bits bitstream_skip +#define get_bits bitstream_read +#define get_bitsz bitstream_read +#define get_bits_le bitstream_read +#define get_bits_long bitstream_read +#define get_bits64 bitstream_read_63 +#define get_xbits bitstream_read_xbits +#define get_sbits bitstream_read_signed +#define get_sbits_long bitstream_read_signed +#define show_bits bitstream_peek +#define show_bits_long bitstream_peek +#define init_get_bits bitstream_init +#define init_get_bits8 bitstream_init8 +#define init_get_bits8_le bitstream_init8_le +#define align_get_bits bitstream_align +#define get_vlc2 bitstream_read_vlc + +#define get_bits1(s) bitstream_read(s, 1) +#define show_bits1(s) bitstream_peek(s, 1) +#define skip_bits1(s) bitstream_skip(s, 1) + +#define skip_1stop_8data_bits bitstream_skip_1stop_8data + +#else // CACHED_BITSTREAM_READER + typedef struct GetBitContext { const uint8_t *buffer, *buffer_end; -#if CACHED_BITSTREAM_READER - uint64_t cache; - unsigned bits_left; -#endif int index; int size_in_bits; int size_in_bits_plus8; @@ -121,16 +152,12 @@ static inline unsigned int show_bits(GetBitContext *s, int n); * For examples see get_bits, show_bits, skip_bits, get_vlc. */ -#if CACHED_BITSTREAM_READER -# define MIN_CACHE_BITS 64 -#elif defined LONG_BITSTREAM_READER +#if defined LONG_BITSTREAM_READER # define MIN_CACHE_BITS 32 #else # define MIN_CACHE_BITS 25 #endif -#if !CACHED_BITSTREAM_READER - #define OPEN_READER_NOSIZE(name, gb) \ unsigned int name ## _index = (gb)->index; \ unsigned int av_unused name ## _cache @@ -215,73 +242,12 @@ static inline unsigned int show_bits(GetBitContext *s, int n); #define GET_CACHE(name, gb) ((uint32_t) name ## _cache) -#endif static inline int get_bits_count(const GetBitContext *s) { -#if CACHED_BITSTREAM_READER - return s->index - s->bits_left; -#else return s->index; -#endif } -#if CACHED_BITSTREAM_READER -static inline void refill_32(GetBitContext *s, int is_le) -{ -#if !UNCHECKED_BITSTREAM_READER - if (s->index >> 3 >= s->buffer_end - s->buffer) - return; -#endif - - if (is_le) - s->cache = (uint64_t)AV_RL32(s->buffer + (s->index >> 3)) << s->bits_left | s->cache; - else - s->cache = s->cache | (uint64_t)AV_RB32(s->buffer + (s->index >> 3)) << (32 - s->bits_left); - s->index += 32; - s->bits_left += 32; -} - -static inline void refill_64(GetBitContext *s, int is_le) -{ -#if !UNCHECKED_BITSTREAM_READER - if (s->index >> 3 >= s->buffer_end - s->buffer) - return; -#endif - - if (is_le) - s->cache = AV_RL64(s->buffer + (s->index >> 3)); - else - s->cache = AV_RB64(s->buffer + (s->index >> 3)); - s->index += 64; - s->bits_left = 64; -} - -static inline uint64_t get_val(GetBitContext *s, unsigned n, int is_le) -{ - uint64_t ret; - av_assert2(n>0 && n<=63); - if (is_le) { - ret = s->cache & ((UINT64_C(1) << n) - 1); - s->cache >>= n; - } else { - ret = s->cache >> (64 - n); - s->cache <<= n; - } - s->bits_left -= n; - return ret; -} - -static inline unsigned show_val(const GetBitContext *s, unsigned n) -{ -#ifdef BITSTREAM_READER_LE - return s->cache & ((UINT64_C(1) << n) - 1); -#else - return s->cache >> (64 - n); -#endif -} -#endif - /** * Skips the specified number of bits. * @param n the number of bits to skip, @@ -291,28 +257,12 @@ static inline unsigned show_val(const GetBitContext *s, unsigned n) */ static inline void skip_bits_long(GetBitContext *s, int n) { -#if CACHED_BITSTREAM_READER - skip_bits(s, n); -#else #if UNCHECKED_BITSTREAM_READER s->index += n; #else s->index += av_clip(n, -s->index, s->size_in_bits_plus8 - s->index); #endif -#endif -} - -#if CACHED_BITSTREAM_READER -static inline void skip_remaining(GetBitContext *s, unsigned n) -{ -#ifdef BITSTREAM_READER_LE - s->cache >>= n; -#else - s->cache <<= n; -#endif - s->bits_left -= n; } -#endif /** * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB). @@ -321,13 +271,6 @@ static inline void skip_remaining(GetBitContext *s, unsigned n) */ static inline int get_xbits(GetBitContext *s, int n) { -#if CACHED_BITSTREAM_READER - int32_t cache = show_bits(s, 32); - int sign = ~cache >> 31; - skip_remaining(s, n); - - return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; -#else register int sign; register int32_t cache; OPEN_READER(re, s); @@ -338,10 +281,8 @@ static inline int get_xbits(GetBitContext *s, int n) LAST_SKIP_BITS(re, s, n); CLOSE_READER(re, s); return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; -#endif } -#if !CACHED_BITSTREAM_READER static inline int get_xbits_le(GetBitContext *s, int n) { register int sign; @@ -355,22 +296,16 @@ static inline int get_xbits_le(GetBitContext *s, int n) CLOSE_READER(re, s); return (zero_extend(sign ^ cache, n) ^ sign) - sign; } -#endif static inline int get_sbits(GetBitContext *s, int n) { register int tmp; -#if CACHED_BITSTREAM_READER - av_assert2(n>0 && n<=25); - tmp = sign_extend(get_bits(s, n), n); -#else OPEN_READER(re, s); av_assert2(n>0 && n<=25); UPDATE_CACHE(re, s); tmp = SHOW_SBITS(re, s, n); LAST_SKIP_BITS(re, s, n); CLOSE_READER(re, s); -#endif return tmp; } @@ -380,32 +315,12 @@ static inline int get_sbits(GetBitContext *s, int n) static inline unsigned int get_bits(GetBitContext *s, int n) { register unsigned int tmp; -#if CACHED_BITSTREAM_READER - - av_assert2(n>0 && n<=32); - if (n > s->bits_left) { -#ifdef BITSTREAM_READER_LE - refill_32(s, 1); -#else - refill_32(s, 0); -#endif - if (s->bits_left < 32) - s->bits_left = n; - } - -#ifdef BITSTREAM_READER_LE - tmp = get_val(s, n, 1); -#else - tmp = get_val(s, n, 0); -#endif -#else OPEN_READER(re, s); av_assert2(n>0 && n<=25); UPDATE_CACHE(re, s); tmp = SHOW_UBITS(re, s, n); LAST_SKIP_BITS(re, s, n); CLOSE_READER(re, s); -#endif av_assert2(tmp < UINT64_C(1) << n); return tmp; } @@ -420,16 +335,6 @@ static av_always_inline int get_bitsz(GetBitContext *s, int n) static inline unsigned int get_bits_le(GetBitContext *s, int n) { -#if CACHED_BITSTREAM_READER - av_assert2(n>0 && n<=32); - if (n > s->bits_left) { - refill_32(s, 1); - if (s->bits_left < 32) - s->bits_left = n; - } - - return get_val(s, n, 1); -#else register int tmp; OPEN_READER(re, s); av_assert2(n>0 && n<=25); @@ -438,7 +343,6 @@ static inline unsigned int get_bits_le(GetBitContext *s, int n) LAST_SKIP_BITS(re, s, n); CLOSE_READER(re, s); return tmp; -#endif } /** @@ -447,71 +351,22 @@ static inline unsigned int get_bits_le(GetBitContext *s, int n) static inline unsigned int show_bits(GetBitContext *s, int n) { register unsigned int tmp; -#if CACHED_BITSTREAM_READER - if (n > s->bits_left) -#ifdef BITSTREAM_READER_LE - refill_32(s, 1); -#else - refill_32(s, 0); -#endif - - tmp = show_val(s, n); -#else OPEN_READER_NOSIZE(re, s); av_assert2(n>0 && n<=25); UPDATE_CACHE(re, s); tmp = SHOW_UBITS(re, s, n); -#endif return tmp; } static inline void skip_bits(GetBitContext *s, int n) { -#if CACHED_BITSTREAM_READER - if (n < s->bits_left) - skip_remaining(s, n); - else { - n -= s->bits_left; - s->cache = 0; - s->bits_left = 0; - - if (n >= 64) { - unsigned skip = (n / 8) * 8; - - n -= skip; - s->index += skip; - } -#ifdef BITSTREAM_READER_LE - refill_64(s, 1); -#else - refill_64(s, 0); -#endif - if (n) - skip_remaining(s, n); - } -#else OPEN_READER(re, s); LAST_SKIP_BITS(re, s, n); CLOSE_READER(re, s); -#endif } static inline unsigned int get_bits1(GetBitContext *s) { -#if CACHED_BITSTREAM_READER - if (!s->bits_left) -#ifdef BITSTREAM_READER_LE - refill_64(s, 1); -#else - refill_64(s, 0); -#endif - -#ifdef BITSTREAM_READER_LE - return get_val(s, 1, 1); -#else - return get_val(s, 1, 0); -#endif -#else unsigned int index = s->index; uint8_t result = s->buffer[index >> 3]; #ifdef BITSTREAM_READER_LE @@ -528,7 +383,6 @@ static inline unsigned int get_bits1(GetBitContext *s) s->index = index; return result; -#endif } static inline unsigned int show_bits1(GetBitContext *s) @@ -549,10 +403,6 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n) av_assert2(n>=0 && n<=32); if (!n) { return 0; -#if CACHED_BITSTREAM_READER - } - return get_bits(s, n); -#else } else if (n <= MIN_CACHE_BITS) { return get_bits(s, n); } else { @@ -564,7 +414,6 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n) return ret | get_bits(s, n - 16); #endif } -#endif } /** @@ -610,8 +459,17 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n) } } -static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer, - int bit_size, int is_le) + +/** + * Initialize GetBitContext. + * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, + int bit_size) { int buffer_size; int ret = 0; @@ -630,33 +488,9 @@ static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer, s->buffer_end = buffer + buffer_size; s->index = 0; -#if CACHED_BITSTREAM_READER - s->cache = 0; - s->bits_left = 0; - refill_64(s, is_le); -#endif - return ret; } -/** - * Initialize GetBitContext. - * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes - * larger than the actual read bits because some optimized bitstream - * readers read 32 or 64 bit at once and could read over the end - * @param bit_size the size of the buffer in bits - * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. - */ -static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, - int bit_size) -{ -#ifdef BITSTREAM_READER_LE - return init_get_bits_xe(s, buffer, bit_size, 1); -#else - return init_get_bits_xe(s, buffer, bit_size, 0); -#endif -} - /** * Initialize GetBitContext. * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes @@ -678,7 +512,7 @@ static inline int init_get_bits8_le(GetBitContext *s, const uint8_t *buffer, { if (byte_size > INT_MAX / 8 || byte_size < 0) byte_size = -1; - return init_get_bits_xe(s, buffer, byte_size * 8, 1); + return init_get_bits(s, buffer, byte_size * 8); } static inline const uint8_t *align_get_bits(GetBitContext *s) @@ -763,19 +597,6 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) SKIP_BITS(name, gb, n); \ } while (0) -/* Return the LUT element for the given bitstream configuration. */ -static inline int set_idx(GetBitContext *s, int code, int *n, int *nb_bits, - VLC_TYPE (*table)[2]) -{ - unsigned idx; - - *nb_bits = -*n; - idx = show_bits(s, *nb_bits) + code; - *n = table[idx][1]; - - return table[idx][0]; -} - /** * Parse a vlc code. * @param bits is the number of bits which will be read at once, must be @@ -788,24 +609,6 @@ static inline int set_idx(GetBitContext *s, int code, int *n, int *nb_bits, static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth) { -#if CACHED_BITSTREAM_READER - int nb_bits; - unsigned idx = show_bits(s, bits); - int code = table[idx][0]; - int n = table[idx][1]; - - if (max_depth > 1 && n < 0) { - skip_remaining(s, bits); - code = set_idx(s, code, &n, &nb_bits, table); - if (max_depth > 2 && n < 0) { - skip_remaining(s, nb_bits); - code = set_idx(s, code, &n, &nb_bits, table); - } - } - skip_remaining(s, n); - - return code; -#else int code; OPEN_READER(re, s); @@ -816,7 +619,6 @@ static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], CLOSE_READER(re, s); return code; -#endif } static inline int decode012(GetBitContext *gb) @@ -856,4 +658,6 @@ static inline int skip_1stop_8data_bits(GetBitContext *gb) return 0; } +#endif // CACHED_BITSTREAM_READER + #endif /* AVCODEC_GET_BITS_H */