idec.c revision a2415724fb3466168b2af5b08bd94ba732c0e753
1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved. 203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// 303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// This code is licensed under the same terms as WebM: 403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Software License Agreement: http://www.webmproject.org/license/software/ 503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// ----------------------------------------------------------------------------- 703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// 803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Incremental decoding 903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// 1003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Author: somnath@google.com (Somnath Banerjee) 1103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 1203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#include <assert.h> 1303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#include <string.h> 1403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#include <stdlib.h> 1503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./webpi.h" 17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8i.h" 18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/utils.h" 1903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 2003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 2103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroraextern "C" { 2203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#endif 2303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// In append mode, buffer allocations increase as multiples of this value. 25a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Needs to be a power of 2. 2603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#define CHUNK_SIZE 4096 2703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#define MAX_MB_SIZE 4096 2803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 2903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 3003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Data structures for memory and states 3103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 3203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Decoding states. State normally flows like HEADER->PARTS0->DATA->DONE. 3303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// If there is any error the decoder goes into state ERROR. 34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef enum { 35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_PRE_VP8, // All data before that of the first VP8 chunk. 36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk). 37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_VP8_PARTS0, 38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_VP8_DATA, 39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_VP8L_HEADER, 40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_VP8L_DATA, 41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_DONE, 42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora STATE_ERROR 4303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} DecState; 4403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 4503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Operating state for the MemBuffer 46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef enum { 47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MEM_MODE_NONE = 0, 48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MEM_MODE_APPEND, 49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MEM_MODE_MAP 5003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} MemBufferMode; 5103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 5203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// storage for partition #0 and partial data (in a rolling fashion) 5303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroratypedef struct { 5403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MemBufferMode mode_; // Operation mode 55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t start_; // start location of the data to be decoded 56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t end_; // end location 5703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora size_t buf_size_; // size of the allocated buffer 5803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora uint8_t* buf_; // We don't own this buffer in case WebPIUpdate() 5903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 6003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora size_t part0_size_; // size of partition #0 6103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint8_t* part0_buf_; // buffer to store partition #0 6203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} MemBuffer; 6303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 6403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastruct WebPIDecoder { 6503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora DecState state_; // current decoding state 6603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPDecParams params_; // Params to store output info 67a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int is_lossless_; // for down-casting 'dec_'. 68a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora void* dec_; // either a VP8Decoder or a VP8LDecoder instance 6903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8Io io_; 7003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 71466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora MemBuffer mem_; // input memory buffer. 72466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer output_; // output buffer (when no external one is supplied) 73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header. 7403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora}; 7503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// MB context to restore in case VP8DecodeMB() fails 7703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroratypedef struct { 7803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8MB left_; 7903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8MB info_; 8003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora uint8_t intra_t_[4]; 8103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora uint8_t intra_l_[4]; 8203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8BitReader br_; 8303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8BitReader token_br_; 8403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} MBContext; 8503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 8603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 8703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// MemBuffer: incoming data handling 8803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { 90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (br->buf_ != NULL) { 91a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora br->buf_ += offset; 92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora br->buf_end_ += offset; 93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 9503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { 9703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return (mem->end_ - mem->start_); 9803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 9903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { 101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MemBuffer* const mem = &idec->mem_; 102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* const new_base = mem->buf_ + mem->start_; 103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // note: for VP8, setting up idec->io_ is only really needed at the beginning 104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // of the decoding, till partition #0 is complete. 105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->io_.data = new_base; 106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->io_.data_size = MemDataSize(mem); 107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->dec_ != NULL) { 109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!idec->is_lossless_) { 110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int last_part = dec->num_parts_ - 1; 112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (offset != 0) { 113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int p; 114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora for (p = 0; p <= last_part; ++p) { 115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora RemapBitReader(dec->parts_ + p, offset); 116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Remap partition #0 data pointer to new offset, but only in MAP 118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // mode (in APPEND mode, partition #0 is copied into a fixed memory). 119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (mem->mode_ == MEM_MODE_MAP) { 120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora RemapBitReader(&dec->br_, offset); 121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(last_part >= 0); 124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; 125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { // Resize lossless bitreader 126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); 128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 13203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Appends data to the end of MemBuffer->buf_. It expands the allocated memory 13303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// size if required and also updates VP8BitReader's if new memory is allocated. 13403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic int AppendToMemBuffer(WebPIDecoder* const idec, 13503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint8_t* const data, size_t data_size) { 13603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MemBuffer* const mem = &idec->mem_; 137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* const old_base = mem->buf_ + mem->start_; 13803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->mode_ == MEM_MODE_APPEND); 139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data_size > MAX_CHUNK_PAYLOAD) { 140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // security safeguard: trying to allocate more than what the format 141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // allows for a chunk should be considered a smoke smell. 142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 14403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 14503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory 146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const size_t current_size = MemDataSize(mem); 147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t new_size = (uint64_t)current_size + data_size; 148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); 149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const new_buf = 150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); 151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (new_buf == NULL) return 0; 152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora memcpy(new_buf, old_base, current_size); 15303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free(mem->buf_); 15403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->buf_ = new_buf; 155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->buf_size_ = (size_t)extra_size; 15603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->start_ = 0; 157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->end_ = current_size; 15803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 15903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 16003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(mem->buf_ + mem->end_, data, data_size); 16103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->end_ += data_size; 16203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->end_ <= mem->buf_size_); 16303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora DoRemap(idec, mem->buf_ + mem->start_ - old_base); 16503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 1; 16603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 16703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 16803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic int RemapMemBuffer(WebPIDecoder* const idec, 16903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint8_t* const data, size_t data_size) { 17003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MemBuffer* const mem = &idec->mem_; 171a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* const old_base = mem->buf_ + mem->start_; 17203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->mode_ == MEM_MODE_MAP); 17303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! 17503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 17603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->buf_ = (uint8_t*)data; 17703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->end_ = mem->buf_size_ = data_size; 17803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora DoRemap(idec, mem->buf_ + mem->start_ - old_base); 18003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 1; 18103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 18203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 18303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic void InitMemBuffer(MemBuffer* const mem) { 18403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->mode_ = MEM_MODE_NONE; 185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->buf_ = NULL; 18603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->buf_size_ = 0; 187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->part0_buf_ = NULL; 18803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->part0_size_ = 0; 18903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 19003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 19103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic void ClearMemBuffer(MemBuffer* const mem) { 19203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem); 19303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (mem->mode_ == MEM_MODE_APPEND) { 19403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free(mem->buf_); 19503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free((void*)mem->part0_buf_); 19603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 19703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 19803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 19903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) { 20003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (mem->mode_ == MEM_MODE_NONE) { 20103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->mode_ = expected; // switch to the expected mode 20203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } else if (mem->mode_ != expected) { 20303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 0; // we mixed the modes => error 20403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 20503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->mode_ == expected); // mode is ok 20603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 1; 20703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 20803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 20903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 21003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Macroblock-decoding contexts 21103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 21203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br, 21303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MBContext* const context) { 21403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const VP8BitReader* const br = &dec->br_; 21503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const VP8MB* const left = dec->mb_info_ - 1; 21603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const VP8MB* const info = dec->mb_info_ + dec->mb_x_; 21703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 21803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora context->left_ = *left; 21903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora context->info_ = *info; 22003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora context->br_ = *br; 22103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora context->token_br_ = *token_br; 22203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(context->intra_t_, dec->intra_t_ + 4 * dec->mb_x_, 4); 22303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(context->intra_l_, dec->intra_l_, 4); 22403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 22503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 22603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic void RestoreContext(const MBContext* context, VP8Decoder* const dec, 22703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8BitReader* const token_br) { 22803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8BitReader* const br = &dec->br_; 22903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8MB* const left = dec->mb_info_ - 1; 23003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8MB* const info = dec->mb_info_ + dec->mb_x_; 23103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 23203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora *left = context->left_; 23303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora *info = context->info_; 23403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora *br = context->br_; 23503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora *token_br = context->token_br_; 23603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4); 23703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(dec->intra_l_, context->intra_l_, 4); 23803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 23903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 24003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 24103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { 243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_DATA) { 24488fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora VP8Io* const io = &idec->io_; 24588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora if (io->teardown) { 24688fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora io->teardown(io); 24788fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora } 24888fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora } 24903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->state_ = STATE_ERROR; 25003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return error; 25103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 25203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ChangeState(WebPIDecoder* const idec, DecState new_state, 254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t consumed_bytes) { 255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MemBuffer* const mem = &idec->mem_; 256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = new_state; 257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->start_ += consumed_bytes; 258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(mem->start_ <= mem->end_); 259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->io_.data = mem->buf_ + mem->start_; 260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->io_.data_size = MemDataSize(mem); 261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Headers 264a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { 265a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora MemBuffer* const mem = &idec->mem_; 266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* data = mem->buf_ + mem->start_; 267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t curr_size = MemDataSize(mem); 268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8StatusCode status; 269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPHeaderStructure headers; 270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora headers.data = data; 272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora headers.data_size = curr_size; 273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = WebPParseHeaders(&headers); 274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (status == VP8_STATUS_NOT_ENOUGH_DATA) { 275a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. 276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else if (status != VP8_STATUS_OK) { 277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, status); 278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->chunk_size_ = headers.compressed_size; 281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->is_lossless_ = headers.is_lossless; 282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!idec->is_lossless_) { 283a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Decoder* const dec = VP8New(); 284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) { 285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->dec_ = dec; 288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef WEBP_USE_THREAD 289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->use_threads_ = (idec->params_.options != NULL) && 290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (idec->params_.options->use_threads > 0); 291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#else 292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->use_threads_ = 0; 293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif 294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->alpha_data_ = headers.alpha_data; 295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->alpha_data_size_ = headers.alpha_data_size; 296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset); 297a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 298a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = VP8LNew(); 299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec == NULL) { 300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 301a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 302a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->dec_ = dec; 303a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ChangeState(idec, STATE_VP8L_HEADER, headers.offset); 304a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OK; 306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 308a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { 30903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; 310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const size_t curr_size = MemDataSize(&idec->mem_); 311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint32_t bits; 31203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (curr_size < VP8_FRAME_HEADER_SIZE) { 314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Not enough data bytes to extract VP8 Frame Header. 31503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 31603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8GetInfo(data, curr_size, idec->chunk_size_, NULL, NULL)) { 31803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 31903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 320466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 32103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora bits = data[0] | (data[1] << 8) | (data[2] << 16); 322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; 32303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 32403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->io_.data = data; 325a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->io_.data_size = curr_size; 326a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_VP8_PARTS0; 32703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 32803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 32903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 33003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Partition #0 331a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int CopyParts0Data(WebPIDecoder* const idec) { 332a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8BitReader* const br = &dec->br_; 33403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const size_t psize = br->buf_end_ - br->buf_; 33503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MemBuffer* const mem = &idec->mem_; 336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(!idec->is_lossless_); 337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(mem->part0_buf_ == NULL); 33803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(psize > 0); 339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(psize <= mem->part0_size_); // Format limit: no need for runtime check 34003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (mem->mode_ == MEM_MODE_APPEND) { 34103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // We copy and grab ownership of the partition #0 data. 34203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora uint8_t* const part0_buf = (uint8_t*)malloc(psize); 343a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (part0_buf == NULL) { 34403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 0; 34503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 34603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora memcpy(part0_buf, br->buf_, psize); 34703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->part0_buf_ = part0_buf; 34803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora br->buf_ = part0_buf; 34903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora br->buf_end_ = part0_buf + psize; 35003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } else { 35103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Else: just keep pointers to the partition #0's data in dec_->br_. 35203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem->start_ += psize; 35403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 1; 35503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 35603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 35703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { 358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 35903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8Io* const io = &idec->io_; 36003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const WebPDecParams* const params = &idec->params_; 361466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPDecBuffer* const output = params->output; 36203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 36303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Wait till we have enough data for the whole partition #0 36403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) { 36503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 36603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 36703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 36803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!VP8GetHeaders(dec, io)) { 36903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const VP8StatusCode status = dec->status_; 37003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (status == VP8_STATUS_SUSPENDED || 37103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status == VP8_STATUS_NOT_ENOUGH_DATA) { 37203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // treating NOT_ENOUGH_DATA as SUSPENDED state 37303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 37403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 37503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, status); 37603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 37703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 378466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Allocate/Verify output buffer now 379466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, 380466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora output); 381466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (dec->status_ != VP8_STATUS_OK) { 382466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return IDecError(idec, dec->status_); 38303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 38403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 38503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!CopyParts0Data(idec)) { 38603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY); 38703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 38888fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora 389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Finish setting up the decoding parameters. Will call io->setup(). 390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { 39188fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora return IDecError(idec, dec->status_); 39288fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora } 393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 39488fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora // Note: past this point, teardown() must always be called 39588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora // in case of error. 396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_VP8_DATA; 397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Allocate memory and prepare everything. 398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8InitFrame(dec, io)) { 399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, dec->status_); 400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 40103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 40203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 40303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 40403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Remaining partitions 40503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { 406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 40703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8Io* const io = &idec->io_; 40803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 40903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(dec->ready_); 41003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 41103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { 41203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)]; 41303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (dec->mb_x_ == 0) { 414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8InitScanline(dec); 41503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 41603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora for (; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) { 41703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MBContext context; 41803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora SaveContext(dec, token_br, &context); 41903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 42003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!VP8DecodeMB(dec, token_br)) { 42103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora RestoreContext(&context, dec, token_br); 42203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // We shouldn't fail when MAX_MB data was available 42303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) { 42403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); 42503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 42603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 42703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 42803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8ReconstructBlock(dec); 42903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Store data and save block's filtering params 43003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StoreBlock(dec); 43103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 43203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Release buffer only if there is only one partition 43303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (dec->num_parts_ == 1) { 43403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; 43503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(idec->mem_.start_ <= idec->mem_.end_); 43603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 43703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8ProcessRow(dec, io)) { 43903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_USER_ABORT); 44003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 44103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora dec->mb_x_ = 0; 44203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Synchronize the thread and check for errors. 444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8ExitCritical(dec, io)) { 445a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, VP8_STATUS_USER_ABORT); 44603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 44703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora dec->ready_ = 0; 44803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->state_ = STATE_DONE; 44903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 45003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 45103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 45203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 453a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) { 454a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { 455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, status); 458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { 461a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* const io = &idec->io_; 462a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecParams* const params = &idec->params_; 464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecBuffer* const output = params->output; 465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t curr_size = MemDataSize(&idec->mem_); 466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(idec->is_lossless_); 467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Wait until there's enough data for decoding header. 469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (curr_size < (idec->chunk_size_ >> 3)) { 470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LDecodeHeader(dec, io)) { 473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ErrorStatusLossless(idec, dec->status_); 474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Allocate/verify output buffer now. 476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, 477a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora output); 478a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->status_ != VP8_STATUS_OK) { 479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, dec->status_); 480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_VP8L_DATA; 483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OK; 484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { 487a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 488a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const size_t curr_size = MemDataSize(&idec->mem_); 489a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(idec->is_lossless_); 490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // At present Lossless decoder can't decode image incrementally. So wait till 492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // all the image data is aggregated before image can be decoded. 493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (curr_size < idec->chunk_size_) { 494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LDecodeImage(dec)) { 498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ErrorStatusLossless(idec, dec->status_); 499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_DONE; 502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OK; 504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 50603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Main decoding loop 50703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode IDecode(WebPIDecoder* idec) { 50803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status = VP8_STATUS_SUSPENDED; 50903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 510a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_PRE_VP8) { 511a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeWebPHeaders(idec); 512a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->dec_ == NULL) { 514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. 515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 51603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_FRAME_HEADER) { 518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8FrameHeader(idec); 519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_PARTS0) { 52103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = DecodePartition0(idec); 52203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 523a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_DATA) { 524466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = DecodeRemaining(idec); 52503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 526a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8L_HEADER) { 527a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8LHeader(idec); 528a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8L_DATA) { 530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8LData(idec); 531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 53203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 53303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 53403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 53503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 53603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Public functions 53703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { 539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec)); 540466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (idec == NULL) { 541466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 542466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 54303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 544a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_PRE_VP8; 545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->chunk_size_ = 0; 54603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 54703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora InitMemBuffer(&idec->mem_); 548466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&idec->output_); 54903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8InitIo(&idec->io_); 550466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 551466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(&idec->params_); 552466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->params_.output = output_buffer ? output_buffer : &idec->output_; 553466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. 554466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 555466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return idec; 556466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 557466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 558a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, 559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecoderConfig* config) { 560466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPIDecoder* idec; 561466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 562466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Parse the bitstream's features, if requested: 563466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (data != NULL && data_size > 0 && config != NULL) { 564466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { 565466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 566466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 567466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 568466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Create an instance of the incremental decoder 569466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec = WebPINewDecoder(config ? &config->output : NULL); 570a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) { 571466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 572466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 573466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Finish initialization 574466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (config != NULL) { 575466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->params_.options = &config->options; 576466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 57703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 57803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 57903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid WebPIDelete(WebPIDecoder* idec) { 581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return; 582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->dec_ != NULL) { 583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!idec->is_lossless_) { 584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Delete(idec->dec_); 585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDelete(idec->dec_); 587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 588a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 58903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora ClearMemBuffer(&idec->mem_); 590466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPFreeDecBuffer(&idec->output_); 59103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free(idec); 59203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 59303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 59403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 595466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Wrapper toward WebPINewDecoder 596466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 59703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas AroraWebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, 598a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t output_buffer_size, int output_stride) { 59903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPIDecoder* idec; 600466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (mode >= MODE_YUV) return NULL; 601466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec = WebPINewDecoder(NULL); 602a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return NULL; 603466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.colorspace = mode; 604466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.is_external_memory = 1; 605466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.rgba = output_buffer; 606466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.stride = output_stride; 607466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.size = output_buffer_size; 60803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 60903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 61003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, 612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* u, size_t u_size, int u_stride, 613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* v, size_t v_size, int v_stride, 614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* a, size_t a_size, int a_stride) { 615466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPIDecoder* const idec = WebPINewDecoder(NULL); 616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return NULL; 617a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; 618466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.is_external_memory = 1; 619466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y = luma; 620466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y_stride = luma_stride; 621466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y_size = luma_size; 622466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u = u; 623466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u_stride = u_stride; 624466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u_size = u_size; 625466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v = v; 626466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v_stride = v_stride; 627466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v_size = v_size; 628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a = a; 629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a_stride = a_stride; 630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a_size = a_size; 63103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 63203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 63303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, 635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* u, size_t u_size, int u_stride, 636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* v, size_t v_size, int v_stride) { 637a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return WebPINewYUVA(luma, luma_size, luma_stride, 638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u, u_size, u_stride, 639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v, v_size, v_stride, 640a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora NULL, 0, 0); 641a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 64303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 64403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 64503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { 64603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(idec); 64703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec->state_ == STATE_ERROR) { 64803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_BITSTREAM_ERROR; 64903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 65003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec->state_ == STATE_DONE) { 65103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 65203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 65303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 65403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 65503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 656a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8StatusCode WebPIAppend(WebPIDecoder* idec, 657a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* data, size_t data_size) { 65803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status; 65903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec == NULL || data == NULL) { 66003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 66103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 66203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = IDecCheckStatus(idec); 66303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (status != VP8_STATUS_SUSPENDED) { 66403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 66503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 66603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 66703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { 66803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 66903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 67003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Append data to memory buffer 67103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!AppendToMemBuffer(idec, data, data_size)) { 67203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 67303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 67403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecode(idec); 67503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 67603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8StatusCode WebPIUpdate(WebPIDecoder* idec, 678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* data, size_t data_size) { 67903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status; 68003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec == NULL || data == NULL) { 68103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 68203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 68303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = IDecCheckStatus(idec); 68403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (status != VP8_STATUS_SUSPENDED) { 68503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 68603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 68703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 68803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { 68903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 69003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 69103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Make the memory buffer point to the new buffer 69203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!RemapMemBuffer(idec, data, data_size)) { 69303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 69403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 69503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecode(idec); 69603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 69703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 69803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 69903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 700466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { 701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL || idec->dec_ == NULL) { 702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return NULL; 703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ <= STATE_VP8_PARTS0) { 705466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 706466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 707466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return idec->params_.output; 708466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 709466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 710a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraconst WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, 711a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* left, int* top, 712a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* width, int* height) { 713466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 714a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (left != NULL) *left = 0; 715a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top != NULL) *top = 0; 716466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // TODO(skal): later include handling of rotations. 717466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src) { 718a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 719a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = idec->params_.last_y; 720466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } else { 721a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = 0; 722a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = 0; 723466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 724466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src; 725466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 726466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 727a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorauint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, 72803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora int* width, int* height, int* stride) { 729466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 730a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (src == NULL) return NULL; 731466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace >= MODE_YUV) { 73203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 73303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 73403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 735a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 736a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 737a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = src->height; 738a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (stride != NULL) *stride = src->u.RGBA.stride; 73903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 740466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src->u.RGBA.rgba; 74103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 74203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 743a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorauint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, 744a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t** u, uint8_t** v, uint8_t** a, 745a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* width, int* height, 746a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* stride, int* uv_stride, int* a_stride) { 747466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 748a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (src == NULL) return NULL; 749466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace < MODE_YUV) { 75003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 75103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 75203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 753a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 754a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (u != NULL) *u = src->u.YUVA.u; 755a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (v != NULL) *v = src->u.YUVA.v; 756a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (a != NULL) *a = src->u.YUVA.a; 757a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 758a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = src->height; 759a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (stride != NULL) *stride = src->u.YUVA.y_stride; 760a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; 761a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; 762466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 763466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src->u.YUVA.y; 76403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 76503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7663417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Aroraint WebPISetIOHooks(WebPIDecoder* const idec, 7673417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoPutHook put, 7683417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoSetupHook setup, 7693417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoTeardownHook teardown, 7703417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora void* user_data) { 771a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL || idec->state_ > STATE_PRE_VP8) { 7723417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora return 0; 7733417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora } 7743417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 7753417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.put = put; 7763417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.setup = setup; 7773417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.teardown = teardown; 7783417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.opaque = user_data; 7793417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 7803417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora return 1; 7813417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora} 7823417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 78303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 78403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} // extern "C" 78503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#endif 786