1// Copyright 2010 Google Inc.
2//
3// This code is licensed under the same terms as WebM:
4//  Software License Agreement:  http://www.webmproject.org/license/software/
5//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
6// -----------------------------------------------------------------------------
7//
8// Boolean decoder
9//
10// Author: Skal (pascal.massimino@gmail.com)
11
12#ifndef WEBP_DEC_BITS_H_
13#define WEBP_DEC_BITS_H_
14
15#include <assert.h>
16#include "webp/decode_vp8.h"
17
18#if defined(__cplusplus) || defined(c_plusplus)
19extern "C" {
20#endif
21
22//-----------------------------------------------------------------------------
23// Bitreader and code-tree reader
24
25typedef struct {
26  const uint8_t* buf_;        // next byte to be read
27  const uint8_t* buf_end_;    // end of read buffer
28  int eof_;                   // true if input is exhausted
29
30  // boolean decoder
31  uint32_t range_;            // current range minus 1. In [127, 254] interval.
32  uint32_t value_;            // current value
33  int missing_;               // number of missing bits in value_ (8bit)
34} VP8BitReader;
35
36// Initialize the bit reader and the boolean decoder.
37void VP8InitBitReader(VP8BitReader* const br,
38                      const uint8_t* const start, const uint8_t* const end);
39
40// return the next value made of 'num_bits' bits
41uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
42static inline uint32_t VP8Get(VP8BitReader* const br) {
43  return VP8GetValue(br, 1);
44}
45
46// return the next value with sign-extension.
47int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
48
49// Read a bit with proba 'prob'. Speed-critical function!
50extern const uint8_t kVP8Log2Range[128];
51extern const uint8_t kVP8NewRange[128];
52static inline uint32_t VP8GetByte(VP8BitReader* const br) {
53  assert(br);
54  if (br->buf_ < br->buf_end_) {
55    assert(br->buf_);
56    return *br->buf_++;
57  }
58  br->eof_ = 1;
59  return 0xff;
60}
61
62static inline uint32_t VP8BitUpdate(VP8BitReader* const br, uint32_t split) {
63  uint32_t bit;
64  const uint32_t value_split = (split + 1) << 8;
65  // Make sure we have a least 8 bits in 'value_'
66  if (br->missing_ > 0) {
67    br->value_ |= VP8GetByte(br) << br->missing_;
68    br->missing_ -= 8;
69  }
70  bit = (br->value_ >= value_split);
71  if (bit) {
72    br->range_ -= split + 1;
73    br->value_ -= value_split;
74  } else {
75    br->range_ = split;
76  }
77  return bit;
78}
79
80static inline void VP8Shift(VP8BitReader* const br) {
81  // range_ is in [0..127] interval here.
82  const int shift = kVP8Log2Range[br->range_];
83  br->range_ = kVP8NewRange[br->range_];
84  br->value_ <<= shift;
85  br->missing_ += shift;
86}
87
88static inline uint32_t VP8GetBit(VP8BitReader* const br, int prob) {
89  const uint32_t split = (br->range_ * prob) >> 8;
90  const uint32_t bit = VP8BitUpdate(br, split);
91  if (br->range_ < 0x7f) {
92    VP8Shift(br);
93  }
94  return bit;
95}
96
97static inline int VP8GetSigned(VP8BitReader* const br, int v) {
98  const uint32_t split = br->range_ >> 1;
99  const uint32_t bit = VP8BitUpdate(br, split);
100  VP8Shift(br);
101  return bit ? -v : v;
102}
103
104#if defined(__cplusplus) || defined(c_plusplus)
105}    // extern "C"
106#endif
107
108#endif  // WEBP_DEC_BITS_H_
109