Path: blob/master/thirdparty/libwebp/src/utils/bit_reader_utils.h
20837 views
// Copyright 2010 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// Boolean decoder10//11// Author: Skal ([email protected])12// Vikas Arora ([email protected])1314#ifndef WEBP_UTILS_BIT_READER_UTILS_H_15#define WEBP_UTILS_BIT_READER_UTILS_H_1617#include <assert.h>18#include <stddef.h>1920#ifdef _MSC_VER21#include <stdlib.h> // _byteswap_ulong22#endif23#include "src/dsp/cpu.h"24#include "src/webp/types.h"2526// Warning! This macro triggers quite some MACRO wizardry around func signature!27#if !defined(BITTRACE)28#define BITTRACE 0 // 0 = off, 1 = print bits, 2 = print bytes29#endif3031#if (BITTRACE > 0)32struct VP8BitReader;33extern void BitTrace(const struct VP8BitReader* const br, const char label[]);34#define BT_TRACK(br) BitTrace(br, label)35#define VP8Get(BR, L) VP8GetValue(BR, 1, L)36#else37#define BT_TRACK(br)38// We'll REMOVE the 'const char label[]' from all signatures and calls (!!):39#define VP8GetValue(BR, N, L) VP8GetValue(BR, N)40#define VP8Get(BR, L) VP8GetValue(BR, 1, L)41#define VP8GetSignedValue(BR, N, L) VP8GetSignedValue(BR, N)42#define VP8GetBit(BR, P, L) VP8GetBit(BR, P)43#define VP8GetBitAlt(BR, P, L) VP8GetBitAlt(BR, P)44#define VP8GetSigned(BR, V, L) VP8GetSigned(BR, V)45#endif4647#ifdef __cplusplus48extern "C" {49#endif5051// The Boolean decoder needs to maintain infinite precision on the 'value'52// field. However, since 'range' is only 8bit, we only need an active window of53// 8 bits for 'value". Left bits (MSB) gets zeroed and shifted away when54// 'value' falls below 128, 'range' is updated, and fresh bits read from the55// bitstream are brought in as LSB. To avoid reading the fresh bits one by one56// (slow), we cache BITS of them ahead. The total of (BITS + 8) bits must fit57// into a natural register (with type bit_t). To fetch BITS bits from bitstream58// we use a type lbit_t.59//60// BITS can be any multiple of 8 from 8 to 56 (inclusive).61// Pick values that fit natural register size.6263#if defined(__i386__) || defined(_M_IX86) // x86 32bit64#define BITS 2465#elif defined(__x86_64__) || defined(_M_X64) // x86 64bit66#define BITS 5667#elif defined(__arm__) || defined(_M_ARM) // ARM68#define BITS 2469#elif WEBP_AARCH64 // ARM 64bit70#define BITS 5671#elif defined(__mips__) // MIPS72#define BITS 2473#elif defined(__wasm__) // WASM74#define BITS 5675#else // reasonable default76#define BITS 2477#endif7879//------------------------------------------------------------------------------80// Derived types and constants:81// bit_t = natural register type for storing 'value' (which is BITS+8 bits)82// range_t = register for 'range' (which is 8bits only)8384#if (BITS > 24)85typedef uint64_t bit_t;86#else87typedef uint32_t bit_t;88#endif8990typedef uint32_t range_t;9192//------------------------------------------------------------------------------93// Bitreader9495typedef struct VP8BitReader VP8BitReader;96struct VP8BitReader {97// boolean decoder (keep the field ordering as is!)98bit_t value; // current value99range_t range; // current range minus 1. In [127, 254] interval.100int bits; // number of valid bits left101// read buffer102const uint8_t* buf; // next byte to be read103const uint8_t* buf_end; // end of read buffer104const uint8_t* buf_max; // max packed-read position on buffer105int eof; // true if input is exhausted106};107108// Initialize the bit reader and the boolean decoder.109void VP8InitBitReader(VP8BitReader* const br,110const uint8_t* const start, size_t size);111// Sets the working read buffer.112void VP8BitReaderSetBuffer(VP8BitReader* const br,113const uint8_t* const start, size_t size);114115// Update internal pointers to displace the byte buffer by the116// relative offset 'offset'.117void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset);118119// return the next value made of 'num_bits' bits120uint32_t VP8GetValue(VP8BitReader* const br, int num_bits, const char label[]);121122// return the next value with sign-extension.123int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits,124const char label[]);125126// bit_reader_inl.h will implement the following methods:127// static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob, ...)128// static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v, ...)129// and should be included by the .c files that actually need them.130// This is to avoid recompiling the whole library whenever this file is touched,131// and also allowing platform-specific ad-hoc hacks.132133// -----------------------------------------------------------------------------134// Bitreader for lossless format135136// maximum number of bits (inclusive) the bit-reader can handle:137#define VP8L_MAX_NUM_BIT_READ 24138139#define VP8L_LBITS 64 // Number of bits prefetched (= bit-size of vp8l_val_t).140#define VP8L_WBITS 32 // Minimum number of bytes ready after VP8LFillBitWindow.141142typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit.143144typedef struct {145vp8l_val_t val; // pre-fetched bits146const uint8_t* buf; // input byte buffer147size_t len; // buffer length148size_t pos; // byte position in buf149int bit_pos; // current bit-reading position in val150int eos; // true if a bit was read past the end of buffer151} VP8LBitReader;152153void VP8LInitBitReader(VP8LBitReader* const br,154const uint8_t* const start,155size_t length);156157// Sets a new data buffer.158void VP8LBitReaderSetBuffer(VP8LBitReader* const br,159const uint8_t* const buffer, size_t length);160161// Reads the specified number of bits from read buffer.162// Flags an error in case end_of_stream or n_bits is more than the allowed limit163// of VP8L_MAX_NUM_BIT_READ (inclusive).164// Flags 'eos' if this read attempt is going to cross the read buffer.165uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits);166167// Return the prefetched bits, so they can be looked up.168static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) {169return (uint32_t)(br->val >> (br->bit_pos & (VP8L_LBITS - 1)));170}171172// Returns true if there was an attempt at reading bit past the end of173// the buffer. Doesn't set br->eos flag.174static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) {175assert(br->pos <= br->len);176return br->eos || ((br->pos == br->len) && (br->bit_pos > VP8L_LBITS));177}178179// For jumping over a number of bits in the bit stream when accessed with180// VP8LPrefetchBits and VP8LFillBitWindow.181// This function does *not* set br->eos, since it's speed-critical.182// Use with extreme care!183static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) {184br->bit_pos = val;185}186187// Advances the read buffer by 4 bytes to make room for reading next 32 bits.188// Speed critical, but infrequent part of the code can be non-inlined.189extern void VP8LDoFillBitWindow(VP8LBitReader* const br);190static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {191if (br->bit_pos >= VP8L_WBITS) VP8LDoFillBitWindow(br);192}193194#ifdef __cplusplus195} // extern "C"196#endif197198#endif // WEBP_UTILS_BIT_READER_UTILS_H_199200201