Support for unknown chunks in mux library
WebPMuxSetChunk/WebPMuxGetChunk/WebPMuxDeleteChunk now correctly handle unknown chunks. Change-Id: I2b75106ef08260f2bce03eb1782924b620643746
This commit is contained in:
parent
7d60bbc6d9
commit
faa4b07eda
@ -75,49 +75,32 @@ void WebPMuxDelete(WebPMux* mux) {
|
||||
// Handy MACRO, makes MuxSet() very symmetric to MuxGet().
|
||||
#define SWITCH_ID_LIST(INDEX, LIST) \
|
||||
if (idx == (INDEX)) { \
|
||||
err = ChunkAssignData(&chunk, data, copy_data, kChunks[(INDEX)].tag); \
|
||||
err = ChunkAssignData(&chunk, data, copy_data, tag); \
|
||||
if (err == WEBP_MUX_OK) { \
|
||||
err = ChunkSetNth(&chunk, (LIST), nth); \
|
||||
} \
|
||||
return err; \
|
||||
}
|
||||
|
||||
static WebPMuxError MuxSet(WebPMux* const mux, CHUNK_INDEX idx, uint32_t nth,
|
||||
static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
|
||||
const WebPData* const data, int copy_data) {
|
||||
WebPChunk chunk;
|
||||
WebPMuxError err = WEBP_MUX_NOT_FOUND;
|
||||
const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
|
||||
assert(mux != NULL);
|
||||
assert(!IsWPI(kChunks[idx].id));
|
||||
|
||||
ChunkInit(&chunk);
|
||||
SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
|
||||
SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
|
||||
SWITCH_ID_LIST(IDX_ANIM, &mux->anim_);
|
||||
SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
|
||||
SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
|
||||
if (idx == IDX_UNKNOWN && data->size > TAG_SIZE) {
|
||||
// For raw-data unknown chunk, the first four bytes should be the tag to be
|
||||
// used for the chunk.
|
||||
const WebPData tmp = { data->bytes + TAG_SIZE, data->size - TAG_SIZE };
|
||||
err = ChunkAssignData(&chunk, &tmp, copy_data, GetLE32(data->bytes + 0));
|
||||
if (err == WEBP_MUX_OK)
|
||||
err = ChunkSetNth(&chunk, &mux->unknown_, nth);
|
||||
}
|
||||
SWITCH_ID_LIST(IDX_VP8X, &mux->vp8x_);
|
||||
SWITCH_ID_LIST(IDX_ICCP, &mux->iccp_);
|
||||
SWITCH_ID_LIST(IDX_ANIM, &mux->anim_);
|
||||
SWITCH_ID_LIST(IDX_EXIF, &mux->exif_);
|
||||
SWITCH_ID_LIST(IDX_XMP, &mux->xmp_);
|
||||
SWITCH_ID_LIST(IDX_UNKNOWN, &mux->unknown_);
|
||||
return err;
|
||||
}
|
||||
#undef SWITCH_ID_LIST
|
||||
|
||||
static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag,
|
||||
const uint8_t* data, size_t size,
|
||||
int copy_data) {
|
||||
const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
|
||||
const WebPData chunk_data = { data, size };
|
||||
assert(mux != NULL);
|
||||
assert(size <= MAX_CHUNK_PAYLOAD);
|
||||
assert(idx != IDX_NIL);
|
||||
return MuxSet(mux, idx, nth, &chunk_data, copy_data);
|
||||
}
|
||||
|
||||
// Create data for frame/fragment given image data, offsets and duration.
|
||||
static WebPMuxError CreateFrameFragmentData(
|
||||
const WebPData* const image, int x_offset, int y_offset, int duration,
|
||||
@ -200,15 +183,9 @@ static WebPMuxError DeleteChunks(WebPChunk** chunk_list, uint32_t tag) {
|
||||
|
||||
static WebPMuxError MuxDeleteAllNamedData(WebPMux* const mux, uint32_t tag) {
|
||||
const WebPChunkId id = ChunkGetIdFromTag(tag);
|
||||
WebPChunk** chunk_list;
|
||||
|
||||
assert(mux != NULL);
|
||||
if (IsWPI(id)) return WEBP_MUX_INVALID_ARGUMENT;
|
||||
|
||||
chunk_list = MuxGetChunkListFromId(mux, id);
|
||||
if (chunk_list == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||
|
||||
return DeleteChunks(chunk_list, tag);
|
||||
return DeleteChunks(MuxGetChunkListFromId(mux, id), tag);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -231,7 +208,7 @@ WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
|
||||
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;
|
||||
|
||||
// Add the given chunk.
|
||||
return MuxSet(mux, idx, 1, chunk_data, copy_data);
|
||||
return MuxSet(mux, tag, 1, chunk_data, copy_data);
|
||||
}
|
||||
|
||||
// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
|
||||
@ -381,6 +358,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
|
||||
const WebPMuxAnimParams* params) {
|
||||
WebPMuxError err;
|
||||
uint8_t data[ANIM_CHUNK_SIZE];
|
||||
const WebPData anim = { data, ANIM_CHUNK_SIZE };
|
||||
|
||||
if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||
if (params->loop_count < 0 || params->loop_count >= MAX_LOOP_COUNT) {
|
||||
@ -394,7 +372,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
|
||||
// Set the animation parameters.
|
||||
PutLE32(data, params->bgcolor);
|
||||
PutLE16(data + 4, params->loop_count);
|
||||
return MuxAddChunk(mux, 1, kChunks[IDX_ANIM].tag, data, sizeof(data), 1);
|
||||
return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -534,7 +512,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
uint8_t data[VP8X_CHUNK_SIZE];
|
||||
const size_t data_size = VP8X_CHUNK_SIZE;
|
||||
const WebPData vp8x = { data, VP8X_CHUNK_SIZE };
|
||||
const WebPMuxImage* images = NULL;
|
||||
|
||||
assert(mux != NULL);
|
||||
@ -599,8 +577,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
|
||||
PutLE24(data + 4, width - 1); // canvas width.
|
||||
PutLE24(data + 7, height - 1); // canvas height.
|
||||
|
||||
err = MuxAddChunk(mux, 1, kChunks[IDX_VP8X].tag, data, data_size, 1);
|
||||
return err;
|
||||
return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
|
||||
}
|
||||
|
||||
// Cleans up 'mux' by removing any unnecessary chunks.
|
||||
|
@ -101,10 +101,10 @@ extern const ChunkInfo kChunks[IDX_LAST_CHUNK];
|
||||
// Initialize.
|
||||
void ChunkInit(WebPChunk* const chunk);
|
||||
|
||||
// Get chunk index from chunk tag. Returns IDX_NIL if not found.
|
||||
// Get chunk index from chunk tag. Returns IDX_UNKNOWN if not found.
|
||||
CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag);
|
||||
|
||||
// Get chunk id from chunk tag. Returns WEBP_CHUNK_NIL if not found.
|
||||
// Get chunk id from chunk tag. Returns WEBP_CHUNK_UNKNOWN if not found.
|
||||
WebPChunkId ChunkGetIdFromTag(uint32_t tag);
|
||||
|
||||
// Convert a fourcc string to a tag.
|
||||
@ -207,8 +207,6 @@ int MuxHasLosslessImages(const WebPMuxImage* images);
|
||||
uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size);
|
||||
|
||||
// Returns the list where chunk with given ID is to be inserted in mux.
|
||||
// Return value is NULL if this chunk should be inserted in mux->images_ list
|
||||
// or if 'id' is not known.
|
||||
WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id);
|
||||
|
||||
// Validates the given mux object.
|
||||
|
@ -33,7 +33,7 @@ const ChunkInfo kChunks[] = {
|
||||
{ MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
|
||||
{ MKFOURCC('E', 'X', 'I', 'F'), WEBP_CHUNK_EXIF, UNDEFINED_CHUNK_SIZE },
|
||||
{ MKFOURCC('X', 'M', 'P', ' '), WEBP_CHUNK_XMP, UNDEFINED_CHUNK_SIZE },
|
||||
{ MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
|
||||
{ NIL_TAG, WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
|
||||
|
||||
{ NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
|
||||
};
|
||||
@ -72,7 +72,7 @@ CHUNK_INDEX ChunkGetIndexFromTag(uint32_t tag) {
|
||||
for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
|
||||
if (tag == kChunks[i].tag) return i;
|
||||
}
|
||||
return IDX_NIL;
|
||||
return IDX_UNKNOWN;
|
||||
}
|
||||
|
||||
WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
|
||||
@ -80,7 +80,7 @@ WebPChunkId ChunkGetIdFromTag(uint32_t tag) {
|
||||
for (i = 0; kChunks[i].tag != NIL_TAG; ++i) {
|
||||
if (tag == kChunks[i].tag) return kChunks[i].id;
|
||||
}
|
||||
return WEBP_CHUNK_NIL;
|
||||
return WEBP_CHUNK_UNKNOWN;
|
||||
}
|
||||
|
||||
uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) {
|
||||
@ -89,8 +89,7 @@ uint32_t ChunkGetTagFromFourCC(const char fourcc[4]) {
|
||||
|
||||
CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
|
||||
const uint32_t tag = ChunkGetTagFromFourCC(fourcc);
|
||||
const CHUNK_INDEX idx = ChunkGetIndexFromTag(tag);
|
||||
return (idx == IDX_NIL) ? IDX_UNKNOWN : idx;
|
||||
return ChunkGetIndexFromTag(tag);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -421,8 +420,7 @@ WebPChunk** MuxGetChunkListFromId(const WebPMux* mux, WebPChunkId id) {
|
||||
case WEBP_CHUNK_ANIM: return (WebPChunk**)&mux->anim_;
|
||||
case WEBP_CHUNK_EXIF: return (WebPChunk**)&mux->exif_;
|
||||
case WEBP_CHUNK_XMP: return (WebPChunk**)&mux->xmp_;
|
||||
case WEBP_CHUNK_UNKNOWN: return (WebPChunk**)&mux->unknown_;
|
||||
default: return NULL;
|
||||
default: return (WebPChunk**)&mux->unknown_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
|
||||
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
|
||||
// getting all chunks of an image.
|
||||
chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
|
||||
if (chunk_list == NULL) chunk_list = &mux->unknown_;
|
||||
if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
|
||||
break;
|
||||
}
|
||||
@ -502,12 +501,8 @@ WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
|
||||
*num_elements = MuxImageCount(mux->images_, id);
|
||||
} else {
|
||||
WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
|
||||
if (chunk_list == NULL) {
|
||||
*num_elements = 0;
|
||||
} else {
|
||||
const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
|
||||
*num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
|
||||
}
|
||||
const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
|
||||
*num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
|
||||
}
|
||||
|
||||
return WEBP_MUX_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user