15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2012 Google Inc. All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// main entry for the decoder
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Authors: Vikas Arora (vikaas.arora@gmail.com)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//          Jyrki Alakuijala (jyrki@google.com)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "./alphai.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8li.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "../dsp/dsp.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dsp/lossless.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dsp/yuv.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/huffman.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/utils.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUM_ARGB_CACHE_ROWS          16
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCodeLengthLiterals = 16;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCodeLengthRepeatCode = 16;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Five Huffman codes are used at each meta code:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  1. green + length prefix codes + color cache codes,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  2. alpha,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  3. red,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  4. blue, and,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  5. distance prefix codes.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef enum {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GREEN = 0,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RED   = 1,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BLUE  = 2,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ALPHA = 3,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DIST  = 4
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} HuffIndex;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NUM_LITERAL_CODES + NUM_LENGTH_CODES,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NUM_DISTANCE_CODES
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NUM_CODE_LENGTH_CODES       19
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CODE_TO_PLANE_CODES        120
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int DecodeImageStream(int xsize, int ysize,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int is_level0,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             VP8LDecoder* const dec,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             uint32_t** const decoded_data);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8LCheckSignature(const uint8_t* const data, size_t size) {
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return (size >= VP8L_FRAME_HEADER_SIZE &&
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          data[0] == VP8L_MAGIC_BYTE &&
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          (data[4] >> 5) == 0);  // version
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ReadImageInfo(VP8LBitReader* const br,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int* const width, int* const height,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int* const has_alpha) {
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *has_alpha = VP8LReadBits(br, 1);
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8LGetInfo(const uint8_t* data, size_t data_size,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                int* const width, int* const height, int* const has_alpha) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;         // not enough data
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (!VP8LCheckSignature(data, data_size)) {
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return 0;         // bad signature
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int w, h, a;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LBitReader br;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LInitBitReader(&br, data, data_size);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ReadImageInfo(&br, &w, &h, &a)) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (width != NULL) *width = w;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (height != NULL) *height = h;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_alpha != NULL) *has_alpha = a;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE int GetCopyDistance(int distance_symbol,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       VP8LBitReader* const br) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_bits, offset;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (distance_symbol < 4) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return distance_symbol + 1;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_bits = (distance_symbol - 2) >> 1;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  offset = (2 + (distance_symbol & 1)) << extra_bits;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return offset + VP8LReadBits(br, extra_bits) + 1;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE int GetCopyLength(int length_symbol,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     VP8LBitReader* const br) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Length and distance prefixes are encoded the same way.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetCopyDistance(length_symbol, br);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (plane_code > CODE_TO_PLANE_CODES) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return plane_code - CODE_TO_PLANE_CODES;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int dist_code = kCodeToPlane[plane_code - 1];
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int yoffset = dist_code >> 4;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int xoffset = 8 - (dist_code & 0xf);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int dist = yoffset * xsize + xoffset;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return (dist >= 1) ? dist : 1;  // dist<1 can happen if xsize is very small
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the next Huffman code from bit-stream.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FillBitWindow(br) needs to be called at minimum every second call
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to ReadSymbol, in order to pre-fetch enough bits.
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  VP8LBitReader* const br) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HuffmanTreeNode* node = tree->root_;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32_t bits = VP8LPrefetchBits(br);
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int bitpos = br->bit_pos_;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check if we find the bit combination from the Huffman lookup table.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int lut_ix = bits & (HUFF_LUT - 1);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int lut_bits = tree->lut_bits_[lut_ix];
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (lut_bits <= HUFF_LUT_BITS) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8LSetBitPos(br, bitpos + lut_bits);
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return tree->lut_symbol_[lut_ix];
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  node += tree->lut_jump_[lut_ix];
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bitpos += HUFF_LUT_BITS;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bits >>= HUFF_LUT_BITS;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Decode the value from a binary tree.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(node != NULL);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  do {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    node = HuffmanTreeNextNode(node, bits & 1);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bits >>= 1;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++bitpos;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } while (HuffmanTreeNodeIsNotLeaf(node));
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LSetBitPos(br, bitpos);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return node->symbol_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ReadHuffmanCodeLengths(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LDecoder* const dec, const int* const code_length_code_lengths,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_symbols, int* const code_lengths) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 0;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int symbol;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_symbol;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int prev_code_len = DEFAULT_CODE_LENGTH;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HuffmanTree tree;
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int huff_codes[NUM_CODE_LENGTH_CODES] = { 0 };
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!VP8LHuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    huff_codes, NUM_CODE_LENGTH_CODES)) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (VP8LReadBits(br, 1)) {    // use length
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_symbol = 2 + VP8LReadBits(br, length_nbits);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (max_symbol > num_symbols) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto End;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_symbol = num_symbols;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  symbol = 0;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (symbol < num_symbols) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int code_len;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (max_symbol-- == 0) break;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LFillBitWindow(br);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    code_len = ReadSymbol(&tree, br);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (code_len < kCodeLengthLiterals) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      code_lengths[symbol++] = code_len;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (code_len != 0) prev_code_len = code_len;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int use_prev = (code_len == kCodeLengthRepeatCode);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int slot = code_len - kCodeLengthLiterals;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int extra_bits = kCodeLengthExtraBits[slot];
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int repeat_offset = kCodeLengthRepeatOffsets[slot];
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (symbol + repeat > num_symbols) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto End;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int length = use_prev ? prev_code_len : 0;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (repeat-- > 0) code_lengths[symbol++] = length;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = 1;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) End:
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHuffmanTreeFree(&tree);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// 'code_lengths' is pre-allocated temporary buffer, used for creating Huffman
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// tree.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           int* const code_lengths, int* const huff_codes,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           HuffmanTree* const tree) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 0;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int simple_code = VP8LReadBits(br, 1);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (simple_code) {  // Read symbols, codes & code lengths directly.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int symbols[2];
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int codes[2];
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int num_symbols = VP8LReadBits(br, 1) + 1;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int first_symbol_len_code = VP8LReadBits(br, 1);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The first code is either 1 bit or 8 bit code.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    codes[0] = 0;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    code_lengths[0] = num_symbols - 1;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The second code (if present), is always 8 bit long.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_symbols == 2) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      symbols[1] = VP8LReadBits(br, 8);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      codes[1] = 1;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      code_lengths[1] = num_symbols - 1;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ok = VP8LHuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                      alphabet_size, num_symbols);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {  // Decode Huffman-coded code lengths.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int num_codes = VP8LReadBits(br, 4) + 4;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_codes > NUM_CODE_LENGTH_CODES) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    memset(code_lengths, 0, alphabet_size * sizeof(*code_lengths));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_codes; ++i) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                code_lengths);
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ok = ok && VP8LHuffmanTreeBuildImplicit(tree, code_lengths, huff_codes,
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            alphabet_size);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ok && !br->error_;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            int color_cache_bits, int allow_recursion) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, j;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LMetadata* const hdr = &dec->hdr_;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* huffman_image = NULL;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HTreeGroup* htree_groups = NULL;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_htree_groups = 1;
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int max_alphabet_size = 0;
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* code_lengths = NULL;
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int* huff_codes = NULL;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_recursion && VP8LReadBits(br, 1)) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // use meta Huffman codes.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int huffman_precision = VP8LReadBits(br, 3) + 2;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int huffman_pixs = huffman_xsize * huffman_ysize;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &huffman_image)) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto Error;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hdr->huffman_subsample_bits_ = huffman_precision;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < huffman_pixs; ++i) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The huffman data is stored in red and green bytes.
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const int group = (huffman_image[i] >> 8) & 0xffff;
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      huffman_image[i] = group;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (group >= num_htree_groups) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        num_htree_groups = group + 1;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (br->error_) goto Error;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Find maximum alphabet size for the htree group.
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int alphabet_size = kAlphabetSize[j];
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (j == 0 && color_cache_bits > 0) {
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      alphabet_size += 1 << color_cache_bits;
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (max_alphabet_size < alphabet_size) {
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      max_alphabet_size = alphabet_size;
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  htree_groups = VP8LHtreeGroupsNew(num_htree_groups);
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  code_lengths =
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, sizeof(*code_lengths));
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  huff_codes =
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (int*)WebPSafeMalloc((uint64_t)max_alphabet_size, sizeof(*huff_codes));
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (htree_groups == NULL || code_lengths == NULL || huff_codes == NULL) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < num_htree_groups; ++i) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTree* const htrees = htree_groups[i].htrees_;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int alphabet_size = kAlphabetSize[j];
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      HuffmanTree* const htree = htrees + j;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j == 0 && color_cache_bits > 0) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alphabet_size += 1 << color_cache_bits;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, huff_codes,
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           htree)) {
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        goto Error;
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huff_codes);
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(code_lengths);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All OK. Finalize pointers and return.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->huffman_image_ = huffman_image;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->num_htree_groups_ = num_htree_groups;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->htree_groups_ = htree_groups;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huff_codes);
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(code_lengths);
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huffman_image);
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHtreeGroupsFree(htree_groups, num_htree_groups);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Scaling.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_channels = 4;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int in_width = io->mb_w;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int out_width = io->scaled_width;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int in_height = io->mb_h;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int out_height = io->scaled_height;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t* work;        // Rescaler work area.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* scaled_data;  // Temporary storage for scaled BGRA data.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t memory_size = sizeof(*dec->rescaler) +
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               work_size * sizeof(*work) +
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               scaled_data_size * sizeof(*scaled_data);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (memory == NULL) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->rescaler_memory == NULL);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->rescaler_memory = memory;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->rescaler = (WebPRescaler*)memory;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory += sizeof(*dec->rescaler);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  work = (int32_t*)memory;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory += work_size * sizeof(*work);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scaled_data = (uint32_t*)memory;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   out_width, out_height, 0, num_channels,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   in_width, out_width, in_height, out_height, work);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Export to ARGB
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have special "export" function since we need to convert from BGRA
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  int rgba_stride, uint8_t* const rgba) {
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* const src = (uint32_t*)rescaler->dst;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dst_width = rescaler->dst_width;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_lines_out = 0;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (WebPRescalerHasPendingOutput(rescaler)) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const dst = rgba + num_lines_out * rgba_stride;
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPRescalerExportRow(rescaler, 0);
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPMultARGBRow(src, dst_width, 1);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++num_lines_out;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_lines_out;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Emit scaled rows.
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                uint8_t* in, int in_stride, int mb_h,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                uint8_t* const out, int out_stride) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_lines_in = 0;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_lines_out = 0;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_lines_in < mb_h) {
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint8_t* const row_in = in + num_lines_in * in_stride;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const row_out = out + num_lines_out * out_stride;
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int lines_left = mb_h - num_lines_in;
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(needed_lines > 0 && needed_lines <= lines_left);
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPMultARGBRows(row_in, in_stride,
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     dec->rescaler->src_width, needed_lines, 0);
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    num_lines_in += needed_lines;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_lines_out;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Emit rows without any scaling.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRows(WEBP_CSP_MODE colorspace,
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    const uint8_t* row_in, int in_stride,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int mb_w, int mb_h,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    uint8_t* const out, int out_stride) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lines = mb_h;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* row_out = out;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (lines-- > 0) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    row_in += in_stride;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    row_out += out_stride;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mb_h;  // Num rows out == num rows in.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Export to YUVA
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TODO(skal): should be in yuv.c
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const WebPDecBuffer* const output) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebPYUVABuffer* const buf = &output->u.YUVA;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first, the luma plane
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const y = buf->y + y_pos * buf->y_stride;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < width; ++i) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t p = src[i];
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       YUV_HALF);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then U/V planes
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int uv_width = width >> 1;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < uv_width; ++i) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t v0 = src[2 * i + 0];
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t v1 = src[2 * i + 1];
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // VP8RGBToU/V expects four accumulated pixels. Hence we need to
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int g = ((v0 >>  7) & 0x1fe) + ((v1 >>  7) & 0x1fe);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int b = ((v0 <<  1) & 0x1fe) + ((v1 <<  1) & 0x1fe);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!(y_pos & 1)) {  // even lines: store values
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {             // odd lines: average with previous values
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Approximated average-of-four. But it's an acceptable diff.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        u[i] = (u[i] + tmp_u + 1) >> 1;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        v[i] = (v[i] + tmp_v + 1) >> 1;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (width & 1) {       // last pixel
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t v0 = src[2 * i + 0];
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int r = (v0 >> 14) & 0x3fc;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int g = (v0 >>  6) & 0x3fc;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int b = (v0 <<  2) & 0x3fc;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!(y_pos & 1)) {  // even lines
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {             // odd lines (note: we could just skip this)
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        u[i] = (u[i] + tmp_u + 1) >> 1;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        v[i] = (v[i] + tmp_v + 1) >> 1;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lastly, store alpha if needed.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf->a != NULL) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const a = buf->a + y_pos * buf->a_stride;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPRescaler* const rescaler = dec->rescaler;
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* const src = (uint32_t*)rescaler->dst;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dst_width = rescaler->dst_width;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_lines_out = 0;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (WebPRescalerHasPendingOutput(rescaler)) {
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPRescalerExportRow(rescaler, 0);
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPMultARGBRow(src, dst_width, 1);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertToYUVA(src, dst_width, y_pos, dec->output_);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++y_pos;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++num_lines_out;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_lines_out;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                uint8_t* in, int in_stride, int mb_h) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_lines_in = 0;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_pos = dec->last_out_row_;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_lines_in < mb_h) {
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int lines_left = mb_h - num_lines_in;
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    num_lines_in += needed_lines;
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    in += needed_lines * in_stride;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_pos += ExportYUVA(dec, y_pos);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return y_pos;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRowsYUVA(const VP8LDecoder* const dec,
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        const uint8_t* in, int in_stride,
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int mb_w, int num_rows) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y_pos = dec->last_out_row_;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_rows-- > 0) {
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    in += in_stride;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++y_pos;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return y_pos;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cropping.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// crop options. Also updates the input data pointer, so that it points to the
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// start of the cropped window. Note that pixels are in ARGB format even if
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 'in_data' is uint8_t*.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the crop window is not empty.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         uint8_t** const in_data, int pixel_stride) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(y_start < y_end);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(io->crop_left < io->crop_right);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (y_end > io->crop_bottom) {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_end = io->crop_bottom;  // make sure we don't overflow on last row.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (y_start < io->crop_top) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int delta = io->crop_top - y_start;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y_start = io->crop_top;
6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *in_data += delta * pixel_stride;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (y_start >= y_end) return 0;  // Crop window is empty.
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *in_data += io->crop_left * sizeof(uint32_t);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io->mb_y = y_start - io->crop_top;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io->mb_w = io->crop_right - io->crop_left;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io->mb_h = y_end - y_start;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;  // Non-empty crop window.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE int GetMetaIndex(
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t* const image, int xsize, int bits, int x, int y) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bits == 0) return 0;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return image[xsize * (y >> bits) + (x >> bits)];
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   int x, int y) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      hdr->huffman_subsample_bits_, x, y);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(meta_index < hdr->num_htree_groups_);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hdr->htree_groups_ + meta_index;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main loop, with custom row-processing function
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const uint32_t* const rows) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = dec->next_transform_;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int cache_pixs = dec->width_ * num_rows;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int start_row = dec->last_row_;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int end_row = start_row + num_rows;
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32_t* rows_in = rows;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32_t* const rows_out = dec->argb_cache_;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inverse transforms.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: most transforms only need to operate on the cropped region only.
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (n-- > 0) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LTransform* const transform = &dec->transforms_[n];
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rows_in = rows_out;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Special method for paletted alpha data.
655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows,
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                        const uint8_t* const rows) {
657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int start_row = dec->last_row_;
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int end_row = start_row + num_rows;
659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint8_t* rows_in = rows;
660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row;
661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VP8LTransform* const transform = &dec->transforms_[0];
662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  assert(dec->next_transform_ == 1);
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in,
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                      rows_out);
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Processes (transforms, scales & color-converts) the rows decoded after the
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// last call.
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ProcessRows(VP8LDecoder* const dec, int row) {
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_rows = row - dec->last_row_;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_rows <= 0) return;  // Nothing to be done.
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ApplyInverseTransforms(dec, num_rows, rows);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit output.
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8Io* const io = dec->io_;
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int in_stride = io->width * sizeof(uint32_t);  // in unit of RGBA
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Nothing to output (this time).
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const WebPDecBuffer* const output = dec->output_;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (output->colorspace < MODE_YUV) {  // convert to RGBA
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const WebPRGBABuffer* const buf = &output->u.RGBA;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int num_rows_out = io->use_scaling ?
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 rgba, buf->stride) :
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EmitRows(output->colorspace, rows_data, in_stride,
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     io->mb_w, io->mb_h, rgba, buf->stride);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Update 'last_out_row_'.
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dec->last_out_row_ += num_rows_out;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {                              // convert to YUVA
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dec->last_out_row_ = io->use_scaling ?
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(dec->last_out_row_ <= output->height);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update 'last_row_'.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->last_row_ = row;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->last_row_ <= dec->height_);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Row-processing for the special case when alpha data contains only one
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// transform (color indexing), and trivial non-green literals.
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int Is8bOptimizable(const VP8LMetadata* const hdr) {
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int i;
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (hdr->color_cache_size_ > 0) return 0;
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // When the Huffman tree contains only one symbol, we can skip the
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // call to ReadSymbol() for red/blue/alpha channels.
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (i = 0; i < hdr->num_htree_groups_; ++i) {
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_;
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (htrees[RED].num_nodes_ > 1) return 0;
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (htrees[BLUE].num_nodes_ > 1) return 0;
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (htrees[ALPHA].num_nodes_ > 1) return 0;
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 1;
724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int num_rows = row - dec->last_row_;
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint8_t* const in =
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_;
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (num_rows > 0) {
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ApplyInverseTransformsAlpha(dec, num_rows, in);
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->last_row_ = dec->last_out_row_ = row;
734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int width, int height, int last_row) {
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int ok = 1;
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int row = dec->last_pixel_ / width;
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int col = dec->last_pixel_ % width;
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LMetadata* const hdr = &dec->hdr_;
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int pos = dec->last_pixel_;         // current position
7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int end = width * height;     // End of data
7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int last = width * last_row;  // Last pixel to decode
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int mask = hdr->huffman_mask_;
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(htree_group != NULL);
750c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  assert(pos < end);
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(last_row <= height);
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(Is8bOptimizable(hdr));
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (!br->eos_ && pos < last) {
7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int code;
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only update when changing tile.
7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if ((col & mask) == 0) {
7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      htree_group = GetHtreeGroupForPos(hdr, col, row);
7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8LFillBitWindow(br);
7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (code < NUM_LITERAL_CODES) {  // Literal
7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      data[pos] = code;
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++pos;
7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++col;
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (col >= width) {
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        col = 0;
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ++row;
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ExtractPalettedAlphaRows(dec, row);
7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (code < len_code_limit) {  // Backward reference
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int dist_code, dist;
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int length_sym = code - NUM_LITERAL_CODES;
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int length = GetCopyLength(length_sym, br);
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8LFillBitWindow(br);
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dist_code = GetCopyDistance(dist_symbol, br);
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dist = PlaneCodeToDistance(width, dist_code);
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pos >= dist && end - pos >= length) {
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        int i;
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist];
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ok = 0;
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        goto End;
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pos += length;
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      col += length;
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      while (col >= width) {
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        col -= width;
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ++row;
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (row % NUM_ARGB_CACHE_ROWS == 0) {
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ExtractPalettedAlphaRows(dec, row);
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (pos < last && (col & mask)) {
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        htree_group = GetHtreeGroupForPos(hdr, col, row);
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {  // Not reached
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ok = 0;
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      goto End;
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = !br->error_;
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!ok) goto End;
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process the remaining rows corresponding to last row-block.
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtractPalettedAlphaRows(dec, row);
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) End:
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (br->error_ || !ok || (br->eos_ && pos < end)) {
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = 0;
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            : VP8_STATUS_BITSTREAM_ERROR;
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->last_pixel_ = (int)pos;
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (pos == end) dec->state_ = READ_DATA;
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ok;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int width, int height, int last_row,
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           ProcessRowsFunc process_func) {
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int ok = 1;
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int row = dec->last_pixel_ / width;
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int col = dec->last_pixel_ % width;
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LMetadata* const hdr = &dec->hdr_;
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* src = data + dec->last_pixel_;
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* last_cached = src;
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* const src_end = data + width * height;     // End of data
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint32_t* const src_last = data + width * last_row;  // Last pixel to decode
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LColorCache* const color_cache =
8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int mask = hdr->huffman_mask_;
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(htree_group != NULL);
841c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  assert(src < src_end);
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(src_last <= src_end);
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (!br->eos_ && src < src_last) {
8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int code;
8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only update when changing tile. Note we could use this test:
8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // but that's actually slower and needs storing the previous col/row.
8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if ((col & mask) == 0) {
8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      htree_group = GetHtreeGroupForPos(hdr, col, row);
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    VP8LFillBitWindow(br);
8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    code = ReadSymbol(&htree_group->htrees_[GREEN], br);
8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (code < NUM_LITERAL_CODES) {  // Literal
8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int red, green, blue, alpha;
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      red = ReadSymbol(&htree_group->htrees_[RED], br);
8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      green = code;
8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8LFillBitWindow(br);
8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      *src = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | blue;
8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AdvanceByOne:
8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++src;
8645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++col;
8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (col >= width) {
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        col = 0;
8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ++row;
8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
8695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          process_func(dec, row);
8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (color_cache != NULL) {
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          while (last_cached < src) {
8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            VP8LColorCacheInsert(color_cache, *last_cached++);
8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          }
8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (code < len_code_limit) {  // Backward reference
8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int dist_code, dist;
8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int length_sym = code - NUM_LITERAL_CODES;
8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int length = GetCopyLength(length_sym, br);
8815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
8825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8LFillBitWindow(br);
8835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dist_code = GetCopyDistance(dist_symbol, br);
8845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      dist = PlaneCodeToDistance(width, dist_code);
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ok = 0;
8875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        goto End;
8885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        int i;
8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for (i = 0; i < length; ++i) src[i] = src[i - dist];
8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        src += length;
8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      col += length;
8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      while (col >= width) {
8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        col -= width;
8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ++row;
8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          process_func(dec, row);
8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (src < src_last) {
9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (color_cache != NULL) {
9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          while (last_cached < src) {
9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            VP8LColorCacheInsert(color_cache, *last_cached++);
9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          }
9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (code < color_cache_limit) {  // Color cache
9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const int key = code - len_code_limit;
9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      assert(color_cache != NULL);
9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      while (last_cached < src) {
9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        VP8LColorCacheInsert(color_cache, *last_cached++);
9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *src = VP8LColorCacheLookup(color_cache, key);
9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      goto AdvanceByOne;
9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {  // Not reached
9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ok = 0;
9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      goto End;
9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = !br->error_;
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!ok) goto End;
9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process the remaining rows corresponding to last row-block.
9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (process_func != NULL) process_func(dec, row);
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) End:
9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (br->error_ || !ok || (br->eos_ && src < src_end)) {
9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = 0;
9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            : VP8_STATUS_BITSTREAM_ERROR;
9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->last_pixel_ = (int)(src - data);
9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (src == src_end) dec->state_ = READ_DATA;
9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ok;
9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8LTransform
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ClearTransform(VP8LTransform* const transform) {
9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(transform->data_);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform->data_ = NULL;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For security reason, we need to remap the color map to span
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the total possible bundled values, and not just the num_colors.
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int final_num_colors = 1 << (8 >> transform->bits_);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* const new_color_map =
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                sizeof(*new_color_map));
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_color_map == NULL) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const data = (uint8_t*)transform->data_;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const new_data = (uint8_t*)new_color_map;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_color_map[0] = transform->data_[0];
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 4; i < 4 * num_colors; ++i) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Equivalent to AddPixelEq(), on a byte-basis.
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (; i < 4 * final_num_colors; ++i)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_data[i] = 0;  // black tail.
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(transform->data_);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transform->data_ = new_color_map;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ReadTransform(int* const xsize, int const* ysize,
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         VP8LDecoder* const dec) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 1;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VP8LImageTransformType type =
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (VP8LImageTransformType)VP8LReadBits(br, 2);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each transform type can only be present once in the stream.
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec->transforms_seen_ & (1U << type)) {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;  // Already there, let's not accept the second same transform.
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->transforms_seen_ |= (1U << type);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform->type_ = type;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform->xsize_ = *xsize;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform->ysize_ = *ysize;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform->data_ = NULL;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++dec->next_transform_;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->next_transform_ <= NUM_TRANSFORMS);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PREDICTOR_TRANSFORM:
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CROSS_COLOR_TRANSFORM:
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transform->bits_ = VP8LReadBits(br, 3) + 2;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               transform->bits_),
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             VP8LSubSampleSize(transform->ysize_,
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               transform->bits_),
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             0, dec, &transform->data_);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case COLOR_INDEXING_TRANSFORM: {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const int num_colors = VP8LReadBits(br, 8) + 1;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const int bits = (num_colors > 16) ? 0
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      : (num_colors > 4) ? 1
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      : (num_colors > 2) ? 2
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      : 3;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *xsize = VP8LSubSampleSize(transform->xsize_, bits);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       transform->bits_ = bits;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ok = ok && ExpandColorMap(num_colors, transform);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SUBTRACT_GREEN:
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);    // can't happen
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8LMetadata
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitMetadata(VP8LMetadata* const hdr) {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(hdr);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(hdr, 0, sizeof(*hdr));
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ClearMetadata(VP8LMetadata* const hdr) {
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(hdr);
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(hdr->huffman_image_);
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHtreeGroupsFree(hdr->htree_groups_, hdr->num_htree_groups_);
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LColorCacheClear(&hdr->color_cache_);
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitMetadata(hdr);
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8LDecoder
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VP8LDecoder* VP8LNew(void) {
10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec == NULL) return NULL;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->status_ = VP8_STATUS_OK;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->action_ = READ_DIM;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->state_ = READ_DIM;
10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LDspInit();  // Init critical function pointers.
10545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dec;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8LClear(VP8LDecoder* const dec) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec == NULL) return;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearMetadata(&dec->hdr_);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(dec->pixels_);
1064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  dec->pixels_ = NULL;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < dec->next_transform_; ++i) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearTransform(&dec->transforms_[i]);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->next_transform_ = 0;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->transforms_seen_ = 0;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(dec->rescaler_memory);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->rescaler_memory = NULL;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->output_ = NULL;   // leave no trace behind
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VP8LDelete(VP8LDecoder* const dec) {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec != NULL) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LClear(dec);
10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(dec);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LMetadata* const hdr = &dec->hdr_;
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_bits = hdr->huffman_subsample_bits_;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->width_ = width;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->height_ = height;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int DecodeImageStream(int xsize, int ysize,
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int is_level0,
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             VP8LDecoder* const dec,
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             uint32_t** const decoded_data) {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 1;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int transform_xsize = xsize;
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int transform_ysize = ysize;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitReader* const br = &dec->br_;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LMetadata* const hdr = &dec->hdr_;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* data = NULL;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int color_cache_bits = 0;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the transforms (may recurse).
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_level0) {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (ok && VP8LReadBits(br, 1)) {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Color cache
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok && VP8LReadBits(br, 1)) {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    color_cache_bits = VP8LReadBits(br, 4);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ok) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto End;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the Huffman codes (may recurse).
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              color_cache_bits, is_level0);
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto End;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish setting up the color-cache
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (color_cache_bits > 0) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hdr->color_cache_size_ = 1 << color_cache_bits;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = 0;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto End;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hdr->color_cache_size_ = 0;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDecoder(dec, transform_xsize, transform_ysize);
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_level0) {   // level 0 complete
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->state_ = READ_HDR;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto End;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data == NULL) {
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = 0;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto End;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the Huffman trees to decode the LZ77 encoded data.
11605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       transform_ysize, NULL);
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok = ok && !br->error_;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) End:
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok) {
11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(data);
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearMetadata(hdr);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // status appropriately.
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dec->status_ = VP8_STATUS_SUSPENDED;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (decoded_data != NULL) {
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *decoded_data = data;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We allocate image data in this function only for transforms. At level 0
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (that is: not the transforms), we shouldn't have allocated anything.
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(data == NULL);
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(is_level0);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->last_pixel_ = 0;  // Reset for future DECODE_DATA_FUNC() calls.
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_level0) ClearMetadata(hdr);  // Clean up temporary data behind.
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Allocate internal buffers dec->pixels_ and dec->argb_cache_.
11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scratch buffer corresponding to top-prediction row for transforming the
1194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // first row in the row-blocks. Not needed for paletted alpha.
11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint64_t cache_top_pixels = (uint16_t)final_width;
1196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t total_num_pixels =
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_pixels + cache_top_pixels + cache_pixels;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->width_ <= final_width);
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (dec->pixels_ == NULL) {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->argb_cache_ = NULL;    // for sanity check
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 1;
12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->argb_cache_ = NULL;    // for sanity check
12155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
12165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (dec->pixels_ == NULL) {
12175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
12185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Special row-processing that only stores the alpha data.
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int num_rows = row - dec->last_row_;
1228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_rows <= 0) return;  // Nothing to be done.
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ApplyInverseTransforms(dec, num_rows, in);
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract alpha (which is stored in the green plane).
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int width = dec->io_->width;      // the final width (!= dec->width_)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int cache_pixs = width * num_rows;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t* const src = dec->argb_cache_;
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  dec->last_row_ = dec->last_out_row_ = row;
1243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const uint8_t* const data, size_t data_size,
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          uint8_t* const output) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ok = 0;
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LDecoder* dec;
12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8Io* io;
12515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(alph_dec != NULL);
12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  alph_dec->vp8l_dec_ = VP8LNew();
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (alph_dec->vp8l_dec_ == NULL) return 0;
12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec = alph_dec->vp8l_dec_;
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->width_ = alph_dec->width_;
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->height_ = alph_dec->height_;
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dec->io_ = &alph_dec->io_;
12595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io = dec->io_;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8InitIo(io);
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebPInitCustomIo(NULL, io);  // Just a sanity Init. io won't be used.
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io->opaque = output;
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io->width = alph_dec->width_;
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io->height = alph_dec->height_;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->status_ = VP8_STATUS_OK;
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LInitBitReader(&dec->br_, data, data_size);
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->action_ = READ_HDR;
12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    goto Err;
12735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Special case: if alpha data uses only the color indexing transform and
1276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
1277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // method that only needs allocation of 1 byte per pixel (alpha channel).
1278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (dec->next_transform_ == 1 &&
1279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
12805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Is8bOptimizable(&dec->hdr_)) {
12815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    alph_dec->use_8b_decode = 1;
12825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = AllocateInternalBuffers8b(dec);
12835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
12845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Allocate internal buffers (note that dec->width_ may have changed here).
12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    alph_dec->use_8b_decode = 0;
12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ok) goto Err;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->action_ = READ_DATA;
12925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 1;
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Err:
12955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LDelete(alph_dec->vp8l_dec_);
12965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  alph_dec->vp8l_dec_ = NULL;
12975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 0;
12985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
13015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LDecoder* const dec = alph_dec->vp8l_dec_;
13025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(dec != NULL);
13035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(dec->action_ == READ_DATA);
13045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  assert(last_row <= dec->height_);
13055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1306c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (dec->last_pixel_ == dec->width_ * dec->height_) {
1307c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return 1;  // done
1308c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
13105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Decode (with special row processing).
13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return alph_dec->use_8b_decode ?
13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      last_row) :
13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      last_row, ExtractAlphaRows);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width, height, has_alpha;
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec == NULL) return 0;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (io == NULL) {
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_INVALID_PARAM;
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->io_ = io;
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->status_ = VP8_STATUS_OK;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LInitBitReader(&dec->br_, io->data, io->data_size);
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->state_ = READ_DIM;
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io->width = width;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io->height = height;
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->action_ = READ_HDR;
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VP8LClear(dec);
1346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert(dec->status_ != VP8_STATUS_OK);
1347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return 0;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8LDecodeImage(VP8LDecoder* const dec) {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8Io* io = NULL;
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPDecParams* params = NULL;
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity checks.
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dec == NULL) return 0;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io = dec->io_;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(io != NULL);
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params = (WebPDecParams*)io->opaque;
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(params != NULL);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->output_ = params->output;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->output_ != NULL);
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialization.
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dec->status_ = VP8_STATUS_INVALID_PARAM;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Err;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) {
13755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // need the alpha-multiply functions for premultiplied output or rescaling
13765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPInitAlphaProcessing();
13775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
13785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decode.
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dec->action_ = READ_DATA;
1381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
13825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       dec->height_, ProcessRows)) {
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Err;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleanup.
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->last_y = dec->last_out_row_;
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LClear(dec);
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Err:
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LClear(dec);
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(dec->status_ != VP8_STATUS_OK);
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1398