Path: blob/master/3rdparty/libwebp/src/dec/vp8_dec.c
16358 views
// Copyright 2010 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// main entry for the decoder10//11// Author: Skal ([email protected])1213#include <stdlib.h>1415#include "src/dec/alphai_dec.h"16#include "src/dec/vp8i_dec.h"17#include "src/dec/vp8li_dec.h"18#include "src/dec/webpi_dec.h"19#include "src/utils/bit_reader_inl_utils.h"20#include "src/utils/utils.h"2122//------------------------------------------------------------------------------2324int WebPGetDecoderVersion(void) {25return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;26}2728//------------------------------------------------------------------------------29// Signature and pointer-to-function for GetCoeffs() variants below.3031typedef int (*GetCoeffsFunc)(VP8BitReader* const br,32const VP8BandProbas* const prob[],33int ctx, const quant_t dq, int n, int16_t* out);34static volatile GetCoeffsFunc GetCoeffs = NULL;3536static void InitGetCoeffs(void);3738//------------------------------------------------------------------------------39// VP8Decoder4041static void SetOk(VP8Decoder* const dec) {42dec->status_ = VP8_STATUS_OK;43dec->error_msg_ = "OK";44}4546int VP8InitIoInternal(VP8Io* const io, int version) {47if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {48return 0; // mismatch error49}50if (io != NULL) {51memset(io, 0, sizeof(*io));52}53return 1;54}5556VP8Decoder* VP8New(void) {57VP8Decoder* const dec = (VP8Decoder*)WebPSafeCalloc(1ULL, sizeof(*dec));58if (dec != NULL) {59SetOk(dec);60WebPGetWorkerInterface()->Init(&dec->worker_);61dec->ready_ = 0;62dec->num_parts_minus_one_ = 0;63InitGetCoeffs();64}65return dec;66}6768VP8StatusCode VP8Status(VP8Decoder* const dec) {69if (!dec) return VP8_STATUS_INVALID_PARAM;70return dec->status_;71}7273const char* VP8StatusMessage(VP8Decoder* const dec) {74if (dec == NULL) return "no object";75if (!dec->error_msg_) return "OK";76return dec->error_msg_;77}7879void VP8Delete(VP8Decoder* const dec) {80if (dec != NULL) {81VP8Clear(dec);82WebPSafeFree(dec);83}84}8586int VP8SetError(VP8Decoder* const dec,87VP8StatusCode error, const char* const msg) {88// The oldest error reported takes precedence over the new one.89if (dec->status_ == VP8_STATUS_OK) {90dec->status_ = error;91dec->error_msg_ = msg;92dec->ready_ = 0;93}94return 0;95}9697//------------------------------------------------------------------------------9899int VP8CheckSignature(const uint8_t* const data, size_t data_size) {100return (data_size >= 3 &&101data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);102}103104int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,105int* const width, int* const height) {106if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {107return 0; // not enough data108}109// check signature110if (!VP8CheckSignature(data + 3, data_size - 3)) {111return 0; // Wrong signature.112} else {113const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);114const int key_frame = !(bits & 1);115const int w = ((data[7] << 8) | data[6]) & 0x3fff;116const int h = ((data[9] << 8) | data[8]) & 0x3fff;117118if (!key_frame) { // Not a keyframe.119return 0;120}121122if (((bits >> 1) & 7) > 3) {123return 0; // unknown profile124}125if (!((bits >> 4) & 1)) {126return 0; // first frame is invisible!127}128if (((bits >> 5)) >= chunk_size) { // partition_length129return 0; // inconsistent size information.130}131if (w == 0 || h == 0) {132return 0; // We don't support both width and height to be zero.133}134135if (width) {136*width = w;137}138if (height) {139*height = h;140}141142return 1;143}144}145146//------------------------------------------------------------------------------147// Header parsing148149static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {150assert(hdr != NULL);151hdr->use_segment_ = 0;152hdr->update_map_ = 0;153hdr->absolute_delta_ = 1;154memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_));155memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_));156}157158// Paragraph 9.3159static int ParseSegmentHeader(VP8BitReader* br,160VP8SegmentHeader* hdr, VP8Proba* proba) {161assert(br != NULL);162assert(hdr != NULL);163hdr->use_segment_ = VP8Get(br);164if (hdr->use_segment_) {165hdr->update_map_ = VP8Get(br);166if (VP8Get(br)) { // update data167int s;168hdr->absolute_delta_ = VP8Get(br);169for (s = 0; s < NUM_MB_SEGMENTS; ++s) {170hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;171}172for (s = 0; s < NUM_MB_SEGMENTS; ++s) {173hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0;174}175}176if (hdr->update_map_) {177int s;178for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) {179proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u;180}181}182} else {183hdr->update_map_ = 0;184}185return !br->eof_;186}187188// Paragraph 9.5189// This function returns VP8_STATUS_SUSPENDED if we don't have all the190// necessary data in 'buf'.191// This case is not necessarily an error (for incremental decoding).192// Still, no bitreader is ever initialized to make it possible to read193// unavailable memory.194// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA195// is returned, and this is an unrecoverable error.196// If the partitions were positioned ok, VP8_STATUS_OK is returned.197static VP8StatusCode ParsePartitions(VP8Decoder* const dec,198const uint8_t* buf, size_t size) {199VP8BitReader* const br = &dec->br_;200const uint8_t* sz = buf;201const uint8_t* buf_end = buf + size;202const uint8_t* part_start;203size_t size_left = size;204size_t last_part;205size_t p;206207dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;208last_part = dec->num_parts_minus_one_;209if (size < 3 * last_part) {210// we can't even read the sizes with sz[]! That's a failure.211return VP8_STATUS_NOT_ENOUGH_DATA;212}213part_start = buf + last_part * 3;214size_left -= last_part * 3;215for (p = 0; p < last_part; ++p) {216size_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);217if (psize > size_left) psize = size_left;218VP8InitBitReader(dec->parts_ + p, part_start, psize);219part_start += psize;220size_left -= psize;221sz += 3;222}223VP8InitBitReader(dec->parts_ + last_part, part_start, size_left);224return (part_start < buf_end) ? VP8_STATUS_OK :225VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data226}227228// Paragraph 9.4229static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) {230VP8FilterHeader* const hdr = &dec->filter_hdr_;231hdr->simple_ = VP8Get(br);232hdr->level_ = VP8GetValue(br, 6);233hdr->sharpness_ = VP8GetValue(br, 3);234hdr->use_lf_delta_ = VP8Get(br);235if (hdr->use_lf_delta_) {236if (VP8Get(br)) { // update lf-delta?237int i;238for (i = 0; i < NUM_REF_LF_DELTAS; ++i) {239if (VP8Get(br)) {240hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6);241}242}243for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {244if (VP8Get(br)) {245hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);246}247}248}249}250dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;251return !br->eof_;252}253254// Topmost call255int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {256const uint8_t* buf;257size_t buf_size;258VP8FrameHeader* frm_hdr;259VP8PictureHeader* pic_hdr;260VP8BitReader* br;261VP8StatusCode status;262263if (dec == NULL) {264return 0;265}266SetOk(dec);267if (io == NULL) {268return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,269"null VP8Io passed to VP8GetHeaders()");270}271buf = io->data;272buf_size = io->data_size;273if (buf_size < 4) {274return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,275"Truncated header.");276}277278// Paragraph 9.1279{280const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);281frm_hdr = &dec->frm_hdr_;282frm_hdr->key_frame_ = !(bits & 1);283frm_hdr->profile_ = (bits >> 1) & 7;284frm_hdr->show_ = (bits >> 4) & 1;285frm_hdr->partition_length_ = (bits >> 5);286if (frm_hdr->profile_ > 3) {287return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,288"Incorrect keyframe parameters.");289}290if (!frm_hdr->show_) {291return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,292"Frame not displayable.");293}294buf += 3;295buf_size -= 3;296}297298pic_hdr = &dec->pic_hdr_;299if (frm_hdr->key_frame_) {300// Paragraph 9.2301if (buf_size < 7) {302return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,303"cannot parse picture header");304}305if (!VP8CheckSignature(buf, buf_size)) {306return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,307"Bad code word");308}309pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff;310pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2311pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff;312pic_hdr->yscale_ = buf[6] >> 6;313buf += 7;314buf_size -= 7;315316dec->mb_w_ = (pic_hdr->width_ + 15) >> 4;317dec->mb_h_ = (pic_hdr->height_ + 15) >> 4;318319// Setup default output area (can be later modified during io->setup())320io->width = pic_hdr->width_;321io->height = pic_hdr->height_;322// IMPORTANT! use some sane dimensions in crop_* and scaled_* fields.323// So they can be used interchangeably without always testing for324// 'use_cropping'.325io->use_cropping = 0;326io->crop_top = 0;327io->crop_left = 0;328io->crop_right = io->width;329io->crop_bottom = io->height;330io->use_scaling = 0;331io->scaled_width = io->width;332io->scaled_height = io->height;333334io->mb_w = io->width; // sanity check335io->mb_h = io->height; // ditto336337VP8ResetProba(&dec->proba_);338ResetSegmentHeader(&dec->segment_hdr_);339}340341// Check if we have all the partition #0 available, and initialize dec->br_342// to read this partition (and this partition only).343if (frm_hdr->partition_length_ > buf_size) {344return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,345"bad partition length");346}347348br = &dec->br_;349VP8InitBitReader(br, buf, frm_hdr->partition_length_);350buf += frm_hdr->partition_length_;351buf_size -= frm_hdr->partition_length_;352353if (frm_hdr->key_frame_) {354pic_hdr->colorspace_ = VP8Get(br);355pic_hdr->clamp_type_ = VP8Get(br);356}357if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {358return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,359"cannot parse segment header");360}361// Filter specs362if (!ParseFilterHeader(br, dec)) {363return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,364"cannot parse filter header");365}366status = ParsePartitions(dec, buf, buf_size);367if (status != VP8_STATUS_OK) {368return VP8SetError(dec, status, "cannot parse partitions");369}370371// quantizer change372VP8ParseQuant(dec);373374// Frame buffer marking375if (!frm_hdr->key_frame_) {376return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,377"Not a key frame.");378}379380VP8Get(br); // ignore the value of update_proba_381382VP8ParseProba(br, dec);383384// sanitized state385dec->ready_ = 1;386return 1;387}388389//------------------------------------------------------------------------------390// Residual decoding (Paragraph 13.2 / 13.3)391392static const uint8_t kCat3[] = { 173, 148, 140, 0 };393static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };394static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };395static const uint8_t kCat6[] =396{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };397static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };398static const uint8_t kZigzag[16] = {3990, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15400};401402// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2403static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {404int v;405if (!VP8GetBit(br, p[3])) {406if (!VP8GetBit(br, p[4])) {407v = 2;408} else {409v = 3 + VP8GetBit(br, p[5]);410}411} else {412if (!VP8GetBit(br, p[6])) {413if (!VP8GetBit(br, p[7])) {414v = 5 + VP8GetBit(br, 159);415} else {416v = 7 + 2 * VP8GetBit(br, 165);417v += VP8GetBit(br, 145);418}419} else {420const uint8_t* tab;421const int bit1 = VP8GetBit(br, p[8]);422const int bit0 = VP8GetBit(br, p[9 + bit1]);423const int cat = 2 * bit1 + bit0;424v = 0;425for (tab = kCat3456[cat]; *tab; ++tab) {426v += v + VP8GetBit(br, *tab);427}428v += 3 + (8 << cat);429}430}431return v;432}433434// Returns the position of the last non-zero coeff plus one435static int GetCoeffsFast(VP8BitReader* const br,436const VP8BandProbas* const prob[],437int ctx, const quant_t dq, int n, int16_t* out) {438const uint8_t* p = prob[n]->probas_[ctx];439for (; n < 16; ++n) {440if (!VP8GetBit(br, p[0])) {441return n; // previous coeff was last non-zero coeff442}443while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs444p = prob[++n]->probas_[0];445if (n == 16) return 16;446}447{ // non zero coeff448const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];449int v;450if (!VP8GetBit(br, p[2])) {451v = 1;452p = p_ctx[1];453} else {454v = GetLargeValue(br, p);455p = p_ctx[2];456}457out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];458}459}460return 16;461}462463// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version464// of VP8GetBitAlt() targeting specific platforms.465static int GetCoeffsAlt(VP8BitReader* const br,466const VP8BandProbas* const prob[],467int ctx, const quant_t dq, int n, int16_t* out) {468const uint8_t* p = prob[n]->probas_[ctx];469for (; n < 16; ++n) {470if (!VP8GetBitAlt(br, p[0])) {471return n; // previous coeff was last non-zero coeff472}473while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs474p = prob[++n]->probas_[0];475if (n == 16) return 16;476}477{ // non zero coeff478const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];479int v;480if (!VP8GetBitAlt(br, p[2])) {481v = 1;482p = p_ctx[1];483} else {484v = GetLargeValue(br, p);485p = p_ctx[2];486}487out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];488}489}490return 16;491}492493static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) {494if (GetCoeffs == NULL) {495if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {496GetCoeffs = GetCoeffsAlt;497} else {498GetCoeffs = GetCoeffsFast;499}500}501}502503static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {504nz_coeffs <<= 2;505nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;506return nz_coeffs;507}508509static int ParseResiduals(VP8Decoder* const dec,510VP8MB* const mb, VP8BitReader* const token_br) {511const VP8BandProbas* (* const bands)[16 + 1] = dec->proba_.bands_ptr_;512const VP8BandProbas* const * ac_proba;513VP8MBData* const block = dec->mb_data_ + dec->mb_x_;514const VP8QuantMatrix* const q = &dec->dqm_[block->segment_];515int16_t* dst = block->coeffs_;516VP8MB* const left_mb = dec->mb_info_ - 1;517uint8_t tnz, lnz;518uint32_t non_zero_y = 0;519uint32_t non_zero_uv = 0;520int x, y, ch;521uint32_t out_t_nz, out_l_nz;522int first;523524memset(dst, 0, 384 * sizeof(*dst));525if (!block->is_i4x4_) { // parse DC526int16_t dc[16] = { 0 };527const int ctx = mb->nz_dc_ + left_mb->nz_dc_;528const int nz = GetCoeffs(token_br, bands[1], ctx, q->y2_mat_, 0, dc);529mb->nz_dc_ = left_mb->nz_dc_ = (nz > 0);530if (nz > 1) { // more than just the DC -> perform the full transform531VP8TransformWHT(dc, dst);532} else { // only DC is non-zero -> inlined simplified transform533int i;534const int dc0 = (dc[0] + 3) >> 3;535for (i = 0; i < 16 * 16; i += 16) dst[i] = dc0;536}537first = 1;538ac_proba = bands[0];539} else {540first = 0;541ac_proba = bands[3];542}543544tnz = mb->nz_ & 0x0f;545lnz = left_mb->nz_ & 0x0f;546for (y = 0; y < 4; ++y) {547int l = lnz & 1;548uint32_t nz_coeffs = 0;549for (x = 0; x < 4; ++x) {550const int ctx = l + (tnz & 1);551const int nz = GetCoeffs(token_br, ac_proba, ctx, q->y1_mat_, first, dst);552l = (nz > first);553tnz = (tnz >> 1) | (l << 7);554nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);555dst += 16;556}557tnz >>= 4;558lnz = (lnz >> 1) | (l << 7);559non_zero_y = (non_zero_y << 8) | nz_coeffs;560}561out_t_nz = tnz;562out_l_nz = lnz >> 4;563564for (ch = 0; ch < 4; ch += 2) {565uint32_t nz_coeffs = 0;566tnz = mb->nz_ >> (4 + ch);567lnz = left_mb->nz_ >> (4 + ch);568for (y = 0; y < 2; ++y) {569int l = lnz & 1;570for (x = 0; x < 2; ++x) {571const int ctx = l + (tnz & 1);572const int nz = GetCoeffs(token_br, bands[2], ctx, q->uv_mat_, 0, dst);573l = (nz > 0);574tnz = (tnz >> 1) | (l << 3);575nz_coeffs = NzCodeBits(nz_coeffs, nz, dst[0] != 0);576dst += 16;577}578tnz >>= 2;579lnz = (lnz >> 1) | (l << 5);580}581// Note: we don't really need the per-4x4 details for U/V blocks.582non_zero_uv |= nz_coeffs << (4 * ch);583out_t_nz |= (tnz << 4) << ch;584out_l_nz |= (lnz & 0xf0) << ch;585}586mb->nz_ = out_t_nz;587left_mb->nz_ = out_l_nz;588589block->non_zero_y_ = non_zero_y;590block->non_zero_uv_ = non_zero_uv;591592// We look at the mode-code of each block and check if some blocks have less593// than three non-zero coeffs (code < 2). This is to avoid dithering flat and594// empty blocks.595block->dither_ = (non_zero_uv & 0xaaaa) ? 0 : q->dither_;596597return !(non_zero_y | non_zero_uv); // will be used for further optimization598}599600//------------------------------------------------------------------------------601// Main loop602603int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {604VP8MB* const left = dec->mb_info_ - 1;605VP8MB* const mb = dec->mb_info_ + dec->mb_x_;606VP8MBData* const block = dec->mb_data_ + dec->mb_x_;607int skip = dec->use_skip_proba_ ? block->skip_ : 0;608609if (!skip) {610skip = ParseResiduals(dec, mb, token_br);611} else {612left->nz_ = mb->nz_ = 0;613if (!block->is_i4x4_) {614left->nz_dc_ = mb->nz_dc_ = 0;615}616block->non_zero_y_ = 0;617block->non_zero_uv_ = 0;618block->dither_ = 0;619}620621if (dec->filter_type_ > 0) { // store filter info622VP8FInfo* const finfo = dec->f_info_ + dec->mb_x_;623*finfo = dec->fstrengths_[block->segment_][block->is_i4x4_];624finfo->f_inner_ |= !skip;625}626627return !token_br->eof_;628}629630void VP8InitScanline(VP8Decoder* const dec) {631VP8MB* const left = dec->mb_info_ - 1;632left->nz_ = 0;633left->nz_dc_ = 0;634memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));635dec->mb_x_ = 0;636}637638static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {639for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {640// Parse bitstream for this row.641VP8BitReader* const token_br =642&dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_];643if (!VP8ParseIntraModeRow(&dec->br_, dec)) {644return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,645"Premature end-of-partition0 encountered.");646}647for (; dec->mb_x_ < dec->mb_w_; ++dec->mb_x_) {648if (!VP8DecodeMB(dec, token_br)) {649return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,650"Premature end-of-file encountered.");651}652}653VP8InitScanline(dec); // Prepare for next scanline654655// Reconstruct, filter and emit the row.656if (!VP8ProcessRow(dec, io)) {657return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");658}659}660if (dec->mt_method_ > 0) {661if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;662}663664return 1;665}666667// Main entry point668int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {669int ok = 0;670if (dec == NULL) {671return 0;672}673if (io == NULL) {674return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,675"NULL VP8Io parameter in VP8Decode().");676}677678if (!dec->ready_) {679if (!VP8GetHeaders(dec, io)) {680return 0;681}682}683assert(dec->ready_);684685// Finish setting up the decoding parameter. Will call io->setup().686ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);687if (ok) { // good to go.688// Will allocate memory and prepare everything.689if (ok) ok = VP8InitFrame(dec, io);690691// Main decoding loop692if (ok) ok = ParseFrame(dec, io);693694// Exit.695ok &= VP8ExitCritical(dec, io);696}697698if (!ok) {699VP8Clear(dec);700return 0;701}702703dec->ready_ = 0;704return ok;705}706707void VP8Clear(VP8Decoder* const dec) {708if (dec == NULL) {709return;710}711WebPGetWorkerInterface()->End(&dec->worker_);712WebPDeallocateAlphaMemory(dec);713WebPSafeFree(dec->mem_);714dec->mem_ = NULL;715dec->mem_size_ = 0;716memset(&dec->br_, 0, sizeof(dec->br_));717dec->ready_ = 0;718}719720//------------------------------------------------------------------------------721722723