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 left_;                  // how many unused bits (negated)
34} VP8BitReader;
35
36// Initialize the bit reader and the boolean decoder.
37void VP8Init(VP8BitReader* const br, const uint8_t* buf, uint32_t size);
38
39// return the next value made of 'num_bits' bits
40uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
41static inline uint32_t VP8Get(VP8BitReader* const br) {
42  return VP8GetValue(br, 1);
43}
44
45// return the next value with sign-extension.
46int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
47
48// Read a bit with proba 'prob'. Speed-critical function!
49extern const uint8_t kVP8Log2Range[128];
50extern const uint8_t kVP8NewRange[128];
51static inline uint32_t VP8GetByte(VP8BitReader* const br) {
52  assert(br);
53  if (br->buf_ < br->buf_end_) {
54    assert(br->buf_);
55    return *br->buf_++;
56  }
57  br->eof_ = 1;
58  return 0x80;
59}
60
61static inline void VP8Shift(VP8BitReader* const br) {
62  // range_ is in [0..127] interval here.
63  const int shift = kVP8Log2Range[br->range_];
64  br->range_ = kVP8NewRange[br->range_];
65  br->value_ <<= shift;
66  br->left_ += shift;
67  if (br->left_ > 0) {
68    br->value_ |= VP8GetByte(br) << br->left_;
69    br->left_ -= 8;
70  }
71}
72
73static inline uint32_t VP8GetBit(VP8BitReader* const br, int prob) {
74  const uint32_t split = (br->range_ * prob) >> 8;
75  const uint32_t bit = ((br->value_ >> 8) > split);
76  if (bit) {
77    br->range_ -= split + 1;
78    br->value_ -= (split + 1) << 8;
79  } else {
80    br->range_ = split;
81  }
82  if (br->range_ < 0x7f) {
83    VP8Shift(br);
84  }
85  return bit;
86}
87
88static inline int VP8GetSigned(VP8BitReader* const br, int v) {
89  const uint32_t split = br->range_ >> 1;
90  const uint32_t bit = ((br->value_ >> 8) > split);
91  if (bit) {
92    br->range_ -= split + 1;
93    br->value_ -= (split + 1) << 8;
94    v = -v;
95  } else {
96    br->range_ = split;
97  }
98  VP8Shift(br);
99  return v;
100}
101
102#if defined(__cplusplus) || defined(c_plusplus)
103}    // extern "C"
104#endif
105
106#endif  // WEBP_DEC_BITS_H_
107