diff options
Diffstat (limited to 'src/3rdparty/libwebp/src/dec')
-rw-r--r-- | src/3rdparty/libwebp/src/dec/alpha_dec.c | 14 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/alphai_dec.h | 10 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/buffer_dec.c | 54 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/common_dec.h | 6 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/frame_dec.c | 37 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/idec_dec.c | 39 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/io_dec.c | 24 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/quant_dec.c | 19 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/tree_dec.c | 75 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/vp8_dec.c | 95 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/vp8_dec.h | 18 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/vp8i_dec.h | 25 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/vp8l_dec.c | 224 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/vp8li_dec.h | 14 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/webp_dec.c | 14 | ||||
-rw-r--r-- | src/3rdparty/libwebp/src/dec/webpi_dec.h | 10 |
16 files changed, 391 insertions, 287 deletions
diff --git a/src/3rdparty/libwebp/src/dec/alpha_dec.c b/src/3rdparty/libwebp/src/dec/alpha_dec.c index 83ffd4b..bce735b 100644 --- a/src/3rdparty/libwebp/src/dec/alpha_dec.c +++ b/src/3rdparty/libwebp/src/dec/alpha_dec.c @@ -12,13 +12,13 @@ // Author: Skal (pascal.massimino@gmail.com) #include <stdlib.h> -#include "./alphai_dec.h" -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "../dsp/dsp.h" -#include "../utils/quant_levels_dec_utils.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/quant_levels_dec_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" //------------------------------------------------------------------------------ // ALPHDecoder object. diff --git a/src/3rdparty/libwebp/src/dec/alphai_dec.h b/src/3rdparty/libwebp/src/dec/alphai_dec.h index 561e815..a64104a 100644 --- a/src/3rdparty/libwebp/src/dec/alphai_dec.h +++ b/src/3rdparty/libwebp/src/dec/alphai_dec.h @@ -11,11 +11,11 @@ // // Author: Urvang (urvang@google.com) -#ifndef WEBP_DEC_ALPHAI_H_ -#define WEBP_DEC_ALPHAI_H_ +#ifndef WEBP_DEC_ALPHAI_DEC_H_ +#define WEBP_DEC_ALPHAI_DEC_H_ -#include "./webpi_dec.h" -#include "../utils/filters_utils.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/filters_utils.h" #ifdef __cplusplus extern "C" { @@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_ALPHAI_H_ */ +#endif // WEBP_DEC_ALPHAI_DEC_H_ diff --git a/src/3rdparty/libwebp/src/dec/buffer_dec.c b/src/3rdparty/libwebp/src/dec/buffer_dec.c index c685fd5..3cd94eb 100644 --- a/src/3rdparty/libwebp/src/dec/buffer_dec.c +++ b/src/3rdparty/libwebp/src/dec/buffer_dec.c @@ -13,15 +13,15 @@ #include <stdlib.h> -#include "./vp8i_dec.h" -#include "./webpi_dec.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // WebPDecBuffer // Number of bytes per pixel for the different color-spaces. -static const int kModeBpp[MODE_LAST] = { +static const uint8_t kModeBpp[MODE_LAST] = { 3, 4, 3, 4, 4, 2, 2, 4, 4, 4, 2, // pre-multiplied modes 1, 1 }; @@ -36,7 +36,7 @@ static int IsValidColorspace(int webp_csp_mode) { // strictly speaking, the very last (or first, if flipped) row // doesn't require padding. #define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ - (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH) + ((uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)) static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { int ok = 1; @@ -74,7 +74,8 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { } else { // RGB checks const WebPRGBABuffer* const buf = &buffer->u.RGBA; const int stride = abs(buf->stride); - const uint64_t size = MIN_BUFFER_SIZE(width, height, stride); + const uint64_t size = + MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride); ok &= (size <= buf->size); ok &= (stride >= width * kModeBpp[mode]); ok &= (buf->rgba != NULL); @@ -98,9 +99,14 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { uint64_t uv_size = 0, a_size = 0, total_size; // We need memory and it hasn't been allocated yet. // => initialize output buffer, now that dimensions are known. - const int stride = w * kModeBpp[mode]; - const uint64_t size = (uint64_t)stride * h; + int stride; + uint64_t size; + if ((uint64_t)w * kModeBpp[mode] >= (1ull << 32)) { + return VP8_STATUS_INVALID_PARAM; + } + stride = w * kModeBpp[mode]; + size = (uint64_t)stride * h; if (!WebPIsRGBMode(mode)) { uv_stride = (w + 1) / 2; uv_size = (uint64_t)uv_stride * ((h + 1) / 2); @@ -169,11 +175,11 @@ VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { return VP8_STATUS_OK; } -VP8StatusCode WebPAllocateDecBuffer(int w, int h, +VP8StatusCode WebPAllocateDecBuffer(int width, int height, const WebPDecoderOptions* const options, - WebPDecBuffer* const out) { + WebPDecBuffer* const buffer) { VP8StatusCode status; - if (out == NULL || w <= 0 || h <= 0) { + if (buffer == NULL || width <= 0 || height <= 0) { return VP8_STATUS_INVALID_PARAM; } if (options != NULL) { // First, apply options if there is any. @@ -182,33 +188,39 @@ VP8StatusCode WebPAllocateDecBuffer(int w, int h, const int ch = options->crop_height; const int x = options->crop_left & ~1; const int y = options->crop_top & ~1; - if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { + if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || + x + cw > width || y + ch > height) { return VP8_STATUS_INVALID_PARAM; // out of frame boundary. } - w = cw; - h = ch; + width = cw; + height = ch; } + if (options->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) int scaled_width = options->scaled_width; int scaled_height = options->scaled_height; if (!WebPRescalerGetScaledDimensions( - w, h, &scaled_width, &scaled_height)) { + width, height, &scaled_width, &scaled_height)) { return VP8_STATUS_INVALID_PARAM; } - w = scaled_width; - h = scaled_height; + width = scaled_width; + height = scaled_height; +#else + return VP8_STATUS_INVALID_PARAM; // rescaling not supported +#endif } } - out->width = w; - out->height = h; + buffer->width = width; + buffer->height = height; // Then, allocate buffer for real. - status = AllocateBuffer(out); + status = AllocateBuffer(buffer); if (status != VP8_STATUS_OK) return status; // Use the stride trick if vertical flip is needed. if (options != NULL && options->flip) { - status = WebPFlipBuffer(out); + status = WebPFlipBuffer(buffer); } return status; } diff --git a/src/3rdparty/libwebp/src/dec/common_dec.h b/src/3rdparty/libwebp/src/dec/common_dec.h index 6961e22..b158550 100644 --- a/src/3rdparty/libwebp/src/dec/common_dec.h +++ b/src/3rdparty/libwebp/src/dec/common_dec.h @@ -11,8 +11,8 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_DEC_COMMON_H_ -#define WEBP_DEC_COMMON_H_ +#ifndef WEBP_DEC_COMMON_DEC_H_ +#define WEBP_DEC_COMMON_DEC_H_ // intra prediction modes enum { B_DC_PRED = 0, // 4x4 modes @@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3, NUM_PROBAS = 11 }; -#endif // WEBP_DEC_COMMON_H_ +#endif // WEBP_DEC_COMMON_DEC_H_ diff --git a/src/3rdparty/libwebp/src/dec/frame_dec.c b/src/3rdparty/libwebp/src/dec/frame_dec.c index f91e27f..bda9e1a 100644 --- a/src/3rdparty/libwebp/src/dec/frame_dec.c +++ b/src/3rdparty/libwebp/src/dec/frame_dec.c @@ -12,13 +12,13 @@ // Author: Skal (pascal.massimino@gmail.com) #include <stdlib.h> -#include "./vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Main reconstruction function. -static const int kScan[16] = { +static const uint16_t kScan[16] = { 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, @@ -320,7 +320,7 @@ static void PrecomputeFilterStrengths(VP8Decoder* const dec) { #define MIN_DITHER_AMP 4 #define DITHER_AMP_TAB_SIZE 12 -static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { +static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { // roughly, it's dqm->uv_mat_[1] 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 }; @@ -338,7 +338,6 @@ void VP8InitDithering(const WebPDecoderOptions* const options, for (s = 0; s < NUM_MB_SEGMENTS; ++s) { VP8QuantMatrix* const dqm = &dec->dqm_[s]; if (dqm->uv_quant_ < DITHER_AMP_TAB_SIZE) { - // TODO(skal): should we specially dither more for uv_quant_ < 0? const int idx = (dqm->uv_quant_ < 0) ? 0 : dqm->uv_quant_; dqm->dither_ = (f * kQuantToDitherAmp[idx]) >> 3; } @@ -400,7 +399,9 @@ static void DitherRow(VP8Decoder* const dec) { #define MACROBLOCK_VPOS(mb_y) ((mb_y) * 16) // vertical position of a MB // Finalize and transmit a complete row. Return false in case of user-abort. -static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { +static int FinishRow(void* arg1, void* arg2) { + VP8Decoder* const dec = (VP8Decoder*)arg1; + VP8Io* const io = (VP8Io*)arg2; int ok = 1; const VP8ThreadContext* const ctx = &dec->thread_ctx_; const int cache_id = ctx->id_; @@ -448,10 +449,9 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { if (y_end > io->crop_bottom) { y_end = io->crop_bottom; // make sure we don't overflow on last row. } + // If dec->alpha_data_ is not NULL, we have some alpha plane present. io->a = NULL; if (dec->alpha_data_ != NULL && y_start < y_end) { - // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a - // good idea. io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); if (io->a == NULL) { return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, @@ -558,7 +558,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { if (io->bypass_filtering) { dec->filter_type_ = 0; } - // TODO(skal): filter type / strength / sharpness forcing // Define the area where we can skip in-loop filtering, in case of cropping. // @@ -569,8 +568,6 @@ VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) { // Means: there's a dependency chain that goes all the way up to the // top-left corner of the picture (MB #0). We must filter all the previous // macroblocks. - // TODO(skal): add an 'approximate_decoding' option, that won't produce - // a 1:1 bit-exactness for complex filtering? { const int extra_pixels = kFilterExtraRows[dec->filter_type_]; if (dec->filter_type_ == 2) { @@ -651,7 +648,7 @@ static int InitThreadContext(VP8Decoder* const dec) { } worker->data1 = dec; worker->data2 = (void*)&dec->thread_ctx_.io_; - worker->hook = (WebPWorkerHook)FinishRow; + worker->hook = FinishRow; dec->num_caches_ = (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1; } else { @@ -671,15 +668,9 @@ int VP8GetThreadMethod(const WebPDecoderOptions* const options, (void)height; assert(headers == NULL || !headers->is_lossless); #if defined(WEBP_USE_THREAD) - if (width < MIN_WIDTH_FOR_THREADS) return 0; - // TODO(skal): tune the heuristic further -#if 0 - if (height < 2 * width) return 2; + if (width >= MIN_WIDTH_FOR_THREADS) return 2; #endif - return 2; -#else // !WEBP_USE_THREAD return 0; -#endif } #undef MT_CACHE_LINES @@ -728,7 +719,7 @@ static int AllocateMemory(VP8Decoder* const dec) { } mem = (uint8_t*)dec->mem_; - dec->intra_t_ = (uint8_t*)mem; + dec->intra_t_ = mem; mem += intra_pred_mode_size; dec->yuv_t_ = (VP8TopSamples*)mem; @@ -750,7 +741,7 @@ static int AllocateMemory(VP8Decoder* const dec) { mem = (uint8_t*)WEBP_ALIGN(mem); assert((yuv_size & WEBP_ALIGN_CST) == 0); - dec->yuv_b_ = (uint8_t*)mem; + dec->yuv_b_ = mem; mem += yuv_size; dec->mb_data_ = (VP8MBData*)mem; @@ -766,7 +757,7 @@ static int AllocateMemory(VP8Decoder* const dec) { const int extra_rows = kFilterExtraRows[dec->filter_type_]; const int extra_y = extra_rows * dec->cache_y_stride_; const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; - dec->cache_y_ = ((uint8_t*)mem) + extra_y; + dec->cache_y_ = mem + extra_y; dec->cache_u_ = dec->cache_y_ + 16 * num_caches * dec->cache_y_stride_ + extra_uv; dec->cache_v_ = dec->cache_u_ @@ -776,7 +767,7 @@ static int AllocateMemory(VP8Decoder* const dec) { mem += cache_size; // alpha plane - dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL; + dec->alpha_plane_ = alpha_size ? mem : NULL; mem += alpha_size; assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); diff --git a/src/3rdparty/libwebp/src/dec/idec_dec.c b/src/3rdparty/libwebp/src/dec/idec_dec.c index 78fb2e7..9bc9166 100644 --- a/src/3rdparty/libwebp/src/dec/idec_dec.c +++ b/src/3rdparty/libwebp/src/dec/idec_dec.c @@ -15,10 +15,10 @@ #include <string.h> #include <stdlib.h> -#include "./alphai_dec.h" -#include "./webpi_dec.h" -#include "./vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" // In append mode, buffer allocations increase as multiples of this value. // Needs to be a power of 2. @@ -140,10 +140,9 @@ static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) { if (NeedCompressedAlpha(idec)) { ALPHDecoder* const alph_dec = dec->alph_dec_; dec->alpha_data_ += offset; - if (alph_dec != NULL) { + if (alph_dec != NULL && alph_dec->vp8l_dec_ != NULL) { if (alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION) { VP8LDecoder* const alph_vp8l_dec = alph_dec->vp8l_dec_; - assert(alph_vp8l_dec != NULL); assert(dec->alpha_data_size_ >= ALPHA_HEADER_LEN); VP8LBitReaderSetBuffer(&alph_vp8l_dec->br_, dec->alpha_data_ + ALPHA_HEADER_LEN, @@ -283,10 +282,8 @@ static void RestoreContext(const MBContext* context, VP8Decoder* const dec, static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) { if (idec->state_ == STATE_VP8_DATA) { - VP8Io* const io = &idec->io_; - if (io->teardown != NULL) { - io->teardown(io); - } + // Synchronize the thread, clean-up and check for errors. + VP8ExitCritical((VP8Decoder*)idec->dec_, &idec->io_); } idec->state_ = STATE_ERROR; return error; @@ -451,7 +448,10 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8Io* const io = &idec->io_; - assert(dec->ready_); + // Make sure partition #0 has been read before, to set dec to ready_. + if (!dec->ready_) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) { if (idec->last_mb_y_ != dec->mb_y_) { if (!VP8ParseIntraModeRow(&dec->br_, dec)) { @@ -473,6 +473,12 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { MemDataSize(&idec->mem_) > MAX_MB_SIZE) { return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); } + // Synchronize the threads. + if (dec->mt_method_ > 0) { + if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) { + return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR); + } + } RestoreContext(&context, dec, token_br); return VP8_STATUS_SUSPENDED; } @@ -491,6 +497,7 @@ static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) { } // Synchronize the thread and check for errors. if (!VP8ExitCritical(dec, io)) { + idec->state_ = STATE_ERROR; // prevent re-entry in IDecError return IDecError(idec, VP8_STATUS_USER_ABORT); } dec->ready_ = 0; @@ -571,6 +578,10 @@ static VP8StatusCode IDecode(WebPIDecoder* idec) { status = DecodePartition0(idec); } if (idec->state_ == STATE_VP8_DATA) { + const VP8Decoder* const dec = (VP8Decoder*)idec->dec_; + if (dec == NULL) { + return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder. + } status = DecodeRemaining(idec); } if (idec->state_ == STATE_VP8L_HEADER) { @@ -673,12 +684,12 @@ void WebPIDelete(WebPIDecoder* idec) { //------------------------------------------------------------------------------ // Wrapper toward WebPINewDecoder -WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, +WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride) { const int is_external_memory = (output_buffer != NULL) ? 1 : 0; WebPIDecoder* idec; - if (mode >= MODE_YUV) return NULL; + if (csp >= MODE_YUV) return NULL; if (is_external_memory == 0) { // Overwrite parameters to sane values. output_buffer_size = 0; output_stride = 0; @@ -689,7 +700,7 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, } idec = WebPINewDecoder(NULL); if (idec == NULL) return NULL; - idec->output_.colorspace = mode; + idec->output_.colorspace = csp; idec->output_.is_external_memory = is_external_memory; idec->output_.u.RGBA.rgba = output_buffer; idec->output_.u.RGBA.stride = output_stride; diff --git a/src/3rdparty/libwebp/src/dec/io_dec.c b/src/3rdparty/libwebp/src/dec/io_dec.c index 8bfab86..e603f19 100644 --- a/src/3rdparty/libwebp/src/dec/io_dec.c +++ b/src/3rdparty/libwebp/src/dec/io_dec.c @@ -13,11 +13,11 @@ #include <assert.h> #include <stdlib.h> -#include "../dec/vp8i_dec.h" -#include "./webpi_dec.h" -#include "../dsp/dsp.h" -#include "../dsp/yuv.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Main YUV<->RGB conversion functions @@ -212,7 +212,7 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, int num_rows; const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) uint8_t* alpha_dst = base_rgba; #else uint8_t* alpha_dst = base_rgba + 1; @@ -241,6 +241,7 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, //------------------------------------------------------------------------------ // YUV rescaling (no final RGB conversion needed) +#if !defined(WEBP_REDUCE_SIZE) static int Rescale(const uint8_t* src, int src_stride, int new_lines, WebPRescaler* const wrk) { int num_lines_out = 0; @@ -431,7 +432,7 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, int max_lines_out) { const WebPRGBABuffer* const buf = &p->output->u.RGBA; uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) uint8_t* alpha_dst = base_rgba; #else uint8_t* alpha_dst = base_rgba + 1; @@ -541,6 +542,8 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { return 1; } +#endif // WEBP_REDUCE_SIZE + //------------------------------------------------------------------------------ // Default custom functions @@ -561,10 +564,14 @@ static int CustomSetup(VP8Io* io) { WebPInitUpsamplers(); } if (io->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); if (!ok) { return 0; // memory error } +#else + return 0; // rescaling support not compiled +#endif } else { if (is_rgb) { WebPInitSamplers(); @@ -598,9 +605,6 @@ static int CustomSetup(VP8Io* io) { } } - if (is_rgb) { - VP8YUVInit(); - } return 1; } diff --git a/src/3rdparty/libwebp/src/dec/quant_dec.c b/src/3rdparty/libwebp/src/dec/quant_dec.c index 14e3198..a0ac018 100644 --- a/src/3rdparty/libwebp/src/dec/quant_dec.c +++ b/src/3rdparty/libwebp/src/dec/quant_dec.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./vp8i_dec.h" +#include "src/dec/vp8i_dec.h" static WEBP_INLINE int clip(int v, int M) { return v < 0 ? 0 : v > M ? M : v; @@ -61,12 +61,17 @@ static const uint16_t kAcTable[128] = { void VP8ParseQuant(VP8Decoder* const dec) { VP8BitReader* const br = &dec->br_; - const int base_q0 = VP8GetValue(br, 7); - const int dqy1_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dqy2_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_dc = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; - const int dquv_ac = VP8Get(br) ? VP8GetSignedValue(br, 4) : 0; + const int base_q0 = VP8GetValue(br, 7, "global-header"); + const int dqy1_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dqy2_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_dc = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; + const int dquv_ac = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 4, "global-header") : 0; const VP8SegmentHeader* const hdr = &dec->segment_hdr_; int i; diff --git a/src/3rdparty/libwebp/src/dec/tree_dec.c b/src/3rdparty/libwebp/src/dec/tree_dec.c index 9e805f6..1c6fdea 100644 --- a/src/3rdparty/libwebp/src/dec/tree_dec.c +++ b/src/3rdparty/libwebp/src/dec/tree_dec.c @@ -11,15 +11,19 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./vp8i_dec.h" -#include "../utils/bit_reader_inl_utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#if !defined(USE_GENERIC_TREE) #if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) // using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. -#define USE_GENERIC_TREE +#define USE_GENERIC_TREE 1 // ALTERNATE_CODE +#else +#define USE_GENERIC_TREE 0 #endif +#endif // USE_GENERIC_TREE -#ifdef USE_GENERIC_TREE +#if (USE_GENERIC_TREE == 1) static const int8_t kYModesIntra4[18] = { -B_DC_PRED, 1, -B_TM_PRED, 2, @@ -292,20 +296,21 @@ static void ParseIntraMode(VP8BitReader* const br, // to decode more than 1 keyframe. if (dec->segment_hdr_.update_map_) { // Hardcoded tree parsing - block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) - ? VP8GetBit(br, dec->proba_.segments_[1]) - : 2 + VP8GetBit(br, dec->proba_.segments_[2]); + block->segment_ = !VP8GetBit(br, dec->proba_.segments_[0], "segments") + ? VP8GetBit(br, dec->proba_.segments_[1], "segments") + : VP8GetBit(br, dec->proba_.segments_[2], "segments") + 2; } else { block->segment_ = 0; // default for intra } - if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_); + if (dec->use_skip_proba_) block->skip_ = VP8GetBit(br, dec->skip_p_, "skip"); - block->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first + block->is_i4x4_ = !VP8GetBit(br, 145, "block-size"); if (!block->is_i4x4_) { // Hardcoded 16x16 intra-mode decision tree. const int ymode = - VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED) - : (VP8GetBit(br, 163) ? V_PRED : DC_PRED); + VP8GetBit(br, 156, "pred-modes") ? + (VP8GetBit(br, 128, "pred-modes") ? TM_PRED : H_PRED) : + (VP8GetBit(br, 163, "pred-modes") ? V_PRED : DC_PRED); block->imodes_[0] = ymode; memset(top, ymode, 4 * sizeof(*top)); memset(left, ymode, 4 * sizeof(*left)); @@ -317,25 +322,28 @@ static void ParseIntraMode(VP8BitReader* const br, int x; for (x = 0; x < 4; ++x) { const uint8_t* const prob = kBModesProba[top[x]][ymode]; -#ifdef USE_GENERIC_TREE +#if (USE_GENERIC_TREE == 1) // Generic tree-parsing - int i = kYModesIntra4[VP8GetBit(br, prob[0])]; + int i = kYModesIntra4[VP8GetBit(br, prob[0], "pred-modes")]; while (i > 0) { - i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])]; + i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i], "pred-modes")]; } ymode = -i; #else // Hardcoded tree parsing - ymode = !VP8GetBit(br, prob[0]) ? B_DC_PRED : - !VP8GetBit(br, prob[1]) ? B_TM_PRED : - !VP8GetBit(br, prob[2]) ? B_VE_PRED : - !VP8GetBit(br, prob[3]) ? - (!VP8GetBit(br, prob[4]) ? B_HE_PRED : - (!VP8GetBit(br, prob[5]) ? B_RD_PRED : B_VR_PRED)) : - (!VP8GetBit(br, prob[6]) ? B_LD_PRED : - (!VP8GetBit(br, prob[7]) ? B_VL_PRED : - (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); -#endif // USE_GENERIC_TREE + ymode = !VP8GetBit(br, prob[0], "pred-modes") ? B_DC_PRED : + !VP8GetBit(br, prob[1], "pred-modes") ? B_TM_PRED : + !VP8GetBit(br, prob[2], "pred-modes") ? B_VE_PRED : + !VP8GetBit(br, prob[3], "pred-modes") ? + (!VP8GetBit(br, prob[4], "pred-modes") ? B_HE_PRED : + (!VP8GetBit(br, prob[5], "pred-modes") ? B_RD_PRED + : B_VR_PRED)) : + (!VP8GetBit(br, prob[6], "pred-modes") ? B_LD_PRED : + (!VP8GetBit(br, prob[7], "pred-modes") ? B_VL_PRED : + (!VP8GetBit(br, prob[8], "pred-modes") ? B_HD_PRED + : B_HU_PRED)) + ); +#endif // USE_GENERIC_TREE top[x] = ymode; } memcpy(modes, top, 4 * sizeof(*top)); @@ -344,9 +352,9 @@ static void ParseIntraMode(VP8BitReader* const br, } } // Hardcoded UVMode decision tree - block->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED - : !VP8GetBit(br, 114) ? V_PRED - : VP8GetBit(br, 183) ? TM_PRED : H_PRED; + block->uvmode_ = !VP8GetBit(br, 142, "pred-modes-uv") ? DC_PRED + : !VP8GetBit(br, 114, "pred-modes-uv") ? V_PRED + : VP8GetBit(br, 183, "pred-modes-uv") ? TM_PRED : H_PRED; } int VP8ParseIntraModeRow(VP8BitReader* const br, VP8Decoder* const dec) { @@ -498,7 +506,7 @@ static const uint8_t // Paragraph 9.9 -static const int kBands[16 + 1] = { +static const uint8_t kBands[16 + 1] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0 // extra entry as sentinel }; @@ -510,8 +518,10 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { for (b = 0; b < NUM_BANDS; ++b) { for (c = 0; c < NUM_CTX; ++c) { for (p = 0; p < NUM_PROBAS; ++p) { - const int v = VP8GetBit(br, CoeffsUpdateProba[t][b][c][p]) ? - VP8GetValue(br, 8) : CoeffsProba0[t][b][c][p]; + const int v = + VP8GetBit(br, CoeffsUpdateProba[t][b][c][p], "global-header") ? + VP8GetValue(br, 8, "global-header") : + CoeffsProba0[t][b][c][p]; proba->bands_[t][b].probas_[c][p] = v; } } @@ -520,9 +530,8 @@ void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) { proba->bands_ptr_[t][b] = &proba->bands_[t][kBands[b]]; } } - dec->use_skip_proba_ = VP8Get(br); + dec->use_skip_proba_ = VP8Get(br, "global-header"); if (dec->use_skip_proba_) { - dec->skip_p_ = VP8GetValue(br, 8); + dec->skip_p_ = VP8GetValue(br, 8, "global-header"); } } - diff --git a/src/3rdparty/libwebp/src/dec/vp8_dec.c b/src/3rdparty/libwebp/src/dec/vp8_dec.c index fad8d9c..57efb69 100644 --- a/src/3rdparty/libwebp/src/dec/vp8_dec.c +++ b/src/3rdparty/libwebp/src/dec/vp8_dec.c @@ -13,12 +13,12 @@ #include <stdlib.h> -#include "./alphai_dec.h" -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "./webpi_dec.h" -#include "../utils/bit_reader_inl_utils.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ @@ -161,23 +161,26 @@ static int ParseSegmentHeader(VP8BitReader* br, VP8SegmentHeader* hdr, VP8Proba* proba) { assert(br != NULL); assert(hdr != NULL); - hdr->use_segment_ = VP8Get(br); + hdr->use_segment_ = VP8Get(br, "global-header"); if (hdr->use_segment_) { - hdr->update_map_ = VP8Get(br); - if (VP8Get(br)) { // update data + hdr->update_map_ = VP8Get(br, "global-header"); + if (VP8Get(br, "global-header")) { // update data int s; - hdr->absolute_delta_ = VP8Get(br); + hdr->absolute_delta_ = VP8Get(br, "global-header"); for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0; + hdr->quantizer_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 7, "global-header") : 0; } for (s = 0; s < NUM_MB_SEGMENTS; ++s) { - hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0; + hdr->filter_strength_[s] = VP8Get(br, "global-header") ? + VP8GetSignedValue(br, 6, "global-header") : 0; } } if (hdr->update_map_) { int s; for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { - proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u; + proba->segments_[s] = VP8Get(br, "global-header") ? + VP8GetValue(br, 8, "global-header") : 255u; } } } else { @@ -205,7 +208,7 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, size_t last_part; size_t p; - dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1; + dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1; last_part = dec->num_parts_minus_one_; if (size < 3 * last_part) { // we can't even read the sizes with sz[]! That's a failure. @@ -229,21 +232,21 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, // Paragraph 9.4 static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { VP8FilterHeader* const hdr = &dec->filter_hdr_; - hdr->simple_ = VP8Get(br); - hdr->level_ = VP8GetValue(br, 6); - hdr->sharpness_ = VP8GetValue(br, 3); - hdr->use_lf_delta_ = VP8Get(br); + hdr->simple_ = VP8Get(br, "global-header"); + hdr->level_ = VP8GetValue(br, 6, "global-header"); + hdr->sharpness_ = VP8GetValue(br, 3, "global-header"); + hdr->use_lf_delta_ = VP8Get(br, "global-header"); if (hdr->use_lf_delta_) { - if (VP8Get(br)) { // update lf-delta? + if (VP8Get(br, "global-header")) { // update lf-delta? int i; for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6); + if (VP8Get(br, "global-header")) { + hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); } } for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { - if (VP8Get(br)) { - hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6); + if (VP8Get(br, "global-header")) { + hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); } } } @@ -352,8 +355,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { buf_size -= frm_hdr->partition_length_; if (frm_hdr->key_frame_) { - pic_hdr->colorspace_ = VP8Get(br); - pic_hdr->clamp_type_ = VP8Get(br); + pic_hdr->colorspace_ = VP8Get(br, "global-header"); + pic_hdr->clamp_type_ = VP8Get(br, "global-header"); } if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, @@ -378,7 +381,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { "Not a key frame."); } - VP8Get(br); // ignore the value of update_proba_ + VP8Get(br, "global-header"); // ignore the value of update_proba_ VP8ParseProba(br, dec); @@ -403,28 +406,28 @@ static const uint8_t kZigzag[16] = { // See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2 static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { int v; - if (!VP8GetBit(br, p[3])) { - if (!VP8GetBit(br, p[4])) { + if (!VP8GetBit(br, p[3], "coeffs")) { + if (!VP8GetBit(br, p[4], "coeffs")) { v = 2; } else { - v = 3 + VP8GetBit(br, p[5]); + v = 3 + VP8GetBit(br, p[5], "coeffs"); } } else { - if (!VP8GetBit(br, p[6])) { - if (!VP8GetBit(br, p[7])) { - v = 5 + VP8GetBit(br, 159); + if (!VP8GetBit(br, p[6], "coeffs")) { + if (!VP8GetBit(br, p[7], "coeffs")) { + v = 5 + VP8GetBit(br, 159, "coeffs"); } else { - v = 7 + 2 * VP8GetBit(br, 165); - v += VP8GetBit(br, 145); + v = 7 + 2 * VP8GetBit(br, 165, "coeffs"); + v += VP8GetBit(br, 145, "coeffs"); } } else { const uint8_t* tab; - const int bit1 = VP8GetBit(br, p[8]); - const int bit0 = VP8GetBit(br, p[9 + bit1]); + const int bit1 = VP8GetBit(br, p[8], "coeffs"); + const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs"); const int cat = 2 * bit1 + bit0; v = 0; for (tab = kCat3456[cat]; *tab; ++tab) { - v += v + VP8GetBit(br, *tab); + v += v + VP8GetBit(br, *tab, "coeffs"); } v += 3 + (8 << cat); } @@ -438,24 +441,24 @@ static int GetCoeffsFast(VP8BitReader* const br, int ctx, const quant_t dq, int n, int16_t* out) { const uint8_t* p = prob[n]->probas_[ctx]; for (; n < 16; ++n) { - if (!VP8GetBit(br, p[0])) { + if (!VP8GetBit(br, p[0], "coeffs")) { return n; // previous coeff was last non-zero coeff } - while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs + while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs p = prob[++n]->probas_[0]; if (n == 16) return 16; } { // non zero coeff const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; int v; - if (!VP8GetBit(br, p[2])) { + if (!VP8GetBit(br, p[2], "coeffs")) { v = 1; p = p_ctx[1]; } else { v = GetLargeValue(br, p); p = p_ctx[2]; } - out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; } } return 16; @@ -468,30 +471,30 @@ static int GetCoeffsAlt(VP8BitReader* const br, int ctx, const quant_t dq, int n, int16_t* out) { const uint8_t* p = prob[n]->probas_[ctx]; for (; n < 16; ++n) { - if (!VP8GetBitAlt(br, p[0])) { + if (!VP8GetBitAlt(br, p[0], "coeffs")) { return n; // previous coeff was last non-zero coeff } - while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs + while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs p = prob[++n]->probas_[0]; if (n == 16) return 16; } { // non zero coeff const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; int v; - if (!VP8GetBitAlt(br, p[2])) { + if (!VP8GetBitAlt(br, p[2], "coeffs")) { v = 1; p = p_ctx[1]; } else { v = GetLargeValue(br, p); p = p_ctx[2]; } - out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; + out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; } } return 16; } -WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) { +static WEBP_TSAN_IGNORE_FUNCTION void InitGetCoeffs(void) { if (GetCoeffs == NULL) { if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) { GetCoeffs = GetCoeffsAlt; diff --git a/src/3rdparty/libwebp/src/dec/vp8_dec.h b/src/3rdparty/libwebp/src/dec/vp8_dec.h index b9337bb..a05405d 100644 --- a/src/3rdparty/libwebp/src/dec/vp8_dec.h +++ b/src/3rdparty/libwebp/src/dec/vp8_dec.h @@ -11,10 +11,10 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_WEBP_DECODE_VP8_H_ -#define WEBP_WEBP_DECODE_VP8_H_ +#ifndef WEBP_DEC_VP8_DEC_H_ +#define WEBP_DEC_VP8_DEC_H_ -#include "../webp/decode.h" +#include "src/webp/decode.h" #ifdef __cplusplus extern "C" { @@ -33,7 +33,7 @@ extern "C" { // /* customize io's functions (setup()/put()/teardown()) if needed. */ // // VP8Decoder* dec = VP8New(); -// bool ok = VP8Decode(dec); +// int ok = VP8Decode(dec, &io); // if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); // VP8Delete(dec); // return ok; @@ -157,24 +157,24 @@ void VP8Delete(VP8Decoder* const dec); // Miscellaneous VP8/VP8L bitstream probing functions. // Returns true if the next 3 bytes in data contain the VP8 signature. -WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); +WEBP_EXTERN int VP8CheckSignature(const uint8_t* const data, size_t data_size); // Validates the VP8 data-header and retrieves basic header information viz // width and height. Returns 0 in case of formatting error. *width/*height // can be passed NULL. -WEBP_EXTERN(int) VP8GetInfo( +WEBP_EXTERN int VP8GetInfo( const uint8_t* data, size_t data_size, // data available so far size_t chunk_size, // total data size expected in the chunk int* const width, int* const height); // Returns true if the next byte(s) in data is a VP8L signature. -WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); +WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size); // Validates the VP8L data-header and retrieves basic header information viz // width, height and alpha. Returns 0 in case of formatting error. // width/height/has_alpha can be passed NULL. -WEBP_EXTERN(int) VP8LGetInfo( +WEBP_EXTERN int VP8LGetInfo( const uint8_t* data, size_t data_size, // data available so far int* const width, int* const height, int* const has_alpha); @@ -182,4 +182,4 @@ WEBP_EXTERN(int) VP8LGetInfo( } // extern "C" #endif -#endif /* WEBP_WEBP_DECODE_VP8_H_ */ +#endif // WEBP_DEC_VP8_DEC_H_ diff --git a/src/3rdparty/libwebp/src/dec/vp8i_dec.h b/src/3rdparty/libwebp/src/dec/vp8i_dec.h index 555853e..3de8d86 100644 --- a/src/3rdparty/libwebp/src/dec/vp8i_dec.h +++ b/src/3rdparty/libwebp/src/dec/vp8i_dec.h @@ -11,16 +11,16 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_DEC_VP8I_H_ -#define WEBP_DEC_VP8I_H_ +#ifndef WEBP_DEC_VP8I_DEC_H_ +#define WEBP_DEC_VP8I_DEC_H_ #include <string.h> // for memcpy() -#include "./common_dec.h" -#include "./vp8li_dec.h" -#include "../utils/bit_reader_utils.h" -#include "../utils/random_utils.h" -#include "../utils/thread_utils.h" -#include "../dsp/dsp.h" +#include "src/dec/common_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/random_utils.h" +#include "src/utils/thread_utils.h" +#include "src/dsp/dsp.h" #ifdef __cplusplus extern "C" { @@ -30,9 +30,9 @@ extern "C" { // Various defines and enums // version numbers -#define DEC_MAJ_VERSION 0 -#define DEC_MIN_VERSION 6 -#define DEC_REV_VERSION 0 +#define DEC_MAJ_VERSION 1 +#define DEC_MIN_VERSION 0 +#define DEC_REV_VERSION 3 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), @@ -57,7 +57,6 @@ extern "C" { // '|' = left sample, '-' = top sample, '+' = top-left sample // 't' = extra top-right sample for 4x4 modes #define YUV_SIZE (BPS * 17 + BPS * 9) -#define Y_SIZE (BPS * 17) #define Y_OFF (BPS * 1 + 8) #define U_OFF (Y_OFF + BPS * 16 + BPS) #define V_OFF (U_OFF + 16) @@ -317,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, } // extern "C" #endif -#endif /* WEBP_DEC_VP8I_H_ */ +#endif // WEBP_DEC_VP8I_DEC_H_ diff --git a/src/3rdparty/libwebp/src/dec/vp8l_dec.c b/src/3rdparty/libwebp/src/dec/vp8l_dec.c index ef359a9..d3e2711 100644 --- a/src/3rdparty/libwebp/src/dec/vp8l_dec.c +++ b/src/3rdparty/libwebp/src/dec/vp8l_dec.c @@ -14,22 +14,22 @@ #include <stdlib.h> -#include "./alphai_dec.h" -#include "./vp8li_dec.h" -#include "../dsp/dsp.h" -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "../dsp/yuv.h" -#include "../utils/endian_inl_utils.h" -#include "../utils/huffman_utils.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" #define NUM_ARGB_CACHE_ROWS 16 static const int kCodeLengthLiterals = 16; static const int kCodeLengthRepeatCode = 16; -static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; -static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; +static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 }; +static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; // ----------------------------------------------------------------------------- // Five Huffman codes are used at each meta code: @@ -86,7 +86,7 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { // All values computed for 8-bit first level lookup with Mark Adler's tool: // http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c #define FIXED_TABLE_SIZE (630 * 3 + 410) -static const int kTableSize[12] = { +static const uint16_t kTableSize[12] = { FIXED_TABLE_SIZE + 654, FIXED_TABLE_SIZE + 656, FIXED_TABLE_SIZE + 658, @@ -363,11 +363,14 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, uint32_t* huffman_image = NULL; HTreeGroup* htree_groups = NULL; HuffmanCode* huffman_tables = NULL; - HuffmanCode* next = NULL; + HuffmanCode* huffman_table = NULL; int num_htree_groups = 1; + int num_htree_groups_max = 1; int max_alphabet_size = 0; int* code_lengths = NULL; const int table_size = kTableSize[color_cache_bits]; + int* mapping = NULL; + int ok = 0; if (allow_recursion && VP8LReadBits(br, 1)) { // use meta Huffman codes. @@ -384,9 +387,35 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, // The huffman data is stored in red and green bytes. const int group = (huffman_image[i] >> 8) & 0xffff; huffman_image[i] = group; - if (group >= num_htree_groups) { - num_htree_groups = group + 1; + if (group >= num_htree_groups_max) { + num_htree_groups_max = group + 1; + } + } + // Check the validity of num_htree_groups_max. If it seems too big, use a + // smaller value for later. This will prevent big memory allocations to end + // up with a bad bitstream anyway. + // The value of 1000 is totally arbitrary. We know that num_htree_groups_max + // is smaller than (1 << 16) and should be smaller than the number of pixels + // (though the format allows it to be bigger). + if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) { + // Create a mapping from the used indices to the minimal set of used + // values [0, num_htree_groups) + mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping)); + if (mapping == NULL) { + dec->status_ = VP8_STATUS_OUT_OF_MEMORY; + goto Error; + } + // -1 means a value is unmapped, and therefore unused in the Huffman + // image. + memset(mapping, 0xff, num_htree_groups_max * sizeof(*mapping)); + for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) { + // Get the current mapping for the group and remap the Huffman image. + int* const mapped_group = &mapping[huffman_image[i]]; + if (*mapped_group == -1) *mapped_group = num_htree_groups++; + huffman_image[i] = *mapped_group; } + } else { + num_htree_groups = num_htree_groups_max; } } @@ -403,88 +432,106 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, } } + code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, + sizeof(*code_lengths)); huffman_tables = (HuffmanCode*)WebPSafeMalloc(num_htree_groups * table_size, sizeof(*huffman_tables)); htree_groups = VP8LHtreeGroupsNew(num_htree_groups); - code_lengths = (int*)WebPSafeCalloc((uint64_t)max_alphabet_size, - sizeof(*code_lengths)); if (htree_groups == NULL || code_lengths == NULL || huffman_tables == NULL) { dec->status_ = VP8_STATUS_OUT_OF_MEMORY; goto Error; } - next = huffman_tables; - for (i = 0; i < num_htree_groups; ++i) { - HTreeGroup* const htree_group = &htree_groups[i]; - HuffmanCode** const htrees = htree_group->htrees; - int size; - int total_size = 0; - int is_trivial_literal = 1; - int max_bits = 0; - for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { - int alphabet_size = kAlphabetSize[j]; - htrees[j] = next; - if (j == 0 && color_cache_bits > 0) { - alphabet_size += 1 << color_cache_bits; - } - size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next); - if (size == 0) { - goto Error; - } - if (is_trivial_literal && kLiteralMap[j] == 1) { - is_trivial_literal = (next->bits == 0); + huffman_table = huffman_tables; + for (i = 0; i < num_htree_groups_max; ++i) { + // If the index "i" is unused in the Huffman image, just make sure the + // coefficients are valid but do not store them. + if (mapping != NULL && mapping[i] == -1) { + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + // Passing in NULL so that nothing gets filled. + if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) { + goto Error; + } } - total_size += next->bits; - next += size; - if (j <= ALPHA) { - int local_max_bits = code_lengths[0]; - int k; - for (k = 1; k < alphabet_size; ++k) { - if (code_lengths[k] > local_max_bits) { - local_max_bits = code_lengths[k]; + } else { + HTreeGroup* const htree_group = + &htree_groups[(mapping == NULL) ? i : mapping[i]]; + HuffmanCode** const htrees = htree_group->htrees; + int size; + int total_size = 0; + int is_trivial_literal = 1; + int max_bits = 0; + for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) { + int alphabet_size = kAlphabetSize[j]; + htrees[j] = huffman_table; + if (j == 0 && color_cache_bits > 0) { + alphabet_size += (1 << color_cache_bits); + } + size = ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_table); + if (size == 0) { + goto Error; + } + if (is_trivial_literal && kLiteralMap[j] == 1) { + is_trivial_literal = (huffman_table->bits == 0); + } + total_size += huffman_table->bits; + huffman_table += size; + if (j <= ALPHA) { + int local_max_bits = code_lengths[0]; + int k; + for (k = 1; k < alphabet_size; ++k) { + if (code_lengths[k] > local_max_bits) { + local_max_bits = code_lengths[k]; + } } + max_bits += local_max_bits; } - max_bits += local_max_bits; } - } - htree_group->is_trivial_literal = is_trivial_literal; - htree_group->is_trivial_code = 0; - if (is_trivial_literal) { - const int red = htrees[RED][0].value; - const int blue = htrees[BLUE][0].value; - const int alpha = htrees[ALPHA][0].value; - htree_group->literal_arb = - ((uint32_t)alpha << 24) | (red << 16) | blue; - if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { - htree_group->is_trivial_code = 1; - htree_group->literal_arb |= htrees[GREEN][0].value << 8; + htree_group->is_trivial_literal = is_trivial_literal; + htree_group->is_trivial_code = 0; + if (is_trivial_literal) { + const int red = htrees[RED][0].value; + const int blue = htrees[BLUE][0].value; + const int alpha = htrees[ALPHA][0].value; + htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; + if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { + htree_group->is_trivial_code = 1; + htree_group->literal_arb |= htrees[GREEN][0].value << 8; + } } + htree_group->use_packed_table = + !htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS); + if (htree_group->use_packed_table) BuildPackedTable(htree_group); } - htree_group->use_packed_table = !htree_group->is_trivial_code && - (max_bits < HUFFMAN_PACKED_BITS); - if (htree_group->use_packed_table) BuildPackedTable(htree_group); } - WebPSafeFree(code_lengths); + ok = 1; - // All OK. Finalize pointers and return. + // All OK. Finalize pointers. hdr->huffman_image_ = huffman_image; hdr->num_htree_groups_ = num_htree_groups; hdr->htree_groups_ = htree_groups; hdr->huffman_tables_ = huffman_tables; - return 1; Error: WebPSafeFree(code_lengths); - WebPSafeFree(huffman_image); - WebPSafeFree(huffman_tables); - VP8LHtreeGroupsFree(htree_groups); - return 0; + WebPSafeFree(mapping); + if (!ok) { + WebPSafeFree(huffman_image); + WebPSafeFree(huffman_tables); + VP8LHtreeGroupsFree(htree_groups); + } + return ok; } //------------------------------------------------------------------------------ // Scaling. +#if !defined(WEBP_REDUCE_SIZE) static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { const int num_channels = 4; const int in_width = io->mb_w; @@ -516,10 +563,13 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { out_width, out_height, 0, num_channels, work); return 1; } +#endif // WEBP_REDUCE_SIZE //------------------------------------------------------------------------------ // Export to ARGB +#if !defined(WEBP_REDUCE_SIZE) + // We have special "export" function since we need to convert from BGRA static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, int rgba_stride, uint8_t* const rgba) { @@ -561,6 +611,8 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, return num_lines_out; } +#endif // WEBP_REDUCE_SIZE + // Emit rows without any scaling. static int EmitRows(WEBP_CSP_MODE colorspace, const uint8_t* row_in, int in_stride, @@ -746,9 +798,12 @@ static void ProcessRows(VP8LDecoder* const dec, int row) { if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA const WebPRGBABuffer* const buf = &output->u.RGBA; uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; - const int num_rows_out = io->use_scaling ? + const int num_rows_out = +#if !defined(WEBP_REDUCE_SIZE) + io->use_scaling ? EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, rgba, buf->stride) : +#endif // WEBP_REDUCE_SIZE EmitRows(output->colorspace, rows_data, in_stride, io->mb_w, io->mb_h, rgba, buf->stride); // Update 'last_out_row_'. @@ -875,7 +930,11 @@ static WEBP_INLINE void CopyBlock8b(uint8_t* const dst, int dist, int length) { #endif break; case 2: +#if !defined(WORDS_BIGENDIAN) memcpy(&pattern, src, sizeof(uint16_t)); +#else + pattern = ((uint32_t)src[0] << 8) | src[1]; +#endif #if defined(__arm__) || defined(_M_ARM) pattern |= pattern << 16; #elif defined(WEBP_USE_MIPS_DSP_R2) @@ -1012,12 +1071,13 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, ok = 0; goto End; } - assert(br->eos_ == VP8LIsEndOfStream(br)); + br->eos_ = VP8LIsEndOfStream(br); } // Process the remaining rows corresponding to last row-block. ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); End: + br->eos_ = VP8LIsEndOfStream(br); if (!ok || (br->eos_ && pos < end)) { ok = 0; dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED @@ -1090,11 +1150,12 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); if (htree_group->use_packed_table) { code = ReadPackedSymbols(htree_group, br, src); + if (VP8LIsEndOfStream(br)) break; if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; } else { code = ReadSymbol(htree_group->htrees[GREEN], br); } - if (br->eos_) break; // early out + if (VP8LIsEndOfStream(br)) break; if (code < NUM_LITERAL_CODES) { // Literal if (htree_group->is_trivial_literal) { *src = htree_group->literal_arb | (code << 8); @@ -1104,7 +1165,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); blue = ReadSymbol(htree_group->htrees[BLUE], br); alpha = ReadSymbol(htree_group->htrees[ALPHA], br); - if (br->eos_) break; + if (VP8LIsEndOfStream(br)) break; *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; } AdvanceByOne: @@ -1132,7 +1193,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); dist_code = GetCopyDistance(dist_symbol, br); dist = PlaneCodeToDistance(width, dist_code); - if (br->eos_) break; + if (VP8LIsEndOfStream(br)) break; if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { goto Error; } else { @@ -1169,9 +1230,9 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, } else { // Not reached goto Error; } - assert(br->eos_ == VP8LIsEndOfStream(br)); } + br->eos_ = VP8LIsEndOfStream(br); if (dec->incremental_ && br->eos_ && src < src_end) { RestoreState(dec); } else if (!br->eos_) { @@ -1512,7 +1573,6 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, if (dec == NULL) return 0; assert(alph_dec != NULL); - alph_dec->vp8l_dec_ = dec; dec->width_ = alph_dec->width_; dec->height_ = alph_dec->height_; @@ -1544,11 +1604,12 @@ int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, if (!ok) goto Err; + // Only set here, once we are sure it is valid (to avoid thread races). + alph_dec->vp8l_dec_ = dec; return 1; Err: - VP8LDelete(alph_dec->vp8l_dec_); - alph_dec->vp8l_dec_ = NULL; + VP8LDelete(dec); return 0; } @@ -1630,12 +1691,19 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; +#if !defined(WEBP_REDUCE_SIZE) if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; - +#else + if (io->use_scaling) { + dec->status_ = VP8_STATUS_INVALID_PARAM; + goto Err; + } +#endif if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { // need the alpha-multiply functions for premultiplied output or rescaling WebPInitAlphaProcessing(); } + if (!WebPIsRGBMode(dec->output_->colorspace)) { WebPInitConvertARGBToYUV(); if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); diff --git a/src/3rdparty/libwebp/src/dec/vp8li_dec.h b/src/3rdparty/libwebp/src/dec/vp8li_dec.h index 097a9d0..0a4d613 100644 --- a/src/3rdparty/libwebp/src/dec/vp8li_dec.h +++ b/src/3rdparty/libwebp/src/dec/vp8li_dec.h @@ -12,14 +12,14 @@ // Author: Skal (pascal.massimino@gmail.com) // Vikas Arora(vikaas.arora@gmail.com) -#ifndef WEBP_DEC_VP8LI_H_ -#define WEBP_DEC_VP8LI_H_ +#ifndef WEBP_DEC_VP8LI_DEC_H_ +#define WEBP_DEC_VP8LI_DEC_H_ #include <string.h> // for memcpy() -#include "./webpi_dec.h" -#include "../utils/bit_reader_utils.h" -#include "../utils/color_cache_utils.h" -#include "../utils/huffman_utils.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/huffman_utils.h" #ifdef __cplusplus extern "C" { @@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_VP8LI_H_ */ +#endif // WEBP_DEC_VP8LI_DEC_H_ diff --git a/src/3rdparty/libwebp/src/dec/webp_dec.c b/src/3rdparty/libwebp/src/dec/webp_dec.c index a8e9c2c..42d0988 100644 --- a/src/3rdparty/libwebp/src/dec/webp_dec.c +++ b/src/3rdparty/libwebp/src/dec/webp_dec.c @@ -13,11 +13,11 @@ #include <stdlib.h> -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "./webpi_dec.h" -#include "../utils/utils.h" -#include "../webp/mux_types.h" // ALPHA_FLAG +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" +#include "src/webp/mux_types.h" // ALPHA_FLAG //------------------------------------------------------------------------------ // RIFF layout is: @@ -421,7 +421,9 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { NULL, NULL, NULL, &has_animation, NULL, headers); if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { - // TODO(jzern): full support of animation frames will require API additions. + // The WebPDemux API + libwebp can be used to decode individual + // uncomposited frames or the WebPAnimDecoder can be used to fully + // reconstruct them (see webp/demux.h). if (has_animation) { status = VP8_STATUS_UNSUPPORTED_FEATURE; } diff --git a/src/3rdparty/libwebp/src/dec/webpi_dec.h b/src/3rdparty/libwebp/src/dec/webpi_dec.h index 696abc1..24baff5 100644 --- a/src/3rdparty/libwebp/src/dec/webpi_dec.h +++ b/src/3rdparty/libwebp/src/dec/webpi_dec.h @@ -11,15 +11,15 @@ // // Author: somnath@google.com (Somnath Banerjee) -#ifndef WEBP_DEC_WEBPI_H_ -#define WEBP_DEC_WEBPI_H_ +#ifndef WEBP_DEC_WEBPI_DEC_H_ +#define WEBP_DEC_WEBPI_DEC_H_ #ifdef __cplusplus extern "C" { #endif -#include "../utils/rescaler_utils.h" -#include "./vp8_dec.h" +#include "src/utils/rescaler_utils.h" +#include "src/dec/vp8_dec.h" //------------------------------------------------------------------------------ // WebPDecParams: Decoding output parameters. Transient internal object. @@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output, } // extern "C" #endif -#endif /* WEBP_DEC_WEBPI_H_ */ +#endif // WEBP_DEC_WEBPI_DEC_H_ |