Coverage Report

Created: 2026-10-10 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebp/src/dec/vp8_dec.c
Line
Count
Source
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
// main entry for the decoder
11
//
12
// Author: Skal (pascal.massimino@gmail.com)
13
14
#include "src/dec/vp8_dec.h"
15
16
#include <assert.h>
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include "src/dec/alphai_dec.h"
21
#include "src/dec/common_dec.h"
22
#include "src/dec/vp8i_dec.h"
23
#include "src/dec/vp8li_dec.h"
24
#include "src/dec/webpi_dec.h"
25
#include "src/dsp/cpu.h"
26
#include "src/dsp/dsp.h"
27
#include "src/utils/bit_reader_inl_utils.h"
28
#include "src/utils/bit_reader_utils.h"
29
#include "src/utils/thread_utils.h"
30
#include "src/utils/utils.h"
31
#include "src/webp/decode.h"
32
#include "src/webp/format_constants.h"
33
#include "src/webp/types.h"
34
35
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
36
37
//------------------------------------------------------------------------------
38
39
0
int WebPGetDecoderVersion(void) {
40
0
  return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
41
0
}
42
43
//------------------------------------------------------------------------------
44
// Signature and pointer-to-function for GetCoeffs() variants below.
45
46
typedef int (*GetCoeffsFunc)(VP8BitReader* const br,
47
                             const VP8BandProbas* const prob[], int ctx,
48
                             const quant_t dq, int n, int16_t* out);
49
static volatile GetCoeffsFunc GetCoeffs = NULL;
50
51
static void InitGetCoeffs(void);
52
53
//------------------------------------------------------------------------------
54
// VP8Decoder
55
56
131k
static void SetOk(VP8Decoder* const dec) {
57
131k
  dec->status = VP8_STATUS_OK;
58
131k
  dec->error_msg = "OK";
59
131k
}
60
61
120k
int VP8InitIoInternal(VP8Io* const io, int version) {
62
120k
  if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
63
0
    return 0;  // mismatch error
64
0
  }
65
120k
  if (io != NULL) {
66
120k
    WEBP_UNSAFE_MEMSET(io, 0, sizeof(*io));
67
120k
  }
68
120k
  return 1;
69
120k
}
70
71
64.6k
VP8Decoder* VP8New(void) {
72
64.6k
  VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
73
64.6k
  if (dec != NULL) {
74
64.3k
    SetOk(dec);
75
64.3k
    WebPGetWorkerInterface()->Init(&dec->worker);
76
64.3k
    dec->ready = 0;
77
64.3k
    dec->num_parts_minus_one = 0;
78
64.3k
    InitGetCoeffs();
79
64.3k
  }
80
64.6k
  return dec;
81
64.6k
}
82
83
0
VP8StatusCode VP8Status(VP8Decoder* const dec) {
84
0
  if (!dec) return VP8_STATUS_INVALID_PARAM;
85
0
  return dec->status;
86
0
}
87
88
0
const char* VP8StatusMessage(VP8Decoder* const dec) {
89
0
  if (dec == NULL) return "no object";
90
0
  if (!dec->error_msg) return "OK";
91
0
  return dec->error_msg;
92
0
}
93
94
64.3k
void VP8Delete(VP8Decoder* const dec) {
95
64.3k
  if (dec != NULL) {
96
64.3k
    VP8Clear(dec);
97
64.3k
    WebPSafeFree(dec);
98
64.3k
  }
99
64.3k
}
100
101
int VP8SetError(VP8Decoder* const dec, VP8StatusCode error,
102
16.8k
                const char* const msg) {
103
  // VP8_STATUS_SUSPENDED is only meaningful in incremental decoding.
104
16.8k
  assert(dec->incremental || error != VP8_STATUS_SUSPENDED);
105
  // The oldest error reported takes precedence over the new one.
106
16.8k
  if (dec->status == VP8_STATUS_OK) {
107
16.8k
    dec->status = error;
108
16.8k
    dec->error_msg = msg;
109
16.8k
    dec->ready = 0;
110
16.8k
  }
111
16.8k
  return 0;
112
16.8k
}
113
114
//------------------------------------------------------------------------------
115
116
int VP8CheckSignature(const uint8_t* const WEBP_COUNTED_BY(data_size) data,
117
256k
                      size_t data_size) {
118
256k
  return (data_size >= 3 && data[0] == 0x9d && data[1] == 0x01 &&
119
251k
          data[2] == 0x2a);
120
256k
}
121
122
int VP8GetInfo(const uint8_t* WEBP_COUNTED_BY(data_size) data, size_t data_size,
123
189k
               size_t chunk_size, int* const width, int* const height) {
124
189k
  if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {
125
44
    return 0;  // not enough data
126
44
  }
127
  // check signature
128
189k
  if (!VP8CheckSignature(data + 3, data_size - 3)) {
129
4.85k
    return 0;  // Wrong signature.
130
184k
  } else {
131
184k
    const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
132
184k
    const int key_frame = !(bits & 1);
133
184k
    const int w = ((data[7] << 8) | data[6]) & 0x3fff;
134
184k
    const int h = ((data[9] << 8) | data[8]) & 0x3fff;
135
136
184k
    if (!key_frame) {  // Not a keyframe.
137
38
      return 0;
138
38
    }
139
140
184k
    if (((bits >> 1) & 7) > 3) {
141
34
      return 0;  // unknown profile
142
34
    }
143
184k
    if (!((bits >> 4) & 1)) {
144
31
      return 0;  // first frame is invisible!
145
31
    }
146
184k
    if (((bits >> 5)) >= chunk_size) {  // partition_length
147
244
      return 0;                         // inconsistent size information.
148
244
    }
149
183k
    if (w == 0 || h == 0) {
150
61
      return 0;  // We don't support a zero width or height.
151
61
    }
152
153
183k
    if (width) {
154
183k
      *width = w;
155
183k
    }
156
183k
    if (height) {
157
183k
      *height = h;
158
183k
    }
159
160
183k
    return 1;
161
183k
  }
162
189k
}
163
164
//------------------------------------------------------------------------------
165
// Header parsing
166
167
67.3k
static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
168
67.3k
  assert(hdr != NULL);
