summaryrefslogtreecommitdiff
path: root/drivers/webp/mux/muxread.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/webp/mux/muxread.c')
-rw-r--r--drivers/webp/mux/muxread.c437
1 files changed, 154 insertions, 283 deletions
diff --git a/drivers/webp/mux/muxread.c b/drivers/webp/mux/muxread.c
index 6003a25b71..21c3cfbaeb 100644
--- a/drivers/webp/mux/muxread.c
+++ b/drivers/webp/mux/muxread.c
@@ -1,10 +1,8 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
-// Use of this source code is governed by a BSD-style license
-// that can be found in the COPYING file in the root of the source
-// tree. An additional intellectual property rights grant can be found
-// in the file PATENTS. All contributing project authors may
-// be found in the AUTHORS file in the root of the source tree.
+// This code is licensed under the same terms as WebM:
+// Software License Agreement: http://www.webmproject.org/license/software/
+// Additional IP Rights Grant: http://www.webmproject.org/license/additional/
// -----------------------------------------------------------------------------
//
// Read APIs for mux.
@@ -14,7 +12,10 @@
#include <assert.h>
#include "./muxi.h"
-#include "../utils/utils.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
//------------------------------------------------------------------------------
// Helper method(s).
@@ -40,9 +41,8 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
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_LOOP, mux->loop_);
+ SWITCH_ID_LIST(IDX_META, mux->meta_);
SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_);
return WEBP_MUX_NOT_FOUND;
}
@@ -50,9 +50,10 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx,
// Fill the chunk with the given data (includes chunk header bytes), after some
// verifications.
-static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
- const uint8_t* data, size_t data_size,
- size_t riff_size, int copy_data) {
+static WebPMuxError ChunkVerifyAndAssignData(WebPChunk* chunk,
+ const uint8_t* data,
+ size_t data_size, size_t riff_size,
+ int copy_data) {
uint32_t chunk_size;
WebPData chunk_data;
@@ -67,103 +68,11 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
}
// Data assignment.
- chunk_data.bytes = data + CHUNK_HEADER_SIZE;
- chunk_data.size = chunk_size;
+ chunk_data.bytes_ = data + CHUNK_HEADER_SIZE;
+ chunk_data.size_ = chunk_size;
return ChunkAssignData(chunk, &chunk_data, copy_data, GetLE32(data + 0));
}
-int MuxImageFinalize(WebPMuxImage* const wpi) {
- const WebPChunk* const img = wpi->img_;
- const WebPData* const image = &img->data_;
- const int is_lossless = (img->tag_ == kChunks[IDX_VP8L].tag);
- int w, h;
- int vp8l_has_alpha = 0;
- const int ok = is_lossless ?
- VP8LGetInfo(image->bytes, image->size, &w, &h, &vp8l_has_alpha) :
- VP8GetInfo(image->bytes, image->size, image->size, &w, &h);
- assert(img != NULL);
- if (ok) {
- // Ignore ALPH chunk accompanying VP8L.
- if (is_lossless && (wpi->alpha_ != NULL)) {
- ChunkDelete(wpi->alpha_);
- wpi->alpha_ = NULL;
- }
- wpi->width_ = w;
- wpi->height_ = h;
- wpi->has_alpha_ = vp8l_has_alpha || (wpi->alpha_ != NULL);
- }
- return ok;
-}
-
-static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
- WebPMuxImage* const wpi) {
- const uint8_t* bytes = chunk->data_.bytes;
- size_t size = chunk->data_.size;
- const uint8_t* const last = bytes + size;
- WebPChunk subchunk;
- size_t subchunk_size;
- ChunkInit(&subchunk);
-
- assert(chunk->tag_ == kChunks[IDX_ANMF].tag ||
- chunk->tag_ == kChunks[IDX_FRGM].tag);
- assert(!wpi->is_partial_);
-
- // ANMF/FRGM.
- {
- const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ?
- ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
- const WebPData temp = { bytes, hdr_size };
- // Each of ANMF and FRGM chunk contain a header at the beginning. So, its
- // size should at least be 'hdr_size'.
- if (size < hdr_size) goto Fail;
- ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
- }
- ChunkSetNth(&subchunk, &wpi->header_, 1);
- wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.
-
- // Rest of the chunks.
- subchunk_size = ChunkDiskSize(&subchunk) - CHUNK_HEADER_SIZE;
- bytes += subchunk_size;
- size -= subchunk_size;
-
- while (bytes != last) {
- ChunkInit(&subchunk);
- if (ChunkVerifyAndAssign(&subchunk, bytes, size, size,
- copy_data) != WEBP_MUX_OK) {
- goto Fail;
- }
- 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;
- 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 (!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;
- break;
- default:
- goto Fail;
- break;
- }
- subchunk_size = ChunkDiskSize(&subchunk);
- bytes += subchunk_size;
- size -= subchunk_size;
- }
- if (wpi->is_partial_) goto Fail;
- return 1;
-
- Fail:
- ChunkRelease(&subchunk);
- return 0;
-}
-
//------------------------------------------------------------------------------
// Create a mux object from WebP-RIFF data.
@@ -185,8 +94,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
}
if (bitstream == NULL) return NULL;
- data = bitstream->bytes;
- size = bitstream->size;
+ data = bitstream->bytes_;
+ size = bitstream->size_;
if (data == NULL) return NULL;
if (size < RIFF_HEADER_SIZE) return NULL;
@@ -226,48 +135,42 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
// Loop over chunks.
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;
- }
- data_size = ChunkDiskSize(&chunk);
+ WebPMuxError err;
+
+ err = ChunkVerifyAndAssignData(&chunk, data, size, riff_size, copy_data);
+ if (err != WEBP_MUX_OK) goto Err;
+
id = ChunkGetIdFromTag(chunk.tag_);
- 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;
- 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 (!MuxImageFinalize(wpi)) goto Err;
+
+ if (IsWPI(id)) { // An image chunk (frame/tile/alpha/vp8).
+ WebPChunk** wpi_chunk_ptr =
+ MuxImageGetListFromId(wpi, id); // Image chunk to set.
+ assert(wpi_chunk_ptr != NULL);
+ if (*wpi_chunk_ptr != NULL) goto Err; // Consecutive alpha chunks or
+ // consecutive frame/tile chunks.
+ if (ChunkSetNth(&chunk, wpi_chunk_ptr, 1) != WEBP_MUX_OK) goto Err;
+ if (id == WEBP_CHUNK_IMAGE) {
wpi->is_partial_ = 0; // wpi is completely filled.
- PushImage:
// Add this to mux->images_ list.
if (MuxImagePush(wpi, &mux->images_) != WEBP_MUX_OK) goto Err;
MuxImageInit(wpi); // Reset for reading next image.
- break;
- case WEBP_CHUNK_ANMF:
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- case WEBP_CHUNK_FRGM:
-#endif
- if (wpi->is_partial_) goto Err; // Previous wpi is still incomplete.
- if (!MuxImageParse(&chunk, copy_data, wpi)) goto Err;
- ChunkRelease(&chunk);
- goto PushImage;
- break;
- 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;
- break;
+ } else {
+ wpi->is_partial_ = 1; // wpi is only partially filled.
+ }
+ } else { // A non-image chunk.
+ WebPChunk** chunk_list;
+ 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;
+ }
+ {
+ const size_t data_size = ChunkDiskSize(&chunk);
+ data += data_size;
+ size -= data_size;
}
- data += data_size;
- size -= data_size;
ChunkInit(&chunk);
}
@@ -287,66 +190,29 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
//------------------------------------------------------------------------------
// Get API(s).
-// Validates that the given mux has a single image.
-static WebPMuxError ValidateForSingleImage(const WebPMux* const mux) {
- const int num_images = MuxImageCount(mux->images_, WEBP_CHUNK_IMAGE);
- const int num_frames = MuxImageCount(mux->images_, WEBP_CHUNK_ANMF);
- const int num_fragments = MuxImageCount(mux->images_, WEBP_CHUNK_FRGM);
-
- if (num_images == 0) {
- // No images in mux.
- return WEBP_MUX_NOT_FOUND;
- } else if (num_images == 1 && num_frames == 0 && num_fragments == 0) {
- // Valid case (single image).
- return WEBP_MUX_OK;
- } else {
- // Frame/Fragment case OR an invalid mux.
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-}
-
-// Get the canvas width, height and flags after validating that VP8X/VP8/VP8L
-// chunk and canvas size are valid.
-static WebPMuxError MuxGetCanvasInfo(const WebPMux* const mux,
- int* width, int* height, uint32_t* flags) {
- int w, h;
- uint32_t f = 0;
+WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
WebPData data;
- assert(mux != NULL);
+ WebPMuxError err;
+
+ if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ *flags = 0;
// Check if VP8X chunk is present.
- if (MuxGet(mux, IDX_VP8X, 1, &data) == WEBP_MUX_OK) {
- if (data.size < VP8X_CHUNK_SIZE) return WEBP_MUX_BAD_DATA;
- f = GetLE32(data.bytes + 0);
- w = GetLE24(data.bytes + 4) + 1;
- h = GetLE24(data.bytes + 7) + 1;
- } else { // Single image case.
- const WebPMuxImage* const wpi = mux->images_;
- WebPMuxError err = ValidateForSingleImage(mux);
- if (err != WEBP_MUX_OK) return err;
- assert(wpi != NULL);
- w = wpi->width_;
- h = wpi->height_;
- if (wpi->has_alpha_) f |= ALPHA_FLAG;
+ err = MuxGet(mux, IDX_VP8X, 1, &data);
+ if (err == WEBP_MUX_NOT_FOUND) {
+ // Check if VP8/VP8L chunk is present.
+ err = WebPMuxGetImage(mux, &data);
+ WebPDataClear(&data);
+ return err;
+ } else if (err != WEBP_MUX_OK) {
+ return err;
}
- if (w * (uint64_t)h >= MAX_IMAGE_AREA) return WEBP_MUX_BAD_DATA;
- if (width != NULL) *width = w;
- if (height != NULL) *height = h;
- if (flags != NULL) *flags = f;
- return WEBP_MUX_OK;
-}
-
-WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, int* width, int* height) {
- if (mux == NULL || width == NULL || height == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- return MuxGetCanvasInfo(mux, width, height, NULL);
-}
+ if (data.size_ < CHUNK_SIZE_BYTES) return WEBP_MUX_BAD_DATA;
-WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, uint32_t* flags) {
- if (mux == NULL || flags == NULL) return WEBP_MUX_INVALID_ARGUMENT;
- return MuxGetCanvasInfo(mux, NULL, NULL, flags);
+ // All OK. Fill up flags.
+ *flags = GetLE32(data.bytes_);
+ return WEBP_MUX_OK;
}
static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
@@ -364,7 +230,7 @@ static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
}
// Assemble a single image WebP bitstream from 'wpi'.
-static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
+static WebPMuxError SynthesizeBitstream(WebPMuxImage* const wpi,
WebPData* const bitstream) {
uint8_t* dst;
@@ -372,7 +238,7 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
const int need_vp8x = (wpi->alpha_ != NULL);
const size_t vp8x_size = need_vp8x ? CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE : 0;
const size_t alpha_size = need_vp8x ? ChunkDiskSize(wpi->alpha_) : 0;
- // Note: No need to output ANMF/FRGM chunk for a single image.
+ // Note: No need to output FRM/TILE chunk for a single image.
const size_t size = RIFF_HEADER_SIZE + vp8x_size + alpha_size +
ChunkDiskSize(wpi->img_);
uint8_t* const data = (uint8_t*)malloc(size);
@@ -382,7 +248,15 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
dst = MuxEmitRiffHeader(data, size);
if (need_vp8x) {
- dst = EmitVP8XChunk(dst, wpi->width_, wpi->height_, ALPHA_FLAG); // VP8X.
+ int w, h;
+ WebPMuxError err;
+ assert(wpi->img_ != NULL);
+ err = MuxGetImageWidthHeight(wpi->img_, &w, &h);
+ if (err != WEBP_MUX_OK) {
+ free(data);
+ return err;
+ }
+ dst = EmitVP8XChunk(dst, w, h, ALPHA_FLAG); // VP8X.
dst = ChunkListEmit(wpi->alpha_, dst); // ALPH.
}
@@ -391,117 +265,107 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
assert(dst == data + size);
// Output.
- bitstream->bytes = data;
- bitstream->size = size;
+ bitstream->bytes_ = data;
+ bitstream->size_ = size;
return WEBP_MUX_OK;
}
-WebPMuxError WebPMuxGetChunk(const WebPMux* mux, const char fourcc[4],
- WebPData* chunk_data) {
- CHUNK_INDEX idx;
- if (mux == NULL || fourcc == NULL || chunk_data == NULL) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
- idx = ChunkGetIndexFromFourCC(fourcc);
- if (IsWPI(kChunks[idx].id)) { // An image chunk.
+WebPMuxError WebPMuxGetImage(const WebPMux* mux, WebPData* bitstream) {
+ WebPMuxError err;
+ WebPMuxImage* wpi = NULL;
+
+ if (mux == NULL || bitstream == NULL) {
return WEBP_MUX_INVALID_ARGUMENT;
- } else if (idx != IDX_UNKNOWN) { // A known chunk type.
- return MuxGet(mux, idx, 1, chunk_data);
- } else { // An unknown chunk type.
- const WebPChunk* const chunk =
- ChunkSearchList(mux->unknown_, 1, ChunkGetTagFromFourCC(fourcc));
- if (chunk == NULL) return WEBP_MUX_NOT_FOUND;
- *chunk_data = chunk->data_;
- return WEBP_MUX_OK;
}
+
+ err = MuxValidateForImage(mux);
+ if (err != WEBP_MUX_OK) return err;
+
+ // All well. Get the image.
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, WEBP_CHUNK_IMAGE,
+ &wpi);
+ assert(err == WEBP_MUX_OK); // Already tested above.
+
+ return SynthesizeBitstream(wpi, bitstream);
}
-static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const info) {
- // Set some defaults for unrelated fields.
- info->x_offset = 0;
- info->y_offset = 0;
- info->duration = 1;
- info->dispose_method = WEBP_MUX_DISPOSE_NONE;
- info->blend_method = WEBP_MUX_BLEND;
- // Extract data for related fields.
- info->id = ChunkGetIdFromTag(wpi->img_->tag_);
- return SynthesizeBitstream(wpi, &info->bitstream);
+WebPMuxError WebPMuxGetMetadata(const WebPMux* mux, WebPData* metadata) {
+ if (mux == NULL || metadata == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxGet(mux, IDX_META, 1, metadata);
}
-static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const frame) {
- const int is_frame = (wpi->header_->tag_ == kChunks[IDX_ANMF].tag);
- const CHUNK_INDEX idx = is_frame ? IDX_ANMF : IDX_FRGM;
- const WebPData* frame_frgm_data;
-#ifndef WEBP_EXPERIMENTAL_FEATURES
- if (!is_frame) return WEBP_MUX_INVALID_ARGUMENT;
-#endif
- assert(wpi->header_ != NULL); // Already checked by WebPMuxGetFrame().
- // Get frame/fragment chunk.
- frame_frgm_data = &wpi->header_->data_;
- if (frame_frgm_data->size < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
- // Extract info.
- frame->x_offset = 2 * GetLE24(frame_frgm_data->bytes + 0);
- frame->y_offset = 2 * GetLE24(frame_frgm_data->bytes + 3);
- if (is_frame) {
- const uint8_t bits = frame_frgm_data->bytes[15];
- frame->duration = GetLE24(frame_frgm_data->bytes + 12);
- frame->dispose_method =
- (bits & 1) ? WEBP_MUX_DISPOSE_BACKGROUND : WEBP_MUX_DISPOSE_NONE;
- frame->blend_method = (bits & 2) ? WEBP_MUX_NO_BLEND : WEBP_MUX_BLEND;
- } else { // Defaults for unused values.
- frame->duration = 1;
- frame->dispose_method = WEBP_MUX_DISPOSE_NONE;
- frame->blend_method = WEBP_MUX_BLEND;
- }
- frame->id = ChunkGetIdFromTag(wpi->header_->tag_);
- return SynthesizeBitstream(wpi, &frame->bitstream);
+WebPMuxError WebPMuxGetColorProfile(const WebPMux* mux,
+ WebPData* color_profile) {
+ if (mux == NULL || color_profile == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return MuxGet(mux, IDX_ICCP, 1, color_profile);
}
-WebPMuxError WebPMuxGetFrame(
- const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame) {
+WebPMuxError WebPMuxGetLoopCount(const WebPMux* mux, int* loop_count) {
+ WebPData image;
+ WebPMuxError err;
+
+ if (mux == NULL || loop_count == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+
+ err = MuxGet(mux, IDX_LOOP, 1, &image);
+ if (err != WEBP_MUX_OK) return err;
+ if (image.size_ < kChunks[WEBP_CHUNK_LOOP].size) return WEBP_MUX_BAD_DATA;
+ *loop_count = GetLE16(image.bytes_);
+
+ return WEBP_MUX_OK;
+}
+
+static WebPMuxError MuxGetFrameTileInternal(
+ const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
+ int* const x_offset, int* const y_offset, int* const duration,
+ uint32_t tag) {
+ const WebPData* frame_tile_data;
WebPMuxError err;
WebPMuxImage* wpi;
- // Sanity checks.
- if (mux == NULL || frame == NULL) {
+ const int is_frame = (tag == kChunks[WEBP_CHUNK_FRAME].tag) ? 1 : 0;
+ const CHUNK_INDEX idx = is_frame ? IDX_FRAME : IDX_TILE;
+ const WebPChunkId id = kChunks[idx].id;
+
+ if (mux == NULL || bitstream == NULL ||
+ x_offset == NULL || y_offset == NULL || (is_frame && duration == NULL)) {
return WEBP_MUX_INVALID_ARGUMENT;
}
// Get the nth WebPMuxImage.
- err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, &wpi);
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, nth, id, &wpi);
if (err != WEBP_MUX_OK) return err;
- // Get frame info.
- if (wpi->header_ == NULL) {
- return MuxGetImageInternal(wpi, frame);
- } else {
- return MuxGetFrameFragmentInternal(wpi, frame);
- }
-}
+ // Get frame chunk.
+ assert(wpi->header_ != NULL); // As MuxImageGetNth() already checked header_.
+ frame_tile_data = &wpi->header_->data_;
-WebPMuxError WebPMuxGetAnimationParams(const WebPMux* mux,
- WebPMuxAnimParams* params) {
- WebPData anim;
- WebPMuxError err;
+ if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
+ *x_offset = 2 * GetLE24(frame_tile_data->bytes_ + 0);
+ *y_offset = 2 * GetLE24(frame_tile_data->bytes_ + 3);
+ if (is_frame) *duration = 1 + GetLE24(frame_tile_data->bytes_ + 12);
- if (mux == NULL || params == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ return SynthesizeBitstream(wpi, bitstream);
+}
- err = MuxGet(mux, IDX_ANIM, 1, &anim);
- if (err != WEBP_MUX_OK) return err;
- if (anim.size < kChunks[WEBP_CHUNK_ANIM].size) return WEBP_MUX_BAD_DATA;
- params->bgcolor = GetLE32(anim.bytes);
- params->loop_count = GetLE16(anim.bytes + 4);
+WebPMuxError WebPMuxGetFrame(const WebPMux* mux, uint32_t nth,
+ WebPData* bitstream,
+ int* x_offset, int* y_offset, int* duration) {
+ return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset,
+ duration, kChunks[IDX_FRAME].tag);
+}
- return WEBP_MUX_OK;
+WebPMuxError WebPMuxGetTile(const WebPMux* mux, uint32_t nth,
+ WebPData* bitstream,
+ int* x_offset, int* y_offset) {
+ return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, NULL,
+ kChunks[IDX_TILE].tag);
}
// Get chunk index from chunk id. Returns IDX_NIL if not found.
static CHUNK_INDEX ChunkGetIndexFromId(WebPChunkId id) {
int i;
for (i = 0; kChunks[i].id != WEBP_CHUNK_NIL; ++i) {
- if (id == kChunks[i].id) return (CHUNK_INDEX)i;
+ if (id == kChunks[i].id) return i;
}
return IDX_NIL;
}
@@ -529,8 +393,12 @@ WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
*num_elements = MuxImageCount(mux->images_, id);
} else {
WebPChunk* const* chunk_list = MuxGetChunkListFromId(mux, id);
- const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
- *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
+ if (chunk_list == NULL) {
+ *num_elements = 0;
+ } else {
+ const CHUNK_INDEX idx = ChunkGetIndexFromId(id);
+ *num_elements = CountChunks(*chunk_list, kChunks[idx].tag);
+ }
}
return WEBP_MUX_OK;
@@ -538,3 +406,6 @@ WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
//------------------------------------------------------------------------------
+#if defined(__cplusplus) || defined(c_plusplus)
+} // extern "C"
+#endif