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"
1933f74dabbc7920a65ed435d7417987589febdc16Vikas 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;
19033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 };
191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
19233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
19333f74dabbc7920a65ed435d7417987589febdc16Vikas 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:
23633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHuffmanTreeFree(&tree);
2378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora  if (!ok) dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
24133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
24233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// tree.
243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
24433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                           int* const code_lengths, int* const huff_codes,
245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                           HuffmanTree* const tree) {
246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int simple_code = VP8LReadBits(br, 1);
249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (simple_code) {  // Read symbols, codes & code lengths directly.
251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int symbols[2];
252a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int codes[2];
253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int num_symbols = VP8LReadBits(br, 1) + 1;
254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int first_symbol_len_code = VP8LReadBits(br, 1);
255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // The first code is either 1 bit or 8 bit code.
256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    codes[0] = 0;
258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    code_lengths[0] = num_symbols - 1;
259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // The second code (if present), is always 8 bit long.
260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (num_symbols == 2) {
261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      symbols[1] = VP8LReadBits(br, 8);
262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      codes[1] = 1;
263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      code_lengths[1] = num_symbols - 1;
264a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
26533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
26633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                      alphabet_size, num_symbols);
267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {  // Decode Huffman-coded code lengths.
268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int num_codes = VP8LReadBits(br, 4) + 4;
271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (num_codes > NUM_CODE_LENGTH_CODES) {
272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      return 0;
274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
275a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
27633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < num_codes; ++i) {
279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                code_lengths);
28333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    ok = ok && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes,
28433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            alphabet_size);
285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && !br->error_;
287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                            int color_cache_bits, int allow_recursion) {
296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i, j;
297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* huffman_image = NULL;
300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  HTreeGroup* htree_groups = NULL;
301a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_htree_groups = 1;
30233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int max_alphabet_size = 0;
30333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int* code_lengths = NULL;
30433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int* huff_codes = NULL;
305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (allow_recursion && VP8LReadBits(br, 1)) {
307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // use meta Huffman codes.
308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_precision = VP8LReadBits(br, 3) + 2;
309a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int huffman_pixs = huffman_xsize * huffman_ysize;
312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                           &huffman_image)) {
314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto Error;
316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->huffman_subsample_bits_ = huffman_precision;
318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < huffman_pixs; ++i) {
319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // The huffman data is stored in red and green bytes.
3201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      const int group = (huffman_image[i] >> 8) & 0xffff;
3211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      huffman_image[i] = group;
3221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      if (group >= num_htree_groups) {
3231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora        num_htree_groups = group + 1;
324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (br->error_) goto Error;
329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
33033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // Find maximum alphabet size for the htree group.
33133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
33233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int alphabet_size = kAlphabetSize[j];
33333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (j == 0 && color_cache_bits > 0) {
33433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      alphabet_size += 1 << color_cache_bits;
33533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
33633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (max_alphabet_size < alphabet_size) {
33733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      max_alphabet_size = alphabet_size;
33833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
33933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
34033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
34133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
34233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  code_lengths =
34333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
34433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  huff_codes =
34533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes));
34633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
34733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) {
348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Error;
350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 0; i < num_htree_groups; ++i) {
353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    HuffmanTree* const htrees = htree_groups[i].htrees_;
354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int alphabet_size = kAlphabetSize[j];
35633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      HuffmanTree* const htree = htrees + j;
357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (j == 0 && color_cache_bits > 0) {
358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        alphabet_size += 1 << color_cache_bits;
359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
36033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes,
36133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                           htree)) {
36233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        goto Error;
36333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      }
364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
36633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(huff_codes);
36733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(code_lengths);
368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // All OK. Finalize pointers and return.
370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_image_ = huffman_image;
371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->num_htree_groups_ = num_htree_groups;
372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->htree_groups_ = htree_groups;
373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
375a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error:
37633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(huff_codes);
37733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(code_lengths);
37833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(huffman_image);
37933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHtreeGroupsFree(htree_groups, num_htree_groups);
380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 0;
381a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Scaling.
385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_channels = 4;
388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int in_width = io->mb_w;
389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int out_width = io->scaled_width;
390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int in_height = io->mb_h;
391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int out_height = io->scaled_height;
392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int32_t* work;        // Rescaler work area.
394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* scaled_data;  // Temporary storage for scaled BGRA data.
396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t memory_size = sizeof(*dec->rescaler) +
397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                               work_size * sizeof(*work) +
398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                               scaled_data_size * sizeof(*scaled_data);
399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (memory == NULL) {
401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->rescaler_memory == NULL);
405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler_memory = memory;
406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler = (WebPRescaler*)memory;
408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memory += sizeof(*dec->rescaler);
409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  work = (int32_t*)memory;
410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memory += work_size * sizeof(*work);
411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  scaled_data = (uint32_t*)memory;
412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                   out_width, out_height, 0, num_channels,
415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                   in_width, out_width, in_height, out_height, work);
416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to ARGB
421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// We have special "export" function since we need to convert from BGRA
423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
424a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                  int rgba_stride, uint8_t* const rgba) {
4258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src = (uint32_t*)rescaler->dst;
426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int dst_width = rescaler->dst_width;
427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
428a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (WebPRescalerHasPendingOutput(rescaler)) {
429a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const dst = rgba + num_lines_out * rgba_stride;
43033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPRescalerExportRow(rescaler, 0);
4318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRow(src, dst_width, 1);
432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++num_lines_out;
434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit scaled rows.
4398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
4408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* in, int in_stride, int mb_h,
4418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* const out, int out_stride) {
442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_in = 0;
444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
445a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_lines_in < mb_h) {
4468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    uint8_t* const row_in = in + num_lines_in * in_stride;
447a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const row_out = out + num_lines_out * out_stride;
4488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int lines_left = mb_h - num_lines_in;
4498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
4508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    assert(needed_lines > 0 && needed_lines <= lines_left);
4518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRows(row_in, in_stride,
4528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                     dec->rescaler->src_width, needed_lines, 0);
4538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
4548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    num_lines_in += needed_lines;
455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Emit rows without any scaling.
461a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRows(WEBP_CSP_MODE colorspace,
4628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                    const uint8_t* row_in, int in_stride,
463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                    int mb_w, int mb_h,
464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                    uint8_t* const out, int out_stride) {
465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int lines = mb_h;
466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint8_t* row_out = out;
467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (lines-- > 0) {
468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    row_in += in_stride;
470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    row_out += out_stride;
471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return mb_h;  // Num rows out == num rows in.
473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Export to YUVA
477a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
47833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// TODO(skal): should be in yuv.c
479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                          const WebPDecBuffer* const output) {
481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const WebPYUVABuffer* const buf = &output->u.YUVA;
482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // first, the luma plane
483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const y = buf->y + y_pos * buf->y_stride;
486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < width; ++i) {
487a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t p = src[i];
4888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
4898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       YUV_HALF);
490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // then U/V planes
494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int uv_width = width >> 1;
498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < uv_width; ++i) {
500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v0 = src[2 * i + 0];
501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v1 = src[2 * i + 1];
502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // VP8RGBToU/V expects four accumulated pixels. Hence we need to
503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int g = ((v0 >>  7) & 0x1fe) + ((v1 >>  7) & 0x1fe);
506a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int b = ((v0 <<  1) & 0x1fe) + ((v1 <<  1) & 0x1fe);
507a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (!(y_pos & 1)) {  // even lines: store values
5088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
510a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {             // odd lines: average with previous values
5118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Approximated average-of-four. But it's an acceptable diff.
514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        u[i] = (u[i] + tmp_u + 1) >> 1;
515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        v[i] = (v[i] + tmp_v + 1) >> 1;
516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (width & 1) {       // last pixel
519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t v0 = src[2 * i + 0];
520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int r = (v0 >> 14) & 0x3fc;
521a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int g = (v0 >>  6) & 0x3fc;
522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int b = (v0 <<  2) & 0x3fc;
523a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (!(y_pos & 1)) {  // even lines
5248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
526a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {             // odd lines (note: we could just skip this)
5278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        u[i] = (u[i] + tmp_u + 1) >> 1;
530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        v[i] = (v[i] + tmp_v + 1) >> 1;
531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
532a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
533a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
534a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Lastly, store alpha if needed.
535a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (buf->a != NULL) {
536a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const a = buf->a + y_pos * buf->a_stride;
538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
540a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
541a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
542a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
543a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPRescaler* const rescaler = dec->rescaler;
5448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src = (uint32_t*)rescaler->dst;
545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int dst_width = rescaler->dst_width;
546a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_out = 0;
547a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (WebPRescalerHasPendingOutput(rescaler)) {
54833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPRescalerExportRow(rescaler, 0);
5498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRow(src, dst_width, 1);
550a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ConvertToYUVA(src, dst_width, y_pos, dec->output_);
551a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y_pos;
552a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++num_lines_out;
553a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
554a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return num_lines_out;
555a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
556a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
557a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
5588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                uint8_t* in, int in_stride, int mb_h) {
559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int num_lines_in = 0;
560a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y_pos = dec->last_out_row_;
561a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_lines_in < mb_h) {
5628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int lines_left = mb_h - num_lines_in;
5638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
5648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
5658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
5668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    num_lines_in += needed_lines;
5678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    in += needed_lines * in_stride;
568a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_pos += ExportYUVA(dec, y_pos);
569a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
570a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return y_pos;
571a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
572a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
573a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int EmitRowsYUVA(const VP8LDecoder* const dec,
5748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                        const uint8_t* in, int in_stride,
575a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                        int mb_w, int num_rows) {
576a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y_pos = dec->last_out_row_;
577a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (num_rows-- > 0) {
5788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
5798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    in += in_stride;
580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y_pos;
581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return y_pos;
583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Cropping.
587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
588a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
589a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// crop options. Also updates the input data pointer, so that it points to the
5908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// start of the cropped window. Note that pixels are in ARGB format even if
5918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 'in_data' is uint8_t*.
592a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Returns true if the crop window is not empty.
593a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int SetCropWindow(VP8Io* const io, int y_start, int y_end,
5948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                         uint8_t** const in_data, int pixel_stride) {
595a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(y_start < y_end);
596a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(io->crop_left < io->crop_right);
597a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_end > io->crop_bottom) {
598a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_end = io->crop_bottom;  // make sure we don't overflow on last row.
599a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
600a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_start < io->crop_top) {
601a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int delta = io->crop_top - y_start;
602a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    y_start = io->crop_top;
6038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    *in_data += delta * pixel_stride;
604a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
605a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_start >= y_end) return 0;  // Crop window is empty.
606a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  *in_data += io->crop_left * sizeof(uint32_t);
608a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
609a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_y = y_start - io->crop_top;
610a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_w = io->crop_right - io->crop_left;
611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->mb_h = y_end - y_start;
612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;  // Non-empty crop window.
613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
615a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
617a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int GetMetaIndex(
618a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const image, int xsize, int bits, int x, int y) {
619a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (bits == 0) return 0;
620a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return image[xsize * (y >> bits) + (x >> bits)];
621a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
622a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
624a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                   int x, int y) {
625a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
626a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                      hdr->huffman_subsample_bits_, x, y);
627a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(meta_index < hdr->num_htree_groups_);
628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return hdr->htree_groups_ + meta_index;
629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
631a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
632a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main loop, with custom row-processing function
633a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
637a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   const uint32_t* const rows) {
638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int n = dec->next_transform_;
639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int cache_pixs = dec->width_ * num_rows;
640a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int start_row = dec->last_row_;
641a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int end_row = start_row + num_rows;
642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* rows_in = rows;
643a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const rows_out = dec->argb_cache_;
644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
645a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Inverse transforms.
646a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // TODO: most transforms only need to operate on the cropped region only.
647a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
648a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (n-- > 0) {
649a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LTransform* const transform = &dec->transforms_[n];
650a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
651a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    rows_in = rows_out;
652a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
653a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
654a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6550406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special method for paletted alpha data.
6560406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows,
6570406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                        const uint8_t* const rows) {
6580406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int start_row = dec->last_row_;
6590406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int end_row = start_row + num_rows;
6600406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t* rows_in = rows;
6610406ce1417f76f2034833414dcecc9f56253640cVikas Arora  uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row;
6620406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LTransform* const transform = &dec->transforms_[0];
6630406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(dec->next_transform_ == 1);
6640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
6650406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in,
6660406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                      rows_out);
6670406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
6680406ce1417f76f2034833414dcecc9f56253640cVikas Arora
669a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Processes (transforms, scales & color-converts) the rows decoded after the
670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// last call.
671a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ProcessRows(VP8LDecoder* const dec, int row) {
6720406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
673a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_rows = row - dec->last_row_;
674a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
675a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (num_rows <= 0) return;  // Nothing to be done.
676a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ApplyInverseTransforms(dec, num_rows, rows);
677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Emit output.
679a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
680a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8Io* const io = dec->io_;
6818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
6828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const int in_stride = io->width * sizeof(uint32_t);  // in unit of RGBA
6838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
684a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // Nothing to output (this time).
685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    } else {
686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const WebPDecBuffer* const output = dec->output_;
687a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (output->colorspace < MODE_YUV) {  // convert to RGBA
688a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const WebPRGBABuffer* const buf = &output->u.RGBA;
689a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
690a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const int num_rows_out = io->use_scaling ?
6918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
6928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                                 rgba, buf->stride) :
693a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRows(output->colorspace, rows_data, in_stride,
694a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                     io->mb_w, io->mb_h, rgba, buf->stride);
695a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Update 'last_out_row_'.
696a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        dec->last_out_row_ += num_rows_out;
697a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {                              // convert to YUVA
698a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        dec->last_out_row_ = io->use_scaling ?
699a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
700a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(dec->last_out_row_ <= output->height);
703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
705a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Update 'last_row_'.
707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->last_row_ = row;
708a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->last_row_ <= dec->height_);
709a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
710a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Row-processing for the special case when alpha data contains only one
7128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// transform (color indexing), and trivial non-green literals.
7138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int Is8bOptimizable(const VP8LMetadata* const hdr) {
7148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int i;
7158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (hdr->color_cache_size_ > 0) return 0;
7168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // When the Huffman tree contains only one symbol, we can skip the
7178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // call to ReadSymbol() for red/blue/alpha channels.
7188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  for (i = 0; i < hdr->num_htree_groups_; ++i) {
7198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_;
7208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[RED].num_nodes_ > 1) return 0;
7218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[BLUE].num_nodes_ > 1) return 0;
7228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (htrees[ALPHA].num_nodes_ > 1) return 0;
7238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
7248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
7250406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
726a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
7288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int num_rows = row - dec->last_row_;
7298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint8_t* const in =
7308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_;
7318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (num_rows > 0) {
7328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ApplyInverseTransformsAlpha(dec, num_rows, in);
7338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
7348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->last_row_ = dec->last_out_row_ = row;
7350406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
736a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
7378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
7388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           int width, int height, int last_row) {
7398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int ok = 1;
7408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int row = dec->last_pixel_ / width;
7418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int col = dec->last_pixel_ % width;
7428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LBitReader* const br = &dec->br_;
7438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
7448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
7458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int pos = dec->last_pixel_;         // current position
7468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int end = width * height;     // End of data
7478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int last = width * last_row;  // Last pixel to decode
7488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
7498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int mask = hdr->huffman_mask_;
7508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(htree_group != NULL);
751259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  assert(pos < end);
7528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(last_row <= height);
7538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(Is8bOptimizable(hdr));
7548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
7558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  while (!br->eos_ && pos < last) {
7568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int code;
7578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Only update when changing tile.
7588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if ((col & mask) == 0) {
7598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      htree_group = GetHtreeGroupForPos(hdr, col, row);
7608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
7618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LFillBitWindow(br);
7628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
7638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (code < NUM_LITERAL_CODES) {  // Literal
7648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      data[pos] = code;
7658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++pos;
7668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++col;
7678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (col >= width) {
7688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col = 0;
7698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
7708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          ExtractPalettedAlphaRows(dec, row);
7728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
7738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < len_code_limit) {  // Backward reference
7758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int dist_code, dist;
7768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length_sym = code - NUM_LITERAL_CODES;
7778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length = GetCopyLength(length_sym, br);
7788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
7798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
7808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist_code = GetCopyDistance(dist_symbol, br);
7818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist = PlaneCodeToDistance(width, dist_code);
7828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (pos >= dist && end - pos >= length) {
7838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        int i;
7848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist];
7858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      } else {
7868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ok = 0;
7878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        goto End;
7888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      pos += length;
7908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      col += length;
7918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (col >= width) {
7928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col -= width;
7938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
7948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          ExtractPalettedAlphaRows(dec, row);
7968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
7978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
7988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (pos < last && (col & mask)) {
7998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        htree_group = GetHtreeGroupForPos(hdr, col, row);
8008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else {  // Not reached
8028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ok = 0;
8038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto End;
8048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
8058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora    assert(br->eos_ == VP8LIsEndOfStream(br));
8068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = !br->error_;
8078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) goto End;
8088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
8098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Process the remaining rows corresponding to last row-block.
8108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ExtractPalettedAlphaRows(dec, row);
8118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
8128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End:
8138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (br->error_ || !ok || (br->eos_ && pos < end)) {
8148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = 0;
8158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
8168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                            : VP8_STATUS_BITSTREAM_ERROR;
8178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
8188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = (int)pos;
8198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (pos == end) dec->state_ = READ_DATA;
8208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
8218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
822a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
823a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
8248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
8258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           int width, int height, int last_row,
8268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                           ProcessRowsFunc process_func) {
8278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int ok = 1;
8288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int row = dec->last_pixel_ / width;
8298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  int col = dec->last_pixel_ % width;
8308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LBitReader* const br = &dec->br_;
8318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
8328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
8338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* src = data + dec->last_pixel_;
8348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* last_cached = src;
8358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src_end = data + width * height;     // End of data
8368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  uint32_t* const src_last = data + width * last_row;  // Last pixel to decode
8378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
8388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
8398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LColorCache* const color_cache =
8408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
8418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int mask = hdr->huffman_mask_;
8428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(htree_group != NULL);
843259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  assert(src < src_end);
8448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(src_last <= src_end);
8458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
8468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  while (!br->eos_ && src < src_last) {
8478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    int code;
8488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Only update when changing tile. Note we could use this test:
8498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
8508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // but that's actually slower and needs storing the previous col/row.
8518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if ((col & mask) == 0) {
8528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      htree_group = GetHtreeGroupForPos(hdr, col, row);
8538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
8548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    VP8LFillBitWindow(br);
8558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
8568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (code < NUM_LITERAL_CODES) {  // Literal
8578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int red, green, blue, alpha;
8588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      red = ReadSymbol(&htree_group->htrees_[RED], br);
8598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      green = code;
8608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
8618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
8628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
86333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue;
8648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    AdvanceByOne:
8658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++src;
8668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ++col;
8678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (col >= width) {
8688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col = 0;
8698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
8708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
8718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          process_func(dec, row);
8728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
8738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (color_cache != NULL) {
8748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          while (last_cached < src) {
8758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            VP8LColorCacheInsert(color_cache, *last_cached++);
8768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          }
8778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
8788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < len_code_limit) {  // Backward reference
8808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      int dist_code, dist;
8818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length_sym = code - NUM_LITERAL_CODES;
8828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int length = GetCopyLength(length_sym, br);
8838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
8848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LFillBitWindow(br);
8858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist_code = GetCopyDistance(dist_symbol, br);
8868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      dist = PlaneCodeToDistance(width, dist_code);
8878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
8888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ok = 0;
8898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        goto End;
8908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      } else {
8918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        int i;
8928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        for (i = 0; i < length; ++i) src[i] = src[i - dist];
8938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        src += length;
8948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
8958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      col += length;
8968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (col >= width) {
8978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        col -= width;
8988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        ++row;
8998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
9008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          process_func(dec, row);
9018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
9028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora      if (src < src_end) {
9048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
9058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        if (color_cache != NULL) {
9068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          while (last_cached < src) {
9078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora            VP8LColorCacheInsert(color_cache, *last_cached++);
9088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora          }
9098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        }
9108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else if (code < color_cache_limit) {  // Color cache
9128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      const int key = code - len_code_limit;
9138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      assert(color_cache != NULL);
9148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      while (last_cached < src) {
9158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        VP8LColorCacheInsert(color_cache, *last_cached++);
9168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      }
9178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      *src = VP8LColorCacheLookup(color_cache, key);
9188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto AdvanceByOne;
9198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    } else {  // Not reached
9208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      ok = 0;
9218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      goto End;
9228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
9238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora    assert(br->eos_ == VP8LIsEndOfStream(br));
9248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = !br->error_;
9258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (!ok) goto End;
9268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
9278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Process the remaining rows corresponding to last row-block.
9288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (process_func != NULL) process_func(dec, row);
9290406ce1417f76f2034833414dcecc9f56253640cVikas Arora
9308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora End:
9318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (br->error_ || !ok || (br->eos_ && src < src_end)) {
9328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = 0;
9338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
9348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                            : VP8_STATUS_BITSTREAM_ERROR;
9358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
9368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = (int)(src - data);
9378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (src == src_end) dec->state_ = READ_DATA;
9388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
9398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return ok;
9408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
9410406ce1417f76f2034833414dcecc9f56253640cVikas Arora
942a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
943a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LTransform
944a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
945a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearTransform(VP8LTransform* const transform) {
94633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(transform->data_);
947a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->data_ = NULL;
948a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
949a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
950a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// For security reason, we need to remap the color map to span
951a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// the total possible bundled values, and not just the num_colors.
952a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
953a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
954a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int final_num_colors = 1 << (8 >> transform->bits_);
955a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const new_color_map =
956a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
957a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                sizeof(*new_color_map));
958a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (new_color_map == NULL) {
959a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
960a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
961a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const data = (uint8_t*)transform->data_;
962a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const new_data = (uint8_t*)new_color_map;
963a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_color_map[0] = transform->data_[0];
964a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 4; i < 4 * num_colors; ++i) {
965a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // Equivalent to AddPixelEq(), on a byte-basis.
966a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
967a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
968a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (; i < 4 * final_num_colors; ++i)
969a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      new_data[i] = 0;  // black tail.
97033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(transform->data_);
971a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    transform->data_ = new_color_map;
972a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
973a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
974a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
975a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
976a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ReadTransform(int* const xsize, int const* ysize,
977a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                         VP8LDecoder* const dec) {
978a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 1;
979a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
980a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
981a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const VP8LImageTransformType type =
982a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      (VP8LImageTransformType)VP8LReadBits(br, 2);
983a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
984a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Each transform type can only be present once in the stream.
985a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec->transforms_seen_ & (1U << type)) {
986a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;  // Already there, let's not accept the second same transform.
987a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
988a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->transforms_seen_ |= (1U << type);
989a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
990a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->type_ = type;
991a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->xsize_ = *xsize;
992a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->ysize_ = *ysize;
993a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  transform->data_ = NULL;
994a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ++dec->next_transform_;
995a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->next_transform_ <= NUM_TRANSFORMS);
996a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
997a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  switch (type) {
998a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case PREDICTOR_TRANSFORM:
999a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case CROSS_COLOR_TRANSFORM:
1000a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      transform->bits_ = VP8LReadBits(br, 3) + 2;
1001a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
1002a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                               transform->bits_),
1003a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             VP8LSubSampleSize(transform->ysize_,
1004a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                               transform->bits_),
1005a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             0, dec, &transform->data_);
1006a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1007a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case COLOR_INDEXING_TRANSFORM: {
1008a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       const int num_colors = VP8LReadBits(br, 8) + 1;
1009a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       const int bits = (num_colors > 16) ? 0
1010a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : (num_colors > 4) ? 1
1011a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : (num_colors > 2) ? 2
1012a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                      : 3;
1013a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       *xsize = VP8LSubSampleSize(transform->xsize_, bits);
1014a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       transform->bits_ = bits;
1015a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
1016a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora       ok = ok && ExpandColorMap(num_colors, transform);
1017a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1018a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1019a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case SUBTRACT_GREEN:
1020a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1021a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    default:
1022a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(0);    // can't happen
1023a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1024a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1025a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1026a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
1027a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1028a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1029a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
1030a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LMetadata
1031a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1032a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void InitMetadata(VP8LMetadata* const hdr) {
1033a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(hdr);
1034a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memset(hdr, 0, sizeof(*hdr));
1035a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1036a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1037a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ClearMetadata(VP8LMetadata* const hdr) {
1038a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(hdr);
1039a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
104033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(hdr->huffman_image_);
104133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_);
1042a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LColorCacheClear(&hdr->color_cache_);
1043a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  InitMetadata(hdr);
1044a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1045a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1046a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
1047a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// VP8LDecoder
1048a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1049a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8LDecoder* VP8LNew(void) {
105033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
1051a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return NULL;
1052a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1053a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DIM;
1054a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->state_ = READ_DIM;
10558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
10568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDspInit();  // Init critical function pointers.
10578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1058a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return dec;
1059a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1060a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1061a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LClear(VP8LDecoder* const dec) {
1062a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
1063a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return;
1064a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ClearMetadata(&dec->hdr_);
1065a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
106633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(dec->pixels_);
10670406ce1417f76f2034833414dcecc9f56253640cVikas Arora  dec->pixels_ = NULL;
1068a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 0; i < dec->next_transform_; ++i) {
1069a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ClearTransform(&dec->transforms_[i]);
1070a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1071a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->next_transform_ = 0;
1072a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->transforms_seen_ = 0;
1073a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
107433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(dec->rescaler_memory);
1075a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->rescaler_memory = NULL;
1076a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1077a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->output_ = NULL;   // leave no trace behind
1078a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1079a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1080a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LDelete(VP8LDecoder* const dec) {
1081a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec != NULL) {
1082a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    VP8LClear(dec);
108333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(dec);
1084a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1085a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1086a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1087a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
1088a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
1089a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_bits = hdr->huffman_subsample_bits_;
1090a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->width_ = width;
1091a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->height_ = height;
1092a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1093a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
1094a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
1095a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1096a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1097a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int DecodeImageStream(int xsize, int ysize,
1098a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             int is_level0,
1099a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             VP8LDecoder* const dec,
1100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             uint32_t** const decoded_data) {
1101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 1;
1102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int transform_xsize = xsize;
1103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int transform_ysize = ysize;
1104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LBitReader* const br = &dec->br_;
1105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LMetadata* const hdr = &dec->hdr_;
1106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* data = NULL;
1107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int color_cache_bits = 0;
1108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Read the transforms (may recurse).
1110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (is_level0) {
1111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    while (ok && VP8LReadBits(br, 1)) {
1112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
1113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Color cache
1117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (ok && VP8LReadBits(br, 1)) {
1118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    color_cache_bits = VP8LReadBits(br, 4);
1119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
1120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!ok) {
1121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Read the Huffman codes (may recurse).
1127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
1128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                              color_cache_bits, is_level0);
1129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
1130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto End;
1132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Finish setting up the color-cache
1135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (color_cache_bits > 0) {
1136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->color_cache_size_ = 1 << color_cache_bits;
1137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
1138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = 0;
1140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    hdr->color_cache_size_ = 0;
1144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  UpdateDecoder(dec, transform_xsize, transform_ysize);
1146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (is_level0) {   // level 0 complete
1148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->state_ = READ_HDR;
1149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto End;
1150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
1153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
1154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
1155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (data == NULL) {
1156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ok = 0;
1158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      goto End;
1159a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1160a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1161a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Use the Huffman trees to decode the LZ77 encoded data.
11638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
11648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       transform_ysize, NULL);
1165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ok = ok && !br->error_;
1166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1167a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora End:
1168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ok) {
117033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(data);
1171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ClearMetadata(hdr);
1172a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
1173a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // status appropriately.
1174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
1175a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      dec->status_ = VP8_STATUS_SUSPENDED;
1176a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (decoded_data != NULL) {
1179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      *decoded_data = data;
1180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    } else {
1181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // We allocate image data in this function only for transforms. At level 0
1182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // (that is: not the transforms), we shouldn't have allocated anything.
1183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(data == NULL);
1184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(is_level0);
1185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
11868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->last_pixel_ = 0;  // Reset for future DECODE_DATA_FUNC() calls.
1187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (!is_level0) ClearMetadata(hdr);  // Clean up temporary data behind.
1188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ok;
1190a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
11930406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
11948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
1195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
1196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Scratch buffer corresponding to top-prediction row for transforming the
11970406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // first row in the row-blocks. Not needed for paletted alpha.
11988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t cache_top_pixels = (uint16_t)final_width;
11990406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
12008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
1201a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint64_t total_num_pixels =
1202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      num_pixels + cache_top_pixels + cache_pixels;
1203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->width_ <= final_width);
12058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
12060406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (dec->pixels_ == NULL) {
1207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->argb_cache_ = NULL;    // for sanity check
1208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
1210a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
12118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
12128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
12138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
12148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
12158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
12168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
12178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->argb_cache_ = NULL;    // for sanity check
12188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
12198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (dec->pixels_ == NULL) {
12208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
12218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    return 0;
12228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1225a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1226a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12280406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Special row-processing that only stores the alpha data.
1229a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
1230a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int num_rows = row - dec->last_row_;
12310406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
1232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (num_rows <= 0) return;  // Nothing to be done.
1234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  ApplyInverseTransforms(dec, num_rows, in);
1235a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1236a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Extract alpha (which is stored in the green plane).
1237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
1238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int width = dec->io_->width;      // the final width (!= dec->width_)
1239a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int cache_pixs = width * num_rows;
1240a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
1241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const src = dec->argb_cache_;
1242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int i;
1243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
1244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
12450406ce1417f76f2034833414dcecc9f56253640cVikas Arora  dec->last_row_ = dec->last_out_row_ = row;
12460406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12488b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
12498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                          const uint8_t* const data, size_t data_size,
12508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                          uint8_t* const output) {
1251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int ok = 0;
12528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDecoder* dec;
12538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8Io* io;
12548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(alph_dec != NULL);
12558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  alph_dec->vp8l_dec_ = VP8LNew();
12568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (alph_dec->vp8l_dec_ == NULL) return 0;
12578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec = alph_dec->vp8l_dec_;
12588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
12598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->width_ = alph_dec->width_;
12608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->height_ = alph_dec->height_;
12618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  dec->io_ = &alph_dec->io_;
12628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io = dec->io_;
1263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8InitIo(io);
12658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  WebPInitCustomIo(NULL, io);  // Just a sanity Init. io won't be used.
12668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->opaque = output;
12678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->width = alph_dec->width_;
12688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  io->height = alph_dec->height_;
1269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LInitBitReader(&dec->br_, data, data_size);
1272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_HDR;
12748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
12758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    goto Err;
12768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
1277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12780406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // Special case: if alpha data uses only the color indexing transform and
12790406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
12800406ce1417f76f2034833414dcecc9f56253640cVikas Arora  // method that only needs allocation of 1 byte per pixel (alpha channel).
12810406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (dec->next_transform_ == 1 &&
12820406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
12838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      Is8bOptimizable(&dec->hdr_)) {
12848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    alph_dec->use_8b_decode = 1;
12858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = AllocateInternalBuffers8b(dec);
12868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  } else {
12878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    // Allocate internal buffers (note that dec->width_ may have changed here).
12888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    alph_dec->use_8b_decode = 0;
12898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
12900406ce1417f76f2034833414dcecc9f56253640cVikas Arora  }
12910406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!ok) goto Err;
1293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DATA;
12958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 1;
1296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err:
12988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDelete(alph_dec->vp8l_dec_);
12998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  alph_dec->vp8l_dec_ = NULL;
13008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return 0;
13018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
13028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
13038b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
13048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  VP8LDecoder* const dec = alph_dec->vp8l_dec_;
13058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(dec != NULL);
13068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(dec->action_ == READ_DATA);
13078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  assert(last_row <= dec->height_);
13088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
1309259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  if (dec->last_pixel_ == dec->width_ * dec->height_) {
1310259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi    return 1;  // done
1311259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi  }
1312259681a1ff4023ac1b19ccdd9c5cd8172cdd3b8aUrvang Joshi
13138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // Decode (with special row processing).
13148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  return alph_dec->use_8b_decode ?
13158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
13168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                      last_row) :
13178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                      last_row, ExtractAlphaRows);
1319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1320a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1321a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
1324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int width, height, has_alpha;
1325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return 0;
1327a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (io == NULL) {
1328a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_INVALID_PARAM;
1329a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return 0;
1330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->io_ = io;
1333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->status_ = VP8_STATUS_OK;
1334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LInitBitReader(&dec->br_, io->data, io->data_size);
1335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
1336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Error;
1338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->state_ = READ_DIM;
1340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->width = width;
1341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io->height = height;
1342a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_HDR;
1344a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
1345a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1346a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Error:
13480406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8LClear(dec);
13490406ce1417f76f2034833414dcecc9f56253640cVikas Arora  assert(dec->status_ != VP8_STATUS_OK);
13500406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return 0;
1351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint VP8LDecodeImage(VP8LDecoder* const dec) {
1354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8Io* io = NULL;
1355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPDecParams* params = NULL;
1356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Sanity checks.
1358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (dec == NULL) return 0;
1359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
13608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora  dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
13618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora  assert(dec->hdr_.htree_groups_ != NULL);
13628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora  assert(dec->hdr_.num_htree_groups_ > 0);
13638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora
1364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  io = dec->io_;
1365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(io != NULL);
1366a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  params = (WebPDecParams*)io->opaque;
1367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(params != NULL);
1368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->output_ = params->output;
1369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->output_ != NULL);
1370a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Initialization.
1372a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
1373a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    dec->status_ = VP8_STATUS_INVALID_PARAM;
1374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Err;
1375a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1376a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
13778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
1378a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1379a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
1380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
138133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
138233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // need the alpha-multiply functions for premultiplied output or rescaling
138333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPInitAlphaProcessing();
138433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
138533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
1386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Decode.
1387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  dec->action_ = READ_DATA;
13880406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora                       dec->height_, ProcessRows)) {
1390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    goto Err;
1391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Cleanup.
1394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  params->last_y = dec->last_out_row_;
1395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LClear(dec);
1396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
1397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora Err:
1399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  VP8LClear(dec);
1400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(dec->status_ != VP8_STATUS_OK);
1401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 0;
1402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1405