169
67.3k
  hdr->use_segment = 0;
170
67.3k
  hdr->update_map = 0;
171
67.3k
  hdr->absolute_delta = 1;
172
67.3k
  WEBP_UNSAFE_MEMSET(hdr->quantizer, 0, sizeof(hdr->quantizer));
173
67.3k
  WEBP_UNSAFE_MEMSET(hdr->filter_strength, 0, sizeof(hdr->filter_strength));
174
67.3k
}
175
176
// Paragraph 9.3
177
WEBP_NODISCARD static int ParseSegmentHeader(VP8BitReader* br,
178
                                             VP8SegmentHeader* hdr,
179
67.2k
                                             VP8Proba* proba) {
180
67.2k
  assert(br != NULL);
181
67.2k
  assert(hdr != NULL);
182
67.2k
  hdr->use_segment = VP8Get(br, "global-header");
183
67.2k
  if (hdr->use_segment) {
184
25.8k
    hdr->update_map = VP8Get(br, "global-header");
185
25.8k
    if (VP8Get(br, "global-header")) {  // update data
186
23.1k
      int s;
187
23.1k
      hdr->absolute_delta = VP8Get(br, "global-header");
188
115k
      for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
189
92.5k
        hdr->quantizer[s] = VP8Get(br, "global-header")
190
92.5k
                                ? VP8GetSignedValue(br, 7, "global-header")
191
92.5k
                                : 0;
192
92.5k
      }
193
115k
      for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
194
92.5k
        hdr->filter_strength[s] =
195
92.5k
            VP8Get(br, "global-header")
196
92.5k
                ? VP8GetSignedValue(br, 6, "global-header")
197
92.5k
                : 0;
198
92.5k
      }
199
23.1k
    }
200
25.8k
    if (hdr->update_map) {
201
22.9k
      int s;
202
91.7k
      for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {
203
68.7k
        proba->segments[s] = VP8Get(br, "global-header")
204
68.7k
                                 ? VP8GetValue(br, 8, "global-header")
205
68.7k
                                 : 255u;
206
68.7k
      }
207
22.9k
    }
208
41.4k
  } else {
209
41.4k
    hdr->update_map = 0;
210
41.4k
  }
211
67.2k
  return !br->eof;
