From 23782f95b492c211398bb21cc724785955aadc12 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Mon, 19 Nov 2012 11:21:37 -0800 Subject: [PATCH] Separate out mux and demux code and libraries: - Separate out mux.h and demux.h - muxtypes.h: new header for data types common to mux/demux - Move some misc read/write utilities to utils/utils.h - Remove some duplicate methods. - Separate out mux/demux libraries Change-Id: If9b9569b10d55d922ad9317ef51710544315d6de --- Makefile.vc | 24 ++++- configure.ac | 10 +- examples/vwebp.c | 2 +- makefile.unix | 17 +++- src/Makefile.am | 3 + src/dec/webp.c | 2 +- src/demux/Makefile.am | 12 +++ src/{mux => demux}/demux.c | 73 ++++++-------- src/enc/syntax.c | 15 +-- src/enc/vp8l.c | 7 -- src/mux/Makefile.am | 1 - src/mux/muxedit.c | 1 + src/mux/muxi.h | 46 +-------- src/mux/muxinternal.c | 30 +----- src/mux/muxread.c | 1 + src/utils/utils.h | 39 +++++++- src/webp/demux.h | 171 ++++++++++++++++++++++++++++++++ src/webp/format_constants.h | 20 ++-- src/webp/mux.h | 190 +----------------------------------- src/webp/mux_types.h | 78 +++++++++++++++ 20 files changed, 398 insertions(+), 344 deletions(-) create mode 100644 src/demux/Makefile.am rename src/{mux => demux}/demux.c (94%) create mode 100644 src/webp/demux.h create mode 100644 src/webp/mux_types.h diff --git a/Makefile.vc b/Makefile.vc index c7447d83..351a76b5 100644 --- a/Makefile.vc +++ b/Makefile.vc @@ -3,6 +3,7 @@ # LIBWEBP_BASENAME = libwebp LIBWEBPMUX_BASENAME = libwebpmux +LIBWEBPDEMUX_BASENAME = libwebpdemux !IFNDEF ARCH !IF ! [ cl 2>&1 | find "x86" > NUL ] @@ -59,6 +60,7 @@ DIRBIN = $(DIRBASE)\bin LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME).pdb OUTPUT_DIRS = $(DIRBIN) $(DIRINC) $(DIRLIB) \ $(DIROBJ)\dec \ + $(DIROBJ)\demux \ $(DIROBJ)\dsp \ $(DIROBJ)\enc \ $(DIROBJ)\examples \ @@ -75,6 +77,7 @@ RTLIB = $(RTLIBD) STATICLIBBUILD = TRUE LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug +LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug !ELSE IF "$(CFG)" == "release-dynamic" CC = $(CCNODBG) DLLBUILD = TRUE @@ -84,6 +87,7 @@ RTLIB = $(RTLIBD) DLLBUILD = TRUE LIBWEBP_BASENAME = $(LIBWEBP_BASENAME)_debug LIBWEBPMUX_BASENAME = $(LIBWEBPMUX_BASENAME)_debug +LIBWEBPDEMUX_BASENAME = $(LIBWEBPDEMUX_BASENAME)_debug !ENDIF !IF "$(STATICLIBBUILD)" == "TRUE" @@ -91,12 +95,14 @@ CC = $(CC) $(RTLIB) CFGSET = TRUE LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME).lib LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME).lib +LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPDEMUX_BASENAME).lib !ELSE IF "$(DLLBUILD)" == "TRUE" DLLC = webp_dll.c DLLINC = webp_dll.h CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib +LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPMDEMUX_BASENAME)_dll.lib LIBWEBP_OBJS = $(DIROBJ)\$(DLLC:.c=.obj) LIBWEBP_PDBNAME = $(DIROBJ)\$(LIBWEBP_BASENAME)_dll.pdb CFGSET = TRUE @@ -151,6 +157,9 @@ DEC_OBJS = \ $(DIROBJ)\dec\vp8l.obj \ $(DIROBJ)\dec\webp.obj \ +DEMUX_OBJS = \ + $(DIROBJ)\demux\demux.obj \ + DSP_OBJS = \ $(DIROBJ)\dsp\cpu.obj \ $(DIROBJ)\dsp\dec.obj \ @@ -184,7 +193,6 @@ ENC_OBJS = \ $(DIROBJ)\enc\webpenc.obj \ MUX_OBJS = \ - $(DIROBJ)\mux\demux.obj \ $(DIROBJ)\mux\muxedit.obj \ $(DIROBJ)\mux\muxinternal.obj \ $(DIROBJ)\mux\muxread.obj \ @@ -203,6 +211,7 @@ UTILS_OBJS = \ LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) $(LIBWEBP_OBJS) LIBWEBPMUX_OBJS = $(MUX_OBJS) $(LIBWEBPMUX_OBJS) +LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) $(LIBWEBPDEMUX_OBJS) OUT_LIBS = $(LIBWEBP) OUT_EXAMPLES = $(DIRBIN)\cwebp.exe $(DIRBIN)\dwebp.exe @@ -221,25 +230,28 @@ experimental: $(LIBWEBP): $(LIBWEBP_OBJS) $(LIBWEBPMUX): $(LIBWEBPMUX_OBJS) +$(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS) -$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS): $(OUTPUT_DIRS) +$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS) !IF "$(DLLBUILD)" == "TRUE" -$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS): $(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC) +$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): + $(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC) {$(DIROBJ)}.c{$(DIROBJ)}.obj: $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$@ $< $(LIBWEBPMUX): $(LIBWEBP) +$(LIBWEBPDEMUX): $(LIBWEBP) -$(LIBWEBP) $(LIBWEBPMUX): +$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX): $(LNKDLL) /out:$(DIRBIN)\$(@B:_dll=.dll) /implib:$@ $(LFLAGS) $** -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y clean:: @-erase /s $(DIROBJ)\$(DLLC) $(DIROBJ)\$(DLLINC) 2> NUL !ELSE -$(LIBWEBP) $(LIBWEBPMUX): +$(LIBWEBP) $(LIBWEBPMUX) $(LIBWEBPDEMUX): $(LNKLIB) /out:$@ $(LFLAGS) $** -xcopy $(DIROBJ)\*.pdb $(DIRLIB) /y !ENDIF @@ -269,6 +281,8 @@ $(DIROBJ)\$(DLLC): $(DIROBJ)\$(DLLINC) $(CC) $(CFLAGS) /Fd$(DIROBJ)\examples\ /Fo$(DIROBJ)\examples\ $< {src\dec}.c{$(DIROBJ)\dec}.obj:: $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dec\ $< +{src\demux}.c{$(DIROBJ)\demux}.obj:: + $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\demux\ $< {src\dsp}.c{$(DIROBJ)\dsp}.obj:: $(CC) $(CFLAGS) /Fd$(LIBWEBP_PDBNAME) /Fo$(DIROBJ)\dsp\ $< {src\enc}.c{$(DIROBJ)\enc}.obj:: diff --git a/configure.ac b/configure.ac index 4cb6642c..f341942f 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,14 @@ AC_ARG_ENABLE([experimental-libwebpmux], AC_MSG_RESULT(${enable_experimental_libwebpmux-no}) AM_CONDITIONAL([WANT_MUX], [test "$enable_experimental_libwebpmux" = "yes"]) +dnl === Check whether libwebpdemux should be built +AC_MSG_CHECKING(whether libwebpdemux is to be built) +AC_ARG_ENABLE([experimental-libwebpdemux], + AS_HELP_STRING([--enable-experimental-libwebpdemux], + [Build libwebpdemux @<:@default=no@:>@])) +AC_MSG_RESULT(${enable_experimental_libwebpdemux-no}) +AM_CONDITIONAL([WANT_DEMUX], [test "$enable_experimental_libwebpdemux" = "yes"]) + dnl ========================= AC_CONFIG_MACRO_DIR([m4]) @@ -245,8 +253,8 @@ AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile src/Makefile man/Makefile \ examples/Makefile src/dec/Makefile \ src/enc/Makefile src/dsp/Makefile \ + src/demux/Makefile src/mux/Makefile \ src/utils/Makefile \ - src/mux/Makefile \ src/libwebp.pc]) diff --git a/examples/vwebp.c b/examples/vwebp.c index 590a064d..ce5559f8 100644 --- a/examples/vwebp.c +++ b/examples/vwebp.c @@ -20,7 +20,7 @@ #include #include "webp/decode.h" -#include "webp/mux.h" +#include "webp/demux.h" #ifdef __APPLE__ #include diff --git a/makefile.unix b/makefile.unix index baf0c437..2a68f282 100644 --- a/makefile.unix +++ b/makefile.unix @@ -2,7 +2,8 @@ # system, for simple local building of the libraries and tools. # It will not install the libraries system-wide, but just create the 'cwebp' # and 'dwebp' tools in the examples/ directory, along with the static -# libraries 'src/libwebp.a' and 'src/mux/libwebpmux.a'. +# libraries 'src/libwebp.a', 'src/mux/libwebpmux.a' and +# 'src/demux/libwebpdemux.a'. # # To build the library and examples, use: # make -f makefile.unix @@ -85,6 +86,9 @@ DEC_OBJS = \ src/dec/vp8l.o \ src/dec/webp.o \ +DEMUX_OBJS = \ + src/demux/demux.o \ + DSP_OBJS = \ src/dsp/cpu.o \ src/dsp/dec.o \ @@ -120,7 +124,6 @@ EX_UTIL_OBJS = \ examples/example_util.o \ MUX_OBJS = \ - src/mux/demux.o \ src/mux/muxedit.o \ src/mux/muxinternal.o \ src/mux/muxread.o \ @@ -139,6 +142,7 @@ UTILS_OBJS = \ LIBWEBP_OBJS = $(DEC_OBJS) $(DSP_OBJS) $(ENC_OBJS) $(UTILS_OBJS) LIBWEBPMUX_OBJS = $(MUX_OBJS) +LIBWEBPDEMUX_OBJS = $(DEMUX_OBJS) HDRS_INSTALLED = \ src/webp/decode.h \ @@ -164,8 +168,10 @@ HDRS = \ src/utils/quant_levels.h \ src/utils/rescaler.h \ src/utils/thread.h \ + src/webp/demux.h \ src/webp/format_constants.h \ src/webp/mux.h \ + src/webp/mux_types.h \ $(HDRS_INSTALLED) \ OUT_LIBS = examples/libexample_util.a src/libwebp.a @@ -174,7 +180,7 @@ OUT_EXAMPLES = examples/cwebp examples/dwebp OUTPUT = $(OUT_LIBS) $(OUT_EXAMPLES) ifeq ($(MAKECMDGOALS),clean) OUTPUT += examples/gif2webp examples/vwebp examples/webpmux - OUTPUT += src/mux/libwebpmux.a + OUTPUT += src/demux/libwebpdemux.a src/mux/libwebpmux.a endif all: ex @@ -185,6 +191,7 @@ all: ex examples/libexample_util.a: $(EX_UTIL_OBJS) src/libwebp.a: $(LIBWEBP_OBJS) src/mux/libwebpmux.a: $(LIBWEBPMUX_OBJS) +src/demux/libwebpdemux.a: $(LIBWEBPDEMUX_OBJS) %.a: $(AR) $(ARFLAGS) $@ $^ @@ -201,7 +208,8 @@ examples/cwebp: src/libwebp.a examples/dwebp: examples/libexample_util.a src/libwebp.a examples/gif2webp: examples/libexample_util.a src/mux/libwebpmux.a src/libwebp.a examples/gif2webp: EXTRA_LIBS += $(GIF_LIBS) -examples/vwebp: examples/libexample_util.a src/mux/libwebpmux.a src/libwebp.a +examples/vwebp: examples/libexample_util.a src/demux/libwebpdemux.a +examples/vwebp: src/libwebp.a examples/vwebp: EXTRA_LIBS += $(GL_LIBS) examples/webpmux: examples/libexample_util.a src/mux/libwebpmux.a src/libwebp.a @@ -228,6 +236,7 @@ clean: $(RM) $(OUTPUT) *~ \ examples/*.o examples/*~ \ src/dec/*.o src/dec/*~ \ + src/demux/*.o src/demux/*~ \ src/dsp/*.o src/dsp/*~ \ src/enc/*.o src/enc/*~ \ src/mux/*.o src/mux/*~ \ diff --git a/src/Makefile.am b/src/Makefile.am index 99f7f945..6012a5e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,9 @@ SUBDIRS = dec enc dsp utils if WANT_MUX SUBDIRS += mux endif +if WANT_DEMUX + SUBDIRS += demux +endif AM_CPPFLAGS = -I$(top_srcdir)/src lib_LTLIBRARIES = libwebp.la diff --git a/src/dec/webp.c b/src/dec/webp.c index cb95ee73..84f0460e 100644 --- a/src/dec/webp.c +++ b/src/dec/webp.c @@ -308,7 +308,7 @@ static VP8StatusCode ParseHeadersInternal(const uint8_t* data, // necessary to send VP8X chunk to the decoder. return VP8_STATUS_BITSTREAM_ERROR; } - if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT); + if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG); if (found_vp8x && headers == NULL) { return VP8_STATUS_OK; // Return features from VP8X header. } diff --git a/src/demux/Makefile.am b/src/demux/Makefile.am new file mode 100644 index 00000000..f070808b --- /dev/null +++ b/src/demux/Makefile.am @@ -0,0 +1,12 @@ +AM_CPPFLAGS = -I$(top_srcdir)/src +lib_LTLIBRARIES = libwebpdemux.la + +libwebpdemux_la_SOURCES = +libwebpdemux_la_SOURCES += demux.c + +libwebpdemuxinclude_HEADERS = +libwebpdemuxinclude_HEADERS += ../webp/demux.h +libwebpdemuxinclude_HEADERS += ../webp/types.h + +libwebpdemux_la_LDFLAGS = -version-info 0:0:0 +libwebpdemuxincludedir = $(includedir)/webp diff --git a/src/mux/demux.c b/src/demux/demux.c similarity index 94% rename from src/mux/demux.c rename to src/demux/demux.c index 89cf5a8b..64235217 100644 --- a/src/mux/demux.c +++ b/src/demux/demux.c @@ -8,20 +8,18 @@ // WebP container demux. // -#include "../webp/mux.h" - #include #include +#include "../utils/utils.h" #include "../webp/decode.h" // WebPGetInfo +#include "../webp/demux.h" #include "../webp/format_constants.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif -#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) - typedef struct { size_t start_; // start location of the data size_t end_; // end location @@ -129,43 +127,30 @@ static WEBP_INLINE const uint8_t* GetBuffer(MemBuffer* const mem) { return mem->buf_ + mem->start_; } -static WEBP_INLINE uint8_t GetByte(MemBuffer* const mem) { +// Read from 'mem' and skip the read bytes. +static WEBP_INLINE uint8_t ReadByte(MemBuffer* const mem) { const uint8_t byte = mem->buf_[mem->start_]; Skip(mem, 1); 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 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) { +static WEBP_INLINE int ReadLE16s(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const int val = ReadLE16s(data); + const int val = GetLE16(data); Skip(mem, 2); return val; } -static WEBP_INLINE int GetLE24s(MemBuffer* const mem) { +static WEBP_INLINE int ReadLE24s(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const int val = ReadLE24s(data); + const int val = GetLE24(data); Skip(mem, 3); return val; } -static WEBP_INLINE uint32_t GetLE32(MemBuffer* const mem) { +static WEBP_INLINE uint32_t ReadLE32(MemBuffer* const mem) { const uint8_t* const data = mem->buf_ + mem->start_; - const uint32_t val = ReadLE32(data); + const uint32_t val = GetLE32(data); Skip(mem, 4); return val; } @@ -207,8 +192,8 @@ static ParseStatus StoreFrame(int frame_num, uint32_t min_size, do { const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = GetLE32(mem); - const uint32_t payload_size = GetLE32(mem); + const uint32_t fourcc = ReadLE32(mem); + const uint32_t payload_size = ReadLE32(mem); const uint32_t payload_size_padded = payload_size + (payload_size & 1); const size_t payload_available = (payload_size_padded > MemDataSize(mem)) ? MemDataSize(mem) : payload_size_padded; @@ -300,12 +285,12 @@ static ParseStatus ParseFrame( NewFrame(mem, ANMF_CHUNK_SIZE, frame_chunk_size, &frame); if (status != PARSE_OK) return status; - frame->x_offset_ = 2 * GetLE24s(mem); - frame->y_offset_ = 2 * GetLE24s(mem); - frame->width_ = 1 + GetLE24s(mem); - frame->height_ = 1 + GetLE24s(mem); - frame->duration_ = GetLE24s(mem); - frame->dispose_method_ = (WebPMuxAnimDispose)(GetByte(mem) & 1); + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); + frame->width_ = 1 + ReadLE24s(mem); + frame->height_ = 1 + ReadLE24s(mem); + frame->duration_ = ReadLE24s(mem); + frame->dispose_method_ = (WebPMuxAnimDispose)(ReadByte(mem) & 1); if (frame->width_ * (uint64_t)frame->height_ >= MAX_IMAGE_AREA) { return PARSE_ERROR; } @@ -340,8 +325,8 @@ static ParseStatus ParseFragment(WebPDemuxer* const dmux, if (status != PARSE_OK) return status; frame->is_fragment_ = 1; - frame->x_offset_ = 2 * GetLE24s(mem); - frame->y_offset_ = 2 * GetLE24s(mem); + frame->x_offset_ = 2 * ReadLE24s(mem); + frame->y_offset_ = 2 * ReadLE24s(mem); // Store a fragment only if the fragments flag is set and all data for this // fragment is available. @@ -386,7 +371,7 @@ static int ReadHeader(MemBuffer* const mem) { return 0; } - riff_size = ReadLE32(GetBuffer(mem) + TAG_SIZE); + riff_size = GetLE32(GetBuffer(mem) + TAG_SIZE); if (riff_size < CHUNK_HEADER_SIZE) return 0; if (riff_size > MAX_CHUNK_PAYLOAD) return 0; @@ -449,17 +434,17 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { dmux->is_ext_format_ = 1; Skip(mem, TAG_SIZE); // VP8X - vp8x_size = GetLE32(mem); + vp8x_size = ReadLE32(mem); if (vp8x_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; if (vp8x_size < VP8X_CHUNK_SIZE) return PARSE_ERROR; vp8x_size += vp8x_size & 1; if (SizeIsInvalid(mem, vp8x_size)) return PARSE_ERROR; if (MemDataSize(mem) < vp8x_size) return PARSE_NEED_MORE_DATA; - dmux->feature_flags_ = GetByte(mem); + dmux->feature_flags_ = ReadByte(mem); Skip(mem, 3); // Reserved. - dmux->canvas_width_ = 1 + GetLE24s(mem); - dmux->canvas_height_ = 1 + GetLE24s(mem); + dmux->canvas_width_ = 1 + ReadLE24s(mem); + dmux->canvas_height_ = 1 + ReadLE24s(mem); if (dmux->canvas_width_ * (uint64_t)dmux->canvas_height_ >= MAX_IMAGE_AREA) { return PARSE_ERROR; // image final dimension is too large } @@ -472,8 +457,8 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { do { int store_chunk = 1; const size_t chunk_start_offset = mem->start_; - const uint32_t fourcc = GetLE32(mem); - const uint32_t chunk_size = GetLE32(mem); + const uint32_t fourcc = ReadLE32(mem); + const uint32_t chunk_size = ReadLE32(mem); const uint32_t chunk_size_padded = chunk_size + (chunk_size & 1); if (chunk_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; @@ -497,8 +482,8 @@ static ParseStatus ParseVP8X(WebPDemuxer* const dmux) { status = PARSE_NEED_MORE_DATA; } else if (anim_chunks == 0) { ++anim_chunks; - dmux->bgcolor_ = GetLE32(mem); - dmux->loop_count_ = GetLE16s(mem); + dmux->bgcolor_ = ReadLE32(mem); + dmux->loop_count_ = ReadLE16s(mem); Skip(mem, chunk_size_padded - ANIM_CHUNK_SIZE); } else { store_chunk = 0; diff --git a/src/enc/syntax.c b/src/enc/syntax.c index 7c8c7b1a..3bf9f2f2 100644 --- a/src/enc/syntax.c +++ b/src/enc/syntax.c @@ -11,6 +11,7 @@ #include +#include "../utils/utils.h" #include "../webp/format_constants.h" #include "./vp8enci.h" @@ -21,18 +22,6 @@ extern "C" { //------------------------------------------------------------------------------ // Helper functions -// TODO(later): Move to webp/format_constants.h? -static void PutLE24(uint8_t* const data, uint32_t val) { - data[0] = (val >> 0) & 0xff; - data[1] = (val >> 8) & 0xff; - data[2] = (val >> 16) & 0xff; -} - -static void PutLE32(uint8_t* const data, uint32_t val) { - PutLE24(data, val); - data[3] = (val >> 24) & 0xff; -} - static int IsVP8XNeeded(const VP8Encoder* const enc) { return !!enc->has_alpha_; // Currently the only case when VP8X is needed. // This could change in the future. @@ -73,7 +62,7 @@ static WebPEncodingError PutVP8XHeader(const VP8Encoder* const enc) { assert(pic->width <= MAX_CANVAS_SIZE && pic->height <= MAX_CANVAS_SIZE); if (enc->has_alpha_) { - flags |= ALPHA_FLAG_BIT; + flags |= ALPHA_FLAG; } PutLE32(vp8x + TAG_SIZE, VP8X_CHUNK_SIZE); diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 6cc5f4d3..bd73e56a 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -712,13 +712,6 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc, // ----------------------------------------------------------------------------- -static void PutLE32(uint8_t* const data, uint32_t val) { - data[0] = (val >> 0) & 0xff; - data[1] = (val >> 8) & 0xff; - data[2] = (val >> 16) & 0xff; - data[3] = (val >> 24) & 0xff; -} - static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, size_t riff_size, size_t vp8l_size) { uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { diff --git a/src/mux/Makefile.am b/src/mux/Makefile.am index 3beb240e..bc07f7a6 100644 --- a/src/mux/Makefile.am +++ b/src/mux/Makefile.am @@ -2,7 +2,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src lib_LTLIBRARIES = libwebpmux.la libwebpmux_la_SOURCES = -libwebpmux_la_SOURCES += demux.c libwebpmux_la_SOURCES += muxedit.c libwebpmux_la_SOURCES += muxi.h libwebpmux_la_SOURCES += muxinternal.c diff --git a/src/mux/muxedit.c b/src/mux/muxedit.c index 16d18b84..0c4191e1 100644 --- a/src/mux/muxedit.c +++ b/src/mux/muxedit.c @@ -12,6 +12,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { diff --git a/src/mux/muxi.h b/src/mux/muxi.h index 477bed11..074fb6b4 100644 --- a/src/mux/muxi.h +++ b/src/mux/muxi.h @@ -15,7 +15,6 @@ #include #include "../dec/vp8i.h" #include "../dec/vp8li.h" -#include "../webp/format_constants.h" #include "../webp/mux.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -82,8 +81,6 @@ typedef enum { #define NIL_TAG 0x00000000u // To signal void chunk. -#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) - typedef struct { uint32_t tag; WebPChunkId id; @@ -92,44 +89,6 @@ typedef struct { 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 (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16); -} - -// 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, 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, (int)(val & 0xffff)); - PutLE16(data + 2, (int)(val >> 16)); -} - -static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { - return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); -} - //------------------------------------------------------------------------------ // Chunk object management. @@ -167,6 +126,11 @@ WebPChunk* ChunkRelease(WebPChunk* const chunk); // Deletes given chunk & returns chunk->next_. WebPChunk* ChunkDelete(WebPChunk* const chunk); +// Returns size of the chunk including chunk header and padding byte (if any). +static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { + 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; diff --git a/src/mux/muxinternal.c b/src/mux/muxinternal.c index ebeb651e..be20dbd5 100644 --- a/src/mux/muxinternal.c +++ b/src/mux/muxinternal.c @@ -12,6 +12,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -220,35 +221,6 @@ uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) { return dst; } -//------------------------------------------------------------------------------ -// Manipulation of a WebPData object. - -void WebPDataInit(WebPData* webp_data) { - if (webp_data != NULL) { - memset(webp_data, 0, sizeof(*webp_data)); - } -} - -void WebPDataClear(WebPData* webp_data) { - if (webp_data != NULL) { - free((void*)webp_data->bytes); - WebPDataInit(webp_data); - } -} - -int WebPDataCopy(const WebPData* src, WebPData* dst) { - if (src == NULL || dst == NULL) return 0; - - WebPDataInit(dst); - if (src->bytes != NULL && src->size != 0) { - dst->bytes = (uint8_t*)malloc(src->size); - if (dst->bytes == NULL) return 0; - memcpy((void*)dst->bytes, src->bytes, src->size); - dst->size = src->size; - } - return 1; -} - //------------------------------------------------------------------------------ // Life of a MuxImage object. diff --git a/src/mux/muxread.c b/src/mux/muxread.c index e1862e4e..526c3002 100644 --- a/src/mux/muxread.c +++ b/src/mux/muxread.c @@ -12,6 +12,7 @@ #include #include "./muxi.h" +#include "../utils/utils.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { diff --git a/src/utils/utils.h b/src/utils/utils.h index a0347625..e5d6d630 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -7,11 +7,14 @@ // // Misc. common utility functions // -// Author: Skal (pascal.massimino@gmail.com) +// Authors: Skal (pascal.massimino@gmail.com) +// Urvang (urvang@google.com) #ifndef WEBP_UTILS_UTILS_H_ #define WEBP_UTILS_UTILS_H_ +#include + #include "../webp/types.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -35,6 +38,40 @@ void* WebPSafeMalloc(uint64_t nmemb, size_t size); // in order to favor the "calloc(num_foo, sizeof(foo))" pattern. void* WebPSafeCalloc(uint64_t nmemb, size_t size); +//------------------------------------------------------------------------------ +// Reading/writing data. + +// 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 (uint32_t)GetLE16(data) | (GetLE16(data + 2) << 16); +} + +// 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, 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, (int)(val & 0xffff)); + PutLE16(data + 2, (int)(val >> 16)); +} + //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/src/webp/demux.h b/src/webp/demux.h new file mode 100644 index 00000000..c8e77a59 --- /dev/null +++ b/src/webp/demux.h @@ -0,0 +1,171 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// 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/ +// ----------------------------------------------------------------------------- +// +// Demux API. +// Enables extraction of image and extended format data from WebP files. + +// TODO(urvang): Add an example code snippet (similar to mux.h). + +#ifndef WEBP_WEBP_DEMUX_H_ +#define WEBP_WEBP_DEMUX_H_ + +#include "./format_constants.h" +#include "./mux_types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) + +typedef struct WebPDemuxer WebPDemuxer; +#if !(defined(__cplusplus) || defined(c_plusplus)) +typedef enum WebPDemuxState WebPDemuxState; +typedef enum WebPFormatFeature WebPFormatFeature; +#endif +typedef struct WebPIterator WebPIterator; +typedef struct WebPChunkIterator WebPChunkIterator; + +//------------------------------------------------------------------------------ +// Life of a Demux object + +enum WebPDemuxState { + WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header. + WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available. + WEBP_DEMUX_DONE // Entire file has been parsed. +}; + +// Internal, version-checked, entry point +WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( + const WebPData*, int, WebPDemuxState*, int); + +// Parses the WebP file given by 'data'. +// A complete WebP file must be present in 'data' for the function to succeed. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { + return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); +} + +// Parses the WebP file given by 'data'. +// If 'state' is non-NULL it will be set to indicate the status of the demuxer. +// Returns a WebPDemuxer object on successful parse, NULL otherwise. +static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( + const WebPData* data, WebPDemuxState* state) { + return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); +} + +// Frees memory associated with 'dmux'. +WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); + +//------------------------------------------------------------------------------ +// Data/information extraction. + +enum WebPFormatFeature { + WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. + WEBP_FF_CANVAS_WIDTH, + WEBP_FF_CANVAS_HEIGHT, + WEBP_FF_LOOP_COUNT, + WEBP_FF_BACKGROUND_COLOR +}; + +// Get the 'feature' value from the 'dmux'. +// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() +// returned a state > WEBP_DEMUX_PARSING_HEADER. +WEBP_EXTERN(uint32_t) WebPDemuxGetI( + const WebPDemuxer* dmux, WebPFormatFeature feature); + +//------------------------------------------------------------------------------ +// Frame iteration. + +struct WebPIterator { + int frame_num; + int num_frames; + int fragment_num; + int num_fragments; + int x_offset, y_offset; // offset relative to the canvas. + int width, height; // dimensions of this frame or fragment. + int duration; // display duration in milliseconds. + WebPMuxAnimDispose dispose_method; // dispose method for the frame. + int complete; // true if 'fragment' contains a full frame. partial images + // may still be decoded with the WebP incremental decoder. + WebPData fragment; // The frame or fragment given by 'frame_num' and + // 'fragment_num'. + + uint32_t pad[4]; // padding for later use. + void* private_; // for internal use only. +}; + +// Retrieves frame 'frame_number' from 'dmux'. +// 'iter->fragment' points to the first fragment on return from this function. +// Individual fragments may be extracted using WebPDemuxSetFragment(). +// Setting 'frame_number' equal to 0 will return the last frame of the image. +// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. +// Call WebPDemuxReleaseIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of 'iter'. +WEBP_EXTERN(int) WebPDemuxGetFrame( + const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); + +// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or +// previous ('iter->frame_num' - 1) frame. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); + +// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. +// Returns true if fragment 'fragment_num' is present, false otherwise. +WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); + +//------------------------------------------------------------------------------ +// Chunk iteration. + +struct WebPChunkIterator { + // The current and total number of chunks with the fourcc given to + // WebPDemuxGetChunk(). + int chunk_num; + int num_chunks; + WebPData chunk; // The payload of the chunk. + + uint32_t pad[6]; // padding for later use + void* private_; +}; + +// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from +// 'dmux'. +// 'fourcc' is a character array containing the fourcc of the chunk to return, +// e.g., "ICCP", "XMP ", "EXIF", etc. +// Setting 'chunk_number' equal to 0 will return the last chunk in a set. +// Returns true if the chunk is found, false otherwise. Image related chunk +// payloads are accessed through WebPDemuxGetFrame() and related functions. +// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. +// NOTE: 'dmux' must persist for the lifetime of the iterator. +WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_number, + WebPChunkIterator* iter); + +// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous +// ('iter->chunk_num' - 1) chunk. These functions do not loop. +// Returns true on success, false otherwise. +WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); + +// Releases any memory associated with 'iter'. +// Must be called before destroying the associated WebPDemuxer with +// WebPDemuxDelete(). +WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); + +//------------------------------------------------------------------------------ + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_WEBP_DEMUX_H_ */ diff --git a/src/webp/format_constants.h b/src/webp/format_constants.h index daa511f0..2ac8fe67 100644 --- a/src/webp/format_constants.h +++ b/src/webp/format_constants.h @@ -70,14 +70,18 @@ typedef enum { #define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. #define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. -// VP8X Feature Flags. These should be the same as the corresponding values in -// the 'WebPFeatureFlags' enum defined in mux.h. -#define FRAGMENTS_FLAG_BIT 0x01 -#define ANIMATION_FLAG_BIT 0x02 -#define XMP_FLAG_BIT 0x04 -#define EXIF_FLAG_BIT 0x08 -#define ALPHA_FLAG_BIT 0x10 -#define ICC_FLAG_BIT 0x20 +// VP8X Feature Flags. +#if !(defined(__cplusplus) || defined(c_plusplus)) +typedef enum WebPFeatureFlags WebPFeatureFlags; +#endif +enum WebPFeatureFlags { + FRAGMENTS_FLAG = 0x00000001, + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020 +}; #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. diff --git a/src/webp/mux.h b/src/webp/mux.h index ea8caee4..ab963e92 100644 --- a/src/webp/mux.h +++ b/src/webp/mux.h @@ -45,7 +45,8 @@ #ifndef WEBP_WEBP_MUX_H_ #define WEBP_WEBP_MUX_H_ -#include "./types.h" +#include "./format_constants.h" +#include "./mux_types.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -54,24 +55,13 @@ extern "C" { #define WEBP_MUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) typedef struct WebPMux WebPMux; // main opaque object. -typedef struct WebPData WebPData; #if !(defined(__cplusplus) || defined(c_plusplus)) typedef enum WebPMuxError WebPMuxError; -typedef enum WebPFeatureFlags WebPFeatureFlags; typedef enum WebPChunkId WebPChunkId; -typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; #endif typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; typedef struct WebPMuxAnimParams WebPMuxAnimParams; -typedef struct WebPDemuxer WebPDemuxer; -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum WebPDemuxState WebPDemuxState; -typedef enum WebPFormatFeature WebPFormatFeature; -#endif -typedef struct WebPIterator WebPIterator; -typedef struct WebPChunkIterator WebPChunkIterator; - // Error codes enum WebPMuxError { WEBP_MUX_OK = 1, @@ -82,16 +72,6 @@ enum WebPMuxError { WEBP_MUX_NOT_ENOUGH_DATA = -4 }; -// Flag values for different features used in VP8X chunk. -enum WebPFeatureFlags { - FRAGMENTS_FLAG = 0x00000001, - ANIMATION_FLAG = 0x00000002, - XMP_FLAG = 0x00000004, - EXIF_FLAG = 0x00000008, - ALPHA_FLAG = 0x00000010, - ICCP_FLAG = 0x00000020 -}; - // IDs for different types of chunks. enum WebPChunkId { WEBP_CHUNK_VP8X, // VP8X @@ -107,27 +87,6 @@ enum WebPChunkId { WEBP_CHUNK_NIL }; -// Data type used to describe 'raw' data, e.g., chunk data -// (ICC profile, metadata) and WebP compressed image data. -struct WebPData { - const uint8_t* bytes; - size_t size; -}; - -//------------------------------------------------------------------------------ -// Manipulation of a WebPData object. - -// Initializes the contents of the 'webp_data' object with default values. -WEBP_EXTERN(void) WebPDataInit(WebPData* webp_data); - -// Clears the contents of the 'webp_data' object by calling free(). Does not -// deallocate the object itself. -WEBP_EXTERN(void) WebPDataClear(WebPData* webp_data); - -// Allocates necessary storage for 'dst' and copies the contents of 'src'. -// Returns true on success. -WEBP_EXTERN(int) WebPDataCopy(const WebPData* src, WebPData* dst); - //------------------------------------------------------------------------------ // Life of a Mux object @@ -222,13 +181,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( //------------------------------------------------------------------------------ // Images. -// Dispose method (animation only). Indicates how the area used by the current -// frame is to be treated before rendering the next frame on the canvas. -enum WebPMuxAnimDispose { - WEBP_MUX_DISPOSE_NONE, // Do not dispose. - WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. -}; - // Encapsulates data about a single frame/fragment. struct WebPMuxFrameInfo { WebPData bitstream; // image data: can either be a raw VP8/VP8L bitstream @@ -389,144 +341,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data); -//------------------------------------------------------------------------------ -// Demux API. -// Enables extraction of image and extended format data from WebP files. - -#define WEBP_DEMUX_ABI_VERSION 0x0100 // MAJOR(8b) + MINOR(8b) - -enum WebPDemuxState { - WEBP_DEMUX_PARSING_HEADER, // Not enough data to parse full header. - WEBP_DEMUX_PARSED_HEADER, // Header parsing complete, data may be available. - WEBP_DEMUX_DONE // Entire file has been parsed. -}; - -//------------------------------------------------------------------------------ -// Life of a Demux object - -// Internal, version-checked, entry point -WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( - const WebPData*, int, WebPDemuxState*, int); - -// Parses the WebP file given by 'data'. -// A complete WebP file must be present in 'data' for the function to succeed. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { - return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); -} - -// Parses the WebP file given by 'data'. -// If 'state' is non-NULL it will be set to indicate the status of the demuxer. -// Returns a WebPDemuxer object on successful parse, NULL otherwise. -static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( - const WebPData* data, WebPDemuxState* state) { - return WebPDemuxInternal(data, 1, state, WEBP_DEMUX_ABI_VERSION); -} - -// Frees memory associated with 'dmux'. -WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); - -//------------------------------------------------------------------------------ -// Data/information extraction. - -enum WebPFormatFeature { - WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. - WEBP_FF_CANVAS_WIDTH, - WEBP_FF_CANVAS_HEIGHT, - WEBP_FF_LOOP_COUNT, - WEBP_FF_BACKGROUND_COLOR -}; - -// Get the 'feature' value from the 'dmux'. -// NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() -// returned a state > WEBP_DEMUX_PARSING_HEADER. -WEBP_EXTERN(uint32_t) WebPDemuxGetI( - const WebPDemuxer* dmux, WebPFormatFeature feature); - -//------------------------------------------------------------------------------ -// Frame iteration. - -struct WebPIterator { - int frame_num; - int num_frames; - int fragment_num; - int num_fragments; - int x_offset, y_offset; // offset relative to the canvas. - int width, height; // dimensions of this frame or fragment. - int duration; // display duration in milliseconds. - WebPMuxAnimDispose dispose_method; // dispose method for the frame. - int complete; // true if 'fragment' contains a full frame. partial images - // may still be decoded with the WebP incremental decoder. - WebPData fragment; // The frame or fragment given by 'frame_num' and - // 'fragment_num'. - - uint32_t pad[4]; // padding for later use. - void* private_; // for internal use only. -}; - -// Retrieves frame 'frame_number' from 'dmux'. -// 'iter->fragment' points to the first fragment on return from this function. -// Individual fragments may be extracted using WebPDemuxSetFragment(). -// Setting 'frame_number' equal to 0 will return the last frame of the image. -// Returns false if 'dmux' is NULL or frame 'frame_number' is not present. -// Call WebPDemuxReleaseIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN(int) WebPDemuxGetFrame( - const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); - -// Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or -// previous ('iter->frame_num' - 1) frame. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); - -// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. -// Returns true if fragment 'fragment_num' is present, false otherwise. -WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); - -//------------------------------------------------------------------------------ -// Chunk iteration. - -struct WebPChunkIterator { - // The current and total number of chunks with the fourcc given to - // WebPDemuxGetChunk(). - int chunk_num; - int num_chunks; - WebPData chunk; // The payload of the chunk. - - uint32_t pad[6]; // padding for later use - void* private_; -}; - -// Retrieves the 'chunk_number' instance of the chunk with id 'fourcc' from -// 'dmux'. -// 'fourcc' is a character array containing the fourcc of the chunk to return, -// e.g., "ICCP", "XMP ", "EXIF", etc. -// Setting 'chunk_number' equal to 0 will return the last chunk in a set. -// Returns true if the chunk is found, false otherwise. Image related chunk -// payloads are accessed through WebPDemuxGetFrame() and related functions. -// Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. -// NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); - -// Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous -// ('iter->chunk_num' - 1) chunk. These functions do not loop. -// Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); - -// Releases any memory associated with 'iter'. -// Must be called before destroying the associated WebPDemuxer with -// WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); - //------------------------------------------------------------------------------ #if defined(__cplusplus) || defined(c_plusplus) diff --git a/src/webp/mux_types.h b/src/webp/mux_types.h new file mode 100644 index 00000000..84d94472 --- /dev/null +++ b/src/webp/mux_types.h @@ -0,0 +1,78 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// 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/ +// ----------------------------------------------------------------------------- +// +// Internal header for some common data-types used by mux and demux libraries. +// +// Author: Urvang (urvang@google.com) + +#ifndef WEBP_WEBP_MUX_TYPES_H_ +#define WEBP_WEBP_MUX_TYPES_H_ + +#include // free() +#include // memset() +#include "./types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +// Create fourcc of the chunk from the chunk tag characters. +#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) + +// Dispose method (animation only). Indicates how the area used by the current +// frame is to be treated before rendering the next frame on the canvas. +#if !(defined(__cplusplus) || defined(c_plusplus)) +typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; +#endif +enum WebPMuxAnimDispose { + WEBP_MUX_DISPOSE_NONE, // Do not dispose. + WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color. +}; + +// Data type used to describe 'raw' data, e.g., chunk data +// (ICC profile, metadata) and WebP compressed image data. +typedef struct WebPData WebPData; +struct WebPData { + const uint8_t* bytes; + size_t size; +}; + +// Initializes the contents of the 'webp_data' object with default values. +static WEBP_INLINE void WebPDataInit(WebPData* webp_data) { + if (webp_data != NULL) { + memset(webp_data, 0, sizeof(*webp_data)); + } +} + +// Clears the contents of the 'webp_data' object by calling free(). Does not +// deallocate the object itself. +static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { + if (webp_data != NULL) { + free((void*)webp_data->bytes); + WebPDataInit(webp_data); + } +} + +// Allocates necessary storage for 'dst' and copies the contents of 'src'. +// Returns true on success. +static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) { + if (src == NULL || dst == NULL) return 0; + WebPDataInit(dst); + if (src->bytes != NULL && src->size != 0) { + dst->bytes = (uint8_t*)malloc(src->size); + if (dst->bytes == NULL) return 0; + memcpy((void*)dst->bytes, src->bytes, src->size); + dst->size = src->size; + } + return 1; +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_WEBP_MUX_TYPES_H_ */