• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 // Boolean decoder non-inlined methods
11 //
12 // Author: Skal (pascal.massimino@gmail.com)
13 
14 #ifdef HAVE_CONFIG_H
15 #include "../webp/config.h"
16 #endif
17 
18 #include "./bit_reader_inl.h"
19 
20 //------------------------------------------------------------------------------
21 // VP8BitReader
22 
VP8BitReaderSetBuffer(VP8BitReader * const br,const uint8_t * const start,size_t size)23 void VP8BitReaderSetBuffer(VP8BitReader* const br,
24                            const uint8_t* const start,
25                            size_t size) {
26   br->buf_     = start;
27   br->buf_end_ = start + size;
28   br->buf_max_ =
29       (size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1
30                                : start;
31 }
32 
VP8InitBitReader(VP8BitReader * const br,const uint8_t * const start,size_t size)33 void VP8InitBitReader(VP8BitReader* const br,
34                       const uint8_t* const start, size_t size) {
35   assert(br != NULL);
36   assert(start != NULL);
37   assert(size < (1u << 31));   // limit ensured by format and upstream checks
38   br->range_   = 255 - 1;
39   br->value_   = 0;
40   br->bits_    = -8;   // to load the very first 8bits
41   br->eof_     = 0;
42   VP8BitReaderSetBuffer(br, start, size);
43   VP8LoadNewBytes(br);
44 }
45 
VP8RemapBitReader(VP8BitReader * const br,ptrdiff_t offset)46 void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
47   if (br->buf_ != NULL) {
48     br->buf_ += offset;
49     br->buf_end_ += offset;
50     br->buf_max_ += offset;
51   }
52 }
53 
54 const uint8_t kVP8Log2Range[128] = {
55      7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
56   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
57   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
58   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
59   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
60   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
61   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
62   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
63   0
64 };
65 
66 // range = ((range - 1) << kVP8Log2Range[range]) + 1
67 const uint8_t kVP8NewRange[128] = {
68   127, 127, 191, 127, 159, 191, 223, 127,
69   143, 159, 175, 191, 207, 223, 239, 127,
70   135, 143, 151, 159, 167, 175, 183, 191,
71   199, 207, 215, 223, 231, 239, 247, 127,
72   131, 135, 139, 143, 147, 151, 155, 159,
73   163, 167, 171, 175, 179, 183, 187, 191,
74   195, 199, 203, 207, 211, 215, 219, 223,
75   227, 231, 235, 239, 243, 247, 251, 127,
76   129, 131, 133, 135, 137, 139, 141, 143,
77   145, 147, 149, 151, 153, 155, 157, 159,
78   161, 163, 165, 167, 169, 171, 173, 175,
79   177, 179, 181, 183, 185, 187, 189, 191,
80   193, 195, 197, 199, 201, 203, 205, 207,
81   209, 211, 213, 215, 217, 219, 221, 223,
82   225, 227, 229, 231, 233, 235, 237, 239,
83   241, 243, 245, 247, 249, 251, 253, 127
84 };
85 
VP8LoadFinalBytes(VP8BitReader * const br)86 void VP8LoadFinalBytes(VP8BitReader* const br) {
87   assert(br != NULL && br->buf_ != NULL);
88   // Only read 8bits at a time
89   if (br->buf_ < br->buf_end_) {
90     br->bits_ += 8;
91     br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);
92   } else if (!br->eof_) {
93     br->value_ <<= 8;
94     br->bits_ += 8;
95     br->eof_ = 1;
96   } else {
97     br->bits_ = 0;  // This is to avoid undefined behaviour with shifts.
98   }
99 }
100 
101 //------------------------------------------------------------------------------
102 // Higher-level calls
103 
VP8GetValue(VP8BitReader * const br,int bits)104 uint32_t VP8GetValue(VP8BitReader* const br, int bits) {
105   uint32_t v = 0;
106   while (bits-- > 0) {
107     v |= VP8GetBit(br, 0x80) << bits;
108   }
109   return v;
110 }
111 
VP8GetSignedValue(VP8BitReader * const br,int bits)112 int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) {
113   const int value = VP8GetValue(br, bits);
114   return VP8Get(br) ? -value : value;
115 }
116 
117 //------------------------------------------------------------------------------
118 // VP8LBitReader
119 
120 #define VP8L_LOG8_WBITS 4  // Number of bytes needed to store VP8L_WBITS bits.
121 
122 #if !defined(WEBP_FORCE_ALIGNED) && \
123     (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
124      defined(__i386__) || defined(_M_IX86) || \
125      defined(__x86_64__) || defined(_M_X64))
126 #define VP8L_USE_UNALIGNED_LOAD
127 #endif
128 
129 static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {
130   0,
131   0x000001, 0x000003, 0x000007, 0x00000f,
132   0x00001f, 0x00003f, 0x00007f, 0x0000ff,
133   0x0001ff, 0x0003ff, 0x0007ff, 0x000fff,
134   0x001fff, 0x003fff, 0x007fff, 0x00ffff,
135   0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,
136   0x1fffff, 0x3fffff, 0x7fffff, 0xffffff
137 };
138 
VP8LInitBitReader(VP8LBitReader * const br,const uint8_t * const start,size_t length)139 void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
140                        size_t length) {
141   size_t i;
142   vp8l_val_t value = 0;
143   assert(br != NULL);
144   assert(start != NULL);
145   assert(length < 0xfffffff8u);   // can't happen with a RIFF chunk.
146 
147   br->len_ = length;
148   br->val_ = 0;
149   br->bit_pos_ = 0;
150   br->eos_ = 0;
151 
152   if (length > sizeof(br->val_)) {
153     length = sizeof(br->val_);
154   }
155   for (i = 0; i < length; ++i) {
156     value |= (vp8l_val_t)start[i] << (8 * i);
157   }
158   br->val_ = value;
159   br->pos_ = length;
160   br->buf_ = start;
161 }
162 
VP8LBitReaderSetBuffer(VP8LBitReader * const br,const uint8_t * const buf,size_t len)163 void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
164                             const uint8_t* const buf, size_t len) {
165   assert(br != NULL);
166   assert(buf != NULL);
167   assert(len < 0xfffffff8u);   // can't happen with a RIFF chunk.
168   br->buf_ = buf;
169   br->len_ = len;
170   // pos_ > len_ should be considered a param error.
171   br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);
172 }
173 
VP8LSetEndOfStream(VP8LBitReader * const br)174 static void VP8LSetEndOfStream(VP8LBitReader* const br) {
175   br->eos_ = 1;
176   br->bit_pos_ = 0;  // To avoid undefined behaviour with shifts.
177 }
178 
179 // If not at EOS, reload up to VP8L_LBITS byte-by-byte
ShiftBytes(VP8LBitReader * const br)180 static void ShiftBytes(VP8LBitReader* const br) {
181   while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
182     br->val_ >>= 8;
183     br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
184     ++br->pos_;
185     br->bit_pos_ -= 8;
186   }
187   if (VP8LIsEndOfStream(br)) {
188     VP8LSetEndOfStream(br);
189   }
190 }
191 
VP8LDoFillBitWindow(VP8LBitReader * const br)192 void VP8LDoFillBitWindow(VP8LBitReader* const br) {
193   assert(br->bit_pos_ >= VP8L_WBITS);
194   // TODO(jzern): given the fixed read size it may be possible to force
195   //              alignment in this block.
196 #if defined(VP8L_USE_UNALIGNED_LOAD)
197   if (br->pos_ + sizeof(br->val_) < br->len_) {
198     br->val_ >>= VP8L_WBITS;
199     br->bit_pos_ -= VP8L_WBITS;
200     // The expression below needs a little-endian arch to work correctly.
201     // This gives a large speedup for decoding speed.
202     br->val_ |= (vp8l_val_t)WebPMemToUint32(br->buf_ + br->pos_) <<
203                 (VP8L_LBITS - VP8L_WBITS);
204     br->pos_ += VP8L_LOG8_WBITS;
205     return;
206   }
207 #endif
208   ShiftBytes(br);       // Slow path.
209 }
210 
VP8LReadBits(VP8LBitReader * const br,int n_bits)211 uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
212   assert(n_bits >= 0);
213   // Flag an error if end_of_stream or n_bits is more than allowed limit.
214   if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {
215     const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];
216     const int new_bits = br->bit_pos_ + n_bits;
217     br->bit_pos_ = new_bits;
218     ShiftBytes(br);
219     return val;
220   } else {
221     VP8LSetEndOfStream(br);
222     return 0;
223   }
224 }
225 
226 //------------------------------------------------------------------------------
227