212
67.2k
}
213
214
// Paragraph 9.5
215
// If we don't have all the necessary data in 'buf', this function returns
216
// VP8_STATUS_SUSPENDED in incremental decoding, VP8_STATUS_NOT_ENOUGH_DATA
217
// otherwise.
218
// In incremental decoding, this case is not necessarily an error. Still, no
219
// bitreader is ever initialized to make it possible to read unavailable memory.
220
// If we don't even have the partitions' sizes, then VP8_STATUS_NOT_ENOUGH_DATA
221
// is returned, and this is an unrecoverable error.
222
// If the partitions were positioned ok, VP8_STATUS_OK is returned.
223
static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
224
                                     const uint8_t* WEBP_COUNTED_BY(size) buf,
225
66.8k
                                     size_t size) {
226
66.8k
  VP8BitReader* const br = &dec->br;
227
66.8k
  const uint8_t* WEBP_BIDI_INDEXABLE sz = buf;
228
66.8k
  const uint8_t* buf_end = buf + size;
229
66.8k
  const uint8_t* WEBP_BIDI_INDEXABLE part_start;
230
66.8k
  size_t size_left = size;
231
66.8k
  size_t last_part;
232
66.8k
  size_t p;
233
234
66.8k
  dec->num_parts_minus_one = (1 << VP8GetValue(br, 2, "global-header")) - 1;
235
66.8k
  last_part = dec->num_parts_minus_one;
236
66.8k
  if (size < 3 * last_part) {
237
    // we can't even read the sizes with sz[]! That's a failure.
238
346
    return VP8_STATUS_NOT_ENOUGH_DATA;
239
346
  }
240
66.5k
  part_start = buf + last_part * 3;
241
66.5k
  size_left -= last_part * 3;
242
178k
  for (p = 0; p < last_part; ++p) {
243
112k
    size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
244
112k
    if (psize > size_left) psize = size_left;
245
112k
    VP8InitBitReader(dec->parts + p, part_start, psize);
246
112k
    part_start += psize;
247
112k
    size_left -= psize;
248
112k
    sz += 3;
249
112k
  }
250
66.5k
  VP8InitBitReader(dec->parts + last_part, part_start, size_left);
251
66.5k
  if (part_start < buf_end) return VP8_STATUS_OK;
252
3.44k
  return dec->incremental
253
3.44k
             ? VP8_STATUS_SUSPENDED  // Init is ok, but there's not enough data
254
3.44k
             : VP8_STATUS_NOT_ENOUGH_DATA;
255
66.5k
}
256
257
// Paragraph 9.4
258
WEBP_NODISCARD static int ParseFilterHeader(VP8BitReader* br,
259
66.9k
                                            VP8Decoder* const dec) {
260
66.9k
  VP8FilterHeader* const hdr = &dec->filter_hdr;
261
66.9k
  hdr->simple = VP8Get(br, "global-header");
262
66.9k
  hdr->level = VP8GetValue(br, 6, "global-header");
263
66.9k
  hdr->sharpness = VP8GetValue(br, 3, "global-header");
264
66.9k
  hdr->use_lf_delta = VP8Get(br, "global-header");
265
66.9k
  if (hdr->use_lf_delta) {
266
6.88k
    if (VP8Get(br, "global-header")) {  // update lf-delta?
267
3.57k
      int i;
268
17.8k
      for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {
269
14.3k
        if (VP8Get(br, "global-header")) {
270
7.87k
          hdr->ref_lf_delta[i] = VP8GetSignedValue(br, 6, "global-header");
271
7.87k
        }
272
14.3k
      }
273
17.8k
      for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
274
14.3k
        if (VP8Get(br, "global-header")) {
275
6.82k
          hdr->mode_lf_delta[i] = VP8GetSignedValue(br, 6, "global-header");
276
6.82k
        }
277
14.3k
      }
278
3.57k
    }
279
6.88k
  }
280
66.9k
  dec->filter_type = (hdr->level == 0) ? 0 : hdr->simple ? 1 : 2;
281
66.9k
  return !br->eof;
282
66.9k
}
283
284
// Topmost call
285
67.3k
int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
286
67.3k
  size_t buf_size;
287
67.3k
  const uint8_t* WEBP_COUNTED_BY(buf_size) buf;
288
67.3k
  VP8FrameHeader* frm_hdr;
289
67.3k
  VP8PictureHeader* pic_hdr;
290
67.3k
  VP8BitReader* br;
291
67.3k
  VP8StatusCode status;
