Path: blob/master/thirdparty/libwebp/src/dec/vp8l_dec.c
9913 views
// Copyright 2012 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// main entry for the decoder10//11// Authors: Vikas Arora ([email protected])12// Jyrki Alakuijala ([email protected])1314#include <assert.h>15#include <stdlib.h>1617#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/utils/huffman_utils.h"23#include "src/utils/utils.h"24#include "src/webp/format_constants.h"2526#define NUM_ARGB_CACHE_ROWS 162728static const int kCodeLengthLiterals = 16;29static const int kCodeLengthRepeatCode = 16;30static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 };31static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };3233// -----------------------------------------------------------------------------34// Five Huffman codes are used at each meta code:35// 1. green + length prefix codes + color cache codes,36// 2. alpha,37// 3. red,38// 4. blue, and,39// 5. distance prefix codes.40typedef enum {41GREEN = 0,42RED = 1,43BLUE = 2,44ALPHA = 3,45DIST = 446} HuffIndex;4748static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {49NUM_LITERAL_CODES + NUM_LENGTH_CODES,50NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,51NUM_DISTANCE_CODES52};5354static const uint8_t kLiteralMap[HUFFMAN_CODES_PER_META_CODE] = {550, 1, 1, 1, 056};5758#define NUM_CODE_LENGTH_CODES 1959static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {6017, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1561};6263#define CODE_TO_PLANE_CODES 12064static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {650x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,660x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,670x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,680x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,690x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,700x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,710x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,720x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,730x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,740x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,750x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,760x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x7077};7879// Memory needed for lookup tables of one Huffman tree group. Red, blue, alpha80// and distance alphabets are constant (256 for red, blue and alpha, 40 for81// distance) and lookup table sizes for them in worst case are 630 and 41082// respectively. Size of green alphabet depends on color cache size and is equal83// to 256 (green component values) + 24 (length prefix values)84// + color_cache_size (between 0 and 2048).85// All values computed for 8-bit first level lookup with Mark Adler's tool:86// https://github.com/madler/zlib/blob/v1.2.5/examples/enough.c87#define FIXED_TABLE_SIZE (630 * 3 + 410)88static const uint16_t kTableSize[12] = {89FIXED_TABLE_SIZE + 654,90FIXED_TABLE_SIZE + 656,91FIXED_TABLE_SIZE + 658,92FIXED_TABLE_SIZE + 662,93FIXED_TABLE_SIZE + 670,94FIXED_TABLE_SIZE + 686,95FIXED_TABLE_SIZE + 718,96FIXED_TABLE_SIZE + 782,97FIXED_TABLE_SIZE + 912,98FIXED_TABLE_SIZE + 1168,99FIXED_TABLE_SIZE + 1680,100FIXED_TABLE_SIZE + 2704101};102103static int VP8LSetError(VP8LDecoder* const dec, VP8StatusCode error) {104// The oldest error reported takes precedence over the new one.105if (dec->status_ == VP8_STATUS_OK || dec->status_ == VP8_STATUS_SUSPENDED) {106dec->status_ = error;107}108return 0;109}110111static int DecodeImageStream(int xsize, int ysize,112int is_level0,113VP8LDecoder* const dec,114uint32_t** const decoded_data);115116//------------------------------------------------------------------------------117118int VP8LCheckSignature(const uint8_t* const data, size_t size) {119return (size >= VP8L_FRAME_HEADER_SIZE &&120data[0] == VP8L_MAGIC_BYTE &&121(data[4] >> 5) == 0); // version122}123124static int ReadImageInfo(VP8LBitReader* const br,125int* const width, int* const height,126int* const has_alpha) {127if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;128*width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;129*height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;130*has_alpha = VP8LReadBits(br, 1);131if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;132return !br->eos_;133}134135int VP8LGetInfo(const uint8_t* data, size_t data_size,136int* const width, int* const height, int* const has_alpha) {137if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {138return 0; // not enough data139} else if (!VP8LCheckSignature(data, data_size)) {140return 0; // bad signature141} else {142int w, h, a;143VP8LBitReader br;144VP8LInitBitReader(&br, data, data_size);145if (!ReadImageInfo(&br, &w, &h, &a)) {146return 0;147}148if (width != NULL) *width = w;149if (height != NULL) *height = h;150if (has_alpha != NULL) *has_alpha = a;151return 1;152}153}154155//------------------------------------------------------------------------------156157static WEBP_INLINE int GetCopyDistance(int distance_symbol,158VP8LBitReader* const br) {159int extra_bits, offset;160if (distance_symbol < 4) {161return distance_symbol + 1;162}163extra_bits = (distance_symbol - 2) >> 1;164offset = (2 + (distance_symbol & 1)) << extra_bits;165return offset + VP8LReadBits(br, extra_bits) + 1;166}167168static WEBP_INLINE int GetCopyLength(int length_symbol,169VP8LBitReader* const br) {170// Length and distance prefixes are encoded the same way.171return GetCopyDistance(length_symbol, br);172}173174static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {175if (plane_code > CODE_TO_PLANE_CODES) {176return plane_code - CODE_TO_PLANE_CODES;177} else {178const int dist_code = kCodeToPlane[plane_code - 1];179const int yoffset = dist_code >> 4;180const int xoffset = 8 - (dist_code & 0xf);181const int dist = yoffset * xsize + xoffset;182return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small183}184}185186//------------------------------------------------------------------------------187// Decodes the next Huffman code from bit-stream.188// VP8LFillBitWindow(br) needs to be called at minimum every second call189// to ReadSymbol, in order to pre-fetch enough bits.190static WEBP_INLINE int ReadSymbol(const HuffmanCode* table,191VP8LBitReader* const br) {192int nbits;193uint32_t val = VP8LPrefetchBits(br);194table += val & HUFFMAN_TABLE_MASK;195nbits = table->bits - HUFFMAN_TABLE_BITS;196if (nbits > 0) {197VP8LSetBitPos(br, br->bit_pos_ + HUFFMAN_TABLE_BITS);198val = VP8LPrefetchBits(br);199table += table->value;200table += val & ((1 << nbits) - 1);201}202VP8LSetBitPos(br, br->bit_pos_ + table->bits);203return table->value;204}205206// Reads packed symbol depending on GREEN channel207#define BITS_SPECIAL_MARKER 0x100 // something large enough (and a bit-mask)208#define PACKED_NON_LITERAL_CODE 0 // must be < NUM_LITERAL_CODES209static WEBP_INLINE int ReadPackedSymbols(const HTreeGroup* group,210VP8LBitReader* const br,211uint32_t* const dst) {212const uint32_t val = VP8LPrefetchBits(br) & (HUFFMAN_PACKED_TABLE_SIZE - 1);213const HuffmanCode32 code = group->packed_table[val];214assert(group->use_packed_table);215if (code.bits < BITS_SPECIAL_MARKER) {216VP8LSetBitPos(br, br->bit_pos_ + code.bits);217*dst = code.value;218return PACKED_NON_LITERAL_CODE;219} else {220VP8LSetBitPos(br, br->bit_pos_ + code.bits - BITS_SPECIAL_MARKER);221assert(code.value >= NUM_LITERAL_CODES);222return code.value;223}224}225226static int AccumulateHCode(HuffmanCode hcode, int shift,227HuffmanCode32* const huff) {228huff->bits += hcode.bits;229huff->value |= (uint32_t)hcode.value << shift;230assert(huff->bits <= HUFFMAN_TABLE_BITS);231return hcode.bits;232}233234static void BuildPackedTable(HTreeGroup* const htree_group) {235uint32_t code;236for (code = 0; code < HUFFMAN_PACKED_TABLE_SIZE; ++code) {237uint32_t bits = code;238HuffmanCode32* const huff = &htree_group->packed_table[bits];239HuffmanCode hcode = htree_group->htrees[GREEN][bits];240if (hcode.value >= NUM_LITERAL_CODES) {241huff->bits = hcode.bits + BITS_SPECIAL_MARKER;242huff->value = hcode.value;243} else {244huff->bits = 0;245huff->value = 0;246bits >>= AccumulateHCode(hcode, 8, huff);247bits >>= AccumulateHCode(htree_group->htrees[RED][bits], 16, huff);248bits >>= AccumulateHCode(htree_group->htrees[BLUE][bits], 0, huff);249bits >>= AccumulateHCode(htree_group->htrees[ALPHA][bits], 24, huff);250(void)bits;251}252}253}254255static int ReadHuffmanCodeLengths(256VP8LDecoder* const dec, const int* const code_length_code_lengths,257int num_symbols, int* const code_lengths) {258int ok = 0;259VP8LBitReader* const br = &dec->br_;260int symbol;261int max_symbol;262int prev_code_len = DEFAULT_CODE_LENGTH;263HuffmanTables tables;264265if (!VP8LHuffmanTablesAllocate(1 << LENGTHS_TABLE_BITS, &tables) ||266!VP8LBuildHuffmanTable(&tables, LENGTHS_TABLE_BITS,267code_length_code_lengths, NUM_CODE_LENGTH_CODES)) {268goto End;269}270271if (VP8LReadBits(br, 1)) { // use length272const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);273max_symbol = 2 + VP8LReadBits(br, length_nbits);274if (max_symbol > num_symbols) {275goto End;276}277} else {278max_symbol = num_symbols;279}280281symbol = 0;282while (symbol < num_symbols) {283const HuffmanCode* p;284int code_len;285if (max_symbol-- == 0) break;286VP8LFillBitWindow(br);287p = &tables.curr_segment->start[VP8LPrefetchBits(br) & LENGTHS_TABLE_MASK];288VP8LSetBitPos(br, br->bit_pos_ + p->bits);289code_len = p->value;290if (code_len < kCodeLengthLiterals) {291code_lengths[symbol++] = code_len;292if (code_len != 0) prev_code_len = code_len;293} else {294const int use_prev = (code_len == kCodeLengthRepeatCode);295const int slot = code_len - kCodeLengthLiterals;296const int extra_bits = kCodeLengthExtraBits[slot];297const int repeat_offset = kCodeLengthRepeatOffsets[slot];298int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;299if (symbol + repeat > num_symbols) {300goto End;301} else {302const int length = use_prev ? prev_code_len : 0;303while (repeat-- > 0) code_lengths[symbol++] = length;304}305}306}307ok = 1;308309End:310VP8LHuffmanTablesDeallocate(&tables);311if (!ok) return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);312return ok;313}314315// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman316// tree.317static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,318int* const code_lengths,319HuffmanTables* const table) {320int ok = 0;321int size = 0;322VP8LBitReader* const br = &dec->br_;323const int simple_code = VP8LReadBits(br, 1);324325memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));326327if (simple_code) { // Read symbols, codes & code lengths directly.328const int num_symbols = VP8LReadBits(br, 1) + 1;329const int first_symbol_len_code = VP8LReadBits(br, 1);330// The first code is either 1 bit or 8 bit code.331int symbol = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);332code_lengths[symbol] = 1;333// The second code (if present), is always 8 bits long.334if (num_symbols == 2) {335symbol = VP8LReadBits(br, 8);336code_lengths[symbol] = 1;337}338ok = 1;339} else { // Decode Huffman-coded code lengths.340int i;341int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };342const int num_codes = VP8LReadBits(br, 4) + 4;343assert(num_codes <= NUM_CODE_LENGTH_CODES);344345for (i = 0; i < num_codes; ++i) {346code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);347}348ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,349code_lengths);350}351352ok = ok && !br->eos_;353if (ok) {354size = VP8LBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,355code_lengths, alphabet_size);356}357if (!ok || size == 0) {358return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);359}360return size;361}362363static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,364int color_cache_bits, int allow_recursion) {365int i;366VP8LBitReader* const br = &dec->br_;367VP8LMetadata* const hdr = &dec->hdr_;368uint32_t* huffman_image = NULL;369HTreeGroup* htree_groups = NULL;370HuffmanTables* huffman_tables = &hdr->huffman_tables_;371int num_htree_groups = 1;372int num_htree_groups_max = 1;373int* mapping = NULL;374int ok = 0;375376// Check the table has been 0 initialized (through InitMetadata).377assert(huffman_tables->root.start == NULL);378assert(huffman_tables->curr_segment == NULL);379380if (allow_recursion && VP8LReadBits(br, 1)) {381// use meta Huffman codes.382const int huffman_precision =383MIN_HUFFMAN_BITS + VP8LReadBits(br, NUM_HUFFMAN_BITS);384const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);385const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);386const int huffman_pixs = huffman_xsize * huffman_ysize;387if (!DecodeImageStream(huffman_xsize, huffman_ysize, /*is_level0=*/0, dec,388&huffman_image)) {389goto Error;390}391hdr->huffman_subsample_bits_ = huffman_precision;392for (i = 0; i < huffman_pixs; ++i) {393// The huffman data is stored in red and green bytes.394const int group = (huffman_image[i] >> 8) & 0xffff;395huffman_image[i] = group;396if (group >= num_htree_groups_max) {397num_htree_groups_max = group + 1;398}399}400// Check the validity of num_htree_groups_max. If it seems too big, use a401// smaller value for later. This will prevent big memory allocations to end402// up with a bad bitstream anyway.403// The value of 1000 is totally arbitrary. We know that num_htree_groups_max404// is smaller than (1 << 16) and should be smaller than the number of pixels405// (though the format allows it to be bigger).406if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {407// Create a mapping from the used indices to the minimal set of used408// values [0, num_htree_groups)409mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));410if (mapping == NULL) {411VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);412goto Error;413}414// -1 means a value is unmapped, and therefore unused in the Huffman415// image.416memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping));417for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {418// Get the current mapping for the group and remap the Huffman image.419int* const mapped_group = &mapping[huffman_image[i]];420if (*mapped_group == -1) *mapped_group = num_htree_groups++;421huffman_image[i] = *mapped_group;422}423} else {424num_htree_groups = num_htree_groups_max;425}426}427428if (br->eos_) goto Error;429430if (!ReadHuffmanCodesHelper(color_cache_bits, num_htree_groups,431num_htree_groups_max, mapping, dec,432huffman_tables, &htree_groups)) {433goto Error;434}435ok = 1;436437// All OK. Finalize pointers.438hdr->huffman_image_ = huffman_image;439hdr->num_htree_groups_ = num_htree_groups;440hdr->htree_groups_ = htree_groups;441442Error:443WebPSafeFree(mapping);444if (!ok) {445WebPSafeFree(huffman_image);446VP8LHuffmanTablesDeallocate(huffman_tables);447VP8LHtreeGroupsFree(htree_groups);448}449return ok;450}451452int ReadHuffmanCodesHelper(int color_cache_bits, int num_htree_groups,453int num_htree_groups_max, const int* const mapping,454VP8LDecoder* const dec,455HuffmanTables* const huffman_tables,456HTreeGroup** const htree_groups) {457int i, j, ok = 0;458const int max_alphabet_size =459kAlphabetSize[0] + ((color_cache_bits > 0) ? 1 << color_cache_bits : 0);460const int table_size = kTableSize[color_cache_bits];461int* code_lengths = NULL;462463if ((mapping == NULL && num_htree_groups != num_htree_groups_max) ||464num_htree_groups > num_htree_groups_max) {465goto Error;466}467468code_lengths =469(int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));470*htree_groups = VP8LHtreeGroupsNew(num_htree_groups);471472if (*htree_groups == NULL || code_lengths == NULL ||473!VP8LHuffmanTablesAllocate(num_htree_groups * table_size,474huffman_tables)) {475VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);476goto Error;477}478479for (i = 0; i < num_htree_groups_max; ++i) {480// If the index "i" is unused in the Huffman image, just make sure the481// coefficients are valid but do not store them.482if (mapping != NULL && mapping[i] == -1) {483for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {484int alphabet_size = kAlphabetSize[j];485if (j == 0 && color_cache_bits > 0) {486alphabet_size += (1 << color_cache_bits);487}488// Passing in NULL so that nothing gets filled.489if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {490goto Error;491}492}493} else {494HTreeGroup* const htree_group =495&(*htree_groups)[(mapping == NULL) ? i : mapping[i]];496HuffmanCode** const htrees = htree_group->htrees;497int size;498int total_size = 0;499int is_trivial_literal = 1;500int max_bits = 0;501for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {502int alphabet_size = kAlphabetSize[j];503if (j == 0 && color_cache_bits > 0) {504alphabet_size += (1 << color_cache_bits);505}506size =507ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);508htrees[j] = huffman_tables->curr_segment->curr_table;509if (size == 0) {510goto Error;511}512if (is_trivial_literal && kLiteralMap[j] == 1) {513is_trivial_literal = (htrees[j]->bits == 0);514}515total_size += htrees[j]->bits;516huffman_tables->curr_segment->curr_table += size;517if (j <= ALPHA) {518int local_max_bits = code_lengths[0];519int k;520for (k = 1; k < alphabet_size; ++k) {521if (code_lengths[k] > local_max_bits) {522local_max_bits = code_lengths[k];523}524}525max_bits += local_max_bits;526}527}528htree_group->is_trivial_literal = is_trivial_literal;529htree_group->is_trivial_code = 0;530if (is_trivial_literal) {531const int red = htrees[RED][0].value;532const int blue = htrees[BLUE][0].value;533const int alpha = htrees[ALPHA][0].value;534htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;535if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {536htree_group->is_trivial_code = 1;537htree_group->literal_arb |= htrees[GREEN][0].value << 8;538}539}540htree_group->use_packed_table =541!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);542if (htree_group->use_packed_table) BuildPackedTable(htree_group);543}544}545ok = 1;546547Error:548WebPSafeFree(code_lengths);549if (!ok) {550VP8LHuffmanTablesDeallocate(huffman_tables);551VP8LHtreeGroupsFree(*htree_groups);552*htree_groups = NULL;553}554return ok;555}556557//------------------------------------------------------------------------------558// Scaling.559560#if !defined(WEBP_REDUCE_SIZE)561static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {562const int num_channels = 4;563const int in_width = io->mb_w;564const int out_width = io->scaled_width;565const int in_height = io->mb_h;566const int out_height = io->scaled_height;567const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;568rescaler_t* work; // Rescaler work area.569const uint64_t scaled_data_size = (uint64_t)out_width;570uint32_t* scaled_data; // Temporary storage for scaled BGRA data.571const uint64_t memory_size = sizeof(*dec->rescaler) +572work_size * sizeof(*work) +573scaled_data_size * sizeof(*scaled_data);574uint8_t* memory = (uint8_t*)WebPSafeMalloc(memory_size, sizeof(*memory));575if (memory == NULL) {576return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);577}578assert(dec->rescaler_memory == NULL);579dec->rescaler_memory = memory;580581dec->rescaler = (WebPRescaler*)memory;582memory += sizeof(*dec->rescaler);583work = (rescaler_t*)memory;584memory += work_size * sizeof(*work);585scaled_data = (uint32_t*)memory;586587if (!WebPRescalerInit(dec->rescaler, in_width, in_height,588(uint8_t*)scaled_data, out_width, out_height,5890, num_channels, work)) {590return 0;591}592return 1;593}594#endif // WEBP_REDUCE_SIZE595596//------------------------------------------------------------------------------597// Export to ARGB598599#if !defined(WEBP_REDUCE_SIZE)600601// We have special "export" function since we need to convert from BGRA602static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,603int rgba_stride, uint8_t* const rgba) {604uint32_t* const src = (uint32_t*)rescaler->dst;605uint8_t* dst = rgba;606const int dst_width = rescaler->dst_width;607int num_lines_out = 0;608while (WebPRescalerHasPendingOutput(rescaler)) {609WebPRescalerExportRow(rescaler);610WebPMultARGBRow(src, dst_width, 1);611VP8LConvertFromBGRA(src, dst_width, colorspace, dst);612dst += rgba_stride;613++num_lines_out;614}615return num_lines_out;616}617618// Emit scaled rows.619static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,620uint8_t* in, int in_stride, int mb_h,621uint8_t* const out, int out_stride) {622const WEBP_CSP_MODE colorspace = dec->output_->colorspace;623int num_lines_in = 0;624int num_lines_out = 0;625while (num_lines_in < mb_h) {626uint8_t* const row_in = in + (uint64_t)num_lines_in * in_stride;627uint8_t* const row_out = out + (uint64_t)num_lines_out * out_stride;628const int lines_left = mb_h - num_lines_in;629const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);630int lines_imported;631assert(needed_lines > 0 && needed_lines <= lines_left);632WebPMultARGBRows(row_in, in_stride,633dec->rescaler->src_width, needed_lines, 0);634lines_imported =635WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);636assert(lines_imported == needed_lines);637num_lines_in += lines_imported;638num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);639}640return num_lines_out;641}642643#endif // WEBP_REDUCE_SIZE644645// Emit rows without any scaling.646static int EmitRows(WEBP_CSP_MODE colorspace,647const uint8_t* row_in, int in_stride,648int mb_w, int mb_h,649uint8_t* const out, int out_stride) {650int lines = mb_h;651uint8_t* row_out = out;652while (lines-- > 0) {653VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);654row_in += in_stride;655row_out += out_stride;656}657return mb_h; // Num rows out == num rows in.658}659660//------------------------------------------------------------------------------661// Export to YUVA662663static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,664const WebPDecBuffer* const output) {665const WebPYUVABuffer* const buf = &output->u.YUVA;666667// first, the luma plane668WebPConvertARGBToY(src, buf->y + y_pos * buf->y_stride, width);669670// then U/V planes671{672uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;673uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;674// even lines: store values675// odd lines: average with previous values676WebPConvertARGBToUV(src, u, v, width, !(y_pos & 1));677}678// Lastly, store alpha if needed.679if (buf->a != NULL) {680uint8_t* const a = buf->a + y_pos * buf->a_stride;681#if defined(WORDS_BIGENDIAN)682WebPExtractAlpha((uint8_t*)src + 0, 0, width, 1, a, 0);683#else684WebPExtractAlpha((uint8_t*)src + 3, 0, width, 1, a, 0);685#endif686}687}688689static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {690WebPRescaler* const rescaler = dec->rescaler;691uint32_t* const src = (uint32_t*)rescaler->dst;692const int dst_width = rescaler->dst_width;693int num_lines_out = 0;694while (WebPRescalerHasPendingOutput(rescaler)) {695WebPRescalerExportRow(rescaler);696WebPMultARGBRow(src, dst_width, 1);697ConvertToYUVA(src, dst_width, y_pos, dec->output_);698++y_pos;699++num_lines_out;700}701return num_lines_out;702}703704static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,705uint8_t* in, int in_stride, int mb_h) {706int num_lines_in = 0;707int y_pos = dec->last_out_row_;708while (num_lines_in < mb_h) {709const int lines_left = mb_h - num_lines_in;710const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);711int lines_imported;712WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);713lines_imported =714WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);715assert(lines_imported == needed_lines);716num_lines_in += lines_imported;717in += needed_lines * in_stride;718y_pos += ExportYUVA(dec, y_pos);719}720return y_pos;721}722723static int EmitRowsYUVA(const VP8LDecoder* const dec,724const uint8_t* in, int in_stride,725int mb_w, int num_rows) {726int y_pos = dec->last_out_row_;727while (num_rows-- > 0) {728ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);729in += in_stride;730++y_pos;731}732return y_pos;733}734735//------------------------------------------------------------------------------736// Cropping.737738// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and739// crop options. Also updates the input data pointer, so that it points to the740// start of the cropped window. Note that pixels are in ARGB format even if741// 'in_data' is uint8_t*.742// Returns true if the crop window is not empty.743static int SetCropWindow(VP8Io* const io, int y_start, int y_end,744uint8_t** const in_data, int pixel_stride) {745assert(y_start < y_end);746assert(io->crop_left < io->crop_right);747if (y_end > io->crop_bottom) {748y_end = io->crop_bottom; // make sure we don't overflow on last row.749}750if (y_start < io->crop_top) {751const int delta = io->crop_top - y_start;752y_start = io->crop_top;753*in_data += delta * pixel_stride;754}755if (y_start >= y_end) return 0; // Crop window is empty.756757*in_data += io->crop_left * sizeof(uint32_t);758759io->mb_y = y_start - io->crop_top;760io->mb_w = io->crop_right - io->crop_left;761io->mb_h = y_end - y_start;762return 1; // Non-empty crop window.763}764765//------------------------------------------------------------------------------766767static WEBP_INLINE int GetMetaIndex(768const uint32_t* const image, int xsize, int bits, int x, int y) {769if (bits == 0) return 0;770return image[xsize * (y >> bits) + (x >> bits)];771}772773static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,774int x, int y) {775const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,776hdr->huffman_subsample_bits_, x, y);777assert(meta_index < hdr->num_htree_groups_);778return hdr->htree_groups_ + meta_index;779}780781//------------------------------------------------------------------------------782// Main loop, with custom row-processing function783784typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);785786static void ApplyInverseTransforms(VP8LDecoder* const dec,787int start_row, int num_rows,788const uint32_t* const rows) {789int n = dec->next_transform_;790const int cache_pixs = dec->width_ * num_rows;791const int end_row = start_row + num_rows;792const uint32_t* rows_in = rows;793uint32_t* const rows_out = dec->argb_cache_;794795// Inverse transforms.796while (n-- > 0) {797VP8LTransform* const transform = &dec->transforms_[n];798VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);799rows_in = rows_out;800}801if (rows_in != rows_out) {802// No transform called, hence just copy.803memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));804}805}806807// Processes (transforms, scales & color-converts) the rows decoded after the808// last call.809static void ProcessRows(VP8LDecoder* const dec, int row) {810const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;811const int num_rows = row - dec->last_row_;812813assert(row <= dec->io_->crop_bottom);814// We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size815// of argb_cache_), but we currently don't need more than that.816assert(num_rows <= NUM_ARGB_CACHE_ROWS);817if (num_rows > 0) { // Emit output.818VP8Io* const io = dec->io_;819uint8_t* rows_data = (uint8_t*)dec->argb_cache_;820const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA821ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);822if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {823// Nothing to output (this time).824} else {825const WebPDecBuffer* const output = dec->output_;826if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA827const WebPRGBABuffer* const buf = &output->u.RGBA;828uint8_t* const rgba =829buf->rgba + (int64_t)dec->last_out_row_ * buf->stride;830const int num_rows_out =831#if !defined(WEBP_REDUCE_SIZE)832io->use_scaling ?833EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,834rgba, buf->stride) :835#endif // WEBP_REDUCE_SIZE836EmitRows(output->colorspace, rows_data, in_stride,837io->mb_w, io->mb_h, rgba, buf->stride);838// Update 'last_out_row_'.839dec->last_out_row_ += num_rows_out;840} else { // convert to YUVA841dec->last_out_row_ = io->use_scaling ?842EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :843EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);844}845assert(dec->last_out_row_ <= output->height);846}847}848849// Update 'last_row_'.850dec->last_row_ = row;851assert(dec->last_row_ <= dec->height_);852}853854// Row-processing for the special case when alpha data contains only one855// transform (color indexing), and trivial non-green literals.856static int Is8bOptimizable(const VP8LMetadata* const hdr) {857int i;858if (hdr->color_cache_size_ > 0) return 0;859// When the Huffman tree contains only one symbol, we can skip the860// call to ReadSymbol() for red/blue/alpha channels.861for (i = 0; i < hdr->num_htree_groups_; ++i) {862HuffmanCode** const htrees = hdr->htree_groups_[i].htrees;863if (htrees[RED][0].bits > 0) return 0;864if (htrees[BLUE][0].bits > 0) return 0;865if (htrees[ALPHA][0].bits > 0) return 0;866}867return 1;868}869870static void AlphaApplyFilter(ALPHDecoder* const alph_dec,871int first_row, int last_row,872uint8_t* out, int stride) {873if (alph_dec->filter_ != WEBP_FILTER_NONE) {874int y;875const uint8_t* prev_line = alph_dec->prev_line_;876assert(WebPUnfilters[alph_dec->filter_] != NULL);877for (y = first_row; y < last_row; ++y) {878WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);879prev_line = out;880out += stride;881}882alph_dec->prev_line_ = prev_line;883}884}885886static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {887// For vertical and gradient filtering, we need to decode the part above the888// crop_top row, in order to have the correct spatial predictors.889ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;890const int top_row =891(alph_dec->filter_ == WEBP_FILTER_NONE ||892alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top893: dec->last_row_;894const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;895assert(last_row <= dec->io_->crop_bottom);896if (last_row > first_row) {897// Special method for paletted alpha data. We only process the cropped area.898const int width = dec->io_->width;899uint8_t* out = alph_dec->output_ + width * first_row;900const uint8_t* const in =901(uint8_t*)dec->pixels_ + dec->width_ * first_row;902VP8LTransform* const transform = &dec->transforms_[0];903assert(dec->next_transform_ == 1);904assert(transform->type_ == COLOR_INDEXING_TRANSFORM);905VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,906in, out);907AlphaApplyFilter(alph_dec, first_row, last_row, out, width);908}909dec->last_row_ = dec->last_out_row_ = last_row;910}911912//------------------------------------------------------------------------------913// Helper functions for fast pattern copy (8b and 32b)914915// cyclic rotation of pattern word916static WEBP_INLINE uint32_t Rotate8b(uint32_t V) {917#if defined(WORDS_BIGENDIAN)918return ((V & 0xff000000u) >> 24) | (V << 8);919#else920return ((V & 0xffu) << 24) | (V >> 8);921#endif922}923924// copy 1, 2 or 4-bytes pattern925static WEBP_INLINE void CopySmallPattern8b(const uint8_t* src, uint8_t* dst,926int length, uint32_t pattern) {927int i;928// align 'dst' to 4-bytes boundary. Adjust the pattern along the way.929while ((uintptr_t)dst & 3) {930*dst++ = *src++;931pattern = Rotate8b(pattern);932--length;933}934// Copy the pattern 4 bytes at a time.935for (i = 0; i < (length >> 2); ++i) {936((uint32_t*)dst)[i] = pattern;937}938// Finish with left-overs. 'pattern' is still correctly positioned,939// so no Rotate8b() call is needed.940for (i <<= 2; i < length; ++i) {941dst[i] = src[i];942}943}944945static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) {946const uint8_t* src = dst - dist;947if (length >= 8) {948uint32_t pattern = 0;949switch (dist) {950case 1:951pattern = src[0];952#if defined(__arm__) || defined(_M_ARM) // arm doesn't like multiply that much953pattern |= pattern << 8;954pattern |= pattern << 16;955#elif defined(WEBP_USE_MIPS_DSP_R2)956__asm__ volatile ("replv.qb %0, %0" : "+r"(pattern));957#else958pattern = 0x01010101u * pattern;959#endif960break;961case 2:962#if !defined(WORDS_BIGENDIAN)963memcpy(&pattern, src, sizeof(uint16_t));964#else965pattern = ((uint32_t)src[0] << 8) | src[1];966#endif967#if defined(__arm__) || defined(_M_ARM)968pattern |= pattern << 16;969#elif defined(WEBP_USE_MIPS_DSP_R2)970__asm__ volatile ("replv.ph %0, %0" : "+r"(pattern));971#else972pattern = 0x00010001u * pattern;973#endif974break;975case 4:976memcpy(&pattern, src, sizeof(uint32_t));977break;978default:979goto Copy;980}981CopySmallPattern8b(src, dst, length, pattern);982return;983}984Copy:985if (dist >= length) { // no overlap -> use memcpy()986memcpy(dst, src, length * sizeof(*dst));987} else {988int i;989for (i = 0; i < length; ++i) dst[i] = src[i];990}991}992993// copy pattern of 1 or 2 uint32_t's994static WEBP_INLINE void CopySmallPattern32b(const uint32_t* src,995uint32_t* dst,996int length, uint64_t pattern) {997int i;998if ((uintptr_t)dst & 4) { // Align 'dst' to 8-bytes boundary.999*dst++ = *src++;1000pattern = (pattern >> 32) | (pattern << 32);1001--length;1002}1003assert(0 == ((uintptr_t)dst & 7));1004for (i = 0; i < (length >> 1); ++i) {1005((uint64_t*)dst)[i] = pattern; // Copy the pattern 8 bytes at a time.1006}1007if (length & 1) { // Finish with left-over.1008dst[i << 1] = src[i << 1];1009}1010}10111012static WEBP_INLINE void CopyBlock32b(uint32_t* const dst,1013int dist, int length) {1014const uint32_t* const src = dst - dist;1015if (dist <= 2 && length >= 4 && ((uintptr_t)dst & 3) == 0) {1016uint64_t pattern;1017if (dist == 1) {1018pattern = (uint64_t)src[0];1019pattern |= pattern << 32;1020} else {1021memcpy(&pattern, src, sizeof(pattern));1022}1023CopySmallPattern32b(src, dst, length, pattern);1024} else if (dist >= length) { // no overlap1025memcpy(dst, src, length * sizeof(*dst));1026} else {1027int i;1028for (i = 0; i < length; ++i) dst[i] = src[i];1029}1030}10311032//------------------------------------------------------------------------------10331034static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,1035int width, int height, int last_row) {1036int ok = 1;1037int row = dec->last_pixel_ / width;1038int col = dec->last_pixel_ % width;1039VP8LBitReader* const br = &dec->br_;1040VP8LMetadata* const hdr = &dec->hdr_;1041int pos = dec->last_pixel_; // current position1042const int end = width * height; // End of data1043const int last = width * last_row; // Last pixel to decode1044const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;1045const int mask = hdr->huffman_mask_;1046const HTreeGroup* htree_group =1047(pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;1048assert(pos <= end);1049assert(last_row <= height);1050assert(Is8bOptimizable(hdr));10511052while (!br->eos_ && pos < last) {1053int code;1054// Only update when changing tile.1055if ((col & mask) == 0) {1056htree_group = GetHtreeGroupForPos(hdr, col, row);1057}1058assert(htree_group != NULL);1059VP8LFillBitWindow(br);1060code = ReadSymbol(htree_group->htrees[GREEN], br);1061if (code < NUM_LITERAL_CODES) { // Literal1062data[pos] = code;1063++pos;1064++col;1065if (col >= width) {1066col = 0;1067++row;1068if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1069ExtractPalettedAlphaRows(dec, row);1070}1071}1072} else if (code < len_code_limit) { // Backward reference1073int dist_code, dist;1074const int length_sym = code - NUM_LITERAL_CODES;1075const int length = GetCopyLength(length_sym, br);1076const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);1077VP8LFillBitWindow(br);1078dist_code = GetCopyDistance(dist_symbol, br);1079dist = PlaneCodeToDistance(width, dist_code);1080if (pos >= dist && end - pos >= length) {1081CopyBlock8b(data + pos, dist, length);1082} else {1083ok = 0;1084goto End;1085}1086pos += length;1087col += length;1088while (col >= width) {1089col -= width;1090++row;1091if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1092ExtractPalettedAlphaRows(dec, row);1093}1094}1095if (pos < last && (col & mask)) {1096htree_group = GetHtreeGroupForPos(hdr, col, row);1097}1098} else { // Not reached1099ok = 0;1100goto End;1101}1102br->eos_ = VP8LIsEndOfStream(br);1103}1104// Process the remaining rows corresponding to last row-block.1105ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row);11061107End:1108br->eos_ = VP8LIsEndOfStream(br);1109if (!ok || (br->eos_ && pos < end)) {1110return VP8LSetError(1111dec, br->eos_ ? VP8_STATUS_SUSPENDED : VP8_STATUS_BITSTREAM_ERROR);1112}1113dec->last_pixel_ = pos;1114return ok;1115}11161117static void SaveState(VP8LDecoder* const dec, int last_pixel) {1118assert(dec->incremental_);1119dec->saved_br_ = dec->br_;1120dec->saved_last_pixel_ = last_pixel;1121if (dec->hdr_.color_cache_size_ > 0) {1122VP8LColorCacheCopy(&dec->hdr_.color_cache_, &dec->hdr_.saved_color_cache_);1123}1124}11251126static void RestoreState(VP8LDecoder* const dec) {1127assert(dec->br_.eos_);1128dec->status_ = VP8_STATUS_SUSPENDED;1129dec->br_ = dec->saved_br_;1130dec->last_pixel_ = dec->saved_last_pixel_;1131if (dec->hdr_.color_cache_size_ > 0) {1132VP8LColorCacheCopy(&dec->hdr_.saved_color_cache_, &dec->hdr_.color_cache_);1133}1134}11351136#define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points1137static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,1138int width, int height, int last_row,1139ProcessRowsFunc process_func) {1140int row = dec->last_pixel_ / width;1141int col = dec->last_pixel_ % width;1142VP8LBitReader* const br = &dec->br_;1143VP8LMetadata* const hdr = &dec->hdr_;1144uint32_t* src = data + dec->last_pixel_;1145uint32_t* last_cached = src;1146uint32_t* const src_end = data + width * height; // End of data1147uint32_t* const src_last = data + width * last_row; // Last pixel to decode1148const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;1149const int color_cache_limit = len_code_limit + hdr->color_cache_size_;1150int next_sync_row = dec->incremental_ ? row : 1 << 24;1151VP8LColorCache* const color_cache =1152(hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;1153const int mask = hdr->huffman_mask_;1154const HTreeGroup* htree_group =1155(src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;1156assert(dec->last_row_ < last_row);1157assert(src_last <= src_end);11581159while (src < src_last) {1160int code;1161if (row >= next_sync_row) {1162SaveState(dec, (int)(src - data));1163next_sync_row = row + SYNC_EVERY_N_ROWS;1164}1165// Only update when changing tile. Note we could use this test:1166// if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed1167// but that's actually slower and needs storing the previous col/row.1168if ((col & mask) == 0) {1169htree_group = GetHtreeGroupForPos(hdr, col, row);1170}1171assert(htree_group != NULL);1172if (htree_group->is_trivial_code) {1173*src = htree_group->literal_arb;1174goto AdvanceByOne;1175}1176VP8LFillBitWindow(br);1177if (htree_group->use_packed_table) {1178code = ReadPackedSymbols(htree_group, br, src);1179if (VP8LIsEndOfStream(br)) break;1180if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne;1181} else {1182code = ReadSymbol(htree_group->htrees[GREEN], br);1183}1184if (VP8LIsEndOfStream(br)) break;1185if (code < NUM_LITERAL_CODES) { // Literal1186if (htree_group->is_trivial_literal) {1187*src = htree_group->literal_arb | (code << 8);1188} else {1189int red, blue, alpha;1190red = ReadSymbol(htree_group->htrees[RED], br);1191VP8LFillBitWindow(br);1192blue = ReadSymbol(htree_group->htrees[BLUE], br);1193alpha = ReadSymbol(htree_group->htrees[ALPHA], br);1194if (VP8LIsEndOfStream(br)) break;1195*src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue;1196}1197AdvanceByOne:1198++src;1199++col;1200if (col >= width) {1201col = 0;1202++row;1203if (process_func != NULL) {1204if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1205process_func(dec, row);1206}1207}1208if (color_cache != NULL) {1209while (last_cached < src) {1210VP8LColorCacheInsert(color_cache, *last_cached++);1211}1212}1213}1214} else if (code < len_code_limit) { // Backward reference1215int dist_code, dist;1216const int length_sym = code - NUM_LITERAL_CODES;1217const int length = GetCopyLength(length_sym, br);1218const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br);1219VP8LFillBitWindow(br);1220dist_code = GetCopyDistance(dist_symbol, br);1221dist = PlaneCodeToDistance(width, dist_code);12221223if (VP8LIsEndOfStream(br)) break;1224if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {1225goto Error;1226} else {1227CopyBlock32b(src, dist, length);1228}1229src += length;1230col += length;1231while (col >= width) {1232col -= width;1233++row;1234if (process_func != NULL) {1235if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {1236process_func(dec, row);1237}1238}1239}1240// Because of the check done above (before 'src' was incremented by1241// 'length'), the following holds true.1242assert(src <= src_end);1243if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);1244if (color_cache != NULL) {1245while (last_cached < src) {1246VP8LColorCacheInsert(color_cache, *last_cached++);1247}1248}1249} else if (code < color_cache_limit) { // Color cache1250const int key = code - len_code_limit;1251assert(color_cache != NULL);1252while (last_cached < src) {1253VP8LColorCacheInsert(color_cache, *last_cached++);1254}1255*src = VP8LColorCacheLookup(color_cache, key);1256goto AdvanceByOne;1257} else { // Not reached1258goto Error;1259}1260}12611262br->eos_ = VP8LIsEndOfStream(br);1263// In incremental decoding:1264// br->eos_ && src < src_last: if 'br' reached the end of the buffer and1265// 'src_last' has not been reached yet, there is not enough data. 'dec' has to1266// be reset until there is more data.1267// !br->eos_ && src < src_last: this cannot happen as either the buffer is1268// fully read, either enough has been read to reach 'src_last'.1269// src >= src_last: 'src_last' is reached, all is fine. 'src' can actually go1270// beyond 'src_last' in case the image is cropped and an LZ77 goes further.1271// The buffer might have been enough or there is some left. 'br->eos_' does1272// not matter.1273assert(!dec->incremental_ || (br->eos_ && src < src_last) || src >= src_last);1274if (dec->incremental_ && br->eos_ && src < src_last) {1275RestoreState(dec);1276} else if ((dec->incremental_ && src >= src_last) || !br->eos_) {1277// Process the remaining rows corresponding to last row-block.1278if (process_func != NULL) {1279process_func(dec, row > last_row ? last_row : row);1280}1281dec->status_ = VP8_STATUS_OK;1282dec->last_pixel_ = (int)(src - data); // end-of-scan marker1283} else {1284// if not incremental, and we are past the end of buffer (eos_=1), then this1285// is a real bitstream error.1286goto Error;1287}1288return 1;12891290Error:1291return VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1292}12931294// -----------------------------------------------------------------------------1295// VP8LTransform12961297static void ClearTransform(VP8LTransform* const transform) {1298WebPSafeFree(transform->data_);1299transform->data_ = NULL;1300}13011302// For security reason, we need to remap the color map to span1303// the total possible bundled values, and not just the num_colors.1304static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {1305int i;1306const int final_num_colors = 1 << (8 >> transform->bits_);1307uint32_t* const new_color_map =1308(uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,1309sizeof(*new_color_map));1310if (new_color_map == NULL) {1311return 0;1312} else {1313uint8_t* const data = (uint8_t*)transform->data_;1314uint8_t* const new_data = (uint8_t*)new_color_map;1315new_color_map[0] = transform->data_[0];1316for (i = 4; i < 4 * num_colors; ++i) {1317// Equivalent to VP8LAddPixels(), on a byte-basis.1318new_data[i] = (data[i] + new_data[i - 4]) & 0xff;1319}1320for (; i < 4 * final_num_colors; ++i) {1321new_data[i] = 0; // black tail.1322}1323WebPSafeFree(transform->data_);1324transform->data_ = new_color_map;1325}1326return 1;1327}13281329static int ReadTransform(int* const xsize, int const* ysize,1330VP8LDecoder* const dec) {1331int ok = 1;1332VP8LBitReader* const br = &dec->br_;1333VP8LTransform* transform = &dec->transforms_[dec->next_transform_];1334const VP8LImageTransformType type =1335(VP8LImageTransformType)VP8LReadBits(br, 2);13361337// Each transform type can only be present once in the stream.1338if (dec->transforms_seen_ & (1U << type)) {1339return 0; // Already there, let's not accept the second same transform.1340}1341dec->transforms_seen_ |= (1U << type);13421343transform->type_ = type;1344transform->xsize_ = *xsize;1345transform->ysize_ = *ysize;1346transform->data_ = NULL;1347++dec->next_transform_;1348assert(dec->next_transform_ <= NUM_TRANSFORMS);13491350switch (type) {1351case PREDICTOR_TRANSFORM:1352case CROSS_COLOR_TRANSFORM:1353transform->bits_ =1354MIN_TRANSFORM_BITS + VP8LReadBits(br, NUM_TRANSFORM_BITS);1355ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,1356transform->bits_),1357VP8LSubSampleSize(transform->ysize_,1358transform->bits_),1359/*is_level0=*/0, dec, &transform->data_);1360break;1361case COLOR_INDEXING_TRANSFORM: {1362const int num_colors = VP8LReadBits(br, 8) + 1;1363const int bits = (num_colors > 16) ? 01364: (num_colors > 4) ? 11365: (num_colors > 2) ? 21366: 3;1367*xsize = VP8LSubSampleSize(transform->xsize_, bits);1368transform->bits_ = bits;1369ok = DecodeImageStream(num_colors, /*ysize=*/1, /*is_level0=*/0, dec,1370&transform->data_);1371if (ok && !ExpandColorMap(num_colors, transform)) {1372return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1373}1374break;1375}1376case SUBTRACT_GREEN_TRANSFORM:1377break;1378default:1379assert(0); // can't happen1380break;1381}13821383return ok;1384}13851386// -----------------------------------------------------------------------------1387// VP8LMetadata13881389static void InitMetadata(VP8LMetadata* const hdr) {1390assert(hdr != NULL);1391memset(hdr, 0, sizeof(*hdr));1392}13931394static void ClearMetadata(VP8LMetadata* const hdr) {1395assert(hdr != NULL);13961397WebPSafeFree(hdr->huffman_image_);1398VP8LHuffmanTablesDeallocate(&hdr->huffman_tables_);1399VP8LHtreeGroupsFree(hdr->htree_groups_);1400VP8LColorCacheClear(&hdr->color_cache_);1401VP8LColorCacheClear(&hdr->saved_color_cache_);1402InitMetadata(hdr);1403}14041405// -----------------------------------------------------------------------------1406// VP8LDecoder14071408VP8LDecoder* VP8LNew(void) {1409VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));1410if (dec == NULL) return NULL;1411dec->status_ = VP8_STATUS_OK;1412dec->state_ = READ_DIM;14131414VP8LDspInit(); // Init critical function pointers.14151416return dec;1417}14181419// Resets the decoder in its initial state, reclaiming memory.1420// Preserves the dec->status_ value.1421static void VP8LClear(VP8LDecoder* const dec) {1422int i;1423if (dec == NULL) return;1424ClearMetadata(&dec->hdr_);14251426WebPSafeFree(dec->pixels_);1427dec->pixels_ = NULL;1428for (i = 0; i < dec->next_transform_; ++i) {1429ClearTransform(&dec->transforms_[i]);1430}1431dec->next_transform_ = 0;1432dec->transforms_seen_ = 0;14331434WebPSafeFree(dec->rescaler_memory);1435dec->rescaler_memory = NULL;14361437dec->output_ = NULL; // leave no trace behind1438}14391440void VP8LDelete(VP8LDecoder* const dec) {1441if (dec != NULL) {1442VP8LClear(dec);1443WebPSafeFree(dec);1444}1445}14461447static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {1448VP8LMetadata* const hdr = &dec->hdr_;1449const int num_bits = hdr->huffman_subsample_bits_;1450dec->width_ = width;1451dec->height_ = height;14521453hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);1454hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;1455}14561457static int DecodeImageStream(int xsize, int ysize,1458int is_level0,1459VP8LDecoder* const dec,1460uint32_t** const decoded_data) {1461int ok = 1;1462int transform_xsize = xsize;1463int transform_ysize = ysize;1464VP8LBitReader* const br = &dec->br_;1465VP8LMetadata* const hdr = &dec->hdr_;1466uint32_t* data = NULL;1467int color_cache_bits = 0;14681469// Read the transforms (may recurse).1470if (is_level0) {1471while (ok && VP8LReadBits(br, 1)) {1472ok = ReadTransform(&transform_xsize, &transform_ysize, dec);1473}1474}14751476// Color cache1477if (ok && VP8LReadBits(br, 1)) {1478color_cache_bits = VP8LReadBits(br, 4);1479ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);1480if (!ok) {1481VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1482goto End;1483}1484}14851486// Read the Huffman codes (may recurse).1487ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,1488color_cache_bits, is_level0);1489if (!ok) {1490VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1491goto End;1492}14931494// Finish setting up the color-cache1495if (color_cache_bits > 0) {1496hdr->color_cache_size_ = 1 << color_cache_bits;1497if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {1498ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1499goto End;1500}1501} else {1502hdr->color_cache_size_ = 0;1503}1504UpdateDecoder(dec, transform_xsize, transform_ysize);15051506if (is_level0) { // level 0 complete1507dec->state_ = READ_HDR;1508goto End;1509}15101511{1512const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;1513data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));1514if (data == NULL) {1515ok = VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1516goto End;1517}1518}15191520// Use the Huffman trees to decode the LZ77 encoded data.1521ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,1522transform_ysize, NULL);1523ok = ok && !br->eos_;15241525End:1526if (!ok) {1527WebPSafeFree(data);1528ClearMetadata(hdr);1529} else {1530if (decoded_data != NULL) {1531*decoded_data = data;1532} else {1533// We allocate image data in this function only for transforms. At level 01534// (that is: not the transforms), we shouldn't have allocated anything.1535assert(data == NULL);1536assert(is_level0);1537}1538dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.1539if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.1540}1541return ok;1542}15431544//------------------------------------------------------------------------------1545// Allocate internal buffers dec->pixels_ and dec->argb_cache_.1546static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {1547const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;1548// Scratch buffer corresponding to top-prediction row for transforming the1549// first row in the row-blocks. Not needed for paletted alpha.1550const uint64_t cache_top_pixels = (uint16_t)final_width;1551// Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.1552const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;1553const uint64_t total_num_pixels =1554num_pixels + cache_top_pixels + cache_pixels;15551556assert(dec->width_ <= final_width);1557dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));1558if (dec->pixels_ == NULL) {1559dec->argb_cache_ = NULL; // for soundness1560return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1561}1562dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;1563return 1;1564}15651566static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {1567const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;1568dec->argb_cache_ = NULL; // for soundness1569dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));1570if (dec->pixels_ == NULL) {1571return VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1572}1573return 1;1574}15751576//------------------------------------------------------------------------------15771578// Special row-processing that only stores the alpha data.1579static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {1580int cur_row = dec->last_row_;1581int num_rows = last_row - cur_row;1582const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;15831584assert(last_row <= dec->io_->crop_bottom);1585while (num_rows > 0) {1586const int num_rows_to_process =1587(num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;1588// Extract alpha (which is stored in the green plane).1589ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;1590uint8_t* const output = alph_dec->output_;1591const int width = dec->io_->width; // the final width (!= dec->width_)1592const int cache_pixs = width * num_rows_to_process;1593uint8_t* const dst = output + width * cur_row;1594const uint32_t* const src = dec->argb_cache_;1595ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);1596WebPExtractGreen(src, dst, cache_pixs);1597AlphaApplyFilter(alph_dec,1598cur_row, cur_row + num_rows_to_process, dst, width);1599num_rows -= num_rows_to_process;1600in += num_rows_to_process * dec->width_;1601cur_row += num_rows_to_process;1602}1603assert(cur_row == last_row);1604dec->last_row_ = dec->last_out_row_ = last_row;1605}16061607int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,1608const uint8_t* const data, size_t data_size) {1609int ok = 0;1610VP8LDecoder* dec = VP8LNew();16111612if (dec == NULL) return 0;16131614assert(alph_dec != NULL);16151616dec->width_ = alph_dec->width_;1617dec->height_ = alph_dec->height_;1618dec->io_ = &alph_dec->io_;1619dec->io_->opaque = alph_dec;1620dec->io_->width = alph_dec->width_;1621dec->io_->height = alph_dec->height_;16221623dec->status_ = VP8_STATUS_OK;1624VP8LInitBitReader(&dec->br_, data, data_size);16251626if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, /*is_level0=*/1,1627dec, /*decoded_data=*/NULL)) {1628goto Err;1629}16301631// Special case: if alpha data uses only the color indexing transform and1632// doesn't use color cache (a frequent case), we will use DecodeAlphaData()1633// method that only needs allocation of 1 byte per pixel (alpha channel).1634if (dec->next_transform_ == 1 &&1635dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&1636Is8bOptimizable(&dec->hdr_)) {1637alph_dec->use_8b_decode_ = 1;1638ok = AllocateInternalBuffers8b(dec);1639} else {1640// Allocate internal buffers (note that dec->width_ may have changed here).1641alph_dec->use_8b_decode_ = 0;1642ok = AllocateInternalBuffers32b(dec, alph_dec->width_);1643}16441645if (!ok) goto Err;16461647// Only set here, once we are sure it is valid (to avoid thread races).1648alph_dec->vp8l_dec_ = dec;1649return 1;16501651Err:1652VP8LDelete(dec);1653return 0;1654}16551656int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {1657VP8LDecoder* const dec = alph_dec->vp8l_dec_;1658assert(dec != NULL);1659assert(last_row <= dec->height_);16601661if (dec->last_row_ >= last_row) {1662return 1; // done1663}16641665if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing();16661667// Decode (with special row processing).1668return alph_dec->use_8b_decode_ ?1669DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,1670last_row) :1671DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,1672last_row, ExtractAlphaRows);1673}16741675//------------------------------------------------------------------------------16761677int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {1678int width, height, has_alpha;16791680if (dec == NULL) return 0;1681if (io == NULL) {1682return VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1683}16841685dec->io_ = io;1686dec->status_ = VP8_STATUS_OK;1687VP8LInitBitReader(&dec->br_, io->data, io->data_size);1688if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {1689VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);1690goto Error;1691}1692dec->state_ = READ_DIM;1693io->width = width;1694io->height = height;16951696if (!DecodeImageStream(width, height, /*is_level0=*/1, dec,1697/*decoded_data=*/NULL)) {1698goto Error;1699}1700return 1;17011702Error:1703VP8LClear(dec);1704assert(dec->status_ != VP8_STATUS_OK);1705return 0;1706}17071708int VP8LDecodeImage(VP8LDecoder* const dec) {1709VP8Io* io = NULL;1710WebPDecParams* params = NULL;17111712if (dec == NULL) return 0;17131714assert(dec->hdr_.huffman_tables_.root.start != NULL);1715assert(dec->hdr_.htree_groups_ != NULL);1716assert(dec->hdr_.num_htree_groups_ > 0);17171718io = dec->io_;1719assert(io != NULL);1720params = (WebPDecParams*)io->opaque;1721assert(params != NULL);17221723// Initialization.1724if (dec->state_ != READ_DATA) {1725dec->output_ = params->output;1726assert(dec->output_ != NULL);17271728if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {1729VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1730goto Err;1731}17321733if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;17341735#if !defined(WEBP_REDUCE_SIZE)1736if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;1737#else1738if (io->use_scaling) {1739VP8LSetError(dec, VP8_STATUS_INVALID_PARAM);1740goto Err;1741}1742#endif1743if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {1744// need the alpha-multiply functions for premultiplied output or rescaling1745WebPInitAlphaProcessing();1746}17471748if (!WebPIsRGBMode(dec->output_->colorspace)) {1749WebPInitConvertARGBToYUV();1750if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing();1751}1752if (dec->incremental_) {1753if (dec->hdr_.color_cache_size_ > 0 &&1754dec->hdr_.saved_color_cache_.colors_ == NULL) {1755if (!VP8LColorCacheInit(&dec->hdr_.saved_color_cache_,1756dec->hdr_.color_cache_.hash_bits_)) {1757VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);1758goto Err;1759}1760}1761}1762dec->state_ = READ_DATA;1763}17641765// Decode.1766if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,1767io->crop_bottom, ProcessRows)) {1768goto Err;1769}17701771params->last_y = dec->last_out_row_;1772return 1;17731774Err:1775VP8LClear(dec);1776assert(dec->status_ != VP8_STATUS_OK);1777return 0;1778}17791780//------------------------------------------------------------------------------178117821783