From patchwork Sat Oct 22 10:32:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38903 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp1223019pzb; Sat, 22 Oct 2022 03:34:47 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4tKwGNfFtZlAmDKuiZeZAb+sy+BmuF+PrXSE2bPIGhydr7MI0m8VQ4DDqM9tdP7yyUBJzp X-Received: by 2002:a17:907:2d1f:b0:78e:174d:2ce0 with SMTP id gs31-20020a1709072d1f00b0078e174d2ce0mr19562540ejc.638.1666434886771; Sat, 22 Oct 2022 03:34:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666434886; cv=none; d=google.com; s=arc-20160816; b=rS1IhOc0LuBLo5gn204d/S8brCORcnkYe5bs2kxtfw8Ndzir62x6b2NPOTSLRFajwT 5ab991xLbAvR0lEltwCQxONKZNfQVU7K/prRyD82Tm7mSnjRnhjlSRM+MHGHR/armvcd 7JO6IET2OUBu7TzyI9TFl47ifppwwyVa6CUoVOl986HnfcccKo6/dVf8lZTWVf21nC8Y PIfIXd8ywfS8UOVzuNo0SEmQhujpGdmdblQU1SOiaxBeqmGMq4v6T3hCUuGWTeJvUMJ6 AcFuJz6s5kYeRVmKv9/ye2olJjOwUP5M2BSiuuY0dMl41rI2mRcKGWkV6cALOuuVLEps tUkQ== 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=IzmGjqh8kuf0gEWVVwVSXs6gps2OuzpgQhIdCa4BSFU=; b=jM0kBjiIv+d4BHxINNpIpTcOmEGr01o0ICf+ACLzeky76VF+mzdumwwpxxSiiiBVV6 +fa4DxvcatO02jkRxE0LMjUzQ4OkeblhxEvhilhcbKUOpKoxg1TuvwHpMz9DZivaE9uc shSpTWqPbJx3OdPiD4g2JgvLRhpYFs4hmpQo8PiuBGvgp8IE6vfw0OCKcrp6xEdCeE1d uCXvamyXSg/9U30hWw/WHaL1+ioDK0B35kKYl88BbjYc3tmuKCt6C4yO8sCO9KRtg0IX EYkV+LblFryH+orYX9bbdWl7OseZLO9Z4tgfXlj86SEk+mjFE5Qm+XCGvDERs/Li+Ccr hNLA== 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 qb4-20020a1709077e8400b0078b85fdf4e4si23419023ejc.532.2022.10.22.03.34.46; Sat, 22 Oct 2022 03:34:46 -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 3BE2D68BCA8; Sat, 22 Oct 2022 13:34:25 +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 D93D968BCA8 for ; Sat, 22 Oct 2022 13:34:16 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 7EEF12404F7 for ; Sat, 22 Oct 2022 12:34:16 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id fjEg_3V3SuA0 for ; Sat, 22 Oct 2022 12:34:14 +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 37A6C2404E4 for ; Sat, 22 Oct 2022 12:34:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 1BA1D3A0212 for ; Sat, 22 Oct 2022 12:34:04 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 22 Oct 2022 12:32:54 +0200 Message-Id: <20221022103257.15463-1-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 1/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: x5a7CIhpmJVB 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 | 529 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 libavcodec/bitstream.h diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h new file mode 100644 index 0000000000..6fd321dba5 --- /dev/null +++ b/libavcodec/bitstream.h @@ -0,0 +1,529 @@ +/* + * 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/avassert.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_valid; // number of bits left in bits field + unsigned size_in_bits; +} BitstreamContext; + +/** + * @return + * - 0 on successful refill + * - a negative number when bitstream end is hit + * + * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. + */ +static inline int bits_priv_refill_64(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return -1; +#endif + +#ifdef BITSTREAM_READER_LE + bc->bits = AV_RL64(bc->ptr); +#else + bc->bits = AV_RB64(bc->ptr); +#endif + bc->ptr += 8; + bc->bits_valid = 64; + + return 0; +} + +/** + * @return + * - 0 on successful refill + * - a negative number when bitstream end is hit + * + * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. + */ +static inline int bits_priv_refill_32(BitstreamContext *bc) +{ +#if !UNCHECKED_BITSTREAM_READER + if (bc->ptr >= bc->buffer_end) + return -1; +#endif + +#ifdef BITSTREAM_READER_LE + bc->bits |= (uint64_t)AV_RL32(bc->ptr) << bc->bits_valid; +#else + bc->bits |= (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_valid); +#endif + bc->ptr += 4; + bc->bits_valid += 32; + + 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 bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int bits_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_valid = 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_valid = 0; + bc->bits = 0; + + bits_priv_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 bits_init8(BitstreamContext *bc, const uint8_t *buffer, + unsigned int byte_size) +{ + if (byte_size > INT_MAX / 8) + return AVERROR_INVALIDDATA; + return bits_init(bc, buffer, byte_size * 8); +} + +/** + * Return number of bits already read. + */ +static inline int bits_tell(const BitstreamContext *bc) +{ + return (bc->ptr - bc->buffer) * 8 - bc->bits_valid; +} + +/** + * Return buffer size in bits. + */ +static inline int bits_size(const BitstreamContext *bc) +{ + return bc->size_in_bits; +} + +/** + * Return the number of the bits left in a buffer. + */ +static inline int bits_left(const BitstreamContext *bc) +{ + return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_valid; +} + +static inline uint64_t bits_priv_val_show(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n > 0 && n <= 64); + +#ifdef BITSTREAM_READER_LE + return bc->bits & (UINT64_MAX >> (64 - n)); +#else + return bc->bits >> (64 - n); +#endif +} + +static inline void bits_priv_skip_remaining(BitstreamContext *bc, unsigned int n) +{ +#ifdef BITSTREAM_READER_LE + bc->bits >>= n; +#else + bc->bits <<= n; +#endif + bc->bits_valid -= n; +} + +static inline uint64_t bits_priv_val_get(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret; + + av_assert2(n > 0 && n < 64); + + ret = bits_priv_val_show(bc, n); + bits_priv_skip_remaining(bc, n); + + return ret; +} + +/** + * Return one bit from the buffer. + */ +static inline unsigned int bits_read_bit(BitstreamContext *bc) +{ + if (!bc->bits_valid && bits_priv_refill_64(bc) < 0) + return 0; + + return bits_priv_val_get(bc, 1); +} + +/** + * Return n bits from the buffer, n has to be in the 1-32 range. + * May be faster than bits_read() when n is not a compile-time constant and is + * known to be non-zero; + */ +static inline uint32_t bits_read_nz(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n > 0 && n <= 32); + + if (n > bc->bits_valid) { + if (bits_priv_refill_32(bc) < 0) + bc->bits_valid = n; + } + + return bits_priv_val_get(bc, n); +} + +/** + * Return n bits from the buffer, n has to be in the 0-32 range. + */ +static inline uint32_t bits_read(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n <= 32); + + if (!n) + return 0; + + return bits_read_nz(bc, n); +} + +/** + * Return n bits from the buffer, n has to be in the 0-63 range. + */ +static inline uint64_t bits_read_63(BitstreamContext *bc, unsigned int n) +{ + uint64_t ret = 0; + unsigned left = 0; + + av_assert2(n <= 63); + + if (!n) + return 0; + + if (n > bc->bits_valid) { + left = bc->bits_valid; + n -= left; + + if (left) + ret = bits_priv_val_get(bc, left); + + if (bits_priv_refill_64(bc) < 0) + bc->bits_valid = n; + + } + +#ifdef BITSTREAM_READER_LE + ret = bits_priv_val_get(bc, n) << left | ret; +#else + ret = bits_priv_val_get(bc, n) | ret << n; +#endif + + return ret; +} + +/** + * Return n bits from the buffer, n has to be in the 0-64 range. + */ +static inline uint64_t bits_read_64(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n <= 64); + + if (n == 64) { + uint64_t ret = bits_read_63(bc, 63); +#ifdef BITSTREAM_READER_LE + return ret | ((uint64_t)bits_read_bit(bc) << 63); +#else + return (ret << 1) | (uint64_t)bits_read_bit(bc); +#endif + } + return bits_read_63(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 bits_read_signed(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(bits_read(bc, n), n); +} + +/** + * Return n bits from the buffer but do not change the buffer state. + * n has to be in the 1-32 range. May + */ +static inline uint32_t bits_peek_nz(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n > 0 && n <= 32); + + if (n > bc->bits_valid) + bits_priv_refill_32(bc); + + return bits_priv_val_show(bc, n); +} + +/** + * Return n bits from the buffer but do not change the buffer state. + * n has to be in the 0-32 range. + */ +static inline uint32_t bits_peek(BitstreamContext *bc, unsigned int n) +{ + av_assert2(n <= 32); + + if (!n) + return 0; + + return bits_peek_nz(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 bits_peek_signed(BitstreamContext *bc, unsigned int n) +{ + return sign_extend(bits_peek(bc, n), n); +} + +/** + * Skip n bits in the buffer. + */ +static inline void bits_skip(BitstreamContext *bc, unsigned int n) +{ + if (n < bc->bits_valid) + bits_priv_skip_remaining(bc, n); + else { + n -= bc->bits_valid; + bc->bits = 0; + bc->bits_valid = 0; + + if (n >= 64) { + unsigned int skip = n / 8; + + n -= skip * 8; + bc->ptr += skip; + } + bits_priv_refill_64(bc); + if (n) + bits_priv_skip_remaining(bc, n); + } +} + +/** + * Seek to the given bit position. + */ +static inline void bits_seek(BitstreamContext *bc, unsigned pos) +{ + bc->ptr = bc->buffer; + bc->bits = 0; + bc->bits_valid = 0; + + bits_skip(bc, pos); +} + +/** + * Skip bits to a byte boundary. + */ +static inline const uint8_t *bits_align(BitstreamContext *bc) +{ + unsigned int n = -bits_tell(bc) & 7; + if (n) + bits_skip(bc, n); + return bc->buffer + (bits_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 bits_read_xbits(BitstreamContext *bc, unsigned int n) +{ + int32_t cache = bits_peek(bc, 32); + int sign = ~cache >> 31; + bits_priv_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 bits_decode012(BitstreamContext *bc) +{ + if (!bits_read_bit(bc)) + return 0; + else + return bits_read_bit(bc) + 1; +} + +/** + * Return decoded truncated unary code for the values 2, 1, 0. + */ +static inline int bits_decode210(BitstreamContext *bc) +{ + if (bits_read_bit(bc)) + return 0; + else + return 2 - bits_read_bit(bc); +} + +/* Read sign bit and flip the sign of the provided value accordingly. */ +static inline int bits_apply_sign(BitstreamContext *bc, int val) +{ + int sign = bits_read_signed(bc, 1); + return (val ^ sign) - sign; +} + +static inline int bits_skip_1stop_8data(BitstreamContext *s) +{ + if (bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + + while (bits_read_bit(s)) { + bits_skip(s, 8); + if (bits_left(s) <= 0) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/** + * Return the LUT element for the given bitstream configuration. + */ +static inline int bits_priv_set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, + const VLCElem *table) +{ + unsigned idx; + + *nb_bits = -*n; + idx = bits_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 bits_read_vlc(BitstreamContext *bc, const VLCElem *table, + int bits, int max_depth) +{ + int nb_bits; + unsigned idx = bits_peek(bc, bits); + int code = table[idx].sym; + int n = table[idx].len; + + if (max_depth > 1 && n < 0) { + bits_priv_skip_remaining(bc, bits); + code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); + if (max_depth > 2 && n < 0) { + bits_priv_skip_remaining(bc, nb_bits); + code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); + } + } + bits_priv_skip_remaining(bc, n); + + return code; +} + +#define BITS_RL_VLC(level, run, bc, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + unsigned int index = bits_peek(bc, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + bits_skip(bc, bits); \ + \ + nb_bits = -n; \ + \ + index = bits_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + if (max_depth > 2 && n < 0) { \ + bits_skip(bc, nb_bits); \ + nb_bits = -n; \ + \ + index = bits_peek(bc, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + } \ + run = table[index].run; \ + bits_skip(bc, n); \ + } while (0) + +#endif /* AVCODEC_BITSTREAM_H */ From patchwork Sat Oct 22 10:32:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38904 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp1223078pzb; Sat, 22 Oct 2022 03:34:56 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6U3aMCt+wShP4tDNhE8qCH06pb0yuNXfqOaSSCxuAaGlJe7ZluQQJFA20kR29FmYX6t5ZE X-Received: by 2002:a05:6402:220b:b0:460:f0a1:c4ed with SMTP id cq11-20020a056402220b00b00460f0a1c4edmr11050748edb.318.1666434896627; Sat, 22 Oct 2022 03:34:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666434896; cv=none; d=google.com; s=arc-20160816; b=0Owh1BrUAhJDLoxUBz4cOCWU/DIbqgt8S4yzXM+mL18t9lQgUToiWMkI1881Xbc5r8 ZM/l68Y2yL6XoCnDBuOAqZ0FO6XKv7IDqz/foyZ5HryugplBQRg9Q4HAzR6yTYrq5uOJ faJOdrAUkcdT08CzhygL+u9Diwo5Gx727m4rZSt0JqRq8JWwixV34HIqMvnTb6HRLUB8 xZ3GCKHHOWO5aT8vrlo+O08VxP61xWVJc6bbiT++9D+VRNJU5wmITI28LR42uj0uCwXL fwS3JyWwlS1x7ly0n5600ZbYJ5KB7l5Uy5CCWYXzNntA6Yly2N5mTxWUsrAlbL6vhz1p R+Ww== 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=Jas55GdoWevLWwsSqKpko5DpgcXga5ramkZIid8/TqQ=; b=sWRwqpS+lJyw6+jGNxn1tSZ2+/Q1IfGyeGr1MJVFLrXBCRbajmwVAczFzfBwWEUwjL Kt0P34VzWK5KQSQiFJ+74a3rXtgjzcdjtCtAJwmNe/rwwKYMLiMIWO8unRhFK3FSarFO 4u8NuC+ti2gD9noGYi1KDVhmHPLQTNvVfM2JJ9TKTJoiIFopTX1LUgcphw1ya0LjaM5q 5n5QIbk5KWvsSZ/Fg9hQJM5CtpwRe0lho5ujTf6VzRc3OoCDKgLa6Nu5KIb9auHv7djT CSQH1BPvy0Ee8YSQ5ZXpDAZPY3Tz9yGLzg6JAEXTr9ANydHxB1Oi01hhiuKzKbtvUtoy 5SHA== 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 o25-20020a170906289900b0078d4dcceb5dsi19196564ejd.717.2022.10.22.03.34.55; Sat, 22 Oct 2022 03:34:56 -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 3988268BEB5; Sat, 22 Oct 2022 13:34:26 +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 0327B68BE7D for ; Sat, 22 Oct 2022 13:34:17 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 954C52404E4 for ; Sat, 22 Oct 2022 12:34:17 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id krhpnpNpHWk0 for ; Sat, 22 Oct 2022 12:34:15 +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 35B4E2400F4 for ; Sat, 22 Oct 2022 12:34:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 2290E3A0922 for ; Sat, 22 Oct 2022 12:34:04 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 22 Oct 2022 12:32:55 +0200 Message-Id: <20221022103257.15463-2-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221022103257.15463-1-anton@khirnov.net> References: <20221022103257.15463-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 2/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: s9pBVOcISl37 Allows using both BE and LE bitstream readers in the same file. --- libavcodec/Makefile | 1 + libavcodec/bitstream.h | 563 ++++-------------- .../{bitstream.h => bitstream_template.h} | 243 ++++---- tests/ref/fate/source | 1 + 4 files changed, 220 insertions(+), 588 deletions(-) copy libavcodec/{bitstream.h => bitstream_template.h} (54%) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 8fa83c72b2..b77fe0db8e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1238,6 +1238,7 @@ SKIPHEADERS += %_tablegen.h \ aaccoder_trellis.h \ aacenc_quantization.h \ aacenc_quantization_misc.h \ + bitstream_template.h \ $(ARCH)/vpx_arith.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h index 6fd321dba5..ef7d8d55c2 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream.h @@ -23,6 +23,21 @@ * bitstream reader API header. */ +/* + * Bit order (endianness) is controlled by #defining BITSTREAM_BE and/or + * BITSTREAM_LE before #including this header. The corresponding bitreading + * functions are provided as bits_*_be()/bits_*_le() respectively. + * + * If neither or only BITSTREAM_BE is defined, then the default (unsuffixed) + * bits_*() will resolve to the big-endian implementation. If only BITSTREAM_LE + * is defined, little-endian will be the default. + * + * If both are defined, then the default can be controlled by defining at most + * one of BITSTREAM_DEFAULT_LE/BE. When BITSTREAM_DEFAULT_* is not defined, no + * default is provided and you must always explicitly use the _be() or _le() + * variants. + */ + #ifndef AVCODEC_BITSTREAM_H #define AVCODEC_BITSTREAM_H @@ -42,461 +57,80 @@ #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_valid; // number of bits left in bits field - unsigned size_in_bits; -} BitstreamContext; - -/** - * @return - * - 0 on successful refill - * - a negative number when bitstream end is hit - * - * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. - */ -static inline int bits_priv_refill_64(BitstreamContext *bc) -{ -#if !UNCHECKED_BITSTREAM_READER - if (bc->ptr >= bc->buffer_end) - return -1; -#endif - -#ifdef BITSTREAM_READER_LE - bc->bits = AV_RL64(bc->ptr); -#else - bc->bits = AV_RB64(bc->ptr); -#endif - bc->ptr += 8; - bc->bits_valid = 64; - - return 0; -} - -/** - * @return - * - 0 on successful refill - * - a negative number when bitstream end is hit - * - * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. - */ -static inline int bits_priv_refill_32(BitstreamContext *bc) -{ -#if !UNCHECKED_BITSTREAM_READER - if (bc->ptr >= bc->buffer_end) - return -1; -#endif - -#ifdef BITSTREAM_READER_LE - bc->bits |= (uint64_t)AV_RL32(bc->ptr) << bc->bits_valid; -#else - bc->bits |= (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_valid); -#endif - bc->ptr += 4; - bc->bits_valid += 32; - - 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 bit_size the size of the buffer in bits - * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. - */ -static inline int bits_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_valid = 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_valid = 0; - bc->bits = 0; - - bits_priv_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 bits_init8(BitstreamContext *bc, const uint8_t *buffer, - unsigned int byte_size) -{ - if (byte_size > INT_MAX / 8) - return AVERROR_INVALIDDATA; - return bits_init(bc, buffer, byte_size * 8); -} - -/** - * Return number of bits already read. - */ -static inline int bits_tell(const BitstreamContext *bc) -{ - return (bc->ptr - bc->buffer) * 8 - bc->bits_valid; -} - -/** - * Return buffer size in bits. - */ -static inline int bits_size(const BitstreamContext *bc) -{ - return bc->size_in_bits; -} - -/** - * Return the number of the bits left in a buffer. - */ -static inline int bits_left(const BitstreamContext *bc) -{ - return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_valid; -} - -static inline uint64_t bits_priv_val_show(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n > 0 && n <= 64); - -#ifdef BITSTREAM_READER_LE - return bc->bits & (UINT64_MAX >> (64 - n)); -#else - return bc->bits >> (64 - n); -#endif -} - -static inline void bits_priv_skip_remaining(BitstreamContext *bc, unsigned int n) -{ -#ifdef BITSTREAM_READER_LE - bc->bits >>= n; -#else - bc->bits <<= n; -#endif - bc->bits_valid -= n; -} - -static inline uint64_t bits_priv_val_get(BitstreamContext *bc, unsigned int n) -{ - uint64_t ret; - - av_assert2(n > 0 && n < 64); - - ret = bits_priv_val_show(bc, n); - bits_priv_skip_remaining(bc, n); - - return ret; -} - -/** - * Return one bit from the buffer. - */ -static inline unsigned int bits_read_bit(BitstreamContext *bc) -{ - if (!bc->bits_valid && bits_priv_refill_64(bc) < 0) - return 0; - - return bits_priv_val_get(bc, 1); -} - -/** - * Return n bits from the buffer, n has to be in the 1-32 range. - * May be faster than bits_read() when n is not a compile-time constant and is - * known to be non-zero; - */ -static inline uint32_t bits_read_nz(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n > 0 && n <= 32); - - if (n > bc->bits_valid) { - if (bits_priv_refill_32(bc) < 0) - bc->bits_valid = n; - } - - return bits_priv_val_get(bc, n); -} - -/** - * Return n bits from the buffer, n has to be in the 0-32 range. - */ -static inline uint32_t bits_read(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n <= 32); - - if (!n) - return 0; - - return bits_read_nz(bc, n); -} - -/** - * Return n bits from the buffer, n has to be in the 0-63 range. - */ -static inline uint64_t bits_read_63(BitstreamContext *bc, unsigned int n) -{ - uint64_t ret = 0; - unsigned left = 0; - - av_assert2(n <= 63); - - if (!n) - return 0; - - if (n > bc->bits_valid) { - left = bc->bits_valid; - n -= left; - - if (left) - ret = bits_priv_val_get(bc, left); - - if (bits_priv_refill_64(bc) < 0) - bc->bits_valid = n; - - } - -#ifdef BITSTREAM_READER_LE - ret = bits_priv_val_get(bc, n) << left | ret; -#else - ret = bits_priv_val_get(bc, n) | ret << n; +// select the default endianness, if any +#if defined(BITSTREAM_LE) && defined(BITSTREAM_BE) + +# if defined(BITSTREAM_DEFAULT_BE) && defined(BITSTREAM_DEFAULT_LE) +# error "At most one of BITSTREAM_DEFAULT_BE/LE must be defined" +# elif defined(BITSTREAM_DEFAULT_BE) +# define BITS_DEFAULT_BE +# elif defined(BITSTREAM_DEFAULT_LE) +# define BITS_DEFAULT_LE +# endif + +#elif defined(BITSTREAM_LE) +# define BITS_DEFAULT_LE +#else // select BE if nothing is requested explicitly +# define BITS_DEFAULT_BE +# define BITSTREAM_WANT_BE #endif - return ret; -} +#if defined(BITS_DEFAULT_LE) + +# define BitstreamContext BitstreamContextLE +# define bits_init bits_init_le +# define bits_init8 bits_init8_le +# define bits_tell bits_tell_le +# define bits_size bits_size_le +# define bits_left bits_left_le +# define bits_read_bit bits_read_bit_le +# define bits_read_nz bits_read_nz_le +# define bits_read bits_read_le +# define bits_read_63 bits_read_63_le +# define bits_read_64 bits_read_64_le +# define bits_read_signed bits_read_signed_le +# define bits_peek_nz bits_peek_nz_le +# define bits_peek bits_peek_le +# define bits_peek_signed bits_peek_signed_le +# define bits_skip bits_skip_le +# define bits_seek bits_seek_le +# define bits_align bits_align_le +# define bits_read_xbits bits_read_xbits_le +# define bits_decode012 bits_decode012_le +# define bits_decode210 bits_decode210_le +# define bits_apply_sign bits_apply_sign_le +# define bits_read_vlc bits_read_vlc_le + +#elif defined(BITS_DEFAULT_BE) + +# define BitstreamContext BitstreamContextBE +# define bits_init bits_init_be +# define bits_init8 bits_init8_be +# define bits_tell bits_tell_be +# define bits_size bits_size_be +# define bits_left bits_left_be +# define bits_read_bit bits_read_bit_be +# define bits_read_nz bits_read_nz_be +# define bits_read bits_read_be +# define bits_read_63 bits_read_63_be +# define bits_read_64 bits_read_64_be +# define bits_read_signed bits_read_signed_be +# define bits_peek_nz bits_peek_nz_be +# define bits_peek bits_peek_be +# define bits_peek_signed bits_peek_signed_be +# define bits_skip bits_skip_be +# define bits_seek bits_seek_be +# define bits_align bits_align_be +# define bits_read_xbits bits_read_xbits_be +# define bits_decode012 bits_decode012_be +# define bits_decode210 bits_decode210_be +# define bits_apply_sign bits_apply_sign_be +# define bits_read_vlc bits_read_vlc_be -/** - * Return n bits from the buffer, n has to be in the 0-64 range. - */ -static inline uint64_t bits_read_64(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n <= 64); - - if (n == 64) { - uint64_t ret = bits_read_63(bc, 63); -#ifdef BITSTREAM_READER_LE - return ret | ((uint64_t)bits_read_bit(bc) << 63); -#else - return (ret << 1) | (uint64_t)bits_read_bit(bc); #endif - } - return bits_read_63(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 bits_read_signed(BitstreamContext *bc, unsigned int n) -{ - return sign_extend(bits_read(bc, n), n); -} - -/** - * Return n bits from the buffer but do not change the buffer state. - * n has to be in the 1-32 range. May - */ -static inline uint32_t bits_peek_nz(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n > 0 && n <= 32); - - if (n > bc->bits_valid) - bits_priv_refill_32(bc); - - return bits_priv_val_show(bc, n); -} - -/** - * Return n bits from the buffer but do not change the buffer state. - * n has to be in the 0-32 range. - */ -static inline uint32_t bits_peek(BitstreamContext *bc, unsigned int n) -{ - av_assert2(n <= 32); - - if (!n) - return 0; - return bits_peek_nz(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 bits_peek_signed(BitstreamContext *bc, unsigned int n) -{ - return sign_extend(bits_peek(bc, n), n); -} - -/** - * Skip n bits in the buffer. - */ -static inline void bits_skip(BitstreamContext *bc, unsigned int n) -{ - if (n < bc->bits_valid) - bits_priv_skip_remaining(bc, n); - else { - n -= bc->bits_valid; - bc->bits = 0; - bc->bits_valid = 0; - - if (n >= 64) { - unsigned int skip = n / 8; - - n -= skip * 8; - bc->ptr += skip; - } - bits_priv_refill_64(bc); - if (n) - bits_priv_skip_remaining(bc, n); - } -} - -/** - * Seek to the given bit position. - */ -static inline void bits_seek(BitstreamContext *bc, unsigned pos) -{ - bc->ptr = bc->buffer; - bc->bits = 0; - bc->bits_valid = 0; - - bits_skip(bc, pos); -} - -/** - * Skip bits to a byte boundary. - */ -static inline const uint8_t *bits_align(BitstreamContext *bc) -{ - unsigned int n = -bits_tell(bc) & 7; - if (n) - bits_skip(bc, n); - return bc->buffer + (bits_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 bits_read_xbits(BitstreamContext *bc, unsigned int n) -{ - int32_t cache = bits_peek(bc, 32); - int sign = ~cache >> 31; - bits_priv_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 bits_decode012(BitstreamContext *bc) -{ - if (!bits_read_bit(bc)) - return 0; - else - return bits_read_bit(bc) + 1; -} - -/** - * Return decoded truncated unary code for the values 2, 1, 0. - */ -static inline int bits_decode210(BitstreamContext *bc) -{ - if (bits_read_bit(bc)) - return 0; - else - return 2 - bits_read_bit(bc); -} - -/* Read sign bit and flip the sign of the provided value accordingly. */ -static inline int bits_apply_sign(BitstreamContext *bc, int val) -{ - int sign = bits_read_signed(bc, 1); - return (val ^ sign) - sign; -} - -static inline int bits_skip_1stop_8data(BitstreamContext *s) -{ - if (bits_left(s) <= 0) - return AVERROR_INVALIDDATA; - - while (bits_read_bit(s)) { - bits_skip(s, 8); - if (bits_left(s) <= 0) - return AVERROR_INVALIDDATA; - } - - return 0; -} - -/** - * Return the LUT element for the given bitstream configuration. - */ -static inline int bits_priv_set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, - const VLCElem *table) -{ - unsigned idx; - - *nb_bits = -*n; - idx = bits_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 bits_read_vlc(BitstreamContext *bc, const VLCElem *table, - int bits, int max_depth) -{ - int nb_bits; - unsigned idx = bits_peek(bc, bits); - int code = table[idx].sym; - int n = table[idx].len; - - if (max_depth > 1 && n < 0) { - bits_priv_skip_remaining(bc, bits); - code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); - if (max_depth > 2 && n < 0) { - bits_priv_skip_remaining(bc, nb_bits); - code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); - } - } - bits_priv_skip_remaining(bc, n); - - return code; -} +#undef BITS_DEFAULT_LE +#undef BITS_DEFAULT_BE #define BITS_RL_VLC(level, run, bc, table, bits, max_depth) \ do { \ @@ -527,3 +161,32 @@ static inline int bits_read_vlc(BitstreamContext *bc, const VLCElem *table, } while (0) #endif /* AVCODEC_BITSTREAM_H */ + +// the following is deliberately outside of the standard #include guards + +#if defined(BITSTREAM_LE) && !defined(BITSTREAM_WANT_LE) +# define BITSTREAM_WANT_LE +#endif + +#if defined(BITSTREAM_BE) && !defined(BITSTREAM_WANT_BE) +# define BITSTREAM_WANT_BE +#endif + +#if defined(BITSTREAM_WANT_LE) && !defined(AVCODEC_BITSTREAM_LE) +#define AVCODEC_BITSTREAM_LE + +#define BITSTREAM_TEMPLATE_LE +#include "bitstream_template.h" +#undef BITSTREAM_TEMPLATE_LE + +#endif + +#if defined(BITSTREAM_WANT_BE) && !defined(AVCODEC_BITSTREAM_BE) +#define AVCODEC_BITSTREAM_BE + +#include "bitstream_template.h" + +#endif + +#undef BITSTREAM_WANT_LE +#undef BITSTREAM_WANT_BE diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream_template.h similarity index 54% copy from libavcodec/bitstream.h copy to libavcodec/bitstream_template.h index 6fd321dba5..f2c14fc4d3 100644 --- a/libavcodec/bitstream.h +++ b/libavcodec/bitstream_template.h @@ -18,37 +18,27 @@ * 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/avassert.h" -#include "libavutil/common.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/log.h" +#ifdef BITSTREAM_TEMPLATE_LE +# define BS_SUFFIX_LOWER _le +# define BS_SUFFIX_UPPER LE +#else +# define BS_SUFFIX_LOWER _be +# define BS_SUFFIX_UPPER BE +#endif -#include "mathops.h" -#include "vlc.h" +#define BS_JOIN(x, y, z) x ## y ## z +#define BS_JOIN3(x, y, z) BS_JOIN(x, y, z) +#define BS_FUNC(x) BS_JOIN3(bits_, x, BS_SUFFIX_LOWER) -#ifndef UNCHECKED_BITSTREAM_READER -#define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER -#endif +#define BSCTX BS_JOIN3(Bitstream, Context, BS_SUFFIX_UPPER) -typedef struct BitstreamContext { +typedef struct BSCTX { 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_valid; // number of bits left in bits field unsigned size_in_bits; -} BitstreamContext; +} BSCTX; /** * @return @@ -57,14 +47,14 @@ typedef struct BitstreamContext { * * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. */ -static inline int bits_priv_refill_64(BitstreamContext *bc) +static inline int BS_FUNC(priv_refill_64)(BSCTX *bc) { #if !UNCHECKED_BITSTREAM_READER if (bc->ptr >= bc->buffer_end) return -1; #endif -#ifdef BITSTREAM_READER_LE +#ifdef BITSTREAM_TEMPLATE_LE bc->bits = AV_RL64(bc->ptr); #else bc->bits = AV_RB64(bc->ptr); @@ -82,14 +72,14 @@ static inline int bits_priv_refill_64(BitstreamContext *bc) * * Always succeeds when UNCHECKED_BITSTREAM_READER is enabled. */ -static inline int bits_priv_refill_32(BitstreamContext *bc) +static inline int BS_FUNC(priv_refill_32)(BSCTX *bc) { #if !UNCHECKED_BITSTREAM_READER if (bc->ptr >= bc->buffer_end) return -1; #endif -#ifdef BITSTREAM_READER_LE +#ifdef BITSTREAM_TEMPLATE_LE bc->bits |= (uint64_t)AV_RL32(bc->ptr) << bc->bits_valid; #else bc->bits |= (uint64_t)AV_RB32(bc->ptr) << (32 - bc->bits_valid); @@ -108,8 +98,8 @@ static inline int bits_priv_refill_32(BitstreamContext *bc) * @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 bits_init(BitstreamContext *bc, const uint8_t *buffer, - unsigned int bit_size) +static inline int BS_FUNC(init)(BSCTX *bc, const uint8_t *buffer, + unsigned int bit_size) { unsigned int buffer_size; @@ -129,7 +119,7 @@ static inline int bits_init(BitstreamContext *bc, const uint8_t *buffer, bc->bits_valid = 0; bc->bits = 0; - bits_priv_refill_64(bc); + BS_FUNC(priv_refill_64)(bc); return 0; } @@ -142,18 +132,18 @@ static inline int bits_init(BitstreamContext *bc, const uint8_t *buffer, * @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 bits_init8(BitstreamContext *bc, const uint8_t *buffer, - unsigned int byte_size) +static inline int BS_FUNC(init8)(BSCTX *bc, const uint8_t *buffer, + unsigned int byte_size) { if (byte_size > INT_MAX / 8) return AVERROR_INVALIDDATA; - return bits_init(bc, buffer, byte_size * 8); + return BS_FUNC(init)(bc, buffer, byte_size * 8); } /** * Return number of bits already read. */ -static inline int bits_tell(const BitstreamContext *bc) +static inline int BS_FUNC(tell)(const BSCTX *bc) { return (bc->ptr - bc->buffer) * 8 - bc->bits_valid; } @@ -161,7 +151,7 @@ static inline int bits_tell(const BitstreamContext *bc) /** * Return buffer size in bits. */ -static inline int bits_size(const BitstreamContext *bc) +static inline int BS_FUNC(size)(const BSCTX *bc) { return bc->size_in_bits; } @@ -169,25 +159,25 @@ static inline int bits_size(const BitstreamContext *bc) /** * Return the number of the bits left in a buffer. */ -static inline int bits_left(const BitstreamContext *bc) +static inline int BS_FUNC(left)(const BSCTX *bc) { return (bc->buffer - bc->ptr) * 8 + bc->size_in_bits + bc->bits_valid; } -static inline uint64_t bits_priv_val_show(BitstreamContext *bc, unsigned int n) +static inline uint64_t BS_FUNC(priv_val_show)(BSCTX *bc, unsigned int n) { av_assert2(n > 0 && n <= 64); -#ifdef BITSTREAM_READER_LE +#ifdef BITSTREAM_TEMPLATE_LE return bc->bits & (UINT64_MAX >> (64 - n)); #else return bc->bits >> (64 - n); #endif } -static inline void bits_priv_skip_remaining(BitstreamContext *bc, unsigned int n) +static inline void BS_FUNC(priv_skip_remaining)(BSCTX *bc, unsigned int n) { -#ifdef BITSTREAM_READER_LE +#ifdef BITSTREAM_TEMPLATE_LE bc->bits >>= n; #else bc->bits <<= n; @@ -195,14 +185,14 @@ static inline void bits_priv_skip_remaining(BitstreamContext *bc, unsigned int n bc->bits_valid -= n; } -static inline uint64_t bits_priv_val_get(BitstreamContext *bc, unsigned int n) +static inline uint64_t BS_FUNC(priv_val_get)(BSCTX *bc, unsigned int n) { uint64_t ret; av_assert2(n > 0 && n < 64); - ret = bits_priv_val_show(bc, n); - bits_priv_skip_remaining(bc, n); + ret = BS_FUNC(priv_val_show)(bc, n); + BS_FUNC(priv_skip_remaining)(bc, n); return ret; } @@ -210,12 +200,12 @@ static inline uint64_t bits_priv_val_get(BitstreamContext *bc, unsigned int n) /** * Return one bit from the buffer. */ -static inline unsigned int bits_read_bit(BitstreamContext *bc) +static inline unsigned int BS_FUNC(read_bit)(BSCTX *bc) { - if (!bc->bits_valid && bits_priv_refill_64(bc) < 0) + if (!bc->bits_valid && BS_FUNC(priv_refill_64)(bc) < 0) return 0; - return bits_priv_val_get(bc, 1); + return BS_FUNC(priv_val_get)(bc, 1); } /** @@ -223,35 +213,35 @@ static inline unsigned int bits_read_bit(BitstreamContext *bc) * May be faster than bits_read() when n is not a compile-time constant and is * known to be non-zero; */ -static inline uint32_t bits_read_nz(BitstreamContext *bc, unsigned int n) +static inline uint32_t BS_FUNC(read_nz)(BSCTX *bc, unsigned int n) { av_assert2(n > 0 && n <= 32); if (n > bc->bits_valid) { - if (bits_priv_refill_32(bc) < 0) + if (BS_FUNC(priv_refill_32)(bc) < 0) bc->bits_valid = n; } - return bits_priv_val_get(bc, n); + return BS_FUNC(priv_val_get)(bc, n); } /** * Return n bits from the buffer, n has to be in the 0-32 range. */ -static inline uint32_t bits_read(BitstreamContext *bc, unsigned int n) +static inline uint32_t BS_FUNC(read)(BSCTX *bc, unsigned int n) { av_assert2(n <= 32); if (!n) return 0; - return bits_read_nz(bc, n); + return BS_FUNC(read_nz)(bc, n); } /** * Return n bits from the buffer, n has to be in the 0-63 range. */ -static inline uint64_t bits_read_63(BitstreamContext *bc, unsigned int n) +static inline uint64_t BS_FUNC(read_63)(BSCTX *bc, unsigned int n) { uint64_t ret = 0; unsigned left = 0; @@ -266,17 +256,17 @@ static inline uint64_t bits_read_63(BitstreamContext *bc, unsigned int n) n -= left; if (left) - ret = bits_priv_val_get(bc, left); + ret = BS_FUNC(priv_val_get)(bc, left); - if (bits_priv_refill_64(bc) < 0) + if (BS_FUNC(priv_refill_64)(bc) < 0) bc->bits_valid = n; } -#ifdef BITSTREAM_READER_LE - ret = bits_priv_val_get(bc, n) << left | ret; +#ifdef BITSTREAM_TEMPLATE_LE + ret = BS_FUNC(priv_val_get)(bc, n) << left | ret; #else - ret = bits_priv_val_get(bc, n) | ret << n; + ret = BS_FUNC(priv_val_get)(bc, n) | ret << n; #endif return ret; @@ -285,56 +275,56 @@ static inline uint64_t bits_read_63(BitstreamContext *bc, unsigned int n) /** * Return n bits from the buffer, n has to be in the 0-64 range. */ -static inline uint64_t bits_read_64(BitstreamContext *bc, unsigned int n) +static inline uint64_t BS_FUNC(read_64)(BSCTX *bc, unsigned int n) { av_assert2(n <= 64); if (n == 64) { - uint64_t ret = bits_read_63(bc, 63); -#ifdef BITSTREAM_READER_LE - return ret | ((uint64_t)bits_read_bit(bc) << 63); + uint64_t ret = BS_FUNC(read_63)(bc, 63); +#ifdef BITSTREAM_TEMPLATE_LE + return ret | ((uint64_t)BS_FUNC(read_bit)(bc) << 63); #else - return (ret << 1) | (uint64_t)bits_read_bit(bc); + return (ret << 1) | (uint64_t)BS_FUNC(read_bit)(bc); #endif } - return bits_read_63(bc, n); + return BS_FUNC(read_63)(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 bits_read_signed(BitstreamContext *bc, unsigned int n) +static inline int32_t BS_FUNC(read_signed)(BSCTX *bc, unsigned int n) { - return sign_extend(bits_read(bc, n), n); + return sign_extend(BS_FUNC(read)(bc, n), n); } /** * Return n bits from the buffer but do not change the buffer state. * n has to be in the 1-32 range. May */ -static inline uint32_t bits_peek_nz(BitstreamContext *bc, unsigned int n) +static inline uint32_t BS_FUNC(peek_nz)(BSCTX *bc, unsigned int n) { av_assert2(n > 0 && n <= 32); if (n > bc->bits_valid) - bits_priv_refill_32(bc); + BS_FUNC(priv_refill_32)(bc); - return bits_priv_val_show(bc, n); + return BS_FUNC(priv_val_show)(bc, n); } /** * Return n bits from the buffer but do not change the buffer state. * n has to be in the 0-32 range. */ -static inline uint32_t bits_peek(BitstreamContext *bc, unsigned int n) +static inline uint32_t BS_FUNC(peek)(BSCTX *bc, unsigned int n) { av_assert2(n <= 32); if (!n) return 0; - return bits_peek_nz(bc, n); + return BS_FUNC(peek_nz)(bc, n); } /** @@ -342,18 +332,18 @@ static inline uint32_t bits_peek(BitstreamContext *bc, unsigned int n) * do not change the buffer state. * n has to be in the 0-32 range. */ -static inline int bits_peek_signed(BitstreamContext *bc, unsigned int n) +static inline int BS_FUNC(peek_signed)(BSCTX *bc, unsigned int n) { - return sign_extend(bits_peek(bc, n), n); + return sign_extend(BS_FUNC(peek)(bc, n), n); } /** * Skip n bits in the buffer. */ -static inline void bits_skip(BitstreamContext *bc, unsigned int n) +static inline void BS_FUNC(skip)(BSCTX *bc, unsigned int n) { if (n < bc->bits_valid) - bits_priv_skip_remaining(bc, n); + BS_FUNC(priv_skip_remaining)(bc, n); else { n -= bc->bits_valid; bc->bits = 0; @@ -365,33 +355,33 @@ static inline void bits_skip(BitstreamContext *bc, unsigned int n) n -= skip * 8; bc->ptr += skip; } - bits_priv_refill_64(bc); + BS_FUNC(priv_refill_64)(bc); if (n) - bits_priv_skip_remaining(bc, n); + BS_FUNC(priv_skip_remaining)(bc, n); } } /** * Seek to the given bit position. */ -static inline void bits_seek(BitstreamContext *bc, unsigned pos) +static inline void BS_FUNC(seek)(BSCTX *bc, unsigned pos) { bc->ptr = bc->buffer; bc->bits = 0; bc->bits_valid = 0; - bits_skip(bc, pos); + BS_FUNC(skip)(bc, pos); } /** * Skip bits to a byte boundary. */ -static inline const uint8_t *bits_align(BitstreamContext *bc) +static inline const uint8_t *BS_FUNC(align)(BSCTX *bc) { - unsigned int n = -bits_tell(bc) & 7; + unsigned int n = -BS_FUNC(tell)(bc) & 7; if (n) - bits_skip(bc, n); - return bc->buffer + (bits_tell(bc) >> 3); + BS_FUNC(skip)(bc, n); + return bc->buffer + (BS_FUNC(tell)(bc) >> 3); } /** @@ -399,11 +389,11 @@ static inline const uint8_t *bits_align(BitstreamContext *bc) * If MSB not set it is negative. * @param n length in bits */ -static inline int bits_read_xbits(BitstreamContext *bc, unsigned int n) +static inline int BS_FUNC(read_xbits)(BSCTX *bc, unsigned int n) { - int32_t cache = bits_peek(bc, 32); + int32_t cache = BS_FUNC(peek)(bc, 32); int sign = ~cache >> 31; - bits_priv_skip_remaining(bc, n); + BS_FUNC(priv_skip_remaining)(bc, n); return ((((uint32_t)(sign ^ cache)) >> (32 - n)) ^ sign) - sign; } @@ -411,40 +401,40 @@ static inline int bits_read_xbits(BitstreamContext *bc, unsigned int n) /** * Return decoded truncated unary code for the values 0, 1, 2. */ -static inline int bits_decode012(BitstreamContext *bc) +static inline int BS_FUNC(decode012)(BSCTX *bc) { - if (!bits_read_bit(bc)) + if (!BS_FUNC(read_bit)(bc)) return 0; else - return bits_read_bit(bc) + 1; + return BS_FUNC(read_bit)(bc) + 1; } /** * Return decoded truncated unary code for the values 2, 1, 0. */ -static inline int bits_decode210(BitstreamContext *bc) +static inline int BS_FUNC(decode210)(BSCTX *bc) { - if (bits_read_bit(bc)) + if (BS_FUNC(read_bit)(bc)) return 0; else - return 2 - bits_read_bit(bc); + return 2 - BS_FUNC(read_bit)(bc); } /* Read sign bit and flip the sign of the provided value accordingly. */ -static inline int bits_apply_sign(BitstreamContext *bc, int val) +static inline int BS_FUNC(apply_sign)(BSCTX *bc, int val) { - int sign = bits_read_signed(bc, 1); + int sign = BS_FUNC(read_signed)(bc, 1); return (val ^ sign) - sign; } -static inline int bits_skip_1stop_8data(BitstreamContext *s) +static inline int BS_FUNC(skip_1stop_8data)(BSCTX *s) { - if (bits_left(s) <= 0) + if (BS_FUNC(left)(s) <= 0) return AVERROR_INVALIDDATA; - while (bits_read_bit(s)) { - bits_skip(s, 8); - if (bits_left(s) <= 0) + while (BS_FUNC(read_bit)(s)) { + BS_FUNC(skip)(s, 8); + if (BS_FUNC(left)(s) <= 0) return AVERROR_INVALIDDATA; } @@ -454,13 +444,13 @@ static inline int bits_skip_1stop_8data(BitstreamContext *s) /** * Return the LUT element for the given bitstream configuration. */ -static inline int bits_priv_set_idx(BitstreamContext *bc, int code, int *n, int *nb_bits, - const VLCElem *table) +static inline int BS_FUNC(priv_set_idx)(BSCTX *bc, int code, int *n, + int *nb_bits, const VLCElem *table) { unsigned idx; *nb_bits = -*n; - idx = bits_peek(bc, *nb_bits) + code; + idx = BS_FUNC(peek)(bc, *nb_bits) + code; *n = table[idx].len; return table[idx].sym; @@ -477,53 +467,30 @@ static inline int bits_priv_set_idx(BitstreamContext *bc, int code, int *n, int * If the vlc code is invalid and max_depth>1, then the number of bits removed * is undefined. */ -static inline int bits_read_vlc(BitstreamContext *bc, const VLCElem *table, - int bits, int max_depth) +static inline int BS_FUNC(read_vlc)(BSCTX *bc, const VLCElem *table, + int bits, int max_depth) { int nb_bits; - unsigned idx = bits_peek(bc, bits); + unsigned idx = BS_FUNC(peek)(bc, bits); int code = table[idx].sym; int n = table[idx].len; if (max_depth > 1 && n < 0) { - bits_priv_skip_remaining(bc, bits); - code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); + BS_FUNC(priv_skip_remaining)(bc, bits); + code = BS_FUNC(priv_set_idx)(bc, code, &n, &nb_bits, table); if (max_depth > 2 && n < 0) { - bits_priv_skip_remaining(bc, nb_bits); - code = bits_priv_set_idx(bc, code, &n, &nb_bits, table); + BS_FUNC(priv_skip_remaining)(bc, nb_bits); + code = BS_FUNC(priv_set_idx)(bc, code, &n, &nb_bits, table); } } - bits_priv_skip_remaining(bc, n); + BS_FUNC(priv_skip_remaining)(bc, n); return code; } -#define BITS_RL_VLC(level, run, bc, table, bits, max_depth) \ - do { \ - int n, nb_bits; \ - unsigned int index = bits_peek(bc, bits); \ - level = table[index].level; \ - n = table[index].len; \ - \ - if (max_depth > 1 && n < 0) { \ - bits_skip(bc, bits); \ - \ - nb_bits = -n; \ - \ - index = bits_peek(bc, nb_bits) + level; \ - level = table[index].level; \ - n = table[index].len; \ - if (max_depth > 2 && n < 0) { \ - bits_skip(bc, nb_bits); \ - nb_bits = -n; \ - \ - index = bits_peek(bc, nb_bits) + level; \ - level = table[index].level; \ - n = table[index].len; \ - } \ - } \ - run = table[index].run; \ - bits_skip(bc, n); \ - } while (0) - -#endif /* AVCODEC_BITSTREAM_H */ +#undef BSCTX +#undef BS_FUNC +#undef BS_JOIN3 +#undef BS_JOIN +#undef BS_SUFFIX_UPPER +#undef BS_SUFFIX_LOWER 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 Sat Oct 22 10:32:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38901 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp1222921pzb; Sat, 22 Oct 2022 03:34:27 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5i2EfClOUl/7BuS11TwcVWeadD+jxyR5Hu5h95R9PtlhusDEJOcSw+PDDV1zPr35lzofiQ X-Received: by 2002:a17:907:3188:b0:741:4bf7:ec1a with SMTP id xe8-20020a170907318800b007414bf7ec1amr19849206ejb.448.1666434867617; Sat, 22 Oct 2022 03:34:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666434867; cv=none; d=google.com; s=arc-20160816; b=goRu+s8VpNThijgIrjC4hHrw/y6bGqbZOs1saNhwGKOi5VMK1d7KNz1VqB2jNzSLdH dq5nEqBUHPL9vH8IfUGKhosBwVmig1UinQ7fp00NDjzZQvm7MCafcKx2eN03pQhI7nOg YckWzirKAKeb32tw34KxARe8jH/rZdHh4Z8gWsXV0N4tBrSNFFt9yne+989rJ5tci1Az +c2jmOC8svwuGNBdAPUS8h0xtWNV5e+c4MouiqWDCm9if69VtnErb1DPeTNkmOq2Q7M3 TlLgcoCam3nXmHfdUgENYUAGk+6/qf2Ax9Gf8WbuwoP/1af2jZalokHiZaQgR43RfxZC R6Jg== 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=0WzoowcFp/qmQVTlmF33XtqtuKrNPyItrBSBpG7tgcw=; b=UNchk75NltjCQqQiN8tsFEBN77/gCZZ5rCvH/vIM5UzjLmk7TmXKNJaNb7NhbPyf68 13tXrT3UC3P7H5ZPVX7d7J5v6huE/JaOPG0tWOA54mFZkg2dxrMdVDLxNv2P+foeqL0K Yi7lxFYHnWifGLgzZyJOG+cRLea2Wy/t9P0jsIbbwo996S5lU03WwSomP8m04H9KPcqv D376cNCLE13L9Ze2SBt3ZCoazWylh+gcbs/vYSBmt9Bl6dXgIWsWeZufpsMMHqoeTwZR Vy/HjkkbtcH1J1okIoah1qYvCQwWOO2lWkbq6Vr8ep8XBEhEq9nh+qMJwtEfa7CD+lNx 01zQ== 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 m10-20020a50cc0a000000b00458d94f1a45si19579026edi.413.2022.10.22.03.34.26; Sat, 22 Oct 2022 03:34:27 -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 191A768BE7F; Sat, 22 Oct 2022 13:34:23 +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 B990368BDAF for ; Sat, 22 Oct 2022 13:34:15 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id AEFED2404F8 for ; Sat, 22 Oct 2022 12:34:14 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id cEMRe9GFvBLJ for ; Sat, 22 Oct 2022 12:34:13 +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 397E82404F5 for ; Sat, 22 Oct 2022 12:34:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 265613A13D9 for ; Sat, 22 Oct 2022 12:34:04 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 22 Oct 2022 12:32:56 +0200 Message-Id: <20221022103257.15463-3-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221022103257.15463-1-anton@khirnov.net> References: <20221022103257.15463-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 3/4] lavc/tests: add a cached bitstream reader test 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: 0K5FAWGTF42w --- libavcodec/Makefile | 2 + libavcodec/tests/bitstream_be.c | 19 +++ libavcodec/tests/bitstream_le.c | 20 +++ libavcodec/tests/bitstream_template.c | 183 ++++++++++++++++++++++++++ tests/fate/libavcodec.mak | 10 ++ 5 files changed, 234 insertions(+) create mode 100644 libavcodec/tests/bitstream_be.c create mode 100644 libavcodec/tests/bitstream_le.c create mode 100644 libavcodec/tests/bitstream_template.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b77fe0db8e..4314b47d65 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1265,6 +1265,8 @@ SKIPHEADERS-$(CONFIG_ZLIB) += zlib_wrapper.h TESTPROGS = avcodec \ avpacket \ + bitstream_be \ + bitstream_le \ celp_math \ codec_desc \ htmlsubtitles \ diff --git a/libavcodec/tests/bitstream_be.c b/libavcodec/tests/bitstream_be.c new file mode 100644 index 0000000000..bc562ed3b1 --- /dev/null +++ b/libavcodec/tests/bitstream_be.c @@ -0,0 +1,19 @@ +/* + * 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 + */ + +#include "bitstream_template.c" diff --git a/libavcodec/tests/bitstream_le.c b/libavcodec/tests/bitstream_le.c new file mode 100644 index 0000000000..ba9296c95a --- /dev/null +++ b/libavcodec/tests/bitstream_le.c @@ -0,0 +1,20 @@ +/* + * 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 + */ + +#define BITSTREAM_LE +#include "bitstream_template.c" diff --git a/libavcodec/tests/bitstream_template.c b/libavcodec/tests/bitstream_template.c new file mode 100644 index 0000000000..13e92a31c6 --- /dev/null +++ b/libavcodec/tests/bitstream_template.c @@ -0,0 +1,183 @@ +/* + * cached bitstream reader test + * copyright (c) 2022 Anton Khirnov + * + * 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 + */ + +#define ASSERT_LEVEL 2 + +#include "libavutil/avassert.h" +#include "libavutil/lfg.h" +#include "libavutil/random_seed.h" + +#include "libavcodec/bitstream.h" +#include "libavcodec/defs.h" + +#ifdef BITSTREAM_LE +#define BITSTREAM_WRITER_LE +#endif +#include "libavcodec/put_bits.h" + +#define SIZE 157 + +enum Op { + OP_READ, + OP_READ_NZ, + OP_READ_BIT, + OP_READ_63, + OP_READ_64, + OP_READ_SIGNED, + OP_APPLY_SIGN, + OP_ALIGN, + OP_NB, +}; + +int main(int argc, char **argv) +{ + BitstreamContext bc; + PutBitContext pb; + AVLFG lfg; + + uint8_t buf[SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + uint8_t dst[SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + + uint32_t random_seed; + uint64_t val, val1; + int32_t sval; + unsigned count; + + /* generate random input, using a given or random seed */ + if (argc > 1) + random_seed = strtoul(argv[1], NULL, 0); + else + random_seed = av_get_random_seed(); + + fprintf(stderr, "Testing with LFG seed: %"PRIu32"\n", random_seed); + av_lfg_init(&lfg, random_seed); + + for (unsigned i = 0; i < SIZE; i++) + buf[i] = av_lfg_get(&lfg); + + bits_init8 (&bc, buf, SIZE); + init_put_bits(&pb, dst, SIZE); + + /* use a random sequence of bitreading operations to transfer data + * from BitstreamContext to PutBitContext */ + while (bits_left(&bc) > 0) { + enum Op op = av_lfg_get(&lfg) % OP_NB; + + switch (op) { + case OP_READ: + count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1); + val1 = bits_peek(&bc, count); + val = bits_read(&bc, count); + + fprintf(stderr, "%d read %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val); + + av_assert0(val == val1); + + put_bits64(&pb, count, val); + break; + case OP_READ_NZ: + count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1); + count = FFMAX(count, 1); + val1 = bits_peek_nz(&bc, count); + val = bits_read_nz(&bc, count); + + fprintf(stderr, "%d read_nz %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val); + + av_assert0(val == val1); + + put_bits64(&pb, count, val); + break; + case OP_READ_BIT: + val = bits_read_bit(&bc); + + fprintf(stderr, "%d read_bit: %"PRIu64"\n", bits_tell(&bc) - 1, val); + + put_bits(&pb, 1, val); + break; + case OP_READ_63: + count = av_lfg_get(&lfg) % FFMIN(64, bits_left(&bc) + 1); + val = bits_read_63(&bc, count); + + fprintf(stderr, "%d read_63 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val); + + put_bits64(&pb, count, val); + break; + case OP_READ_64: + count = av_lfg_get(&lfg) % FFMIN(65, bits_left(&bc) + 1); + val = bits_read_64(&bc, count); + + fprintf(stderr, "%d read_64 %u: %"PRIu64"\n", bits_tell(&bc) - count, count, val); + + put_bits64(&pb, count, val); + break; + case OP_READ_SIGNED: + count = av_lfg_get(&lfg) % FFMIN(33, bits_left(&bc) + 1); + sval = bits_read_signed(&bc, count); + + fprintf(stderr, "%d read_signed %u: %"PRId32"\n", bits_tell(&bc) - count, count, sval); + + if (count == 32) put_bits32(&pb, sval); + else put_sbits(&pb, count, sval); + break; + case OP_ALIGN: + count = (bits_tell(&bc) + 7) / 8 * 8 - bits_tell(&bc); + + fprintf(stderr, "%d align %u\n", bits_tell(&bc), count); + + put_bits(&pb, count, bits_peek(&bc, count)); + bits_align(&bc); + break; + case OP_APPLY_SIGN: + if (bits_left(&bc) < 2) + continue; + + count = av_lfg_get(&lfg) % FFMIN(32, bits_left(&bc)); + count = FFMAX(count, 1); + + if (!bits_peek(&bc, count)) + continue; + + val = bits_read(&bc, count); + sval = bits_apply_sign(&bc, val); + + fprintf(stderr, "%d apply_sign %u %"PRId32"\n", + bits_tell(&bc) - count - 1, count, sval); + + put_bits64(&pb, count, FFABS(sval)); + put_bits(&pb, 1, sval < 0); + + break; + default: + av_assert0(0); + } + } + + flush_put_bits(&pb); + + for (unsigned i = 0; i < SIZE; i++) + if (buf[i] != dst[i]) { + fprintf(stderr, "Mismatch at byte %u: %hhu %hhu; seed %"PRIu32"\n", + i, buf[i], dst[i], random_seed); + return 1; + } + + return 0; +} diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak index aa199e0308..8f56fae3a8 100644 --- a/tests/fate/libavcodec.mak +++ b/tests/fate/libavcodec.mak @@ -3,6 +3,16 @@ fate-avpacket: libavcodec/tests/avpacket$(EXESUF) fate-avpacket: CMD = run libavcodec/tests/avpacket$(EXESUF) fate-avpacket: CMP = null +FATE_LIBAVCODEC-yes += fate-bitstream-be +fate-bitstream-be: libavcodec/tests/bitstream_be$(EXESUF) +fate-bitstream-be: CMD = run libavcodec/tests/bitstream_be$(EXESUF) +fate-bitstream-be: CMP = null + +FATE_LIBAVCODEC-yes += fate-bitstream-le +fate-bitstream-le: libavcodec/tests/bitstream_le$(EXESUF) +fate-bitstream-le: CMD = run libavcodec/tests/bitstream_le$(EXESUF) +fate-bitstream-le: CMP = null + FATE_LIBAVCODEC-$(CONFIG_CABAC) += fate-cabac fate-cabac: libavcodec/tests/cabac$(EXESUF) fate-cabac: CMD = run libavcodec/tests/cabac$(EXESUF) From patchwork Sat Oct 22 10:32:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 38902 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp1222973pzb; Sat, 22 Oct 2022 03:34:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM67guKE9WstALrgMz+oNQEEPY056M6bH0Kyl277J2mSdpJ2m2kZHT7miU1j0au+LTh/01/u X-Received: by 2002:a17:907:2e0b:b0:78e:16cb:327b with SMTP id ig11-20020a1709072e0b00b0078e16cb327bmr19127554ejc.458.1666434877965; Sat, 22 Oct 2022 03:34:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666434877; cv=none; d=google.com; s=arc-20160816; b=HpSkelxolNqfwvNAoateJqEFfagWa0NVBdS2LrDt46HDI7dvAoNPTVjeEQ9XuMIfXM WCWvxa9+OfLQRSq8b5izqVKCKjP8LU2Uxr2gssBEtdchGfjQb9Mu0T+mYksbTvkbkA6e 0GLWZlRWvKQqCdzfytYuh49j37t9GqrDZRPjxyunBiS5nu3KgUuCo4tUDpazXdii+o0i CiXx+TFeEjp14f3VgbSpqUZPe3uYiAICPHkvoMrICd9aF1kzzXj5BoB+RajSBKPrJ1v9 yxZ9AGuze6C0TDd1NF6fzBmZpvCRJ2GoXmw0y6ipXt7rxaDoF1Lik36DDwOOvCivoQi1 IgSA== 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=mX4mmlmdwh4RwDxWVyb9jgXo4lETqgtg4YhyPRN+ouY=; b=JyyeRsmVTZQD+XqmwaIbFKDJym3S8uOEkRYF4+Gc6rzsXC/qhu3Z3hZpp571Nk+5Ec mY6Ry2vdjHDD7Fd9+c3g/Iu44fTR7tpU1WkPGWU5+Ka0lAYSMIHlDrQW/0eRQU7VK9ro JPVwOUzoaEjBnxv6cY6rTdjWfoPb8FAOYCiyZtovI+CHUDbrl0PeYVckHUH0J4I3pxZZ 0+AxFdml9rspcj+DRVIqZvWMwcdbQ+eksYynqZjs+ju7l1W7mm3mqEfVmoaayLuWagr6 TlZK4R7CihtgVaqjK74TkL3hFoTBDClxH/lqS4Vi4jNORR7BOjV7Lk+kTtx9xkuHOZj+ 8AEg== 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 gt31-20020a1709072d9f00b0078debc9d30fsi27473775ejc.45.2022.10.22.03.34.37; Sat, 22 Oct 2022 03:34:37 -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 31DB968BE70; Sat, 22 Oct 2022 13:34:24 +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 0FDF768BDAF for ; Sat, 22 Oct 2022 13:34:16 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id A93EC2404F5 for ; Sat, 22 Oct 2022 12:34:15 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id Z0mb7hQDXwe9 for ; Sat, 22 Oct 2022 12:34:13 +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 3A6BD2404F7 for ; Sat, 22 Oct 2022 12:34:13 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 332353A13E9 for ; Sat, 22 Oct 2022 12:34:04 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Sat, 22 Oct 2022 12:32:57 +0200 Message-Id: <20221022103257.15463-4-anton@khirnov.net> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221022103257.15463-1-anton@khirnov.net> References: <20221022103257.15463-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v4 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: jLDhkE0AJTYy Use that instead of the merged version. --- libavcodec/get_bits.h | 309 +++++++++--------------------------------- 1 file changed, 62 insertions(+), 247 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 992765dc92..a50469b427 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. * @@ -58,12 +57,55 @@ #define CACHED_BITSTREAM_READER 0 #endif -typedef struct GetBitContext { - const uint8_t *buffer, *buffer_end; #if CACHED_BITSTREAM_READER - uint64_t cache; - unsigned bits_left; + +// we always want the LE implementation, to provide get_bits_le() +#define BITSTREAM_LE + +#ifndef BITSTREAM_READER_LE +# define BITSTREAM_BE +# define BITSTREAM_DEFAULT_BE #endif + +#include "bitstream.h" + +#undef BITSTREAM_LE +#undef BITSTREAM_BE +#undef BITSTREAM_DEFAULT_BE + +typedef BitstreamContext GetBitContext; + +#define get_bits_count bits_tell +#define get_bits_left bits_left +#define skip_bits_long bits_skip +#define skip_bits bits_skip +#define get_bits bits_read_nz +#define get_bitsz bits_read +#define get_bits_long bits_read +#define get_bits1 bits_read_bit +#define get_bits64 bits_read_64 +#define get_xbits bits_read_xbits +#define get_sbits bits_read_signed +#define get_sbits_long bits_read_signed +#define show_bits bits_peek +#define show_bits_long bits_peek +#define init_get_bits bits_init +#define init_get_bits8 bits_init8 +#define align_get_bits bits_align +#define get_vlc2 bits_read_vlc + +#define init_get_bits8_le(s, buffer, byte_size) bits_init8_le((BitstreamContextLE*)s, buffer, byte_size) +#define get_bits_le(s, n) bits_read_le((BitstreamContextLE*)s, n) + +#define show_bits1(s) bits_peek(s, 1) +#define skip_bits1(s) bits_skip(s, 1) + +#define skip_1stop_8data_bits bits_skip_1stop_8data + +#else // CACHED_BITSTREAM_READER + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; int index; int size_in_bits; int size_in_bits_plus8; @@ -120,16 +162,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 @@ -214,73 +252,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, @@ -290,28 +267,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). @@ -320,13 +281,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); @@ -337,10 +291,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; @@ -354,22 +306,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; } @@ -379,32 +325,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; } @@ -419,16 +345,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); @@ -437,7 +353,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 } /** @@ -446,71 +361,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 @@ -527,7 +393,6 @@ static inline unsigned int get_bits1(GetBitContext *s) s->index = index; return result; -#endif } static inline unsigned int show_bits1(GetBitContext *s) @@ -548,10 +413,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 { @@ -563,7 +424,6 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n) return ret | get_bits(s, n - 16); #endif } -#endif } /** @@ -609,8 +469,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; @@ -629,33 +498,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 @@ -677,7 +522,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) @@ -762,19 +607,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 @@ -787,24 +619,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); @@ -815,7 +629,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) @@ -855,4 +668,6 @@ static inline int skip_1stop_8data_bits(GetBitContext *gb) return 0; } +#endif // CACHED_BITSTREAM_READER + #endif /* AVCODEC_GET_BITS_H */