292
293
67.3k
  if (dec == NULL) {
294
0
    return 0;
295
0
  }
296
67.3k
  SetOk(dec);
297
67.3k
  if (io == NULL) {
298
0
    return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
299
0
                       "null VP8Io passed to VP8GetHeaders()");
300
0
  }
301
67.3k
  buf_size = io->data_size;
302
67.3k
  buf =
303
67.3k
      WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(const uint8_t*, io->data, io->data_size);
304
67.3k
  if (buf_size < 4) {
305
0
    return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, "Truncated header.");
306
0
  }
307
308
  // Paragraph 9.1
309
67.3k
  {
310
67.3k
    const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
311
67.3k
    frm_hdr = &dec->frm_hdr;
312
67.3k
    frm_hdr->key_frame = !(bits & 1);
313
67.3k
    frm_hdr->profile = (bits >> 1) & 7;
314
67.3k
    frm_hdr->show = (bits >> 4) & 1;
315
67.3k
    frm_hdr->partition_length = (bits >> 5);
316
67.3k
    if (frm_hdr->profile > 3) {
317
0
      return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
318
0
                         "Incorrect keyframe parameters.");
319
0
    }
320
67.3k
    if (!frm_hdr->show) {
321
0
      return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
322
0
                         "Frame not displayable.");
323
0
    }
324
67.3k
    buf += 3;
325
67.3k
    buf_size -= 3;
326
67.3k
  }
327
328
0
  pic_hdr = &dec->pic_hdr;
329
67.3k
  if (frm_hdr->key_frame) {
330
    // Paragraph 9.2
331
67.3k
    if (buf_size < 7) {
332
0
      return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
333
0
                         "cannot parse picture header");
334
0
    }
335
67.3k
    if (!VP8CheckSignature(buf, buf_size)) {
336
0
      return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, "Bad code word");
337
0
    }
338
67.3k
    pic_hdr->width = ((buf[4] << 8) | buf[3]) & 0x3fff;
339
67.3k
    pic_hdr->xscale = buf[4] >> 6;  // ratio: 1, 5/4 5/3 or 2
340
67.3k
    pic_hdr->height = ((buf[6] << 8) | buf[5]) & 0x3fff;
341
67.3k
    pic_hdr->yscale = buf[6] >> 6;
342
67.3k
    buf += 7;
343
67.3k
    buf_size -= 7;
344
345
67.3k
    dec->mb_w = (pic_hdr->width + 15) >> 4;
346
67.3k
    dec->mb_h = (pic_hdr->height + 15) >> 4;
347
348
    // Setup default output area (can be later modified during io->setup())
349
67.3k
    io->width = pic_hdr->width;
350
67.3k
    io->height = pic_hdr->height;
351
    // IMPORTANT! use some sane dimensions in crop* and scaled* fields.
352
    // So they can be used interchangeably without always testing for
353
    // 'use_cropping'.
354
67.3k
    io->use_cropping = 0;
355
67.3k
    io->crop_top = 0;
356
67.3k
    io->crop_left = 0;
357
67.3k
    io->crop_right = io->width;
358
67.3k
    io->crop_bottom = io->height;
359
67.3k
    io->use_scaling = 0;
360
67.3k
    io->scaled_width = io->width;
361
67.3k
    io->scaled_height = io->height;
362
363
67.3k
    io->mb_w = io->width;   // for soundness
364
67.3k
    io->mb_h = io->height;  // ditto
365
366
67.3k
    VP8ResetProba(&dec->proba);
367
67.3k
    ResetSegmentHeader(&dec->segment_hdr);
368
67.3k
  }
369
370
  // Check if we have all the partition #0 available, and initialize dec->br
371
  // to read this partition (and this partition only).
372
67.3k
  if (frm_hdr->partition_length > buf_size) {
373
32
    return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA, "bad partition length");
374
32
  }
375
376
67.2k
  br = &dec->br;
377
67.2k
  VP8InitBitReader(br, buf, frm_hdr->partition_length);
378
67.2k
  buf += frm_hdr->partition_length;
379
67.2k
  buf_size -= frm_hdr->partition_length;
380
381
67.2k
  if (frm_hdr->key_frame) {
382
67.2k
    pic_hdr->colorspace = VP8Get(br, "global-header");
383
67.2k
    pic_hdr->clamp_type = VP8Get(br, "global-header");
384
67.2k
  }
