From patchwork Thu Jun 23 12:26:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36397 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp3439376pzb; Thu, 23 Jun 2022 05:26:50 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uyvXB9yNoEDfUikZWCig2Y6/9DoHP3ucENXC/uc4uruyHYShjHmD7MWKT+8b9DRejKUpg+ X-Received: by 2002:a17:907:1ca8:b0:706:9ee2:dbc with SMTP id nb40-20020a1709071ca800b007069ee20dbcmr8056034ejc.398.1655987209921; Thu, 23 Jun 2022 05:26:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655987209; cv=none; d=google.com; s=arc-20160816; b=ByuzgwKfxh88lDzc8LL0I0KtsZU9/1x4Hwi29nKWmXNPzvVJX2AxM18kOLxSI3N4bN 3vyazCoCUIGMb2/lDBIXeL+s3fu1eEND90MCC4SK/hrYfZWFIXtiGXxMqZJPL+eUtNRu t7XDl9Kjb1244TwWX/1FcB0w8MEUder181cb6+BEYOoFuH8UQkpnGfNo6QkbKgH+mfn/ NGN+ACSpJbPtDPFTI6wbnCiRHh6s9+kNh3mCecCs3K3taWLHMpfSuivSNSGt+smE9JmT pXXdZcWrI2XqWYMc8UNsnzycY+L9JK4IOKvFvV9Fuuv0tpKGXli/Yt4ocuBadgKHx1Ez +ofA== 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=WHjcz/UMdcOhGlCDVKTFfiS3RETg8ory/Gf/UMgA8Dk=; b=hFEJPGb+pz8EdOwzy1ONPI4jHlOu5NOejaEdrFHfOVv64NxmGqkFp7odHwCLpPnVvB A5ddxhZuVmv2/itFiFYaCFRSq0G05EYUJMFh8qAOQlEZxXXQV0hPZBHBFWY4/+0hx3CH HkTkHrwK4UE55N3GmQumJVz28bcDduxJDFlofYOyIJUR/F5gfDP0cPy8lI/+i0BaBIRN 6Vi1pEmF4XM5gE+Fr4Ik4oOWR0NDEFZXIg6zVDBTgjaTEVRUZeXVjMiEa4aJOhkmBL3q iCQRI/wLTzOlcyd2dJWvmLT9lBOHbR8y10genpe/oQFl4FpTtxCwb8n6HKVeMCIFKCe+ 9vvw== 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 hg5-20020a1709072cc500b006fe8ee84794si4059829ejc.370.2022.06.23.05.26.49; Thu, 23 Jun 2022 05:26:49 -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 A4BD168B6B6; Thu, 23 Jun 2022 15:26:46 +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 A0CB068B0FB for ; Thu, 23 Jun 2022 15:26:40 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 4C0562404FE for ; Thu, 23 Jun 2022 14:26:40 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id dKQgBV-CZ5ms for ; Thu, 23 Jun 2022 14:26:39 +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 AC5AC2400F5 for ; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id 9DD853A068E; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 Jun 2022 14:26:33 +0200 Message-Id: <20220623122636.24732-1-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/4] 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: BAhQ/Stjbd6F It is only used by mpegvideo-based decoders - specifically mpeg12, intelh263, ituh263, mpeg4video. --- Resending the set rebased against current master (there conflicts with 2d764069be3b4092dc986467660607d922023332) and with patch 04 skipped, as Andreas pointed out issues with it. It is not needed by the other patches, so can be left out for now. Apparently Paul has withrawn his objections and Lynne approved the previous iteration on IRC, so will push this in a few days if nobody objects. --- 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 16f8af5107..9f2b1784d5 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 Thu Jun 23 12:26:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36398 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp3439460pzb; Thu, 23 Jun 2022 05:26:59 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uBGyg0D2WXVnBBFYkPt8LLDDnkrMJpTOAKKspdqcWdn/sfo2elYuD3q6h4ksufOYh/cKmx X-Received: by 2002:a05:6402:34d2:b0:435:9d8f:3328 with SMTP id w18-20020a05640234d200b004359d8f3328mr10447084edc.88.1655987219419; Thu, 23 Jun 2022 05:26:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655987219; cv=none; d=google.com; s=arc-20160816; b=SXOK9+0NE2nI9BpOlYDFOIQnTQ5+HJPpGrl4wRoGvU8KMAkm1TNspYjA1Z4O8kstHk Q9sxfYqFy3ZFAoc3SRNgT7W4IplOgJl/3d5PuGkTjew9VG4IWBZ4y5J0bueRL4v0PvXj kSimGyO+sHcUrXS6lScFfZrQ4vGkBYhQiaunf+QzMYZEopY9PGNJusIrgXvQqQ/47/9V ObmR7JnxaNN/VsEPJ3G0OoNj8V+CICAESr8vM5oJk2s+s8WKUD0ped3J4wq+PYV9RgdQ UgLxyGsjTMk2VFuFV6sqEAjUjS5We61tGTE4RGK+t7L1uKijoYJQRnsW+ogj/LD12vFn Gr1g== 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=jIumn1H9ZKrHnTfLYSY3KVS1hKtoLnzYogSBUfJgrww=; b=sX3jXaleO+0J1q2PP1NNkw+0lWZRqXI3pWRXT9hPcXL3UtF57p23Y/WBOg5DbygnKU tGqQCzR2XtNCdCc6p/AmyD7qQASd7OMwytlLtw+553HxGkp62ooG4ZQBbqLc9yixldR5 CxnngBwSoHleytlzaJvC5S9PpsbHnzd4OolXBG3PvW/v20QEuMGgiPdhyxCJwUNCciB4 z3U44sU4tlpDw7G0NadLVtFBaUuCy3CfKSD/Q8nKgjaZeCJokpMs78D0JOmL1f+fwa+T EDucm2V/SOg5R3RS7+BXn5BJ5kof4lTrOP2GeyhmqX6H4ifTDy0WKws+StW66Vdmw/bp eHXw== 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 ho30-20020a1709070e9e00b00718bebeb259si24954430ejc.696.2022.06.23.05.26.58; Thu, 23 Jun 2022 05:26:59 -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 A312068B6E2; Thu, 23 Jun 2022 15:26:47 +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 2AFE368B0FB for ; Thu, 23 Jun 2022 15:26:41 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id D081D2400F5 for ; Thu, 23 Jun 2022 14:26:40 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id yYDdxyAIrDOY for ; Thu, 23 Jun 2022 14:26:39 +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 C0FD5240179 for ; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id 9FB433A0396; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 Jun 2022 14:26:34 +0200 Message-Id: <20220623122636.24732-2-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220623122636.24732-1-anton@khirnov.net> References: <20220623122636.24732-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/4] 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: I9DrOtBm4YA5 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..8a710bcecc --- /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, + const VLCElem *table) +{ + unsigned idx; + + *nb_bits = -*n; + idx = bitstream_peek(bc, *nb_bits) + code; + *n = table[idx].len; + + return table[idx].sym; +} + +/** + * 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, const VLCElem *table, + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = bitstream_peek(bc, bits); + int code = table[idx].sym; + int n = table[idx].len; + + 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 Thu Jun 23 12:26:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36400 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp3439613pzb; Thu, 23 Jun 2022 05:27:19 -0700 (PDT) X-Google-Smtp-Source: AGRyM1te3M0xUjZrOTms3/xCefAnj5SNtVu5yuJoiiSzQs+dw3SHM8aOFWEnHISkcKf00H0cxEXS X-Received: by 2002:a05:6402:e0c:b0:435:25cd:6088 with SMTP id h12-20020a0564020e0c00b0043525cd6088mr10585981edh.60.1655987239058; Thu, 23 Jun 2022 05:27:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655987239; cv=none; d=google.com; s=arc-20160816; b=Y06NcUvdXI4Wq/obOB4QDh1yZutSbsHdKdjWUx1jPFoUOsypYkg7DVHniCWb33eBi9 uOSRSFw3LN5HzAO6kCYXAnixW/25r1c9gkgw9xSbEmp/bE4nM+nS3dMBxkhn1GCy5tb2 OKWc+pyAUeT8FB7rw7+Q6Fb7qpTTX72NUW0TSOUDrt6xmYkX8cdXswOEWG5GZCRJXxZY WrXsYVSkMb9+LHGylV5UNFHXSMCj+XYepY5OAGPnGf6ruphFozgj//S9ysoUvMt87F1y UtWMpntue2EiAjbY1cm3P+9fGGUHhKihYdMnsqnFkKAb3w2DuRctJL9Gf+ADpsIW78Cc uC0Q== 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=cBvuF262nYsu2YPGDuhJfDl3NUuYZY/Q5XjVr8nBaLI=; b=t9BiRE3/bMBTwmXNLI54QlOfWxFP6ePjPgLeaMaajFJWr5L9jNQQeHR/tBGp7zPNTa ST7frhe5tcfbyqacK1lSpqr4A0egirLVpvjuAm/HT8gm2VB5VoO4N+M54GeWD7gBAEsH KcpTaOrKi/SBkPfyyCslTYwOliYlWOrXiEWkXgpP9GjiYLCADRDO8PsHAwCLLtRZuhM6 8FCzjsJiw771C9P31HyNhEmN071nAYQZUbNov7s2/Tu51Jwa7zKQ1TzXA5nJxVyj81Xp MEkG20Wpr4C2wJYKVeYFbPlcYqy9ZGfH1In/spJcS/VXEBKbVC5eOTsuv1tN4bTJIFhJ 4HeA== 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 hr32-20020a1709073fa000b00725be17a629si2170616ejc.852.2022.06.23.05.27.18; Thu, 23 Jun 2022 05:27: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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C0DD768B701; Thu, 23 Jun 2022 15:26:50 +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 9AAF168B6DD for ; Thu, 23 Jun 2022 15:26:42 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 440BE24017E for ; Thu, 23 Jun 2022 14:26:42 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id 8kdGKq_3-Rjk for ; Thu, 23 Jun 2022 14:26:40 +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 C7C0B24017C for ; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id A70FE3A073B; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 Jun 2022 14:26:35 +0200 Message-Id: <20220623122636.24732-3-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220623122636.24732-1-anton@khirnov.net> References: <20220623122636.24732-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/4] 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: 7k4crdV7hP0X 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 8a710bcecc..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, - const VLCElem *table) -{ - unsigned idx; - - *nb_bits = -*n; - idx = bitstream_peek(bc, *nb_bits) + code; - *n = table[idx].len; - - return table[idx].sym; -} - -/** - * 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, const VLCElem *table, - int bits, int max_depth) -{ - int nb_bits; - unsigned idx = bitstream_peek(bc, bits); - int code = table[idx].sym; - int n = table[idx].len; - - 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..6b31bc53a2 --- /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, + const VLCElem *table) +{ + unsigned idx; + + *nb_bits = -*n; + idx = BS_FUNC(bitstream_peek)(bc, *nb_bits) + code; + *n = table[idx].len; + + return table[idx].sym; +} + +/** + * 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, const VLCElem *table, + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = BS_FUNC(bitstream_peek)(bc, bits); + int code = table[idx].sym; + int n = table[idx].len; + + 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 Thu Jun 23 12:26:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 36399 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:1a22:b0:84:42e0:ad30 with SMTP id cj34csp3439531pzb; Thu, 23 Jun 2022 05:27:09 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uwu0Xvjpx3jWa+UCAn0TX0tW4AUzyFTgDkRnTG1fRPb8IefiPM+idFVNgTLANIqXgmCBcK X-Received: by 2002:aa7:c352:0:b0:435:7fbd:90b9 with SMTP id j18-20020aa7c352000000b004357fbd90b9mr10484702edr.139.1655987228926; Thu, 23 Jun 2022 05:27:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655987228; cv=none; d=google.com; s=arc-20160816; b=B5On3bRoRBwVdEwCeCZxk+wjBAvLjVGRSbGJG6/x5GRGDFE0LsFZi3VWJYRbRZ7M9N b1472Zob/EqoCCO8tYwnIBfxccJ+B6/6CcsASkT+zwJpyQx6eiXi9O6FAS0x4YvaGzf+ VTNMGS1KaPzdq9UFgcOUtIO4AU5WcD0ZN11QRAlyWqX9iqS4nqoPnTeB+WUvuOQ643js 2DMt5F4KJria8hbT7q7nOFfabQdWG6fFMZDvVmnhXuszWZP4gnabv8HtMtZRWgmLqF4l qkk6gYU7fYy1iGp3B2P8kbxJrbzHqx/4P9oJAWAT3jYcXzJbzXH8Y0T/vWlNXhxR8y+b /WvQ== 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=EdrfGjH0eLOlZ87ZOV36J1iRSMv9MczPr6hL2136TIs=; b=UURwkBL2hGruCJ3+Y6irt3gDdyTcJDiXuXbvkZzvdml6Bpu1dUcDR0uWHCvUjyfPzf oTurk4ttS9LUnh9lm8EQwFqU7NxIclpO8I0nbsitcHUkBjxpXC8K5FcTM6qeUv3yLChp ZfIU5vyKln9VdTT6Mrgr2PXc6gInwYa4ZANCm2ndUWzwPWn42cWCoJKH2Tz3yobwY4OF EK9utlW8hRF/+KrRIJ2Ylrv9WQVucPY9qtVFRpsAhBZOs2jB3yY4Q+LcjuJMPusb9mLJ 2xCFrTS18ob2NucewapTc21pBEzTjCdiK/GV14/vjCsKiJ9MAhc7j/sHDFX6irxYIRHe I2/A== 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 20-20020a170906015400b00722e51a9027si373455ejh.621.2022.06.23.05.27.08; Thu, 23 Jun 2022 05:27:08 -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 B394068B67B; Thu, 23 Jun 2022 15:26:48 +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 A2C1368B6AC for ; Thu, 23 Jun 2022 15:26:41 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 4F1CE240179 for ; Thu, 23 Jun 2022 14:26:41 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id bsEy3cAggU4W for ; Thu, 23 Jun 2022 14:26:40 +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 C857424017E for ; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) Received: by libav.khirnov.net (Postfix, from userid 1000) id AC1F73A074C; Thu, 23 Jun 2022 14:26:39 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 Jun 2022 14:26:36 +0200 Message-Id: <20220623122636.24732-4-anton@khirnov.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220623122636.24732-1-anton@khirnov.net> References: <20220623122636.24732-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/4] 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: iWdwDstnGa1c Use that instead of the merged version. --- libavcodec/get_bits.h | 297 +++++++----------------------------------- 1 file changed, 50 insertions(+), 247 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 9f2b1784d5..d9fc794c8c 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2004 Michael Niedermayer - * Copyright (c) 2016 Alexandra Hájková * * This file is part of FFmpeg. * @@ -59,12 +58,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 +151,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 +241,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 +256,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 +270,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 +280,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 +295,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 +314,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 +334,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 +342,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 +350,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 +382,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 +402,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 +413,6 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n) return ret | get_bits(s, n - 16); #endif } -#endif } /** @@ -610,8 +458,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 +487,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 +511,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 +596,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, - const VLCElem *table) -{ - unsigned idx; - - *nb_bits = -*n; - idx = show_bits(s, *nb_bits) + code; - *n = table[idx].len; - - return table[idx].sym; -} - /** * Parse a vlc code. * @param bits is the number of bits which will be read at once, must be @@ -788,24 +608,6 @@ static inline int set_idx(GetBitContext *s, int code, int *n, int *nb_bits, static av_always_inline int get_vlc2(GetBitContext *s, const VLCElem *table, int bits, int max_depth) { -#if CACHED_BITSTREAM_READER - int nb_bits; - unsigned idx = show_bits(s, bits); - int code = table[idx].sym; - int n = table[idx].len; - - 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 +618,6 @@ static av_always_inline int get_vlc2(GetBitContext *s, const VLCElem *table, CLOSE_READER(re, s); return code; -#endif } static inline int decode012(GetBitContext *gb) @@ -856,4 +657,6 @@ static inline int skip_1stop_8data_bits(GetBitContext *gb) return 0; } +#endif // CACHED_BITSTREAM_READER + #endif /* AVCODEC_GET_BITS_H */