mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
Incremental support for some of the mux APIs.
This CL adds incremental support for WebPMuxCreate() and WebPMuxGetFeatures() Change-Id: I312122f5e817d58366e18ae238cb9e2a493811fb
This commit is contained in:
parent
2e74ec8b5f
commit
8d6490dae6
@ -355,15 +355,16 @@ static int ReadData(const char* filename, void** data_ptr, uint32_t* size_ptr) {
|
|||||||
static int ReadFile(const char* const filename, WebPMux** mux) {
|
static int ReadFile(const char* const filename, WebPMux** mux) {
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
void* data = NULL;
|
void* data = NULL;
|
||||||
|
WebPMuxState mux_state;
|
||||||
|
|
||||||
assert(mux != NULL);
|
assert(mux != NULL);
|
||||||
|
|
||||||
if (!ReadData(filename, &data, &size)) return 0;
|
if (!ReadData(filename, &data, &size)) return 0;
|
||||||
*mux = WebPMuxCreate((const uint8_t*)data, size, 1);
|
*mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state);
|
||||||
free(data);
|
free(data);
|
||||||
if (*mux != NULL) return 1;
|
if (*mux != NULL && mux_state == WEBP_MUX_STATE_COMPLETE) return 1;
|
||||||
fprintf(stderr, "Failed to create mux object from file %s.\n",
|
fprintf(stderr, "Failed to create mux object from file %s. mux_state = %d.\n",
|
||||||
filename);
|
filename, mux_state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,14 +378,16 @@ static int ReadImage(const char* filename,
|
|||||||
WebPMux* mux;
|
WebPMux* mux;
|
||||||
WebPMuxError err;
|
WebPMuxError err;
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
|
WebPMuxState mux_state;
|
||||||
|
|
||||||
if (!ReadData(filename, &data, &size)) return 0;
|
if (!ReadData(filename, &data, &size)) return 0;
|
||||||
|
|
||||||
mux = WebPMuxCreate((const uint8_t*)data, size, 1);
|
mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state);
|
||||||
free(data);
|
free(data);
|
||||||
if (mux == NULL) {
|
if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) {
|
||||||
fprintf(stderr, "Failed to create mux object from file %s.\n",
|
fprintf(stderr,
|
||||||
filename);
|
"Failed to create mux object from file %s. mux_state = %d.\n",
|
||||||
|
filename, mux_state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
err = WebPMuxGetImage(mux, (const uint8_t**)&data, &size,
|
err = WebPMuxGetImage(mux, (const uint8_t**)&data, &size,
|
||||||
|
@ -23,6 +23,7 @@ extern "C" {
|
|||||||
static int MuxInit(WebPMux* const mux) {
|
static int MuxInit(WebPMux* const mux) {
|
||||||
if (mux == NULL) return 0;
|
if (mux == NULL) return 0;
|
||||||
memset(mux, 0, sizeof(*mux));
|
memset(mux, 0, sizeof(*mux));
|
||||||
|
mux->state_ = WEBP_MUX_STATE_PARTIAL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,8 +180,11 @@ static WebPMuxError GetImageData(const uint8_t* data, uint32_t size,
|
|||||||
// It is webp file data. Extract image data from it.
|
// It is webp file data. Extract image data from it.
|
||||||
WebPMux* mux;
|
WebPMux* mux;
|
||||||
WebPMuxError err;
|
WebPMuxError err;
|
||||||
mux = WebPMuxCreate(data, size, 0);
|
WebPMuxState mux_state;
|
||||||
if (mux == NULL) return WEBP_MUX_BAD_DATA;
|
mux = WebPMuxCreate(data, size, 0, &mux_state);
|
||||||
|
if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) {
|
||||||
|
return WEBP_MUX_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
err = WebPMuxGetImage(mux, image_data, image_size, alpha_data, alpha_size);
|
err = WebPMuxGetImage(mux, image_data, image_size, alpha_data, alpha_size);
|
||||||
WebPMuxDelete(mux);
|
WebPMuxDelete(mux);
|
||||||
@ -634,6 +638,9 @@ WebPMuxError WebPMuxAssemble(WebPMux* const mux, uint8_t** output_data,
|
|||||||
err = CreateVP8XChunk(mux);
|
err = CreateVP8XChunk(mux);
|
||||||
if (err != WEBP_MUX_OK) return err;
|
if (err != WEBP_MUX_OK) return err;
|
||||||
|
|
||||||
|
// Mark mux as complete.
|
||||||
|
mux->state_ = WEBP_MUX_STATE_COMPLETE;
|
||||||
|
|
||||||
// Allocate data.
|
// Allocate data.
|
||||||
size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_)
|
size = ChunksListDiskSize(mux->vp8x_) + ChunksListDiskSize(mux->iccp_)
|
||||||
+ ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_)
|
+ ChunksListDiskSize(mux->loop_) + MuxImageListDiskSize(mux->images_)
|
||||||
|
@ -59,6 +59,7 @@ struct WebPMuxImage {
|
|||||||
|
|
||||||
// Main mux object. Stores data chunks.
|
// Main mux object. Stores data chunks.
|
||||||
struct WebPMux {
|
struct WebPMux {
|
||||||
|
WebPMuxState state_;
|
||||||
WebPMuxImage* images_;
|
WebPMuxImage* images_;
|
||||||
WebPChunk* iccp_;
|
WebPChunk* iccp_;
|
||||||
WebPChunk* meta_;
|
WebPChunk* meta_;
|
||||||
@ -121,6 +122,10 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
|
|||||||
PutLE16(data + 2, val >> 16);
|
PutLE16(data + 2, val >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE uint32_t SizeWithPadding(uint32_t chunk_size) {
|
||||||
|
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Chunk object management.
|
// Chunk object management.
|
||||||
|
|
||||||
@ -154,7 +159,7 @@ WebPChunk* ChunkDelete(WebPChunk* const chunk);
|
|||||||
// Size of a chunk including header and padding.
|
// Size of a chunk including header and padding.
|
||||||
static WEBP_INLINE uint32_t ChunkDiskSize(const WebPChunk* chunk) {
|
static WEBP_INLINE uint32_t ChunkDiskSize(const WebPChunk* chunk) {
|
||||||
assert(chunk->payload_size_ < MAX_CHUNK_PAYLOAD);
|
assert(chunk->payload_size_ < MAX_CHUNK_PAYLOAD);
|
||||||
return CHUNK_HEADER_SIZE + ((chunk->payload_size_ + 1) & ~1U);
|
return SizeWithPadding(chunk->payload_size_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total size of a list of chunks.
|
// Total size of a list of chunks.
|
||||||
@ -169,6 +174,9 @@ uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst);
|
|||||||
// Initialize.
|
// Initialize.
|
||||||
void MuxImageInit(WebPMuxImage* const wpi);
|
void MuxImageInit(WebPMuxImage* const wpi);
|
||||||
|
|
||||||
|
// Delete image 'wpi'.
|
||||||
|
WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi);
|
||||||
|
|
||||||
// Delete all images in 'wpi_list'.
|
// Delete all images in 'wpi_list'.
|
||||||
void MuxImageDeleteAll(WebPMuxImage** const wpi_list);
|
void MuxImageDeleteAll(WebPMuxImage** const wpi_list);
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ WebPMuxError MuxImageSetNth(const WebPMuxImage* wpi, WebPMuxImage** wpi_list,
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// MuxImage deletion methods.
|
// MuxImage deletion methods.
|
||||||
|
|
||||||
static WebPMuxImage* DeleteImage(WebPMuxImage* const wpi) {
|
WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
|
||||||
WebPMuxImage* const next = MuxImageRelease(wpi);
|
WebPMuxImage* const next = MuxImageRelease(wpi);
|
||||||
free(wpi);
|
free(wpi);
|
||||||
return next;
|
return next;
|
||||||
@ -352,7 +352,7 @@ static WebPMuxImage* DeleteImage(WebPMuxImage* const wpi) {
|
|||||||
|
|
||||||
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
|
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
|
||||||
while (*wpi_list) {
|
while (*wpi_list) {
|
||||||
*wpi_list = DeleteImage(*wpi_list);
|
*wpi_list = MuxImageDelete(*wpi_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ WebPMuxError MuxImageDeleteNth(WebPMuxImage** wpi_list, uint32_t nth,
|
|||||||
if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) {
|
if (!SearchImageToGetOrDelete(wpi_list, nth, id, &wpi_list)) {
|
||||||
return WEBP_MUX_NOT_FOUND;
|
return WEBP_MUX_NOT_FOUND;
|
||||||
}
|
}
|
||||||
*wpi_list = DeleteImage(*wpi_list);
|
*wpi_list = MuxImageDelete(*wpi_list);
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +474,12 @@ WebPMuxError WebPMuxValidate(const WebPMux* const mux) {
|
|||||||
WebPMuxError err;
|
WebPMuxError err;
|
||||||
|
|
||||||
// Verify mux is not NULL.
|
// Verify mux is not NULL.
|
||||||
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux == NULL || mux->state_ == WEBP_MUX_STATE_ERROR) {
|
||||||
|
return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No further checks if mux is partial.
|
||||||
|
if (mux->state_ == WEBP_MUX_STATE_PARTIAL) return WEBP_MUX_OK;
|
||||||
|
|
||||||
// Verify mux has at least one image.
|
// Verify mux has at least one image.
|
||||||
if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux->images_ == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
@ -53,107 +53,142 @@ static WebPMuxError MuxGet(const WebPMux* const mux, TAG_ID id, uint32_t nth,
|
|||||||
// Fill the chunk with the given data, after verifying that the data size
|
// Fill the chunk with the given data, after verifying that the data size
|
||||||
// doesn't exceed 'max_size'.
|
// doesn't exceed 'max_size'.
|
||||||
static WebPMuxError ChunkAssignData(WebPChunk* chunk, const uint8_t* data,
|
static WebPMuxError ChunkAssignData(WebPChunk* chunk, const uint8_t* data,
|
||||||
uint32_t max_size, int copy_data) {
|
uint32_t data_size, uint32_t riff_size,
|
||||||
uint32_t size = 0;
|
int copy_data) {
|
||||||
assert(max_size >= CHUNK_HEADER_SIZE);
|
uint32_t chunk_size;
|
||||||
|
|
||||||
size = GetLE32(data + 4);
|
// Sanity checks.
|
||||||
assert(size <= MAX_CHUNK_PAYLOAD);
|
if (data_size < TAG_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
|
||||||
if (size + CHUNK_HEADER_SIZE > max_size) {
|
chunk_size = GetLE32(data + TAG_SIZE);
|
||||||
return WEBP_MUX_INVALID_ARGUMENT;
|
|
||||||
|
{
|
||||||
|
const uint32_t chunk_disk_size = SizeWithPadding(chunk_size);
|
||||||
|
if (chunk_disk_size > riff_size) return WEBP_MUX_BAD_DATA;
|
||||||
|
if (chunk_disk_size > data_size) return WEBP_MUX_NOT_ENOUGH_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ChunkAssignDataImageInfo(chunk, data + CHUNK_HEADER_SIZE, size, NULL,
|
// Data assignment.
|
||||||
copy_data, GetLE32(data + 0));
|
return ChunkAssignDataImageInfo(chunk, data + CHUNK_HEADER_SIZE, chunk_size,
|
||||||
|
NULL, copy_data, GetLE32(data + 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Create a mux object from WebP-RIFF data.
|
// Create a mux object from WebP-RIFF data.
|
||||||
|
|
||||||
WebPMux* WebPMuxCreate(const uint8_t* data, uint32_t size, int copy_data) {
|
WebPMux* WebPMuxCreate(const uint8_t* data, uint32_t size, int copy_data,
|
||||||
uint32_t mux_size;
|
WebPMuxState* const mux_state) {
|
||||||
|
uint32_t riff_size;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
const uint8_t* end;
|
const uint8_t* end;
|
||||||
TAG_ID id;
|
TAG_ID id;
|
||||||
WebPMux* mux;
|
WebPMux* mux = NULL;
|
||||||
WebPMuxImage wpi;
|
WebPMuxImage* wpi = NULL;
|
||||||
|
|
||||||
// Sanity checks on size and leading bytes.
|
if (mux_state) *mux_state = WEBP_MUX_STATE_PARTIAL;
|
||||||
if (data == NULL) return NULL;
|
|
||||||
if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) {
|
// Sanity checks.
|
||||||
return NULL;
|
if (data == NULL) goto Err;
|
||||||
}
|
if (size < RIFF_HEADER_SIZE) return NULL;
|
||||||
if (GetLE32(data + 0) != mktag('R', 'I', 'F', 'F') ||
|
if (GetLE32(data + 0) != mktag('R', 'I', 'F', 'F') ||
|
||||||
GetLE32(data + 8) != mktag('W', 'E', 'B', 'P')) {
|
GetLE32(data + CHUNK_HEADER_SIZE) != mktag('W', 'E', 'B', 'P')) {
|
||||||
return NULL;
|
goto Err;
|
||||||
}
|
}
|
||||||
mux_size = CHUNK_HEADER_SIZE + GetLE32(data + TAG_SIZE);
|
|
||||||
if (mux_size > size) {
|
mux = WebPMuxNew();
|
||||||
return NULL;
|
if (mux == NULL) goto Err;
|
||||||
|
|
||||||
|
if (size < RIFF_HEADER_SIZE + TAG_SIZE) {
|
||||||
|
mux->state_ = WEBP_MUX_STATE_PARTIAL;
|
||||||
|
goto Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag = GetLE32(data + RIFF_HEADER_SIZE);
|
tag = GetLE32(data + RIFF_HEADER_SIZE);
|
||||||
if (tag != kChunks[IMAGE_ID].chunkTag && tag != kChunks[VP8X_ID].chunkTag) {
|
if (tag != kChunks[IMAGE_ID].chunkTag && tag != kChunks[VP8X_ID].chunkTag) {
|
||||||
// First chunk should be either VP8X or VP8.
|
// First chunk should be either VP8X or VP8.
|
||||||
return NULL;
|
goto Err;
|
||||||
}
|
}
|
||||||
end = data + mux_size;
|
|
||||||
|
riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
|
||||||
|
if (riff_size > MAX_CHUNK_PAYLOAD) {
|
||||||
|
goto Err;
|
||||||
|
} else if (riff_size > size) {
|
||||||
|
mux->state_ = WEBP_MUX_STATE_PARTIAL;
|
||||||
|
} else {
|
||||||
|
mux->state_ = WEBP_MUX_STATE_COMPLETE;
|
||||||
|
if (riff_size < size) { // Redundant data after last chunk.
|
||||||
|
size = riff_size; // To make sure we don't read any data beyond mux_size.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end = data + size;
|
||||||
data += RIFF_HEADER_SIZE;
|
data += RIFF_HEADER_SIZE;
|
||||||
mux_size -= RIFF_HEADER_SIZE;
|
size -= RIFF_HEADER_SIZE;
|
||||||
|
|
||||||
mux = WebPMuxNew();
|
wpi = (WebPMuxImage*)malloc(sizeof(*wpi));
|
||||||
if (mux == NULL) return NULL;
|
MuxImageInit(wpi);
|
||||||
|
|
||||||
MuxImageInit(&wpi);
|
|
||||||
|
|
||||||
// Loop over chunks.
|
// Loop over chunks.
|
||||||
while (data != end) {
|
while (data != end) {
|
||||||
WebPChunk chunk;
|
WebPChunk chunk;
|
||||||
uint32_t data_size;
|
WebPMuxError err;
|
||||||
|
|
||||||
ChunkInit(&chunk);
|
ChunkInit(&chunk);
|
||||||
if (ChunkAssignData(&chunk, data, mux_size, copy_data) != WEBP_MUX_OK) {
|
err = ChunkAssignData(&chunk, data, size, riff_size, copy_data);
|
||||||
goto Err;
|
if (err != WEBP_MUX_OK) {
|
||||||
|
if (err == WEBP_MUX_NOT_ENOUGH_DATA &&
|
||||||
|
mux->state_ == WEBP_MUX_STATE_PARTIAL) {
|
||||||
|
goto Ok;
|
||||||
|
} else {
|
||||||
|
goto Err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data_size = ChunkDiskSize(&chunk);
|
|
||||||
id = ChunkGetIdFromTag(chunk.tag_);
|
id = ChunkGetIdFromTag(chunk.tag_);
|
||||||
|
|
||||||
if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8).
|
if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8).
|
||||||
WebPChunk** wpi_chunk_ptr;
|
WebPChunk** wpi_chunk_ptr;
|
||||||
wpi_chunk_ptr = MuxImageGetListFromId(&wpi, id); // Image chunk to set.
|
wpi_chunk_ptr = MuxImageGetListFromId(wpi, id); // Image chunk to set.
|
||||||
assert(wpi_chunk_ptr != NULL);
|
assert(wpi_chunk_ptr != NULL);
|
||||||
if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or
|
if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or
|
||||||
// consecutive frame/tile chunks.
|
// consecutive frame/tile chunks.
|
||||||
if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err;
|
if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err;
|
||||||
if (id == IMAGE_ID) {
|
if (id == IMAGE_ID) {
|
||||||
wpi.is_partial_ = 0; // wpi is completely filled.
|
wpi->is_partial_ = 0; // wpi is completely filled.
|
||||||
// Add this to mux->images_ list.
|
// Add this to mux->images_ list.
|
||||||
if (MuxImageSetNth(&wpi, &mux->images_, 0) != WEBP_MUX_OK) goto Err;
|
if (MuxImageSetNth(wpi, &mux->images_, 0) != WEBP_MUX_OK) goto Err;
|
||||||
MuxImageInit(&wpi); // Reset for reading next image.
|
MuxImageInit(wpi); // Reset for reading next image.
|
||||||
} else {
|
} else {
|
||||||
wpi.is_partial_ = 1; // wpi is only partially filled.
|
wpi->is_partial_ = 1; // wpi is only partially filled.
|
||||||
}
|
}
|
||||||
} else { // A non-image chunk.
|
} else { // A non-image chunk.
|
||||||
WebPChunk** chunk_list;
|
WebPChunk** chunk_list;
|
||||||
if (wpi.is_partial_) goto Err; // Encountered a non-image chunk before
|
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
|
||||||
// getting all chunks of an image.
|
// getting all chunks of an image.
|
||||||
chunk_list = GetChunkListFromId(mux, id); // List for adding this chunk.
|
chunk_list = GetChunkListFromId(mux, id); // List for adding this chunk.
|
||||||
if (chunk_list == NULL) chunk_list = (WebPChunk**)&mux->unknown_;
|
if (chunk_list == NULL) chunk_list = (WebPChunk**)&mux->unknown_;
|
||||||
if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
|
if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
data += data_size;
|
{
|
||||||
mux_size -= data_size;
|
const uint32_t data_size = ChunkDiskSize(&chunk);
|
||||||
|
data += data_size;
|
||||||
|
size -= data_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate mux.
|
// Validate mux if complete.
|
||||||
if (WebPMuxValidate(mux) != WEBP_MUX_OK) goto Err;
|
if (WebPMuxValidate(mux) != WEBP_MUX_OK) goto Err;
|
||||||
|
|
||||||
|
Ok:
|
||||||
|
MuxImageDelete(wpi);
|
||||||
|
if (mux_state) *mux_state = mux->state_;
|
||||||
return mux; // All OK;
|
return mux; // All OK;
|
||||||
|
|
||||||
Err: // Something bad happened.
|
Err: // Something bad happened.
|
||||||
WebPMuxDelete(mux);
|
MuxImageDelete(wpi);
|
||||||
return NULL;
|
WebPMuxDelete(mux);
|
||||||
|
if (mux_state) *mux_state = WEBP_MUX_STATE_ERROR;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -165,18 +200,29 @@ WebPMuxError WebPMuxGetFeatures(const WebPMux* const mux, uint32_t* flags) {
|
|||||||
WebPMuxError err;
|
WebPMuxError err;
|
||||||
|
|
||||||
if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
|
||||||
|
*flags = 0;
|
||||||
|
|
||||||
|
// Check if VP8X chunk is present.
|
||||||
err = MuxGet(mux, VP8X_ID, 1, &data, &data_size);
|
err = MuxGet(mux, VP8X_ID, 1, &data, &data_size);
|
||||||
if (err == WEBP_MUX_NOT_FOUND) { // Single image case.
|
if (err == WEBP_MUX_NOT_FOUND) {
|
||||||
*flags = 0;
|
// Check if VP8 chunk is present.
|
||||||
return WEBP_MUX_OK;
|
err = WebPMuxGetImage(mux, &data, &data_size, NULL, NULL);
|
||||||
|
if (err == WEBP_MUX_NOT_FOUND && // Data not available (yet).
|
||||||
|
mux->state_ == WEBP_MUX_STATE_PARTIAL) { // Incremental case.
|
||||||
|
return WEBP_MUX_NOT_ENOUGH_DATA;
|
||||||
|
} else {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
} else if (err != WEBP_MUX_OK) {
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple image case.
|
// TODO(urvang): Add a '#define CHUNK_SIZE_BYTES 4' and use it instead of
|
||||||
if (err != WEBP_MUX_OK) return err;
|
// hard-coded value of 4 everywhere.
|
||||||
if (data_size < 4) return WEBP_MUX_BAD_DATA;
|
if (data_size < 4) return WEBP_MUX_BAD_DATA;
|
||||||
*flags = GetLE32(data);
|
|
||||||
|
|
||||||
|
// All OK. Fill up flags.
|
||||||
|
*flags = GetLE32(data);
|
||||||
return WEBP_MUX_OK;
|
return WEBP_MUX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
//
|
//
|
||||||
// int copy_data = 0;
|
// int copy_data = 0;
|
||||||
// // ... (Read data from file).
|
// // ... (Read data from file).
|
||||||
// WebPMux* mux = WebPMuxCreate(data, data_size, copy_data);
|
// WebPMux* mux = WebPMuxCreate(data, data_size, copy_data, NULL);
|
||||||
// WebPMuxGetImage(mux, &image_data, &image_data_size,
|
// WebPMuxGetImage(mux, &image_data, &image_data_size,
|
||||||
// &alpha_data, &alpha_size);
|
// &alpha_data, &alpha_size);
|
||||||
// // ... (Consume image_data; e.g. call WebPDecode() to decode the data).
|
// // ... (Consume image_data; e.g. call WebPDecode() to decode the data).
|
||||||
@ -60,9 +60,16 @@ typedef enum {
|
|||||||
WEBP_MUX_INVALID_ARGUMENT = -2,
|
WEBP_MUX_INVALID_ARGUMENT = -2,
|
||||||
WEBP_MUX_INVALID_PARAMETER = -3,
|
WEBP_MUX_INVALID_PARAMETER = -3,
|
||||||
WEBP_MUX_BAD_DATA = -4,
|
WEBP_MUX_BAD_DATA = -4,
|
||||||
WEBP_MUX_MEMORY_ERROR = -5
|
WEBP_MUX_MEMORY_ERROR = -5,
|
||||||
|
WEBP_MUX_NOT_ENOUGH_DATA = -6
|
||||||
} WebPMuxError;
|
} WebPMuxError;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WEBP_MUX_STATE_PARTIAL = 0,
|
||||||
|
WEBP_MUX_STATE_COMPLETE = 1,
|
||||||
|
WEBP_MUX_STATE_ERROR = -1
|
||||||
|
} WebPMuxState;
|
||||||
|
|
||||||
// Flag values for different features used in VP8X chunk.
|
// Flag values for different features used in VP8X chunk.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TILE_FLAG = 0x00000001,
|
TILE_FLAG = 0x00000001,
|
||||||
@ -96,11 +103,13 @@ WEBP_EXTERN(void) WebPMuxDelete(WebPMux* const mux);
|
|||||||
// size - (in) size of raw data
|
// size - (in) size of raw data
|
||||||
// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
|
// copy_data - (in) value 1 indicates given data WILL copied to the mux, and
|
||||||
// value 0 indicates data will NOT be copied.
|
// value 0 indicates data will NOT be copied.
|
||||||
|
// mux_state - (out) indicates the state of the mux returned. Can be passed
|
||||||
|
// NULL if not required.
|
||||||
// Returns:
|
// Returns:
|
||||||
// A pointer to the mux object created from given data - on success.
|
// A pointer to the mux object created from given data - on success.
|
||||||
// NULL - In case of invalid data or memory error.
|
// NULL - In case of invalid data or memory error.
|
||||||
WEBP_EXTERN(WebPMux*) WebPMuxCreate(const uint8_t* data, uint32_t size,
|
WEBP_EXTERN(WebPMux*) WebPMuxCreate(const uint8_t* data, uint32_t size,
|
||||||
int copy_data);
|
int copy_data, WebPMuxState* mux_state);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Single Image.
|
// Single Image.
|
||||||
|
Loading…
Reference in New Issue
Block a user