1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-22 15:06:45 +00:00

Update libwebp to 1.0.1

This commit is contained in:
volzhs
2018-12-10 22:33:51 +09:00
parent bf59b73250
commit d4133ac844
65 changed files with 585 additions and 874 deletions

View File

@@ -40,4 +40,4 @@ int WebPAnimEncoderRefineRect(
} // extern "C"
#endif
#endif /* WEBP_MUX_ANIMI_H_ */
#endif // WEBP_MUX_ANIMI_H_

View File

@@ -69,12 +69,12 @@ void WebPMuxDelete(WebPMux* mux) {
if (idx == (INDEX)) { \
err = ChunkAssignData(&chunk, data, copy_data, tag); \
if (err == WEBP_MUX_OK) { \
err = ChunkSetNth(&chunk, (LIST), nth); \
err = ChunkSetHead(&chunk, (LIST)); \
} \
return err; \
}
static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag,
const WebPData* const data, int copy_data) {
WebPChunk chunk;
WebPMuxError err = WEBP_MUX_NOT_FOUND;
@@ -190,7 +190,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, tag, 1, chunk_data, copy_data);
return MuxSet(mux, tag, chunk_data, copy_data);
}
// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
@@ -202,7 +202,7 @@ static WebPMuxError AddDataToChunkList(
ChunkInit(&chunk);
err = ChunkAssignData(&chunk, data, copy_data, tag);
if (err != WEBP_MUX_OK) goto Err;
err = ChunkSetNth(&chunk, chunk_list, 1);
err = ChunkSetHead(&chunk, chunk_list);
if (err != WEBP_MUX_OK) goto Err;
return WEBP_MUX_OK;
Err:
@@ -266,14 +266,14 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
const WebPData* const bitstream = &info->bitstream;
// Sanity checks.
if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT;
if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;
if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
if (info->bitstream.bytes == NULL ||
info->bitstream.size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
@@ -287,7 +287,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
}
MuxImageInit(&wpi);
err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
if (err != WEBP_MUX_OK) goto Err;
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.
@@ -342,7 +342,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
// Set the animation parameters.
PutLE32(data, params->bgcolor);
PutLE16(data + 4, params->loop_count);
return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1);
}
WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
@@ -540,7 +540,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
PutLE24(data + 4, width - 1); // canvas width.
PutLE24(data + 7, height - 1); // canvas height.
return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1);
}
// Cleans up 'mux' by removing any unnecessary chunks.

View File

@@ -14,6 +14,7 @@
#ifndef WEBP_MUX_MUXI_H_
#define WEBP_MUX_MUXI_H_
#include <assert.h>
#include <stdlib.h>
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
@@ -28,7 +29,7 @@ extern "C" {
#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
#define MUX_REV_VERSION 0
#define MUX_REV_VERSION 1
// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -126,11 +127,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
int copy_data, uint32_t tag);
// Sets 'chunk' at nth position in the 'chunk_list'.
// nth = 0 has the special meaning "last of the list".
// Sets 'chunk' as the only element in 'chunk_list' if it is empty.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth);
WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list);
// Sets 'chunk' at last position in the 'chunk_list'.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
// *chunk_list also points towards the last valid element of the initial
// *chunk_list.
WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);
// Releases chunk and returns chunk->next_.
WebPChunk* ChunkRelease(WebPChunk* const chunk);
@@ -143,13 +147,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);
// Returns size of the chunk including chunk header and padding byte (if any).
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
assert(chunk_size <= MAX_CHUNK_PAYLOAD);
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
}
// Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
const size_t data_size = chunk->data_.size;
assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size);
}
@@ -227,4 +231,4 @@ WebPMuxError MuxValidate(const WebPMux* const mux);
} // extern "C"
#endif
#endif /* WEBP_MUX_MUXI_H_ */
#endif // WEBP_MUX_MUXI_H_

View File