385
67.2k
  if (!ParseSegmentHeader(br, &dec->segment_hdr, &dec->proba)) {
386
299
    return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
387
299
                       "cannot parse segment header");
388
299
  }
389
  // Filter specs
390
66.9k
  if (!ParseFilterHeader(br, dec)) {
391
111
    return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
392
111
                       "cannot parse filter header");
393
111
  }
394
66.8k
  status = ParsePartitions(dec, buf, buf_size);
395
66.8k
  if (status != VP8_STATUS_OK) {
396
3.79k
    return VP8SetError(dec, status, "cannot parse partitions");
397
3.79k
  }
398
399
  // quantizer change
400
63.0k
  VP8ParseQuant(dec);
401
402
  // Frame buffer marking
403
63.0k
  if (!frm_hdr->key_frame) {
404
0
    return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE, "Not a key frame.");
405
0
  }
406
407
63.0k
  VP8Get(br, "global-header");  // ignore the value of 'update_proba'
408
409
63.0k
  VP8ParseProba(br, dec);
410
411
  // sanitized state
412
63.0k
  dec->ready = 1;
413
63.0k
  return 1;
414
63.0k
}
415
416
//------------------------------------------------------------------------------
417
// Residual decoding (Paragraph 13.2 / 13.3)
418
419
static const uint8_t kCat3[] = {173, 148, 140, 0};
420
static const uint8_t kCat4[] = {176, 155, 140, 135, 0};
421
static const uint8_t kCat5[] = {180, 157, 141, 134, 130, 0};
422
static const uint8_t kCat6[] = {254, 254, 243, 230, 196, 177,
423
                                153, 140, 133, 130, 129, 0};
424
static const uint8_t* const kCat3456[] = {kCat3, kCat4, kCat5, kCat6};
425
static const uint8_t kZigzag[16] = {0, 1,  4,  8,  5, 2,  3,  6,
426
                                    9, 12, 13, 10, 7, 11, 14, 15};
427
428
// See section 13-2: https://datatracker.ietf.org/doc/html/rfc6386#section-13.2
429
29.8M
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
430
29.8M
  int v;
431
29.8M
  if (!VP8GetBit(br, p[3], "coeffs")) {
432
15.9M
    if (!VP8GetBit(br, p[4], "coeffs")) {
433
8.39M
      v = 2;
434
8.39M
    } else {
435
7.51M
      v = 3 + VP8GetBit(br, p[5], "coeffs");
436
7.51M
    }
437
15.9M
  } else {
438
13.9M
    if (!VP8GetBit(br, p[6], "coeffs")) {
439
7.23M
      if (!VP8GetBit(br, p[7], "coeffs")) {
440
3.63M
        v = 5 + VP8GetBit(br, 159, "coeffs");
441
3.63M
      } else {
442
3.60M
        v = 7 + 2 * VP8GetBit(br, 165, "coeffs");
443
3.60M
        v += VP8GetBit(br, 145, "coeffs");
444
3.60M
      }
445
7.23M
    } else {
446
6.66M
      const uint8_t* tab;
447
6.66M
      const int bit1 = VP8GetBit(br, p[8], "coeffs");
448
6.66M
      const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs");
449
6.66M
      const int cat = 2 * bit1 + bit0;
450
6.66M
      v = 0;
451
37.3M
      for (tab = kCat3456[cat]; *tab; ++tab) {
452
30.6M
        v += v + VP8GetBit(br, *tab, "coeffs");
453
30.6M
      }
454
6.66M
      v += 3 + (8 << cat);
455
6.66M
    }
456
13.9M
  }
457
29.8M
  return v;
