xref: /aosp_15_r20/external/webp/src/dec/vp8l_dec.c (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
1*b2055c35SXin Li // Copyright 2012 Google Inc. All Rights Reserved.
2*b2055c35SXin Li //
3*b2055c35SXin Li // Use of this source code is governed by a BSD-style license
4*b2055c35SXin Li // that can be found in the COPYING file in the root of the source
5*b2055c35SXin Li // tree. An additional intellectual property rights grant can be found
6*b2055c35SXin Li // in the file PATENTS. All contributing project authors may
7*b2055c35SXin Li // be found in the AUTHORS file in the root of the source tree.
8*b2055c35SXin Li // -----------------------------------------------------------------------------
9*b2055c35SXin Li //
10*b2055c35SXin Li // main entry for the decoder
11*b2055c35SXin Li //
12*b2055c35SXin Li // Authors: Vikas Arora ([email protected])
13*b2055c35SXin Li //          Jyrki Alakuijala ([email protected])
14*b2055c35SXin Li 
15*b2055c35SXin Li #include <assert.h>
16*b2055c35SXin Li #include <stdlib.h>
17*b2055c35SXin Li 
18*b2055c35SXin Li #include "src/dec/alphai_dec.h"
19*b2055c35SXin Li #include "src/dec/vp8li_dec.h"
20*b2055c35SXin Li #include "src/dsp/dsp.h"
21*b2055c35SXin Li #include "src/dsp/lossless.h"
22*b2055c35SXin Li #include "src/dsp/lossless_common.h"
23*b2055c35SXin Li #include "src/dsp/yuv.h"
24*b2055c35SXin Li #include "src/utils/endian_inl_utils.h"
25*b2055c35SXin Li #include "src/utils/huffman_utils.h"
26*b2055c35SXin Li #include "src/utils/utils.h"
27*b2055c35SXin Li 
28*b2055c35SXin Li #define NUM_ARGB_CACHE_ROWS          16
29*b2055c35SXin Li 
30*b2055c35SXin Li static const int kCodeLengthLiterals = 16;
31*b2055c35SXin Li static const int kCodeLengthRepeatCode = 16;
32*b2055c35SXin Li static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };
33*b2055c35SXin Li static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
34*b2055c35SXin Li 
35*b2055c35SXin Li // -----------------------------------------------------------------------------
36*b2055c35SXin Li //  Five Huffman codes are used at each meta code:
37*b2055c35SXin Li //  1. green + length prefix codes + color cache codes,
38*b2055c35SXin Li //  2. alpha,
39*b2055c35SXin Li //  3. red,
40*b2055c35SXin Li //  4. blue, and,
41*b2055c35SXin Li //  5. distance prefix codes.
42*b2055c35SXin Li typedef enum {
43*b2055c35SXin Li   GREEN = 0,
44*b2055c35SXin Li   RED   = 1,
45*b2055c35SXin Li   BLUE  = 2,
46*b2055c35SXin Li   ALPHA = 3,
47*b2055c35SXin Li   DIST  = 4
48*b2055c35SXin Li } HuffIndex;
49*b2055c35SXin Li 
50*b2055c35SXin Li static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
51*b2055c35SXin Li   NUM_LITERAL_CODES + NUM_LENGTH_CODES,
52*b2055c35SXin Li   NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
53*b2055c35SXin Li   NUM_DISTANCE_CODES
54*b2055c35SXin Li };
55*b2055c35SXin Li 
56*b2055c35SXin Li static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {
57*b2055c35SXin Li   0, 1, 1, 1, 0
58*b2055c35SXin Li };
59*b2055c35SXin Li 
60*b2055c35SXin Li #define NUM_CODE_LENGTH_CODES       19
61*b2055c35SXin Li static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
62*b2055c35SXin Li   17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
63*b2055c35SXin Li };
64*b2055c35SXin Li 
65*b2055c35SXin Li #define CODE_TO_PLANE_CODES        120
66*b2055c35SXin Li static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
67*b2055c35SXin Li   0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
68*b2055c35SXin Li   0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
69*b2055c35SXin Li   0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
70*b2055c35SXin Li   0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
71*b2055c35SXin Li   0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
72*b2055c35SXin Li   0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
73*b2055c35SXin Li   0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
74*b2055c35SXin Li   0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
75*b2055c35SXin Li   0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
76*b2055c35SXin Li   0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
77*b2055c35SXin Li   0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
78*b2055c35SXin Li   0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
79*b2055c35SXin Li };
80*b2055c35SXin Li 
81*b2055c35SXin Li // Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha
82*b2055c35SXin Li // and distance alphabets are constant (256 for red, blue and alpha, 40 for
83*b2055c35SXin Li // distance) and lookup table sizes for them in worst case are 630 and 410
84*b2055c35SXin Li // respectively. Size of green alphabet depends on color cache size and is equal
85*b2055c35SXin Li // to 256 (green component values) + 24 (length prefix values)
86*b2055c35SXin Li // + color_cache_size (between 0 and 2048).
87*b2055c35SXin Li // All values computed for 8-bit first level lookup with Mark Adler's tool:
88*b2055c35SXin Li // https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c
89*b2055c35SXin Li #define FIXED_TABLE_SIZE (630 * 3 + 410)
90*b2055c35SXin Li static const uint16_t kTableSize[12] = {
91*b2055c35SXin Li   FIXED_TABLE_SIZE + 654,
92*b2055c35SXin Li   FIXED_TABLE_SIZE + 656,
93*b2055c35SXin Li   FIXED_TABLE_SIZE + 658,
94*b2055c35SXin Li   FIXED_TABLE_SIZE + 662,
95*b2055c35SXin Li   FIXED_TABLE_SIZE + 670,
96*b2055c35SXin Li   FIXED_TABLE_SIZE + 686,
97*b2055c35SXin Li   FIXED_TABLE_SIZE + 718,
98*b2055c35SXin Li   FIXED_TABLE_SIZE + 782,
99*b2055c35SXin Li   FIXED_TABLE_SIZE + 912,
100*b2055c35SXin Li   FIXED_TABLE_SIZE + 1168,
101*b2055c35SXin Li   FIXED_TABLE_SIZE + 1680,
102*b2055c35SXin Li   FIXED_TABLE_SIZE + 2704
103*b2055c35SXin Li };
104*b2055c35SXin Li 
VP8LSetError(VP8LDecoder * const dec,VP8StatusCode error)105*b2055c35SXin Li static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {
106*b2055c35SXin Li   // The oldest error reported takes precedence over the new one.
107*b2055c35SXin Li   if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) {
108*b2055c35SXin Li     dec->status_ = error;
109*b2055c35SXin Li   }
110*b2055c35SXin Li   return 0;
111*b2055c35SXin Li }
112*b2055c35SXin Li 
113*b2055c35SXin Li static int DecodeImageStream(int xsize, int ysize,
114*b2055c35SXin Li                              int is_level0,
115*b2055c35SXin Li                              VP8LDecoder* const dec,
116*b2055c35SXin Li                              uint32_t** const decoded_data);
117*b2055c35SXin Li 
118*b2055c35SXin Li //------------------------------------------------------------------------------
119*b2055c35SXin Li 
VP8LCheckSignature(const uint8_t * const data,size_t size)120*b2055c35SXin Li int VP8LCheckSignature(const uint8_t* const data, size_t size) {
121*b2055c35SXin Li   return (size >= VP8L_FRAME_HEADER_SIZE &&
122*b2055c35SXin Li           data[0] == VP8L_MAGIC_BYTE &&
123*b2055c35SXin Li           (data[4] >> 5) == 0);  // version
124*b2055c35SXin Li }
125*b2055c35SXin Li 
ReadImageInfo(VP8LBitReader * const br,int * const width,int * const height,int * const has_alpha)126*b2055c35SXin Li static int ReadImageInfo(VP8LBitReader* const br,
127*b2055c35SXin Li                          int* const width, int* const height,
128*b2055c35SXin Li                          int* const has_alpha) {
129*b2055c35SXin Li   if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
130*b2055c35SXin Li   *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
131*b2055c35SXin Li   *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
132*b2055c35SXin Li   *has_alpha = VP8LReadBits(br, 1);
133*b2055c35SXin Li   if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
134*b2055c35SXin Li   return !br->eos_;
135*b2055c35SXin Li }
136*b2055c35SXin Li 
VP8LGetInfo(const uint8_t * data,size_t data_size,int * const width,int * const height,int * const has_alpha)137*b2055c35SXin Li int VP8LGetInfo(const uint8_t* data, size_t data_size,
138*b2055c35SXin Li                 int* const width, int* const height, int* const has_alpha) {
139*b2055c35SXin Li   if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
140*b2055c35SXin Li     return 0;         // not enough data
141*b2055c35SXin Li   } else if (!VP8LCheckSignature(data, data_size)) {
142*b2055c35SXin Li     return 0;         // bad signature
143*b2055c35SXin Li   } else {
144*b2055c35SXin Li     int w, h, a;
145*b2055c35SXin Li     VP8LBitReader br;
146*b2055c35SXin Li     VP8LInitBitReader(&br, data, data_size);
147*b2055c35SXin Li     if (!ReadImageInfo(&br, &w, &h, &a)) {
148*b2055c35SXin Li       return 0;
149*b2055c35SXin Li     }
150*b2055c35SXin Li     if (width != NULL) *width = w;
151*b2055c35SXin Li     if (height != NULL) *height = h;
152*b2055c35SXin Li     if (has_alpha != NULL) *has_alpha = a;
153*b2055c35SXin Li     return 1;
154*b2055c35SXin Li   }
155*b2055c35SXin Li }
156*b2055c35SXin Li 
157*b2055c35SXin Li //------------------------------------------------------------------------------
158*b2055c35SXin Li 
GetCopyDistance(int distance_symbol,VP8LBitReader * const br)159*b2055c35SXin Li static WEBP_INLINE int GetCopyDistance(int distance_symbol,
160*b2055c35SXin Li                                        VP8LBitReader* const br) {
161*b2055c35SXin Li   int extra_bits, offset;
162*b2055c35SXin Li   if (distance_symbol < 4) {
163*b2055c35SXin Li     return distance_symbol + 1;
164*b2055c35SXin Li   }
165*b2055c35SXin Li   extra_bits = (distance_symbol - 2) >> 1;
166*b2055c35SXin Li   offset = (2 + (distance_symbol & 1)) << extra_bits;
167*b2055c35SXin Li   return offset + VP8LReadBits(br, extra_bits) + 1;
168*b2055c35SXin Li }
169*b2055c35SXin Li 
GetCopyLength(int length_symbol,VP8LBitReader * const br)170*b2055c35SXin Li static WEBP_INLINE int GetCopyLength(int length_symbol,
171*b2055c35SXin Li                                      VP8LBitReader* const br) {
172*b2055c35SXin Li   // Length and distance prefixes are encoded the same way.
173*b2055c35SXin Li   return GetCopyDistance(length_symbol, br);
174*b2055c35SXin Li }
175*b2055c35SXin Li 
PlaneCodeToDistance(int xsize,int plane_code)176*b2055c35SXin Li static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
177*b2055c35SXin Li   if (plane_code > CODE_TO_PLANE_CODES) {
178*b2055c35SXin Li     return plane_code - CODE_TO_PLANE_CODES;
179*b2055c35SXin Li   } else {
180*b2055c35SXin Li     const int dist_code = kCodeToPlane[plane_code - 1];
181*b2055c35SXin Li     const int yoffset = dist_code >> 4;
182*b2055c35SXin Li     const int xoffset = 8 - (dist_code & 0xf);
183*b2055c35SXin Li     const int dist = yoffset * xsize + xoffset;
184*b2055c35SXin Li     return (dist >= 1) ? dist : 1;  // dist<1 can happen if xsize is very small
185*b2055c35SXin Li   }
186*b2055c35SXin Li }
187*b2055c35SXin Li 
188*b2055c35SXin Li //------------------------------------------------------------------------------
189*b2055c35SXin Li // Decodes the next Huffman code from bit-stream.
190*b2055c35SXin Li // VP8LFillBitWindow(br) needs to be called at minimum every second call
191*b2055c35SXin Li // to ReadSymbol, in order to pre-fetch enough bits.
ReadSymbol(const HuffmanCode * table,VP8LBitReader * const br)192*b2055c35SXin Li static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,
193*b2055c35SXin Li                                   VP8LBitReader* const br) {
194*b2055c35SXin Li   int nbits;
195*b2055c35SXin Li   uint32_t val = VP8LPrefetchBits(br);
196*b2055c35SXin Li   table += val & HUFFMAN_TABLE_MASK;
197*b2055c35SXin Li   nbits = table->bits - HUFFMAN_TABLE_BITS;
198*b2055c35SXin Li   if (nbits > 0) {
199*b2055c35SXin Li     VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);
200*b2055c35SXin Li     val = VP8LPrefetchBits(br);
201*b2055c35SXin Li     table += table->value;
202*b2055c35SXin Li     table += val & ((1 << nbits) - 1);
203*b2055c35SXin Li   }
204*b2055c35SXin Li   VP8LSetBitPos(br, br->bit_pos_ + table->bits);
205*b2055c35SXin Li   return table->value;
206*b2055c35SXin Li }
207*b2055c35SXin Li 
208*b2055c35SXin Li // Reads packed symbol depending on GREEN channel
209*b2055c35SXin Li #define BITS_SPECIAL_MARKER 0x100  // something large enough (and a bit-mask)
210*b2055c35SXin Li #define PACKED_NON_LITERAL_CODE 0  // must be < NUM_LITERAL_CODES
ReadPackedSymbols(const HTreeGroup * group,VP8LBitReader * const br,uint32_t * const dst)211*b2055c35SXin Li static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,
212*b2055c35SXin Li                                          VP8LBitReader* const br,
213*b2055c35SXin Li                                          uint32_t* const dst) {
214*b2055c35SXin Li   const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);
215*b2055c35SXin Li   const HuffmanCode32 code = group->packed_table[val];
216*b2055c35SXin Li   assert(group->use_packed_table);
217*b2055c35SXin Li   if (code.bits < BITS_SPECIAL_MARKER) {
218*b2055c35SXin Li     VP8LSetBitPos(br, br->bit_pos_ + code.bits);
219*b2055c35SXin Li     *dst = code.value;
220*b2055c35SXin Li     return PACKED_NON_LITERAL_CODE;
221*b2055c35SXin Li   } else {
222*b2055c35SXin Li     VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);
223*b2055c35SXin Li     assert(code.value >= NUM_LITERAL_CODES);
224*b2055c35SXin Li     return code.value;
225*b2055c35SXin Li   }
226*b2055c35SXin Li }
227*b2055c35SXin Li 
AccumulateHCode(HuffmanCode hcode,int shift,HuffmanCode32 * const huff)228*b2055c35SXin Li static int AccumulateHCode(HuffmanCode hcode, int shift,
229*b2055c35SXin Li                            HuffmanCode32* const huff) {
230*b2055c35SXin Li   huff->bits += hcode.bits;
231*b2055c35SXin Li   huff->value |= (uint32_t)hcode.value << shift;
232*b2055c35SXin Li   assert(huff->bits <= HUFFMAN_TABLE_BITS);
233*b2055c35SXin Li   return hcode.bits;
234*b2055c35SXin Li }
235*b2055c35SXin Li 
BuildPackedTable(HTreeGroup * const htree_group)236*b2055c35SXin Li static void BuildPackedTable(HTreeGroup* const htree_group) {
237*b2055c35SXin Li   uint32_t code;
238*b2055c35SXin Li   for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {
239*b2055c35SXin Li     uint32_t bits = code;
240*b2055c35SXin Li     HuffmanCode32* const huff = &htree_group->packed_table[bits];
241*b2055c35SXin Li     HuffmanCode hcode = htree_group->htrees[GREEN][bits];
242*b2055c35SXin Li     if (hcode.value >= NUM_LITERAL_CODES) {
243*b2055c35SXin Li       huff->bits = hcode.bits + BITS_SPECIAL_MARKER;
244*b2055c35SXin Li       huff->value = hcode.value;
245*b2055c35SXin Li     } else {
246*b2055c35SXin Li       huff->bits = 0;
247*b2055c35SXin Li       huff->value = 0;
248*b2055c35SXin Li       bits >>= AccumulateHCode(hcode, 8, huff);
249*b2055c35SXin Li       bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);
250*b2055c35SXin Li       bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);
251*b2055c35SXin Li       bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);
252*b2055c35SXin Li       (void)bits;
253*b2055c35SXin Li     }
254*b2055c35SXin Li   }
255*b2055c35SXin Li }
256*b2055c35SXin Li 
ReadHuffmanCodeLengths(VP8LDecoder * const dec,const int * const code_length_code_lengths,int num_symbols,int * const code_lengths)257*b2055c35SXin Li static int ReadHuffmanCodeLengths(
258*b2055c35SXin Li     VP8LDecoder* const dec, const int* const code_length_code_lengths,
259*b2055c35SXin Li     int num_symbols, int* const code_lengths) {
260*b2055c35SXin Li   int ok = 0;
261*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
262*b2055c35SXin Li   int symbol;
263*b2055c35SXin Li   int max_symbol;
264*b2055c35SXin Li   int prev_code_len = DEFAULT_CODE_LENGTH;
265*b2055c35SXin Li   HuffmanTables tables;
266*b2055c35SXin Li 
267*b2055c35SXin Li   if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||
268*b2055c35SXin Li       !VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,
269*b2055c35SXin Li                              code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {
270*b2055c35SXin Li     goto End;
271*b2055c35SXin Li   }
272*b2055c35SXin Li 
273*b2055c35SXin Li   if (VP8LReadBits(br, 1)) {    // use length
274*b2055c35SXin Li     const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
275*b2055c35SXin Li     max_symbol = 2 + VP8LReadBits(br, length_nbits);
276*b2055c35SXin Li     if (max_symbol > num_symbols) {
277*b2055c35SXin Li       goto End;
278*b2055c35SXin Li     }
279*b2055c35SXin Li   } else {
280*b2055c35SXin Li     max_symbol = num_symbols;
281*b2055c35SXin Li   }
282*b2055c35SXin Li 
283*b2055c35SXin Li   symbol = 0;
284*b2055c35SXin Li   while (symbol < num_symbols) {
285*b2055c35SXin Li     const HuffmanCode* p;
286*b2055c35SXin Li     int code_len;
287*b2055c35SXin Li     if (max_symbol-- == 0) break;
288*b2055c35SXin Li     VP8LFillBitWindow(br);
289*b2055c35SXin Li     p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];
290*b2055c35SXin Li     VP8LSetBitPos(br, br->bit_pos_ + p->bits);
291*b2055c35SXin Li     code_len = p->value;
292*b2055c35SXin Li     if (code_len < kCodeLengthLiterals) {
293*b2055c35SXin Li       code_lengths[symbol++] = code_len;
294*b2055c35SXin Li       if (code_len != 0) prev_code_len = code_len;
295*b2055c35SXin Li     } else {
296*b2055c35SXin Li       const int use_prev = (code_len == kCodeLengthRepeatCode);
297*b2055c35SXin Li       const int slot = code_len - kCodeLengthLiterals;
298*b2055c35SXin Li       const int extra_bits = kCodeLengthExtraBits[slot];
299*b2055c35SXin Li       const int repeat_offset = kCodeLengthRepeatOffsets[slot];
300*b2055c35SXin Li       int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
301*b2055c35SXin Li       if (symbol + repeat > num_symbols) {
302*b2055c35SXin Li         goto End;
303*b2055c35SXin Li       } else {
304*b2055c35SXin Li         const int length = use_prev ? prev_code_len : 0;
305*b2055c35SXin Li         while (repeat-- > 0) code_lengths[symbol++] = length;
306*b2055c35SXin Li       }
307*b2055c35SXin Li     }
308*b2055c35SXin Li   }
309*b2055c35SXin Li   ok = 1;
310*b2055c35SXin Li 
311*b2055c35SXin Li  End:
312*b2055c35SXin Li   VP8LHuffmanTablesDeallocate(&tables);
313*b2055c35SXin Li   if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
314*b2055c35SXin Li   return ok;
315*b2055c35SXin Li }
316*b2055c35SXin Li 
317*b2055c35SXin Li // 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
318*b2055c35SXin Li // tree.
ReadHuffmanCode(int alphabet_size,VP8LDecoder * const dec,int * const code_lengths,HuffmanTables * const table)319*b2055c35SXin Li static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
320*b2055c35SXin Li                            int* const code_lengths,
321*b2055c35SXin Li                            HuffmanTables* const table) {
322*b2055c35SXin Li   int ok = 0;
323*b2055c35SXin Li   int size = 0;
324*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
325*b2055c35SXin Li   const int simple_code = VP8LReadBits(br, 1);
326*b2055c35SXin Li 
327*b2055c35SXin Li   memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
328*b2055c35SXin Li 
329*b2055c35SXin Li   if (simple_code) {  // Read symbols, codes & code lengths directly.
330*b2055c35SXin Li     const int num_symbols = VP8LReadBits(br, 1) + 1;
331*b2055c35SXin Li     const int first_symbol_len_code = VP8LReadBits(br, 1);
332*b2055c35SXin Li     // The first code is either 1 bit or 8 bit code.
333*b2055c35SXin Li     int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
334*b2055c35SXin Li     code_lengths[symbol] = 1;
335*b2055c35SXin Li     // The second code (if present), is always 8 bits long.
336*b2055c35SXin Li     if (num_symbols == 2) {
337*b2055c35SXin Li       symbol = VP8LReadBits(br, 8);
338*b2055c35SXin Li       code_lengths[symbol] = 1;
339*b2055c35SXin Li     }
340*b2055c35SXin Li     ok = 1;
341*b2055c35SXin Li   } else {  // Decode Huffman-coded code lengths.
342*b2055c35SXin Li     int i;
343*b2055c35SXin Li     int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
344*b2055c35SXin Li     const int num_codes = VP8LReadBits(br, 4) + 4;
345*b2055c35SXin Li     assert(num_codes <= NUM_CODE_LENGTH_CODES);
346*b2055c35SXin Li 
347*b2055c35SXin Li     for (i = 0; i < num_codes; ++i) {
348*b2055c35SXin Li       code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
349*b2055c35SXin Li     }
350*b2055c35SXin Li     ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
351*b2055c35SXin Li                                 code_lengths);
352*b2055c35SXin Li   }
353*b2055c35SXin Li 
354*b2055c35SXin Li   ok = ok && !br->eos_;
355*b2055c35SXin Li   if (ok) {
356*b2055c35SXin Li     size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
357*b2055c35SXin Li                                  code_lengths, alphabet_size);
358*b2055c35SXin Li   }
359*b2055c35SXin Li   if (!ok || size == 0) {
360*b2055c35SXin Li     return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
361*b2055c35SXin Li   }
362*b2055c35SXin Li   return size;
363*b2055c35SXin Li }
364*b2055c35SXin Li 
ReadHuffmanCodes(VP8LDecoder * const dec,int xsize,int ysize,int color_cache_bits,int allow_recursion)365*b2055c35SXin Li static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
366*b2055c35SXin Li                             int color_cache_bits, int allow_recursion) {
367*b2055c35SXin Li   int i;
368*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
369*b2055c35SXin Li   VP8LMetadata* const hdr = &dec->hdr_;
370*b2055c35SXin Li   uint32_t* huffman_image = NULL;
371*b2055c35SXin Li   HTreeGroup* htree_groups = NULL;
372*b2055c35SXin Li   HuffmanTables* huffman_tables = &hdr->huffman_tables_;
373*b2055c35SXin Li   int num_htree_groups = 1;
374*b2055c35SXin Li   int num_htree_groups_max = 1;
375*b2055c35SXin Li   int* mapping = NULL;
376*b2055c35SXin Li   int ok = 0;
377*b2055c35SXin Li 
378*b2055c35SXin Li   // Check the table has been 0 initialized (through InitMetadata).
379*b2055c35SXin Li   assert(huffman_tables->root.start == NULL);
380*b2055c35SXin Li   assert(huffman_tables->curr_segment == NULL);
381*b2055c35SXin Li 
382*b2055c35SXin Li   if (allow_recursion && VP8LReadBits(br, 1)) {
383*b2055c35SXin Li     // use meta Huffman codes.
384*b2055c35SXin Li     const int huffman_precision = VP8LReadBits(br, 3) + 2;
385*b2055c35SXin Li     const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
386*b2055c35SXin Li     const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
387*b2055c35SXin Li     const int huffman_pixs = huffman_xsize * huffman_ysize;
388*b2055c35SXin Li     if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,
389*b2055c35SXin Li                            &huffman_image)) {
390*b2055c35SXin Li       goto Error;
391*b2055c35SXin Li     }
392*b2055c35SXin Li     hdr->huffman_subsample_bits_ = huffman_precision;
393*b2055c35SXin Li     for (i = 0; i < huffman_pixs; ++i) {
394*b2055c35SXin Li       // The huffman data is stored in red and green bytes.
395*b2055c35SXin Li       const int group = (huffman_image[i] >> 8) & 0xffff;
396*b2055c35SXin Li       huffman_image[i] = group;
397*b2055c35SXin Li       if (group >= num_htree_groups_max) {
398*b2055c35SXin Li         num_htree_groups_max = group + 1;
399*b2055c35SXin Li       }
400*b2055c35SXin Li     }
401*b2055c35SXin Li     // Check the validity of num_htree_groups_max. If it seems too big, use a
402*b2055c35SXin Li     // smaller value for later. This will prevent big memory allocations to end
403*b2055c35SXin Li     // up with a bad bitstream anyway.
404*b2055c35SXin Li     // The value of 1000 is totally arbitrary. We know that num_htree_groups_max
405*b2055c35SXin Li     // is smaller than (1 << 16) and should be smaller than the number of pixels
406*b2055c35SXin Li     // (though the format allows it to be bigger).
407*b2055c35SXin Li     if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
408*b2055c35SXin Li       // Create a mapping from the used indices to the minimal set of used
409*b2055c35SXin Li       // values [0, num_htree_groups)
410*b2055c35SXin Li       mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
411*b2055c35SXin Li       if (mapping == NULL) {
412*b2055c35SXin Li         VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
413*b2055c35SXin Li         goto Error;
414*b2055c35SXin Li       }
415*b2055c35SXin Li       // -1 means a value is unmapped, and therefore unused in the Huffman
416*b2055c35SXin Li       // image.
417*b2055c35SXin Li       memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));
418*b2055c35SXin Li       for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
419*b2055c35SXin Li         // Get the current mapping for the group and remap the Huffman image.
420*b2055c35SXin Li         int* const mapped_group = &mapping[huffman_image[i]];
421*b2055c35SXin Li         if (*mapped_group == -1) *mapped_group = num_htree_groups++;
422*b2055c35SXin Li         huffman_image[i] = *mapped_group;
423*b2055c35SXin Li       }
424*b2055c35SXin Li     } else {
425*b2055c35SXin Li       num_htree_groups = num_htree_groups_max;
426*b2055c35SXin Li     }
427*b2055c35SXin Li   }
428*b2055c35SXin Li 
429*b2055c35SXin Li   if (br->eos_) goto Error;
430*b2055c35SXin Li 
431*b2055c35SXin Li   if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,
432*b2055c35SXin Li                               num_htree_groups_max, mapping, dec,
433*b2055c35SXin Li                               huffman_tables, &htree_groups)) {
434*b2055c35SXin Li     goto Error;
435*b2055c35SXin Li   }
436*b2055c35SXin Li   ok = 1;
437*b2055c35SXin Li 
438*b2055c35SXin Li   // All OK. Finalize pointers.
439*b2055c35SXin Li   hdr->huffman_image_ = huffman_image;
440*b2055c35SXin Li   hdr->num_htree_groups_ = num_htree_groups;
441*b2055c35SXin Li   hdr->htree_groups_ = htree_groups;
442*b2055c35SXin Li 
443*b2055c35SXin Li  Error:
444*b2055c35SXin Li   WebPSafeFree(mapping);
445*b2055c35SXin Li   if (!ok) {
446*b2055c35SXin Li     WebPSafeFree(huffman_image);
447*b2055c35SXin Li     VP8LHuffmanTablesDeallocate(huffman_tables);
448*b2055c35SXin Li     VP8LHtreeGroupsFree(htree_groups);
449*b2055c35SXin Li   }
450*b2055c35SXin Li   return ok;
451*b2055c35SXin Li }
452*b2055c35SXin Li 
ReadHuffmanCodesHelper(int color_cache_bits,int num_htree_groups,int num_htree_groups_max,const int * const mapping,VP8LDecoder * const dec,HuffmanTables * const huffman_tables,HTreeGroup ** const htree_groups)453*b2055c35SXin Li int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,
454*b2055c35SXin Li                            int num_htree_groups_max, const int* const mapping,
455*b2055c35SXin Li                            VP8LDecoder* const dec,
456*b2055c35SXin Li                            HuffmanTables* const huffman_tables,
457*b2055c35SXin Li                            HTreeGroup** const htree_groups) {
458*b2055c35SXin Li   int i, j, ok = 0;
459*b2055c35SXin Li   const int max_alphabet_size =
460*b2055c35SXin Li       kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);
461*b2055c35SXin Li   const int table_size = kTableSize[color_cache_bits];
462*b2055c35SXin Li   int* code_lengths = NULL;
463*b2055c35SXin Li 
464*b2055c35SXin Li   if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||
465*b2055c35SXin Li       num_htree_groups > num_htree_groups_max) {
466*b2055c35SXin Li     goto Error;
467*b2055c35SXin Li   }
468*b2055c35SXin Li 
469*b2055c35SXin Li   code_lengths =
470*b2055c35SXin Li       (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
471*b2055c35SXin Li   *htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
472*b2055c35SXin Li 
473*b2055c35SXin Li   if (*htree_groups == NULL || code_lengths == NULL ||
474*b2055c35SXin Li       !VP8LHuffmanTablesAllocate(num_htree_groups * table_size,
475*b2055c35SXin Li                                  huffman_tables)) {
476*b2055c35SXin Li     VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
477*b2055c35SXin Li     goto Error;
478*b2055c35SXin Li   }
479*b2055c35SXin Li 
480*b2055c35SXin Li   for (i = 0; i < num_htree_groups_max; ++i) {
481*b2055c35SXin Li     // If the index "i" is unused in the Huffman image, just make sure the
482*b2055c35SXin Li     // coefficients are valid but do not store them.
483*b2055c35SXin Li     if (mapping != NULL && mapping[i] == -1) {
484*b2055c35SXin Li       for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
485*b2055c35SXin Li         int alphabet_size = kAlphabetSize[j];
486*b2055c35SXin Li         if (j == 0 && color_cache_bits > 0) {
487*b2055c35SXin Li           alphabet_size += (1 << color_cache_bits);
488*b2055c35SXin Li         }
489*b2055c35SXin Li         // Passing in NULL so that nothing gets filled.
490*b2055c35SXin Li         if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {
491*b2055c35SXin Li           goto Error;
492*b2055c35SXin Li         }
493*b2055c35SXin Li       }
494*b2055c35SXin Li     } else {
495*b2055c35SXin Li       HTreeGroup* const htree_group =
496*b2055c35SXin Li           &(*htree_groups)[(mapping == NULL) ? i : mapping[i]];
497*b2055c35SXin Li       HuffmanCode** const htrees = htree_group->htrees;
498*b2055c35SXin Li       int size;
499*b2055c35SXin Li       int total_size = 0;
500*b2055c35SXin Li       int is_trivial_literal = 1;
501*b2055c35SXin Li       int max_bits = 0;
502*b2055c35SXin Li       for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
503*b2055c35SXin Li         int alphabet_size = kAlphabetSize[j];
504*b2055c35SXin Li         if (j == 0 && color_cache_bits > 0) {
505*b2055c35SXin Li           alphabet_size += (1 << color_cache_bits);
506*b2055c35SXin Li         }
507*b2055c35SXin Li         size =
508*b2055c35SXin Li             ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
509*b2055c35SXin Li         htrees[j] = huffman_tables->curr_segment->curr_table;
510*b2055c35SXin Li         if (size == 0) {
511*b2055c35SXin Li           goto Error;
512*b2055c35SXin Li         }
513*b2055c35SXin Li         if (is_trivial_literal && kLiteralMap[j] == 1) {
514*b2055c35SXin Li           is_trivial_literal = (htrees[j]->bits == 0);
515*b2055c35SXin Li         }
516*b2055c35SXin Li         total_size += htrees[j]->bits;
517*b2055c35SXin Li         huffman_tables->curr_segment->curr_table += size;
518*b2055c35SXin Li         if (j <= ALPHA) {
519*b2055c35SXin Li           int local_max_bits = code_lengths[0];
520*b2055c35SXin Li           int k;
521*b2055c35SXin Li           for (k = 1; k < alphabet_size; ++k) {
522*b2055c35SXin Li             if (code_lengths[k] > local_max_bits) {
523*b2055c35SXin Li               local_max_bits = code_lengths[k];
524*b2055c35SXin Li             }
525*b2055c35SXin Li           }
526*b2055c35SXin Li           max_bits += local_max_bits;
527*b2055c35SXin Li         }
528*b2055c35SXin Li       }
529*b2055c35SXin Li       htree_group->is_trivial_literal = is_trivial_literal;
530*b2055c35SXin Li       htree_group->is_trivial_code = 0;
531*b2055c35SXin Li       if (is_trivial_literal) {
532*b2055c35SXin Li         const int red = htrees[RED][0].value;
533*b2055c35SXin Li         const int blue = htrees[BLUE][0].value;
534*b2055c35SXin Li         const int alpha = htrees[ALPHA][0].value;
535*b2055c35SXin Li         htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
536*b2055c35SXin Li         if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
537*b2055c35SXin Li           htree_group->is_trivial_code = 1;
538*b2055c35SXin Li           htree_group->literal_arb |= htrees[GREEN][0].value << 8;
539*b2055c35SXin Li         }
540*b2055c35SXin Li       }
541*b2055c35SXin Li       htree_group->use_packed_table =
542*b2055c35SXin Li           !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
543*b2055c35SXin Li       if (htree_group->use_packed_table) BuildPackedTable(htree_group);
544*b2055c35SXin Li     }
545*b2055c35SXin Li   }
546*b2055c35SXin Li   ok = 1;
547*b2055c35SXin Li 
548*b2055c35SXin Li  Error:
549*b2055c35SXin Li   WebPSafeFree(code_lengths);
550*b2055c35SXin Li   if (!ok) {
551*b2055c35SXin Li     VP8LHuffmanTablesDeallocate(huffman_tables);
552*b2055c35SXin Li     VP8LHtreeGroupsFree(*htree_groups);
553*b2055c35SXin Li     *htree_groups = NULL;
554*b2055c35SXin Li   }
555*b2055c35SXin Li   return ok;
556*b2055c35SXin Li }
557*b2055c35SXin Li 
558*b2055c35SXin Li //------------------------------------------------------------------------------
559*b2055c35SXin Li // Scaling.
560*b2055c35SXin Li 
561*b2055c35SXin Li #if !defined(WEBP_REDUCE_SIZE)
AllocateAndInitRescaler(VP8LDecoder * const dec,VP8Io * const io)562*b2055c35SXin Li static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
563*b2055c35SXin Li   const int num_channels = 4;
564*b2055c35SXin Li   const int in_width = io->mb_w;
565*b2055c35SXin Li   const int out_width = io->scaled_width;
566*b2055c35SXin Li   const int in_height = io->mb_h;
567*b2055c35SXin Li   const int out_height = io->scaled_height;
568*b2055c35SXin Li   const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
569*b2055c35SXin Li   rescaler_t* work;        // Rescaler work area.
570*b2055c35SXin Li   const uint64_t scaled_data_size = (uint64_t)out_width;
571*b2055c35SXin Li   uint32_t* scaled_data;  // Temporary storage for scaled BGRA data.
572*b2055c35SXin Li   const uint64_t memory_size = sizeof(*dec->rescaler) +
573*b2055c35SXin Li                                work_size * sizeof(*work) +
574*b2055c35SXin Li                                scaled_data_size * sizeof(*scaled_data);
575*b2055c35SXin Li   uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));
576*b2055c35SXin Li   if (memory == NULL) {
577*b2055c35SXin Li     return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
578*b2055c35SXin Li   }
579*b2055c35SXin Li   assert(dec->rescaler_memory == NULL);
580*b2055c35SXin Li   dec->rescaler_memory = memory;
581*b2055c35SXin Li 
582*b2055c35SXin Li   dec->rescaler = (WebPRescaler*)memory;
583*b2055c35SXin Li   memory += sizeof(*dec->rescaler);
584*b2055c35SXin Li   work = (rescaler_t*)memory;
585*b2055c35SXin Li   memory += work_size * sizeof(*work);
586*b2055c35SXin Li   scaled_data = (uint32_t*)memory;
587*b2055c35SXin Li 
588*b2055c35SXin Li   if (!WebPRescalerInit(dec->rescaler, in_width, in_height,
589*b2055c35SXin Li                         (uint8_t*)scaled_data, out_width, out_height,
590*b2055c35SXin Li                         0, num_channels, work)) {
591*b2055c35SXin Li     return 0;
592*b2055c35SXin Li   }
593*b2055c35SXin Li   return 1;
594*b2055c35SXin Li }
595*b2055c35SXin Li #endif   // WEBP_REDUCE_SIZE
596*b2055c35SXin Li 
597*b2055c35SXin Li //------------------------------------------------------------------------------
598*b2055c35SXin Li // Export to ARGB
599*b2055c35SXin Li 
600*b2055c35SXin Li #if !defined(WEBP_REDUCE_SIZE)
601*b2055c35SXin Li 
602*b2055c35SXin Li // We have special "export" function since we need to convert from BGRA
Export(WebPRescaler * const rescaler,WEBP_CSP_MODE colorspace,int rgba_stride,uint8_t * const rgba)603*b2055c35SXin Li static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
604*b2055c35SXin Li                   int rgba_stride, uint8_t* const rgba) {
605*b2055c35SXin Li   uint32_t* const src = (uint32_t*)rescaler->dst;
606*b2055c35SXin Li   uint8_t* dst = rgba;
607*b2055c35SXin Li   const int dst_width = rescaler->dst_width;
608*b2055c35SXin Li   int num_lines_out = 0;
609*b2055c35SXin Li   while (WebPRescalerHasPendingOutput(rescaler)) {
610*b2055c35SXin Li     WebPRescalerExportRow(rescaler);
611*b2055c35SXin Li     WebPMultARGBRow(src, dst_width, 1);
612*b2055c35SXin Li     VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
613*b2055c35SXin Li     dst += rgba_stride;
614*b2055c35SXin Li     ++num_lines_out;
615*b2055c35SXin Li   }
616*b2055c35SXin Li   return num_lines_out;
617*b2055c35SXin Li }
618*b2055c35SXin Li 
619*b2055c35SXin Li // Emit scaled rows.
EmitRescaledRowsRGBA(const VP8LDecoder * const dec,uint8_t * in,int in_stride,int mb_h,uint8_t * const out,int out_stride)620*b2055c35SXin Li static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
621*b2055c35SXin Li                                 uint8_t* in, int in_stride, int mb_h,
622*b2055c35SXin Li                                 uint8_t* const out, int out_stride) {
623*b2055c35SXin Li   const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
624*b2055c35SXin Li   int num_lines_in = 0;
625*b2055c35SXin Li   int num_lines_out = 0;
626*b2055c35SXin Li   while (num_lines_in < mb_h) {
627*b2055c35SXin Li     uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride;
628*b2055c35SXin Li     uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride;
629*b2055c35SXin Li     const int lines_left = mb_h - num_lines_in;
630*b2055c35SXin Li     const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
631*b2055c35SXin Li     int lines_imported;
632*b2055c35SXin Li     assert(needed_lines > 0 && needed_lines <= lines_left);
633*b2055c35SXin Li     WebPMultARGBRows(row_in, in_stride,
634*b2055c35SXin Li                      dec->rescaler->src_width, needed_lines, 0);
635*b2055c35SXin Li     lines_imported =
636*b2055c35SXin Li         WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
637*b2055c35SXin Li     assert(lines_imported == needed_lines);
638*b2055c35SXin Li     num_lines_in += lines_imported;
639*b2055c35SXin Li     num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
640*b2055c35SXin Li   }
641*b2055c35SXin Li   return num_lines_out;
642*b2055c35SXin Li }
643*b2055c35SXin Li 
644*b2055c35SXin Li #endif   // WEBP_REDUCE_SIZE
645*b2055c35SXin Li 
646*b2055c35SXin Li // Emit rows without any scaling.
EmitRows(WEBP_CSP_MODE colorspace,const uint8_t * row_in,int in_stride,int mb_w,int mb_h,uint8_t * const out,int out_stride)647*b2055c35SXin Li static int EmitRows(WEBP_CSP_MODE colorspace,
648*b2055c35SXin Li                     const uint8_t* row_in, int in_stride,
649*b2055c35SXin Li                     int mb_w, int mb_h,
650*b2055c35SXin Li                     uint8_t* const out, int out_stride) {
651*b2055c35SXin Li   int lines = mb_h;
652*b2055c35SXin Li   uint8_t* row_out = out;
653*b2055c35SXin Li   while (lines-- > 0) {
654*b2055c35SXin Li     VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
655*b2055c35SXin Li     row_in += in_stride;
656*b2055c35SXin Li     row_out += out_stride;
657*b2055c35SXin Li   }
658*b2055c35SXin Li   return mb_h;  // Num rows out == num rows in.
659*b2055c35SXin Li }
660*b2055c35SXin Li 
661*b2055c35SXin Li //------------------------------------------------------------------------------
662*b2055c35SXin Li // Export to YUVA
663*b2055c35SXin Li 
ConvertToYUVA(const uint32_t * const src,int width,int y_pos,const WebPDecBuffer * const output)664*b2055c35SXin Li static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
665*b2055c35SXin Li                           const WebPDecBuffer* const output) {
666*b2055c35SXin Li   const WebPYUVABuffer* const buf = &output->u.YUVA;
667*b2055c35SXin Li 
668*b2055c35SXin Li   // first, the luma plane
669*b2055c35SXin Li   WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);
670*b2055c35SXin Li 
671*b2055c35SXin Li   // then U/V planes
672*b2055c35SXin Li   {
673*b2055c35SXin Li     uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
674*b2055c35SXin Li     uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
675*b2055c35SXin Li     // even lines: store values
676*b2055c35SXin Li     // odd lines: average with previous values
677*b2055c35SXin Li     WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));
678*b2055c35SXin Li   }
679*b2055c35SXin Li   // Lastly, store alpha if needed.
680*b2055c35SXin Li   if (buf->a != NULL) {
681*b2055c35SXin Li     uint8_t* const a = buf->a + y_pos * buf->a_stride;
682*b2055c35SXin Li #if defined(WORDS_BIGENDIAN)
683*b2055c35SXin Li     WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);
684*b2055c35SXin Li #else
685*b2055c35SXin Li     WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);
686*b2055c35SXin Li #endif
687*b2055c35SXin Li   }
688*b2055c35SXin Li }
689*b2055c35SXin Li 
ExportYUVA(const VP8LDecoder * const dec,int y_pos)690*b2055c35SXin Li static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
691*b2055c35SXin Li   WebPRescaler* const rescaler = dec->rescaler;
692*b2055c35SXin Li   uint32_t* const src = (uint32_t*)rescaler->dst;
693*b2055c35SXin Li   const int dst_width = rescaler->dst_width;
694*b2055c35SXin Li   int num_lines_out = 0;
695*b2055c35SXin Li   while (WebPRescalerHasPendingOutput(rescaler)) {
696*b2055c35SXin Li     WebPRescalerExportRow(rescaler);
697*b2055c35SXin Li     WebPMultARGBRow(src, dst_width, 1);
698*b2055c35SXin Li     ConvertToYUVA(src, dst_width, y_pos, dec->output_);
699*b2055c35SXin Li     ++y_pos;
700*b2055c35SXin Li     ++num_lines_out;
701*b2055c35SXin Li   }
702*b2055c35SXin Li   return num_lines_out;
703*b2055c35SXin Li }
704*b2055c35SXin Li 
EmitRescaledRowsYUVA(const VP8LDecoder * const dec,uint8_t * in,int in_stride,int mb_h)705*b2055c35SXin Li static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
706*b2055c35SXin Li                                 uint8_t* in, int in_stride, int mb_h) {
707*b2055c35SXin Li   int num_lines_in = 0;
708*b2055c35SXin Li   int y_pos = dec->last_out_row_;
709*b2055c35SXin Li   while (num_lines_in < mb_h) {
710*b2055c35SXin Li     const int lines_left = mb_h - num_lines_in;
711*b2055c35SXin Li     const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
712*b2055c35SXin Li     int lines_imported;
713*b2055c35SXin Li     WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
714*b2055c35SXin Li     lines_imported =
715*b2055c35SXin Li         WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
716*b2055c35SXin Li     assert(lines_imported == needed_lines);
717*b2055c35SXin Li     num_lines_in += lines_imported;
718*b2055c35SXin Li     in += needed_lines * in_stride;
719*b2055c35SXin Li     y_pos += ExportYUVA(dec, y_pos);
720*b2055c35SXin Li   }
721*b2055c35SXin Li   return y_pos;
722*b2055c35SXin Li }
723*b2055c35SXin Li 
EmitRowsYUVA(const VP8LDecoder * const dec,const uint8_t * in,int in_stride,int mb_w,int num_rows)724*b2055c35SXin Li static int EmitRowsYUVA(const VP8LDecoder* const dec,
725*b2055c35SXin Li                         const uint8_t* in, int in_stride,
726*b2055c35SXin Li                         int mb_w, int num_rows) {
727*b2055c35SXin Li   int y_pos = dec->last_out_row_;
728*b2055c35SXin Li   while (num_rows-- > 0) {
729*b2055c35SXin Li     ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
730*b2055c35SXin Li     in += in_stride;
731*b2055c35SXin Li     ++y_pos;
732*b2055c35SXin Li   }
733*b2055c35SXin Li   return y_pos;
734*b2055c35SXin Li }
735*b2055c35SXin Li 
736*b2055c35SXin Li //------------------------------------------------------------------------------
737*b2055c35SXin Li // Cropping.
738*b2055c35SXin Li 
739*b2055c35SXin Li // Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
740*b2055c35SXin Li // crop options. Also updates the input data pointer, so that it points to the
741*b2055c35SXin Li // start of the cropped window. Note that pixels are in ARGB format even if
742*b2055c35SXin Li // 'in_data' is uint8_t*.
743*b2055c35SXin Li // Returns true if the crop window is not empty.
SetCropWindow(VP8Io * const io,int y_start,int y_end,uint8_t ** const in_data,int pixel_stride)744*b2055c35SXin Li static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
745*b2055c35SXin Li                          uint8_t** const in_data, int pixel_stride) {
746*b2055c35SXin Li   assert(y_start < y_end);
747*b2055c35SXin Li   assert(io->crop_left < io->crop_right);
748*b2055c35SXin Li   if (y_end > io->crop_bottom) {
749*b2055c35SXin Li     y_end = io->crop_bottom;  // make sure we don't overflow on last row.
750*b2055c35SXin Li   }
751*b2055c35SXin Li   if (y_start < io->crop_top) {
752*b2055c35SXin Li     const int delta = io->crop_top - y_start;
753*b2055c35SXin Li     y_start = io->crop_top;
754*b2055c35SXin Li     *in_data += delta * pixel_stride;
755*b2055c35SXin Li   }
756*b2055c35SXin Li   if (y_start >= y_end) return 0;  // Crop window is empty.
757*b2055c35SXin Li 
758*b2055c35SXin Li   *in_data += io->crop_left * sizeof(uint32_t);
759*b2055c35SXin Li 
760*b2055c35SXin Li   io->mb_y = y_start - io->crop_top;
761*b2055c35SXin Li   io->mb_w = io->crop_right - io->crop_left;
762*b2055c35SXin Li   io->mb_h = y_end - y_start;
763*b2055c35SXin Li   return 1;  // Non-empty crop window.
764*b2055c35SXin Li }
765*b2055c35SXin Li 
766*b2055c35SXin Li //------------------------------------------------------------------------------
767*b2055c35SXin Li 
GetMetaIndex(const uint32_t * const image,int xsize,int bits,int x,int y)768*b2055c35SXin Li static WEBP_INLINE int GetMetaIndex(
769*b2055c35SXin Li     const uint32_t* const image, int xsize, int bits, int x, int y) {
770*b2055c35SXin Li   if (bits == 0) return 0;
771*b2055c35SXin Li   return image[xsize * (y >> bits) + (x >> bits)];
772*b2055c35SXin Li }
773*b2055c35SXin Li 
GetHtreeGroupForPos(VP8LMetadata * const hdr,int x,int y)774*b2055c35SXin Li static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
775*b2055c35SXin Li                                                    int x, int y) {
776*b2055c35SXin Li   const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
777*b2055c35SXin Li                                       hdr->huffman_subsample_bits_, x, y);
778*b2055c35SXin Li   assert(meta_index < hdr->num_htree_groups_);
779*b2055c35SXin Li   return hdr->htree_groups_ + meta_index;
780*b2055c35SXin Li }
781*b2055c35SXin Li 
782*b2055c35SXin Li //------------------------------------------------------------------------------
783*b2055c35SXin Li // Main loop, with custom row-processing function
784*b2055c35SXin Li 
785*b2055c35SXin Li typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
786*b2055c35SXin Li 
ApplyInverseTransforms(VP8LDecoder * const dec,int start_row,int num_rows,const uint32_t * const rows)787*b2055c35SXin Li static void ApplyInverseTransforms(VP8LDecoder* const dec,
788*b2055c35SXin Li                                    int start_row, int num_rows,
789*b2055c35SXin Li                                    const uint32_t* const rows) {
790*b2055c35SXin Li   int n = dec->next_transform_;
791*b2055c35SXin Li   const int cache_pixs = dec->width_ * num_rows;
792*b2055c35SXin Li   const int end_row = start_row + num_rows;
793*b2055c35SXin Li   const uint32_t* rows_in = rows;
794*b2055c35SXin Li   uint32_t* const rows_out = dec->argb_cache_;
795*b2055c35SXin Li 
796*b2055c35SXin Li   // Inverse transforms.
797*b2055c35SXin Li   while (n-- > 0) {
798*b2055c35SXin Li     VP8LTransform* const transform = &dec->transforms_[n];
799*b2055c35SXin Li     VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
800*b2055c35SXin Li     rows_in = rows_out;
801*b2055c35SXin Li   }
802*b2055c35SXin Li   if (rows_in != rows_out) {
803*b2055c35SXin Li     // No transform called, hence just copy.
804*b2055c35SXin Li     memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
805*b2055c35SXin Li   }
806*b2055c35SXin Li }
807*b2055c35SXin Li 
808*b2055c35SXin Li // Processes (transforms, scales & color-converts) the rows decoded after the
809*b2055c35SXin Li // last call.
ProcessRows(VP8LDecoder * const dec,int row)810*b2055c35SXin Li static void ProcessRows(VP8LDecoder* const dec, int row) {
811*b2055c35SXin Li   const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
812*b2055c35SXin Li   const int num_rows = row - dec->last_row_;
813*b2055c35SXin Li 
814*b2055c35SXin Li   assert(row <= dec->io_->crop_bottom);
815*b2055c35SXin Li   // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
816*b2055c35SXin Li   // of argb_cache_), but we currently don't need more than that.
817*b2055c35SXin Li   assert(num_rows <= NUM_ARGB_CACHE_ROWS);
818*b2055c35SXin Li   if (num_rows > 0) {    // Emit output.
819*b2055c35SXin Li     VP8Io* const io = dec->io_;
820*b2055c35SXin Li     uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
821*b2055c35SXin Li     const int in_stride = io->width * sizeof(uint32_t);  // in unit of RGBA
822*b2055c35SXin Li     ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
823*b2055c35SXin Li     if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
824*b2055c35SXin Li       // Nothing to output (this time).
825*b2055c35SXin Li     } else {
826*b2055c35SXin Li       const WebPDecBuffer* const output = dec->output_;
827*b2055c35SXin Li       if (WebPIsRGBMode(output->colorspace)) {  // convert to RGBA
828*b2055c35SXin Li         const WebPRGBABuffer* const buf = &output->u.RGBA;
829*b2055c35SXin Li         uint8_t* const rgba =
830*b2055c35SXin Li             buf->rgba + (int64_t)dec->last_out_row_ * buf->stride;
831*b2055c35SXin Li         const int num_rows_out =
832*b2055c35SXin Li #if !defined(WEBP_REDUCE_SIZE)
833*b2055c35SXin Li          io->use_scaling ?
834*b2055c35SXin Li             EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
835*b2055c35SXin Li                                  rgba, buf->stride) :
836*b2055c35SXin Li #endif  // WEBP_REDUCE_SIZE
837*b2055c35SXin Li             EmitRows(output->colorspace, rows_data, in_stride,
838*b2055c35SXin Li                      io->mb_w, io->mb_h, rgba, buf->stride);
839*b2055c35SXin Li         // Update 'last_out_row_'.
840*b2055c35SXin Li         dec->last_out_row_ += num_rows_out;
841*b2055c35SXin Li       } else {                              // convert to YUVA
842*b2055c35SXin Li         dec->last_out_row_ = io->use_scaling ?
843*b2055c35SXin Li             EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
844*b2055c35SXin Li             EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
845*b2055c35SXin Li       }
846*b2055c35SXin Li       assert(dec->last_out_row_ <= output->height);
847*b2055c35SXin Li     }
848*b2055c35SXin Li   }
849*b2055c35SXin Li 
850*b2055c35SXin Li   // Update 'last_row_'.
851*b2055c35SXin Li   dec->last_row_ = row;
852*b2055c35SXin Li   assert(dec->last_row_ <= dec->height_);
853*b2055c35SXin Li }
854*b2055c35SXin Li 
855*b2055c35SXin Li // Row-processing for the special case when alpha data contains only one
856*b2055c35SXin Li // transform (color indexing), and trivial non-green literals.
Is8bOptimizable(const VP8LMetadata * const hdr)857*b2055c35SXin Li static int Is8bOptimizable(const VP8LMetadata* const hdr) {
858*b2055c35SXin Li   int i;
859*b2055c35SXin Li   if (hdr->color_cache_size_ > 0) return 0;
860*b2055c35SXin Li   // When the Huffman tree contains only one symbol, we can skip the
861*b2055c35SXin Li   // call to ReadSymbol() for red/blue/alpha channels.
862*b2055c35SXin Li   for (i = 0; i < hdr->num_htree_groups_; ++i) {
863*b2055c35SXin Li     HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;
864*b2055c35SXin Li     if (htrees[RED][0].bits > 0) return 0;
865*b2055c35SXin Li     if (htrees[BLUE][0].bits > 0) return 0;
866*b2055c35SXin Li     if (htrees[ALPHA][0].bits > 0) return 0;
867*b2055c35SXin Li   }
868*b2055c35SXin Li   return 1;
869*b2055c35SXin Li }
870*b2055c35SXin Li 
AlphaApplyFilter(ALPHDecoder * const alph_dec,int first_row,int last_row,uint8_t * out,int stride)871*b2055c35SXin Li static void AlphaApplyFilter(ALPHDecoder* const alph_dec,
872*b2055c35SXin Li                              int first_row, int last_row,
873*b2055c35SXin Li                              uint8_t* out, int stride) {
874*b2055c35SXin Li   if (alph_dec->filter_ != WEBP_FILTER_NONE) {
875*b2055c35SXin Li     int y;
876*b2055c35SXin Li     const uint8_t* prev_line = alph_dec->prev_line_;
877*b2055c35SXin Li     assert(WebPUnfilters[alph_dec->filter_] != NULL);
878*b2055c35SXin Li     for (y = first_row; y < last_row; ++y) {
879*b2055c35SXin Li       WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);
880*b2055c35SXin Li       prev_line = out;
881*b2055c35SXin Li       out += stride;
882*b2055c35SXin Li     }
883*b2055c35SXin Li     alph_dec->prev_line_ = prev_line;
884*b2055c35SXin Li   }
885*b2055c35SXin Li }
886*b2055c35SXin Li 
ExtractPalettedAlphaRows(VP8LDecoder * const dec,int last_row)887*b2055c35SXin Li static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
888*b2055c35SXin Li   // For vertical and gradient filtering, we need to decode the part above the
889*b2055c35SXin Li   // crop_top row, in order to have the correct spatial predictors.
890*b2055c35SXin Li   ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
891*b2055c35SXin Li   const int top_row =
892*b2055c35SXin Li       (alph_dec->filter_ == WEBP_FILTER_NONE ||
893*b2055c35SXin Li        alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
894*b2055c35SXin Li                                                     : dec->last_row_;
895*b2055c35SXin Li   const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
896*b2055c35SXin Li   assert(last_row <= dec->io_->crop_bottom);
897*b2055c35SXin Li   if (last_row > first_row) {
898*b2055c35SXin Li     // Special method for paletted alpha data. We only process the cropped area.
899*b2055c35SXin Li     const int width = dec->io_->width;
900*b2055c35SXin Li     uint8_t* out = alph_dec->output_ + width * first_row;
901*b2055c35SXin Li     const uint8_t* const in =
902*b2055c35SXin Li       (uint8_t*)dec->pixels_ + dec->width_ * first_row;
903*b2055c35SXin Li     VP8LTransform* const transform = &dec->transforms_[0];
904*b2055c35SXin Li     assert(dec->next_transform_ == 1);
905*b2055c35SXin Li     assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
906*b2055c35SXin Li     VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
907*b2055c35SXin Li                                         in, out);
908*b2055c35SXin Li     AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
909*b2055c35SXin Li   }
910*b2055c35SXin Li   dec->last_row_ = dec->last_out_row_ = last_row;
911*b2055c35SXin Li }
912*b2055c35SXin Li 
913*b2055c35SXin Li //------------------------------------------------------------------------------
914*b2055c35SXin Li // Helper functions for fast pattern copy (8b and 32b)
915*b2055c35SXin Li 
916*b2055c35SXin Li // cyclic rotation of pattern word
Rotate8b(uint32_t V)917*b2055c35SXin Li static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {
918*b2055c35SXin Li #if defined(WORDS_BIGENDIAN)
919*b2055c35SXin Li   return ((V & 0xff000000u) >> 24) | (V << 8);
920*b2055c35SXin Li #else
921*b2055c35SXin Li   return ((V & 0xffu) << 24) | (V >> 8);
922*b2055c35SXin Li #endif
923*b2055c35SXin Li }
924*b2055c35SXin Li 
925*b2055c35SXin Li // copy 1, 2 or 4-bytes pattern
CopySmallPattern8b(const uint8_t * src,uint8_t * dst,int length,uint32_t pattern)926*b2055c35SXin Li static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,
927*b2055c35SXin Li                                            int length, uint32_t pattern) {
928*b2055c35SXin Li   int i;
929*b2055c35SXin Li   // align 'dst' to 4-bytes boundary. Adjust the pattern along the way.
930*b2055c35SXin Li   while ((uintptr_t)dst & 3) {
931*b2055c35SXin Li     *dst++ = *src++;
932*b2055c35SXin Li     pattern = Rotate8b(pattern);
933*b2055c35SXin Li     --length;
934*b2055c35SXin Li   }
935*b2055c35SXin Li   // Copy the pattern 4 bytes at a time.
936*b2055c35SXin Li   for (i = 0; i < (length >> 2); ++i) {
937*b2055c35SXin Li     ((uint32_t*)dst)[i] = pattern;
938*b2055c35SXin Li   }
939*b2055c35SXin Li   // Finish with left-overs. 'pattern' is still correctly positioned,
940*b2055c35SXin Li   // so no Rotate8b() call is needed.
941*b2055c35SXin Li   for (i <<= 2; i < length; ++i) {
942*b2055c35SXin Li     dst[i] = src[i];
943*b2055c35SXin Li   }
944*b2055c35SXin Li }
945*b2055c35SXin Li 
CopyBlock8b(uint8_t * const dst,int dist,int length)946*b2055c35SXin Li static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {
947*b2055c35SXin Li   const uint8_t* src = dst - dist;
948*b2055c35SXin Li   if (length >= 8) {
949*b2055c35SXin Li     uint32_t pattern = 0;
950*b2055c35SXin Li     switch (dist) {
951*b2055c35SXin Li       case 1:
952*b2055c35SXin Li         pattern = src[0];
953*b2055c35SXin Li #if defined(__arm__) || defined(_M_ARM)   // arm doesn't like multiply that much
954*b2055c35SXin Li         pattern |= pattern << 8;
955*b2055c35SXin Li         pattern |= pattern << 16;
956*b2055c35SXin Li #elif defined(WEBP_USE_MIPS_DSP_R2)
957*b2055c35SXin Li         __asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));
958*b2055c35SXin Li #else
959*b2055c35SXin Li         pattern = 0x01010101u * pattern;
960*b2055c35SXin Li #endif
961*b2055c35SXin Li         break;
962*b2055c35SXin Li       case 2:
963*b2055c35SXin Li #if !defined(WORDS_BIGENDIAN)
964*b2055c35SXin Li         memcpy(&pattern, src, sizeof(uint16_t));
965*b2055c35SXin Li #else
966*b2055c35SXin Li         pattern = ((uint32_t)src[0] << 8) | src[1];
967*b2055c35SXin Li #endif
968*b2055c35SXin Li #if defined(__arm__) || defined(_M_ARM)
969*b2055c35SXin Li         pattern |= pattern << 16;
970*b2055c35SXin Li #elif defined(WEBP_USE_MIPS_DSP_R2)
971*b2055c35SXin Li         __asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));
972*b2055c35SXin Li #else
973*b2055c35SXin Li         pattern = 0x00010001u * pattern;
974*b2055c35SXin Li #endif
975*b2055c35SXin Li         break;
976*b2055c35SXin Li       case 4:
977*b2055c35SXin Li         memcpy(&pattern, src, sizeof(uint32_t));
978*b2055c35SXin Li         break;
979*b2055c35SXin Li       default:
980*b2055c35SXin Li         goto Copy;
981*b2055c35SXin Li     }
982*b2055c35SXin Li     CopySmallPattern8b(src, dst, length, pattern);
983*b2055c35SXin Li     return;
984*b2055c35SXin Li   }
985*b2055c35SXin Li  Copy:
986*b2055c35SXin Li   if (dist >= length) {  // no overlap -> use memcpy()
987*b2055c35SXin Li     memcpy(dst, src, length * sizeof(*dst));
988*b2055c35SXin Li   } else {
989*b2055c35SXin Li     int i;
990*b2055c35SXin Li     for (i = 0; i < length; ++i) dst[i] = src[i];
991*b2055c35SXin Li   }
992*b2055c35SXin Li }
993*b2055c35SXin Li 
994*b2055c35SXin Li // copy pattern of 1 or 2 uint32_t's
CopySmallPattern32b(const uint32_t * src,uint32_t * dst,int length,uint64_t pattern)995*b2055c35SXin Li static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,
996*b2055c35SXin Li                                             uint32_t* dst,
997*b2055c35SXin Li                                             int length, uint64_t pattern) {
998*b2055c35SXin Li   int i;
999*b2055c35SXin Li   if ((uintptr_t)dst & 4) {           // Align 'dst' to 8-bytes boundary.
1000*b2055c35SXin Li     *dst++ = *src++;
1001*b2055c35SXin Li     pattern = (pattern >> 32) | (pattern << 32);
1002*b2055c35SXin Li     --length;
1003*b2055c35SXin Li   }
1004*b2055c35SXin Li   assert(0 == ((uintptr_t)dst & 7));
1005*b2055c35SXin Li   for (i = 0; i < (length >> 1); ++i) {
1006*b2055c35SXin Li     ((uint64_t*)dst)[i] = pattern;    // Copy the pattern 8 bytes at a time.
1007*b2055c35SXin Li   }
1008*b2055c35SXin Li   if (length & 1) {                   // Finish with left-over.
1009*b2055c35SXin Li     dst[i << 1] = src[i << 1];
1010*b2055c35SXin Li   }
1011*b2055c35SXin Li }
1012*b2055c35SXin Li 
CopyBlock32b(uint32_t * const dst,int dist,int length)1013*b2055c35SXin Li static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,
1014*b2055c35SXin Li                                      int dist, int length) {
1015*b2055c35SXin Li   const uint32_t* const src = dst - dist;
1016*b2055c35SXin Li   if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {
1017*b2055c35SXin Li     uint64_t pattern;
1018*b2055c35SXin Li     if (dist == 1) {
1019*b2055c35SXin Li       pattern = (uint64_t)src[0];
1020*b2055c35SXin Li       pattern |= pattern << 32;
1021*b2055c35SXin Li     } else {
1022*b2055c35SXin Li       memcpy(&pattern, src, sizeof(pattern));
1023*b2055c35SXin Li     }
1024*b2055c35SXin Li     CopySmallPattern32b(src, dst, length, pattern);
1025*b2055c35SXin Li   } else if (dist >= length) {  // no overlap
1026*b2055c35SXin Li     memcpy(dst, src, length * sizeof(*dst));
1027*b2055c35SXin Li   } else {
1028*b2055c35SXin Li     int i;
1029*b2055c35SXin Li     for (i = 0; i < length; ++i) dst[i] = src[i];
1030*b2055c35SXin Li   }
1031*b2055c35SXin Li }
1032*b2055c35SXin Li 
1033*b2055c35SXin Li //------------------------------------------------------------------------------
1034*b2055c35SXin Li 
DecodeAlphaData(VP8LDecoder * const dec,uint8_t * const data,int width,int height,int last_row)1035*b2055c35SXin Li static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
1036*b2055c35SXin Li                            int width, int height, int last_row) {
1037*b2055c35SXin Li   int ok = 1;
1038*b2055c35SXin Li   int row = dec->last_pixel_ / width;
1039*b2055c35SXin Li   int col = dec->last_pixel_ % width;
1040*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
1041*b2055c35SXin Li   VP8LMetadata* const hdr = &dec->hdr_;
1042*b2055c35SXin Li   int pos = dec->last_pixel_;         // current position
1043*b2055c35SXin Li   const int end = width * height;     // End of data
1044*b2055c35SXin Li   const int last = width * last_row;  // Last pixel to decode
1045*b2055c35SXin Li   const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
1046*b2055c35SXin Li   const int mask = hdr->huffman_mask_;
1047*b2055c35SXin Li   const HTreeGroup* htree_group =
1048*b2055c35SXin Li       (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
1049*b2055c35SXin Li   assert(pos <= end);
1050*b2055c35SXin Li   assert(last_row <= height);
1051*b2055c35SXin Li   assert(Is8bOptimizable(hdr));
1052*b2055c35SXin Li 
1053*b2055c35SXin Li   while (!br->eos_ && pos < last) {
1054*b2055c35SXin Li     int code;
1055*b2055c35SXin Li     // Only update when changing tile.
1056*b2055c35SXin Li     if ((col & mask) == 0) {
1057*b2055c35SXin Li       htree_group = GetHtreeGroupForPos(hdr, col, row);
1058*b2055c35SXin Li     }
1059*b2055c35SXin Li     assert(htree_group != NULL);
1060*b2055c35SXin Li     VP8LFillBitWindow(br);
1061*b2055c35SXin Li     code = ReadSymbol(htree_group->htrees[GREEN], br);
1062*b2055c35SXin Li     if (code < NUM_LITERAL_CODES) {  // Literal
1063*b2055c35SXin Li       data[pos] = code;
1064*b2055c35SXin Li       ++pos;
1065*b2055c35SXin Li       ++col;
1066*b2055c35SXin Li       if (col >= width) {
1067*b2055c35SXin Li         col = 0;
1068*b2055c35SXin Li         ++row;
1069*b2055c35SXin Li         if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1070*b2055c35SXin Li           ExtractPalettedAlphaRows(dec, row);
1071*b2055c35SXin Li         }
1072*b2055c35SXin Li       }
1073*b2055c35SXin Li     } else if (code < len_code_limit) {  // Backward reference
1074*b2055c35SXin Li       int dist_code, dist;
1075*b2055c35SXin Li       const int length_sym = code - NUM_LITERAL_CODES;
1076*b2055c35SXin Li       const int length = GetCopyLength(length_sym, br);
1077*b2055c35SXin Li       const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
1078*b2055c35SXin Li       VP8LFillBitWindow(br);
1079*b2055c35SXin Li       dist_code = GetCopyDistance(dist_symbol, br);
1080*b2055c35SXin Li       dist = PlaneCodeToDistance(width, dist_code);
1081*b2055c35SXin Li       if (pos >= dist && end - pos >= length) {
1082*b2055c35SXin Li         CopyBlock8b(data + pos, dist, length);
1083*b2055c35SXin Li       } else {
1084*b2055c35SXin Li         ok = 0;
1085*b2055c35SXin Li         goto End;
1086*b2055c35SXin Li       }
1087*b2055c35SXin Li       pos += length;
1088*b2055c35SXin Li       col += length;
1089*b2055c35SXin Li       while (col >= width) {
1090*b2055c35SXin Li         col -= width;
1091*b2055c35SXin Li         ++row;
1092*b2055c35SXin Li         if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1093*b2055c35SXin Li           ExtractPalettedAlphaRows(dec, row);
1094*b2055c35SXin Li         }
1095*b2055c35SXin Li       }
1096*b2055c35SXin Li       if (pos < last && (col & mask)) {
1097*b2055c35SXin Li         htree_group = GetHtreeGroupForPos(hdr, col, row);
1098*b2055c35SXin Li       }
1099*b2055c35SXin Li     } else {  // Not reached
1100*b2055c35SXin Li       ok = 0;
1101*b2055c35SXin Li       goto End;
1102*b2055c35SXin Li     }
1103*b2055c35SXin Li     br->eos_ = VP8LIsEndOfStream(br);
1104*b2055c35SXin Li   }
1105*b2055c35SXin Li   // Process the remaining rows corresponding to last row-block.
1106*b2055c35SXin Li   ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);
1107*b2055c35SXin Li 
1108*b2055c35SXin Li  End:
1109*b2055c35SXin Li   br->eos_ = VP8LIsEndOfStream(br);
1110*b2055c35SXin Li   if (!ok || (br->eos_ && pos < end)) {
1111*b2055c35SXin Li     return VP8LSetError(
1112*b2055c35SXin Li         dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);
1113*b2055c35SXin Li   }
1114*b2055c35SXin Li   dec->last_pixel_ = pos;
1115*b2055c35SXin Li   return ok;
1116*b2055c35SXin Li }
1117*b2055c35SXin Li 
SaveState(VP8LDecoder * const dec,int last_pixel)1118*b2055c35SXin Li static void SaveState(VP8LDecoder* const dec, int last_pixel) {
1119*b2055c35SXin Li   assert(dec->incremental_);
1120*b2055c35SXin Li   dec->saved_br_ = dec->br_;
1121*b2055c35SXin Li   dec->saved_last_pixel_ = last_pixel;
1122*b2055c35SXin Li   if (dec->hdr_.color_cache_size_ > 0) {
1123*b2055c35SXin Li     VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);
1124*b2055c35SXin Li   }
1125*b2055c35SXin Li }
1126*b2055c35SXin Li 
RestoreState(VP8LDecoder * const dec)1127*b2055c35SXin Li static void RestoreState(VP8LDecoder* const dec) {
1128*b2055c35SXin Li   assert(dec->br_.eos_);
1129*b2055c35SXin Li   dec->status_ = VP8_STATUS_SUSPENDED;
1130*b2055c35SXin Li   dec->br_ = dec->saved_br_;
1131*b2055c35SXin Li   dec->last_pixel_ = dec->saved_last_pixel_;
1132*b2055c35SXin Li   if (dec->hdr_.color_cache_size_ > 0) {
1133*b2055c35SXin Li     VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);
1134*b2055c35SXin Li   }
1135*b2055c35SXin Li }
1136*b2055c35SXin Li 
1137*b2055c35SXin Li #define SYNC_EVERY_N_ROWS 8  // minimum number of rows between check-points
DecodeImageData(VP8LDecoder * const dec,uint32_t * const data,int width,int height,int last_row,ProcessRowsFunc process_func)1138*b2055c35SXin Li static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
1139*b2055c35SXin Li                            int width, int height, int last_row,
1140*b2055c35SXin Li                            ProcessRowsFunc process_func) {
1141*b2055c35SXin Li   int row = dec->last_pixel_ / width;
1142*b2055c35SXin Li   int col = dec->last_pixel_ % width;
1143*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
1144*b2055c35SXin Li   VP8LMetadata* const hdr = &dec->hdr_;
1145*b2055c35SXin Li   uint32_t* src = data + dec->last_pixel_;
1146*b2055c35SXin Li   uint32_t* last_cached = src;
1147*b2055c35SXin Li   uint32_t* const src_end = data + width * height;     // End of data
1148*b2055c35SXin Li   uint32_t* const src_last = data + width * last_row;  // Last pixel to decode
1149*b2055c35SXin Li   const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
1150*b2055c35SXin Li   const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
1151*b2055c35SXin Li   int next_sync_row = dec->incremental_ ? row : 1 << 24;
1152*b2055c35SXin Li   VP8LColorCache* const color_cache =
1153*b2055c35SXin Li       (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
1154*b2055c35SXin Li   const int mask = hdr->huffman_mask_;
1155*b2055c35SXin Li   const HTreeGroup* htree_group =
1156*b2055c35SXin Li       (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
1157*b2055c35SXin Li   assert(dec->last_row_ < last_row);
1158*b2055c35SXin Li   assert(src_last <= src_end);
1159*b2055c35SXin Li 
1160*b2055c35SXin Li   while (src < src_last) {
1161*b2055c35SXin Li     int code;
1162*b2055c35SXin Li     if (row >= next_sync_row) {
1163*b2055c35SXin Li       SaveState(dec, (int)(src - data));
1164*b2055c35SXin Li       next_sync_row = row + SYNC_EVERY_N_ROWS;
1165*b2055c35SXin Li     }
1166*b2055c35SXin Li     // Only update when changing tile. Note we could use this test:
1167*b2055c35SXin Li     // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
1168*b2055c35SXin Li     // but that's actually slower and needs storing the previous col/row.
1169*b2055c35SXin Li     if ((col & mask) == 0) {
1170*b2055c35SXin Li       htree_group = GetHtreeGroupForPos(hdr, col, row);
1171*b2055c35SXin Li     }
1172*b2055c35SXin Li     assert(htree_group != NULL);
1173*b2055c35SXin Li     if (htree_group->is_trivial_code) {
1174*b2055c35SXin Li       *src = htree_group->literal_arb;
1175*b2055c35SXin Li       goto AdvanceByOne;
1176*b2055c35SXin Li     }
1177*b2055c35SXin Li     VP8LFillBitWindow(br);
1178*b2055c35SXin Li     if (htree_group->use_packed_table) {
1179*b2055c35SXin Li       code = ReadPackedSymbols(htree_group, br, src);
1180*b2055c35SXin Li       if (VP8LIsEndOfStream(br)) break;
1181*b2055c35SXin Li       if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;
1182*b2055c35SXin Li     } else {
1183*b2055c35SXin Li       code = ReadSymbol(htree_group->htrees[GREEN], br);
1184*b2055c35SXin Li     }
1185*b2055c35SXin Li     if (VP8LIsEndOfStream(br)) break;
1186*b2055c35SXin Li     if (code < NUM_LITERAL_CODES) {  // Literal
1187*b2055c35SXin Li       if (htree_group->is_trivial_literal) {
1188*b2055c35SXin Li         *src = htree_group->literal_arb | (code << 8);
1189*b2055c35SXin Li       } else {
1190*b2055c35SXin Li         int red, blue, alpha;
1191*b2055c35SXin Li         red = ReadSymbol(htree_group->htrees[RED], br);
1192*b2055c35SXin Li         VP8LFillBitWindow(br);
1193*b2055c35SXin Li         blue = ReadSymbol(htree_group->htrees[BLUE], br);
1194*b2055c35SXin Li         alpha = ReadSymbol(htree_group->htrees[ALPHA], br);
1195*b2055c35SXin Li         if (VP8LIsEndOfStream(br)) break;
1196*b2055c35SXin Li         *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;
1197*b2055c35SXin Li       }
1198*b2055c35SXin Li     AdvanceByOne:
1199*b2055c35SXin Li       ++src;
1200*b2055c35SXin Li       ++col;
1201*b2055c35SXin Li       if (col >= width) {
1202*b2055c35SXin Li         col = 0;
1203*b2055c35SXin Li         ++row;
1204*b2055c35SXin Li         if (process_func != NULL) {
1205*b2055c35SXin Li           if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1206*b2055c35SXin Li             process_func(dec, row);
1207*b2055c35SXin Li           }
1208*b2055c35SXin Li         }
1209*b2055c35SXin Li         if (color_cache != NULL) {
1210*b2055c35SXin Li           while (last_cached < src) {
1211*b2055c35SXin Li             VP8LColorCacheInsert(color_cache, *last_cached++);
1212*b2055c35SXin Li           }
1213*b2055c35SXin Li         }
1214*b2055c35SXin Li       }
1215*b2055c35SXin Li     } else if (code < len_code_limit) {  // Backward reference
1216*b2055c35SXin Li       int dist_code, dist;
1217*b2055c35SXin Li       const int length_sym = code - NUM_LITERAL_CODES;
1218*b2055c35SXin Li       const int length = GetCopyLength(length_sym, br);
1219*b2055c35SXin Li       const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);
1220*b2055c35SXin Li       VP8LFillBitWindow(br);
1221*b2055c35SXin Li       dist_code = GetCopyDistance(dist_symbol, br);
1222*b2055c35SXin Li       dist = PlaneCodeToDistance(width, dist_code);
1223*b2055c35SXin Li 
1224*b2055c35SXin Li       if (VP8LIsEndOfStream(br)) break;
1225*b2055c35SXin Li       if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
1226*b2055c35SXin Li         goto Error;
1227*b2055c35SXin Li       } else {
1228*b2055c35SXin Li         CopyBlock32b(src, dist, length);
1229*b2055c35SXin Li       }
1230*b2055c35SXin Li       src += length;
1231*b2055c35SXin Li       col += length;
1232*b2055c35SXin Li       while (col >= width) {
1233*b2055c35SXin Li         col -= width;
1234*b2055c35SXin Li         ++row;
1235*b2055c35SXin Li         if (process_func != NULL) {
1236*b2055c35SXin Li           if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
1237*b2055c35SXin Li             process_func(dec, row);
1238*b2055c35SXin Li           }
1239*b2055c35SXin Li         }
1240*b2055c35SXin Li       }
1241*b2055c35SXin Li       // Because of the check done above (before 'src' was incremented by
1242*b2055c35SXin Li       // 'length'), the following holds true.
1243*b2055c35SXin Li       assert(src <= src_end);
1244*b2055c35SXin Li       if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
1245*b2055c35SXin Li       if (color_cache != NULL) {
1246*b2055c35SXin Li         while (last_cached < src) {
1247*b2055c35SXin Li           VP8LColorCacheInsert(color_cache, *last_cached++);
1248*b2055c35SXin Li         }
1249*b2055c35SXin Li       }
1250*b2055c35SXin Li     } else if (code < color_cache_limit) {  // Color cache
1251*b2055c35SXin Li       const int key = code - len_code_limit;
1252*b2055c35SXin Li       assert(color_cache != NULL);
1253*b2055c35SXin Li       while (last_cached < src) {
1254*b2055c35SXin Li         VP8LColorCacheInsert(color_cache, *last_cached++);
1255*b2055c35SXin Li       }
1256*b2055c35SXin Li       *src = VP8LColorCacheLookup(color_cache, key);
1257*b2055c35SXin Li       goto AdvanceByOne;
1258*b2055c35SXin Li     } else {  // Not reached
1259*b2055c35SXin Li       goto Error;
1260*b2055c35SXin Li     }
1261*b2055c35SXin Li   }
1262*b2055c35SXin Li 
1263*b2055c35SXin Li   br->eos_ = VP8LIsEndOfStream(br);
1264*b2055c35SXin Li   // In incremental decoding:
1265*b2055c35SXin Li   // br->eos_ && src < src_last: if 'br' reached the end of the buffer and
1266*b2055c35SXin Li   // 'src_last' has not been reached yet, there is not enough data. 'dec' has to
1267*b2055c35SXin Li   // be reset until there is more data.
1268*b2055c35SXin Li   // !br->eos_ && src < src_last: this cannot happen as either the buffer is
1269*b2055c35SXin Li   // fully read, either enough has been read to reach 'src_last'.
1270*b2055c35SXin Li   // src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go
1271*b2055c35SXin Li   // beyond 'src_last' in case the image is cropped and an LZ77 goes further.
1272*b2055c35SXin Li   // The buffer might have been enough or there is some left. 'br->eos_' does
1273*b2055c35SXin Li   // not matter.
1274*b2055c35SXin Li   assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);
1275*b2055c35SXin Li   if (dec->incremental_ && br->eos_ && src < src_last) {
1276*b2055c35SXin Li     RestoreState(dec);
1277*b2055c35SXin Li   } else if ((dec->incremental_ && src >= src_last) || !br->eos_) {
1278*b2055c35SXin Li     // Process the remaining rows corresponding to last row-block.
1279*b2055c35SXin Li     if (process_func != NULL) {
1280*b2055c35SXin Li       process_func(dec, row > last_row ? last_row : row);
1281*b2055c35SXin Li     }
1282*b2055c35SXin Li     dec->status_ = VP8_STATUS_OK;
1283*b2055c35SXin Li     dec->last_pixel_ = (int)(src - data);  // end-of-scan marker
1284*b2055c35SXin Li   } else {
1285*b2055c35SXin Li     // if not incremental, and we are past the end of buffer (eos_=1), then this
1286*b2055c35SXin Li     // is a real bitstream error.
1287*b2055c35SXin Li     goto Error;
1288*b2055c35SXin Li   }
1289*b2055c35SXin Li   return 1;
1290*b2055c35SXin Li 
1291*b2055c35SXin Li  Error:
1292*b2055c35SXin Li   return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1293*b2055c35SXin Li }
1294*b2055c35SXin Li 
1295*b2055c35SXin Li // -----------------------------------------------------------------------------
1296*b2055c35SXin Li // VP8LTransform
1297*b2055c35SXin Li 
ClearTransform(VP8LTransform * const transform)1298*b2055c35SXin Li static void ClearTransform(VP8LTransform* const transform) {
1299*b2055c35SXin Li   WebPSafeFree(transform->data_);
1300*b2055c35SXin Li   transform->data_ = NULL;
1301*b2055c35SXin Li }
1302*b2055c35SXin Li 
1303*b2055c35SXin Li // For security reason, we need to remap the color map to span
1304*b2055c35SXin Li // the total possible bundled values, and not just the num_colors.
ExpandColorMap(int num_colors,VP8LTransform * const transform)1305*b2055c35SXin Li static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
1306*b2055c35SXin Li   int i;
1307*b2055c35SXin Li   const int final_num_colors = 1 << (8 >> transform->bits_);
1308*b2055c35SXin Li   uint32_t* const new_color_map =
1309*b2055c35SXin Li       (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
1310*b2055c35SXin Li                                 sizeof(*new_color_map));
1311*b2055c35SXin Li   if (new_color_map == NULL) {
1312*b2055c35SXin Li     return 0;
1313*b2055c35SXin Li   } else {
1314*b2055c35SXin Li     uint8_t* const data = (uint8_t*)transform->data_;
1315*b2055c35SXin Li     uint8_t* const new_data = (uint8_t*)new_color_map;
1316*b2055c35SXin Li     new_color_map[0] = transform->data_[0];
1317*b2055c35SXin Li     for (i = 4; i < 4 * num_colors; ++i) {
1318*b2055c35SXin Li       // Equivalent to VP8LAddPixels(), on a byte-basis.
1319*b2055c35SXin Li       new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
1320*b2055c35SXin Li     }
1321*b2055c35SXin Li     for (; i < 4 * final_num_colors; ++i) {
1322*b2055c35SXin Li       new_data[i] = 0;  // black tail.
1323*b2055c35SXin Li     }
1324*b2055c35SXin Li     WebPSafeFree(transform->data_);
1325*b2055c35SXin Li     transform->data_ = new_color_map;
1326*b2055c35SXin Li   }
1327*b2055c35SXin Li   return 1;
1328*b2055c35SXin Li }
1329*b2055c35SXin Li 
ReadTransform(int * const xsize,int const * ysize,VP8LDecoder * const dec)1330*b2055c35SXin Li static int ReadTransform(int* const xsize, int const* ysize,
1331*b2055c35SXin Li                          VP8LDecoder* const dec) {
1332*b2055c35SXin Li   int ok = 1;
1333*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
1334*b2055c35SXin Li   VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
1335*b2055c35SXin Li   const VP8LImageTransformType type =
1336*b2055c35SXin Li       (VP8LImageTransformType)VP8LReadBits(br, 2);
1337*b2055c35SXin Li 
1338*b2055c35SXin Li   // Each transform type can only be present once in the stream.
1339*b2055c35SXin Li   if (dec->transforms_seen_ & (1U << type)) {
1340*b2055c35SXin Li     return 0;  // Already there, let's not accept the second same transform.
1341*b2055c35SXin Li   }
1342*b2055c35SXin Li   dec->transforms_seen_ |= (1U << type);
1343*b2055c35SXin Li 
1344*b2055c35SXin Li   transform->type_ = type;
1345*b2055c35SXin Li   transform->xsize_ = *xsize;
1346*b2055c35SXin Li   transform->ysize_ = *ysize;
1347*b2055c35SXin Li   transform->data_ = NULL;
1348*b2055c35SXin Li   ++dec->next_transform_;
1349*b2055c35SXin Li   assert(dec->next_transform_ <= NUM_TRANSFORMS);
1350*b2055c35SXin Li 
1351*b2055c35SXin Li   switch (type) {
1352*b2055c35SXin Li     case PREDICTOR_TRANSFORM:
1353*b2055c35SXin Li     case CROSS_COLOR_TRANSFORM:
1354*b2055c35SXin Li       transform->bits_ = VP8LReadBits(br, 3) + 2;
1355*b2055c35SXin Li       ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
1356*b2055c35SXin Li                                                transform->bits_),
1357*b2055c35SXin Li                              VP8LSubSampleSize(transform->ysize_,
1358*b2055c35SXin Li                                                transform->bits_),
1359*b2055c35SXin Li                              /*is_level0=*/0, dec, &transform->data_);
1360*b2055c35SXin Li       break;
1361*b2055c35SXin Li     case COLOR_INDEXING_TRANSFORM: {
1362*b2055c35SXin Li        const int num_colors = VP8LReadBits(br, 8) + 1;
1363*b2055c35SXin Li        const int bits = (num_colors > 16) ? 0
1364*b2055c35SXin Li                       : (num_colors > 4) ? 1
1365*b2055c35SXin Li                       : (num_colors > 2) ? 2
1366*b2055c35SXin Li                       : 3;
1367*b2055c35SXin Li        *xsize = VP8LSubSampleSize(transform->xsize_, bits);
1368*b2055c35SXin Li        transform->bits_ = bits;
1369*b2055c35SXin Li        ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,
1370*b2055c35SXin Li                               &transform->data_);
1371*b2055c35SXin Li        if (ok && !ExpandColorMap(num_colors, transform)) {
1372*b2055c35SXin Li          return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1373*b2055c35SXin Li        }
1374*b2055c35SXin Li       break;
1375*b2055c35SXin Li     }
1376*b2055c35SXin Li     case SUBTRACT_GREEN_TRANSFORM:
1377*b2055c35SXin Li       break;
1378*b2055c35SXin Li     default:
1379*b2055c35SXin Li       assert(0);    // can't happen
1380*b2055c35SXin Li       break;
1381*b2055c35SXin Li   }
1382*b2055c35SXin Li 
1383*b2055c35SXin Li   return ok;
1384*b2055c35SXin Li }
1385*b2055c35SXin Li 
1386*b2055c35SXin Li // -----------------------------------------------------------------------------
1387*b2055c35SXin Li // VP8LMetadata
1388*b2055c35SXin Li 
InitMetadata(VP8LMetadata * const hdr)1389*b2055c35SXin Li static void InitMetadata(VP8LMetadata* const hdr) {
1390*b2055c35SXin Li   assert(hdr != NULL);
1391*b2055c35SXin Li   memset(hdr, 0, sizeof(*hdr));
1392*b2055c35SXin Li }
1393*b2055c35SXin Li 
ClearMetadata(VP8LMetadata * const hdr)1394*b2055c35SXin Li static void ClearMetadata(VP8LMetadata* const hdr) {
1395*b2055c35SXin Li   assert(hdr != NULL);
1396*b2055c35SXin Li 
1397*b2055c35SXin Li   WebPSafeFree(hdr->huffman_image_);
1398*b2055c35SXin Li   VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);
1399*b2055c35SXin Li   VP8LHtreeGroupsFree(hdr->htree_groups_);
1400*b2055c35SXin Li   VP8LColorCacheClear(&hdr->color_cache_);
1401*b2055c35SXin Li   VP8LColorCacheClear(&hdr->saved_color_cache_);
1402*b2055c35SXin Li   InitMetadata(hdr);
1403*b2055c35SXin Li }
1404*b2055c35SXin Li 
1405*b2055c35SXin Li // -----------------------------------------------------------------------------
1406*b2055c35SXin Li // VP8LDecoder
1407*b2055c35SXin Li 
VP8LNew(void)1408*b2055c35SXin Li VP8LDecoder* VP8LNew(void) {
1409*b2055c35SXin Li   VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
1410*b2055c35SXin Li   if (dec == NULL) return NULL;
1411*b2055c35SXin Li   dec->status_ = VP8_STATUS_OK;
1412*b2055c35SXin Li   dec->state_ = READ_DIM;
1413*b2055c35SXin Li 
1414*b2055c35SXin Li   VP8LDspInit();  // Init critical function pointers.
1415*b2055c35SXin Li 
1416*b2055c35SXin Li   return dec;
1417*b2055c35SXin Li }
1418*b2055c35SXin Li 
VP8LClear(VP8LDecoder * const dec)1419*b2055c35SXin Li void VP8LClear(VP8LDecoder* const dec) {
1420*b2055c35SXin Li   int i;
1421*b2055c35SXin Li   if (dec == NULL) return;
1422*b2055c35SXin Li   ClearMetadata(&dec->hdr_);
1423*b2055c35SXin Li 
1424*b2055c35SXin Li   WebPSafeFree(dec->pixels_);
1425*b2055c35SXin Li   dec->pixels_ = NULL;
1426*b2055c35SXin Li   for (i = 0; i < dec->next_transform_; ++i) {
1427*b2055c35SXin Li     ClearTransform(&dec->transforms_[i]);
1428*b2055c35SXin Li   }
1429*b2055c35SXin Li   dec->next_transform_ = 0;
1430*b2055c35SXin Li   dec->transforms_seen_ = 0;
1431*b2055c35SXin Li 
1432*b2055c35SXin Li   WebPSafeFree(dec->rescaler_memory);
1433*b2055c35SXin Li   dec->rescaler_memory = NULL;
1434*b2055c35SXin Li 
1435*b2055c35SXin Li   dec->output_ = NULL;   // leave no trace behind
1436*b2055c35SXin Li }
1437*b2055c35SXin Li 
VP8LDelete(VP8LDecoder * const dec)1438*b2055c35SXin Li void VP8LDelete(VP8LDecoder* const dec) {
1439*b2055c35SXin Li   if (dec != NULL) {
1440*b2055c35SXin Li     VP8LClear(dec);
1441*b2055c35SXin Li     WebPSafeFree(dec);
1442*b2055c35SXin Li   }
1443*b2055c35SXin Li }
1444*b2055c35SXin Li 
UpdateDecoder(VP8LDecoder * const dec,int width,int height)1445*b2055c35SXin Li static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
1446*b2055c35SXin Li   VP8LMetadata* const hdr = &dec->hdr_;
1447*b2055c35SXin Li   const int num_bits = hdr->huffman_subsample_bits_;
1448*b2055c35SXin Li   dec->width_ = width;
1449*b2055c35SXin Li   dec->height_ = height;
1450*b2055c35SXin Li 
1451*b2055c35SXin Li   hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
1452*b2055c35SXin Li   hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
1453*b2055c35SXin Li }
1454*b2055c35SXin Li 
DecodeImageStream(int xsize,int ysize,int is_level0,VP8LDecoder * const dec,uint32_t ** const decoded_data)1455*b2055c35SXin Li static int DecodeImageStream(int xsize, int ysize,
1456*b2055c35SXin Li                              int is_level0,
1457*b2055c35SXin Li                              VP8LDecoder* const dec,
1458*b2055c35SXin Li                              uint32_t** const decoded_data) {
1459*b2055c35SXin Li   int ok = 1;
1460*b2055c35SXin Li   int transform_xsize = xsize;
1461*b2055c35SXin Li   int transform_ysize = ysize;
1462*b2055c35SXin Li   VP8LBitReader* const br = &dec->br_;
1463*b2055c35SXin Li   VP8LMetadata* const hdr = &dec->hdr_;
1464*b2055c35SXin Li   uint32_t* data = NULL;
1465*b2055c35SXin Li   int color_cache_bits = 0;
1466*b2055c35SXin Li 
1467*b2055c35SXin Li   // Read the transforms (may recurse).
1468*b2055c35SXin Li   if (is_level0) {
1469*b2055c35SXin Li     while (ok && VP8LReadBits(br, 1)) {
1470*b2055c35SXin Li       ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
1471*b2055c35SXin Li     }
1472*b2055c35SXin Li   }
1473*b2055c35SXin Li 
1474*b2055c35SXin Li   // Color cache
1475*b2055c35SXin Li   if (ok && VP8LReadBits(br, 1)) {
1476*b2055c35SXin Li     color_cache_bits = VP8LReadBits(br, 4);
1477*b2055c35SXin Li     ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
1478*b2055c35SXin Li     if (!ok) {
1479*b2055c35SXin Li       VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1480*b2055c35SXin Li       goto End;
1481*b2055c35SXin Li     }
1482*b2055c35SXin Li   }
1483*b2055c35SXin Li 
1484*b2055c35SXin Li   // Read the Huffman codes (may recurse).
1485*b2055c35SXin Li   ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
1486*b2055c35SXin Li                               color_cache_bits, is_level0);
1487*b2055c35SXin Li   if (!ok) {
1488*b2055c35SXin Li     VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1489*b2055c35SXin Li     goto End;
1490*b2055c35SXin Li   }
1491*b2055c35SXin Li 
1492*b2055c35SXin Li   // Finish setting up the color-cache
1493*b2055c35SXin Li   if (color_cache_bits > 0) {
1494*b2055c35SXin Li     hdr->color_cache_size_ = 1 << color_cache_bits;
1495*b2055c35SXin Li     if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
1496*b2055c35SXin Li       ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1497*b2055c35SXin Li       goto End;
1498*b2055c35SXin Li     }
1499*b2055c35SXin Li   } else {
1500*b2055c35SXin Li     hdr->color_cache_size_ = 0;
1501*b2055c35SXin Li   }
1502*b2055c35SXin Li   UpdateDecoder(dec, transform_xsize, transform_ysize);
1503*b2055c35SXin Li 
1504*b2055c35SXin Li   if (is_level0) {   // level 0 complete
1505*b2055c35SXin Li     dec->state_ = READ_HDR;
1506*b2055c35SXin Li     goto End;
1507*b2055c35SXin Li   }
1508*b2055c35SXin Li 
1509*b2055c35SXin Li   {
1510*b2055c35SXin Li     const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
1511*b2055c35SXin Li     data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
1512*b2055c35SXin Li     if (data == NULL) {
1513*b2055c35SXin Li       ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1514*b2055c35SXin Li       goto End;
1515*b2055c35SXin Li     }
1516*b2055c35SXin Li   }
1517*b2055c35SXin Li 
1518*b2055c35SXin Li   // Use the Huffman trees to decode the LZ77 encoded data.
1519*b2055c35SXin Li   ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
1520*b2055c35SXin Li                        transform_ysize, NULL);
1521*b2055c35SXin Li   ok = ok && !br->eos_;
1522*b2055c35SXin Li 
1523*b2055c35SXin Li  End:
1524*b2055c35SXin Li   if (!ok) {
1525*b2055c35SXin Li     WebPSafeFree(data);
1526*b2055c35SXin Li     ClearMetadata(hdr);
1527*b2055c35SXin Li   } else {
1528*b2055c35SXin Li     if (decoded_data != NULL) {
1529*b2055c35SXin Li       *decoded_data = data;
1530*b2055c35SXin Li     } else {
1531*b2055c35SXin Li       // We allocate image data in this function only for transforms. At level 0
1532*b2055c35SXin Li       // (that is: not the transforms), we shouldn't have allocated anything.
1533*b2055c35SXin Li       assert(data == NULL);
1534*b2055c35SXin Li       assert(is_level0);
1535*b2055c35SXin Li     }
1536*b2055c35SXin Li     dec->last_pixel_ = 0;  // Reset for future DECODE_DATA_FUNC() calls.
1537*b2055c35SXin Li     if (!is_level0) ClearMetadata(hdr);  // Clean up temporary data behind.
1538*b2055c35SXin Li   }
1539*b2055c35SXin Li   return ok;
1540*b2055c35SXin Li }
1541*b2055c35SXin Li 
1542*b2055c35SXin Li //------------------------------------------------------------------------------
1543*b2055c35SXin Li // Allocate internal buffers dec->pixels_ and dec->argb_cache_.
AllocateInternalBuffers32b(VP8LDecoder * const dec,int final_width)1544*b2055c35SXin Li static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
1545*b2055c35SXin Li   const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
1546*b2055c35SXin Li   // Scratch buffer corresponding to top-prediction row for transforming the
1547*b2055c35SXin Li   // first row in the row-blocks. Not needed for paletted alpha.
1548*b2055c35SXin Li   const uint64_t cache_top_pixels = (uint16_t)final_width;
1549*b2055c35SXin Li   // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
1550*b2055c35SXin Li   const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
1551*b2055c35SXin Li   const uint64_t total_num_pixels =
1552*b2055c35SXin Li       num_pixels + cache_top_pixels + cache_pixels;
1553*b2055c35SXin Li 
1554*b2055c35SXin Li   assert(dec->width_ <= final_width);
1555*b2055c35SXin Li   dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
1556*b2055c35SXin Li   if (dec->pixels_ == NULL) {
1557*b2055c35SXin Li     dec->argb_cache_ = NULL;    // for soundness
1558*b2055c35SXin Li     return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1559*b2055c35SXin Li   }
1560*b2055c35SXin Li   dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
1561*b2055c35SXin Li   return 1;
1562*b2055c35SXin Li }
1563*b2055c35SXin Li 
AllocateInternalBuffers8b(VP8LDecoder * const dec)1564*b2055c35SXin Li static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
1565*b2055c35SXin Li   const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
1566*b2055c35SXin Li   dec->argb_cache_ = NULL;    // for soundness
1567*b2055c35SXin Li   dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
1568*b2055c35SXin Li   if (dec->pixels_ == NULL) {
1569*b2055c35SXin Li     return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1570*b2055c35SXin Li   }
1571*b2055c35SXin Li   return 1;
1572*b2055c35SXin Li }
1573*b2055c35SXin Li 
1574*b2055c35SXin Li //------------------------------------------------------------------------------
1575*b2055c35SXin Li 
1576*b2055c35SXin Li // Special row-processing that only stores the alpha data.
ExtractAlphaRows(VP8LDecoder * const dec,int last_row)1577*b2055c35SXin Li static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
1578*b2055c35SXin Li   int cur_row = dec->last_row_;
1579*b2055c35SXin Li   int num_rows = last_row - cur_row;
1580*b2055c35SXin Li   const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
1581*b2055c35SXin Li 
1582*b2055c35SXin Li   assert(last_row <= dec->io_->crop_bottom);
1583*b2055c35SXin Li   while (num_rows > 0) {
1584*b2055c35SXin Li     const int num_rows_to_process =
1585*b2055c35SXin Li         (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
1586*b2055c35SXin Li     // Extract alpha (which is stored in the green plane).
1587*b2055c35SXin Li     ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
1588*b2055c35SXin Li     uint8_t* const output = alph_dec->output_;
1589*b2055c35SXin Li     const int width = dec->io_->width;      // the final width (!= dec->width_)
1590*b2055c35SXin Li     const int cache_pixs = width * num_rows_to_process;
1591*b2055c35SXin Li     uint8_t* const dst = output + width * cur_row;
1592*b2055c35SXin Li     const uint32_t* const src = dec->argb_cache_;
1593*b2055c35SXin Li     ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
1594*b2055c35SXin Li     WebPExtractGreen(src, dst, cache_pixs);
1595*b2055c35SXin Li     AlphaApplyFilter(alph_dec,
1596*b2055c35SXin Li                      cur_row, cur_row + num_rows_to_process, dst, width);
1597*b2055c35SXin Li     num_rows -= num_rows_to_process;
1598*b2055c35SXin Li     in += num_rows_to_process * dec->width_;
1599*b2055c35SXin Li     cur_row += num_rows_to_process;
1600*b2055c35SXin Li   }
1601*b2055c35SXin Li   assert(cur_row == last_row);
1602*b2055c35SXin Li   dec->last_row_ = dec->last_out_row_ = last_row;
1603*b2055c35SXin Li }
1604*b2055c35SXin Li 
VP8LDecodeAlphaHeader(ALPHDecoder * const alph_dec,const uint8_t * const data,size_t data_size)1605*b2055c35SXin Li int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
1606*b2055c35SXin Li                           const uint8_t* const data, size_t data_size) {
1607*b2055c35SXin Li   int ok = 0;
1608*b2055c35SXin Li   VP8LDecoder* dec = VP8LNew();
1609*b2055c35SXin Li 
1610*b2055c35SXin Li   if (dec == NULL) return 0;
1611*b2055c35SXin Li 
1612*b2055c35SXin Li   assert(alph_dec != NULL);
1613*b2055c35SXin Li 
1614*b2055c35SXin Li   dec->width_ = alph_dec->width_;
1615*b2055c35SXin Li   dec->height_ = alph_dec->height_;
1616*b2055c35SXin Li   dec->io_ = &alph_dec->io_;
1617*b2055c35SXin Li   dec->io_->opaque = alph_dec;
1618*b2055c35SXin Li   dec->io_->width = alph_dec->width_;
1619*b2055c35SXin Li   dec->io_->height = alph_dec->height_;
1620*b2055c35SXin Li 
1621*b2055c35SXin Li   dec->status_ = VP8_STATUS_OK;
1622*b2055c35SXin Li   VP8LInitBitReader(&dec->br_, data, data_size);
1623*b2055c35SXin Li 
1624*b2055c35SXin Li   if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1,
1625*b2055c35SXin Li                          dec, /*decoded_data=*/NULL)) {
1626*b2055c35SXin Li     goto Err;
1627*b2055c35SXin Li   }
1628*b2055c35SXin Li 
1629*b2055c35SXin Li   // Special case: if alpha data uses only the color indexing transform and
1630*b2055c35SXin Li   // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
1631*b2055c35SXin Li   // method that only needs allocation of 1 byte per pixel (alpha channel).
1632*b2055c35SXin Li   if (dec->next_transform_ == 1 &&
1633*b2055c35SXin Li       dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
1634*b2055c35SXin Li       Is8bOptimizable(&dec->hdr_)) {
1635*b2055c35SXin Li     alph_dec->use_8b_decode_ = 1;
1636*b2055c35SXin Li     ok = AllocateInternalBuffers8b(dec);
1637*b2055c35SXin Li   } else {
1638*b2055c35SXin Li     // Allocate internal buffers (note that dec->width_ may have changed here).
1639*b2055c35SXin Li     alph_dec->use_8b_decode_ = 0;
1640*b2055c35SXin Li     ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
1641*b2055c35SXin Li   }
1642*b2055c35SXin Li 
1643*b2055c35SXin Li   if (!ok) goto Err;
1644*b2055c35SXin Li 
1645*b2055c35SXin Li   // Only set here, once we are sure it is valid (to avoid thread races).
1646*b2055c35SXin Li   alph_dec->vp8l_dec_ = dec;
1647*b2055c35SXin Li   return 1;
1648*b2055c35SXin Li 
1649*b2055c35SXin Li  Err:
1650*b2055c35SXin Li   VP8LDelete(dec);
1651*b2055c35SXin Li   return 0;
1652*b2055c35SXin Li }
1653*b2055c35SXin Li 
VP8LDecodeAlphaImageStream(ALPHDecoder * const alph_dec,int last_row)1654*b2055c35SXin Li int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
1655*b2055c35SXin Li   VP8LDecoder* const dec = alph_dec->vp8l_dec_;
1656*b2055c35SXin Li   assert(dec != NULL);
1657*b2055c35SXin Li   assert(last_row <= dec->height_);
1658*b2055c35SXin Li 
1659*b2055c35SXin Li   if (dec->last_row_ >= last_row) {
1660*b2055c35SXin Li     return 1;  // done
1661*b2055c35SXin Li   }
1662*b2055c35SXin Li 
1663*b2055c35SXin Li   if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing();
1664*b2055c35SXin Li 
1665*b2055c35SXin Li   // Decode (with special row processing).
1666*b2055c35SXin Li   return alph_dec->use_8b_decode_ ?
1667*b2055c35SXin Li       DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
1668*b2055c35SXin Li                       last_row) :
1669*b2055c35SXin Li       DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1670*b2055c35SXin Li                       last_row, ExtractAlphaRows);
1671*b2055c35SXin Li }
1672*b2055c35SXin Li 
1673*b2055c35SXin Li //------------------------------------------------------------------------------
1674*b2055c35SXin Li 
VP8LDecodeHeader(VP8LDecoder * const dec,VP8Io * const io)1675*b2055c35SXin Li int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
1676*b2055c35SXin Li   int width, height, has_alpha;
1677*b2055c35SXin Li 
1678*b2055c35SXin Li   if (dec == NULL) return 0;
1679*b2055c35SXin Li   if (io == NULL) {
1680*b2055c35SXin Li     return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1681*b2055c35SXin Li   }
1682*b2055c35SXin Li 
1683*b2055c35SXin Li   dec->io_ = io;
1684*b2055c35SXin Li   dec->status_ = VP8_STATUS_OK;
1685*b2055c35SXin Li   VP8LInitBitReader(&dec->br_, io->data, io->data_size);
1686*b2055c35SXin Li   if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
1687*b2055c35SXin Li     VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
1688*b2055c35SXin Li     goto Error;
1689*b2055c35SXin Li   }
1690*b2055c35SXin Li   dec->state_ = READ_DIM;
1691*b2055c35SXin Li   io->width = width;
1692*b2055c35SXin Li   io->height = height;
1693*b2055c35SXin Li 
1694*b2055c35SXin Li   if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,
1695*b2055c35SXin Li                          /*decoded_data=*/NULL)) {
1696*b2055c35SXin Li     goto Error;
1697*b2055c35SXin Li   }
1698*b2055c35SXin Li   return 1;
1699*b2055c35SXin Li 
1700*b2055c35SXin Li  Error:
1701*b2055c35SXin Li   VP8LClear(dec);
1702*b2055c35SXin Li   assert(dec->status_ != VP8_STATUS_OK);
1703*b2055c35SXin Li   return 0;
1704*b2055c35SXin Li }
1705*b2055c35SXin Li 
VP8LDecodeImage(VP8LDecoder * const dec)1706*b2055c35SXin Li int VP8LDecodeImage(VP8LDecoder* const dec) {
1707*b2055c35SXin Li   VP8Io* io = NULL;
1708*b2055c35SXin Li   WebPDecParams* params = NULL;
1709*b2055c35SXin Li 
1710*b2055c35SXin Li   if (dec == NULL) return 0;
1711*b2055c35SXin Li 
1712*b2055c35SXin Li   assert(dec->hdr_.huffman_tables_.root.start != NULL);
1713*b2055c35SXin Li   assert(dec->hdr_.htree_groups_ != NULL);
1714*b2055c35SXin Li   assert(dec->hdr_.num_htree_groups_ > 0);
1715*b2055c35SXin Li 
1716*b2055c35SXin Li   io = dec->io_;
1717*b2055c35SXin Li   assert(io != NULL);
1718*b2055c35SXin Li   params = (WebPDecParams*)io->opaque;
1719*b2055c35SXin Li   assert(params != NULL);
1720*b2055c35SXin Li 
1721*b2055c35SXin Li   // Initialization.
1722*b2055c35SXin Li   if (dec->state_ != READ_DATA) {
1723*b2055c35SXin Li     dec->output_ = params->output;
1724*b2055c35SXin Li     assert(dec->output_ != NULL);
1725*b2055c35SXin Li 
1726*b2055c35SXin Li     if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
1727*b2055c35SXin Li       VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1728*b2055c35SXin Li       goto Err;
1729*b2055c35SXin Li     }
1730*b2055c35SXin Li 
1731*b2055c35SXin Li     if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
1732*b2055c35SXin Li 
1733*b2055c35SXin Li #if !defined(WEBP_REDUCE_SIZE)
1734*b2055c35SXin Li     if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
1735*b2055c35SXin Li #else
1736*b2055c35SXin Li     if (io->use_scaling) {
1737*b2055c35SXin Li       VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);
1738*b2055c35SXin Li       goto Err;
1739*b2055c35SXin Li     }
1740*b2055c35SXin Li #endif
1741*b2055c35SXin Li     if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
1742*b2055c35SXin Li       // need the alpha-multiply functions for premultiplied output or rescaling
1743*b2055c35SXin Li       WebPInitAlphaProcessing();
1744*b2055c35SXin Li     }
1745*b2055c35SXin Li 
1746*b2055c35SXin Li     if (!WebPIsRGBMode(dec->output_->colorspace)) {
1747*b2055c35SXin Li       WebPInitConvertARGBToYUV();
1748*b2055c35SXin Li       if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();
1749*b2055c35SXin Li     }
1750*b2055c35SXin Li     if (dec->incremental_) {
1751*b2055c35SXin Li       if (dec->hdr_.color_cache_size_ > 0 &&
1752*b2055c35SXin Li           dec->hdr_.saved_color_cache_.colors_ == NULL) {
1753*b2055c35SXin Li         if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,
1754*b2055c35SXin Li                                 dec->hdr_.color_cache_.hash_bits_)) {
1755*b2055c35SXin Li           VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
1756*b2055c35SXin Li           goto Err;
1757*b2055c35SXin Li         }
1758*b2055c35SXin Li       }
1759*b2055c35SXin Li     }
1760*b2055c35SXin Li     dec->state_ = READ_DATA;
1761*b2055c35SXin Li   }
1762*b2055c35SXin Li 
1763*b2055c35SXin Li   // Decode.
1764*b2055c35SXin Li   if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1765*b2055c35SXin Li                        io->crop_bottom, ProcessRows)) {
1766*b2055c35SXin Li     goto Err;
1767*b2055c35SXin Li   }
1768*b2055c35SXin Li 
1769*b2055c35SXin Li   params->last_y = dec->last_out_row_;
1770*b2055c35SXin Li   return 1;
1771*b2055c35SXin Li 
1772*b2055c35SXin Li  Err:
1773*b2055c35SXin Li   VP8LClear(dec);
1774*b2055c35SXin Li   assert(dec->status_ != VP8_STATUS_OK);
1775*b2055c35SXin Li   return 0;
1776*b2055c35SXin Li }
1777*b2055c35SXin Li 
1778*b2055c35SXin Li //------------------------------------------------------------------------------
1779