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