@@ -111,27 +111,6 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
return ((nth > 0) && (iter > 0)) ? NULL : first;
}
// Outputs a pointer to 'prev_chunk->next_',
// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
// Returns true if nth chunk was found.
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
WebPChunk*** const location) {
uint32_t count = 0;
assert(chunk_list != NULL);
*location = chunk_list;
while (*chunk_list != NULL) {
WebPChunk* const cur_chunk = *chunk_list;
++count;
if (count == nth) return 1; // Found.
chunk_list = &cur_chunk->next_;
*location = chunk_list;
}
// *chunk_list is ok to be NULL if adding at last location.
return (nth == 0 || (count == nth - 1)) ? 1 : 0;
}
//------------------------------------------------------------------------------
// Chunk writer methods.
@@ -156,11 +135,12 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
return WEBP_MUX_OK;
}
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth) {
WebPMuxError ChunkSetHead(WebPChunk* const chunk,
WebPChunk** const chunk_list) {
WebPChunk* new_chunk;
if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
assert(chunk_list != NULL);
if (*chunk_list != NULL) {
return WEBP_MUX_NOT_FOUND;
}
@@ -168,11 +148,26 @@ WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
chunk->owner_ = 0;
new_chunk->next_ = *chunk_list;
new_chunk->next_ = NULL;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
}
WebPMuxError ChunkAppend(WebPChunk* const chunk,
WebPChunk*** const chunk_list) {
assert(chunk_list != NULL && *chunk_list != NULL);
if (**chunk_list == NULL) {
ChunkSetHead(chunk, *chunk_list);
} else {
WebPChunk* last_chunk = **chunk_list;
while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_;
ChunkSetHead(chunk, &last_chunk->next_);
*chunk_list = &last_chunk->next_;
}
return WEBP_MUX_OK;
}
//------------------------------------------------------------------------------
// Chunk deletion method(s).
@@ -232,9 +227,11 @@ void MuxImageInit(WebPMuxImage* const wpi) {
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
WebPMuxImage* next;
if (wpi == NULL) return NULL;
ChunkDelete(wpi->header_);
ChunkDelete(wpi->alpha_);
ChunkDelete(wpi->img_);
// There should be at most one chunk of header_, alpha_, img_ but we call
// ChunkListDelete to be safe
ChunkListDelete(&wpi->header_);
ChunkListDelete(&wpi->alpha_);
ChunkListDelete(&wpi->img_);
ChunkListDelete(&wpi->unknown_);
next = wpi->next_;

View File

@@ -59,6 +59,7 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
// Sanity checks.
if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE);
if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA;
{
const size_t chunk_disk_size = SizeWithPadding(chunk_size);
@@ -102,6 +103,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
const uint8_t* const last = bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_;
ChunkInit(&subchunk);
assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
@@ -116,7 +118,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
ChunkSetNth(&subchunk, &wpi->header_, 1);
ChunkSetHead(&subchunk, &wpi->header_);
wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
// Rest of the chunks.
@@ -133,18 +135,23 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
switch (ChunkGetIdFromTag(subchunk.tag_)) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail;
if (!MuxImageFinalize(wpi)) goto Fail;
wpi->is_partial_ = 0; // wpi is completely filled.
break;
case WEBP_CHUNK_UNKNOWN:
if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
// before some image chunks.
if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
if (wpi->is_partial_) {
goto Fail; // Encountered an unknown chunk
// before some image chunks.
}
if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) {
goto Fail;
}
break;
default:
goto Fail;
@@ -175,6 +182,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
const uint8_t* data;
size_t size;
WebPChunk chunk;
// Stores the end of the chunk lists so that it is faster to append data to
// their ends.
WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL };
ChunkInit(&chunk);
// Sanity checks.
@@ -187,7 +197,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
size = bitstream->size;
if (data == NULL) return NULL;
if (size < RIFF_HEADER_SIZE) return NULL;
if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL;
if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
return NULL;
@@ -196,8 +206,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
mux = WebPMuxNew();
if (mux == NULL) return NULL;
if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;
tag = GetLE32(data + RIFF_HEADER_SIZE);
if (tag != kChunks[IDX_VP8].tag &&
tag != kChunks[IDX_VP8L].tag &&
@@ -205,13 +213,17 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
goto Err; // First chunk should be VP8, VP8L or VP8X.
}
riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
goto Err;
} else {
if (riff_size < size) { // Redundant data after last chunk.
size = riff_size; // To make sure we don't read any data beyond mux_size.
}
riff_size = GetLE32(data + TAG_SIZE);
if (riff_size > MAX_CHUNK_PAYLOAD) goto Err;
// Note this padding is historical and differs from demux.c which does not
// pad the file size.
riff_size = SizeWithPadding(riff_size);
if (riff_size < CHUNK_HEADER_SIZE) goto Err;
if (riff_size > size) goto Err;
// There's no point in reading past the end of the RIFF chunk.
if (size > riff_size + CHUNK_HEADER_SIZE) {
size = riff_size + CHUNK_HEADER_SIZE;
}
end = data + size;
@@ -226,7 +238,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
while (data != end) {
size_t data_size;
WebPChunkId id;
WebPChunk** chunk_list;
if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
copy_data) != WEBP_MUX_OK) {
goto Err;
@@ -236,11 +247,11 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
switch (id) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err;
if (!MuxImageFinalize(wpi)) goto Err;
wpi->is_partial_ = 0; // wpi is completely filled.
PushImage:
@@ -257,9 +268,13 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
default: // A non-image chunk.
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 (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
if (chunk_list_ends[id] == NULL) {
chunk_list_ends[id] =
MuxGetChunkListFromId(mux, id); // List to add this chunk.
}
if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
if (id == WEBP_CHUNK_VP8X) { // grab global specs
if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
mux->canvas_width_ = GetLE24(data + 12) + 1;
mux->canvas_height_ = GetLE24(data + 15) + 1;
}
@@ -385,6 +400,10 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
// There should be at most one alpha_ chunk and exactly one img_ chunk.
assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL);
assert(wpi->img_ != NULL && wpi->img_->next_ == NULL);
// Main RIFF header.
dst = MuxEmitRiffHeader(data, size);