Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libwebp/src/utils/bit_reader_utils.c
9912 views
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 ([email protected])
13
14
#ifdef HAVE_CONFIG_H
15
#include "src/webp/config.h"
16
#endif
17
18
#include "src/dsp/cpu.h"
19
#include "src/utils/bit_reader_inl_utils.h"
20
#include "src/utils/utils.h"
21
22
//------------------------------------------------------------------------------
23
// VP8BitReader
24
25
void VP8BitReaderSetBuffer(VP8BitReader* const br,
26
const uint8_t* const start,
27
size_t size) {
28
br->buf_ = start;
29
br->buf_end_ = start + size;
30
br->buf_max_ =
31
(size >= sizeof(lbit_t)) ? start + size - sizeof(lbit_t) + 1
32
: start;
33
}
34
35
void VP8InitBitReader(VP8BitReader* const br,
36
const uint8_t* const start, size_t size) {
37
assert(br != NULL);
38
assert(start != NULL);
39
assert(size < (1u << 31)); // limit ensured by format and upstream checks
40
br->range_ = 255 - 1;
41
br->value_ = 0;
42
br->bits_ = -8; // to load the very first 8bits
43
br->eof_ = 0;
44
VP8BitReaderSetBuffer(br, start, size);
45
VP8LoadNewBytes(br);
46
}
47
48
void VP8RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
49
if (br->buf_ != NULL) {
50
br->buf_ += offset;
51
br->buf_end_ += offset;
52
br->buf_max_ += offset;
53
}
54
}
55
56
const uint8_t kVP8Log2Range[128] = {
57
7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
58
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
59
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
60
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
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
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
65
0
66
};
67
68
// range = ((range - 1) << kVP8Log2Range[range]) + 1
69
const uint8_t kVP8NewRange[128] = {
70
127, 127, 191, 127, 159, 191, 223, 127,
71
143, 159, 175, 191, 207, 223, 239, 127,
72
135, 143, 151, 159, 167, 175, 183, 191,
73
199, 207, 215, 223, 231, 239, 247, 127,
74
131, 135, 139, 143, 147, 151, 155, 159,
75
163, 167, 171, 175, 179, 183, 187, 191,
76
195, 199, 203, 207, 211, 215, 219, 223,
77
227, 231, 235, 239, 243, 247, 251, 127,
78
129, 131, 133, 135, 137, 139, 141, 143,
79
145, 147, 149, 151, 153, 155, 157, 159,
80
161, 163, 165, 167, 169, 171, 173, 175,
81
177, 179, 181, 183, 185, 187, 189, 191,
82
193, 195, 197, 199, 201, 203, 205, 207,
83
209, 211, 213, 215, 217, 219, 221, 223,
84
225, 227, 229, 231, 233, 235, 237, 239,
85
241, 243, 245, 247, 249, 251, 253, 127
86
};
87
88
void VP8LoadFinalBytes(VP8BitReader* const br) {
89
assert(br != NULL && br->buf_ != NULL);
90
// Only read 8bits at a time
91
if (br->buf_ < br->buf_end_) {
92
br->bits_ += 8;
93
br->value_ = (bit_t)(*br->buf_++) | (br->value_ << 8);
94
} else if (!br->eof_) {
95
br->value_ <<= 8;
96
br->bits_ += 8;
97
br->eof_ = 1;
98
} else {
99
br->bits_ = 0; // This is to avoid undefined behaviour with shifts.
100
}
101
}
102
103
//------------------------------------------------------------------------------
104
// Higher-level calls
105
106
uint32_t VP8GetValue(VP8BitReader* const br, int bits, const char label[]) {
107
uint32_t v = 0;
108
while (bits-- > 0) {
109
v |= VP8GetBit(br, 0x80, label) << bits;
110
}
111
return v;
112
}
113
114
int32_t VP8GetSignedValue(VP8BitReader* const br, int bits,
115
const char label[]) {
116
const int value = VP8GetValue(br, bits, label);
117
return VP8Get(br, label) ? -value : value;
118
}
119
120
//------------------------------------------------------------------------------
121
// VP8LBitReader
122
123
#define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
124
125
#if defined(__arm__) || defined(_M_ARM) || WEBP_AARCH64 || \
126
defined(__i386__) || defined(_M_IX86) || \
127
defined(__x86_64__) || defined(_M_X64) || \
128
defined(__wasm__)
129
#define VP8L_USE_FAST_LOAD
130
#endif
131
132
static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = {
133
0,
134
0x000001, 0x000003, 0x000007, 0x00000f,
135
0x00001f, 0x00003f, 0x00007f, 0x0000ff,
136
0x0001ff, 0x0003ff, 0x0007ff, 0x000fff,
137
0x001fff, 0x003fff, 0x007fff, 0x00ffff,
138
0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff,
139
0x1fffff, 0x3fffff, 0x7fffff, 0xffffff
140
};
141
142
void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start,
143
size_t length) {
144
size_t i;
145
vp8l_val_t value = 0;
146
assert(br != NULL);
147
assert(start != NULL);
148
assert(length < 0xfffffff8u); // can't happen with a RIFF chunk.
149
150
br->len_ = length;
151
br->val_ = 0;
152
br->bit_pos_ = 0;
153
br->eos_ = 0;
154
155
if (length > sizeof(br->val_)) {
156
length = sizeof(br->val_);
157
}
158
for (i = 0; i < length; ++i) {
159
value |= (vp8l_val_t)start[i] << (8 * i);
160
}
161
br->val_ = value;
162
br->pos_ = length;
163
br->buf_ = start;
164
}
165
166
void VP8LBitReaderSetBuffer(VP8LBitReader* const br,
167
const uint8_t* const buf, size_t len) {
168
assert(br != NULL);
169
assert(buf != NULL);
170
assert(len < 0xfffffff8u); // can't happen with a RIFF chunk.
171
br->buf_ = buf;
172
br->len_ = len;
173
// pos_ > len_ should be considered a param error.
174
br->eos_ = (br->pos_ > br->len_) || VP8LIsEndOfStream(br);
175
}
176
177
static void VP8LSetEndOfStream(VP8LBitReader* const br) {
178
br->eos_ = 1;
179
br->bit_pos_ = 0; // To avoid undefined behaviour with shifts.
180
}
181
182
// If not at EOS, reload up to VP8L_LBITS byte-by-byte
183
static void ShiftBytes(VP8LBitReader* const br) {
184
while (br->bit_pos_ >= 8 && br->pos_ < br->len_) {
185
br->val_ >>= 8;
186
br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
187
++br->pos_;
188
br->bit_pos_ -= 8;
189
}
190
if (VP8LIsEndOfStream(br)) {
191
VP8LSetEndOfStream(br);
192
}
193
}
194
195
void VP8LDoFillBitWindow(VP8LBitReader* const br) {
196
assert(br->bit_pos_ >= VP8L_WBITS);
197
#if defined(VP8L_USE_FAST_LOAD)
198
if (br->pos_ + sizeof(br->val_) < br->len_) {
199
br->val_ >>= VP8L_WBITS;
200
br->bit_pos_ -= VP8L_WBITS;
201
br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<
202
(VP8L_LBITS - VP8L_WBITS);
203
br->pos_ += VP8L_LOG8_WBITS;
204
return;
205
}
206
#endif
207
ShiftBytes(br); // Slow path.
208
}
209
210
uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
211
assert(n_bits >= 0);
212
// Flag an error if end_of_stream or n_bits is more than allowed limit.
213
if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) {
214
const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits];
215
const int new_bits = br->bit_pos_ + n_bits;
216
br->bit_pos_ = new_bits;
217
ShiftBytes(br);
218
return val;
219
} else {
220
VP8LSetEndOfStream(br);
221
return 0;
222
}
223
}
224
225
//------------------------------------------------------------------------------
226
// Bit-tracing tool
227
228
#if (BITTRACE > 0)
229
230
#include <stdlib.h> // for atexit()
231
#include <stdio.h>
232
#include <string.h>
233
234
#define MAX_NUM_LABELS 32
235
static struct {
236
const char* label;
237
int size;
238
int count;
239
} kLabels[MAX_NUM_LABELS];
240
241
static int last_label = 0;
242
static int last_pos = 0;
243
static const uint8_t* buf_start = NULL;
244
static int init_done = 0;
245
246
static void PrintBitTraces(void) {
247
int i;
248
int scale = 1;
249
int total = 0;
250
const char* units = "bits";
251
#if (BITTRACE == 2)
252
scale = 8;
253
units = "bytes";
254
#endif
255
for (i = 0; i < last_label; ++i) total += kLabels[i].size;
256
if (total < 1) total = 1; // avoid rounding errors
257
printf("=== Bit traces ===\n");
258
for (i = 0; i < last_label; ++i) {
259
const int skip = 16 - (int)strlen(kLabels[i].label);
260
const int value = (kLabels[i].size + scale - 1) / scale;
261
assert(skip > 0);
262
printf("%s \%*s: %6d %s \t[%5.2f%%] [count: %7d]\n",
263
kLabels[i].label, skip, "", value, units,
264
100.f * kLabels[i].size / total,
265
kLabels[i].count);
266
}
267
total = (total + scale - 1) / scale;
268
printf("Total: %d %s\n", total, units);
269
}
270
271
void BitTrace(const struct VP8BitReader* const br, const char label[]) {
272
int i, pos;
273
if (!init_done) {
274
memset(kLabels, 0, sizeof(kLabels));
275
atexit(PrintBitTraces);
276
buf_start = br->buf_;
277
init_done = 1;
278
}
279
pos = (int)(br->buf_ - buf_start) * 8 - br->bits_;
280
// if there's a too large jump, we've changed partition -> reset counter
281
if (abs(pos - last_pos) > 32) {
282
buf_start = br->buf_;
283
pos = 0;
284
last_pos = 0;
285
}
286
if (br->range_ >= 0x7f) pos += kVP8Log2Range[br->range_ - 0x7f];
287
for (i = 0; i < last_label; ++i) {
288
if (!strcmp(label, kLabels[i].label)) break;
289
}
290
if (i == MAX_NUM_LABELS) abort(); // overflow!
291
kLabels[i].label = label;
292
kLabels[i].size += pos - last_pos;
293
kLabels[i].count += 1;
294
if (i == last_label) ++last_label;
295
last_pos = pos;
296
}
297
298
#endif // BITTRACE > 0
299
300
//------------------------------------------------------------------------------
301
302