458
29.8M
}
459
460
// Returns the position of the last non-zero coeff plus one
461
static int GetCoeffsFast(VP8BitReader* const br,
462
                         const VP8BandProbas* const prob[], int ctx,
463
22.7M
                         const quant_t dq, int n, int16_t* out) {
464
22.7M
  const uint8_t* p = prob[n]->probas[ctx];
465
68.9M
  for (; n < 16; ++n) {
466
66.7M
    if (!VP8GetBit(br, p[0], "coeffs")) {
467
20.5M
      return n;  // previous coeff was last non-zero coeff
468
20.5M
    }
469
75.1M
    while (!VP8GetBit(br, p[1], "coeffs")) {  // sequence of zero coeffs
470
28.9M
      p = prob[++n]->probas[0];
471
28.9M
      if (n == 16) return 16;
472
28.9M
    }
473
46.2M
    {  // non zero coeff
474
46.2M
      const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas[0];
475
46.2M
      int v;
476
46.2M
      if (!VP8GetBit(br, p[2], "coeffs")) {
477
21.5M
        v = 1;
478
21.5M
        p = p_ctx[1];
479
24.6M
      } else {
480
24.6M
        v = GetLargeValue(br, p);
481
24.6M
        p = p_ctx[2];
482
24.6M
      }
483
46.2M
      out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0];
484
46.2M
    }
485
46.2M
  }
486
2.24M
  return 16;
487
22.7M
}
488
489
// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version
490
// of VP8GetBitAlt() targeting specific platforms.
491
static int GetCoeffsAlt(VP8BitReader* const br,
492
                        const VP8BandProbas* const prob[], int ctx,
493
1.57M
                        const quant_t dq, int n, int16_t* out) {
494
1.57M
  const uint8_t* p = prob[n]->probas[ctx];
495
10.0M
  for (; n < 16; ++n) {
496
9.58M
    if (!VP8GetBitAlt(br, p[0], "coeffs")) {
497
1.09M
      return n;  // previous coeff was last non-zero coeff
498
1.09M
    }
499
13.6M
    while (!VP8GetBitAlt(br, p[1], "coeffs")) {  // sequence of zero coeffs
500
5.13M
      p = prob[++n]->probas[0];
501
5.13M
      if (n == 16) return 16;
502
5.13M
    }
503
8.49M
    {  // non zero coeff
504
8.49M
      const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas[0];
505
8.49M
      int v;
506
8.49M
      if (!VP8GetBitAlt(br, p[2], "coeffs")) {
507
3.33M
        v = 1;
508
3.33M
        p = p_ctx[1];
509
5.15M
      } else {
510
5.15M
        v = GetLargeValue(br, p);
511
5.15M
        p = p_ctx[2];
512
5.15M
      }
513
8.49M
      out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0];
514
8.49M
    }
515
8.49M
  }
516
485k
  return 16;
517
1.57M
}
518
519
extern VP8CPUInfo VP8GetCPUInfo;
520
521
24.3k
WEBP_DSP_INIT_FUNC(InitGetCoeffs) {
522
24.3k
  if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
523
4.37k
    GetCoeffs = GetCoeffsAlt;
524
19.9k
  } else {
525
19.9k
    GetCoeffs = GetCoeffsFast;
526
19.9k
  }
527
24.3k
}
528
529
23.8M
static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
530
23.8M
  nz_coeffs <<= 2;
531
23.8M
  nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;
532
23.8M
  return nz_coeffs;
533
23.8M
}
534
535
WEBP_NODISCARD static int ParseResiduals(VP8Decoder* const dec, VP8MB* const mb,
536
992k
                                         VP8BitReader* const token_br) {
537
992k
  const VP8BandProbas*(*const bands)[16 + 1] = dec->proba.bands_ptr;
538
992k
  const VP8BandProbas* const* ac_proba;
539
992k
  VP8MBData* const block = dec->mb_data + dec->mb_x;
540
992k
  const VP8QuantMatrix* const q = &dec->dqm[block->segment];
541
992k
  int16_t* dst = block->coeffs;
542
992k
  VP8MB* const left_mb = dec->mb_info - 1;
543
992k
  uint8_t tnz, lnz;
544
992k
  uint32_t non_zero_y = 0;
545
992k
  uint32_t non_zero_uv = 0;
546
992k
  int x, y, ch;
547
992k
  uint32_t out_t_nz, out_l_nz;
548
992k
  int first;
549
550
992k
  WEBP_UNSAFE_MEMSET(dst, 0, 384 * sizeof(*dst));
551
992k
  if (!block->is_i4x4) {  // parse DC
552
542k
    int16_t dc[16] = {0};
553
542k
    const int ctx = mb->nz_dc + left_mb->nz_dc;
554
542k
    const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat, 0, dc);
555
542k
    mb->nz_dc = left_mb->nz_dc = (nz > 0);
556
542k
    if (nz > 1) {  // more than just the DC -> perform the full transform
557
226k
      VP8TransformWHT(dc, dst);
558
316k
    } else {  // only DC is non-zero -> inlined simplified transform
559
316k
      int i;
560
316k
      const int dc0 = (dc[0] + 3) >> 3;
561
5.38M
      for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0;
562
316k
    }
563
542k
    first = 1;
564
542k
    ac_proba = bands[0];
565
542k
  } else {
566
449k
    first = 0;
567
449k
    ac_proba = bands[3];
568
449k
  }
