Coverage Report

Created: 2025-06-16 07:00

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