1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved.
2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// main entry for the decoder
11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Authors: Vikas Arora (vikaas.arora@gmail.com)
13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//          Jyrki Alakuijala (jyrki@google.com)
14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <stdlib.h>
16259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi
178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include "./alphai.h"
18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8li.h"
19af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora#include "../dsp/dsp.h"
20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dsp/lossless.h"
21a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dsp/yuv.h"
22a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/huffman.h"
23a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/utils.h"
24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
25a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define NUM_ARGB_CACHE_ROWS          16
26a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
27a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthLiterals = 16;
28a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthRepeatCode = 16;
29a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
30a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
31a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
32a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  Five Huffman codes are used at each meta code:
34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  1. green + length prefix codes + color cache codes,
35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  2. alpha,
36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  3. red,
37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  4. blue, and,
38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//  5. distance prefix codes.
39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef enum {
40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  GREEN = 0,
41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  RED   = 1,
42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  BLUE  = 2,
43a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ALPHA = 3,
44a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  DIST  = 4
45a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} HuffIndex;
46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  NUM_LITERAL_CODES + NUM_LENGTH_CODES,
49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  NUM_DISTANCE_CODES
51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define NUM_CODE_LENGTH_CODES       19
55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define CODE_TO_PLANE_CODES        120
608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
610406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
620406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
630406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
650406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
660406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
670406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
680406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
690406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
700406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
710406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
720406ce1417f76f2034833414dcecc9f56253640cVikas Arora  0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
75a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize,
76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             int is_level0,
77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             VP8LDecoder* const dec,
78a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             uint32_t** const decoded_data);
79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
81a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LCheckSignature(const uint8_t* const data, size_t size) {
838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return (size >= VP8L_FRAME_HEADER_SIZE &&
848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          data[0] == VP8L_MAGIC_BYTE &&
858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          (data[4] >> 5) == 0);  // version
86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadImageInfo(VP8LBitReader* const br,
89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                         int* const width, int* const height,
90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                         int* const has_alpha) {
918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  *has_alpha = VP8LReadBits(br, 1);
958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
97a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LGetInfo(const uint8_t* data, size_t data_size,
100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                int* const width, int* const height, int* const has_alpha) {
101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;         // not enough data
1038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else if (!VP8LCheckSignature(data, data_size)) {
1048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    return 0;         // bad signature
105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int w, h, a;
107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LBitReader br;
108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LInitBitReader(&br, data, data_size);
109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!ReadImageInfo(&br, &w, &h, &a)) {
110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      return 0;
111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (width != NULL) *width = w;
113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (height != NULL) *height = h;
114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (has_alpha != NULL) *has_alpha = a;
115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 1;
116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetCopyDistance(int distance_symbol,
122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                       VP8LBitReader* const br) {
123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int extra_bits, offset;
124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (distance_symbol < 4) {
125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return distance_symbol + 1;
126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  extra_bits = (distance_symbol - 2) >> 1;
128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  offset = (2 + (distance_symbol & 1)) << extra_bits;
129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return offset + VP8LReadBits(br, extra_bits) + 1;
130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetCopyLength(int length_symbol,
133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                     VP8LBitReader* const br) {
134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Length and distance prefixes are encoded the same way.
135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return GetCopyDistance(length_symbol, br);
136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (plane_code > CODE_TO_PLANE_CODES) {
140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return plane_code - CODE_TO_PLANE_CODES;
141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int dist_code = kCodeToPlane[plane_code - 1];
143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int yoffset = dist_code >> 4;
144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int xoffset = 8 - (dist_code & 0xf);
145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int dist = yoffset * xsize + xoffset;
1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    return (dist >= 1) ? dist : 1;  // dist<1 can happen if xsize is very small
147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Decodes the next Huffman code from bit-stream.
152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// FillBitWindow(br) needs to be called at minimum every second call
1531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// to ReadSymbol, in order to pre-fetch enough bits.
1541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
1551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                                  VP8LBitReader* const br) {
156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const HuffmanTreeNode* node = tree->root_;
1571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  uint32_t bits = VP8LPrefetchBits(br);
1588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int bitpos = br->bit_pos_;
1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Check if we find the bit combination from the Huffman lookup table.
1608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int lut_ix = bits & (HUFF_LUT - 1);
1618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int lut_bits = tree->lut_bits_[lut_ix];
1628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (lut_bits <= HUFF_LUT_BITS) {
1638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LSetBitPos(br, bitpos + lut_bits);
1648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    return tree->lut_symbol_[lut_ix];
1658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  node += tree->lut_jump_[lut_ix];
1678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  bitpos += HUFF_LUT_BITS;
1688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  bits >>= HUFF_LUT_BITS;
1698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Decode the value from a binary tree.
171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(node != NULL);
1728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  do {
1731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    node = HuffmanTreeNextNode(node, bits & 1);
1741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    bits >>= 1;
1758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ++bitpos;
1768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } while (HuffmanTreeNodeIsNotLeaf(node));
1778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LSetBitPos(br, bitpos);
178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return node->symbol_;
179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodeLengths(
182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LDecoder* const dec, const int* const code_length_code_lengths,
183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int num_symbols, int* const code_lengths) {
184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int symbol;
187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int max_symbol;
188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int prev_code_len = DEFAULT_CODE_LENGTH;
189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  HuffmanTree tree;
190af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 };
191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
192af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
193af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                                    huff_codes, NUM_CODE_LENGTH_CODES)) {
194a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
197a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (VP8LReadBits(br, 1)) {    // use length
199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
200a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    max_symbol = 2 + VP8LReadBits(br, length_nbits);
201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (max_symbol > num_symbols) {
202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    max_symbol = num_symbols;
207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  symbol = 0;
210a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (symbol < num_symbols) {
211a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int code_len;
212a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (max_symbol-- == 0) break;
213a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LFillBitWindow(br);
214a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    code_len = ReadSymbol(&tree, br);
215a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (code_len < kCodeLengthLiterals) {
216a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      code_lengths[symbol++] = code_len;
217a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (code_len != 0) prev_code_len = code_len;
218a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    } else {
219a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int use_prev = (code_len == kCodeLengthRepeatCode);
220a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int slot = code_len - kCodeLengthLiterals;
221a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int extra_bits = kCodeLengthExtraBits[slot];
222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int repeat_offset = kCodeLengthRepeatOffsets[slot];
223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (symbol + repeat > num_symbols) {
225a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        goto End;
227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {
228a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const int length = use_prev ? prev_code_len : 0;
229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        while (repeat-- > 0) code_lengths[symbol++] = length;
230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = 1;
234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End:
236af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  VP8LHuffmanTreeFree(&tree);
237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
240af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
241af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// tree.
242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
243af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                           int* const code_lengths, int* const huff_codes,
244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                           HuffmanTree* const tree) {
245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int simple_code = VP8LReadBits(br, 1);
248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (simple_code) {  // Read symbols, codes & code lengths directly.
250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int symbols[2];
251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int codes[2];
252a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int num_symbols = VP8LReadBits(br, 1) + 1;
253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int first_symbol_len_code = VP8LReadBits(br, 1);
254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // The first code is either 1 bit or 8 bit code.
255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    codes[0] = 0;
257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    code_lengths[0] = num_symbols - 1;
258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // The second code (if present), is always 8 bit long.
259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (num_symbols == 2) {
260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      symbols[1] = VP8LReadBits(br, 8);
261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      codes[1] = 1;
262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      code_lengths[1] = num_symbols - 1;
263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
264af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
265af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                                      alphabet_size, num_symbols);
266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {  // Decode Huffman-coded code lengths.
267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int num_codes = VP8LReadBits(br, 4) + 4;
270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (num_codes > NUM_CODE_LENGTH_CODES) {
271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      return 0;
273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
275af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < num_codes; ++i) {
278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                code_lengths);
282af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    ok = ok && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes,
283af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                                            alphabet_size);
284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && !br->error_;
286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                            int color_cache_bits, int allow_recursion) {
295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i, j;
296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* huffman_image = NULL;
299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  HTreeGroup* htree_groups = NULL;
300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_htree_groups = 1;
301af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  int max_alphabet_size = 0;
302af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  int* code_lengths = NULL;
303af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  int* huff_codes = NULL;
304a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (allow_recursion && VP8LReadBits(br, 1)) {
306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // use meta Huffman codes.
307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_precision = VP8LReadBits(br, 3) + 2;
308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
309a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_pixs = huffman_xsize * huffman_ysize;
311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                           &huffman_image)) {
313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto Error;
315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->huffman_subsample_bits_ = huffman_precision;
317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < huffman_pixs; ++i) {
318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // The huffman data is stored in red and green bytes.
3191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      const int group = (huffman_image[i] >> 8) & 0xffff;
3201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      huffman_image[i] = group;
3211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      if (group >= num_htree_groups) {
3221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora        num_htree_groups = group + 1;
323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (br->error_) goto Error;
328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
329af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  // Find maximum alphabet size for the htree group.
330af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
331af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    int alphabet_size = kAlphabetSize[j];
332af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    if (j == 0 && color_cache_bits > 0) {
333af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      alphabet_size += 1 << color_cache_bits;
334af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    }
335af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    if (max_alphabet_size < alphabet_size) {
336af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      max_alphabet_size = alphabet_size;
337af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    }
338af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  }
339af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora
340af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
341af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  code_lengths =
342af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
343af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  huff_codes =
344af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes));
345af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora
346af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) {
347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Error;
349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 0; i < num_htree_groups; ++i) {
352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    HuffmanTree* const htrees = htree_groups[i].htrees_;
353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int alphabet_size = kAlphabetSize[j];
355af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      HuffmanTree* const htree = htrees + j;
356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (j == 0 && color_cache_bits > 0) {
357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        alphabet_size += 1 << color_cache_bits;
358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
359af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes,
360af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora                           htree)) {
361af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora        goto Error;
362af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      }
363a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
365af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(huff_codes);
366af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(code_lengths);
367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // All OK. Finalize pointers and return.
369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_image_ = huffman_image;
370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->num_htree_groups_ = num_htree_groups;
371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->htree_groups_ = htree_groups;
372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error:
375af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(huff_codes);
376af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(code_lengths);
377af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(huffman_image);
378af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  VP8LHtreeGroupsFree(htree_groups, num_htree_groups);
379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 0;
380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
381a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Scaling.
384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_channels = 4;
387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int in_width = io->mb_w;
388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int out_width = io->scaled_width;
389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int in_height = io->mb_h;
390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int out_height = io->scaled_height;
391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int32_t* work;        // Rescaler work area.
393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* scaled_data;  // Temporary storage for scaled BGRA data.
395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t memory_size = sizeof(*dec->rescaler) +
396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                               work_size * sizeof(*work) +
397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                               scaled_data_size * sizeof(*scaled_data);
398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (memory == NULL) {
400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->rescaler_memory == NULL);
404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler_memory = memory;
405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler = (WebPRescaler*)memory;
407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memory += sizeof(*dec->rescaler);
408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  work = (int32_t*)memory;
409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memory += work_size * sizeof(*work);
410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  scaled_data = (uint32_t*)memory;
411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                   out_width, out_height, 0, num_channels,
414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                   in_width, out_width, in_height, out_height, work);
415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to ARGB
420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// We have special "export" function since we need to convert from BGRA
422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                  int rgba_stride, uint8_t* const rgba) {
4248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src = (uint32_t*)rescaler->dst;
425a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int dst_width = rescaler->dst_width;
426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (WebPRescalerHasPendingOutput(rescaler)) {
428a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const dst = rgba + num_lines_out * rgba_stride;
429af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPRescalerExportRow(rescaler, 0);
4308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRow(src, dst_width, 1);
431a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++num_lines_out;
433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit scaled rows.
4388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
4398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* in, int in_stride, int mb_h,
4408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* const out, int out_stride) {
441a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_in = 0;
443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_lines_in < mb_h) {
4458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    uint8_t* const row_in = in + num_lines_in * in_stride;
446a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const row_out = out + num_lines_out * out_stride;
4478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int lines_left = mb_h - num_lines_in;
4488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
4498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(needed_lines > 0 && needed_lines <= lines_left);
4508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRows(row_in, in_stride,
4518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                     dec->rescaler->src_width, needed_lines, 0);
4528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
4538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    num_lines_in += needed_lines;
454a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit rows without any scaling.
460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRows(WEBP_CSP_MODE colorspace,
4618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                    const uint8_t* row_in, int in_stride,
462a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                    int mb_w, int mb_h,
463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                    uint8_t* const out, int out_stride) {
464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int lines = mb_h;
465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint8_t* row_out = out;
466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (lines-- > 0) {
467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    row_in += in_stride;
469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    row_out += out_stride;
470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return mb_h;  // Num rows out == num rows in.
472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to YUVA
476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
477af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora// TODO(skal): should be in yuv.c
478a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                          const WebPDecBuffer* const output) {
480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const WebPYUVABuffer* const buf = &output->u.YUVA;
481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // first, the luma plane
482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const y = buf->y + y_pos * buf->y_stride;
485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < width; ++i) {
486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t p = src[i];
4878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
4888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       YUV_HALF);
489a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // then U/V planes
493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int uv_width = width >> 1;
497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < uv_width; ++i) {
499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v0 = src[2 * i + 0];
500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v1 = src[2 * i + 1];
501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // VP8RGBToU/V expects four accumulated pixels. Hence we need to
502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int g = ((v0 >>  7) & 0x1fe) + ((v1 >>  7) & 0x1fe);
505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int b = ((v0 <<  1) & 0x1fe) + ((v1 <<  1) & 0x1fe);
506a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (!(y_pos & 1)) {  // even lines: store values
5078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
509a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {             // odd lines: average with previous values
5108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
512a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Approximated average-of-four. But it's an acceptable diff.
513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        u[i] = (u[i] + tmp_u + 1) >> 1;
514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        v[i] = (v[i] + tmp_v + 1) >> 1;
515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (width & 1) {       // last pixel
518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v0 = src[2 * i + 0];
519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int r = (v0 >> 14) & 0x3fc;
520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int g = (v0 >>  6) & 0x3fc;
521a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int b = (v0 <<  2) & 0x3fc;
522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (!(y_pos & 1)) {  // even lines
5238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
525a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {             // odd lines (note: we could just skip this)
5268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
528a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        u[i] = (u[i] + tmp_u + 1) >> 1;
529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        v[i] = (v[i] + tmp_v + 1) >> 1;
530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
532a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
533a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Lastly, store alpha if needed.
534a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (buf->a != NULL) {
535a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
536a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const a = buf->a + y_pos * buf->a_stride;
537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
540a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
541a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
542a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPRescaler* const rescaler = dec->rescaler;
5438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src = (uint32_t*)rescaler->dst;
544a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int dst_width = rescaler->dst_width;
545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
546a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (WebPRescalerHasPendingOutput(rescaler)) {
547af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPRescalerExportRow(rescaler, 0);
5488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRow(src, dst_width, 1);
549a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ConvertToYUVA(src, dst_width, y_pos, dec->output_);
550a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y_pos;
551a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++num_lines_out;
552a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
553a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
554a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
555a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
556a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
5578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* in, int in_stride, int mb_h) {
558a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_in = 0;
559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y_pos = dec->last_out_row_;
560a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_lines_in < mb_h) {
5618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int lines_left = mb_h - num_lines_in;
5628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
5638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
5648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
5658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    num_lines_in += needed_lines;
5668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    in += needed_lines * in_stride;
567a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_pos += ExportYUVA(dec, y_pos);
568a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
569a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return y_pos;
570a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
571a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
572a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRowsYUVA(const VP8LDecoder* const dec,
5738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                        const uint8_t* in, int in_stride,
574a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                        int mb_w, int num_rows) {
575a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y_pos = dec->last_out_row_;
576a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_rows-- > 0) {
5778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
5788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    in += in_stride;
579a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y_pos;
580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return y_pos;
582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Cropping.
586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
588a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// crop options. Also updates the input data pointer, so that it points to the
5898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// start of the cropped window. Note that pixels are in ARGB format even if
5908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 'in_data' is uint8_t*.
591a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Returns true if the crop window is not empty.
592a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int SetCropWindow(VP8Io* const io, int y_start, int y_end,
5938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                         uint8_t** const in_data, int pixel_stride) {
594a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(y_start < y_end);
595a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(io->crop_left < io->crop_right);
596a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_end > io->crop_bottom) {
597a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_end = io->crop_bottom;  // make sure we don't overflow on last row.
598a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
599a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_start < io->crop_top) {
600a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int delta = io->crop_top - y_start;
601a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_start = io->crop_top;
6028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    *in_data += delta * pixel_stride;
603a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
604a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_start >= y_end) return 0;  // Crop window is empty.
605a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  *in_data += io->crop_left * sizeof(uint32_t);
607a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
608a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_y = y_start - io->crop_top;
609a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_w = io->crop_right - io->crop_left;
610a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_h = y_end - y_start;
611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;  // Non-empty crop window.
612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
615a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetMetaIndex(
617a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const image, int xsize, int bits, int x, int y) {
618a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (bits == 0) return 0;
619a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return image[xsize * (y >> bits) + (x >> bits)];
620a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
621a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
622a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                   int x, int y) {
624a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
625a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                      hdr->huffman_subsample_bits_, x, y);
626a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(meta_index < hdr->num_htree_groups_);
627a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return hdr->htree_groups_ + meta_index;
628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
631a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main loop, with custom row-processing function
632a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
633a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   const uint32_t* const rows) {
637a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int n = dec->next_transform_;
638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int cache_pixs = dec->width_ * num_rows;
639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int start_row = dec->last_row_;
640a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int end_row = start_row + num_rows;
641a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* rows_in = rows;
642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const rows_out = dec->argb_cache_;
643a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Inverse transforms.
645a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // TODO: most transforms only need to operate on the cropped region only.
646a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
647a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (n-- > 0) {
648a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LTransform* const transform = &dec->transforms_[n];
649a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
650a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    rows_in = rows_out;
651a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
652a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
653a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6540406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special method for paletted alpha data.
6550406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows,
6560406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                        const uint8_t* const rows) {
6570406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int start_row = dec->last_row_;
6580406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int end_row = start_row + num_rows;
6590406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t* rows_in = rows;
6600406ce1417f76f2034833414dcecc9f56253640cVikas Arora  uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row;
6610406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LTransform* const transform = &dec->transforms_[0];
6620406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(dec->next_transform_ == 1);
6630406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
6640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in,
6650406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                      rows_out);
6660406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
6670406ce1417f76f2034833414dcecc9f56253640cVikas Arora
668a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Processes (transforms, scales & color-converts) the rows decoded after the
669a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// last call.
670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ProcessRows(VP8LDecoder* const dec, int row) {
6710406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
672a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_rows = row - dec->last_row_;
673a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
674a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (num_rows <= 0) return;  // Nothing to be done.
675a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ApplyInverseTransforms(dec, num_rows, rows);
676a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Emit output.
678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
679a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8Io* const io = dec->io_;
6808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
6818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int in_stride = io->width * sizeof(uint32_t);  // in unit of RGBA
6828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
683a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // Nothing to output (this time).
684a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    } else {
685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const WebPDecBuffer* const output = dec->output_;
686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (output->colorspace < MODE_YUV) {  // convert to RGBA
687a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const WebPRGBABuffer* const buf = &output->u.RGBA;
688a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
689a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const int num_rows_out = io->use_scaling ?
6908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
6918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                 rgba, buf->stride) :
692a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRows(output->colorspace, rows_data, in_stride,
693a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                     io->mb_w, io->mb_h, rgba, buf->stride);
694a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Update 'last_out_row_'.
695a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        dec->last_out_row_ += num_rows_out;
696a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {                              // convert to YUVA
697a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        dec->last_out_row_ = io->use_scaling ?
698a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
699a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
700a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(dec->last_out_row_ <= output->height);
702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
705a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Update 'last_row_'.
706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->last_row_ = row;
707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->last_row_ <= dec->height_);
708a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
709a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Row-processing for the special case when alpha data contains only one
7118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// transform (color indexing), and trivial non-green literals.
7128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int Is8bOptimizable(const VP8LMetadata* const hdr) {
7138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int i;
7148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (hdr->color_cache_size_ > 0) return 0;
7158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // When the Huffman tree contains only one symbol, we can skip the
7168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // call to ReadSymbol() for red/blue/alpha channels.
7178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  for (i = 0; i < hdr->num_htree_groups_; ++i) {
7188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_;
7198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[RED].num_nodes_ > 1) return 0;
7208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[BLUE].num_nodes_ > 1) return 0;
7218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[ALPHA].num_nodes_ > 1) return 0;
7228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
7238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
7240406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
725a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
7278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int num_rows = row - dec->last_row_;
7288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint8_t* const in =
7298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_;
7308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (num_rows > 0) {
7318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ApplyInverseTransformsAlpha(dec, num_rows, in);
7328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
7338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->last_row_ = dec->last_out_row_ = row;
7340406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
735a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
7378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           int width, int height, int last_row) {
7388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int ok = 1;
7398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int row = dec->last_pixel_ / width;
7408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int col = dec->last_pixel_ % width;
7418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LBitReader* const br = &dec->br_;
7428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
7438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
7448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int pos = dec->last_pixel_;         // current position
7458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int end = width * height;     // End of data
7468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int last = width * last_row;  // Last pixel to decode
7478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
7488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int mask = hdr->huffman_mask_;
7498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(htree_group != NULL);
750259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  assert(pos < end);
7518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(last_row <= height);
7528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(Is8bOptimizable(hdr));
7538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
7548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  while (!br->eos_ && pos < last) {
7558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int code;
7568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Only update when changing tile.
7578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if ((col & mask) == 0) {
7588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      htree_group = GetHtreeGroupForPos(hdr, col, row);
7598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
7608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LFillBitWindow(br);
7618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
7628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (code < NUM_LITERAL_CODES) {  // Literal
7638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      data[pos] = code;
7648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++pos;
7658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++col;
7668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (col >= width) {
7678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col = 0;
7688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
7698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          ExtractPalettedAlphaRows(dec, row);
7718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
7728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < len_code_limit) {  // Backward reference
7748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int dist_code, dist;
7758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length_sym = code - NUM_LITERAL_CODES;
7768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length = GetCopyLength(length_sym, br);
7778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
7788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
7798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist_code = GetCopyDistance(dist_symbol, br);
7808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist = PlaneCodeToDistance(width, dist_code);
7818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (pos >= dist && end - pos >= length) {
7828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        int i;
7838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist];
7848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      } else {
7858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ok = 0;
7868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        goto End;
7878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      pos += length;
7898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      col += length;
7908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (col >= width) {
7918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col -= width;
7928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
7938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          ExtractPalettedAlphaRows(dec, row);
7958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
7968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (pos < last && (col & mask)) {
7988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        htree_group = GetHtreeGroupForPos(hdr, col, row);
7998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else {  // Not reached
8018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ok = 0;
8028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto End;
8038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
8048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = !br->error_;
8058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) goto End;
8068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
8078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Process the remaining rows corresponding to last row-block.
8088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ExtractPalettedAlphaRows(dec, row);
8098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
8108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End:
8118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (br->error_ || !ok || (br->eos_ && pos < end)) {
8128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = 0;
8138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
8148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                            : VP8_STATUS_BITSTREAM_ERROR;
8158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
8168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = (int)pos;
8178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (pos == end) dec->state_ = READ_DATA;
8188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
8198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
820a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
821a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
8228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
8238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           int width, int height, int last_row,
8248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           ProcessRowsFunc process_func) {
8258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int ok = 1;
8268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int row = dec->last_pixel_ / width;
8278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int col = dec->last_pixel_ % width;
8288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LBitReader* const br = &dec->br_;
8298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
8308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
8318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* src = data + dec->last_pixel_;
8328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* last_cached = src;
8338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src_end = data + width * height;     // End of data
8348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src_last = data + width * last_row;  // Last pixel to decode
8358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
8368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
8378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LColorCache* const color_cache =
8388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
8398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int mask = hdr->huffman_mask_;
8408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(htree_group != NULL);
841259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  assert(src < src_end);
8428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(src_last <= src_end);
8438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
8448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  while (!br->eos_ && src < src_last) {
8458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int code;
8468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Only update when changing tile. Note we could use this test:
8478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
8488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // but that's actually slower and needs storing the previous col/row.
8498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if ((col & mask) == 0) {
8508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      htree_group = GetHtreeGroupForPos(hdr, col, row);
8518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
8528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LFillBitWindow(br);
8538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
8548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (code < NUM_LITERAL_CODES) {  // Literal
8558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int red, green, blue, alpha;
8568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      red = ReadSymbol(&htree_group->htrees_[RED], br);
8578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      green = code;
8588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
8598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
8608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
861af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora      *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue;
8628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    AdvanceByOne:
8638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++src;
8648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++col;
8658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (col >= width) {
8668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col = 0;
8678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
8688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
8698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          process_func(dec, row);
8708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
8718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (color_cache != NULL) {
8728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          while (last_cached < src) {
8738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            VP8LColorCacheInsert(color_cache, *last_cached++);
8748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          }
8758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
8768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < len_code_limit) {  // Backward reference
8788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int dist_code, dist;
8798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length_sym = code - NUM_LITERAL_CODES;
8808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length = GetCopyLength(length_sym, br);
8818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
8828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
8838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist_code = GetCopyDistance(dist_symbol, br);
8848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist = PlaneCodeToDistance(width, dist_code);
8858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
8868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ok = 0;
8878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        goto End;
8888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      } else {
8898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        int i;
8908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        for (i = 0; i < length; ++i) src[i] = src[i - dist];
8918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        src += length;
8928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      col += length;
8948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (col >= width) {
8958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col -= width;
8968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
8978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
8988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          process_func(dec, row);
8998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
9008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (src < src_last) {
9028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
9038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (color_cache != NULL) {
9048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          while (last_cached < src) {
9058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            VP8LColorCacheInsert(color_cache, *last_cached++);
9068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          }
9078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
9088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < color_cache_limit) {  // Color cache
9108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int key = code - len_code_limit;
9118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      assert(color_cache != NULL);
9128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (last_cached < src) {
9138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        VP8LColorCacheInsert(color_cache, *last_cached++);
9148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      *src = VP8LColorCacheLookup(color_cache, key);
9168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto AdvanceByOne;
9178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else {  // Not reached
9188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ok = 0;
9198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto End;
9208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
9218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = !br->error_;
9228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) goto End;
9238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
9248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Process the remaining rows corresponding to last row-block.
9258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (process_func != NULL) process_func(dec, row);
9260406ce1417f76f2034833414dcecc9f56253640cVikas Arora
9278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End:
9288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (br->error_ || !ok || (br->eos_ && src < src_end)) {
9298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = 0;
9308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
9318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                            : VP8_STATUS_BITSTREAM_ERROR;
9328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
9338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = (int)(src - data);
9348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (src == src_end) dec->state_ = READ_DATA;
9358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
9368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
9378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
9380406ce1417f76f2034833414dcecc9f56253640cVikas Arora
939a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
940a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LTransform
941a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
942a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearTransform(VP8LTransform* const transform) {
943af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(transform->data_);
944a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->data_ = NULL;
945a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
946a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
947a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// For security reason, we need to remap the color map to span
948a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// the total possible bundled values, and not just the num_colors.
949a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
950a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
951a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int final_num_colors = 1 << (8 >> transform->bits_);
952a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const new_color_map =
953a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
954a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                sizeof(*new_color_map));
955a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (new_color_map == NULL) {
956a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
957a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
958a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const data = (uint8_t*)transform->data_;
959a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const new_data = (uint8_t*)new_color_map;
960a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_color_map[0] = transform->data_[0];
961a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 4; i < 4 * num_colors; ++i) {
962a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // Equivalent to AddPixelEq(), on a byte-basis.
963a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
964a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
965a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (; i < 4 * final_num_colors; ++i)
966a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      new_data[i] = 0;  // black tail.
967af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPSafeFree(transform->data_);
968a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    transform->data_ = new_color_map;
969a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
970a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
971a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
972a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
973a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadTransform(int* const xsize, int const* ysize,
974a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                         VP8LDecoder* const dec) {
975a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 1;
976a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
977a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
978a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const VP8LImageTransformType type =
979a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      (VP8LImageTransformType)VP8LReadBits(br, 2);
980a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
981a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Each transform type can only be present once in the stream.
982a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec->transforms_seen_ & (1U << type)) {
983a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;  // Already there, let's not accept the second same transform.
984a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
985a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->transforms_seen_ |= (1U << type);
986a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
987a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->type_ = type;
988a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->xsize_ = *xsize;
989a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->ysize_ = *ysize;
990a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->data_ = NULL;
991a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ++dec->next_transform_;
992a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->next_transform_ <= NUM_TRANSFORMS);
993a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
994a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  switch (type) {
995a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case PREDICTOR_TRANSFORM:
996a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case CROSS_COLOR_TRANSFORM:
997a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      transform->bits_ = VP8LReadBits(br, 3) + 2;
998a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
999a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                               transform->bits_),
1000a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             VP8LSubSampleSize(transform->ysize_,
1001a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                               transform->bits_),
1002a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             0, dec, &transform->data_);
1003a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1004a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case COLOR_INDEXING_TRANSFORM: {
1005a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       const int num_colors = VP8LReadBits(br, 8) + 1;
1006a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       const int bits = (num_colors > 16) ? 0
1007a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : (num_colors > 4) ? 1
1008a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : (num_colors > 2) ? 2
1009a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : 3;
1010a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       *xsize = VP8LSubSampleSize(transform->xsize_, bits);
1011a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       transform->bits_ = bits;
1012a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
1013a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       ok = ok && ExpandColorMap(num_colors, transform);
1014a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1015a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1016a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case SUBTRACT_GREEN:
1017a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1018a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    default:
1019a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(0);    // can't happen
1020a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1021a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1022a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1023a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
1024a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1025a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1026a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
1027a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LMetadata
1028a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1029a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void InitMetadata(VP8LMetadata* const hdr) {
1030a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(hdr);
1031a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memset(hdr, 0, sizeof(*hdr));
1032a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1033a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1034a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearMetadata(VP8LMetadata* const hdr) {
1035a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(hdr);
1036a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1037af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(hdr->huffman_image_);
1038af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_);
1039a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LColorCacheClear(&hdr->color_cache_);
1040a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  InitMetadata(hdr);
1041a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1042a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1043a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
1044a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LDecoder
1045a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1046a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8LDecoder* VP8LNew(void) {
1047af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
1048a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return NULL;
1049a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1050a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DIM;
1051a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->state_ = READ_DIM;
10528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
10538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDspInit();  // Init critical function pointers.
10548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1055a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return dec;
1056a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1057a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1058a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LClear(VP8LDecoder* const dec) {
1059a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
1060a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return;
1061a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ClearMetadata(&dec->hdr_);
1062a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1063af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(dec->pixels_);
10640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  dec->pixels_ = NULL;
1065a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 0; i < dec->next_transform_; ++i) {
1066a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ClearTransform(&dec->transforms_[i]);
1067a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1068a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->next_transform_ = 0;
1069a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->transforms_seen_ = 0;
1070a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1071af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  WebPSafeFree(dec->rescaler_memory);
1072a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler_memory = NULL;
1073a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1074a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->output_ = NULL;   // leave no trace behind
1075a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1076a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1077a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LDelete(VP8LDecoder* const dec) {
1078a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec != NULL) {
1079a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LClear(dec);
1080af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPSafeFree(dec);
1081a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1082a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1083a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1084a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
1085a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
1086a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_bits = hdr->huffman_subsample_bits_;
1087a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->width_ = width;
1088a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->height_ = height;
1089a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1090a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
1091a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
1092a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1093a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1094a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize,
1095a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             int is_level0,
1096a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             VP8LDecoder* const dec,
1097a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             uint32_t** const decoded_data) {
1098a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 1;
1099a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int transform_xsize = xsize;
1100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int transform_ysize = ysize;
1101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
1102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
1103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* data = NULL;
1104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int color_cache_bits = 0;
1105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Read the transforms (may recurse).
1107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (is_level0) {
1108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    while (ok && VP8LReadBits(br, 1)) {
1109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
1110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Color cache
1114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (ok && VP8LReadBits(br, 1)) {
1115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    color_cache_bits = VP8LReadBits(br, 4);
1116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
1117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!ok) {
1118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Read the Huffman codes (may recurse).
1124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
1125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                              color_cache_bits, is_level0);
1126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
1127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto End;
1129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Finish setting up the color-cache
1132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (color_cache_bits > 0) {
1133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->color_cache_size_ = 1 << color_cache_bits;
1134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
1135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = 0;
1137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->color_cache_size_ = 0;
1141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  UpdateDecoder(dec, transform_xsize, transform_ysize);
1143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (is_level0) {   // level 0 complete
1145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->state_ = READ_HDR;
1146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto End;
1147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
1150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
1151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
1152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (data == NULL) {
1153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = 0;
1155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1159a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Use the Huffman trees to decode the LZ77 encoded data.
11608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
11618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       transform_ysize, NULL);
1162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && !br->error_;
1163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End:
1165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
1167af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPSafeFree(data);
1168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ClearMetadata(hdr);
1169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
1170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // status appropriately.
1171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
1172a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_SUSPENDED;
1173a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1175a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (decoded_data != NULL) {
1176a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      *decoded_data = data;
1177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    } else {
1178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // We allocate image data in this function only for transforms. At level 0
1179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // (that is: not the transforms), we shouldn't have allocated anything.
1180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(data == NULL);
1181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(is_level0);
1182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
11838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = 0;  // Reset for future DECODE_DATA_FUNC() calls.
1184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!is_level0) ClearMetadata(hdr);  // Clean up temporary data behind.
1185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
1187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
11900406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
11918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
1192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
1193a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Scratch buffer corresponding to top-prediction row for transforming the
11940406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // first row in the row-blocks. Not needed for paletted alpha.
11958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t cache_top_pixels = (uint16_t)final_width;
11960406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
11978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
1198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t total_num_pixels =
1199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      num_pixels + cache_top_pixels + cache_pixels;
1200a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->width_ <= final_width);
12028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
12030406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (dec->pixels_ == NULL) {
1204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->argb_cache_ = NULL;    // for sanity check
1205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
1207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
12088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
12098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
12108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
12118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
12128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
12138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
12148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->argb_cache_ = NULL;    // for sanity check
12158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
12168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->pixels_ == NULL) {
12178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
12188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    return 0;
12198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1220a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1221a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12250406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special row-processing that only stores the alpha data.
1226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
1227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_rows = row - dec->last_row_;
12280406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
1229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (num_rows <= 0) return;  // Nothing to be done.
1231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ApplyInverseTransforms(dec, num_rows, in);
1232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Extract alpha (which is stored in the green plane).
1234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
1235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int width = dec->io_->width;      // the final width (!= dec->width_)
1236a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int cache_pixs = width * num_rows;
1237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
1238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const src = dec->argb_cache_;
1239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
1240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
1241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
12420406ce1417f76f2034833414dcecc9f56253640cVikas Arora  dec->last_row_ = dec->last_out_row_ = row;
12430406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12458b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
12468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                          const uint8_t* const data, size_t data_size,
12478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                          uint8_t* const output) {
1248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
12498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDecoder* dec;
12508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8Io* io;
12518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(alph_dec != NULL);
12528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  alph_dec->vp8l_dec_ = VP8LNew();
12538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (alph_dec->vp8l_dec_ == NULL) return 0;
12548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec = alph_dec->vp8l_dec_;
12558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
12568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->width_ = alph_dec->width_;
12578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->height_ = alph_dec->height_;
12588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->io_ = &alph_dec->io_;
12598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io = dec->io_;
1260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8InitIo(io);
12628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  WebPInitCustomIo(NULL, io);  // Just a sanity Init. io won't be used.
12638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->opaque = output;
12648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->width = alph_dec->width_;
12658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->height = alph_dec->height_;
1266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LInitBitReader(&dec->br_, data, data_size);
1269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_HDR;
12718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
12728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    goto Err;
12738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12750406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // Special case: if alpha data uses only the color indexing transform and
12760406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
12770406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // method that only needs allocation of 1 byte per pixel (alpha channel).
12780406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (dec->next_transform_ == 1 &&
12790406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
12808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      Is8bOptimizable(&dec->hdr_)) {
12818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    alph_dec->use_8b_decode = 1;
12828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = AllocateInternalBuffers8b(dec);
12838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
12848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Allocate internal buffers (note that dec->width_ may have changed here).
12858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    alph_dec->use_8b_decode = 0;
12868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
12870406ce1417f76f2034833414dcecc9f56253640cVikas Arora  }
12880406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!ok) goto Err;
1290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DATA;
12928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
1293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err:
12958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDelete(alph_dec->vp8l_dec_);
12968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  alph_dec->vp8l_dec_ = NULL;
12978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 0;
12988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
12998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
13008b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
13018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDecoder* const dec = alph_dec->vp8l_dec_;
13028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(dec != NULL);
13038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(dec->action_ == READ_DATA);
13048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(last_row <= dec->height_);
13058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1306259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  if (dec->last_pixel_ == dec->width_ * dec->height_) {
1307259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi    return 1;  // done
1308259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  }
1309259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi
13108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Decode (with special row processing).
13118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return alph_dec->use_8b_decode ?
13128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
13138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                      last_row) :
13148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                      last_row, ExtractAlphaRows);
1316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1320a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
1321a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int width, height, has_alpha;
1322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return 0;
1324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (io == NULL) {
1325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_INVALID_PARAM;
1326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
1327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->io_ = io;
1330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LInitBitReader(&dec->br_, io->data, io->data_size);
1332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
1333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Error;
1335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->state_ = READ_DIM;
1337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->width = width;
1338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->height = height;
1339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_HDR;
1341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
1342a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1344a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error:
13450406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LClear(dec);
13460406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(dec->status_ != VP8_STATUS_OK);
13470406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return 0;
1348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeImage(VP8LDecoder* const dec) {
1351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8Io* io = NULL;
1352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPDecParams* params = NULL;
1353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Sanity checks.
1355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return 0;
1356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io = dec->io_;
1358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(io != NULL);
1359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  params = (WebPDecParams*)io->opaque;
1360a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(params != NULL);
1361a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->output_ = params->output;
1362a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->output_ != NULL);
1363a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Initialization.
1365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
1366a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_INVALID_PARAM;
1367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Err;
1368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
13708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
1371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
1373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1374af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
1375af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    // need the alpha-multiply functions for premultiplied output or rescaling
1376af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora    WebPInitAlphaProcessing();
1377af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora  }
1378af51b94a435132e9014c324e25fb686b3d07a8c8Vikas Arora
1379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Decode.
1380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DATA;
13810406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       dec->height_, ProcessRows)) {
1383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Err;
1384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Cleanup.
1387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  params->last_y = dec->last_out_row_;
1388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LClear(dec);
1389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err:
1392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LClear(dec);
1393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->status_ != VP8_STATUS_OK);
1394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 0;
1395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1398