mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 04:18:26 +01:00
VP8GetInfo() + WebPResetDecParams()
- add an internal VP8GetInfo() to parse header - add WebPResetDecParams() for proper initialization Change-Id: Ic39ea634d1d8016d25bdcfef2cb0d00b6dad83e9
This commit is contained in:
parent
416b7a6b95
commit
92e5c6e1d4
@ -429,6 +429,8 @@ WebPIDecoder* WebPINew(WEBP_CSP_MODE mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
idec->state_ = STATE_HEADER;
|
idec->state_ = STATE_HEADER;
|
||||||
|
|
||||||
|
WebPResetDecParams(&idec->params_);
|
||||||
idec->params_.mode = mode;
|
idec->params_.mode = mode;
|
||||||
|
|
||||||
InitMemBuffer(&idec->mem_);
|
InitMemBuffer(&idec->mem_);
|
||||||
|
@ -74,6 +74,44 @@ int VP8SetError(VP8Decoder* const dec,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int VP8GetInfo(const uint8_t* data, uint32_t chunk_size,
|
||||||
|
int *width, int *height) {
|
||||||
|
// check signature
|
||||||
|
if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a) {
|
||||||
|
return 0; // Wrong signature.
|
||||||
|
} else {
|
||||||
|
const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
|
||||||
|
const int key_frame = !(bits & 1);
|
||||||
|
const int w = ((data[7] << 8) | data[6]) & 0x3fff;
|
||||||
|
const int h = ((data[9] << 8) | data[8]) & 0x3fff;
|
||||||
|
|
||||||
|
if (!key_frame) { // Not a keyframe.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((bits >> 1) & 7) > 3) {
|
||||||
|
return 0; // unknown profile
|
||||||
|
}
|
||||||
|
if (!((bits >> 4) & 1)) {
|
||||||
|
return 0; // first frame is invisible!
|
||||||
|
}
|
||||||
|
if (((bits >> 5)) >= chunk_size) { // partition_length
|
||||||
|
return 0; // inconsistent size information.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width) {
|
||||||
|
*width = w;
|
||||||
|
}
|
||||||
|
if (height) {
|
||||||
|
*height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Header parsing
|
// Header parsing
|
||||||
|
|
||||||
|
@ -263,6 +263,11 @@ struct VP8Decoder {
|
|||||||
// in vp8.c
|
// in vp8.c
|
||||||
int VP8SetError(VP8Decoder* const dec,
|
int VP8SetError(VP8Decoder* const dec,
|
||||||
VP8StatusCode error, const char * const msg);
|
VP8StatusCode error, const char * const msg);
|
||||||
|
// Validates the VP8 data-header and retrieve basic header information viz width
|
||||||
|
// and height. Returns 0 in case of formatting error. *width/*height can be
|
||||||
|
// passed NULL.
|
||||||
|
int VP8GetInfo(const uint8_t* data, uint32_t data_size,
|
||||||
|
int *width, int *height);
|
||||||
|
|
||||||
// in tree.c
|
// in tree.c
|
||||||
void VP8ResetProba(VP8Proba* const proba);
|
void VP8ResetProba(VP8Proba* const proba);
|
||||||
|
@ -414,18 +414,23 @@ int WebPCheckDecParams(const VP8Io* io, const WebPDecParams* params) {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebPResetDecParams(WebPDecParams* const params) {
|
||||||
|
assert(params);
|
||||||
|
memset(params, 0, sizeof(*params));
|
||||||
|
}
|
||||||
|
|
||||||
void WebPClearDecParams(WebPDecParams* params) {
|
void WebPClearDecParams(WebPDecParams* params) {
|
||||||
|
assert(params);
|
||||||
if (!params->external_buffer) {
|
if (!params->external_buffer) {
|
||||||
free(params->output);
|
free(params->output);
|
||||||
}
|
}
|
||||||
memset(params, 0, sizeof(*params));
|
WebPResetDecParams(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// "Into" variants
|
// "Into" variants
|
||||||
|
|
||||||
static uint8_t* DecodeInto(WEBP_CSP_MODE mode,
|
static uint8_t* DecodeInto(const uint8_t* data, uint32_t data_size,
|
||||||
const uint8_t* data, uint32_t data_size,
|
|
||||||
WebPDecParams* params) {
|
WebPDecParams* params) {
|
||||||
VP8Decoder* dec = VP8New();
|
VP8Decoder* dec = VP8New();
|
||||||
VP8Io io;
|
VP8Io io;
|
||||||
@ -439,7 +444,6 @@ static uint8_t* DecodeInto(WEBP_CSP_MODE mode,
|
|||||||
io.data = data;
|
io.data = data;
|
||||||
io.data_size = data_size;
|
io.data_size = data_size;
|
||||||
|
|
||||||
params->mode = mode;
|
|
||||||
io.opaque = params;
|
io.opaque = params;
|
||||||
WebPInitCustomIo(&io);
|
WebPInitCustomIo(&io);
|
||||||
|
|
||||||
@ -455,7 +459,7 @@ static uint8_t* DecodeInto(WEBP_CSP_MODE mode,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode != MODE_YUV) {
|
if (params->mode != MODE_YUV) {
|
||||||
VP8YUVInit();
|
VP8YUVInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,12 +477,12 @@ uint8_t* WebPDecodeRGBInto(const uint8_t* data, uint32_t data_size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPResetDecParams(¶ms);
|
||||||
|
params.mode = MODE_RGB;
|
||||||
params.output = output;
|
params.output = output;
|
||||||
params.stride = output_stride;
|
params.stride = output_stride;
|
||||||
params.output_size = output_size;
|
params.output_size = output_size;
|
||||||
params.output_u_size = 0;
|
return DecodeInto(data, data_size, ¶ms);
|
||||||
params.output_v_size = 0;
|
|
||||||
return DecodeInto(MODE_RGB, data, data_size, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size,
|
uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size,
|
||||||
@ -490,12 +494,12 @@ uint8_t* WebPDecodeRGBAInto(const uint8_t* data, uint32_t data_size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPResetDecParams(¶ms);
|
||||||
|
params.mode = MODE_RGBA;
|
||||||
params.output = output;
|
params.output = output;
|
||||||
params.stride = output_stride;
|
params.stride = output_stride;
|
||||||
params.output_size = output_size;
|
params.output_size = output_size;
|
||||||
params.output_u_size = 0;
|
return DecodeInto(data, data_size, ¶ms);
|
||||||
params.output_v_size = 0;
|
|
||||||
return DecodeInto(MODE_RGBA, data, data_size, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size,
|
uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size,
|
||||||
@ -507,12 +511,12 @@ uint8_t* WebPDecodeBGRInto(const uint8_t* data, uint32_t data_size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPResetDecParams(¶ms);
|
||||||
|
params.mode = MODE_BGR;
|
||||||
params.output = output;
|
params.output = output;
|
||||||
params.stride = output_stride;
|
params.stride = output_stride;
|
||||||
params.output_size = output_size;
|
params.output_size = output_size;
|
||||||
params.output_u_size = 0;
|
return DecodeInto(data, data_size, ¶ms);
|
||||||
params.output_v_size = 0;
|
|
||||||
return DecodeInto(MODE_BGR, data, data_size, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size,
|
uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size,
|
||||||
@ -524,12 +528,12 @@ uint8_t* WebPDecodeBGRAInto(const uint8_t* data, uint32_t data_size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPResetDecParams(¶ms);
|
||||||
|
params.mode = MODE_BGRA;
|
||||||
params.output = output;
|
params.output = output;
|
||||||
params.stride = output_stride;
|
params.stride = output_stride;
|
||||||
params.output_size = output_size;
|
params.output_size = output_size;
|
||||||
params.output_u_size = 0;
|
return DecodeInto(data, data_size, ¶ms);
|
||||||
params.output_v_size = 0;
|
|
||||||
return DecodeInto(MODE_BGRA, data, data_size, ¶ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size,
|
uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size,
|
||||||
@ -542,6 +546,8 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebPResetDecParams(¶ms);
|
||||||
|
params.mode = MODE_YUV;
|
||||||
params.output = luma;
|
params.output = luma;
|
||||||
params.stride = luma_stride;
|
params.stride = luma_stride;
|
||||||
params.output_size = luma_size;
|
params.output_size = luma_size;
|
||||||
@ -551,7 +557,7 @@ uint8_t* WebPDecodeYUVInto(const uint8_t* data, uint32_t data_size,
|
|||||||
params.v = v;
|
params.v = v;
|
||||||
params.v_stride = v_stride;
|
params.v_stride = v_stride;
|
||||||
params.output_v_size = v_size;
|
params.output_v_size = v_size;
|
||||||
return DecodeInto(MODE_YUV, data, data_size, ¶ms);
|
return DecodeInto(data, data_size, ¶ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -562,7 +568,7 @@ static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* data,
|
|||||||
uint8_t* output;
|
uint8_t* output;
|
||||||
WebPDecParams params;
|
WebPDecParams params;
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
WebPResetDecParams(¶ms);
|
||||||
params.mode = mode;
|
params.mode = mode;
|
||||||
if (!WebPInitDecParams(data, data_size, width, height, ¶ms)) {
|
if (!WebPInitDecParams(data, data_size, width, height, ¶ms)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -571,7 +577,7 @@ static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* data,
|
|||||||
params.output_size = params.stride * (*height);
|
params.output_size = params.stride * (*height);
|
||||||
params.output_u_size = params.output_v_size =
|
params.output_u_size = params.output_v_size =
|
||||||
params.u_stride * ((*height + 1) / 2);
|
params.u_stride * ((*height + 1) / 2);
|
||||||
output = DecodeInto(mode, data, data_size, ¶ms);
|
output = DecodeInto(data, data_size, ¶ms);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
WebPClearDecParams(¶ms);
|
WebPClearDecParams(¶ms);
|
||||||
}
|
}
|
||||||
@ -631,38 +637,7 @@ int WebPGetInfo(const uint8_t* data, uint32_t data_size,
|
|||||||
if (data_size < 10) {
|
if (data_size < 10) {
|
||||||
return 0; // not enough data
|
return 0; // not enough data
|
||||||
}
|
}
|
||||||
// check signature
|
return VP8GetInfo(data, chunk_size, width, height);
|
||||||
if (data[3] != 0x9d || data[4] != 0x01 || data[5] != 0x2a) {
|
|
||||||
return 0; // Wrong signature.
|
|
||||||
} else {
|
|
||||||
const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
|
|
||||||
const int key_frame = !(bits & 1);
|
|
||||||
const int w = ((data[7] << 8) | data[6]) & 0x3fff;
|
|
||||||
const int h = ((data[9] << 8) | data[8]) & 0x3fff;
|
|
||||||
|
|
||||||
if (!key_frame) { // Not a keyframe.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((bits >> 1) & 7) > 3) {
|
|
||||||
return 0; // unknown profile
|
|
||||||
}
|
|
||||||
if (!((bits >> 4) & 1)) {
|
|
||||||
return 0; // first frame is invisible!
|
|
||||||
}
|
|
||||||
if (((bits >> 5)) >= chunk_size) { // partition_length
|
|
||||||
return 0; // inconsistent size information.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width) {
|
|
||||||
*width = w;
|
|
||||||
}
|
|
||||||
if (height) {
|
|
||||||
*height = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
|
@ -34,6 +34,9 @@ typedef struct {
|
|||||||
int external_buffer; // If true, the output buffers are externally owned
|
int external_buffer; // If true, the output buffers are externally owned
|
||||||
} WebPDecParams;
|
} WebPDecParams;
|
||||||
|
|
||||||
|
// Should be called first, before any use of the WebPDecParams object.
|
||||||
|
void WebPResetDecParams(WebPDecParams* const params);
|
||||||
|
|
||||||
// If a RIFF container is detected, validate it and skip over it. Returns
|
// If a RIFF container is detected, validate it and skip over it. Returns
|
||||||
// VP8 bit-stream size if RIFF header is valid else returns 0
|
// VP8 bit-stream size if RIFF header is valid else returns 0
|
||||||
uint32_t WebPCheckRIFFHeader(const uint8_t** data_ptr,
|
uint32_t WebPCheckRIFFHeader(const uint8_t** data_ptr,
|
||||||
|
Loading…
Reference in New Issue
Block a user