569
570
992k
  tnz = mb->nz & 0x0f;
571
992k
  lnz = left_mb->nz & 0x0f;
572
4.96M
  for (y = 0; y < 4; ++y) {
573
3.96M
    int l = lnz & 1;
574
3.96M
    uint32_t nz_coeffs = 0;
575
19.8M
    for (x = 0; x < 4; ++x) {
576
15.8M
      const int ctx = l + (tnz & 1);
577
15.8M
      const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat, first, dst);
578
15.8M
      l = (nz > first);
579
15.8M
      tnz = (tnz >> 1) | (l << 7);
580
15.8M
      nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
581
15.8M
      dst += 16;
582
15.8M
    }
583
3.96M
    tnz >>= 4;
584
3.96M
    lnz = (lnz >> 1) | (l << 7);
585
3.96M
    non_zero_y = (non_zero_y << 8) | nz_coeffs;
586
3.96M
  }
587
992k
  out_t_nz = tnz;
588
992k
  out_l_nz = lnz >> 4;
589
590
2.97M
  for (ch = 0; ch < 4; ch += 2) {
591
1.98M
    uint32_t nz_coeffs = 0;
592
1.98M
    tnz = mb->nz >> (4 + ch);
593
1.98M
    lnz = left_mb->nz >> (4 + ch);
594
5.95M
    for (y = 0; y < 2; ++y) {
595
3.96M
      int l = lnz & 1;
596
11.9M
      for (x = 0; x < 2; ++x) {
597
7.93M
        const int ctx = l + (tnz & 1);
598
7.93M
        const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat, 0, dst);
599
7.93M
        l = (nz > 0);
600
7.93M
        tnz = (tnz >> 1) | (l << 3);
601
7.93M
        nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);
602
7.93M
        dst += 16;
603
7.93M
      }
604
3.96M
      tnz >>= 2;
605
3.96M
      lnz = (lnz >> 1) | (l << 5);
606
3.96M
    }
607
    // Note: we don't really need the per-4x4 details for U/V blocks.
608
1.98M
    non_zero_uv |= nz_coeffs << (4 * ch);
609
1.98M
    out_t_nz |= (tnz << 4) << ch;
610
1.98M
    out_l_nz |= (lnz & 0xf0) << ch;
611
1.98M
  }
612
992k
  mb->nz = out_t_nz;
613
992k
  left_mb->nz = out_l_nz;
614
615
992k
  block->non_zero_y = non_zero_y;
616
992k
  block->non_zero_uv = non_zero_uv;
617
618
  // We look at the mode-code of each block and check if some blocks have less
619
  // than three non-zero coeffs (code < 2). This is to avoid dithering flat and
620
  // empty blocks.
621
992k
  block->dither = (non_zero_uv & 0xaaaa) ? 0 : q->dither;
622
623
992k
  return !(non_zero_y | non_zero_uv);  // will be used for further optimization
624
992k
}
625
626
//------------------------------------------------------------------------------
627
// Main loop
628
629
1.34M
int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
630
1.34M
  VP8MB* const left = dec->mb_info - 1;
631
1.34M
  VP8MB* const mb = dec->mb_info + dec->mb_x;
632
1.34M
  VP8MBData* const block = dec->mb_data + dec->mb_x;
633
1.34M
  int skip = dec->use_skip_proba ? block->skip : 0;
634
635
1.34M
  if (!skip) {
636
992k
    skip = ParseResiduals(dec, mb, token_br);
637
992k
  } else {
638
350k
    left->nz = mb->nz = 0;
639
350k
    if (!block->is_i4x4) {
640
212k
      left->nz_dc = mb->nz_dc = 0;
641
212k
    }
642
350k
    block->non_zero_y = 0;
643
350k
    block->non_zero_uv = 0;
644
350k
    block->dither = 0;
645
350k
  }
