static ParseStatus CreateRawImageDemuxer(MemBuffer* const mem, WebPDemuxer** demuxer) { WebPBitstreamFeatures features; const VP8StatusCode status = WebPGetFeatures(mem->buf_, mem->buf_size_, &features); *demuxer = NULL; if (status != VP8_STATUS_OK) { return (status == VP8_STATUS_NOT_ENOUGH_DATA) ? PARSE_NEED_MORE_DATA : PARSE_ERROR; } { WebPDemuxer* const dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); Frame* const frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); if (dmux == NULL || frame == NULL) goto Error; InitDemux(dmux, mem); SetFrameInfo(0, mem->buf_size_, 1 /*frame_num*/, 1 /*complete*/, &features, frame); if (!AddFrame(dmux, frame)) goto Error; dmux->state_ = WEBP_DEMUX_DONE; dmux->canvas_width_ = frame->width_; dmux->canvas_height_ = frame->height_; dmux->feature_flags_ |= frame->has_alpha_ ? ALPHA_FLAG : 0; dmux->num_frames_ = 1; assert(IsValidSimpleFormat(dmux)); *demuxer = dmux; return PARSE_OK; Error: WebPSafeFree(dmux); WebPSafeFree(frame); return PARSE_ERROR; } }
WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, WebPDemuxState* state, int version) { const ChunkParser* parser; int partial; ParseStatus status = PARSE_ERROR; MemBuffer mem; WebPDemuxer* dmux; if (state != NULL) *state = WEBP_DEMUX_PARSE_ERROR; if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; status = ReadHeader(&mem); if (status != PARSE_OK) { // If parsing of the webp file header fails attempt to handle a raw // VP8/VP8L frame. Note 'allow_partial' is ignored in this case. if (status == PARSE_ERROR) { status = CreateRawImageDemuxer(&mem, &dmux); if (status == PARSE_OK) { if (state != NULL) *state = WEBP_DEMUX_DONE; return dmux; } } if (state != NULL) { *state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER : WEBP_DEMUX_PARSE_ERROR; } return NULL; } partial = (mem.buf_size_ < mem.riff_end_); if (!allow_partial && partial) return NULL; dmux = (WebPDemuxer*)WebPSafeCalloc(1ULL, sizeof(*dmux)); if (dmux == NULL) return NULL; InitDemux(dmux, &mem); status = PARSE_ERROR; for (parser = kMasterChunks; parser->parse != NULL; ++parser) { if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { status = parser->parse(dmux); if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; if (status == PARSE_ERROR) dmux->state_ = WEBP_DEMUX_PARSE_ERROR; break; } } if (state != NULL) *state = dmux->state_; if (status == PARSE_ERROR) { WebPDemuxDelete(dmux); return NULL; } return dmux; }
WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial, WebPDemuxState* state, int version) { const ChunkParser* parser; int partial; ParseStatus status = PARSE_ERROR; MemBuffer mem; WebPDemuxer* dmux; if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DEMUX_ABI_VERSION)) return NULL; if (data == NULL || data->bytes == NULL || data->size == 0) return NULL; if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL; if (!ReadHeader(&mem)) return NULL; partial = (mem.buf_size_ < mem.riff_end_); if (!allow_partial && partial) return NULL; dmux = (WebPDemuxer*)calloc(1, sizeof(*dmux)); if (dmux == NULL) return NULL; InitDemux(dmux, &mem); for (parser = kMasterChunks; parser->parse != NULL; ++parser) { if (!memcmp(parser->id, GetBuffer(&dmux->mem_), TAG_SIZE)) { status = parser->parse(dmux); if (status == PARSE_OK) dmux->state_ = WEBP_DEMUX_DONE; if (status == PARSE_NEED_MORE_DATA && !partial) status = PARSE_ERROR; if (status != PARSE_ERROR && !parser->valid(dmux)) status = PARSE_ERROR; break; } } if (state) *state = dmux->state_; if (status == PARSE_ERROR) { WebPDemuxDelete(dmux); return NULL; } return dmux; }