Coverage Report

Created: 2025-07-23 06:34

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