Path: blob/master/thirdparty/libwebp/src/utils/bit_reader_utils.c
9912 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 decoder non-inlined methods10//11// Author: Skal ([email protected])1213#ifdef HAVE_CONFIG_H14#include "src/webp/config.h"15#endif1617#include "src/dsp/cpu.h"18#include "src/utils/bit_reader_inl_utils.h"19#include "src/utils/utils.h"2021//------------------------------------------------------------------------------22// VP8BitReader2324void VP8BitReaderSetBuffer(VP8BitReader* const br,25const uint8_t* const start,26size_t size) {27br->buf_ = start;28br->buf_end_ = start + size;29br->buf_max_ =30(size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 131: start;32}3334void VP8InitBitReader(VP8BitReader* const br,35const uint8_t* const start, size_t size) {36assert(br != NULL);37assert(start != NULL);38assert(size < (1u << 31)); // limit ensured by format and upstream checks39br->range_ = 255 - 1;40br->value_ = 0;41br->bits_ = -8; // to load the very first 8bits42br->eof_ = 0;43VP8BitReaderSetBuffer(br, start, size);44VP8LoadNewBytes(br);45}4647void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {48if (br->buf_ != NULL) {49br->buf_ += offset;50br->buf_end_ += offset;51br->buf_max_ += offset;52}53}5455const uint8_t kVP8Log2Range[128] = {567, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,573, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,582, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,592, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,601, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,611, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,621, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,64065};6667// range = ((range - 1) << kVP8Log2Range[range]) + 168const uint8_t kVP8NewRange[128] = {69127, 127, 191, 127, 159, 191, 223, 127,70143, 159, 175, 191, 207, 223, 239, 127,71135, 143, 151, 159, 167, 175, 183, 191,72199, 207, 215, 223, 231, 239, 247, 127,73131, 135, 139, 143, 147, 151, 155, 159,74163, 167, 171, 175, 179, 183, 187, 191,75195, 199, 203, 207, 211, 215, 219, 223,76227, 231, 235, 239, 243, 247, 251, 127,77129, 131, 133, 135, 137, 139, 141, 143,78145, 147, 149, 151, 153, 155, 157, 159,79161, 163, 165, 167, 169, 171, 173, 175,80177, 179, 181, 183, 185, 187, 189, 191,81193, 195, 197, 199, 201, 203, 205, 207,82209, 211, 213, 215, 217, 219, 221, 223,83225, 227, 229, 231, 233, 235, 237, 239,84241, 243, 245, 247, 249, 251, 253, 12785};8687void VP8LoadFinalBytes(VP8BitReader* const br) {88assert(br != NULL && br->buf_ != NULL);89// Only read 8bits at a time90if (br->buf_ < br->buf_end_) {91br->bits_ += 8;92br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);93} else if (!br->eof_) {94br->value_ <<= 8;95br->bits_ += 8;96br->eof_ = 1;97} else {98br->bits_ = 0; // This is to avoid undefined behaviour with shifts.99}100}101102//------------------------------------------------------------------------------103// Higher-level calls104105uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) {106uint32_t v = 0;107while (bits-- > 0) {108v |= VP8GetBit(br, 0x80, label) << bits;109}110return v;111}112113int32_t VP8GetSignedValue(VP8BitReader* const br, int bits,114const char label[]) {115const int value = VP8GetValue(br, bits, label);116return VP8Get(br, label) ? -value : value;117}118119//------------------------------------------------------------------------------120// VP8LBitReader121122#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.123124#if defined(__arm__) || defined(_M_ARM) || WEBP_AARCH64 || \125defined(__i386__) || defined(_M_IX86) || \126defined(__x86_64__) || defined(_M_X64) || \127defined(__wasm__)128#define VP8L_USE_FAST_LOAD129#endif130131static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {1320,1330x000001, 0x000003, 0x000007, 0x00000f,1340x00001f, 0x00003f, 0x00007f, 0x0000ff,1350x0001ff, 0x0003ff, 0x0007ff, 0x000fff,1360x001fff, 0x003fff, 0x007fff, 0x00ffff,1370x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,1380x1fffff, 0x3fffff, 0x7fffff, 0xffffff139};140141void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,142size_t length) {143size_t i;144vp8l_val_t value = 0;145assert(br != NULL);146assert(start != NULL);147assert(length < 0xfffffff8u); // can't happen with a RIFF chunk.148149br->len_ = length;150br->val_ = 0;151br->bit_pos_ = 0;152br->eos_ = 0;153154if (length > sizeof(br->val_)) {155length = sizeof(br->val_);156}157for (i = 0; i < length; ++i) {158value |= (vp8l_val_t)start[i] << (8 * i);159}160br->val_ = value;161br->pos_ = length;162br->buf_ = start;163}164165void VP8LBitReaderSetBuffer(VP8LBitReader* const br,166const uint8_t* const buf, size_t len) {167assert(br != NULL);168assert(buf != NULL);169assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.170br->buf_ = buf;171br->len_ = len;172// pos_ > len_ should be considered a param error.173br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);174}175176static void VP8LSetEndOfStream(VP8LBitReader* const br) {177br->eos_ = 1;178br->bit_pos_ = 0; // To avoid undefined behaviour with shifts.179}180181// If not at EOS, reload up to VP8L_LBITS byte-by-byte182static void ShiftBytes(VP8LBitReader* const br) {183while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {184br->val_ >>= 8;185br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);186++br->pos_;187br->bit_pos_ -= 8;188}189if (VP8LIsEndOfStream(br)) {190VP8LSetEndOfStream(br);191}192}193194void VP8LDoFillBitWindow(VP8LBitReader* const br) {195assert(br->bit_pos_ >= VP8L_WBITS);196#if defined(VP8L_USE_FAST_LOAD)197if (br->pos_ + sizeof(br->val_) < br->len_) {198br->val_ >>= VP8L_WBITS;199br->bit_pos_ -= VP8L_WBITS;200br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<201(VP8L_LBITS - VP8L_WBITS);202br->pos_ += VP8L_LOG8_WBITS;203return;204}205#endif206ShiftBytes(br); // Slow path.207}208209uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {210assert(n_bits >= 0);211// Flag an error if end_of_stream or n_bits is more than allowed limit.212if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {213const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];214const int new_bits = br->bit_pos_ + n_bits;215br->bit_pos_ = new_bits;216ShiftBytes(br);217return val;218} else {219VP8LSetEndOfStream(br);220return 0;221}222}223224//------------------------------------------------------------------------------225// Bit-tracing tool226227#if (BITTRACE > 0)228229#include <stdlib.h> // for atexit()230#include <stdio.h>231#include <string.h>232233#define MAX_NUM_LABELS 32234static struct {235const char* label;236int size;237int count;238} kLabels[MAX_NUM_LABELS];239240static int last_label = 0;241static int last_pos = 0;242static const uint8_t* buf_start = NULL;243static int init_done = 0;244245static void PrintBitTraces(void) {246int i;247int scale = 1;248int total = 0;249const char* units = "bits";250#if (BITTRACE == 2)251scale = 8;252units = "bytes";253#endif254for (i = 0; i < last_label; ++i) total += kLabels[i].size;255if (total < 1) total = 1; // avoid rounding errors256printf("=== Bit traces ===\n");257for (i = 0; i < last_label; ++i) {258const int skip = 16 - (int)strlen(kLabels[i].label);259const int value = (kLabels[i].size + scale - 1) / scale;260assert(skip > 0);261printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n",262kLabels[i].label, skip, "", value, units,263100.f * kLabels[i].size / total,264kLabels[i].count);265}266total = (total + scale - 1) / scale;267printf("Total: %d %s\n", total, units);268}269270void BitTrace(const struct VP8BitReader* const br, const char label[]) {271int i, pos;272if (!init_done) {273memset(kLabels, 0, sizeof(kLabels));274atexit(PrintBitTraces);275buf_start = br->buf_;276init_done = 1;277}278pos = (int)(br->buf_ - buf_start) * 8 - br->bits_;279// if there's a too large jump, we've changed partition -> reset counter280if (abs(pos - last_pos) > 32) {281buf_start = br->buf_;282pos = 0;283last_pos = 0;284}285if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f];286for (i = 0; i < last_label; ++i) {287if (!strcmp(label, kLabels[i].label)) break;288}289if (i == MAX_NUM_LABELS) abort(); // overflow!290kLabels[i].label = label;291kLabels[i].size += pos - last_pos;292kLabels[i].count += 1;293if (i == last_label) ++last_label;294last_pos = pos;295}296297#endif // BITTRACE > 0298299//------------------------------------------------------------------------------300301302