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 } 4281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Reconstruct and emit samples. 42903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8ReconstructBlock(dec); 43003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 43103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Release buffer only if there is only one partition 43203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (dec->num_parts_ == 1) { 43303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_; 43403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(idec->mem_.start_ <= idec->mem_.end_); 43503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 43603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8ProcessRow(dec, io)) { 43803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_USER_ABORT); 43903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 44003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora dec->mb_x_ = 0; 44103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Synchronize the thread and check for errors. 443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8ExitCritical(dec, io)) { 444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, VP8_STATUS_USER_ABORT); 44503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 44603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora dec->ready_ = 0; 44703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->state_ = STATE_DONE; 44803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 44903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 45003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 45103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 452a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) { 453a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { 454a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 455a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 456a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, status); 457a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 458a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 459a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { 460a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Io* const io = &idec->io_; 461a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 462a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const WebPDecParams* const params = &idec->params_; 463a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecBuffer* const output = params->output; 464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t curr_size = MemDataSize(&idec->mem_); 465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(idec->is_lossless_); 466a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 467a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Wait until there's enough data for decoding header. 468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (curr_size < (idec->chunk_size_ >> 3)) { 469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LDecodeHeader(dec, io)) { 472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ErrorStatusLossless(idec, dec->status_); 473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Allocate/verify output buffer now. 475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, 476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora output); 477a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (dec->status_ != VP8_STATUS_OK) { 478a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return IDecError(idec, dec->status_); 479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_VP8L_DATA; 482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OK; 483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { 486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 487a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const size_t curr_size = MemDataSize(&idec->mem_); 488a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert(idec->is_lossless_); 489a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // At present Lossless decoder can't decode image incrementally. So wait till 491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // all the image data is aggregated before image can be decoded. 492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (curr_size < idec->chunk_size_) { 493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; 494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!VP8LDecodeImage(dec)) { 497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return ErrorStatusLossless(idec, dec->status_); 498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_DONE; 501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_OK; 503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 50503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Main decoding loop 50603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode IDecode(WebPIDecoder* idec) { 50703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status = VP8_STATUS_SUSPENDED; 50803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 509a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_PRE_VP8) { 510a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeWebPHeaders(idec); 511a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 512a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->dec_ == NULL) { 513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. 514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 51503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_FRAME_HEADER) { 517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8FrameHeader(idec); 518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_PARTS0) { 52003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = DecodePartition0(idec); 52103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8_DATA) { 523466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = DecodeRemaining(idec); 52403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 525a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8L_HEADER) { 526a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8LHeader(idec); 527a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 528a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ == STATE_VP8L_DATA) { 529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora status = DecodeVP8LData(idec); 530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 53103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 53203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 53303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 53403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 53503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Public functions 53603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { 538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec)); 539466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (idec == NULL) { 540466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 541466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 54203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 543a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->state_ = STATE_PRE_VP8; 544a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->chunk_size_ = 0; 54503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 54603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora InitMemBuffer(&idec->mem_); 547466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitDecBuffer(&idec->output_); 54803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8InitIo(&idec->io_); 549466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 550466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPResetDecParams(&idec->params_); 551466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->params_.output = output_buffer ? output_buffer : &idec->output_; 552466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions. 553466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 554466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return idec; 555466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 556466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 557a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, 558a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPDecoderConfig* config) { 559466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPIDecoder* idec; 560466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 561466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Parse the bitstream's features, if requested: 562466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (data != NULL && data_size > 0 && config != NULL) { 563466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) { 564466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 565466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 566466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 567466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Create an instance of the incremental decoder 568466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec = WebPINewDecoder(config ? &config->output : NULL); 569a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) { 570466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 571466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 572466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // Finish initialization 573466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (config != NULL) { 574466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->params_.options = &config->options; 575466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 57603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 57703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 57803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 579a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid WebPIDelete(WebPIDecoder* idec) { 580a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return; 581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->dec_ != NULL) { 582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!idec->is_lossless_) { 583a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Delete(idec->dec_); 584a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8LDelete(idec->dec_); 586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 58803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora ClearMemBuffer(&idec->mem_); 589466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPFreeDecBuffer(&idec->output_); 59003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free(idec); 59103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 59203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 59303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 594466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Wrapper toward WebPINewDecoder 595466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 59603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas AroraWebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, 597a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora size_t output_buffer_size, int output_stride) { 5981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int is_external_memory = (output_buffer != NULL); 59903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora WebPIDecoder* idec; 6001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 601466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (mode >= MODE_YUV) return NULL; 6021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!is_external_memory) { // Overwrite parameters to sane values. 6031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora output_buffer_size = 0; 6041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora output_stride = 0; 6051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { // A buffer was passed. Validate the other params. 6061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (output_stride == 0 || output_buffer_size == 0) { 6071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return NULL; // invalid parameter. 6081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 610466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec = WebPINewDecoder(NULL); 611a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return NULL; 612466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.colorspace = mode; 6131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora idec->output_.is_external_memory = is_external_memory; 614466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.rgba = output_buffer; 615466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.stride = output_stride; 616466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.RGBA.size = output_buffer_size; 61703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 61803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 61903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 620a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, 621a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* u, size_t u_size, int u_stride, 622a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* v, size_t v_size, int v_stride, 623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* a, size_t a_size, int a_stride) { 6241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int is_external_memory = (luma != NULL); 6251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora WebPIDecoder* idec; 6261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora WEBP_CSP_MODE colorspace; 6271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!is_external_memory) { // Overwrite parameters to sane values. 6291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora luma_size = u_size = v_size = a_size = 0; 6301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora luma_stride = u_stride = v_stride = a_stride = 0; 6311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora u = v = a = NULL; 6321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora colorspace = MODE_YUVA; 6331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { // A luma buffer was passed. Validate the other parameters. 6341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (u == NULL || v == NULL) return NULL; 6351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (luma_size == 0 || u_size == 0 || v_size == 0) return NULL; 6361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (luma_stride == 0 || u_stride == 0 || v_stride == 0) return NULL; 6371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (a != NULL) { 6381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (a_size == 0 || a_stride == 0) return NULL; 6391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA; 6411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 6421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora idec = WebPINewDecoder(NULL); 644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL) return NULL; 6451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 6461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora idec->output_.colorspace = colorspace; 6471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora idec->output_.is_external_memory = is_external_memory; 648466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y = luma; 649466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y_stride = luma_stride; 650466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.y_size = luma_size; 651466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u = u; 652466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u_stride = u_stride; 653466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.u_size = u_size; 654466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v = v; 655466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v_stride = v_stride; 656466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora idec->output_.u.YUVA.v_size = v_size; 657a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a = a; 658a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a_stride = a_stride; 659a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora idec->output_.u.YUVA.a_size = a_size; 66003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 66103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 66203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 663a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraWebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, 664a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* u, size_t u_size, int u_stride, 665a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* v, size_t v_size, int v_stride) { 666a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return WebPINewYUVA(luma, luma_size, luma_stride, 667a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora u, u_size, u_stride, 668a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora v, v_size, v_stride, 669a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora NULL, 0, 0); 670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 671a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 67203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 67303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 67403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) { 67503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(idec); 67603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec->state_ == STATE_ERROR) { 67703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_BITSTREAM_ERROR; 67803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 67903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec->state_ == STATE_DONE) { 68003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 68103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 68203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 68303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 68403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8StatusCode WebPIAppend(WebPIDecoder* idec, 686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* data, size_t data_size) { 68703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status; 68803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec == NULL || data == NULL) { 68903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 69003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 69103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = IDecCheckStatus(idec); 69203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (status != VP8_STATUS_SUSPENDED) { 69303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 69403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 69503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 69603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) { 69703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 69803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 69903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Append data to memory buffer 70003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!AppendToMemBuffer(idec, data, data_size)) { 70103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 70203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 70303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecode(idec); 70403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 70503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas AroraVP8StatusCode WebPIUpdate(WebPIDecoder* idec, 707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* data, size_t data_size) { 70803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status; 70903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (idec == NULL || data == NULL) { 71003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 71103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 71203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = IDecCheckStatus(idec); 71303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (status != VP8_STATUS_SUSPENDED) { 71403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 71503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 71603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Check mixed calls between RemapMemBuffer and AppendToMemBuffer. 71703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) { 71803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 71903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 72003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Make the memory buffer point to the new buffer 72103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (!RemapMemBuffer(idec, data, data_size)) { 72203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_INVALID_PARAM; 72303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 72403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecode(idec); 72503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 72603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 72703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 72803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 729466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) { 730a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL || idec->dec_ == NULL) { 731a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return NULL; 732a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 733a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec->state_ <= STATE_VP8_PARTS0) { 734466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 735466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 736466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return idec->params_.output; 737466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 738466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 739a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraconst WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, 740a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* left, int* top, 741a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* width, int* height) { 742466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 743a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (left != NULL) *left = 0; 744a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (top != NULL) *top = 0; 745466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // TODO(skal): later include handling of rotations. 746466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src) { 747a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 748a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = idec->params_.last_y; 749466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } else { 750a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = 0; 751a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = 0; 752466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 753466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src; 754466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 755466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 756a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorauint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y, 75703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora int* width, int* height, int* stride) { 758466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 759a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (src == NULL) return NULL; 760466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace >= MODE_YUV) { 76103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 76203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 76303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 764a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 765a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 766a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = src->height; 767a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (stride != NULL) *stride = src->u.RGBA.stride; 76803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 769466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src->u.RGBA.rgba; 77003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 77103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 772a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorauint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, 773a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t** u, uint8_t** v, uint8_t** a, 774a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* width, int* height, 775a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int* stride, int* uv_stride, int* a_stride) { 776466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 777a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (src == NULL) return NULL; 778466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace < MODE_YUV) { 77903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 78003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 78103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 782a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 783a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (u != NULL) *u = src->u.YUVA.u; 784a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (v != NULL) *v = src->u.YUVA.v; 785a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (a != NULL) *a = src->u.YUVA.a; 786a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (width != NULL) *width = src->width; 787a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (height != NULL) *height = src->height; 788a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (stride != NULL) *stride = src->u.YUVA.y_stride; 789a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; 790a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride; 791466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 792466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src->u.YUVA.y; 79303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 79403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7953417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Aroraint WebPISetIOHooks(WebPIDecoder* const idec, 7963417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoPutHook put, 7973417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoSetupHook setup, 7983417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora VP8IoTeardownHook teardown, 7993417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora void* user_data) { 800a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (idec == NULL || idec->state_ > STATE_PRE_VP8) { 8013417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora return 0; 8023417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora } 8033417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 8043417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.put = put; 8053417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.setup = setup; 8063417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.teardown = teardown; 8073417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora idec->io_.opaque = user_data; 8083417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 8093417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora return 1; 8103417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora} 8113417a639b7b2a482a76019e987c9cfb5045e1ceeVikas Arora 81203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 81303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} // extern "C" 81403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#endif 815