15a50414796e9a458925c7a13a15055d02406bf43Vikas 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 165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./webpi.h" 175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./vp8i.h" 185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../utils/utils.h" 1903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 2003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 2103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroraextern "C" { 2203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora#endif 2303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// In append mode, buffer allocations increase as multiples of this value. 255a50414796e9a458925c7a13a15055d02406bf43Vikas 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. 345a50414796e9a458925c7a13a15055d02406bf43Vikas Aroratypedef enum { 355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_PRE_VP8, // All data before that of the first VP8 chunk. 365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk). 375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_VP8_PARTS0, 385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_VP8_DATA, 395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_VP8L_HEADER, 405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_VP8L_DATA, 415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_DONE, 425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora STATE_ERROR 4303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} DecState; 4403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 4503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Operating state for the MemBuffer 465a50414796e9a458925c7a13a15055d02406bf43Vikas Aroratypedef enum { 475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora MEM_MODE_NONE = 0, 485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora MEM_MODE_APPEND, 495a50414796e9a458925c7a13a15055d02406bf43Vikas 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 555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t start_; // start location of the data to be decoded 565a50414796e9a458925c7a13a15055d02406bf43Vikas 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 675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int is_lossless_; // for down-casting 'dec_'. 685a50414796e9a458925c7a13a15055d02406bf43Vikas 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) 735a50414796e9a458925c7a13a15055d02406bf43Vikas 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 895a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) { 905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (br->buf_ != NULL) { 915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora br->buf_ += offset; 925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora br->buf_end_ += offset; 935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 9503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 965a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) { 9703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return (mem->end_ - mem->start_); 9803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 9903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 1005a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { 1015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora MemBuffer* const mem = &idec->mem_; 1025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t* const new_base = mem->buf_ + mem->start_; 1035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // note: for VP8, setting up idec->io_ is only really needed at the beginning 1045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // of the decoding, till partition #0 is complete. 1055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->io_.data = new_base; 1065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->io_.data_size = MemDataSize(mem); 1075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->dec_ != NULL) { 1095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!idec->is_lossless_) { 1105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 1115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int last_part = dec->num_parts_ - 1; 1125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (offset != 0) { 1135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int p; 1145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (p = 0; p <= last_part; ++p) { 1155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora RemapBitReader(dec->parts_ + p, offset); 1165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Remap partition #0 data pointer to new offset, but only in MAP 1185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // mode (in APPEND mode, partition #0 is copied into a fixed memory). 1195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (mem->mode_ == MEM_MODE_MAP) { 1205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora RemapBitReader(&dec->br_, offset); 1215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(last_part >= 0); 1245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_; 1255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { // Resize lossless bitreader 1265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 1275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem)); 1285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 1315a50414796e9a458925c7a13a15055d02406bf43Vikas 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_; 1375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t* const old_base = mem->buf_ + mem->start_; 13803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->mode_ == MEM_MODE_APPEND); 1395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (data_size > MAX_CHUNK_PAYLOAD) { 1405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // security safeguard: trying to allocate more than what the format 1415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // allows for a chunk should be considered a smoke smell. 1425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 1435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 14403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 14503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory 1465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t current_size = MemDataSize(mem); 1475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t new_size = (uint64_t)current_size + data_size; 1485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); 1495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* const new_buf = 1505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); 1515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (new_buf == NULL) return 0; 1525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora memcpy(new_buf, old_base, current_size); 15303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora free(mem->buf_); 15403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->buf_ = new_buf; 1555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem->buf_size_ = (size_t)extra_size; 15603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->start_ = 0; 1575a50414796e9a458925c7a13a15055d02406bf43Vikas 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 1645a50414796e9a458925c7a13a15055d02406bf43Vikas 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_; 1715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t* const old_base = mem->buf_ + mem->start_; 17203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(mem->mode_ == MEM_MODE_MAP); 17303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 1745a50414796e9a458925c7a13a15055d02406bf43Vikas 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 1795a50414796e9a458925c7a13a15055d02406bf43Vikas 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; 1855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem->buf_ = NULL; 18603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora mem->buf_size_ = 0; 1875a50414796e9a458925c7a13a15055d02406bf43Vikas 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 2425a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { 2435a50414796e9a458925c7a13a15055d02406bf43Vikas 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 2535a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ChangeState(WebPIDecoder* const idec, DecState new_state, 2545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t consumed_bytes) { 2555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora MemBuffer* const mem = &idec->mem_; 2565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = new_state; 2575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem->start_ += consumed_bytes; 2585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(mem->start_ <= mem->end_); 2595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->io_.data = mem->buf_ + mem->start_; 2605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->io_.data_size = MemDataSize(mem); 2615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 2625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Headers 2645a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) { 2655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora MemBuffer* const mem = &idec->mem_; 2665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t* data = mem->buf_ + mem->start_; 2675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t curr_size = MemDataSize(mem); 2685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8StatusCode status; 2695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPHeaderStructure headers; 2705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora headers.data = data; 2725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora headers.data_size = curr_size; 2735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora status = WebPParseHeaders(&headers); 2745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (status == VP8_STATUS_NOT_ENOUGH_DATA) { 2755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet. 2765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (status != VP8_STATUS_OK) { 2775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return IDecError(idec, status); 2785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->chunk_size_ = headers.compressed_size; 2815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->is_lossless_ = headers.is_lossless; 2825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!idec->is_lossless_) { 2835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8Decoder* const dec = VP8New(); 2845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (dec == NULL) { 2855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 2865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->dec_ = dec; 2885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#ifdef WEBP_USE_THREAD 2895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->use_threads_ = (idec->params_.options != NULL) && 2905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (idec->params_.options->use_threads > 0); 2915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#else 2925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->use_threads_ = 0; 2935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif 2945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->alpha_data_ = headers.alpha_data; 2955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->alpha_data_size_ = headers.alpha_data_size; 2965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset); 2975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 2985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LDecoder* const dec = VP8LNew(); 2995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (dec == NULL) { 3005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_OUT_OF_MEMORY; 3015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->dec_ = dec; 3035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ChangeState(idec, STATE_VP8L_HEADER, headers.offset); 3045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_OK; 3065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 3075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3085a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) { 30903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_; 3105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t curr_size = MemDataSize(&idec->mem_); 3115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t bits; 31203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 3135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (curr_size < VP8_FRAME_HEADER_SIZE) { 3145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Not enough data bytes to extract VP8 Frame Header. 31503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_SUSPENDED; 31603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 3175a50414796e9a458925c7a13a15055d02406bf43Vikas 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); 3225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE; 32303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 32403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora idec->io_.data = data; 3255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->io_.data_size = curr_size; 3265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = STATE_VP8_PARTS0; 32703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 32803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 32903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 33003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Partition #0 3315a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int CopyParts0Data(WebPIDecoder* const idec) { 3325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8Decoder* const dec = (VP8Decoder*)idec->dec_; 3335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8BitReader* const br = &dec->br_; 33403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora const size_t psize = br->buf_end_ - br->buf_; 33503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora MemBuffer* const mem = &idec->mem_; 3365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(!idec->is_lossless_); 3375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(mem->part0_buf_ == NULL); 33803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora assert(psize > 0); 3395a50414796e9a458925c7a13a15055d02406bf43Vikas 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); 3435a50414796e9a458925c7a13a15055d02406bf43Vikas 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 } 3535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem->start_ += psize; 35403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return 1; 35503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 35603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 35703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode DecodePartition0(WebPIDecoder* const idec) { 3585a50414796e9a458925c7a13a15055d02406bf43Vikas 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 3895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Finish setting up the decoding parameters. Will call io->setup(). 3905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) { 39188fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora return IDecError(idec, dec->status_); 39288fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora } 3935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 39488fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora // Note: past this point, teardown() must always be called 39588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora // in case of error. 3965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = STATE_VP8_DATA; 3975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Allocate memory and prepare everything. 3985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8InitFrame(dec, io)) { 3995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return IDecError(idec, dec->status_); 4005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 40103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return VP8_STATUS_OK; 40203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 40303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 40403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Remaining partitions 40503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { 4065a50414796e9a458925c7a13a15055d02406bf43Vikas 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) { 4145a50414796e9a458925c7a13a15055d02406bf43Vikas 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 } 4385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8ProcessRow(dec, io)) { 43903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return IDecError(idec, VP8_STATUS_USER_ABORT); 44003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 44103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora dec->mb_x_ = 0; 44203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 4435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Synchronize the thread and check for errors. 4445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8ExitCritical(dec, io)) { 4455a50414796e9a458925c7a13a15055d02406bf43Vikas 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 4535a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) { 4545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) { 4555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_SUSPENDED; 4565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return IDecError(idec, status); 4585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 4595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4605a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) { 4615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8Io* const io = &idec->io_; 4625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 4635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPDecParams* const params = &idec->params_; 4645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPDecBuffer* const output = params->output; 4655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t curr_size = MemDataSize(&idec->mem_); 4665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(idec->is_lossless_); 4675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Wait until there's enough data for decoding header. 4695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (curr_size < (idec->chunk_size_ >> 3)) { 4705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_SUSPENDED; 4715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LDecodeHeader(dec, io)) { 4735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ErrorStatusLossless(idec, dec->status_); 4745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Allocate/verify output buffer now. 4765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options, 4775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora output); 4785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (dec->status_ != VP8_STATUS_OK) { 4795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return IDecError(idec, dec->status_); 4805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = STATE_VP8L_DATA; 4835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_OK; 4845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 4855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4865a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) { 4875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_; 4885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t curr_size = MemDataSize(&idec->mem_); 4895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(idec->is_lossless_); 4905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // At present Lossless decoder can't decode image incrementally. So wait till 4925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // all the image data is aggregated before image can be decoded. 4935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (curr_size < idec->chunk_size_) { 4945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_SUSPENDED; 4955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LDecodeImage(dec)) { 4985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ErrorStatusLossless(idec, dec->status_); 4995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = STATE_DONE; 5025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_OK; 5045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 5055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 50603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora // Main decoding loop 50703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arorastatic VP8StatusCode IDecode(WebPIDecoder* idec) { 50803d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora VP8StatusCode status = VP8_STATUS_SUSPENDED; 50903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 5105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_PRE_VP8) { 5115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora status = DecodeWebPHeaders(idec); 5125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 5135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->dec_ == NULL) { 5145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. 5155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 51603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 5175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_VP8_FRAME_HEADER) { 5185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora status = DecodeVP8FrameHeader(idec); 5195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_VP8_PARTS0) { 52103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora status = DecodePartition0(idec); 52203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 5235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_VP8_DATA) { 524466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora status = DecodeRemaining(idec); 52503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 5265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_VP8L_HEADER) { 5275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora status = DecodeVP8LHeader(idec); 5285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ == STATE_VP8L_DATA) { 5305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora status = DecodeVP8LData(idec); 5315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 53203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return status; 53303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 53403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 53503d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora//------------------------------------------------------------------------------ 53603d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora// Public functions 53703d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 5385a50414796e9a458925c7a13a15055d02406bf43Vikas AroraWebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) { 5395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec)); 540466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (idec == NULL) { 541466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 542466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 54303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 5445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->state_ = STATE_PRE_VP8; 5455a50414796e9a458925c7a13a15055d02406bf43Vikas 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 5585a50414796e9a458925c7a13a15055d02406bf43Vikas AroraWebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, 5595a50414796e9a458925c7a13a15055d02406bf43Vikas 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); 5705a50414796e9a458925c7a13a15055d02406bf43Vikas 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 5805a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid WebPIDelete(WebPIDecoder* idec) { 5815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec == NULL) return; 5825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->dec_ != NULL) { 5835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!idec->is_lossless_) { 5845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8Delete(idec->dec_); 5855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 5865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LDelete(idec->dec_); 5875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5885a50414796e9a458925c7a13a15055d02406bf43Vikas 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, 5985a50414796e9a458925c7a13a15055d02406bf43Vikas 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); 6025a50414796e9a458925c7a13a15055d02406bf43Vikas 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 6115a50414796e9a458925c7a13a15055d02406bf43Vikas AroraWebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride, 6125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* u, size_t u_size, int u_stride, 6135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* v, size_t v_size, int v_stride, 6145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* a, size_t a_size, int a_stride) { 615466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPIDecoder* const idec = WebPINewDecoder(NULL); 6165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec == NULL) return NULL; 6175a50414796e9a458925c7a13a15055d02406bf43Vikas 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; 6285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->output_.u.YUVA.a = a; 6295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->output_.u.YUVA.a_stride = a_stride; 6305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora idec->output_.u.YUVA.a_size = a_size; 63103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return idec; 63203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 63303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 6345a50414796e9a458925c7a13a15055d02406bf43Vikas AroraWebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride, 6355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* u, size_t u_size, int u_stride, 6365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* v, size_t v_size, int v_stride) { 6375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return WebPINewYUVA(luma, luma_size, luma_stride, 6385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora u, u_size, u_stride, 6395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora v, v_size, v_stride, 6405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora NULL, 0, 0); 6415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 6425a50414796e9a458925c7a13a15055d02406bf43Vikas 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 6565a50414796e9a458925c7a13a15055d02406bf43Vikas AroraVP8StatusCode WebPIAppend(WebPIDecoder* idec, 6575a50414796e9a458925c7a13a15055d02406bf43Vikas 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 6775a50414796e9a458925c7a13a15055d02406bf43Vikas AroraVP8StatusCode WebPIUpdate(WebPIDecoder* idec, 6785a50414796e9a458925c7a13a15055d02406bf43Vikas 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) { 7015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec == NULL || idec->dec_ == NULL) { 7025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return NULL; 7035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (idec->state_ <= STATE_VP8_PARTS0) { 705466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 706466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 707466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return idec->params_.output; 708466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 709466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 7105a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraconst WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec, 7115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int* left, int* top, 7125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int* width, int* height) { 713466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 7145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (left != NULL) *left = 0; 7155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (top != NULL) *top = 0; 716466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora // TODO(skal): later include handling of rotations. 717466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src) { 7185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (width != NULL) *width = src->width; 7195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (height != NULL) *height = idec->params_.last_y; 720466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } else { 7215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (width != NULL) *width = 0; 7225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (height != NULL) *height = 0; 723466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 724466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src; 725466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 726466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 7275a50414796e9a458925c7a13a15055d02406bf43Vikas 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); 7305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (src == NULL) return NULL; 731466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace >= MODE_YUV) { 73203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 73303d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 73403d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 7365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (width != NULL) *width = src->width; 7375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (height != NULL) *height = src->height; 7385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (stride != NULL) *stride = src->u.RGBA.stride; 73903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 740466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return src->u.RGBA.rgba; 74103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora} 74203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7435a50414796e9a458925c7a13a15055d02406bf43Vikas Arorauint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y, 7445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t** u, uint8_t** v, uint8_t** a, 7455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int* width, int* height, 7465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int* stride, int* uv_stride, int* a_stride) { 747466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const WebPDecBuffer* const src = GetOutputBuffer(idec); 7485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (src == NULL) return NULL; 749466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (src->colorspace < MODE_YUV) { 75003d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora return NULL; 75103d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora } 75203d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Arora 7535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (last_y != NULL) *last_y = idec->params_.last_y; 7545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (u != NULL) *u = src->u.YUVA.u; 7555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (v != NULL) *v = src->u.YUVA.v; 7565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (a != NULL) *a = src->u.YUVA.a; 7575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (width != NULL) *width = src->width; 7585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (height != NULL) *height = src->height; 7595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (stride != NULL) *stride = src->u.YUVA.y_stride; 7605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride; 7615a50414796e9a458925c7a13a15055d02406bf43Vikas 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) { 7715a50414796e9a458925c7a13a15055d02406bf43Vikas 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