Blame src/utils/bit_reader_utils.c

Packit 9c6abc
// Copyright 2010 Google Inc. All Rights Reserved.
Packit 9c6abc
//
Packit 9c6abc
// Use of this source code is governed by a BSD-style license
Packit 9c6abc
// that can be found in the COPYING file in the root of the source
Packit 9c6abc
// tree. An additional intellectual property rights grant can be found
Packit 9c6abc
// in the file PATENTS. All contributing project authors may
Packit 9c6abc
// be found in the AUTHORS file in the root of the source tree.
Packit 9c6abc
// -----------------------------------------------------------------------------
Packit 9c6abc
//
Packit 9c6abc
// Boolean decoder non-inlined methods
Packit 9c6abc
//
Packit 9c6abc
// Author: Skal (pascal.massimino@gmail.com)
Packit 9c6abc
Packit 9c6abc
#ifdef HAVE_CONFIG_H
Packit 9c6abc
#include "src/webp/config.h"
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
#include "src/utils/bit_reader_inl_utils.h"
Packit 9c6abc
#include "src/utils/utils.h"
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// VP8BitReader
Packit 9c6abc
Packit 9c6abc
void VP8BitReaderSetBuffer(VP8BitReader* const br,
Packit 9c6abc
                           const uint8_t* const start,
Packit 9c6abc
                           size_t size) {
Packit 9c6abc
  br->buf_     = start;
Packit 9c6abc
  br->buf_end_ = start + size;
Packit 9c6abc
  br->buf_max_ =
Packit 9c6abc
      (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1
Packit 9c6abc
                               : start;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void VP8InitBitReader(VP8BitReader* const br,
Packit 9c6abc
                      const uint8_t* const start, size_t size) {
Packit 9c6abc
  assert(br != NULL);
Packit 9c6abc
  assert(start != NULL);
Packit 9c6abc
  assert(size < (1u << 31));   // limit ensured by format and upstream checks
Packit 9c6abc
  br->range_   = 255 - 1;
Packit 9c6abc
  br->value_   = 0;
Packit 9c6abc
  br->bits_    = -8;   // to load the very first 8bits
Packit 9c6abc
  br->eof_     = 0;
Packit 9c6abc
  VP8BitReaderSetBuffer(br, start, size);
Packit 9c6abc
  VP8LoadNewBytes(br);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
Packit 9c6abc
  if (br->buf_ != NULL) {
Packit 9c6abc
    br->buf_ += offset;
Packit 9c6abc
    br->buf_end_ += offset;
Packit 9c6abc
    br->buf_max_ += offset;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
const uint8_t kVP8Log2Range[128] = {
Packit 9c6abc
     7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
Packit 9c6abc
  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
Packit 9c6abc
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
Packit 9c6abc
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
Packit 9c6abc
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit 9c6abc
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit 9c6abc
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit 9c6abc
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit 9c6abc
  0
Packit 9c6abc
};
Packit 9c6abc
Packit 9c6abc
// range = ((range - 1) << kVP8Log2Range[range]) + 1
Packit 9c6abc
const uint8_t kVP8NewRange[128] = {
Packit 9c6abc
  127, 127, 191, 127, 159, 191, 223, 127,
Packit 9c6abc
  143, 159, 175, 191, 207, 223, 239, 127,
Packit 9c6abc
  135, 143, 151, 159, 167, 175, 183, 191,
Packit 9c6abc
  199, 207, 215, 223, 231, 239, 247, 127,
Packit 9c6abc
  131, 135, 139, 143, 147, 151, 155, 159,
Packit 9c6abc
  163, 167, 171, 175, 179, 183, 187, 191,
Packit 9c6abc
  195, 199, 203, 207, 211, 215, 219, 223,
Packit 9c6abc
  227, 231, 235, 239, 243, 247, 251, 127,
Packit 9c6abc
  129, 131, 133, 135, 137, 139, 141, 143,
Packit 9c6abc
  145, 147, 149, 151, 153, 155, 157, 159,
Packit 9c6abc
  161, 163, 165, 167, 169, 171, 173, 175,
Packit 9c6abc
  177, 179, 181, 183, 185, 187, 189, 191,
Packit 9c6abc
  193, 195, 197, 199, 201, 203, 205, 207,
Packit 9c6abc
  209, 211, 213, 215, 217, 219, 221, 223,
Packit 9c6abc
  225, 227, 229, 231, 233, 235, 237, 239,
Packit 9c6abc
  241, 243, 245, 247, 249, 251, 253, 127
Packit 9c6abc
};
Packit 9c6abc
Packit 9c6abc
void VP8LoadFinalBytes(VP8BitReader* const br) {
Packit 9c6abc
  assert(br != NULL && br->buf_ != NULL);
Packit 9c6abc
  // Only read 8bits at a time
Packit 9c6abc
  if (br->buf_ < br->buf_end_) {
Packit 9c6abc
    br->bits_ += 8;
Packit 9c6abc
    br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);
Packit 9c6abc
  } else if (!br->eof_) {
Packit 9c6abc
    br->value_ <<= 8;
Packit 9c6abc
    br->bits_ += 8;
Packit 9c6abc
    br->eof_ = 1;
Packit 9c6abc
  } else {
Packit 9c6abc
    br->bits_ = 0;  // This is to avoid undefined behaviour with shifts.
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Higher-level calls
Packit 9c6abc
Packit 9c6abc
uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
Packit 9c6abc
  uint32_t v = 0;
Packit 9c6abc
  while (bits-- > 0) {
Packit 9c6abc
    v |= VP8GetBit(br, 0x80) << bits;
Packit 9c6abc
  }
Packit 9c6abc
  return v;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
Packit 9c6abc
  const int value = VP8GetValue(br, bits);
Packit 9c6abc
  return VP8Get(br) ? -value : value;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// VP8LBitReader
Packit 9c6abc
Packit 9c6abc
#define VP8L_LOG8_WBITS 4  // Number of bytes needed to store VP8L_WBITS bits.
Packit 9c6abc
Packit 9c6abc
#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
Packit 9c6abc
    defined(__i386__) || defined(_M_IX86) || \
Packit 9c6abc
    defined(__x86_64__) || defined(_M_X64)
Packit 9c6abc
#define VP8L_USE_FAST_LOAD
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {
Packit 9c6abc
  0,
Packit 9c6abc
  0x000001, 0x000003, 0x000007, 0x00000f,
Packit 9c6abc
  0x00001f, 0x00003f, 0x00007f, 0x0000ff,
Packit 9c6abc
  0x0001ff, 0x0003ff, 0x0007ff, 0x000fff,
Packit 9c6abc
  0x001fff, 0x003fff, 0x007fff, 0x00ffff,
Packit 9c6abc
  0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,
Packit 9c6abc
  0x1fffff, 0x3fffff, 0x7fffff, 0xffffff
Packit 9c6abc
};
Packit 9c6abc
Packit 9c6abc
void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
Packit 9c6abc
                       size_t length) {
Packit 9c6abc
  size_t i;
Packit 9c6abc
  vp8l_val_t value = 0;
Packit 9c6abc
  assert(br != NULL);
Packit 9c6abc
  assert(start != NULL);
Packit 9c6abc
  assert(length < 0xfffffff8u);   // can't happen with a RIFF chunk.
Packit 9c6abc
Packit 9c6abc
  br->len_ = length;
Packit 9c6abc
  br->val_ = 0;
Packit 9c6abc
  br->bit_pos_ = 0;
Packit 9c6abc
  br->eos_ = 0;
Packit 9c6abc
Packit 9c6abc
  if (length > sizeof(br->val_)) {
Packit 9c6abc
    length = sizeof(br->val_);
Packit 9c6abc
  }
Packit 9c6abc
  for (i = 0; i < length; ++i) {
Packit 9c6abc
    value |= (vp8l_val_t)start[i] << (8 * i);
Packit 9c6abc
  }
Packit 9c6abc
  br->val_ = value;
Packit 9c6abc
  br->pos_ = length;
Packit 9c6abc
  br->buf_ = start;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
Packit 9c6abc
                            const uint8_t* const buf, size_t len) {
Packit 9c6abc
  assert(br != NULL);
Packit 9c6abc
  assert(buf != NULL);
Packit 9c6abc
  assert(len < 0xfffffff8u);   // can't happen with a RIFF chunk.
Packit 9c6abc
  br->buf_ = buf;
Packit 9c6abc
  br->len_ = len;
Packit 9c6abc
  // pos_ > len_ should be considered a param error.
Packit 9c6abc
  br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static void VP8LSetEndOfStream(VP8LBitReader* const br) {
Packit 9c6abc
  br->eos_ = 1;
Packit 9c6abc
  br->bit_pos_ = 0;  // To avoid undefined behaviour with shifts.
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
// If not at EOS, reload up to VP8L_LBITS byte-by-byte
Packit 9c6abc
static void ShiftBytes(VP8LBitReader* const br) {
Packit 9c6abc
  while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
Packit 9c6abc
    br->val_ >>= 8;
Packit 9c6abc
    br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
Packit 9c6abc
    ++br->pos_;
Packit 9c6abc
    br->bit_pos_ -= 8;
Packit 9c6abc
  }
Packit 9c6abc
  if (VP8LIsEndOfStream(br)) {
Packit 9c6abc
    VP8LSetEndOfStream(br);
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void VP8LDoFillBitWindow(VP8LBitReader* const br) {
Packit 9c6abc
  assert(br->bit_pos_ >= VP8L_WBITS);
Packit 9c6abc
#if defined(VP8L_USE_FAST_LOAD)
Packit 9c6abc
  if (br->pos_ + sizeof(br->val_) < br->len_) {
Packit 9c6abc
    br->val_ >>= VP8L_WBITS;
Packit 9c6abc
    br->bit_pos_ -= VP8L_WBITS;
Packit 9c6abc
    br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<
Packit 9c6abc
                (VP8L_LBITS - VP8L_WBITS);
Packit 9c6abc
    br->pos_ += VP8L_LOG8_WBITS;
Packit 9c6abc
    return;
Packit 9c6abc
  }
Packit 9c6abc
#endif
Packit 9c6abc
  ShiftBytes(br);       // Slow path.
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
Packit 9c6abc
  assert(n_bits >= 0);
Packit 9c6abc
  // Flag an error if end_of_stream or n_bits is more than allowed limit.
Packit 9c6abc
  if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {
Packit 9c6abc
    const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];
Packit 9c6abc
    const int new_bits = br->bit_pos_ + n_bits;
Packit 9c6abc
    br->bit_pos_ = new_bits;
Packit 9c6abc
    ShiftBytes(br);
Packit 9c6abc
    return val;
Packit 9c6abc
  } else {
Packit 9c6abc
    VP8LSetEndOfStream(br);
Packit 9c6abc
    return 0;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------