Merge "More spec/code matching in mux:"

This commit is contained in:
James Zern 2012-07-12 23:53:58 -07:00 committed by Gerrit Code Review
commit 05108f6ea0
9 changed files with 173 additions and 134 deletions

View File

@ -47,7 +47,7 @@ static struct {
int print_info;
uint32_t flags;
uint32_t loop_count;
int loop_count;
int frame_num;
int frame_max;
@ -177,10 +177,10 @@ static void StartDisplay(const WebPDecBuffer* const pic) {
//------------------------------------------------------------------------------
// File decoding
static int Decode(const int frame_number, uint32_t* const duration) {
static int Decode(const int frame_number, int* const duration) {
WebPDecoderConfig* const config = kParams.config;
WebPData *data, image_data;
uint32_t x_off = 0, y_off = 0;
int x_off = 0, y_off = 0;
WebPDecBuffer* const output_buffer = &config->output;
int ok = 0;
@ -214,7 +214,7 @@ static int Decode(const int frame_number, uint32_t* const duration) {
static void decode_callback(int what) {
if (what == 0 && !kParams.done) {
uint32_t duration = 0;
int duration = 0;
if (kParams.mux != NULL) {
if (!Decode(kParams.frame_num, &duration)) {
kParams.decoding_error = 1;
@ -339,7 +339,7 @@ int main(int argc, char *argv[]) {
// Decode first frame
{
uint32_t duration;
int duration;
if (!Decode(1, &duration)) goto Error;
}

View File

@ -186,7 +186,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
if (flag & ANIMATION_FLAG) {
int nFrames;
uint32_t loop_count;
int loop_count;
err = WebPMuxGetLoopCount(mux, &loop_count);
RETURN_IF_ERROR("Failed to retrieve loop count\n");
printf("Loop Count : %d\n", loop_count);
@ -200,7 +200,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
printf("No.: x_offset y_offset duration image_size");
printf("\n");
for (i = 1; i <= nFrames; i++) {
uint32_t x_offset, y_offset, duration;
int x_offset, y_offset, duration;
WebPData bitstream;
err = WebPMuxGetFrame(mux, i, &bitstream,
&x_offset, &y_offset, &duration);
@ -223,7 +223,7 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) {
printf("No.: x_offset y_offset image_size");
printf("\n");
for (i = 1; i <= nTiles; i++) {
uint32_t x_offset, y_offset;
int x_offset, y_offset;
WebPData bitstream;
err = WebPMuxGetTile(mux, i, &bitstream, &x_offset, &y_offset);
RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i);
@ -356,13 +356,13 @@ static int WriteWebP(WebPMux* const mux, const char* filename) {
return ok;
}
static int ParseFrameArgs(const char* args, uint32_t* x_offset,
uint32_t* y_offset, uint32_t* duration) {
static int ParseFrameArgs(const char* args, int* const x_offset,
int* const y_offset, int* const duration) {
return (sscanf(args, "+%d+%d+%d", x_offset, y_offset, duration) == 3);
}
static int ParseTileArgs(const char* args, uint32_t* x_offset,
uint32_t* y_offset) {
static int ParseTileArgs(const char* args,
int* const x_offset, int* const y_offset) {
return (sscanf(args, "+%d+%d", x_offset, y_offset) == 2);
}
@ -690,9 +690,9 @@ static int InitializeConfig(int argc, const char* argv[],
static int GetFrameTile(const WebPMux* mux,
const WebPMuxConfig* config, int isFrame) {
WebPData bitstream;
uint32_t x_offset = 0;
uint32_t y_offset = 0;
uint32_t duration = 0;
int x_offset = 0;
int y_offset = 0;
int duration = 0;
WebPMuxError err = WEBP_MUX_OK;
WebPMux* mux_single = NULL;
long num = 0;
@ -741,8 +741,8 @@ static int Process(const WebPMuxConfig* config) {
WebPMux* mux = NULL;
WebPData webpdata;
WebPData metadata, color_profile;
uint32_t x_offset = 0;
uint32_t y_offset = 0;
int x_offset = 0;
int y_offset = 0;
WebPMuxError err = WEBP_MUX_OK;
int index = 0;
int ok = 1;
@ -804,7 +804,7 @@ static int Process(const WebPMuxConfig* config) {
ErrorString(err), Err2);
}
} else if (feature->args_[index].subtype_ == SUBTYPE_FRM) {
uint32_t duration;
int duration;
ok = ReadFileToWebPData(feature->args_[index].filename_,
&webpdata);
if (!ok) goto Err2;

View File

@ -133,17 +133,30 @@ static WEBP_INLINE uint8_t GetByte(MemBuffer* const mem) {
return byte;
}
// Read 16, 24 or 32 bits stored in little-endian order.
static WEBP_INLINE int ReadLE16s(const uint8_t* const data) {
return (int)(data[0] << 0) | (data[1] << 8);
}
static WEBP_INLINE int ReadLE24s(const uint8_t* const data) {
return (int)(data[0] << 0) | (data[1] << 8) | (data[2] << 16);
return ReadLE16s(data) | (data[2] << 16);
}
static WEBP_INLINE uint32_t ReadLE32(const uint8_t* const data) {
return (uint32_t)ReadLE24s(data) | (data[3] << 24);
}
// In addition to reading, skip the read bytes.
static WEBP_INLINE int GetLE16s(MemBuffer* const mem) {
const uint8_t* const data = mem->buf_ + mem->start_;
const int val = ReadLE16s(data);
Skip(mem, 2);
return val;
}
static WEBP_INLINE int GetLE24s(MemBuffer* const mem) {
const uint8_t* const data = mem->buf_ + mem->start_;
const uint32_t val = ReadLE24s(data);
const int val = ReadLE24s(data);
Skip(mem, 3);
return val;
}
@ -155,10 +168,6 @@ static WEBP_INLINE uint32_t GetLE32(MemBuffer* const mem) {
return val;
}
static WEBP_INLINE int GetLE32s(MemBuffer* const mem) {
return (int)GetLE32(mem);
}
// -----------------------------------------------------------------------------
// Secondary chunk parsing
@ -289,12 +298,15 @@ static ParseStatus ParseFrame(
NewFrame(mem, min_size, FRAME_CHUNK_SIZE, frame_chunk_size, &frame);
if (status != PARSE_OK) return status;
frame->x_offset_ = GetLE32s(mem);
frame->y_offset_ = GetLE32s(mem);
frame->width_ = GetLE32s(mem);
frame->height_ = GetLE32s(mem);
frame->duration_ = GetLE32s(mem);
frame->x_offset_ = 2 * GetLE24s(mem);
frame->y_offset_ = 2 * GetLE24s(mem);
frame->width_ = 1 + GetLE24s(mem);
frame->height_ = 1 + GetLE24s(mem);
frame->duration_ = 1 + GetLE24s(mem);
Skip(mem, frame_chunk_size - FRAME_CHUNK_SIZE); // skip any trailing data.
if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) {
return PARSE_ERROR;
}
// Store a (potentially partial) frame only if the animation flag is set
// and there is some data in 'frame'.
@ -326,8 +338,8 @@ static ParseStatus ParseTile(WebPDemuxer* const dmux,
if (status != PARSE_OK) return status;
frame->is_tile_ = 1;
frame->x_offset_ = GetLE32s(mem);
frame->y_offset_ = GetLE32s(mem);
frame->x_offset_ = 2 * GetLE24s(mem);
frame->y_offset_ = 2 * GetLE24s(mem);
Skip(mem, tile_chunk_size - TILE_CHUNK_SIZE); // skip any trailing data.
// Store a (potentially partial) tile only if the tile flag is set
@ -481,7 +493,7 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) {
status = PARSE_NEED_MORE_DATA;
} else if (loop_chunks == 0) {
++loop_chunks;
dmux->loop_count_ = GetLE32s(mem);
dmux->loop_count_ = GetLE16s(mem);
Skip(mem, chunk_size_padded - LOOP_CHUNK_SIZE);
} else {
store_chunk = 0;

View File

@ -19,11 +19,11 @@ extern "C" {
// Object to store metadata about images.
typedef struct {
uint32_t x_offset_;
uint32_t y_offset_;
uint32_t duration_;
uint32_t width_;
uint32_t height_;
int x_offset_;
int y_offset_;
int duration_;
int width_;
int height_;
} WebPImageInfo;
//------------------------------------------------------------------------------
@ -115,8 +115,8 @@ static WebPMuxError MuxAddChunk(WebPMux* const mux, uint32_t nth, uint32_t tag,
// Create data for frame/tile given image data, offsets and duration.
static WebPMuxError CreateFrameTileData(const WebPData* const image,
uint32_t x_offset, uint32_t y_offset,
uint32_t duration, int is_lossless,
int x_offset, int y_offset,
int duration, int is_lossless,
int is_frame,
WebPData* const frame_tile) {
int width;
@ -129,16 +129,19 @@ static WebPMuxError CreateFrameTileData(const WebPData* const image,
VP8GetInfo(image->bytes_, image->size_, image->size_, &width, &height);
if (!ok) return WEBP_MUX_INVALID_ARGUMENT;
assert(width > 0 && height > 0 && duration > 0);
// Note: assertion on upper bounds is done in PutLE24().
frame_tile_bytes = (uint8_t*)malloc(frame_tile_size);
if (frame_tile_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
PutLE32(frame_tile_bytes + 0, x_offset);
PutLE32(frame_tile_bytes + 4, y_offset);
PutLE24(frame_tile_bytes + 0, x_offset / 2);
PutLE24(frame_tile_bytes + 3, y_offset / 2);
if (is_frame) {
PutLE32(frame_tile_bytes + 8, (uint32_t)width);
PutLE32(frame_tile_bytes + 12, (uint32_t)height);
PutLE32(frame_tile_bytes + 16, duration);
PutLE24(frame_tile_bytes + 6, width - 1);
PutLE24(frame_tile_bytes + 9, height - 1);
PutLE24(frame_tile_bytes + 12, duration - 1);
}
frame_tile->bytes_ = frame_tile_bytes;
@ -300,11 +303,12 @@ WebPMuxError WebPMuxSetColorProfile(WebPMux* const mux,
return MuxSet(mux, IDX_ICCP, 1, color_profile, copy_data);
}
WebPMuxError WebPMuxSetLoopCount(WebPMux* const mux, uint32_t loop_count) {
WebPMuxError WebPMuxSetLoopCount(WebPMux* const mux, int loop_count) {
WebPMuxError err;
uint8_t* data = NULL;
if (mux == NULL) return WEBP_MUX_INVALID_ARGUMENT;
if (loop_count >= MAX_LOOP_COUNT) return WEBP_MUX_INVALID_ARGUMENT;
// Delete the existing LOOP chunk(s).
err = DeleteLoopCount(mux);
@ -314,7 +318,7 @@ WebPMuxError WebPMuxSetLoopCount(WebPMux* const mux, uint32_t loop_count) {
data = (uint8_t*)malloc(kChunks[IDX_LOOP].size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;
PutLE32(data, loop_count);
PutLE16(data, loop_count);
err = MuxAddChunk(mux, 1, kChunks[IDX_LOOP].tag, data,
kChunks[IDX_LOOP].size, 1);
free(data);
@ -322,8 +326,8 @@ WebPMuxError WebPMuxSetLoopCount(WebPMux* const mux, uint32_t loop_count) {
}
static WebPMuxError MuxPushFrameTileInternal(
WebPMux* const mux, const WebPData* const bitstream, uint32_t x_offset,
uint32_t y_offset, uint32_t duration, int copy_data, uint32_t tag) {
WebPMux* const mux, const WebPData* const bitstream, int x_offset,
int y_offset, int duration, int copy_data, uint32_t tag) {
WebPChunk chunk;
WebPData image;
WebPData alpha;
@ -334,10 +338,20 @@ static WebPMuxError MuxPushFrameTileInternal(
int is_lossless;
int image_tag;
// Sanity checks.
if (mux == NULL || bitstream == NULL || bitstream->bytes_ == NULL ||
bitstream->size_ > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}
if (x_offset < 0 || x_offset >= MAX_POSITION_OFFSET ||
y_offset < 0 || y_offset >= MAX_POSITION_OFFSET ||
duration <= 0 || duration > MAX_DURATION) {
return WEBP_MUX_INVALID_ARGUMENT;
}
// Snap offsets to even positions.
x_offset &= ~1;
y_offset &= ~1;
// If given data is for a whole webp file,
// extract only the VP8/VP8L data from it.
@ -394,15 +408,15 @@ static WebPMuxError MuxPushFrameTileInternal(
WebPMuxError WebPMuxPushFrame(WebPMux* const mux,
const WebPData* const bitstream,
uint32_t x_offset, uint32_t y_offset,
uint32_t duration, int copy_data) {
int x_offset, int y_offset,
int duration, int copy_data) {
return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
duration, copy_data, kChunks[IDX_FRAME].tag);
}
WebPMuxError WebPMuxPushTile(WebPMux* const mux,
const WebPData* const bitstream,
uint32_t x_offset, uint32_t y_offset,
int x_offset, int y_offset,
int copy_data) {
return MuxPushFrameTileInternal(mux, bitstream, x_offset, y_offset,
1 /* unused duration */, copy_data,
@ -454,9 +468,8 @@ WebPMuxError WebPMuxDeleteTile(WebPMux* const mux, uint32_t nth) {
// Assembly of the WebP RIFF file.
static WebPMuxError GetFrameTileInfo(const WebPChunk* const frame_tile_chunk,
uint32_t* const x_offset,
uint32_t* const y_offset,
uint32_t* const duration) {
int* const x_offset, int* const y_offset,
int* const duration) {
const uint32_t tag = frame_tile_chunk->tag_;
const int is_frame = (tag == kChunks[IDX_FRAME].tag);
const WebPData* const data = &frame_tile_chunk->data_;
@ -466,9 +479,9 @@ static WebPMuxError GetFrameTileInfo(const WebPChunk* const frame_tile_chunk,
assert(tag == kChunks[IDX_FRAME].tag || tag == kChunks[IDX_TILE].tag);
if (data->size_ != expected_data_size) return WEBP_MUX_INVALID_ARGUMENT;
*x_offset = GetLE32(data->bytes_ + 0);
*y_offset = GetLE32(data->bytes_ + 4);
if (is_frame) *duration = GetLE32(data->bytes_ + 16);
*x_offset = 2 * GetLE24(data->bytes_ + 0);
*y_offset = 2 * GetLE24(data->bytes_ + 3);
if (is_frame) *duration = 1 + GetLE24(data->bytes_ + 12);
return WEBP_MUX_OK;
}
@ -497,7 +510,7 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
const WebPChunk* const image_chunk = wpi->img_;
const WebPChunk* const frame_tile_chunk = wpi->header_;
WebPMuxError err;
uint32_t x_offset, y_offset, duration;
int x_offset, y_offset, duration;
int width, height;
memset(image_info, 0, sizeof(*image_info));
@ -520,8 +533,8 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
}
static WebPMuxError GetImageCanvasWidthHeight(
const WebPMux* const mux,
uint32_t flags, uint32_t* width, uint32_t* height) {
const WebPMux* const mux, uint32_t flags,
int* const width, int* const height) {
WebPMuxImage* wpi = NULL;
assert(mux != NULL);
assert(width && height);
@ -531,25 +544,21 @@ static WebPMuxError GetImageCanvasWidthHeight(
assert(wpi->img_ != NULL);
if (wpi->next_) {
uint32_t max_x = 0;
uint32_t max_y = 0;
uint64_t image_area = 0;
int max_x = 0;
int max_y = 0;
int64_t image_area = 0;
// Aggregate the bounding box for animation frames & tiled images.
for (; wpi != NULL; wpi = wpi->next_) {
WebPImageInfo image_info;
const WebPMuxError err = GetImageInfo(wpi, &image_info);
const uint32_t max_x_pos = image_info.x_offset_ + image_info.width_;
const uint32_t max_y_pos = image_info.y_offset_ + image_info.height_;
const int max_x_pos = image_info.x_offset_ + image_info.width_;
const int max_y_pos = image_info.y_offset_ + image_info.height_;
if (err != WEBP_MUX_OK) return err;
assert(image_info.x_offset_ < MAX_POSITION_OFFSET);
assert(image_info.y_offset_ < MAX_POSITION_OFFSET);
if (max_x_pos < image_info.x_offset_) { // Overflow occurred.
return WEBP_MUX_INVALID_ARGUMENT;
}
if (max_y_pos < image_info.y_offset_) { // Overflow occurred.
return WEBP_MUX_INVALID_ARGUMENT;
}
if (max_x_pos > max_x) max_x = max_x_pos;
if (max_y_pos > max_y) max_y = max_y_pos;
if (max_x_pos > max_x) max_x = max_x_pos;
if (max_y_pos > max_y) max_y = max_y_pos;
image_area += (image_info.width_ * image_info.height_);
}
*width = max_x;
@ -583,8 +592,8 @@ static WebPMuxError GetImageCanvasWidthHeight(
static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
WebPMuxError err = WEBP_MUX_OK;
uint32_t flags = 0;
uint32_t width = 0;
uint32_t height = 0;
int width = 0;
int height = 0;
uint8_t data[VP8X_CHUNK_SIZE];
const size_t data_size = VP8X_CHUNK_SIZE;
const WebPMuxImage* images = NULL;
@ -632,6 +641,13 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
err = GetImageCanvasWidthHeight(mux, flags, &width, &height);
if (err != WEBP_MUX_OK) return err;
if (width <= 0 || height <= 0) {
return WEBP_MUX_INVALID_ARGUMENT;
}
if (width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) {
return WEBP_MUX_INVALID_ARGUMENT;
}
if (MuxHasLosslessImages(images)) {
// We have a file with a VP8X chunk having some lossless images.
// As lossless images implicitly contain alpha, force ALPHA_FLAG to be true.

View File

@ -80,8 +80,7 @@ typedef enum {
#define NIL_TAG 0x00000000u // To signal void chunk.
#define mktag(c1, c2, c3, c4) \
((uint32_t)c1 | (c2 << 8) | (c3 << 16) | (c4 << 24))
#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24)
typedef struct {
uint32_t tag;
@ -94,23 +93,35 @@ extern const ChunkInfo kChunks[IDX_LAST_CHUNK];
//------------------------------------------------------------------------------
// Helper functions.
// Read 16, 24 or 32 bits stored in little-endian order.
static WEBP_INLINE int GetLE16(const uint8_t* const data) {
return (int)(data[0] << 0) | (data[1] << 8);
}
static WEBP_INLINE int GetLE24(const uint8_t* const data) {
return GetLE16(data) | (data[2] << 16);
}
static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) {
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
return (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16);
}
static WEBP_INLINE void PutLE16(uint8_t* const data, uint32_t val) {
data[0] = (val >> 0) & 0xff;
data[1] = (val >> 8) & 0xff;
// Store 16, 24 or 32 bits in little-endian order.
static WEBP_INLINE void PutLE16(uint8_t* const data, int val) {
assert(val < (1 << 16));
data[0] = (val >> 0);
data[1] = (val >> 8);
}
static WEBP_INLINE void PutLE24(uint8_t* const data, uint32_t val) {
PutLE16(data, val);
static WEBP_INLINE void PutLE24(uint8_t* const data, int val) {
assert(val < (1 << 24));
PutLE16(data, val & 0xffff);
data[2] = (val >> 16);
}
static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data, val);
PutLE16(data + 2, val >> 16);
PutLE16(data, (int)(val & 0xffff));
PutLE16(data + 2, (int)(val >> 16));
}
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {

View File

@ -20,16 +20,16 @@ extern "C" {
#define UNDEFINED_CHUNK_SIZE (-1)
const ChunkInfo kChunks[] = {
{ mktag('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE },
{ mktag('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
{ mktag('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE },
{ mktag('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE },
{ mktag('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE },
{ mktag('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
{ mktag('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ mktag('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ mktag('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE },
{ mktag('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', 'X'), WEBP_CHUNK_VP8X, VP8X_CHUNK_SIZE },
{ MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('L', 'O', 'O', 'P'), WEBP_CHUNK_LOOP, LOOP_CHUNK_SIZE },
{ MKFOURCC('F', 'R', 'M', ' '), WEBP_CHUNK_FRAME, FRAME_CHUNK_SIZE },
{ MKFOURCC('T', 'I', 'L', 'E'), WEBP_CHUNK_TILE, TILE_CHUNK_SIZE },
{ MKFOURCC('A', 'L', 'P', 'H'), WEBP_CHUNK_ALPHA, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', ' '), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('V', 'P', '8', 'L'), WEBP_CHUNK_IMAGE, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('M', 'E', 'T', 'A'), WEBP_CHUNK_META, UNDEFINED_CHUNK_SIZE },
{ MKFOURCC('U', 'N', 'K', 'N'), WEBP_CHUNK_UNKNOWN, UNDEFINED_CHUNK_SIZE },
{ NIL_TAG, WEBP_CHUNK_NIL, UNDEFINED_CHUNK_SIZE }
};
@ -426,10 +426,10 @@ int MuxHasLosslessImages(const WebPMuxImage* images) {
}
uint8_t* MuxEmitRiffHeader(uint8_t* const data, size_t size) {
PutLE32(data + 0, mktag('R', 'I', 'F', 'F'));
PutLE32(data + 0, MKFOURCC('R', 'I', 'F', 'F'));
PutLE32(data + TAG_SIZE, (uint32_t)size - CHUNK_HEADER_SIZE);
assert(size == (uint32_t)size);
PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, mktag('W', 'E', 'B', 'P'));
PutLE32(data + TAG_SIZE + CHUNK_SIZE_BYTES, MKFOURCC('W', 'E', 'B', 'P'));
return data + RIFF_HEADER_SIZE;
}

View File

@ -97,8 +97,8 @@ WebPMux* WebPMuxCreateInternal(const WebPData* const bitstream, int copy_data,
if (data == NULL) return NULL;
if (size < RIFF_HEADER_SIZE) return NULL;
if (GetLE32(data + 0) != mktag('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != mktag('W', 'E', 'B', 'P')) {
if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
return NULL;
}
@ -213,13 +213,13 @@ WebPMuxError WebPMuxGetFeatures(const WebPMux* const mux, uint32_t* flags) {
return WEBP_MUX_OK;
}
static uint8_t* EmitVP8XChunk(uint8_t* const dst, uint32_t width,
uint32_t height, uint32_t flags) {
static uint8_t* EmitVP8XChunk(uint8_t* const dst, int width,
int height, uint32_t flags) {
const size_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
assert(width >= 1 && height >= 1);
assert(width <= MAX_CANVAS_SIZE && height <= MAX_CANVAS_SIZE);
assert(width * (uint64_t)height < MAX_IMAGE_AREA);
PutLE32(dst, mktag('V', 'P', '8', 'X'));
PutLE32(dst, MKFOURCC('V', 'P', '8', 'X'));
PutLE32(dst + TAG_SIZE, VP8X_CHUNK_SIZE);
PutLE32(dst + CHUNK_HEADER_SIZE, flags);
PutLE24(dst + CHUNK_HEADER_SIZE + 4, width - 1);
@ -301,7 +301,7 @@ WebPMuxError WebPMuxGetColorProfile(const WebPMux* const mux,
}
WebPMuxError WebPMuxGetLoopCount(const WebPMux* const mux,
uint32_t* loop_count) {
int* const loop_count) {
WebPData image;
WebPMuxError err;
@ -310,14 +310,15 @@ WebPMuxError WebPMuxGetLoopCount(const WebPMux* const mux,
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 = GetLE32(image.bytes_);
*loop_count = GetLE16(image.bytes_);
return WEBP_MUX_OK;
}
static WebPMuxError MuxGetFrameTileInternal(
const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
uint32_t* x_offset, uint32_t* y_offset, uint32_t* duration, uint32_t tag) {
int* const x_offset, int* const y_offset, int* const duration,
uint32_t tag) {
const WebPData* frame_tile_data;
WebPMuxError err;
WebPMuxImage* wpi;
@ -340,27 +341,24 @@ static WebPMuxError MuxGetFrameTileInternal(
frame_tile_data = &wpi->header_->data_;
if (frame_tile_data->size_ < kChunks[idx].size) return WEBP_MUX_BAD_DATA;
*x_offset = GetLE32(frame_tile_data->bytes_ + 0);
*y_offset = GetLE32(frame_tile_data->bytes_ + 4);
if (is_frame) *duration = GetLE32(frame_tile_data->bytes_ + 16);
*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);
return SynthesizeBitstream(wpi, bitstream);
}
WebPMuxError WebPMuxGetFrame(const WebPMux* const mux, uint32_t nth,
WebPData* const bitstream,
uint32_t* x_offset, uint32_t* y_offset,
uint32_t* duration) {
return MuxGetFrameTileInternal(mux, nth, bitstream,
x_offset, y_offset, duration,
kChunks[IDX_FRAME].tag);
WebPData* const bitstream, int* const x_offset,
int* const y_offset, int* const duration) {
return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset,
duration, kChunks[IDX_FRAME].tag);
}
WebPMuxError WebPMuxGetTile(const WebPMux* const mux, uint32_t nth,
WebPData* const bitstream,
uint32_t* x_offset, uint32_t* y_offset) {
return MuxGetFrameTileInternal(mux, nth, bitstream,
x_offset, y_offset, NULL,
int* const x_offset, int* const y_offset) {
return MuxGetFrameTileInternal(mux, nth, bitstream, x_offset, y_offset, NULL,
kChunks[IDX_TILE].tag);
}

View File

@ -62,9 +62,9 @@ typedef enum {
#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size.
#define CHUNK_HEADER_SIZE 8 // Size of a chunk header.
#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
#define FRAME_CHUNK_SIZE 20 // Size of a FRM chunk.
#define LOOP_CHUNK_SIZE 4 // Size of a LOOP chunk.
#define TILE_CHUNK_SIZE 8 // Size of a TILE chunk.
#define FRAME_CHUNK_SIZE 15 // Size of a FRM chunk.
#define LOOP_CHUNK_SIZE 2 // Size of a LOOP chunk.
#define TILE_CHUNK_SIZE 6 // Size of a TILE chunk.
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
#define TILING_FLAG_BIT 0x01 // Set if tiles are possibly used.
@ -76,9 +76,9 @@ typedef enum {
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
#define MAX_DURATION (1U << 24) // maximum duration
#define MAX_POSITION_OFFSET (1U << 24) // maximum frame/tile x/y offset
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
#define MAX_DURATION (1 << 24) // maximum duration
#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/tile x/y offset
// Maximum chunk payload is such that adding the header and padding won't
// overflow a uint32_t.

View File

@ -268,6 +268,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* const mux);
// Animation.
// Adds an animation frame at the end of the mux object.
// Note: as WebP only supports even offsets, any odd offset will be snapped to
// an even location using: offset &= ~1
// Parameters:
// mux - (in/out) object to which an animation frame is to be added
// bitstream - (in) the image data corresponding to the frame. It can either
@ -284,15 +286,13 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteColorProfile(WebPMux* const mux);
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(
WebPMux* const mux, const WebPData* const bitstream,
uint32_t x_offset, uint32_t y_offset, uint32_t duration,
int copy_data);
int x_offset, int y_offset, int duration, int copy_data);
// TODO(urvang): Create a struct as follows to reduce argument list size:
// typedef struct {
// WebPData image;
// WebPData alpha;
// uint32_t x_offset, y_offset;
// uint32_t duration;
// WebPData bitstream;
// int x_offset, y_offset;
// int duration;
// } FrameInfo;
// Gets the nth animation frame from the mux object.
@ -315,7 +315,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame(
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame(
const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
uint32_t* x_offset, uint32_t* y_offset, uint32_t* duration);
int* const x_offset, int* const y_offset, int* const duration);
// Deletes an animation frame from the mux object.
// nth=0 has a special meaning - last position.
@ -340,7 +340,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* const mux, uint32_t nth);
// WEBP_MUX_MEMORY_ERROR - on memory allocation error.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* const mux,
uint32_t loop_count);
int loop_count);
// Gets the animation loop count from the mux object.
// Parameters:
@ -351,12 +351,14 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetLoopCount(WebPMux* const mux,
// WEBP_MUX_NOT_FOUND - if loop chunk is not present in mux object.
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* const mux,
uint32_t* loop_count);
int* const loop_count);
//------------------------------------------------------------------------------
// Tiling.
// Adds a tile at the end of the mux object.
// Note: as WebP only supports even offsets, any odd offset will be snapped to
// an even location using: offset &= ~1
// Parameters:
// mux - (in/out) object to which a tile is to be added.
// bitstream - (in) the image data corresponding to the frame. It can either
@ -372,7 +374,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetLoopCount(const WebPMux* const mux,
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxPushTile(
WebPMux* const mux, const WebPData* const bitstream,
uint32_t x_offset, uint32_t y_offset, int copy_data);
int x_offset, int y_offset, int copy_data);
// Gets the nth tile from the mux object.
// The content of 'bitstream' is allocated using malloc(), and NOT
@ -393,7 +395,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxPushTile(
// WEBP_MUX_OK - on success.
WEBP_EXTERN(WebPMuxError) WebPMuxGetTile(
const WebPMux* const mux, uint32_t nth, WebPData* const bitstream,
uint32_t* x_offset, uint32_t* y_offset);
int* const x_offset, int* const y_offset);
// Deletes a tile from the mux object.
// nth=0 has a special meaning - last position