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)
19 extern "C" {
20 #endif
21
22 //-----------------------------------------------------------------------------
23 // Bitreader and code-tree reader
24
25 typedef 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.
37 void 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
41 uint32_t VP8GetValue(VP8BitReader* const br, int num_bits);
VP8Get(VP8BitReader * const br)42 static inline uint32_t VP8Get(VP8BitReader* const br) {
43 return VP8GetValue(br, 1);
44 }
45
46 // return the next value with sign-extension.
47 int32_t VP8GetSignedValue(VP8BitReader* const br, int num_bits);
48
49 // Read a bit with proba 'prob'. Speed-critical function!
50 extern const uint8_t kVP8Log2Range[128];
51 extern const uint8_t kVP8NewRange[128];
VP8GetByte(VP8BitReader * const br)52 static 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
VP8BitUpdate(VP8BitReader * const br,uint32_t split)62 static 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
VP8Shift(VP8BitReader * const br)80 static 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
VP8GetBit(VP8BitReader * const br,int prob)88 static 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
VP8GetSigned(VP8BitReader * const br,int v)97 static 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