mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-28 14:38:21 +01:00
demux: accept raw bitstreams
i.e., allow the WebP file header and leading chunk header to be stripped. Change-Id: I43818ed56a14881d9ad11aaddcd0bf5c0ca6aef3
This commit is contained in:
parent
d6dad5d05f
commit
3f3ea2c539
@ -193,6 +193,19 @@ static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetFrameInfo(size_t start_offset, size_t size,
|
||||||
|
int frame_num, int complete,
|
||||||
|
const WebPBitstreamFeatures* const features,
|
||||||
|
Frame* const frame) {
|
||||||
|
frame->img_components_[0].offset_ = start_offset;
|
||||||
|
frame->img_components_[0].size_ = size;
|
||||||
|
frame->width_ = features->width;
|
||||||
|
frame->height_ = features->height;
|
||||||
|
frame->has_alpha_ |= features->has_alpha;
|
||||||
|
frame->frame_num_ = frame_num;
|
||||||
|
frame->complete_ = complete;
|
||||||
|
}
|
||||||
|
|
||||||
// Store image bearing chunks to 'frame'.
|
// Store image bearing chunks to 'frame'.
|
||||||
static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
||||||
MemBuffer* const mem, Frame* const frame) {
|
MemBuffer* const mem, Frame* const frame) {
|
||||||
@ -248,13 +261,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
++image_chunks;
|
++image_chunks;
|
||||||
frame->img_components_[0].offset_ = chunk_start_offset;
|
SetFrameInfo(chunk_start_offset, chunk_size, frame_num,
|
||||||
frame->img_components_[0].size_ = chunk_size;
|
status == PARSE_OK, &features, frame);
|
||||||
frame->width_ = features.width;
|
|
||||||
frame->height_ = features.height;
|
|
||||||
frame->has_alpha_ |= features.has_alpha;
|
|
||||||
frame->frame_num_ = frame_num;
|
|
||||||
frame->complete_ = (status == PARSE_OK);
|
|
||||||
Skip(mem, payload_available);
|
Skip(mem, payload_available);
|
||||||
} else {
|
} else {
|
||||||
goto Done;
|
goto Done;
|
||||||
@ -659,6 +667,41 @@ static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
|
|||||||
dmux->mem_ = *mem;
|
dmux->mem_ = *mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
|
||||||
WebPDemuxState* state, int version) {
|
WebPDemuxState* state, int version) {
|
||||||
const ChunkParser* parser;
|
const ChunkParser* parser;
|
||||||
@ -675,6 +718,15 @@ WebPDemuxer* WebPDemuxInternal(const WebPData* data, int allow_partial,
|
|||||||
if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
|
if (!InitMemBuffer(&mem, data->bytes, data->size)) return NULL;
|
||||||
status = ReadHeader(&mem);
|
status = ReadHeader(&mem);
|
||||||
if (status != PARSE_OK) {
|
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) {
|
if (state != NULL) {
|
||||||
*state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
|
*state = (status == PARSE_NEED_MORE_DATA) ? WEBP_DEMUX_PARSING_HEADER
|
||||||
: WEBP_DEMUX_PARSE_ERROR;
|
: WEBP_DEMUX_PARSE_ERROR;
|
||||||
|
@ -88,7 +88,8 @@ typedef enum WebPDemuxState {
|
|||||||
WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
|
WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal(
|
||||||
const WebPData*, int, WebPDemuxState*, int);
|
const WebPData*, int, WebPDemuxState*, int);
|
||||||
|
|
||||||
// Parses the full WebP file given by 'data'.
|
// Parses the full WebP file given by 'data'. For single images the WebP file
|
||||||
|
// header alone or the file header and the chunk header may be absent.
|
||||||
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
// Returns a WebPDemuxer object on successful parse, NULL otherwise.
|
||||||
static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) {
|
||||||
return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
|
return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION);
|
||||||
|
Loading…
Reference in New Issue
Block a user