646
647
1.34M
  if (dec->filter_type > 0) {  // store filter info
648
1.00M
    VP8FInfo* const finfo = dec->f_info + dec->mb_x;
649
1.00M
    *finfo = dec->fstrengths[block->segment][block->is_i4x4];
650
1.00M
    finfo->f_inner |= !skip;
651
1.00M
  }
652
653
1.34M
  return !token_br->eof;
654
1.34M
}
655
656
445k
void VP8InitScanline(VP8Decoder* const dec) {
657
445k
  VP8MB* const left = dec->mb_info - 1;
658
445k
  left->nz = 0;
659
445k
  left->nz_dc = 0;
660
445k
  WEBP_UNSAFE_MEMSET(dec->intra_l, B_DC_PRED, sizeof(dec->intra_l));
661
445k
  dec->mb_x = 0;
662
445k
}
663
664
59.7k
WEBP_NODISCARD static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
665
430k
  for (dec->mb_y = 0; dec->mb_y < dec->br_mb_y; ++dec->mb_y) {
666
    // Parse bitstream for this row.
667
382k
    VP8BitReader* const token_br =
668
382k
        &dec->parts[dec->mb_y & dec->num_parts_minus_one];
669
382k
    if (!VP8ParseIntraModeRow(&dec->br, dec)) {
670
6.69k
      return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
671
6.69k
                         "Premature end-of-partition0 encountered.");
672
6.69k
    }
673
1.68M
    for (; dec->mb_x < dec->mb_w; ++dec->mb_x) {
674
1.31M
      if (!VP8DecodeMB(dec, token_br)) {
675
5.79k
        return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
676
5.79k
                           "Premature end-of-file encountered.");
677
5.79k
      }
678
1.31M
    }
679
370k
    VP8InitScanline(dec);  // Prepare for next scanline
680
681
    // Reconstruct, filter and emit the row.
682
370k
    if (!VP8ProcessRow(dec, io)) {
683
0
      return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
684
0
    }
685
370k
  }
686
47.2k
  if (dec->mt_method > 0) {
687
    // Collect the last row's put(), which may have aborted.
688
86
    if (!WebPGetWorkerInterface()->Sync(&dec->worker)) {
689
0
      return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
690
0
    }
691
86
  }
692
693
47.2k
  return 1;
694
47.2k
}
695
696
// Main entry point
697
59.9k
int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
698
59.9k
  int ok = 0;
699
59.9k
  if (dec == NULL) {
700
0
    return 0;
701
0
  }
702
59.9k
  if (io == NULL) {
703
0
    return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
704
0
                       "NULL VP8Io parameter in VP8Decode().");
705
0
  }
706
707
59.9k
  if (!dec->ready) {
708
0
    if (!VP8GetHeaders(dec, io)) {
709
0
      return 0;
710
0
    }
711
0
  }
712
59.9k
  assert(dec->ready);
713
714
  // Finish setting up the decoding parameter. Will call io->setup().
715
59.9k
  ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);
716
59.9k
  if (ok) {  // good to go.
717
    // Will allocate memory and prepare everything.
718
59.8k
    ok = VP8InitFrame(dec, io);
719
720
    // Main decoding loop
721
59.8k
    if (ok) ok = ParseFrame(dec, io);
722
723
    // Exit.
724
59.8k
    ok &= VP8ExitCritical(dec, io);
725
59.8k
  }
726
727
59.9k
  if (!ok) {
728
12.6k
    VP8Clear(dec);
729
12.6k
    return 0;
730
12.6k
  }
731
732
47.2k
  dec->ready = 0;
733
47.2k
  return ok;
734
59.9k
}
735
736
76.9k
void VP8Clear(VP8Decoder* const dec) {
737
76.9k
  if (dec == NULL) {
738
0
    return;
739
0
  }
740
76.9k
  WebPGetWorkerInterface()->End(&dec->worker);
741
76.9k
  WebPDeallocateAlphaMemory(dec);
742
76.9k
  WebPSafeFree(dec->mem);
743
76.9k
  dec->mem = NULL;
744
76.9k
  dec->mem_size = 0;
745
76.9k
  WEBP_UNSAFE_MEMSET(&dec->br, 0, sizeof(dec->br));
746
76.9k
  dec->ready = 0;
747
76.9k
}
748
749
//------------------------------------------------------------------------------