summaryrefslogtreecommitdiff
path: root/drivers/webpold/dec
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/webpold/dec')
-rw-r--r--drivers/webpold/dec/alpha.c140
-rw-r--r--drivers/webpold/dec/buffer.c215
-rw-r--r--drivers/webpold/dec/decode_vp8.h182
-rw-r--r--drivers/webpold/dec/frame.c679
-rw-r--r--drivers/webpold/dec/idec.c785
-rw-r--r--drivers/webpold/dec/io.c633
-rw-r--r--drivers/webpold/dec/layer.c35
-rw-r--r--drivers/webpold/dec/quant.c113
-rw-r--r--drivers/webpold/dec/tree.c589
-rw-r--r--drivers/webpold/dec/vp8.c787
-rw-r--r--drivers/webpold/dec/vp8i.h335
-rw-r--r--drivers/webpold/dec/vp8l.c1200
-rw-r--r--drivers/webpold/dec/vp8li.h121
-rw-r--r--drivers/webpold/dec/webp.c771
-rw-r--r--drivers/webpold/dec/webpi.h114
15 files changed, 0 insertions, 6699 deletions
diff --git a/drivers/webpold/dec/alpha.c b/drivers/webpold/dec/alpha.c
deleted file mode 100644
index d1095fa555..0000000000
--- a/drivers/webpold/dec/alpha.c
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2011 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/
-// -----------------------------------------------------------------------------
-//
-// Alpha-plane decompression.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "../utils/filters.h"
-#include "../utils/quant_levels.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-// TODO(skal): move to dsp/ ?
-static void CopyPlane(const uint8_t* src, int src_stride,
- uint8_t* dst, int dst_stride, int width, int height) {
- while (height-- > 0) {
- memcpy(dst, src, width);
- src += src_stride;
- dst += dst_stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// Decodes the compressed data 'data' of size 'data_size' into the 'output'.
-// The 'output' buffer should be pre-allocated and must be of the same
-// dimension 'height'x'stride', as that of the image.
-//
-// Returns 1 on successfully decoding the compressed alpha and
-// 0 if either:
-// error in bit-stream header (invalid compression mode or filter), or
-// error returned by appropriate compression method.
-
-static int DecodeAlpha(const uint8_t* data, size_t data_size,
- int width, int height, int stride, uint8_t* output) {
- uint8_t* decoded_data = NULL;
- const size_t decoded_size = height * width;
- uint8_t* unfiltered_data = NULL;
- WEBP_FILTER_TYPE filter;
- int pre_processing;
- int rsrv;
- int ok = 0;
- int method;
-
- assert(width > 0 && height > 0 && stride >= width);
- assert(data != NULL && output != NULL);
-
- if (data_size <= ALPHA_HEADER_LEN) {
- return 0;
- }
-
- method = (data[0] >> 0) & 0x03;
- filter = (data[0] >> 2) & 0x03;
- pre_processing = (data[0] >> 4) & 0x03;
- rsrv = (data[0] >> 6) & 0x03;
- if (method < ALPHA_NO_COMPRESSION ||
- method > ALPHA_LOSSLESS_COMPRESSION ||
- filter >= WEBP_FILTER_LAST ||
- pre_processing > ALPHA_PREPROCESSED_LEVELS ||
- rsrv != 0) {
- return 0;
- }
-
- if (method == ALPHA_NO_COMPRESSION) {
- ok = (data_size >= decoded_size);
- decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN;
- } else {
- decoded_data = (uint8_t*)malloc(decoded_size);
- if (decoded_data == NULL) return 0;
- ok = VP8LDecodeAlphaImageStream(width, height,
- data + ALPHA_HEADER_LEN,
- data_size - ALPHA_HEADER_LEN,
- decoded_data);
- }
-
- if (ok) {
- WebPFilterFunc unfilter_func = WebPUnfilters[filter];
- if (unfilter_func != NULL) {
- unfiltered_data = (uint8_t*)malloc(decoded_size);
- if (unfiltered_data == NULL) {
- ok = 0;
- goto Error;
- }
- // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode
- // and apply filter per image-row.
- unfilter_func(decoded_data, width, height, 1, width, unfiltered_data);
- // Construct raw_data (height x stride) from alpha data (height x width).
- CopyPlane(unfiltered_data, width, output, stride, width, height);
- free(unfiltered_data);
- } else {
- // Construct raw_data (height x stride) from alpha data (height x width).
- CopyPlane(decoded_data, width, output, stride, width, height);
- }
- if (pre_processing == ALPHA_PREPROCESSED_LEVELS) {
- ok = DequantizeLevels(decoded_data, width, height);
- }
- }
-
- Error:
- if (method != ALPHA_NO_COMPRESSION) {
- free(decoded_data);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-
-const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
- int row, int num_rows) {
- const int stride = dec->pic_hdr_.width_;
-
- if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) {
- return NULL; // sanity check.
- }
-
- if (row == 0) {
- // Decode everything during the first call.
- if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_,
- dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride,
- dec->alpha_plane_)) {
- return NULL; // Error.
- }
- }
-
- // Return a pointer to the current decoded row.
- return dec->alpha_plane_ + row * stride;
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/buffer.c b/drivers/webpold/dec/buffer.c
deleted file mode 100644
index c159f6f248..0000000000
--- a/drivers/webpold/dec/buffer.c
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2011 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/
-// -----------------------------------------------------------------------------
-//
-// Everything about WebPDecBuffer
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./webpi.h"
-#include "../utils/utils.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// WebPDecBuffer
-
-// Number of bytes per pixel for the different color-spaces.
-static const int kModeBpp[MODE_LAST] = {
- 3, 4, 3, 4, 4, 2, 2,
- 4, 4, 4, 2, // pre-multiplied modes
- 1, 1 };
-
-// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
-// Convert to an integer to handle both the unsigned/signed enum cases
-// without the need for casting to remove type limit warnings.
-static int IsValidColorspace(int webp_csp_mode) {
- return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
-}
-
-static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
- int ok = 1;
- const WEBP_CSP_MODE mode = buffer->colorspace;
- const int width = buffer->width;
- const int height = buffer->height;
- if (!IsValidColorspace(mode)) {
- ok = 0;
- } else if (!WebPIsRGBMode(mode)) { // YUV checks
- const WebPYUVABuffer* const buf = &buffer->u.YUVA;
- const uint64_t y_size = (uint64_t)buf->y_stride * height;
- const uint64_t u_size = (uint64_t)buf->u_stride * ((height + 1) / 2);
- const uint64_t v_size = (uint64_t)buf->v_stride * ((height + 1) / 2);
- const uint64_t a_size = (uint64_t)buf->a_stride * height;
- ok &= (y_size <= buf->y_size);
- ok &= (u_size <= buf->u_size);
- ok &= (v_size <= buf->v_size);
- ok &= (buf->y_stride >= width);
- ok &= (buf->u_stride >= (width + 1) / 2);
- ok &= (buf->v_stride >= (width + 1) / 2);
- ok &= (buf->y != NULL);
- ok &= (buf->u != NULL);
- ok &= (buf->v != NULL);
- if (mode == MODE_YUVA) {
- ok &= (buf->a_stride >= width);
- ok &= (a_size <= buf->a_size);
- ok &= (buf->a != NULL);
- }
- } else { // RGB checks
- const WebPRGBABuffer* const buf = &buffer->u.RGBA;
- const uint64_t size = (uint64_t)buf->stride * height;
- ok &= (size <= buf->size);
- ok &= (buf->stride >= width * kModeBpp[mode]);
- ok &= (buf->rgba != NULL);
- }
- return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
-}
-
-static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
- const int w = buffer->width;
- const int h = buffer->height;
- const WEBP_CSP_MODE mode = buffer->colorspace;
-
- if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) {
- return VP8_STATUS_INVALID_PARAM;
- }
-
- if (!buffer->is_external_memory && buffer->private_memory == NULL) {
- uint8_t* output;
- int uv_stride = 0, a_stride = 0;
- 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;
-
- if (!WebPIsRGBMode(mode)) {
- uv_stride = (w + 1) / 2;
- uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
- if (mode == MODE_YUVA) {
- a_stride = w;
- a_size = (uint64_t)a_stride * h;
- }
- }
- total_size = size + 2 * uv_size + a_size;
-
- // Security/sanity checks
- output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
- if (output == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- buffer->private_memory = output;
-
- if (!WebPIsRGBMode(mode)) { // YUVA initialization
- WebPYUVABuffer* const buf = &buffer->u.YUVA;
- buf->y = output;
- buf->y_stride = stride;
- buf->y_size = (size_t)size;
- buf->u = output + size;
- buf->u_stride = uv_stride;
- buf->u_size = (size_t)uv_size;
- buf->v = output + size + uv_size;
- buf->v_stride = uv_stride;
- buf->v_size = (size_t)uv_size;
- if (mode == MODE_YUVA) {
- buf->a = output + size + 2 * uv_size;
- }
- buf->a_size = (size_t)a_size;
- buf->a_stride = a_stride;
- } else { // RGBA initialization
- WebPRGBABuffer* const buf = &buffer->u.RGBA;
- buf->rgba = output;
- buf->stride = stride;
- buf->size = (size_t)size;
- }
- }
- return CheckDecBuffer(buffer);
-}
-
-VP8StatusCode WebPAllocateDecBuffer(int w, int h,
- const WebPDecoderOptions* const options,
- WebPDecBuffer* const out) {
- if (out == NULL || w <= 0 || h <= 0) {
- return VP8_STATUS_INVALID_PARAM;
- }
- if (options != NULL) { // First, apply options if there is any.
- if (options->use_cropping) {
- const int cw = options->crop_width;
- 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) {
- return VP8_STATUS_INVALID_PARAM; // out of frame boundary.
- }
- w = cw;
- h = ch;
- }
- if (options->use_scaling) {
- if (options->scaled_width <= 0 || options->scaled_height <= 0) {
- return VP8_STATUS_INVALID_PARAM;
- }
- w = options->scaled_width;
- h = options->scaled_height;
- }
- }
- out->width = w;
- out->height = h;
-
- // Then, allocate buffer for real
- return AllocateBuffer(out);
-}
-
-//------------------------------------------------------------------------------
-// constructors / destructors
-
-int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // version mismatch
- }
- if (buffer == NULL) return 0;
- memset(buffer, 0, sizeof(*buffer));
- return 1;
-}
-
-void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
- if (buffer != NULL) {
- if (!buffer->is_external_memory)
- free(buffer->private_memory);
- buffer->private_memory = NULL;
- }
-}
-
-void WebPCopyDecBuffer(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst) {
- if (src != NULL && dst != NULL) {
- *dst = *src;
- if (src->private_memory != NULL) {
- dst->is_external_memory = 1; // dst buffer doesn't own the memory.
- dst->private_memory = NULL;
- }
- }
-}
-
-// Copy and transfer ownership from src to dst (beware of parameter order!)
-void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
- if (src != NULL && dst != NULL) {
- *dst = *src;
- if (src->private_memory != NULL) {
- src->is_external_memory = 1; // src relinquishes ownership
- src->private_memory = NULL;
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/decode_vp8.h b/drivers/webpold/dec/decode_vp8.h
deleted file mode 100644
index c26a9fc891..0000000000
--- a/drivers/webpold/dec/decode_vp8.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// Low-level API for VP8 decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_WEBP_DECODE_VP8_H_
-#define WEBP_WEBP_DECODE_VP8_H_
-
-#include "../decode.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Lower-level API
-//
-// These functions provide fine-grained control of the decoding process.
-// The call flow should resemble:
-//
-// VP8Io io;
-// VP8InitIo(&io);
-// io.data = data;
-// io.data_size = size;
-// /* customize io's functions (setup()/put()/teardown()) if needed. */
-//
-// VP8Decoder* dec = VP8New();
-// bool ok = VP8Decode(dec);
-// if (!ok) printf("Error: %s\n", VP8StatusMessage(dec));
-// VP8Delete(dec);
-// return ok;
-
-// Input / Output
-typedef struct VP8Io VP8Io;
-typedef int (*VP8IoPutHook)(const VP8Io* io);
-typedef int (*VP8IoSetupHook)(VP8Io* io);
-typedef void (*VP8IoTeardownHook)(const VP8Io* io);
-
-struct VP8Io {
- // set by VP8GetHeaders()
- int width, height; // picture dimensions, in pixels (invariable).
- // These are the original, uncropped dimensions.
- // The actual area passed to put() is stored
- // in mb_w / mb_h fields.
-
- // set before calling put()
- int mb_y; // position of the current rows (in pixels)
- int mb_w; // number of columns in the sample
- int mb_h; // number of rows in the sample
- const uint8_t* y, *u, *v; // rows to copy (in yuv420 format)
- int y_stride; // row stride for luma
- int uv_stride; // row stride for chroma
-
- void* opaque; // user data
-
- // called when fresh samples are available. Currently, samples are in
- // YUV420 format, and can be up to width x 24 in size (depending on the
- // in-loop filtering level, e.g.). Should return false in case of error
- // or abort request. The actual size of the area to update is mb_w x mb_h
- // in size, taking cropping into account.
- VP8IoPutHook put;
-
- // called just before starting to decode the blocks.
- // Must return false in case of setup error, true otherwise. If false is
- // returned, teardown() will NOT be called. But if the setup succeeded
- // and true is returned, then teardown() will always be called afterward.
- VP8IoSetupHook setup;
-
- // Called just after block decoding is finished (or when an error occurred
- // during put()). Is NOT called if setup() failed.
- VP8IoTeardownHook teardown;
-
- // this is a recommendation for the user-side yuv->rgb converter. This flag
- // is set when calling setup() hook and can be overwritten by it. It then
- // can be taken into consideration during the put() method.
- int fancy_upsampling;
-
- // Input buffer.
- size_t data_size;
- const uint8_t* data;
-
- // If true, in-loop filtering will not be performed even if present in the
- // bitstream. Switching off filtering may speed up decoding at the expense
- // of more visible blocking. Note that output will also be non-compliant
- // with the VP8 specifications.
- int bypass_filtering;
-
- // Cropping parameters.
- int use_cropping;
- int crop_left, crop_right, crop_top, crop_bottom;
-
- // Scaling parameters.
- int use_scaling;
- int scaled_width, scaled_height;
-
- // If non NULL, pointer to the alpha data (if present) corresponding to the
- // start of the current row (That is: it is pre-offset by mb_y and takes
- // cropping into account).
- const uint8_t* a;
-};
-
-// Internal, version-checked, entry point
-int VP8InitIoInternal(VP8Io* const, int);
-
-// Set the custom IO function pointers and user-data. The setter for IO hooks
-// should be called before initiating incremental decoding. Returns true if
-// WebPIDecoder object is successfully modified, false otherwise.
-int WebPISetIOHooks(WebPIDecoder* const idec,
- VP8IoPutHook put,
- VP8IoSetupHook setup,
- VP8IoTeardownHook teardown,
- void* user_data);
-
-// Main decoding object. This is an opaque structure.
-typedef struct VP8Decoder VP8Decoder;
-
-// Create a new decoder object.
-VP8Decoder* VP8New(void);
-
-// Must be called to make sure 'io' is initialized properly.
-// Returns false in case of version mismatch. Upon such failure, no other
-// decoding function should be called (VP8Decode, VP8GetHeaders, ...)
-static WEBP_INLINE int VP8InitIo(VP8Io* const io) {
- return VP8InitIoInternal(io, WEBP_DECODER_ABI_VERSION);
-}
-
-// Start decoding a new picture. Returns true if ok.
-int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io);
-
-// Decode a picture. Will call VP8GetHeaders() if it wasn't done already.
-// Returns false in case of error.
-int VP8Decode(VP8Decoder* const dec, VP8Io* const io);
-
-// Return current status of the decoder:
-VP8StatusCode VP8Status(VP8Decoder* const dec);
-
-// return readable string corresponding to the last status.
-const char* VP8StatusMessage(VP8Decoder* const dec);
-
-// Resets the decoder in its initial state, reclaiming memory.
-// Not a mandatory call between calls to VP8Decode().
-void VP8Clear(VP8Decoder* const dec);
-
-// Destroy the decoder object.
-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);
-
-// 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(
- 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);
-
-// 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(
- const uint8_t* data, size_t data_size, // data available so far
- int* const width, int* const height, int* const has_alpha);
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
-
-#endif /* WEBP_WEBP_DECODE_VP8_H_ */
diff --git a/drivers/webpold/dec/frame.c b/drivers/webpold/dec/frame.c
deleted file mode 100644
index 9c91a48e17..0000000000
--- a/drivers/webpold/dec/frame.c
+++ /dev/null
@@ -1,679 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// Frame-reconstruction function. Memory allocation.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#define ALIGN_MASK (32 - 1)
-
-//------------------------------------------------------------------------------
-// Filtering
-
-// kFilterExtraRows[] = How many extra lines are needed on the MB boundary
-// for caching, given a filtering level.
-// Simple filter: up to 2 luma samples are read and 1 is written.
-// Complex filter: up to 4 luma samples are read and 3 are written. Same for
-// U/V, so it's 8 samples total (because of the 2x upsampling).
-static const uint8_t kFilterExtraRows[3] = { 0, 2, 8 };
-
-static WEBP_INLINE int hev_thresh_from_level(int level, int keyframe) {
- if (keyframe) {
- return (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- } else {
- return (level >= 40) ? 3 : (level >= 20) ? 2 : (level >= 15) ? 1 : 0;
- }
-}
-
-static void DoFilter(const VP8Decoder* const dec, int mb_x, int mb_y) {
- const VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const int y_bps = dec->cache_y_stride_;
- VP8FInfo* const f_info = ctx->f_info_ + mb_x;
- uint8_t* const y_dst = dec->cache_y_ + ctx->id_ * 16 * y_bps + mb_x * 16;
- const int level = f_info->f_level_;
- const int ilevel = f_info->f_ilevel_;
- const int limit = 2 * level + ilevel;
- if (level == 0) {
- return;
- }
- if (dec->filter_type_ == 1) { // simple
- if (mb_x > 0) {
- VP8SimpleHFilter16(y_dst, y_bps, limit + 4);
- }
- if (f_info->f_inner_) {
- VP8SimpleHFilter16i(y_dst, y_bps, limit);
- }
- if (mb_y > 0) {
- VP8SimpleVFilter16(y_dst, y_bps, limit + 4);
- }
- if (f_info->f_inner_) {
- VP8SimpleVFilter16i(y_dst, y_bps, limit);
- }
- } else { // complex
- const int uv_bps = dec->cache_uv_stride_;
- uint8_t* const u_dst = dec->cache_u_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
- uint8_t* const v_dst = dec->cache_v_ + ctx->id_ * 8 * uv_bps + mb_x * 8;
- const int hev_thresh =
- hev_thresh_from_level(level, dec->frm_hdr_.key_frame_);
- if (mb_x > 0) {
- VP8HFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
- VP8HFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
- }
- if (f_info->f_inner_) {
- VP8HFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
- VP8HFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
- }
- if (mb_y > 0) {
- VP8VFilter16(y_dst, y_bps, limit + 4, ilevel, hev_thresh);
- VP8VFilter8(u_dst, v_dst, uv_bps, limit + 4, ilevel, hev_thresh);
- }
- if (f_info->f_inner_) {
- VP8VFilter16i(y_dst, y_bps, limit, ilevel, hev_thresh);
- VP8VFilter8i(u_dst, v_dst, uv_bps, limit, ilevel, hev_thresh);
- }
- }
-}
-
-// Filter the decoded macroblock row (if needed)
-static void FilterRow(const VP8Decoder* const dec) {
- int mb_x;
- const int mb_y = dec->thread_ctx_.mb_y_;
- assert(dec->thread_ctx_.filter_row_);
- for (mb_x = dec->tl_mb_x_; mb_x < dec->br_mb_x_; ++mb_x) {
- DoFilter(dec, mb_x, mb_y);
- }
-}
-
-//------------------------------------------------------------------------------
-
-void VP8StoreBlock(VP8Decoder* const dec) {
- if (dec->filter_type_ > 0) {
- VP8FInfo* const info = dec->f_info_ + dec->mb_x_;
- const int skip = dec->mb_info_[dec->mb_x_].skip_;
- int level = dec->filter_levels_[dec->segment_];
- if (dec->filter_hdr_.use_lf_delta_) {
- // TODO(skal): only CURRENT is handled for now.
- level += dec->filter_hdr_.ref_lf_delta_[0];
- if (dec->is_i4x4_) {
- level += dec->filter_hdr_.mode_lf_delta_[0];
- }
- }
- level = (level < 0) ? 0 : (level > 63) ? 63 : level;
- info->f_level_ = level;
-
- if (dec->filter_hdr_.sharpness_ > 0) {
- if (dec->filter_hdr_.sharpness_ > 4) {
- level >>= 2;
- } else {
- level >>= 1;
- }
- if (level > 9 - dec->filter_hdr_.sharpness_) {
- level = 9 - dec->filter_hdr_.sharpness_;
- }
- }
-
- info->f_ilevel_ = (level < 1) ? 1 : level;
- info->f_inner_ = (!skip || dec->is_i4x4_);
- }
- {
- // Transfer samples to row cache
- int y;
- const int y_offset = dec->cache_id_ * 16 * dec->cache_y_stride_;
- const int uv_offset = dec->cache_id_ * 8 * dec->cache_uv_stride_;
- uint8_t* const ydst = dec->cache_y_ + dec->mb_x_ * 16 + y_offset;
- uint8_t* const udst = dec->cache_u_ + dec->mb_x_ * 8 + uv_offset;
- uint8_t* const vdst = dec->cache_v_ + dec->mb_x_ * 8 + uv_offset;
- for (y = 0; y < 16; ++y) {
- memcpy(ydst + y * dec->cache_y_stride_,
- dec->yuv_b_ + Y_OFF + y * BPS, 16);
- }
- for (y = 0; y < 8; ++y) {
- memcpy(udst + y * dec->cache_uv_stride_,
- dec->yuv_b_ + U_OFF + y * BPS, 8);
- memcpy(vdst + y * dec->cache_uv_stride_,
- dec->yuv_b_ + V_OFF + y * BPS, 8);
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// This function is called after a row of macroblocks is finished decoding.
-// It also takes into account the following restrictions:
-// * In case of in-loop filtering, we must hold off sending some of the bottom
-// pixels as they are yet unfiltered. They will be when the next macroblock
-// row is decoded. Meanwhile, we must preserve them by rotating them in the
-// cache area. This doesn't hold for the very bottom row of the uncropped
-// picture of course.
-// * we must clip the remaining pixels against the cropping area. The VP8Io
-// struct must have the following fields set correctly before calling put():
-
-#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) {
- int ok = 1;
- const VP8ThreadContext* const ctx = &dec->thread_ctx_;
- const int extra_y_rows = kFilterExtraRows[dec->filter_type_];
- const int ysize = extra_y_rows * dec->cache_y_stride_;
- const int uvsize = (extra_y_rows / 2) * dec->cache_uv_stride_;
- const int y_offset = ctx->id_ * 16 * dec->cache_y_stride_;
- const int uv_offset = ctx->id_ * 8 * dec->cache_uv_stride_;
- uint8_t* const ydst = dec->cache_y_ - ysize + y_offset;
- uint8_t* const udst = dec->cache_u_ - uvsize + uv_offset;
- uint8_t* const vdst = dec->cache_v_ - uvsize + uv_offset;
- const int first_row = (ctx->mb_y_ == 0);
- const int last_row = (ctx->mb_y_ >= dec->br_mb_y_ - 1);
- int y_start = MACROBLOCK_VPOS(ctx->mb_y_);
- int y_end = MACROBLOCK_VPOS(ctx->mb_y_ + 1);
-
- if (ctx->filter_row_) {
- FilterRow(dec);
- }
-
- if (io->put) {
- if (!first_row) {
- y_start -= extra_y_rows;
- io->y = ydst;
- io->u = udst;
- io->v = vdst;
- } else {
- io->y = dec->cache_y_ + y_offset;
- io->u = dec->cache_u_ + uv_offset;
- io->v = dec->cache_v_ + uv_offset;
- }
-
- if (!last_row) {
- y_end -= extra_y_rows;
- }
- if (y_end > io->crop_bottom) {
- y_end = io->crop_bottom; // make sure we don't overflow on last row.
- }
- io->a = NULL;
- if (dec->alpha_data_ != NULL && y_start < y_end) {
- // TODO(skal): several things to correct here:
- // * testing presence of alpha with dec->alpha_data_ is not a good idea
- // * we're actually decompressing the full plane only once. It should be
- // more obvious from signature.
- // * we could free alpha_data_ right after this call, but we don't own.
- io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start);
- if (io->a == NULL) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Could not decode alpha data.");
- }
- }
- if (y_start < io->crop_top) {
- const int delta_y = io->crop_top - y_start;
- y_start = io->crop_top;
- assert(!(delta_y & 1));
- io->y += dec->cache_y_stride_ * delta_y;
- io->u += dec->cache_uv_stride_ * (delta_y >> 1);
- io->v += dec->cache_uv_stride_ * (delta_y >> 1);
- if (io->a != NULL) {
- io->a += io->width * delta_y;
- }
- }
- if (y_start < y_end) {
- io->y += io->crop_left;
- io->u += io->crop_left >> 1;
- io->v += io->crop_left >> 1;
- if (io->a != NULL) {
- io->a += io->crop_left;
- }
- io->mb_y = y_start - io->crop_top;
- io->mb_w = io->crop_right - io->crop_left;
- io->mb_h = y_end - y_start;
- ok = io->put(io);
- }
- }
- // rotate top samples if needed
- if (ctx->id_ + 1 == dec->num_caches_) {
- if (!last_row) {
- memcpy(dec->cache_y_ - ysize, ydst + 16 * dec->cache_y_stride_, ysize);
- memcpy(dec->cache_u_ - uvsize, udst + 8 * dec->cache_uv_stride_, uvsize);
- memcpy(dec->cache_v_ - uvsize, vdst + 8 * dec->cache_uv_stride_, uvsize);
- }
- }
-
- return ok;
-}
-
-#undef MACROBLOCK_VPOS
-
-//------------------------------------------------------------------------------
-
-int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- VP8ThreadContext* const ctx = &dec->thread_ctx_;
- if (!dec->use_threads_) {
- // ctx->id_ and ctx->f_info_ are already set
- ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = dec->filter_row_;
- ok = FinishRow(dec, io);
- } else {
- WebPWorker* const worker = &dec->worker_;
- // Finish previous job *before* updating context
- ok &= WebPWorkerSync(worker);
- assert(worker->status_ == OK);
- if (ok) { // spawn a new deblocking/output job
- ctx->io_ = *io;
- ctx->id_ = dec->cache_id_;
- ctx->mb_y_ = dec->mb_y_;
- ctx->filter_row_ = dec->filter_row_;
- if (ctx->filter_row_) { // just swap filter info
- VP8FInfo* const tmp = ctx->f_info_;
- ctx->f_info_ = dec->f_info_;
- dec->f_info_ = tmp;
- }
- WebPWorkerLaunch(worker);
- if (++dec->cache_id_ == dec->num_caches_) {
- dec->cache_id_ = 0;
- }
- }
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// Finish setting up the decoding parameter once user's setup() is called.
-
-VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io) {
- // Call setup() first. This may trigger additional decoding features on 'io'.
- // Note: Afterward, we must call teardown() not matter what.
- if (io->setup && !io->setup(io)) {
- VP8SetError(dec, VP8_STATUS_USER_ABORT, "Frame setup failed");
- return dec->status_;
- }
-
- // Disable filtering per user request
- 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.
- //
- // 'Simple' filter reads two luma samples outside of the macroblock and
- // and filters one. It doesn't filter the chroma samples. Hence, we can
- // avoid doing the in-loop filtering before crop_top/crop_left position.
- // For the 'Complex' filter, 3 samples are read and up to 3 are filtered.
- // 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) {
- // For complex filter, we need to preserve the dependency chain.
- dec->tl_mb_x_ = 0;
- dec->tl_mb_y_ = 0;
- } else {
- // For simple filter, we can filter only the cropped region.
- // We include 'extra_pixels' on the other side of the boundary, since
- // vertical or horizontal filtering of the previous macroblock can
- // modify some abutting pixels.
- dec->tl_mb_x_ = (io->crop_left - extra_pixels) >> 4;
- dec->tl_mb_y_ = (io->crop_top - extra_pixels) >> 4;
- if (dec->tl_mb_x_ < 0) dec->tl_mb_x_ = 0;
- if (dec->tl_mb_y_ < 0) dec->tl_mb_y_ = 0;
- }
- // We need some 'extra' pixels on the right/bottom.
- dec->br_mb_y_ = (io->crop_bottom + 15 + extra_pixels) >> 4;
- dec->br_mb_x_ = (io->crop_right + 15 + extra_pixels) >> 4;
- if (dec->br_mb_x_ > dec->mb_w_) {
- dec->br_mb_x_ = dec->mb_w_;
- }
- if (dec->br_mb_y_ > dec->mb_h_) {
- dec->br_mb_y_ = dec->mb_h_;
- }
- }
- return VP8_STATUS_OK;
-}
-
-int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- if (dec->use_threads_) {
- ok = WebPWorkerSync(&dec->worker_);
- }
-
- if (io->teardown) {
- io->teardown(io);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// For multi-threaded decoding we need to use 3 rows of 16 pixels as delay line.
-//
-// Reason is: the deblocking filter cannot deblock the bottom horizontal edges
-// immediately, and needs to wait for first few rows of the next macroblock to
-// be decoded. Hence, deblocking is lagging behind by 4 or 8 pixels (depending
-// on strength).
-// With two threads, the vertical positions of the rows being decoded are:
-// Decode: [ 0..15][16..31][32..47][48..63][64..79][...
-// Deblock: [ 0..11][12..27][28..43][44..59][...
-// If we use two threads and two caches of 16 pixels, the sequence would be:
-// Decode: [ 0..15][16..31][ 0..15!!][16..31][ 0..15][...
-// Deblock: [ 0..11][12..27!!][-4..11][12..27][...
-// The problem occurs during row [12..15!!] that both the decoding and
-// deblocking threads are writing simultaneously.
-// With 3 cache lines, one get a safe write pattern:
-// Decode: [ 0..15][16..31][32..47][ 0..15][16..31][32..47][0..
-// Deblock: [ 0..11][12..27][28..43][-4..11][12..27][28...
-// Note that multi-threaded output _without_ deblocking can make use of two
-// cache lines of 16 pixels only, since there's no lagging behind. The decoding
-// and output process have non-concurrent writing:
-// Decode: [ 0..15][16..31][ 0..15][16..31][...
-// io->put: [ 0..15][16..31][ 0..15][...
-
-#define MT_CACHE_LINES 3
-#define ST_CACHE_LINES 1 // 1 cache row only for single-threaded case
-
-// Initialize multi/single-thread worker
-static int InitThreadContext(VP8Decoder* const dec) {
- dec->cache_id_ = 0;
- if (dec->use_threads_) {
- WebPWorker* const worker = &dec->worker_;
- if (!WebPWorkerReset(worker)) {
- return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
- "thread initialization failed.");
- }
- worker->data1 = dec;
- worker->data2 = (void*)&dec->thread_ctx_.io_;
- worker->hook = (WebPWorkerHook)FinishRow;
- dec->num_caches_ =
- (dec->filter_type_ > 0) ? MT_CACHE_LINES : MT_CACHE_LINES - 1;
- } else {
- dec->num_caches_ = ST_CACHE_LINES;
- }
- return 1;
-}
-
-#undef MT_CACHE_LINES
-#undef ST_CACHE_LINES
-
-//------------------------------------------------------------------------------
-// Memory setup
-
-static int AllocateMemory(VP8Decoder* const dec) {
- const int num_caches = dec->num_caches_;
- const int mb_w = dec->mb_w_;
- // Note: we use 'size_t' when there's no overflow risk, uint64_t otherwise.
- const size_t intra_pred_mode_size = 4 * mb_w * sizeof(uint8_t);
- const size_t top_size = (16 + 8 + 8) * mb_w;
- const size_t mb_info_size = (mb_w + 1) * sizeof(VP8MB);
- const size_t f_info_size =
- (dec->filter_type_ > 0) ?
- mb_w * (dec->use_threads_ ? 2 : 1) * sizeof(VP8FInfo)
- : 0;
- const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
- const size_t coeffs_size = 384 * sizeof(*dec->coeffs_);
- const size_t cache_height = (16 * num_caches
- + kFilterExtraRows[dec->filter_type_]) * 3 / 2;
- const size_t cache_size = top_size * cache_height;
- // alpha_size is the only one that scales as width x height.
- const uint64_t alpha_size = (dec->alpha_data_ != NULL) ?
- (uint64_t)dec->pic_hdr_.width_ * dec->pic_hdr_.height_ : 0ULL;
- const uint64_t needed = (uint64_t)intra_pred_mode_size
- + top_size + mb_info_size + f_info_size
- + yuv_size + coeffs_size
- + cache_size + alpha_size + ALIGN_MASK;
- uint8_t* mem;
-
- if (needed != (size_t)needed) return 0; // check for overflow
- if (needed > dec->mem_size_) {
- free(dec->mem_);
- dec->mem_size_ = 0;
- dec->mem_ = WebPSafeMalloc(needed, sizeof(uint8_t));
- if (dec->mem_ == NULL) {
- return VP8SetError(dec, VP8_STATUS_OUT_OF_MEMORY,
- "no memory during frame initialization.");
- }
- // down-cast is ok, thanks to WebPSafeAlloc() above.
- dec->mem_size_ = (size_t)needed;
- }
-
- mem = (uint8_t*)dec->mem_;
- dec->intra_t_ = (uint8_t*)mem;
- mem += intra_pred_mode_size;
-
- dec->y_t_ = (uint8_t*)mem;
- mem += 16 * mb_w;
- dec->u_t_ = (uint8_t*)mem;
- mem += 8 * mb_w;
- dec->v_t_ = (uint8_t*)mem;
- mem += 8 * mb_w;
-
- dec->mb_info_ = ((VP8MB*)mem) + 1;
- mem += mb_info_size;
-
- dec->f_info_ = f_info_size ? (VP8FInfo*)mem : NULL;
- mem += f_info_size;
- dec->thread_ctx_.id_ = 0;
- dec->thread_ctx_.f_info_ = dec->f_info_;
- if (dec->use_threads_) {
- // secondary cache line. The deblocking process need to make use of the
- // filtering strength from previous macroblock row, while the new ones
- // are being decoded in parallel. We'll just swap the pointers.
- dec->thread_ctx_.f_info_ += mb_w;
- }
-
- mem = (uint8_t*)((uintptr_t)(mem + ALIGN_MASK) & ~ALIGN_MASK);
- assert((yuv_size & ALIGN_MASK) == 0);
- dec->yuv_b_ = (uint8_t*)mem;
- mem += yuv_size;
-
- dec->coeffs_ = (int16_t*)mem;
- mem += coeffs_size;
-
- dec->cache_y_stride_ = 16 * mb_w;
- dec->cache_uv_stride_ = 8 * mb_w;
- {
- 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_u_ = dec->cache_y_
- + 16 * num_caches * dec->cache_y_stride_ + extra_uv;
- dec->cache_v_ = dec->cache_u_
- + 8 * num_caches * dec->cache_uv_stride_ + extra_uv;
- dec->cache_id_ = 0;
- }
- mem += cache_size;
-
- // alpha plane
- dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL;
- mem += alpha_size;
-
- // note: left-info is initialized once for all.
- memset(dec->mb_info_ - 1, 0, mb_info_size);
-
- // initialize top
- memset(dec->intra_t_, B_DC_PRED, intra_pred_mode_size);
-
- return 1;
-}
-
-static void InitIo(VP8Decoder* const dec, VP8Io* io) {
- // prepare 'io'
- io->mb_y = 0;
- io->y = dec->cache_y_;
- io->u = dec->cache_u_;
- io->v = dec->cache_v_;
- io->y_stride = dec->cache_y_stride_;
- io->uv_stride = dec->cache_uv_stride_;
- io->a = NULL;
-}
-
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* io) {
- if (!InitThreadContext(dec)) return 0; // call first. Sets dec->num_caches_.
- if (!AllocateMemory(dec)) return 0;
- InitIo(dec, io);
- VP8DspInit(); // Init critical function pointers and look-up tables.
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Main reconstruction function.
-
-static const int 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,
- 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS
-};
-
-static WEBP_INLINE int CheckMode(VP8Decoder* const dec, int mode) {
- if (mode == B_DC_PRED) {
- if (dec->mb_x_ == 0) {
- return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOPLEFT : B_DC_PRED_NOLEFT;
- } else {
- return (dec->mb_y_ == 0) ? B_DC_PRED_NOTOP : B_DC_PRED;
- }
- }
- return mode;
-}
-
-static WEBP_INLINE void Copy32b(uint8_t* dst, uint8_t* src) {
- *(uint32_t*)dst = *(uint32_t*)src;
-}
-
-void VP8ReconstructBlock(VP8Decoder* const dec) {
- uint8_t* const y_dst = dec->yuv_b_ + Y_OFF;
- uint8_t* const u_dst = dec->yuv_b_ + U_OFF;
- uint8_t* const v_dst = dec->yuv_b_ + V_OFF;
-
- // Rotate in the left samples from previously decoded block. We move four
- // pixels at a time for alignment reason, and because of in-loop filter.
- if (dec->mb_x_ > 0) {
- int j;
- for (j = -1; j < 16; ++j) {
- Copy32b(&y_dst[j * BPS - 4], &y_dst[j * BPS + 12]);
- }
- for (j = -1; j < 8; ++j) {
- Copy32b(&u_dst[j * BPS - 4], &u_dst[j * BPS + 4]);
- Copy32b(&v_dst[j * BPS - 4], &v_dst[j * BPS + 4]);
- }
- } else {
- int j;
- for (j = 0; j < 16; ++j) {
- y_dst[j * BPS - 1] = 129;
- }
- for (j = 0; j < 8; ++j) {
- u_dst[j * BPS - 1] = 129;
- v_dst[j * BPS - 1] = 129;
- }
- // Init top-left sample on left column too
- if (dec->mb_y_ > 0) {
- y_dst[-1 - BPS] = u_dst[-1 - BPS] = v_dst[-1 - BPS] = 129;
- }
- }
- {
- // bring top samples into the cache
- uint8_t* const top_y = dec->y_t_ + dec->mb_x_ * 16;
- uint8_t* const top_u = dec->u_t_ + dec->mb_x_ * 8;
- uint8_t* const top_v = dec->v_t_ + dec->mb_x_ * 8;
- const int16_t* coeffs = dec->coeffs_;
- int n;
-
- if (dec->mb_y_ > 0) {
- memcpy(y_dst - BPS, top_y, 16);
- memcpy(u_dst - BPS, top_u, 8);
- memcpy(v_dst - BPS, top_v, 8);
- } else if (dec->mb_x_ == 0) {
- // we only need to do this init once at block (0,0).
- // Afterward, it remains valid for the whole topmost row.
- memset(y_dst - BPS - 1, 127, 16 + 4 + 1);
- memset(u_dst - BPS - 1, 127, 8 + 1);
- memset(v_dst - BPS - 1, 127, 8 + 1);
- }
-
- // predict and add residuals
-
- if (dec->is_i4x4_) { // 4x4
- uint32_t* const top_right = (uint32_t*)(y_dst - BPS + 16);
-
- if (dec->mb_y_ > 0) {
- if (dec->mb_x_ >= dec->mb_w_ - 1) { // on rightmost border
- top_right[0] = top_y[15] * 0x01010101u;
- } else {
- memcpy(top_right, top_y + 16, sizeof(*top_right));
- }
- }
- // replicate the top-right pixels below
- top_right[BPS] = top_right[2 * BPS] = top_right[3 * BPS] = top_right[0];
-
- // predict and add residues for all 4x4 blocks in turn.
- for (n = 0; n < 16; n++) {
- uint8_t* const dst = y_dst + kScan[n];
- VP8PredLuma4[dec->imodes_[n]](dst);
- if (dec->non_zero_ac_ & (1 << n)) {
- VP8Transform(coeffs + n * 16, dst, 0);
- } else if (dec->non_zero_ & (1 << n)) { // only DC is present
- VP8TransformDC(coeffs + n * 16, dst);
- }
- }
- } else { // 16x16
- const int pred_func = CheckMode(dec, dec->imodes_[0]);
- VP8PredLuma16[pred_func](y_dst);
- if (dec->non_zero_) {
- for (n = 0; n < 16; n++) {
- uint8_t* const dst = y_dst + kScan[n];
- if (dec->non_zero_ac_ & (1 << n)) {
- VP8Transform(coeffs + n * 16, dst, 0);
- } else if (dec->non_zero_ & (1 << n)) { // only DC is present
- VP8TransformDC(coeffs + n * 16, dst);
- }
- }
- }
- }
- {
- // Chroma
- const int pred_func = CheckMode(dec, dec->uvmode_);
- VP8PredChroma8[pred_func](u_dst);
- VP8PredChroma8[pred_func](v_dst);
-
- if (dec->non_zero_ & 0x0f0000) { // chroma-U
- const int16_t* const u_coeffs = dec->coeffs_ + 16 * 16;
- if (dec->non_zero_ac_ & 0x0f0000) {
- VP8TransformUV(u_coeffs, u_dst);
- } else {
- VP8TransformDCUV(u_coeffs, u_dst);
- }
- }
- if (dec->non_zero_ & 0xf00000) { // chroma-V
- const int16_t* const v_coeffs = dec->coeffs_ + 20 * 16;
- if (dec->non_zero_ac_ & 0xf00000) {
- VP8TransformUV(v_coeffs, v_dst);
- } else {
- VP8TransformDCUV(v_coeffs, v_dst);
- }
- }
-
- // stash away top samples for next block
- if (dec->mb_y_ < dec->mb_h_ - 1) {
- memcpy(top_y, y_dst + 15 * BPS, 16);
- memcpy(top_u, u_dst + 7 * BPS, 8);
- memcpy(top_v, v_dst + 7 * BPS, 8);
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/idec.c b/drivers/webpold/dec/idec.c
deleted file mode 100644
index 7df790ced8..0000000000
--- a/drivers/webpold/dec/idec.c
+++ /dev/null
@@ -1,785 +0,0 @@
-// Copyright 2011 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/
-// -----------------------------------------------------------------------------
-//
-// Incremental decoding
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "./webpi.h"
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-// In append mode, buffer allocations increase as multiples of this value.
-// Needs to be a power of 2.
-#define CHUNK_SIZE 4096
-#define MAX_MB_SIZE 4096
-
-//------------------------------------------------------------------------------
-// Data structures for memory and states
-
-// Decoding states. State normally flows like HEADER->PARTS0->DATA->DONE.
-// If there is any error the decoder goes into state ERROR.
-typedef enum {
- STATE_PRE_VP8, // All data before that of the first VP8 chunk.
- STATE_VP8_FRAME_HEADER, // For VP8 Frame header (within VP8 chunk).
- STATE_VP8_PARTS0,
- STATE_VP8_DATA,
- STATE_VP8L_HEADER,
- STATE_VP8L_DATA,
- STATE_DONE,
- STATE_ERROR
-} DecState;
-
-// Operating state for the MemBuffer
-typedef enum {
- MEM_MODE_NONE = 0,
- MEM_MODE_APPEND,
- MEM_MODE_MAP
-} MemBufferMode;
-
-// storage for partition #0 and partial data (in a rolling fashion)
-typedef struct {
- MemBufferMode mode_; // Operation mode
- size_t start_; // start location of the data to be decoded
- size_t end_; // end location
- size_t buf_size_; // size of the allocated buffer
- uint8_t* buf_; // We don't own this buffer in case WebPIUpdate()
-
- size_t part0_size_; // size of partition #0
- const uint8_t* part0_buf_; // buffer to store partition #0
-} MemBuffer;
-
-struct WebPIDecoder {
- DecState state_; // current decoding state
- WebPDecParams params_; // Params to store output info
- int is_lossless_; // for down-casting 'dec_'.
- void* dec_; // either a VP8Decoder or a VP8LDecoder instance
- VP8Io io_;
-
- MemBuffer mem_; // input memory buffer.
- WebPDecBuffer output_; // output buffer (when no external one is supplied)
- size_t chunk_size_; // Compressed VP8/VP8L size extracted from Header.
-};
-
-// MB context to restore in case VP8DecodeMB() fails
-typedef struct {
- VP8MB left_;
- VP8MB info_;
- uint8_t intra_t_[4];
- uint8_t intra_l_[4];
- VP8BitReader br_;
- VP8BitReader token_br_;
-} MBContext;
-
-//------------------------------------------------------------------------------
-// MemBuffer: incoming data handling
-
-static void RemapBitReader(VP8BitReader* const br, ptrdiff_t offset) {
- if (br->buf_ != NULL) {
- br->buf_ += offset;
- br->buf_end_ += offset;
- }
-}
-
-static WEBP_INLINE size_t MemDataSize(const MemBuffer* mem) {
- return (mem->end_ - mem->start_);
-}
-
-static void DoRemap(WebPIDecoder* const idec, ptrdiff_t offset) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* const new_base = mem->buf_ + mem->start_;
- // note: for VP8, setting up idec->io_ is only really needed at the beginning
- // of the decoding, till partition #0 is complete.
- idec->io_.data = new_base;
- idec->io_.data_size = MemDataSize(mem);
-
- if (idec->dec_ != NULL) {
- if (!idec->is_lossless_) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- const int last_part = dec->num_parts_ - 1;
- if (offset != 0) {
- int p;
- for (p = 0; p <= last_part; ++p) {
- RemapBitReader(dec->parts_ + p, offset);
- }
- // Remap partition #0 data pointer to new offset, but only in MAP
- // mode (in APPEND mode, partition #0 is copied into a fixed memory).
- if (mem->mode_ == MEM_MODE_MAP) {
- RemapBitReader(&dec->br_, offset);
- }
- }
- assert(last_part >= 0);
- dec->parts_[last_part].buf_end_ = mem->buf_ + mem->end_;
- } else { // Resize lossless bitreader
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- VP8LBitReaderSetBuffer(&dec->br_, new_base, MemDataSize(mem));
- }
- }
-}
-
-// Appends data to the end of MemBuffer->buf_. It expands the allocated memory
-// size if required and also updates VP8BitReader's if new memory is allocated.
-static int AppendToMemBuffer(WebPIDecoder* const idec,
- const uint8_t* const data, size_t data_size) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* const old_base = mem->buf_ + mem->start_;
- assert(mem->mode_ == MEM_MODE_APPEND);
- if (data_size > MAX_CHUNK_PAYLOAD) {
- // security safeguard: trying to allocate more than what the format
- // allows for a chunk should be considered a smoke smell.
- return 0;
- }
-
- if (mem->end_ + data_size > mem->buf_size_) { // Need some free memory
- const size_t current_size = MemDataSize(mem);
- const uint64_t new_size = (uint64_t)current_size + data_size;
- const uint64_t extra_size = (new_size + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);
- uint8_t* const new_buf =
- (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
- if (new_buf == NULL) return 0;
- memcpy(new_buf, old_base, current_size);
- free(mem->buf_);
- mem->buf_ = new_buf;
- mem->buf_size_ = (size_t)extra_size;
- mem->start_ = 0;
- mem->end_ = current_size;
- }
-
- memcpy(mem->buf_ + mem->end_, data, data_size);
- mem->end_ += data_size;
- assert(mem->end_ <= mem->buf_size_);
-
- DoRemap(idec, mem->buf_ + mem->start_ - old_base);
- return 1;
-}
-
-static int RemapMemBuffer(WebPIDecoder* const idec,
- const uint8_t* const data, size_t data_size) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* const old_base = mem->buf_ + mem->start_;
- assert(mem->mode_ == MEM_MODE_MAP);
-
- if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!
-
- mem->buf_ = (uint8_t*)data;
- mem->end_ = mem->buf_size_ = data_size;
-
- DoRemap(idec, mem->buf_ + mem->start_ - old_base);
- return 1;
-}
-
-static void InitMemBuffer(MemBuffer* const mem) {
- mem->mode_ = MEM_MODE_NONE;
- mem->buf_ = NULL;
- mem->buf_size_ = 0;
- mem->part0_buf_ = NULL;
- mem->part0_size_ = 0;
-}
-
-static void ClearMemBuffer(MemBuffer* const mem) {
- assert(mem);
- if (mem->mode_ == MEM_MODE_APPEND) {
- free(mem->buf_);
- free((void*)mem->part0_buf_);
- }
-}
-
-static int CheckMemBufferMode(MemBuffer* const mem, MemBufferMode expected) {
- if (mem->mode_ == MEM_MODE_NONE) {
- mem->mode_ = expected; // switch to the expected mode
- } else if (mem->mode_ != expected) {
- return 0; // we mixed the modes => error
- }
- assert(mem->mode_ == expected); // mode is ok
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Macroblock-decoding contexts
-
-static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
- MBContext* const context) {
- const VP8BitReader* const br = &dec->br_;
- const VP8MB* const left = dec->mb_info_ - 1;
- const VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- context->left_ = *left;
- context->info_ = *info;
- context->br_ = *br;
- context->token_br_ = *token_br;
- memcpy(context->intra_t_, dec->intra_t_ + 4 * dec->mb_x_, 4);
- memcpy(context->intra_l_, dec->intra_l_, 4);
-}
-
-static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
- VP8BitReader* const token_br) {
- VP8BitReader* const br = &dec->br_;
- VP8MB* const left = dec->mb_info_ - 1;
- VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- *left = context->left_;
- *info = context->info_;
- *br = context->br_;
- *token_br = context->token_br_;
- memcpy(dec->intra_t_ + 4 * dec->mb_x_, context->intra_t_, 4);
- memcpy(dec->intra_l_, context->intra_l_, 4);
-}
-
-//------------------------------------------------------------------------------
-
-static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
- if (idec->state_ == STATE_VP8_DATA) {
- VP8Io* const io = &idec->io_;
- if (io->teardown) {
- io->teardown(io);
- }
- }
- idec->state_ = STATE_ERROR;
- return error;
-}
-
-static void ChangeState(WebPIDecoder* const idec, DecState new_state,
- size_t consumed_bytes) {
- MemBuffer* const mem = &idec->mem_;
- idec->state_ = new_state;
- mem->start_ += consumed_bytes;
- assert(mem->start_ <= mem->end_);
- idec->io_.data = mem->buf_ + mem->start_;
- idec->io_.data_size = MemDataSize(mem);
-}
-
-// Headers
-static VP8StatusCode DecodeWebPHeaders(WebPIDecoder* const idec) {
- MemBuffer* const mem = &idec->mem_;
- const uint8_t* data = mem->buf_ + mem->start_;
- size_t curr_size = MemDataSize(mem);
- VP8StatusCode status;
- WebPHeaderStructure headers;
-
- headers.data = data;
- headers.data_size = curr_size;
- status = WebPParseHeaders(&headers);
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_SUSPENDED; // We haven't found a VP8 chunk yet.
- } else if (status != VP8_STATUS_OK) {
- return IDecError(idec, status);
- }
-
- idec->chunk_size_ = headers.compressed_size;
- idec->is_lossless_ = headers.is_lossless;
- if (!idec->is_lossless_) {
- VP8Decoder* const dec = VP8New();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- idec->dec_ = dec;
-#ifdef WEBP_USE_THREAD
- dec->use_threads_ = (idec->params_.options != NULL) &&
- (idec->params_.options->use_threads > 0);
-#else
- dec->use_threads_ = 0;
-#endif
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
- ChangeState(idec, STATE_VP8_FRAME_HEADER, headers.offset);
- } else {
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- idec->dec_ = dec;
- ChangeState(idec, STATE_VP8L_HEADER, headers.offset);
- }
- return VP8_STATUS_OK;
-}
-
-static VP8StatusCode DecodeVP8FrameHeader(WebPIDecoder* const idec) {
- const uint8_t* data = idec->mem_.buf_ + idec->mem_.start_;
- const size_t curr_size = MemDataSize(&idec->mem_);
- uint32_t bits;
-
- if (curr_size < VP8_FRAME_HEADER_SIZE) {
- // Not enough data bytes to extract VP8 Frame Header.
- return VP8_STATUS_SUSPENDED;
- }
- if (!VP8GetInfo(data, curr_size, idec->chunk_size_, NULL, NULL)) {
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
-
- bits = data[0] | (data[1] << 8) | (data[2] << 16);
- idec->mem_.part0_size_ = (bits >> 5) + VP8_FRAME_HEADER_SIZE;
-
- idec->io_.data = data;
- idec->io_.data_size = curr_size;
- idec->state_ = STATE_VP8_PARTS0;
- return VP8_STATUS_OK;
-}
-
-// Partition #0
-static int CopyParts0Data(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8BitReader* const br = &dec->br_;
- const size_t psize = br->buf_end_ - br->buf_;
- MemBuffer* const mem = &idec->mem_;
- assert(!idec->is_lossless_);
- assert(mem->part0_buf_ == NULL);
- assert(psize > 0);
- assert(psize <= mem->part0_size_); // Format limit: no need for runtime check
- if (mem->mode_ == MEM_MODE_APPEND) {
- // We copy and grab ownership of the partition #0 data.
- uint8_t* const part0_buf = (uint8_t*)malloc(psize);
- if (part0_buf == NULL) {
- return 0;
- }
- memcpy(part0_buf, br->buf_, psize);
- mem->part0_buf_ = part0_buf;
- br->buf_ = part0_buf;
- br->buf_end_ = part0_buf + psize;
- } else {
- // Else: just keep pointers to the partition #0's data in dec_->br_.
- }
- mem->start_ += psize;
- return 1;
-}
-
-static VP8StatusCode DecodePartition0(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8Io* const io = &idec->io_;
- const WebPDecParams* const params = &idec->params_;
- WebPDecBuffer* const output = params->output;
-
- // Wait till we have enough data for the whole partition #0
- if (MemDataSize(&idec->mem_) < idec->mem_.part0_size_) {
- return VP8_STATUS_SUSPENDED;
- }
-
- if (!VP8GetHeaders(dec, io)) {
- const VP8StatusCode status = dec->status_;
- if (status == VP8_STATUS_SUSPENDED ||
- status == VP8_STATUS_NOT_ENOUGH_DATA) {
- // treating NOT_ENOUGH_DATA as SUSPENDED state
- return VP8_STATUS_SUSPENDED;
- }
- return IDecError(idec, status);
- }
-
- // Allocate/Verify output buffer now
- dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
- output);
- if (dec->status_ != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- if (!CopyParts0Data(idec)) {
- return IDecError(idec, VP8_STATUS_OUT_OF_MEMORY);
- }
-
- // Finish setting up the decoding parameters. Will call io->setup().
- if (VP8EnterCritical(dec, io) != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- // Note: past this point, teardown() must always be called
- // in case of error.
- idec->state_ = STATE_VP8_DATA;
- // Allocate memory and prepare everything.
- if (!VP8InitFrame(dec, io)) {
- return IDecError(idec, dec->status_);
- }
- return VP8_STATUS_OK;
-}
-
-// Remaining partitions
-static VP8StatusCode DecodeRemaining(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8Io* const io = &idec->io_;
-
- assert(dec->ready_);
-
- for (; dec->mb_y_ < dec->mb_h_; ++dec->mb_y_) {
- VP8BitReader* token_br = &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
- if (dec->mb_x_ == 0) {
- VP8InitScanline(dec);
- }
- for (; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
- MBContext context;
- SaveContext(dec, token_br, &context);
-
- if (!VP8DecodeMB(dec, token_br)) {
- RestoreContext(&context, dec, token_br);
- // We shouldn't fail when MAX_MB data was available
- if (dec->num_parts_ == 1 && MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
- return VP8_STATUS_SUSPENDED;
- }
- VP8ReconstructBlock(dec);
- // Store data and save block's filtering params
- VP8StoreBlock(dec);
-
- // Release buffer only if there is only one partition
- if (dec->num_parts_ == 1) {
- idec->mem_.start_ = token_br->buf_ - idec->mem_.buf_;
- assert(idec->mem_.start_ <= idec->mem_.end_);
- }
- }
- if (!VP8ProcessRow(dec, io)) {
- return IDecError(idec, VP8_STATUS_USER_ABORT);
- }
- dec->mb_x_ = 0;
- }
- // Synchronize the thread and check for errors.
- if (!VP8ExitCritical(dec, io)) {
- return IDecError(idec, VP8_STATUS_USER_ABORT);
- }
- dec->ready_ = 0;
- idec->state_ = STATE_DONE;
-
- return VP8_STATUS_OK;
-}
-
-static int ErrorStatusLossless(WebPIDecoder* const idec, VP8StatusCode status) {
- if (status == VP8_STATUS_SUSPENDED || status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_SUSPENDED;
- }
- return IDecError(idec, status);
-}
-
-static VP8StatusCode DecodeVP8LHeader(WebPIDecoder* const idec) {
- VP8Io* const io = &idec->io_;
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- const WebPDecParams* const params = &idec->params_;
- WebPDecBuffer* const output = params->output;
- size_t curr_size = MemDataSize(&idec->mem_);
- assert(idec->is_lossless_);
-
- // Wait until there's enough data for decoding header.
- if (curr_size < (idec->chunk_size_ >> 3)) {
- return VP8_STATUS_SUSPENDED;
- }
- if (!VP8LDecodeHeader(dec, io)) {
- return ErrorStatusLossless(idec, dec->status_);
- }
- // Allocate/verify output buffer now.
- dec->status_ = WebPAllocateDecBuffer(io->width, io->height, params->options,
- output);
- if (dec->status_ != VP8_STATUS_OK) {
- return IDecError(idec, dec->status_);
- }
-
- idec->state_ = STATE_VP8L_DATA;
- return VP8_STATUS_OK;
-}
-
-static VP8StatusCode DecodeVP8LData(WebPIDecoder* const idec) {
- VP8LDecoder* const dec = (VP8LDecoder*)idec->dec_;
- const size_t curr_size = MemDataSize(&idec->mem_);
- assert(idec->is_lossless_);
-
- // At present Lossless decoder can't decode image incrementally. So wait till
- // all the image data is aggregated before image can be decoded.
- if (curr_size < idec->chunk_size_) {
- return VP8_STATUS_SUSPENDED;
- }
-
- if (!VP8LDecodeImage(dec)) {
- return ErrorStatusLossless(idec, dec->status_);
- }
-
- idec->state_ = STATE_DONE;
-
- return VP8_STATUS_OK;
-}
-
- // Main decoding loop
-static VP8StatusCode IDecode(WebPIDecoder* idec) {
- VP8StatusCode status = VP8_STATUS_SUSPENDED;
-
- if (idec->state_ == STATE_PRE_VP8) {
- status = DecodeWebPHeaders(idec);
- } else {
- if (idec->dec_ == NULL) {
- return VP8_STATUS_SUSPENDED; // can't continue if we have no decoder.
- }
- }
- if (idec->state_ == STATE_VP8_FRAME_HEADER) {
- status = DecodeVP8FrameHeader(idec);
- }
- if (idec->state_ == STATE_VP8_PARTS0) {
- status = DecodePartition0(idec);
- }
- if (idec->state_ == STATE_VP8_DATA) {
- status = DecodeRemaining(idec);
- }
- if (idec->state_ == STATE_VP8L_HEADER) {
- status = DecodeVP8LHeader(idec);
- }
- if (idec->state_ == STATE_VP8L_DATA) {
- status = DecodeVP8LData(idec);
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Public functions
-
-WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
- WebPIDecoder* idec = (WebPIDecoder*)calloc(1, sizeof(*idec));
- if (idec == NULL) {
- return NULL;
- }
-
- idec->state_ = STATE_PRE_VP8;
- idec->chunk_size_ = 0;
-
- InitMemBuffer(&idec->mem_);
- WebPInitDecBuffer(&idec->output_);
- VP8InitIo(&idec->io_);
-
- WebPResetDecParams(&idec->params_);
- idec->params_.output = output_buffer ? output_buffer : &idec->output_;
- WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
-
- return idec;
-}
-
-WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config) {
- WebPIDecoder* idec;
-
- // Parse the bitstream's features, if requested:
- if (data != NULL && data_size > 0 && config != NULL) {
- if (WebPGetFeatures(data, data_size, &config->input) != VP8_STATUS_OK) {
- return NULL;
- }
- }
- // Create an instance of the incremental decoder
- idec = WebPINewDecoder(config ? &config->output : NULL);
- if (idec == NULL) {
- return NULL;
- }
- // Finish initialization
- if (config != NULL) {
- idec->params_.options = &config->options;
- }
- return idec;
-}
-
-void WebPIDelete(WebPIDecoder* idec) {
- if (idec == NULL) return;
- if (idec->dec_ != NULL) {
- if (!idec->is_lossless_) {
- VP8Delete(idec->dec_);
- } else {
- VP8LDelete(idec->dec_);
- }
- }
- ClearMemBuffer(&idec->mem_);
- WebPFreeDecBuffer(&idec->output_);
- free(idec);
-}
-
-//------------------------------------------------------------------------------
-// Wrapper toward WebPINewDecoder
-
-WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer,
- size_t output_buffer_size, int output_stride) {
- WebPIDecoder* idec;
- if (mode >= MODE_YUV) return NULL;
- idec = WebPINewDecoder(NULL);
- if (idec == NULL) return NULL;
- idec->output_.colorspace = mode;
- idec->output_.is_external_memory = 1;
- idec->output_.u.RGBA.rgba = output_buffer;
- idec->output_.u.RGBA.stride = output_stride;
- idec->output_.u.RGBA.size = output_buffer_size;
- return idec;
-}
-
-WebPIDecoder* WebPINewYUVA(uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride,
- uint8_t* a, size_t a_size, int a_stride) {
- WebPIDecoder* const idec = WebPINewDecoder(NULL);
- if (idec == NULL) return NULL;
- idec->output_.colorspace = (a == NULL) ? MODE_YUV : MODE_YUVA;
- idec->output_.is_external_memory = 1;
- idec->output_.u.YUVA.y = luma;
- idec->output_.u.YUVA.y_stride = luma_stride;
- idec->output_.u.YUVA.y_size = luma_size;
- idec->output_.u.YUVA.u = u;
- idec->output_.u.YUVA.u_stride = u_stride;
- idec->output_.u.YUVA.u_size = u_size;
- idec->output_.u.YUVA.v = v;
- idec->output_.u.YUVA.v_stride = v_stride;
- idec->output_.u.YUVA.v_size = v_size;
- idec->output_.u.YUVA.a = a;
- idec->output_.u.YUVA.a_stride = a_stride;
- idec->output_.u.YUVA.a_size = a_size;
- return idec;
-}
-
-WebPIDecoder* WebPINewYUV(uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride) {
- return WebPINewYUVA(luma, luma_size, luma_stride,
- u, u_size, u_stride,
- v, v_size, v_stride,
- NULL, 0, 0);
-}
-
-//------------------------------------------------------------------------------
-
-static VP8StatusCode IDecCheckStatus(const WebPIDecoder* const idec) {
- assert(idec);
- if (idec->state_ == STATE_ERROR) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (idec->state_ == STATE_DONE) {
- return VP8_STATUS_OK;
- }
- return VP8_STATUS_SUSPENDED;
-}
-
-VP8StatusCode WebPIAppend(WebPIDecoder* idec,
- const uint8_t* data, size_t data_size) {
- VP8StatusCode status;
- if (idec == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- status = IDecCheckStatus(idec);
- if (status != VP8_STATUS_SUSPENDED) {
- return status;
- }
- // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
- if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_APPEND)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- // Append data to memory buffer
- if (!AppendToMemBuffer(idec, data, data_size)) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- return IDecode(idec);
-}
-
-VP8StatusCode WebPIUpdate(WebPIDecoder* idec,
- const uint8_t* data, size_t data_size) {
- VP8StatusCode status;
- if (idec == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- status = IDecCheckStatus(idec);
- if (status != VP8_STATUS_SUSPENDED) {
- return status;
- }
- // Check mixed calls between RemapMemBuffer and AppendToMemBuffer.
- if (!CheckMemBufferMode(&idec->mem_, MEM_MODE_MAP)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- // Make the memory buffer point to the new buffer
- if (!RemapMemBuffer(idec, data, data_size)) {
- return VP8_STATUS_INVALID_PARAM;
- }
- return IDecode(idec);
-}
-
-//------------------------------------------------------------------------------
-
-static const WebPDecBuffer* GetOutputBuffer(const WebPIDecoder* const idec) {
- if (idec == NULL || idec->dec_ == NULL) {
- return NULL;
- }
- if (idec->state_ <= STATE_VP8_PARTS0) {
- return NULL;
- }
- return idec->params_.output;
-}
-
-const WebPDecBuffer* WebPIDecodedArea(const WebPIDecoder* idec,
- int* left, int* top,
- int* width, int* height) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (left != NULL) *left = 0;
- if (top != NULL) *top = 0;
- // TODO(skal): later include handling of rotations.
- if (src) {
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = idec->params_.last_y;
- } else {
- if (width != NULL) *width = 0;
- if (height != NULL) *height = 0;
- }
- return src;
-}
-
-uint8_t* WebPIDecGetRGB(const WebPIDecoder* idec, int* last_y,
- int* width, int* height, int* stride) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (src == NULL) return NULL;
- if (src->colorspace >= MODE_YUV) {
- return NULL;
- }
-
- if (last_y != NULL) *last_y = idec->params_.last_y;
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = src->height;
- if (stride != NULL) *stride = src->u.RGBA.stride;
-
- return src->u.RGBA.rgba;
-}
-
-uint8_t* WebPIDecGetYUVA(const WebPIDecoder* idec, int* last_y,
- uint8_t** u, uint8_t** v, uint8_t** a,
- int* width, int* height,
- int* stride, int* uv_stride, int* a_stride) {
- const WebPDecBuffer* const src = GetOutputBuffer(idec);
- if (src == NULL) return NULL;
- if (src->colorspace < MODE_YUV) {
- return NULL;
- }
-
- if (last_y != NULL) *last_y = idec->params_.last_y;
- if (u != NULL) *u = src->u.YUVA.u;
- if (v != NULL) *v = src->u.YUVA.v;
- if (a != NULL) *a = src->u.YUVA.a;
- if (width != NULL) *width = src->width;
- if (height != NULL) *height = src->height;
- if (stride != NULL) *stride = src->u.YUVA.y_stride;
- if (uv_stride != NULL) *uv_stride = src->u.YUVA.u_stride;
- if (a_stride != NULL) *a_stride = src->u.YUVA.a_stride;
-
- return src->u.YUVA.y;
-}
-
-int WebPISetIOHooks(WebPIDecoder* const idec,
- VP8IoPutHook put,
- VP8IoSetupHook setup,
- VP8IoTeardownHook teardown,
- void* user_data) {
- if (idec == NULL || idec->state_ > STATE_PRE_VP8) {
- return 0;
- }
-
- idec->io_.put = put;
- idec->io_.setup = setup;
- idec->io_.teardown = teardown;
- idec->io_.opaque = user_data;
-
- return 1;
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/io.c b/drivers/webpold/dec/io.c
deleted file mode 100644
index 594804c2e6..0000000000
--- a/drivers/webpold/dec/io.c
+++ /dev/null
@@ -1,633 +0,0 @@
-// Copyright 2011 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/
-// -----------------------------------------------------------------------------
-//
-// functions for sample output.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include "../dec/vp8i.h"
-#include "./webpi.h"
-#include "../dsp/dsp.h"
-#include "../dsp/yuv.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Main YUV<->RGB conversion functions
-
-static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPYUVABuffer* const buf = &output->u.YUVA;
- uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride;
- uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride;
- uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- const int uv_w = (mb_w + 1) / 2;
- const int uv_h = (mb_h + 1) / 2;
- int j;
- for (j = 0; j < mb_h; ++j) {
- memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w);
- }
- for (j = 0; j < uv_h; ++j) {
- memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w);
- memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w);
- }
- return io->mb_h;
-}
-
-// Point-sampling U/V sampler.
-static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- const uint8_t* y_src = io->y;
- const uint8_t* u_src = io->u;
- const uint8_t* v_src = io->v;
- const WebPSampleLinePairFunc sample = WebPSamplers[output->colorspace];
- const int mb_w = io->mb_w;
- const int last = io->mb_h - 1;
- int j;
- for (j = 0; j < last; j += 2) {
- sample(y_src, y_src + io->y_stride, u_src, v_src,
- dst, dst + buf->stride, mb_w);
- y_src += 2 * io->y_stride;
- u_src += io->uv_stride;
- v_src += io->uv_stride;
- dst += 2 * buf->stride;
- }
- if (j == last) { // Just do the last line twice
- sample(y_src, y_src, u_src, v_src, dst, dst, mb_w);
- }
- return io->mb_h;
-}
-
-//------------------------------------------------------------------------------
-// YUV444 -> RGB conversion
-
-#if 0 // TODO(skal): this is for future rescaling.
-static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) {
- WebPDecBuffer* output = p->output;
- const WebPRGBABuffer* const buf = &output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- const uint8_t* y_src = io->y;
- const uint8_t* u_src = io->u;
- const uint8_t* v_src = io->v;
- const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace];
- const int mb_w = io->mb_w;
- const int last = io->mb_h;
- int j;
- for (j = 0; j < last; ++j) {
- convert(y_src, u_src, v_src, dst, mb_w);
- y_src += io->y_stride;
- u_src += io->uv_stride;
- v_src += io->uv_stride;
- dst += buf->stride;
- }
- return io->mb_h;
-}
-#endif
-
-//------------------------------------------------------------------------------
-// Fancy upsampling
-
-#ifdef FANCY_UPSAMPLING
-static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
- int num_lines_out = io->mb_h; // a priori guess
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
- WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
- const uint8_t* cur_y = io->y;
- const uint8_t* cur_u = io->u;
- const uint8_t* cur_v = io->v;
- const uint8_t* top_u = p->tmp_u;
- const uint8_t* top_v = p->tmp_v;
- int y = io->mb_y;
- const int y_end = io->mb_y + io->mb_h;
- const int mb_w = io->mb_w;
- const int uv_w = (mb_w + 1) / 2;
-
- if (y == 0) {
- // First line is special cased. We mirror the u/v samples at boundary.
- upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w);
- } else {
- // We can finish the left-over line from previous call.
- upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
- dst - buf->stride, dst, mb_w);
- ++num_lines_out;
- }
- // Loop over each output pairs of row.
- for (; y + 2 < y_end; y += 2) {
- top_u = cur_u;
- top_v = cur_v;
- cur_u += io->uv_stride;
- cur_v += io->uv_stride;
- dst += 2 * buf->stride;
- cur_y += 2 * io->y_stride;
- upsample(cur_y - io->y_stride, cur_y,
- top_u, top_v, cur_u, cur_v,
- dst - buf->stride, dst, mb_w);
- }
- // move to last row
- cur_y += io->y_stride;
- if (io->crop_top + y_end < io->crop_bottom) {
- // Save the unfinished samples for next call (as we're not done yet).
- memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
- memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
- memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
- // The fancy upsampler leaves a row unfinished behind
- // (except for the very last row)
- num_lines_out--;
- } else {
- // Process the very last row of even-sized picture
- if (!(y_end & 1)) {
- upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
- dst + buf->stride, NULL, mb_w);
- }
- }
- return num_lines_out;
-}
-
-#endif /* FANCY_UPSAMPLING */
-
-//------------------------------------------------------------------------------
-
-static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
- const uint8_t* alpha = io->a;
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- uint8_t* dst = buf->a + io->mb_y * buf->a_stride;
- int j;
-
- if (alpha != NULL) {
- for (j = 0; j < mb_h; ++j) {
- memcpy(dst, alpha, mb_w * sizeof(*dst));
- alpha += io->width;
- dst += buf->a_stride;
- }
- } else if (buf->a != NULL) {
- // the user requested alpha, but there is none, set it to opaque.
- for (j = 0; j < mb_h; ++j) {
- memset(dst, 0xff, mb_w * sizeof(*dst));
- dst += buf->a_stride;
- }
- }
- return 0;
-}
-
-static int GetAlphaSourceRow(const VP8Io* const io,
- const uint8_t** alpha, int* const num_rows) {
- int start_y = io->mb_y;
- *num_rows = io->mb_h;
-
- // Compensate for the 1-line delay of the fancy upscaler.
- // This is similar to EmitFancyRGB().
- if (io->fancy_upsampling) {
- if (start_y == 0) {
- // We don't process the last row yet. It'll be done during the next call.
- --*num_rows;
- } else {
- --start_y;
- // Fortunately, *alpha data is persistent, so we can go back
- // one row and finish alpha blending, now that the fancy upscaler
- // completed the YUV->RGB interpolation.
- *alpha -= io->width;
- }
- if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) {
- // If it's the very last call, we process all the remaining rows!
- *num_rows = io->crop_bottom - io->crop_top - start_y;
- }
- }
- return start_y;
-}
-
-static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
- const uint8_t* alpha = io->a;
- if (alpha != NULL) {
- const int mb_w = io->mb_w;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int alpha_first =
- (colorspace == MODE_ARGB || colorspace == MODE_Argb);
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- int num_rows;
- const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
- uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
- uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
- uint32_t alpha_mask = 0xff;
- int i, j;
-
- for (j = 0; j < num_rows; ++j) {
- for (i = 0; i < mb_w; ++i) {
- const uint32_t alpha_value = alpha[i];
- dst[4 * i] = alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha += io->width;
- dst += buf->stride;
- }
- // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
- if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
- WebPApplyAlphaMultiply(base_rgba, alpha_first,
- mb_w, num_rows, buf->stride);
- }
- }
- return 0;
-}
-
-static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
- const uint8_t* alpha = io->a;
- if (alpha != NULL) {
- const int mb_w = io->mb_w;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- int num_rows;
- const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
- uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
- uint8_t* alpha_dst = base_rgba + 1;
- uint32_t alpha_mask = 0x0f;
- int i, j;
-
- for (j = 0; j < num_rows; ++j) {
- for (i = 0; i < mb_w; ++i) {
- // Fill in the alpha value (converted to 4 bits).
- const uint32_t alpha_value = alpha[i] >> 4;
- alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha += io->width;
- alpha_dst += buf->stride;
- }
- if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
- WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
- }
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// YUV rescaling (no final RGB conversion needed)
-
-static int Rescale(const uint8_t* src, int src_stride,
- int new_lines, WebPRescaler* const wrk) {
- int num_lines_out = 0;
- while (new_lines > 0) { // import new contributions of source rows.
- const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride);
- src += lines_in * src_stride;
- new_lines -= lines_in;
- num_lines_out += WebPRescalerExport(wrk); // emit output row(s)
- }
- return num_lines_out;
-}
-
-static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
- const int mb_h = io->mb_h;
- const int uv_mb_h = (mb_h + 1) >> 1;
- const int num_lines_out = Rescale(io->y, io->y_stride, mb_h, &p->scaler_y);
- Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u);
- Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v);
- return num_lines_out;
-}
-
-static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
- if (io->a != NULL) {
- Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
- }
- return 0;
-}
-
-static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
- const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- const int out_width = io->scaled_width;
- const int out_height = io->scaled_height;
- const int uv_out_width = (out_width + 1) >> 1;
- const int uv_out_height = (out_height + 1) >> 1;
- const int uv_in_width = (io->mb_w + 1) >> 1;
- const int uv_in_height = (io->mb_h + 1) >> 1;
- const size_t work_size = 2 * out_width; // scratch memory for luma rescaler
- const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones
- size_t tmp_size;
- int32_t* work;
-
- tmp_size = work_size + 2 * uv_work_size;
- if (has_alpha) {
- tmp_size += work_size;
- }
- p->memory = calloc(1, tmp_size * sizeof(*work));
- if (p->memory == NULL) {
- return 0; // memory error
- }
- work = (int32_t*)p->memory;
- WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
- buf->y, out_width, out_height, buf->y_stride, 1,
- io->mb_w, out_width, io->mb_h, out_height,
- work);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
- uv_in_width, uv_out_width,
- uv_in_height, uv_out_height,
- work + work_size);
- WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
- buf->v, uv_out_width, uv_out_height, buf->v_stride, 1,
- uv_in_width, uv_out_width,
- uv_in_height, uv_out_height,
- work + work_size + uv_work_size);
- p->emit = EmitRescaledYUV;
-
- if (has_alpha) {
- WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
- buf->a, out_width, out_height, buf->a_stride, 1,
- io->mb_w, out_width, io->mb_h, out_height,
- work + work_size + 2 * uv_work_size);
- p->emit_alpha = EmitRescaledAlphaYUV;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// RGBA rescaling
-
-static int ExportRGB(WebPDecParams* const p, int y_pos) {
- const WebPYUV444Converter convert =
- WebPYUV444Converters[p->output->colorspace];
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride;
- int num_lines_out = 0;
- // For RGB rescaling, because of the YUV420, current scan position
- // U/V can be +1/-1 line from the Y one. Hence the double test.
- while (WebPRescalerHasPendingOutput(&p->scaler_y) &&
- WebPRescalerHasPendingOutput(&p->scaler_u)) {
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
- assert(p->scaler_u.y_accum == p->scaler_v.y_accum);
- WebPRescalerExportRow(&p->scaler_y);
- WebPRescalerExportRow(&p->scaler_u);
- WebPRescalerExportRow(&p->scaler_v);
- convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
- dst, p->scaler_y.dst_width);
- dst += buf->stride;
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) {
- const int mb_h = io->mb_h;
- const int uv_mb_h = (mb_h + 1) >> 1;
- int j = 0, uv_j = 0;
- int num_lines_out = 0;
- while (j < mb_h) {
- const int y_lines_in =
- WebPRescalerImport(&p->scaler_y, mb_h - j,
- io->y + j * io->y_stride, io->y_stride);
- const int u_lines_in =
- WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j,
- io->u + uv_j * io->uv_stride, io->uv_stride);
- const int v_lines_in =
- WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j,
- io->v + uv_j * io->uv_stride, io->uv_stride);
- (void)v_lines_in; // remove a gcc warning
- assert(u_lines_in == v_lines_in);
- j += y_lines_in;
- uv_j += u_lines_in;
- num_lines_out += ExportRGB(p, num_lines_out);
- }
- return num_lines_out;
-}
-
-static int ExportAlpha(WebPDecParams* const p, int y_pos) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int alpha_first =
- (colorspace == MODE_ARGB || colorspace == MODE_Argb);
- uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
- int num_lines_out = 0;
- const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
- uint32_t alpha_mask = 0xff;
- const int width = p->scaler_a.dst_width;
-
- while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
- int i;
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
- WebPRescalerExportRow(&p->scaler_a);
- for (i = 0; i < width; ++i) {
- const uint32_t alpha_value = p->scaler_a.dst[i];
- dst[4 * i] = alpha_value;
- alpha_mask &= alpha_value;
- }
- dst += buf->stride;
- ++num_lines_out;
- }
- if (is_premult_alpha && alpha_mask != 0xff) {
- WebPApplyAlphaMultiply(base_rgba, alpha_first,
- width, num_lines_out, buf->stride);
- }
- return num_lines_out;
-}
-
-static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
- uint8_t* alpha_dst = base_rgba + 1;
- int num_lines_out = 0;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int width = p->scaler_a.dst_width;
- const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
- uint32_t alpha_mask = 0x0f;
-
- while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
- int i;
- assert(p->last_y + y_pos + num_lines_out < p->output->height);
- WebPRescalerExportRow(&p->scaler_a);
- for (i = 0; i < width; ++i) {
- // Fill in the alpha value (converted to 4 bits).
- const uint32_t alpha_value = p->scaler_a.dst[i] >> 4;
- alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
- alpha_mask &= alpha_value;
- }
- alpha_dst += buf->stride;
- ++num_lines_out;
- }
- if (is_premult_alpha && alpha_mask != 0x0f) {
- WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
- }
- return num_lines_out;
-}
-
-static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
- if (io->a != NULL) {
- WebPRescaler* const scaler = &p->scaler_a;
- int j = 0;
- int pos = 0;
- while (j < io->mb_h) {
- j += WebPRescalerImport(scaler, io->mb_h - j,
- io->a + j * io->width, io->width);
- pos += p->emit_alpha_row(p, pos);
- }
- }
- return 0;
-}
-
-static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
- const int has_alpha = WebPIsAlphaMode(p->output->colorspace);
- const int out_width = io->scaled_width;
- const int out_height = io->scaled_height;
- const int uv_in_width = (io->mb_w + 1) >> 1;
- const int uv_in_height = (io->mb_h + 1) >> 1;
- const size_t work_size = 2 * out_width; // scratch memory for one rescaler
- int32_t* work; // rescalers work area
- uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
- size_t tmp_size1, tmp_size2;
-
- tmp_size1 = 3 * work_size;
- tmp_size2 = 3 * out_width;
- if (has_alpha) {
- tmp_size1 += work_size;
- tmp_size2 += out_width;
- }
- p->memory = calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
- if (p->memory == NULL) {
- return 0; // memory error
- }
- work = (int32_t*)p->memory;
- tmp = (uint8_t*)(work + tmp_size1);
- WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
- tmp + 0 * out_width, out_width, out_height, 0, 1,
- io->mb_w, out_width, io->mb_h, out_height,
- work + 0 * work_size);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- tmp + 1 * out_width, out_width, out_height, 0, 1,
- io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
- work + 1 * work_size);
- WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
- tmp + 2 * out_width, out_width, out_height, 0, 1,
- io->mb_w, 2 * out_width, io->mb_h, 2 * out_height,
- work + 2 * work_size);
- p->emit = EmitRescaledRGB;
-
- if (has_alpha) {
- WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h,
- tmp + 3 * out_width, out_width, out_height, 0, 1,
- io->mb_w, out_width, io->mb_h, out_height,
- work + 3 * work_size);
- p->emit_alpha = EmitRescaledAlphaRGB;
- if (p->output->colorspace == MODE_RGBA_4444 ||
- p->output->colorspace == MODE_rgbA_4444) {
- p->emit_alpha_row = ExportAlphaRGBA4444;
- } else {
- p->emit_alpha_row = ExportAlpha;
- }
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Default custom functions
-
-static int CustomSetup(VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- const WEBP_CSP_MODE colorspace = p->output->colorspace;
- const int is_rgb = WebPIsRGBMode(colorspace);
- const int is_alpha = WebPIsAlphaMode(colorspace);
-
- p->memory = NULL;
- p->emit = NULL;
- p->emit_alpha = NULL;
- p->emit_alpha_row = NULL;
- if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
- return 0;
- }
-
- if (io->use_scaling) {
- const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
- if (!ok) {
- return 0; // memory error
- }
- } else {
- if (is_rgb) {
- p->emit = EmitSampledRGB; // default
-#ifdef FANCY_UPSAMPLING
- if (io->fancy_upsampling) {
- const int uv_width = (io->mb_w + 1) >> 1;
- p->memory = malloc(io->mb_w + 2 * uv_width);
- if (p->memory == NULL) {
- return 0; // memory error.
- }
- p->tmp_y = (uint8_t*)p->memory;
- p->tmp_u = p->tmp_y + io->mb_w;
- p->tmp_v = p->tmp_u + uv_width;
- p->emit = EmitFancyRGB;
- WebPInitUpsamplers();
- }
-#endif
- } else {
- p->emit = EmitYUV;
- }
- if (is_alpha) { // need transparency output
- if (WebPIsPremultipliedMode(colorspace)) WebPInitPremultiply();
- p->emit_alpha =
- (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
- EmitAlphaRGBA4444
- : is_rgb ? EmitAlphaRGB
- : EmitAlphaYUV;
- }
- }
-
- if (is_rgb) {
- VP8YUVInit();
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static int CustomPut(const VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- const int mb_w = io->mb_w;
- const int mb_h = io->mb_h;
- int num_lines_out;
- assert(!(io->mb_y & 1));
-
- if (mb_w <= 0 || mb_h <= 0) {
- return 0;
- }
- num_lines_out = p->emit(io, p);
- if (p->emit_alpha) {
- p->emit_alpha(io, p);
- }
- p->last_y += num_lines_out;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static void CustomTeardown(const VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- free(p->memory);
- p->memory = NULL;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point
-
-void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
- io->put = CustomPut;
- io->setup = CustomSetup;
- io->teardown = CustomTeardown;
- io->opaque = params;
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/layer.c b/drivers/webpold/dec/layer.c
deleted file mode 100644
index a3a5bdcfe8..0000000000
--- a/drivers/webpold/dec/layer.c
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2011 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/
-// -----------------------------------------------------------------------------
-//
-// Enhancement layer (for YUV444/422)
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8i.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-
-int VP8DecodeLayer(VP8Decoder* const dec) {
- assert(dec);
- assert(dec->layer_data_size_ > 0);
- (void)dec;
-
- // TODO: handle enhancement layer here.
-
- return 1;
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/quant.c b/drivers/webpold/dec/quant.c
deleted file mode 100644
index d54097af0d..0000000000
--- a/drivers/webpold/dec/quant.c
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// Quantizer initialization
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8i.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-static WEBP_INLINE int clip(int v, int M) {
- return v < 0 ? 0 : v > M ? M : v;
-}
-
-// Paragraph 14.1
-static const uint8_t kDcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 10,
- 11, 12, 13, 14, 15, 16, 17, 17,
- 18, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 25, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 76, 77, 78, 79, 80, 81,
- 82, 83, 84, 85, 86, 87, 88, 89,
- 91, 93, 95, 96, 98, 100, 101, 102,
- 104, 106, 108, 110, 112, 114, 116, 118,
- 122, 124, 126, 128, 130, 132, 134, 136,
- 138, 140, 143, 145, 148, 151, 154, 157
-};
-
-static const uint16_t kAcTable[128] = {
- 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 60,
- 62, 64, 66, 68, 70, 72, 74, 76,
- 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100, 102, 104, 106, 108,
- 110, 112, 114, 116, 119, 122, 125, 128,
- 131, 134, 137, 140, 143, 146, 149, 152,
- 155, 158, 161, 164, 167, 170, 173, 177,
- 181, 185, 189, 193, 197, 201, 205, 209,
- 213, 217, 221, 225, 229, 234, 239, 245,
- 249, 254, 259, 264, 269, 274, 279, 284
-};
-
-//------------------------------------------------------------------------------
-// Paragraph 9.6
-
-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 VP8SegmentHeader* const hdr = &dec->segment_hdr_;
- int i;
-
- for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
- int q;
- if (hdr->use_segment_) {
- q = hdr->quantizer_[i];
- if (!hdr->absolute_delta_) {
- q += base_q0;
- }
- } else {
- if (i > 0) {
- dec->dqm_[i] = dec->dqm_[0];
- continue;
- } else {
- q = base_q0;
- }
- }
- {
- VP8QuantMatrix* const m = &dec->dqm_[i];
- m->y1_mat_[0] = kDcTable[clip(q + dqy1_dc, 127)];
- m->y1_mat_[1] = kAcTable[clip(q + 0, 127)];
-
- m->y2_mat_[0] = kDcTable[clip(q + dqy2_dc, 127)] * 2;
- // For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
- // The smallest precision for that is '(x*6349) >> 12' but 16 is a good
- // word size.
- m->y2_mat_[1] = (kAcTable[clip(q + dqy2_ac, 127)] * 101581) >> 16;
- if (m->y2_mat_[1] < 8) m->y2_mat_[1] = 8;
-
- m->uv_mat_[0] = kDcTable[clip(q + dquv_dc, 117)];
- m->uv_mat_[1] = kAcTable[clip(q + dquv_ac, 127)];
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/tree.c b/drivers/webpold/dec/tree.c
deleted file mode 100644
index 82484e4c55..0000000000
--- a/drivers/webpold/dec/tree.c
+++ /dev/null
@@ -1,589 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// Coding trees and probas
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "vp8i.h"
-
-#define USE_GENERIC_TREE
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#ifdef USE_GENERIC_TREE
-static const int8_t kYModesIntra4[18] = {
- -B_DC_PRED, 1,
- -B_TM_PRED, 2,
- -B_VE_PRED, 3,
- 4, 6,
- -B_HE_PRED, 5,
- -B_RD_PRED, -B_VR_PRED,
- -B_LD_PRED, 7,
- -B_VL_PRED, 8,
- -B_HD_PRED, -B_HU_PRED
-};
-#endif
-
-#ifndef ONLY_KEYFRAME_CODE
-
-// inter prediction modes
-enum {
- LEFT4 = 0, ABOVE4 = 1, ZERO4 = 2, NEW4 = 3,
- NEARESTMV, NEARMV, ZEROMV, NEWMV, SPLITMV };
-
-static const int8_t kYModesInter[8] = {
- -DC_PRED, 1,
- 2, 3,
- -V_PRED, -H_PRED,
- -TM_PRED, -B_PRED
-};
-
-static const int8_t kMBSplit[6] = {
- -3, 1,
- -2, 2,
- -0, -1
-};
-
-static const int8_t kMVRef[8] = {
- -ZEROMV, 1,
- -NEARESTMV, 2,
- -NEARMV, 3,
- -NEWMV, -SPLITMV
-};
-
-static const int8_t kMVRef4[6] = {
- -LEFT4, 1,
- -ABOVE4, 2,
- -ZERO4, -NEW4
-};
-#endif
-
-//------------------------------------------------------------------------------
-// Default probabilities
-
-// Inter
-#ifndef ONLY_KEYFRAME_CODE
-static const uint8_t kYModeProbaInter0[4] = { 112, 86, 140, 37 };
-static const uint8_t kUVModeProbaInter0[3] = { 162, 101, 204 };
-static const uint8_t kMVProba0[2][NUM_MV_PROBAS] = {
- { 162, 128, 225, 146, 172, 147, 214, 39,
- 156, 128, 129, 132, 75, 145, 178, 206,
- 239, 254, 254 },
- { 164, 128, 204, 170, 119, 235, 140, 230,
- 228, 128, 130, 130, 74, 148, 180, 203,
- 236, 254, 254 }
-};
-#endif
-
-// Paragraph 13.5
-static const uint8_t
- CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- // genereated using vp8_default_coef_probs() in entropy.c:129
- { { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 },
- { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 },
- { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }
- },
- { { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 },
- { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 },
- { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 },
- },
- { { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 },
- { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 },
- { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 },
- },
- { { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 },
- { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 },
- { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }
- },
- { { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 },
- { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 },
- { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }
- },
- { { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 },
- { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 },
- { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 },
- { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 },
- { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }
- },
- { { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 },
- { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 },
- { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }
- },
- { { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 },
- { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 },
- { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }
- },
- { { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 },
- { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 },
- { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }
- },
- { { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 },
- { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 },
- { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }
- },
- { { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 },
- { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 },
- { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }
- },
- { { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 },
- { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 },
- { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }
- },
- { { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }
- }
- },
- { { { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 },
- { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 },
- { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }
- },
- { { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 },
- { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 },
- { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }
- },
- { { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 },
- { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 },
- { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }
- },
- { { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 },
- { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 },
- { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 },
- { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- },
- { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- },
- { { { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 },
- { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 },
- { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }
- },
- { { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 },
- { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 },
- { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }
- },
- { { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 },
- { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 },
- { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }
- },
- { { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 },
- { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 },
- { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }
- },
- { { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 },
- { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 },
- { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }
- },
- { { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 },
- { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 },
- { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }
- },
- { { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 },
- { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 },
- { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }
- },
- { { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 },
- { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }
- }
- }
-};
-
-// Paragraph 11.5
-static const uint8_t kBModesProba[NUM_BMODES][NUM_BMODES][NUM_BMODES - 1] = {
- { { 231, 120, 48, 89, 115, 113, 120, 152, 112 },
- { 152, 179, 64, 126, 170, 118, 46, 70, 95 },
- { 175, 69, 143, 80, 85, 82, 72, 155, 103 },
- { 56, 58, 10, 171, 218, 189, 17, 13, 152 },
- { 114, 26, 17, 163, 44, 195, 21, 10, 173 },
- { 121, 24, 80, 195, 26, 62, 44, 64, 85 },
- { 144, 71, 10, 38, 171, 213, 144, 34, 26 },
- { 170, 46, 55, 19, 136, 160, 33, 206, 71 },
- { 63, 20, 8, 114, 114, 208, 12, 9, 226 },
- { 81, 40, 11, 96, 182, 84, 29, 16, 36 } },
- { { 134, 183, 89, 137, 98, 101, 106, 165, 148 },
- { 72, 187, 100, 130, 157, 111, 32, 75, 80 },
- { 66, 102, 167, 99, 74, 62, 40, 234, 128 },
- { 41, 53, 9, 178, 241, 141, 26, 8, 107 },
- { 74, 43, 26, 146, 73, 166, 49, 23, 157 },
- { 65, 38, 105, 160, 51, 52, 31, 115, 128 },
- { 104, 79, 12, 27, 217, 255, 87, 17, 7 },
- { 87, 68, 71, 44, 114, 51, 15, 186, 23 },
- { 47, 41, 14, 110, 182, 183, 21, 17, 194 },
- { 66, 45, 25, 102, 197, 189, 23, 18, 22 } },
- { { 88, 88, 147, 150, 42, 46, 45, 196, 205 },
- { 43, 97, 183, 117, 85, 38, 35, 179, 61 },
- { 39, 53, 200, 87, 26, 21, 43, 232, 171 },
- { 56, 34, 51, 104, 114, 102, 29, 93, 77 },
- { 39, 28, 85, 171, 58, 165, 90, 98, 64 },
- { 34, 22, 116, 206, 23, 34, 43, 166, 73 },
- { 107, 54, 32, 26, 51, 1, 81, 43, 31 },
- { 68, 25, 106, 22, 64, 171, 36, 225, 114 },
- { 34, 19, 21, 102, 132, 188, 16, 76, 124 },
- { 62, 18, 78, 95, 85, 57, 50, 48, 51 } },
- { { 193, 101, 35, 159, 215, 111, 89, 46, 111 },
- { 60, 148, 31, 172, 219, 228, 21, 18, 111 },
- { 112, 113, 77, 85, 179, 255, 38, 120, 114 },
- { 40, 42, 1, 196, 245, 209, 10, 25, 109 },
- { 88, 43, 29, 140, 166, 213, 37, 43, 154 },
- { 61, 63, 30, 155, 67, 45, 68, 1, 209 },
- { 100, 80, 8, 43, 154, 1, 51, 26, 71 },
- { 142, 78, 78, 16, 255, 128, 34, 197, 171 },
- { 41, 40, 5, 102, 211, 183, 4, 1, 221 },
- { 51, 50, 17, 168, 209, 192, 23, 25, 82 } },
- { { 138, 31, 36, 171, 27, 166, 38, 44, 229 },
- { 67, 87, 58, 169, 82, 115, 26, 59, 179 },
- { 63, 59, 90, 180, 59, 166, 93, 73, 154 },
- { 40, 40, 21, 116, 143, 209, 34, 39, 175 },
- { 47, 15, 16, 183, 34, 223, 49, 45, 183 },
- { 46, 17, 33, 183, 6, 98, 15, 32, 183 },
- { 57, 46, 22, 24, 128, 1, 54, 17, 37 },
- { 65, 32, 73, 115, 28, 128, 23, 128, 205 },
- { 40, 3, 9, 115, 51, 192, 18, 6, 223 },
- { 87, 37, 9, 115, 59, 77, 64, 21, 47 } },
- { { 104, 55, 44, 218, 9, 54, 53, 130, 226 },
- { 64, 90, 70, 205, 40, 41, 23, 26, 57 },
- { 54, 57, 112, 184, 5, 41, 38, 166, 213 },
- { 30, 34, 26, 133, 152, 116, 10, 32, 134 },
- { 39, 19, 53, 221, 26, 114, 32, 73, 255 },
- { 31, 9, 65, 234, 2, 15, 1, 118, 73 },
- { 75, 32, 12, 51, 192, 255, 160, 43, 51 },
- { 88, 31, 35, 67, 102, 85, 55, 186, 85 },
- { 56, 21, 23, 111, 59, 205, 45, 37, 192 },
- { 55, 38, 70, 124, 73, 102, 1, 34, 98 } },
- { { 125, 98, 42, 88, 104, 85, 117, 175, 82 },
- { 95, 84, 53, 89, 128, 100, 113, 101, 45 },
- { 75, 79, 123, 47, 51, 128, 81, 171, 1 },
- { 57, 17, 5, 71, 102, 57, 53, 41, 49 },
- { 38, 33, 13, 121, 57, 73, 26, 1, 85 },
- { 41, 10, 67, 138, 77, 110, 90, 47, 114 },
- { 115, 21, 2, 10, 102, 255, 166, 23, 6 },
- { 101, 29, 16, 10, 85, 128, 101, 196, 26 },
- { 57, 18, 10, 102, 102, 213, 34, 20, 43 },
- { 117, 20, 15, 36, 163, 128, 68, 1, 26 } },
- { { 102, 61, 71, 37, 34, 53, 31, 243, 192 },
- { 69, 60, 71, 38, 73, 119, 28, 222, 37 },
- { 68, 45, 128, 34, 1, 47, 11, 245, 171 },
- { 62, 17, 19, 70, 146, 85, 55, 62, 70 },
- { 37, 43, 37, 154, 100, 163, 85, 160, 1 },
- { 63, 9, 92, 136, 28, 64, 32, 201, 85 },
- { 75, 15, 9, 9, 64, 255, 184, 119, 16 },
- { 86, 6, 28, 5, 64, 255, 25, 248, 1 },
- { 56, 8, 17, 132, 137, 255, 55, 116, 128 },
- { 58, 15, 20, 82, 135, 57, 26, 121, 40 } },
- { { 164, 50, 31, 137, 154, 133, 25, 35, 218 },
- { 51, 103, 44, 131, 131, 123, 31, 6, 158 },
- { 86, 40, 64, 135, 148, 224, 45, 183, 128 },
- { 22, 26, 17, 131, 240, 154, 14, 1, 209 },
- { 45, 16, 21, 91, 64, 222, 7, 1, 197 },
- { 56, 21, 39, 155, 60, 138, 23, 102, 213 },
- { 83, 12, 13, 54, 192, 255, 68, 47, 28 },
- { 85, 26, 85, 85, 128, 128, 32, 146, 171 },
- { 18, 11, 7, 63, 144, 171, 4, 4, 246 },
- { 35, 27, 10, 146, 174, 171, 12, 26, 128 } },
- { { 190, 80, 35, 99, 180, 80, 126, 54, 45 },
- { 85, 126, 47, 87, 176, 51, 41, 20, 32 },
- { 101, 75, 128, 139, 118, 146, 116, 128, 85 },
- { 56, 41, 15, 176, 236, 85, 37, 9, 62 },
- { 71, 30, 17, 119, 118, 255, 17, 18, 138 },
- { 101, 38, 60, 138, 55, 70, 43, 26, 142 },
- { 146, 36, 19, 30, 171, 255, 97, 27, 20 },
- { 138, 45, 61, 62, 219, 1, 81, 188, 64 },
- { 32, 41, 20, 117, 151, 142, 20, 21, 163 },
- { 112, 19, 12, 61, 195, 128, 48, 4, 24 } }
-};
-
-void VP8ResetProba(VP8Proba* const proba) {
- memset(proba->segments_, 255u, sizeof(proba->segments_));
- memcpy(proba->coeffs_, CoeffsProba0, sizeof(CoeffsProba0));
-#ifndef ONLY_KEYFRAME_CODE
- memcpy(proba->mv_, kMVProba0, sizeof(kMVProba0));
- memcpy(proba->ymode_, kYModeProbaInter0, sizeof(kYModeProbaInter0));
- memcpy(proba->uvmode_, kUVModeProbaInter0, sizeof(kUVModeProbaInter0));
-#endif
-}
-
-void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec) {
- uint8_t* const top = dec->intra_t_ + 4 * dec->mb_x_;
- uint8_t* const left = dec->intra_l_;
- // Hardcoded 16x16 intra-mode decision tree.
- dec->is_i4x4_ = !VP8GetBit(br, 145); // decide for B_PRED first
- if (!dec->is_i4x4_) {
- const int ymode =
- VP8GetBit(br, 156) ? (VP8GetBit(br, 128) ? TM_PRED : H_PRED)
- : (VP8GetBit(br, 163) ? V_PRED : DC_PRED);
- dec->imodes_[0] = ymode;
- memset(top, ymode, 4 * sizeof(top[0]));
- memset(left, ymode, 4 * sizeof(left[0]));
- } else {
- uint8_t* modes = dec->imodes_;
- int y;
- for (y = 0; y < 4; ++y) {
- int ymode = left[y];
- int x;
- for (x = 0; x < 4; ++x) {
- const uint8_t* const prob = kBModesProba[top[x]][ymode];
-#ifdef USE_GENERIC_TREE
- // Generic tree-parsing
- int i = 0;
- do {
- i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
- } while (i > 0);
- 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
- top[x] = ymode;
- *modes++ = ymode;
- }
- left[y] = ymode;
- }
- }
- // Hardcoded UVMode decision tree
- dec->uvmode_ = !VP8GetBit(br, 142) ? DC_PRED
- : !VP8GetBit(br, 114) ? V_PRED
- : VP8GetBit(br, 183) ? TM_PRED : H_PRED;
-}
-
-//------------------------------------------------------------------------------
-// Paragraph 13
-
-static const uint8_t
- CoeffsUpdateProba[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 },
- { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }
- },
- { { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- },
- { { { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- },
- { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
- { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }
- }
- }
-};
-
-#ifndef ONLY_KEYFRAME_CODE
-static const uint8_t MVUpdateProba[2][NUM_MV_PROBAS] = {
- { 237, 246, 253, 253, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 250, 250,
- 252, 254, 254 },
- { 231, 243, 245, 253, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 251, 251,
- 254, 254, 254 }
-};
-#endif
-
-// Paragraph 9.9
-void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec) {
- VP8Proba* const proba = &dec->proba_;
- int t, b, c, p;
- for (t = 0; t < NUM_TYPES; ++t) {
- for (b = 0; b < NUM_BANDS; ++b) {
- for (c = 0; c < NUM_CTX; ++c) {
- for (p = 0; p < NUM_PROBAS; ++p) {
- if (VP8GetBit(br, CoeffsUpdateProba[t][b][c][p])) {
- proba->coeffs_[t][b][c][p] = VP8GetValue(br, 8);
- }
- }
- }
- }
- }
- dec->use_skip_proba_ = VP8Get(br);
- if (dec->use_skip_proba_) {
- dec->skip_p_ = VP8GetValue(br, 8);
- }
-#ifndef ONLY_KEYFRAME_CODE
- if (!dec->frm_hdr_.key_frame_) {
- int i;
- dec->intra_p_ = VP8GetValue(br, 8);
- dec->last_p_ = VP8GetValue(br, 8);
- dec->golden_p_ = VP8GetValue(br, 8);
- if (VP8Get(br)) { // update y-mode
- for (i = 0; i < 4; ++i) {
- proba->ymode_[i] = VP8GetValue(br, 8);
- }
- }
- if (VP8Get(br)) { // update uv-mode
- for (i = 0; i < 3; ++i) {
- proba->uvmode_[i] = VP8GetValue(br, 8);
- }
- }
- // update MV
- for (i = 0; i < 2; ++i) {
- int k;
- for (k = 0; k < NUM_MV_PROBAS; ++k) {
- if (VP8GetBit(br, MVUpdateProba[i][k])) {
- const int v = VP8GetValue(br, 7);
- proba->mv_[i][k] = v ? v << 1 : 1;
- }
- }
- }
- }
-#endif
-}
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/vp8.c b/drivers/webpold/dec/vp8.c
deleted file mode 100644
index b0ccfa2a06..0000000000
--- a/drivers/webpold/dec/vp8.c
+++ /dev/null
@@ -1,787 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "./webpi.h"
-#include "../utils/bit_reader.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-
-int WebPGetDecoderVersion(void) {
- return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
-}
-
-//------------------------------------------------------------------------------
-// VP8Decoder
-
-static void SetOk(VP8Decoder* const dec) {
- dec->status_ = VP8_STATUS_OK;
- dec->error_msg_ = "OK";
-}
-
-int VP8InitIoInternal(VP8Io* const io, int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // mismatch error
- }
- if (io != NULL) {
- memset(io, 0, sizeof(*io));
- }
- return 1;
-}
-
-VP8Decoder* VP8New(void) {
- VP8Decoder* const dec = (VP8Decoder*)calloc(1, sizeof(*dec));
- if (dec != NULL) {
- SetOk(dec);
- WebPWorkerInit(&dec->worker_);
- dec->ready_ = 0;
- dec->num_parts_ = 1;
- }
- return dec;
-}
-
-VP8StatusCode VP8Status(VP8Decoder* const dec) {
- if (!dec) return VP8_STATUS_INVALID_PARAM;
- return dec->status_;
-}
-
-const char* VP8StatusMessage(VP8Decoder* const dec) {
- if (dec == NULL) return "no object";
- if (!dec->error_msg_) return "OK";
- return dec->error_msg_;
-}
-
-void VP8Delete(VP8Decoder* const dec) {
- if (dec != NULL) {
- VP8Clear(dec);
- free(dec);
- }
-}
-
-int VP8SetError(VP8Decoder* const dec,
- VP8StatusCode error, const char* const msg) {
- // TODO This check would be unnecessary if alpha decompression was separated
- // from VP8ProcessRow/FinishRow. This avoids setting 'dec->status_' to
- // something other than VP8_STATUS_BITSTREAM_ERROR on alpha decompression
- // failure.
- if (dec->status_ == VP8_STATUS_OK) {
- dec->status_ = error;
- dec->error_msg_ = msg;
- dec->ready_ = 0;
- }
- return 0;
-}
-
-//------------------------------------------------------------------------------
-
-int VP8CheckSignature(const uint8_t* const data, size_t data_size) {
- return (data_size >= 3 &&
- data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a);
-}
-
-int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size,
- int* const width, int* const height) {
- if (data == NULL || data_size < VP8_FRAME_HEADER_SIZE) {
- return 0; // not enough data
- }
- // check signature
- if (!VP8CheckSignature(data + 3, data_size - 3)) {
- return 0; // Wrong signature.
- } else {
- const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16);
- const int key_frame = !(bits & 1);
- const int w = ((data[7] << 8) | data[6]) & 0x3fff;
- const int h = ((data[9] << 8) | data[8]) & 0x3fff;
-
- if (!key_frame) { // Not a keyframe.
- return 0;
- }
-
- if (((bits >> 1) & 7) > 3) {
- return 0; // unknown profile
- }
- if (!((bits >> 4) & 1)) {
- return 0; // first frame is invisible!
- }
- if (((bits >> 5)) >= chunk_size) { // partition_length
- return 0; // inconsistent size information.
- }
-
- if (width) {
- *width = w;
- }
- if (height) {
- *height = h;
- }
-
- return 1;
- }
-}
-
-//------------------------------------------------------------------------------
-// Header parsing
-
-static void ResetSegmentHeader(VP8SegmentHeader* const hdr) {
- assert(hdr != NULL);
- hdr->use_segment_ = 0;
- hdr->update_map_ = 0;
- hdr->absolute_delta_ = 1;
- memset(hdr->quantizer_, 0, sizeof(hdr->quantizer_));
- memset(hdr->filter_strength_, 0, sizeof(hdr->filter_strength_));
-}
-
-// Paragraph 9.3
-static int ParseSegmentHeader(VP8BitReader* br,
- VP8SegmentHeader* hdr, VP8Proba* proba) {
- assert(br != NULL);
- assert(hdr != NULL);
- hdr->use_segment_ = VP8Get(br);
- if (hdr->use_segment_) {
- hdr->update_map_ = VP8Get(br);
- if (VP8Get(br)) { // update data
- int s;
- hdr->absolute_delta_ = VP8Get(br);
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0;
- }
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 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;
- }
- }
- } else {
- hdr->update_map_ = 0;
- }
- return !br->eof_;
-}
-
-// Paragraph 9.5
-// This function returns VP8_STATUS_SUSPENDED if we don't have all the
-// necessary data in 'buf'.
-// This case is not necessarily an error (for incremental decoding).
-// Still, no bitreader is ever initialized to make it possible to read
-// unavailable memory.
-// If we don't even have the partitions' sizes, than VP8_STATUS_NOT_ENOUGH_DATA
-// is returned, and this is an unrecoverable error.
-// If the partitions were positioned ok, VP8_STATUS_OK is returned.
-static VP8StatusCode ParsePartitions(VP8Decoder* const dec,
- const uint8_t* buf, size_t size) {
- VP8BitReader* const br = &dec->br_;
- const uint8_t* sz = buf;
- const uint8_t* buf_end = buf + size;
- const uint8_t* part_start;
- int last_part;
- int p;
-
- dec->num_parts_ = 1 << VP8GetValue(br, 2);
- last_part = dec->num_parts_ - 1;
- part_start = buf + last_part * 3;
- if (buf_end < part_start) {
- // we can't even read the sizes with sz[]! That's a failure.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- for (p = 0; p < last_part; ++p) {
- const uint32_t psize = sz[0] | (sz[1] << 8) | (sz[2] << 16);
- const uint8_t* part_end = part_start + psize;
- if (part_end > buf_end) part_end = buf_end;
- VP8InitBitReader(dec->parts_ + p, part_start, part_end);
- part_start = part_end;
- sz += 3;
- }
- VP8InitBitReader(dec->parts_ + last_part, part_start, buf_end);
- return (part_start < buf_end) ? VP8_STATUS_OK :
- VP8_STATUS_SUSPENDED; // Init is ok, but there's not enough data
-}
-
-// 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);
- if (hdr->use_lf_delta_) {
- if (VP8Get(br)) { // 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);
- }
- }
- for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) {
- if (VP8Get(br)) {
- hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6);
- }
- }
- }
- }
- dec->filter_type_ = (hdr->level_ == 0) ? 0 : hdr->simple_ ? 1 : 2;
- if (dec->filter_type_ > 0) { // precompute filter levels per segment
- if (dec->segment_hdr_.use_segment_) {
- int s;
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- int strength = dec->segment_hdr_.filter_strength_[s];
- if (!dec->segment_hdr_.absolute_delta_) {
- strength += hdr->level_;
- }
- dec->filter_levels_[s] = strength;
- }
- } else {
- dec->filter_levels_[0] = hdr->level_;
- }
- }
- return !br->eof_;
-}
-
-// Topmost call
-int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) {
- const uint8_t* buf;
- size_t buf_size;
- VP8FrameHeader* frm_hdr;
- VP8PictureHeader* pic_hdr;
- VP8BitReader* br;
- VP8StatusCode status;
- WebPHeaderStructure headers;
-
- if (dec == NULL) {
- return 0;
- }
- SetOk(dec);
- if (io == NULL) {
- return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
- "null VP8Io passed to VP8GetHeaders()");
- }
-
- // Process Pre-VP8 chunks.
- headers.data = io->data;
- headers.data_size = io->data_size;
- status = WebPParseHeaders(&headers);
- if (status != VP8_STATUS_OK) {
- return VP8SetError(dec, status, "Incorrect/incomplete header.");
- }
- if (headers.is_lossless) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Unexpected lossless format encountered.");
- }
-
- if (dec->alpha_data_ == NULL) {
- assert(dec->alpha_data_size_ == 0);
- // We have NOT set alpha data yet. Set it now.
- // (This is to ensure that dec->alpha_data_ is NOT reset to NULL if
- // WebPParseHeaders() is called more than once, as in incremental decoding
- // case.)
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
- }
-
- // Process the VP8 frame header.
- buf = headers.data + headers.offset;
- buf_size = headers.data_size - headers.offset;
- assert(headers.data_size >= headers.offset); // WebPParseHeaders' guarantee
- if (buf_size < 4) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "Truncated header.");
- }
-
- // Paragraph 9.1
- {
- const uint32_t bits = buf[0] | (buf[1] << 8) | (buf[2] << 16);
- frm_hdr = &dec->frm_hdr_;
- frm_hdr->key_frame_ = !(bits & 1);
- frm_hdr->profile_ = (bits >> 1) & 7;
- frm_hdr->show_ = (bits >> 4) & 1;
- frm_hdr->partition_length_ = (bits >> 5);
- if (frm_hdr->profile_ > 3)
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Incorrect keyframe parameters.");
- if (!frm_hdr->show_)
- return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
- "Frame not displayable.");
- buf += 3;
- buf_size -= 3;
- }
-
- pic_hdr = &dec->pic_hdr_;
- if (frm_hdr->key_frame_) {
- // Paragraph 9.2
- if (buf_size < 7) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "cannot parse picture header");
- }
- if (!VP8CheckSignature(buf, buf_size)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "Bad code word");
- }
- pic_hdr->width_ = ((buf[4] << 8) | buf[3]) & 0x3fff;
- pic_hdr->xscale_ = buf[4] >> 6; // ratio: 1, 5/4 5/3 or 2
- pic_hdr->height_ = ((buf[6] << 8) | buf[5]) & 0x3fff;
- pic_hdr->yscale_ = buf[6] >> 6;
- buf += 7;
- buf_size -= 7;
-
- dec->mb_w_ = (pic_hdr->width_ + 15) >> 4;
- dec->mb_h_ = (pic_hdr->height_ + 15) >> 4;
- // Setup default output area (can be later modified during io->setup())
- io->width = pic_hdr->width_;
- io->height = pic_hdr->height_;
- io->use_scaling = 0;
- io->use_cropping = 0;
- io->crop_top = 0;
- io->crop_left = 0;
- io->crop_right = io->width;
- io->crop_bottom = io->height;
- io->mb_w = io->width; // sanity check
- io->mb_h = io->height; // ditto
-
- VP8ResetProba(&dec->proba_);
- ResetSegmentHeader(&dec->segment_hdr_);
- dec->segment_ = 0; // default for intra
- }
-
- // Check if we have all the partition #0 available, and initialize dec->br_
- // to read this partition (and this partition only).
- if (frm_hdr->partition_length_ > buf_size) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "bad partition length");
- }
-
- br = &dec->br_;
- VP8InitBitReader(br, buf, buf + frm_hdr->partition_length_);
- buf += frm_hdr->partition_length_;
- buf_size -= frm_hdr->partition_length_;
-
- if (frm_hdr->key_frame_) {
- pic_hdr->colorspace_ = VP8Get(br);
- pic_hdr->clamp_type_ = VP8Get(br);
- }
- if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "cannot parse segment header");
- }
- // Filter specs
- if (!ParseFilterHeader(br, dec)) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "cannot parse filter header");
- }
- status = ParsePartitions(dec, buf, buf_size);
- if (status != VP8_STATUS_OK) {
- return VP8SetError(dec, status, "cannot parse partitions");
- }
-
- // quantizer change
- VP8ParseQuant(dec);
-
- // Frame buffer marking
- if (!frm_hdr->key_frame_) {
- // Paragraph 9.7
-#ifndef ONLY_KEYFRAME_CODE
- dec->buffer_flags_ = VP8Get(br) << 0; // update golden
- dec->buffer_flags_ |= VP8Get(br) << 1; // update alt ref
- if (!(dec->buffer_flags_ & 1)) {
- dec->buffer_flags_ |= VP8GetValue(br, 2) << 2;
- }
- if (!(dec->buffer_flags_ & 2)) {
- dec->buffer_flags_ |= VP8GetValue(br, 2) << 4;
- }
- dec->buffer_flags_ |= VP8Get(br) << 6; // sign bias golden
- dec->buffer_flags_ |= VP8Get(br) << 7; // sign bias alt ref
-#else
- return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
- "Not a key frame.");
-#endif
- } else {
- dec->buffer_flags_ = 0x003 | 0x100;
- }
-
- // Paragraph 9.8
-#ifndef ONLY_KEYFRAME_CODE
- dec->update_proba_ = VP8Get(br);
- if (!dec->update_proba_) { // save for later restore
- dec->proba_saved_ = dec->proba_;
- }
- dec->buffer_flags_ &= 1 << 8;
- dec->buffer_flags_ |=
- (frm_hdr->key_frame_ || VP8Get(br)) << 8; // refresh last frame
-#else
- VP8Get(br); // just ignore the value of update_proba_
-#endif
-
- VP8ParseProba(br, dec);
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- // Extensions
- if (dec->pic_hdr_.colorspace_) {
- const size_t kTrailerSize = 8;
- const uint8_t kTrailerMarker = 0x01;
- const uint8_t* ext_buf = buf - kTrailerSize;
- size_t size;
-
- if (frm_hdr->partition_length_ < kTrailerSize ||
- ext_buf[kTrailerSize - 1] != kTrailerMarker) {
- return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR,
- "RIFF: Inconsistent extra information.");
- }
-
- // Layer
- size = (ext_buf[0] << 0) | (ext_buf[1] << 8) | (ext_buf[2] << 16);
- dec->layer_data_size_ = size;
- dec->layer_data_ = NULL; // will be set later
- dec->layer_colorspace_ = ext_buf[3];
- }
-#endif
-
- // sanitized state
- dec->ready_ = 1;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Residual decoding (Paragraph 13.2 / 13.3)
-
-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
-};
-
-static const uint8_t kCat3[] = { 173, 148, 140, 0 };
-static const uint8_t kCat4[] = { 176, 155, 140, 135, 0 };
-static const uint8_t kCat5[] = { 180, 157, 141, 134, 130, 0 };
-static const uint8_t kCat6[] =
- { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 };
-static const uint8_t* const kCat3456[] = { kCat3, kCat4, kCat5, kCat6 };
-static const uint8_t kZigzag[16] = {
- 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
-};
-
-typedef const uint8_t (*ProbaArray)[NUM_CTX][NUM_PROBAS]; // for const-casting
-
-// Returns the position of the last non-zero coeff plus one
-// (and 0 if there's no coeff at all)
-static int GetCoeffs(VP8BitReader* const br, ProbaArray prob,
- int ctx, const quant_t dq, int n, int16_t* out) {
- // n is either 0 or 1 here. kBands[n] is not necessary for extracting '*p'.
- const uint8_t* p = prob[n][ctx];
- if (!VP8GetBit(br, p[0])) { // first EOB is more a 'CBP' bit.
- return 0;
- }
- while (1) {
- ++n;
- if (!VP8GetBit(br, p[1])) {
- p = prob[kBands[n]][0];
- } else { // non zero coeff
- int v, j;
- if (!VP8GetBit(br, p[2])) {
- p = prob[kBands[n]][1];
- v = 1;
- } else {
- if (!VP8GetBit(br, p[3])) {
- if (!VP8GetBit(br, p[4])) {
- v = 2;
- } else {
- v = 3 + VP8GetBit(br, p[5]);
- }
- } else {
- if (!VP8GetBit(br, p[6])) {
- if (!VP8GetBit(br, p[7])) {
- v = 5 + VP8GetBit(br, 159);
- } else {
- v = 7 + 2 * VP8GetBit(br, 165);
- v += VP8GetBit(br, 145);
- }
- } else {
- const uint8_t* tab;
- const int bit1 = VP8GetBit(br, p[8]);
- const int bit0 = VP8GetBit(br, p[9 + bit1]);
- const int cat = 2 * bit1 + bit0;
- v = 0;
- for (tab = kCat3456[cat]; *tab; ++tab) {
- v += v + VP8GetBit(br, *tab);
- }
- v += 3 + (8 << cat);
- }
- }
- p = prob[kBands[n]][2];
- }
- j = kZigzag[n - 1];
- out[j] = VP8GetSigned(br, v) * dq[j > 0];
- if (n == 16 || !VP8GetBit(br, p[0])) { // EOB
- return n;
- }
- }
- if (n == 16) {
- return 16;
- }
- }
-}
-
-// Alias-safe way of converting 4bytes to 32bits.
-typedef union {
- uint8_t i8[4];
- uint32_t i32;
-} PackedNz;
-
-// Table to unpack four bits into four bytes
-static const PackedNz kUnpackTab[16] = {
- {{0, 0, 0, 0}}, {{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{1, 1, 0, 0}},
- {{0, 0, 1, 0}}, {{1, 0, 1, 0}}, {{0, 1, 1, 0}}, {{1, 1, 1, 0}},
- {{0, 0, 0, 1}}, {{1, 0, 0, 1}}, {{0, 1, 0, 1}}, {{1, 1, 0, 1}},
- {{0, 0, 1, 1}}, {{1, 0, 1, 1}}, {{0, 1, 1, 1}}, {{1, 1, 1, 1}} };
-
-// Macro to pack four LSB of four bytes into four bits.
-#if defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || \
- defined(__BIG_ENDIAN__)
-#define PACK_CST 0x08040201U
-#else
-#define PACK_CST 0x01020408U
-#endif
-#define PACK(X, S) ((((X).i32 * PACK_CST) & 0xff000000) >> (S))
-
-static void ParseResiduals(VP8Decoder* const dec,
- VP8MB* const mb, VP8BitReader* const token_br) {
- int out_t_nz, out_l_nz, first;
- ProbaArray ac_prob;
- const VP8QuantMatrix* q = &dec->dqm_[dec->segment_];
- int16_t* dst = dec->coeffs_;
- VP8MB* const left_mb = dec->mb_info_ - 1;
- PackedNz nz_ac, nz_dc;
- PackedNz tnz, lnz;
- uint32_t non_zero_ac = 0;
- uint32_t non_zero_dc = 0;
- int x, y, ch;
-
- nz_dc.i32 = nz_ac.i32 = 0;
- memset(dst, 0, 384 * sizeof(*dst));
- if (!dec->is_i4x4_) { // parse DC
- int16_t dc[16] = { 0 };
- const int ctx = mb->dc_nz_ + left_mb->dc_nz_;
- mb->dc_nz_ = left_mb->dc_nz_ =
- (GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[1],
- ctx, q->y2_mat_, 0, dc) > 0);
- first = 1;
- ac_prob = (ProbaArray)dec->proba_.coeffs_[0];
- VP8TransformWHT(dc, dst);
- } else {
- first = 0;
- ac_prob = (ProbaArray)dec->proba_.coeffs_[3];
- }
-
- tnz = kUnpackTab[mb->nz_ & 0xf];
- lnz = kUnpackTab[left_mb->nz_ & 0xf];
- for (y = 0; y < 4; ++y) {
- int l = lnz.i8[y];
- for (x = 0; x < 4; ++x) {
- const int ctx = l + tnz.i8[x];
- const int nz = GetCoeffs(token_br, ac_prob, ctx,
- q->y1_mat_, first, dst);
- tnz.i8[x] = l = (nz > 0);
- nz_dc.i8[x] = (dst[0] != 0);
- nz_ac.i8[x] = (nz > 1);
- dst += 16;
- }
- lnz.i8[y] = l;
- non_zero_dc |= PACK(nz_dc, 24 - y * 4);
- non_zero_ac |= PACK(nz_ac, 24 - y * 4);
- }
- out_t_nz = PACK(tnz, 24);
- out_l_nz = PACK(lnz, 24);
-
- tnz = kUnpackTab[mb->nz_ >> 4];
- lnz = kUnpackTab[left_mb->nz_ >> 4];
- for (ch = 0; ch < 4; ch += 2) {
- for (y = 0; y < 2; ++y) {
- int l = lnz.i8[ch + y];
- for (x = 0; x < 2; ++x) {
- const int ctx = l + tnz.i8[ch + x];
- const int nz =
- GetCoeffs(token_br, (ProbaArray)dec->proba_.coeffs_[2],
- ctx, q->uv_mat_, 0, dst);
- tnz.i8[ch + x] = l = (nz > 0);
- nz_dc.i8[y * 2 + x] = (dst[0] != 0);
- nz_ac.i8[y * 2 + x] = (nz > 1);
- dst += 16;
- }
- lnz.i8[ch + y] = l;
- }
- non_zero_dc |= PACK(nz_dc, 8 - ch * 2);
- non_zero_ac |= PACK(nz_ac, 8 - ch * 2);
- }
- out_t_nz |= PACK(tnz, 20);
- out_l_nz |= PACK(lnz, 20);
- mb->nz_ = out_t_nz;
- left_mb->nz_ = out_l_nz;
-
- dec->non_zero_ac_ = non_zero_ac;
- dec->non_zero_ = non_zero_ac | non_zero_dc;
- mb->skip_ = !dec->non_zero_;
-}
-#undef PACK
-
-//------------------------------------------------------------------------------
-// Main loop
-
-int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
- VP8BitReader* const br = &dec->br_;
- VP8MB* const left = dec->mb_info_ - 1;
- VP8MB* const info = dec->mb_info_ + dec->mb_x_;
-
- // Note: we don't save segment map (yet), as we don't expect
- // to decode more than 1 keyframe.
- if (dec->segment_hdr_.update_map_) {
- // Hardcoded tree parsing
- dec->segment_ = !VP8GetBit(br, dec->proba_.segments_[0]) ?
- VP8GetBit(br, dec->proba_.segments_[1]) :
- 2 + VP8GetBit(br, dec->proba_.segments_[2]);
- }
- info->skip_ = dec->use_skip_proba_ ? VP8GetBit(br, dec->skip_p_) : 0;
-
- VP8ParseIntraMode(br, dec);
- if (br->eof_) {
- return 0;
- }
-
- if (!info->skip_) {
- ParseResiduals(dec, info, token_br);
- } else {
- left->nz_ = info->nz_ = 0;
- if (!dec->is_i4x4_) {
- left->dc_nz_ = info->dc_nz_ = 0;
- }
- dec->non_zero_ = 0;
- dec->non_zero_ac_ = 0;
- }
-
- return (!token_br->eof_);
-}
-
-void VP8InitScanline(VP8Decoder* const dec) {
- VP8MB* const left = dec->mb_info_ - 1;
- left->nz_ = 0;
- left->dc_nz_ = 0;
- memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
- dec->filter_row_ =
- (dec->filter_type_ > 0) &&
- (dec->mb_y_ >= dec->tl_mb_y_) && (dec->mb_y_ <= dec->br_mb_y_);
-}
-
-static int ParseFrame(VP8Decoder* const dec, VP8Io* io) {
- for (dec->mb_y_ = 0; dec->mb_y_ < dec->br_mb_y_; ++dec->mb_y_) {
- VP8BitReader* const token_br =
- &dec->parts_[dec->mb_y_ & (dec->num_parts_ - 1)];
- VP8InitScanline(dec);
- for (dec->mb_x_ = 0; dec->mb_x_ < dec->mb_w_; dec->mb_x_++) {
- if (!VP8DecodeMB(dec, token_br)) {
- return VP8SetError(dec, VP8_STATUS_NOT_ENOUGH_DATA,
- "Premature end-of-file encountered.");
- }
- VP8ReconstructBlock(dec);
-
- // Store data and save block's filtering params
- VP8StoreBlock(dec);
- }
- if (!VP8ProcessRow(dec, io)) {
- return VP8SetError(dec, VP8_STATUS_USER_ABORT, "Output aborted.");
- }
- }
- if (dec->use_threads_ && !WebPWorkerSync(&dec->worker_)) {
- return 0;
- }
-
- // Finish
-#ifndef ONLY_KEYFRAME_CODE
- if (!dec->update_proba_) {
- dec->proba_ = dec->proba_saved_;
- }
-#endif
-
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- if (dec->layer_data_size_ > 0) {
- if (!VP8DecodeLayer(dec)) {
- return 0;
- }
- }
-#endif
-
- return 1;
-}
-
-// Main entry point
-int VP8Decode(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 0;
- if (dec == NULL) {
- return 0;
- }
- if (io == NULL) {
- return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
- "NULL VP8Io parameter in VP8Decode().");
- }
-
- if (!dec->ready_) {
- if (!VP8GetHeaders(dec, io)) {
- return 0;
- }
- }
- assert(dec->ready_);
-
- // Finish setting up the decoding parameter. Will call io->setup().
- ok = (VP8EnterCritical(dec, io) == VP8_STATUS_OK);
- if (ok) { // good to go.
- // Will allocate memory and prepare everything.
- if (ok) ok = VP8InitFrame(dec, io);
-
- // Main decoding loop
- if (ok) ok = ParseFrame(dec, io);
-
- // Exit.
- ok &= VP8ExitCritical(dec, io);
- }
-
- if (!ok) {
- VP8Clear(dec);
- return 0;
- }
-
- dec->ready_ = 0;
- return ok;
-}
-
-void VP8Clear(VP8Decoder* const dec) {
- if (dec == NULL) {
- return;
- }
- if (dec->use_threads_) {
- WebPWorkerEnd(&dec->worker_);
- }
- if (dec->mem_) {
- free(dec->mem_);
- }
- dec->mem_ = NULL;
- dec->mem_size_ = 0;
- memset(&dec->br_, 0, sizeof(dec->br_));
- dec->ready_ = 0;
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/vp8i.h b/drivers/webpold/dec/vp8i.h
deleted file mode 100644
index 4382edfd8e..0000000000
--- a/drivers/webpold/dec/vp8i.h
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// VP8 decoder: internal header.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_DEC_VP8I_H_
-#define WEBP_DEC_VP8I_H_
-
-#include <string.h> // for memcpy()
-#include "./vp8li.h"
-#include "../utils/bit_reader.h"
-#include "../utils/thread.h"
-#include "../dsp/dsp.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Various defines and enums
-
-// version numbers
-#define DEC_MAJ_VERSION 0
-#define DEC_MIN_VERSION 2
-#define DEC_REV_VERSION 0
-
-#define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames
-
-// intra prediction modes
-enum { B_DC_PRED = 0, // 4x4 modes
- B_TM_PRED,
- B_VE_PRED,
- B_HE_PRED,
- B_RD_PRED,
- B_VR_PRED,
- B_LD_PRED,
- B_VL_PRED,
- B_HD_PRED,
- B_HU_PRED,
- NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10
-
- // Luma16 or UV modes
- DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED,
- H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED,
- B_PRED = NUM_BMODES, // refined I4x4 mode
-
- // special modes
- B_DC_PRED_NOTOP = 4,
- B_DC_PRED_NOLEFT = 5,
- B_DC_PRED_NOTOPLEFT = 6,
- NUM_B_DC_MODES = 7 };
-
-enum { MB_FEATURE_TREE_PROBS = 3,
- NUM_MB_SEGMENTS = 4,
- NUM_REF_LF_DELTAS = 4,
- NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT
- MAX_NUM_PARTITIONS = 8,
- // Probabilities
- NUM_TYPES = 4,
- NUM_BANDS = 8,
- NUM_CTX = 3,
- NUM_PROBAS = 11,
- NUM_MV_PROBAS = 19 };
-
-// YUV-cache parameters.
-// Constraints are: We need to store one 16x16 block of luma samples (y),
-// and two 8x8 chroma blocks (u/v). These are better be 16-bytes aligned,
-// in order to be SIMD-friendly. We also need to store the top, left and
-// top-left samples (from previously decoded blocks), along with four
-// extra top-right samples for luma (intra4x4 prediction only).
-// One possible layout is, using 32 * (17 + 9) bytes:
-//
-// .+------ <- only 1 pixel high
-// .|yyyyt.
-// .|yyyyt.
-// .|yyyyt.
-// .|yyyy..
-// .+--.+-- <- only 1 pixel high
-// .|uu.|vv
-// .|uu.|vv
-//
-// Every character is a 4x4 block, with legend:
-// '.' = unused
-// 'y' = y-samples 'u' = u-samples 'v' = u-samples
-// '|' = left sample, '-' = top sample, '+' = top-left sample
-// 't' = extra top-right sample for 4x4 modes
-// With this layout, BPS (=Bytes Per Scan-line) is one cacheline size.
-#define BPS 32 // this is the common stride used by yuv[]
-#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)
-
-//------------------------------------------------------------------------------
-// Headers
-
-typedef struct {
- uint8_t key_frame_;
- uint8_t profile_;
- uint8_t show_;
- uint32_t partition_length_;
-} VP8FrameHeader;
-
-typedef struct {
- uint16_t width_;
- uint16_t height_;
- uint8_t xscale_;
- uint8_t yscale_;
- uint8_t colorspace_; // 0 = YCbCr
- uint8_t clamp_type_;
-} VP8PictureHeader;
-
-// segment features
-typedef struct {
- int use_segment_;
- int update_map_; // whether to update the segment map or not
- int absolute_delta_; // absolute or delta values for quantizer and filter
- int8_t quantizer_[NUM_MB_SEGMENTS]; // quantization changes
- int8_t filter_strength_[NUM_MB_SEGMENTS]; // filter strength for segments
-} VP8SegmentHeader;
-
-// Struct collecting all frame-persistent probabilities.
-typedef struct {
- uint8_t segments_[MB_FEATURE_TREE_PROBS];
- // Type: 0:Intra16-AC 1:Intra16-DC 2:Chroma 3:Intra4
- uint8_t coeffs_[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS];
-#ifndef ONLY_KEYFRAME_CODE
- uint8_t ymode_[4], uvmode_[3];
- uint8_t mv_[2][NUM_MV_PROBAS];
-#endif
-} VP8Proba;
-
-// Filter parameters
-typedef struct {
- int simple_; // 0=complex, 1=simple
- int level_; // [0..63]
- int sharpness_; // [0..7]
- int use_lf_delta_;
- int ref_lf_delta_[NUM_REF_LF_DELTAS];
- int mode_lf_delta_[NUM_MODE_LF_DELTAS];
-} VP8FilterHeader;
-
-//------------------------------------------------------------------------------
-// Informations about the macroblocks.
-
-typedef struct { // filter specs
- unsigned int f_level_:6; // filter strength: 0..63
- unsigned int f_ilevel_:6; // inner limit: 1..63
- unsigned int f_inner_:1; // do inner filtering?
-} VP8FInfo;
-
-typedef struct { // used for syntax-parsing
- unsigned int nz_; // non-zero AC/DC coeffs
- unsigned int dc_nz_:1; // non-zero DC coeffs
- unsigned int skip_:1; // block type
-} VP8MB;
-
-// Dequantization matrices
-typedef int quant_t[2]; // [DC / AC]. Can be 'uint16_t[2]' too (~slower).
-typedef struct {
- quant_t y1_mat_, y2_mat_, uv_mat_;
-} VP8QuantMatrix;
-
-// Persistent information needed by the parallel processing
-typedef struct {
- int id_; // cache row to process (in [0..2])
- int mb_y_; // macroblock position of the row
- int filter_row_; // true if row-filtering is needed
- VP8FInfo* f_info_; // filter strengths
- VP8Io io_; // copy of the VP8Io to pass to put()
-} VP8ThreadContext;
-
-//------------------------------------------------------------------------------
-// VP8Decoder: the main opaque structure handed over to user
-
-struct VP8Decoder {
- VP8StatusCode status_;
- int ready_; // true if ready to decode a picture with VP8Decode()
- const char* error_msg_; // set when status_ is not OK.
-
- // Main data source
- VP8BitReader br_;
-
- // headers
- VP8FrameHeader frm_hdr_;
- VP8PictureHeader pic_hdr_;
- VP8FilterHeader filter_hdr_;
- VP8SegmentHeader segment_hdr_;
-
- // Worker
- WebPWorker worker_;
- int use_threads_; // use multi-thread
- int cache_id_; // current cache row
- int num_caches_; // number of cached rows of 16 pixels (1, 2 or 3)
- VP8ThreadContext thread_ctx_; // Thread context
-
- // dimension, in macroblock units.
- int mb_w_, mb_h_;
-
- // Macroblock to process/filter, depending on cropping and filter_type.
- int tl_mb_x_, tl_mb_y_; // top-left MB that must be in-loop filtered
- int br_mb_x_, br_mb_y_; // last bottom-right MB that must be decoded
-
- // number of partitions.
- int num_parts_;
- // per-partition boolean decoders.
- VP8BitReader parts_[MAX_NUM_PARTITIONS];
-
- // buffer refresh flags
- // bit 0: refresh Gold, bit 1: refresh Alt
- // bit 2-3: copy to Gold, bit 4-5: copy to Alt
- // bit 6: Gold sign bias, bit 7: Alt sign bias
- // bit 8: refresh last frame
- uint32_t buffer_flags_;
-
- // dequantization (one set of DC/AC dequant factor per segment)
- VP8QuantMatrix dqm_[NUM_MB_SEGMENTS];
-
- // probabilities
- VP8Proba proba_;
- int use_skip_proba_;
- uint8_t skip_p_;
-#ifndef ONLY_KEYFRAME_CODE
- uint8_t intra_p_, last_p_, golden_p_;
- VP8Proba proba_saved_;
- int update_proba_;
-#endif
-
- // Boundary data cache and persistent buffers.
- uint8_t* intra_t_; // top intra modes values: 4 * mb_w_
- uint8_t intra_l_[4]; // left intra modes values
- uint8_t* y_t_; // top luma samples: 16 * mb_w_
- uint8_t* u_t_, *v_t_; // top u/v samples: 8 * mb_w_ each
-
- VP8MB* mb_info_; // contextual macroblock info (mb_w_ + 1)
- VP8FInfo* f_info_; // filter strength info
- uint8_t* yuv_b_; // main block for Y/U/V (size = YUV_SIZE)
- int16_t* coeffs_; // 384 coeffs = (16+8+8) * 4*4
-
- uint8_t* cache_y_; // macroblock row for storing unfiltered samples
- uint8_t* cache_u_;
- uint8_t* cache_v_;
- int cache_y_stride_;
- int cache_uv_stride_;
-
- // main memory chunk for the above data. Persistent.
- void* mem_;
- size_t mem_size_;
-
- // Per macroblock non-persistent infos.
- int mb_x_, mb_y_; // current position, in macroblock units
- uint8_t is_i4x4_; // true if intra4x4
- uint8_t imodes_[16]; // one 16x16 mode (#0) or sixteen 4x4 modes
- uint8_t uvmode_; // chroma prediction mode
- uint8_t segment_; // block's segment
-
- // bit-wise info about the content of each sub-4x4 blocks: there are 16 bits
- // for luma (bits #0->#15), then 4 bits for chroma-u (#16->#19) and 4 bits for
- // chroma-v (#20->#23), each corresponding to one 4x4 block in decoding order.
- // If the bit is set, the 4x4 block contains some non-zero coefficients.
- uint32_t non_zero_;
- uint32_t non_zero_ac_;
-
- // Filtering side-info
- int filter_type_; // 0=off, 1=simple, 2=complex
- int filter_row_; // per-row flag
- uint8_t filter_levels_[NUM_MB_SEGMENTS]; // precalculated per-segment
-
- // extensions
- const uint8_t* alpha_data_; // compressed alpha data (if present)
- size_t alpha_data_size_;
- uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
-
- int layer_colorspace_;
- const uint8_t* layer_data_; // compressed layer data (if present)
- size_t layer_data_size_;
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// in vp8.c
-int VP8SetError(VP8Decoder* const dec,
- VP8StatusCode error, const char* const msg);
-
-// in tree.c
-void VP8ResetProba(VP8Proba* const proba);
-void VP8ParseProba(VP8BitReader* const br, VP8Decoder* const dec);
-void VP8ParseIntraMode(VP8BitReader* const br, VP8Decoder* const dec);
-
-// in quant.c
-void VP8ParseQuant(VP8Decoder* const dec);
-
-// in frame.c
-int VP8InitFrame(VP8Decoder* const dec, VP8Io* io);
-// Predict a block and add residual
-void VP8ReconstructBlock(VP8Decoder* const dec);
-// Call io->setup() and finish setting up scan parameters.
-// After this call returns, one must always call VP8ExitCritical() with the
-// same parameters. Both functions should be used in pair. Returns VP8_STATUS_OK
-// if ok, otherwise sets and returns the error status on *dec.
-VP8StatusCode VP8EnterCritical(VP8Decoder* const dec, VP8Io* const io);
-// Must always be called in pair with VP8EnterCritical().
-// Returns false in case of error.
-int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io);
-// Process the last decoded row (filtering + output)
-int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io);
-// Store a block, along with filtering params
-void VP8StoreBlock(VP8Decoder* const dec);
-// To be called at the start of a new scanline, to initialize predictors.
-void VP8InitScanline(VP8Decoder* const dec);
-// Decode one macroblock. Returns false if there is not enough data.
-int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br);
-
-// in alpha.c
-const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
- int row, int num_rows);
-
-// in layer.c
-int VP8DecodeLayer(VP8Decoder* const dec);
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8I_H_ */
diff --git a/drivers/webpold/dec/vp8l.c b/drivers/webpold/dec/vp8l.c
deleted file mode 100644
index 897e4395c7..0000000000
--- a/drivers/webpold/dec/vp8l.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-// 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/
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "./vp8li.h"
-#include "../dsp/lossless.h"
-#include "../dsp/yuv.h"
-#include "../utils/huffman.h"
-#include "../utils/utils.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#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 };
-
-// -----------------------------------------------------------------------------
-// Five Huffman codes are used at each meta code:
-// 1. green + length prefix codes + color cache codes,
-// 2. alpha,
-// 3. red,
-// 4. blue, and,
-// 5. distance prefix codes.
-typedef enum {
- GREEN = 0,
- RED = 1,
- BLUE = 2,
- ALPHA = 3,
- DIST = 4
-} HuffIndex;
-
-static const uint16_t kAlphabetSize[HUFFMAN_CODES_PER_META_CODE] = {
- NUM_LITERAL_CODES + NUM_LENGTH_CODES,
- NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
- NUM_DISTANCE_CODES
-};
-
-
-#define NUM_CODE_LENGTH_CODES 19
-static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
- 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-};
-
-#define CODE_TO_PLANE_CODES 120
-static const uint8_t code_to_plane_lut[CODE_TO_PLANE_CODES] = {
- 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
- 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
- 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
- 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
- 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
- 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
- 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
- 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
- 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
- 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
- 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
- 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
-};
-
-static int DecodeImageStream(int xsize, int ysize,
- int is_level0,
- VP8LDecoder* const dec,
- uint32_t** const decoded_data);
-
-//------------------------------------------------------------------------------
-
-int VP8LCheckSignature(const uint8_t* const data, size_t size) {
- return (size >= 1) && (data[0] == VP8L_MAGIC_BYTE);
-}
-
-static int ReadImageInfo(VP8LBitReader* const br,
- int* const width, int* const height,
- int* const has_alpha) {
- const uint8_t signature = VP8LReadBits(br, 8);
- if (!VP8LCheckSignature(&signature, 1)) {
- return 0;
- }
- *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
- *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1;
- *has_alpha = VP8LReadBits(br, 1);
- VP8LReadBits(br, VP8L_VERSION_BITS); // Read/ignore the version number.
- return 1;
-}
-
-int VP8LGetInfo(const uint8_t* data, size_t data_size,
- int* const width, int* const height, int* const has_alpha) {
- if (data == NULL || data_size < VP8L_FRAME_HEADER_SIZE) {
- return 0; // not enough data
- } else {
- int w, h, a;
- VP8LBitReader br;
- VP8LInitBitReader(&br, data, data_size);
- if (!ReadImageInfo(&br, &w, &h, &a)) {
- return 0;
- }
- if (width != NULL) *width = w;
- if (height != NULL) *height = h;
- if (has_alpha != NULL) *has_alpha = a;
- return 1;
- }
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int GetCopyDistance(int distance_symbol,
- VP8LBitReader* const br) {
- int extra_bits, offset;
- if (distance_symbol < 4) {
- return distance_symbol + 1;
- }
- extra_bits = (distance_symbol - 2) >> 1;
- offset = (2 + (distance_symbol & 1)) << extra_bits;
- return offset + VP8LReadBits(br, extra_bits) + 1;
-}
-
-static WEBP_INLINE int GetCopyLength(int length_symbol,
- VP8LBitReader* const br) {
- // Length and distance prefixes are encoded the same way.
- return GetCopyDistance(length_symbol, br);
-}
-
-static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
- if (plane_code > CODE_TO_PLANE_CODES) {
- return plane_code - CODE_TO_PLANE_CODES;
- } else {
- const int dist_code = code_to_plane_lut[plane_code - 1];
- const int yoffset = dist_code >> 4;
- const int xoffset = 8 - (dist_code & 0xf);
- const int dist = yoffset * xsize + xoffset;
- return (dist >= 1) ? dist : 1;
- }
-}
-
-//------------------------------------------------------------------------------
-// Decodes the next Huffman code from bit-stream.
-// FillBitWindow(br) needs to be called at minimum every second call
-// to ReadSymbolUnsafe.
-static int ReadSymbolUnsafe(const HuffmanTree* tree, VP8LBitReader* const br) {
- const HuffmanTreeNode* node = tree->root_;
- assert(node != NULL);
- while (!HuffmanTreeNodeIsLeaf(node)) {
- node = HuffmanTreeNextNode(node, VP8LReadOneBitUnsafe(br));
- }
- return node->symbol_;
-}
-
-static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
- VP8LBitReader* const br) {
- const int read_safe = (br->pos_ + 8 > br->len_);
- if (!read_safe) {
- return ReadSymbolUnsafe(tree, br);
- } else {
- const HuffmanTreeNode* node = tree->root_;
- assert(node != NULL);
- while (!HuffmanTreeNodeIsLeaf(node)) {
- node = HuffmanTreeNextNode(node, VP8LReadOneBit(br));
- }
- return node->symbol_;
- }
-}
-
-static int ReadHuffmanCodeLengths(
- VP8LDecoder* const dec, const int* const code_length_code_lengths,
- int num_symbols, int* const code_lengths) {
- int ok = 0;
- VP8LBitReader* const br = &dec->br_;
- int symbol;
- int max_symbol;
- int prev_code_len = DEFAULT_CODE_LENGTH;
- HuffmanTree tree;
-
- if (!HuffmanTreeBuildImplicit(&tree, code_length_code_lengths,
- NUM_CODE_LENGTH_CODES)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
- }
-
- if (VP8LReadBits(br, 1)) { // use length
- const int length_nbits = 2 + 2 * VP8LReadBits(br, 3);
- max_symbol = 2 + VP8LReadBits(br, length_nbits);
- if (max_symbol > num_symbols) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- }
- } else {
- max_symbol = num_symbols;
- }
-
- symbol = 0;
- while (symbol < num_symbols) {
- int code_len;
- if (max_symbol-- == 0) break;
- VP8LFillBitWindow(br);
- code_len = ReadSymbol(&tree, br);
- if (code_len < kCodeLengthLiterals) {
- code_lengths[symbol++] = code_len;
- if (code_len != 0) prev_code_len = code_len;
- } else {
- const int use_prev = (code_len == kCodeLengthRepeatCode);
- const int slot = code_len - kCodeLengthLiterals;
- const int extra_bits = kCodeLengthExtraBits[slot];
- const int repeat_offset = kCodeLengthRepeatOffsets[slot];
- int repeat = VP8LReadBits(br, extra_bits) + repeat_offset;
- if (symbol + repeat > num_symbols) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- } else {
- const int length = use_prev ? prev_code_len : 0;
- while (repeat-- > 0) code_lengths[symbol++] = length;
- }
- }
- }
- ok = 1;
-
- End:
- HuffmanTreeRelease(&tree);
- return ok;
-}
-
-static int ReadHuffmanCode(int alphabet_size, VP8LDecoder* const dec,
- HuffmanTree* const tree) {
- int ok = 0;
- VP8LBitReader* const br = &dec->br_;
- const int simple_code = VP8LReadBits(br, 1);
-
- if (simple_code) { // Read symbols, codes & code lengths directly.
- int symbols[2];
- int codes[2];
- int code_lengths[2];
- const int num_symbols = VP8LReadBits(br, 1) + 1;
- const int first_symbol_len_code = VP8LReadBits(br, 1);
- // The first code is either 1 bit or 8 bit code.
- symbols[0] = VP8LReadBits(br, (first_symbol_len_code == 0) ? 1 : 8);
- codes[0] = 0;
- code_lengths[0] = num_symbols - 1;
- // The second code (if present), is always 8 bit long.
- if (num_symbols == 2) {
- symbols[1] = VP8LReadBits(br, 8);
- codes[1] = 1;
- code_lengths[1] = num_symbols - 1;
- }
- ok = HuffmanTreeBuildExplicit(tree, code_lengths, codes, symbols,
- alphabet_size, num_symbols);
- } else { // Decode Huffman-coded code lengths.
- int* code_lengths = NULL;
- int i;
- int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
- const int num_codes = VP8LReadBits(br, 4) + 4;
- if (num_codes > NUM_CODE_LENGTH_CODES) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
- }
-
- code_lengths =
- (int*)WebPSafeCalloc((uint64_t)alphabet_size, sizeof(*code_lengths));
- if (code_lengths == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
-
- for (i = 0; i < num_codes; ++i) {
- code_length_code_lengths[kCodeLengthCodeOrder[i]] = VP8LReadBits(br, 3);
- }
- ok = ReadHuffmanCodeLengths(dec, code_length_code_lengths, alphabet_size,
- code_lengths);
- if (ok) {
- ok = HuffmanTreeBuildImplicit(tree, code_lengths, alphabet_size);
- }
- free(code_lengths);
- }
- ok = ok && !br->error_;
- if (!ok) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
- }
- return 1;
-}
-
-static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
- if (htree_groups != NULL) {
- int i, j;
- for (i = 0; i < num_htree_groups; ++i) {
- HuffmanTree* const htrees = htree_groups[i].htrees_;
- for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
- HuffmanTreeRelease(&htrees[j]);
- }
- }
- free(htree_groups);
- }
-}
-
-static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
- int color_cache_bits, int allow_recursion) {
- int i, j;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- uint32_t* huffman_image = NULL;
- HTreeGroup* htree_groups = NULL;
- int num_htree_groups = 1;
-
- if (allow_recursion && VP8LReadBits(br, 1)) {
- // use meta Huffman codes.
- const int huffman_precision = VP8LReadBits(br, 3) + 2;
- const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
- const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
- const int huffman_pixs = huffman_xsize * huffman_ysize;
- if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
- &huffman_image)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto Error;
- }
- hdr->huffman_subsample_bits_ = huffman_precision;
- for (i = 0; i < huffman_pixs; ++i) {
- // The huffman data is stored in red and green bytes.
- const int index = (huffman_image[i] >> 8) & 0xffff;
- huffman_image[i] = index;
- if (index >= num_htree_groups) {
- num_htree_groups = index + 1;
- }
- }
- }
-
- if (br->error_) goto Error;
-
- assert(num_htree_groups <= 0x10000);
- htree_groups =
- (HTreeGroup*)WebPSafeCalloc((uint64_t)num_htree_groups,
- sizeof(*htree_groups));
- if (htree_groups == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- goto Error;
- }
-
- for (i = 0; i < num_htree_groups; ++i) {
- HuffmanTree* const htrees = htree_groups[i].htrees_;
- 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;
- }
- if (!ReadHuffmanCode(alphabet_size, dec, htrees + j)) goto Error;
- }
- }
-
- // All OK. Finalize pointers and return.
- hdr->huffman_image_ = huffman_image;
- hdr->num_htree_groups_ = num_htree_groups;
- hdr->htree_groups_ = htree_groups;
- return 1;
-
- Error:
- free(huffman_image);
- DeleteHtreeGroups(htree_groups, num_htree_groups);
- return 0;
-}
-
-//------------------------------------------------------------------------------
-// Scaling.
-
-static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) {
- const int num_channels = 4;
- const int in_width = io->mb_w;
- const int out_width = io->scaled_width;
- const int in_height = io->mb_h;
- const int out_height = io->scaled_height;
- const uint64_t work_size = 2 * num_channels * (uint64_t)out_width;
- int32_t* work; // Rescaler work area.
- const uint64_t scaled_data_size = num_channels * (uint64_t)out_width;
- uint32_t* scaled_data; // Temporary storage for scaled BGRA data.
- const uint64_t memory_size = sizeof(*dec->rescaler) +
- work_size * sizeof(*work) +
- scaled_data_size * sizeof(*scaled_data);
- uint8_t* memory = (uint8_t*)WebPSafeCalloc(memory_size, sizeof(*memory));
- if (memory == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
- assert(dec->rescaler_memory == NULL);
- dec->rescaler_memory = memory;
-
- dec->rescaler = (WebPRescaler*)memory;
- memory += sizeof(*dec->rescaler);
- work = (int32_t*)memory;
- memory += work_size * sizeof(*work);
- scaled_data = (uint32_t*)memory;
-
- WebPRescalerInit(dec->rescaler, in_width, in_height, (uint8_t*)scaled_data,
- out_width, out_height, 0, num_channels,
- in_width, out_width, in_height, out_height, work);
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Export to ARGB
-
-// 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) {
- const uint32_t* const src = (const uint32_t*)rescaler->dst;
- const int dst_width = rescaler->dst_width;
- int num_lines_out = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- uint8_t* const dst = rgba + num_lines_out * rgba_stride;
- WebPRescalerExportRow(rescaler);
- VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-// Emit scaled rows.
-static int EmitRescaledRows(const VP8LDecoder* const dec,
- const uint32_t* const data, int in_stride, int mb_h,
- uint8_t* const out, int out_stride) {
- const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
- const uint8_t* const in = (const uint8_t*)data;
- int num_lines_in = 0;
- int num_lines_out = 0;
- while (num_lines_in < mb_h) {
- const uint8_t* const row_in = in + num_lines_in * in_stride;
- uint8_t* const row_out = out + num_lines_out * out_stride;
- num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
- row_in, in_stride);
- num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
- }
- return num_lines_out;
-}
-
-// Emit rows without any scaling.
-static int EmitRows(WEBP_CSP_MODE colorspace,
- const uint32_t* const data, int in_stride,
- int mb_w, int mb_h,
- uint8_t* const out, int out_stride) {
- int lines = mb_h;
- const uint8_t* row_in = (const uint8_t*)data;
- uint8_t* row_out = out;
- while (lines-- > 0) {
- VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
- row_in += in_stride;
- row_out += out_stride;
- }
- return mb_h; // Num rows out == num rows in.
-}
-
-//------------------------------------------------------------------------------
-// Export to YUVA
-
-static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
- const WebPDecBuffer* const output) {
- const WebPYUVABuffer* const buf = &output->u.YUVA;
- // first, the luma plane
- {
- int i;
- uint8_t* const y = buf->y + y_pos * buf->y_stride;
- for (i = 0; i < width; ++i) {
- const uint32_t p = src[i];
- y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff);
- }
- }
-
- // then U/V planes
- {
- uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
- uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
- const int uv_width = width >> 1;
- int i;
- for (i = 0; i < uv_width; ++i) {
- const uint32_t v0 = src[2 * i + 0];
- const uint32_t v1 = src[2 * i + 1];
- // VP8RGBToU/V expects four accumulated pixels. Hence we need to
- // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
- const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
- const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
- const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
- if (!(y_pos & 1)) { // even lines: store values
- u[i] = VP8RGBToU(r, g, b);
- v[i] = VP8RGBToV(r, g, b);
- } else { // odd lines: average with previous values
- const int tmp_u = VP8RGBToU(r, g, b);
- const int tmp_v = VP8RGBToV(r, g, b);
- // Approximated average-of-four. But it's an acceptable diff.
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
- if (width & 1) { // last pixel
- const uint32_t v0 = src[2 * i + 0];
- const int r = (v0 >> 14) & 0x3fc;
- const int g = (v0 >> 6) & 0x3fc;
- const int b = (v0 << 2) & 0x3fc;
- if (!(y_pos & 1)) { // even lines
- u[i] = VP8RGBToU(r, g, b);
- v[i] = VP8RGBToV(r, g, b);
- } else { // odd lines (note: we could just skip this)
- const int tmp_u = VP8RGBToU(r, g, b);
- const int tmp_v = VP8RGBToV(r, g, b);
- u[i] = (u[i] + tmp_u + 1) >> 1;
- v[i] = (v[i] + tmp_v + 1) >> 1;
- }
- }
- }
- // Lastly, store alpha if needed.
- if (buf->a != NULL) {
- int i;
- uint8_t* const a = buf->a + y_pos * buf->a_stride;
- for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
- }
-}
-
-static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
- WebPRescaler* const rescaler = dec->rescaler;
- const uint32_t* const src = (const uint32_t*)rescaler->dst;
- const int dst_width = rescaler->dst_width;
- int num_lines_out = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- WebPRescalerExportRow(rescaler);
- ConvertToYUVA(src, dst_width, y_pos, dec->output_);
- ++y_pos;
- ++num_lines_out;
- }
- return num_lines_out;
-}
-
-static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
- const uint32_t* const data,
- int in_stride, int mb_h) {
- const uint8_t* const in = (const uint8_t*)data;
- int num_lines_in = 0;
- int y_pos = dec->last_out_row_;
- while (num_lines_in < mb_h) {
- const uint8_t* const row_in = in + num_lines_in * in_stride;
- num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in,
- row_in, in_stride);
- y_pos += ExportYUVA(dec, y_pos);
- }
- return y_pos;
-}
-
-static int EmitRowsYUVA(const VP8LDecoder* const dec,
- const uint32_t* const data, int in_stride,
- int mb_w, int num_rows) {
- int y_pos = dec->last_out_row_;
- const uint8_t* row_in = (const uint8_t*)data;
- while (num_rows-- > 0) {
- ConvertToYUVA((const uint32_t*)row_in, mb_w, y_pos, dec->output_);
- row_in += in_stride;
- ++y_pos;
- }
- return y_pos;
-}
-
-//------------------------------------------------------------------------------
-// Cropping.
-
-// Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
-// crop options. Also updates the input data pointer, so that it points to the
-// start of the cropped window.
-// Note that 'pixel_stride' is in units of 'uint32_t' (and not 'bytes).
-// Returns true if the crop window is not empty.
-static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
- const uint32_t** const in_data, int pixel_stride) {
- assert(y_start < y_end);
- assert(io->crop_left < io->crop_right);
- if (y_end > io->crop_bottom) {
- y_end = io->crop_bottom; // make sure we don't overflow on last row.
- }
- if (y_start < io->crop_top) {
- const int delta = io->crop_top - y_start;
- y_start = io->crop_top;
- *in_data += pixel_stride * delta;
- }
- if (y_start >= y_end) return 0; // Crop window is empty.
-
- *in_data += io->crop_left;
-
- io->mb_y = y_start - io->crop_top;
- io->mb_w = io->crop_right - io->crop_left;
- io->mb_h = y_end - y_start;
- return 1; // Non-empty crop window.
-}
-
-//------------------------------------------------------------------------------
-
-static WEBP_INLINE int GetMetaIndex(
- const uint32_t* const image, int xsize, int bits, int x, int y) {
- if (bits == 0) return 0;
- return image[xsize * (y >> bits) + (x >> bits)];
-}
-
-static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
- int x, int y) {
- const int meta_index = GetMetaIndex(hdr->huffman_image_, hdr->huffman_xsize_,
- hdr->huffman_subsample_bits_, x, y);
- assert(meta_index < hdr->num_htree_groups_);
- return hdr->htree_groups_ + meta_index;
-}
-
-//------------------------------------------------------------------------------
-// Main loop, with custom row-processing function
-
-typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
-
-static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
- const uint32_t* const rows) {
- int n = dec->next_transform_;
- const int cache_pixs = dec->width_ * num_rows;
- const int start_row = dec->last_row_;
- const int end_row = start_row + num_rows;
- const uint32_t* rows_in = rows;
- uint32_t* const rows_out = dec->argb_cache_;
-
- // Inverse transforms.
- // TODO: most transforms only need to operate on the cropped region only.
- memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
- while (n-- > 0) {
- VP8LTransform* const transform = &dec->transforms_[n];
- VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
- rows_in = rows_out;
- }
-}
-
-// Processes (transforms, scales & color-converts) the rows decoded after the
-// last call.
-static void ProcessRows(VP8LDecoder* const dec, int row) {
- const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_;
- const int num_rows = row - dec->last_row_;
-
- if (num_rows <= 0) return; // Nothing to be done.
- ApplyInverseTransforms(dec, num_rows, rows);
-
- // Emit output.
- {
- VP8Io* const io = dec->io_;
- const uint32_t* rows_data = dec->argb_cache_;
- if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) {
- // Nothing to output (this time).
- } else {
- const WebPDecBuffer* const output = dec->output_;
- const int in_stride = io->width * sizeof(*rows_data);
- if (output->colorspace < MODE_YUV) { // 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 ?
- EmitRescaledRows(dec, rows_data, in_stride, io->mb_h,
- rgba, buf->stride) :
- EmitRows(output->colorspace, rows_data, in_stride,
- io->mb_w, io->mb_h, rgba, buf->stride);
- // Update 'last_out_row_'.
- dec->last_out_row_ += num_rows_out;
- } else { // convert to YUVA
- dec->last_out_row_ = io->use_scaling ?
- EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
- EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
- }
- assert(dec->last_out_row_ <= output->height);
- }
- }
-
- // Update 'last_row_'.
- dec->last_row_ = row;
- assert(dec->last_row_ <= dec->height_);
-}
-
-static int DecodeImageData(VP8LDecoder* const dec,
- uint32_t* const data, int width, int height,
- ProcessRowsFunc process_func) {
- int ok = 1;
- int col = 0, row = 0;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- HTreeGroup* htree_group = hdr->htree_groups_;
- uint32_t* src = data;
- uint32_t* last_cached = data;
- uint32_t* const src_end = data + width * height;
- const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
- const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
- VP8LColorCache* const color_cache =
- (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
- const int mask = hdr->huffman_mask_;
-
- assert(htree_group != NULL);
-
- while (!br->eos_ && src < src_end) {
- int code;
- // Only update when changing tile. Note we could use the following test:
- // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
- // but that's actually slower and requires storing the previous col/row
- if ((col & mask) == 0) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- }
- VP8LFillBitWindow(br);
- code = ReadSymbol(&htree_group->htrees_[GREEN], br);
- if (code < NUM_LITERAL_CODES) { // Literal.
- int red, green, blue, alpha;
- red = ReadSymbol(&htree_group->htrees_[RED], br);
- green = code;
- VP8LFillBitWindow(br);
- blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
- alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
- *src = (alpha << 24) + (red << 16) + (green << 8) + blue;
- AdvanceByOne:
- ++src;
- ++col;
- if (col >= width) {
- col = 0;
- ++row;
- if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- process_func(dec, row);
- }
- if (color_cache != NULL) {
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- }
- }
- } else if (code < len_code_limit) { // Backward reference
- int dist_code, dist;
- const int length_sym = code - NUM_LITERAL_CODES;
- const int length = GetCopyLength(length_sym, br);
- const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
- VP8LFillBitWindow(br);
- dist_code = GetCopyDistance(dist_symbol, br);
- dist = PlaneCodeToDistance(width, dist_code);
- if (src - data < dist || src_end - src < length) {
- ok = 0;
- goto End;
- }
- {
- int i;
- for (i = 0; i < length; ++i) src[i] = src[i - dist];
- src += length;
- }
- col += length;
- while (col >= width) {
- col -= width;
- ++row;
- if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- process_func(dec, row);
- }
- }
- if (src < src_end) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- if (color_cache != NULL) {
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- }
- }
- } else if (code < color_cache_limit) { // Color cache.
- const int key = code - len_code_limit;
- assert(color_cache != NULL);
- while (last_cached < src) {
- VP8LColorCacheInsert(color_cache, *last_cached++);
- }
- *src = VP8LColorCacheLookup(color_cache, key);
- goto AdvanceByOne;
- } else { // Not reached.
- ok = 0;
- goto End;
- }
- ok = !br->error_;
- if (!ok) goto End;
- }
- // Process the remaining rows corresponding to last row-block.
- if (process_func != NULL) process_func(dec, row);
-
- End:
- if (br->error_ || !ok || (br->eos_ && src < src_end)) {
- ok = 0;
- dec->status_ = (!br->eos_) ?
- VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED;
- } else if (src == src_end) {
- dec->state_ = READ_DATA;
- }
-
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LTransform
-
-static void ClearTransform(VP8LTransform* const transform) {
- free(transform->data_);
- transform->data_ = NULL;
-}
-
-// For security reason, we need to remap the color map to span
-// the total possible bundled values, and not just the num_colors.
-static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
- int i;
- const int final_num_colors = 1 << (8 >> transform->bits_);
- uint32_t* const new_color_map =
- (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
- sizeof(*new_color_map));
- if (new_color_map == NULL) {
- return 0;
- } else {
- uint8_t* const data = (uint8_t*)transform->data_;
- uint8_t* const new_data = (uint8_t*)new_color_map;
- new_color_map[0] = transform->data_[0];
- for (i = 4; i < 4 * num_colors; ++i) {
- // Equivalent to AddPixelEq(), on a byte-basis.
- new_data[i] = (data[i] + new_data[i - 4]) & 0xff;
- }
- for (; i < 4 * final_num_colors; ++i)
- new_data[i] = 0; // black tail.
- free(transform->data_);
- transform->data_ = new_color_map;
- }
- return 1;
-}
-
-static int ReadTransform(int* const xsize, int const* ysize,
- VP8LDecoder* const dec) {
- int ok = 1;
- VP8LBitReader* const br = &dec->br_;
- VP8LTransform* transform = &dec->transforms_[dec->next_transform_];
- const VP8LImageTransformType type =
- (VP8LImageTransformType)VP8LReadBits(br, 2);
-
- // Each transform type can only be present once in the stream.
- if (dec->transforms_seen_ & (1U << type)) {
- return 0; // Already there, let's not accept the second same transform.
- }
- dec->transforms_seen_ |= (1U << type);
-
- transform->type_ = type;
- transform->xsize_ = *xsize;
- transform->ysize_ = *ysize;
- transform->data_ = NULL;
- ++dec->next_transform_;
- assert(dec->next_transform_ <= NUM_TRANSFORMS);
-
- switch (type) {
- case PREDICTOR_TRANSFORM:
- case CROSS_COLOR_TRANSFORM:
- transform->bits_ = VP8LReadBits(br, 3) + 2;
- ok = DecodeImageStream(VP8LSubSampleSize(transform->xsize_,
- transform->bits_),
- VP8LSubSampleSize(transform->ysize_,
- transform->bits_),
- 0, dec, &transform->data_);
- break;
- case COLOR_INDEXING_TRANSFORM: {
- const int num_colors = VP8LReadBits(br, 8) + 1;
- const int bits = (num_colors > 16) ? 0
- : (num_colors > 4) ? 1
- : (num_colors > 2) ? 2
- : 3;
- *xsize = VP8LSubSampleSize(transform->xsize_, bits);
- transform->bits_ = bits;
- ok = DecodeImageStream(num_colors, 1, 0, dec, &transform->data_);
- ok = ok && ExpandColorMap(num_colors, transform);
- break;
- }
- case SUBTRACT_GREEN:
- break;
- default:
- assert(0); // can't happen
- break;
- }
-
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LMetadata
-
-static void InitMetadata(VP8LMetadata* const hdr) {
- assert(hdr);
- memset(hdr, 0, sizeof(*hdr));
-}
-
-static void ClearMetadata(VP8LMetadata* const hdr) {
- assert(hdr);
-
- free(hdr->huffman_image_);
- DeleteHtreeGroups(hdr->htree_groups_, hdr->num_htree_groups_);
- VP8LColorCacheClear(&hdr->color_cache_);
- InitMetadata(hdr);
-}
-
-// -----------------------------------------------------------------------------
-// VP8LDecoder
-
-VP8LDecoder* VP8LNew(void) {
- VP8LDecoder* const dec = (VP8LDecoder*)calloc(1, sizeof(*dec));
- if (dec == NULL) return NULL;
- dec->status_ = VP8_STATUS_OK;
- dec->action_ = READ_DIM;
- dec->state_ = READ_DIM;
- return dec;
-}
-
-void VP8LClear(VP8LDecoder* const dec) {
- int i;
- if (dec == NULL) return;
- ClearMetadata(&dec->hdr_);
-
- free(dec->argb_);
- dec->argb_ = NULL;
- for (i = 0; i < dec->next_transform_; ++i) {
- ClearTransform(&dec->transforms_[i]);
- }
- dec->next_transform_ = 0;
- dec->transforms_seen_ = 0;
-
- free(dec->rescaler_memory);
- dec->rescaler_memory = NULL;
-
- dec->output_ = NULL; // leave no trace behind
-}
-
-void VP8LDelete(VP8LDecoder* const dec) {
- if (dec != NULL) {
- VP8LClear(dec);
- free(dec);
- }
-}
-
-static void UpdateDecoder(VP8LDecoder* const dec, int width, int height) {
- VP8LMetadata* const hdr = &dec->hdr_;
- const int num_bits = hdr->huffman_subsample_bits_;
- dec->width_ = width;
- dec->height_ = height;
-
- hdr->huffman_xsize_ = VP8LSubSampleSize(width, num_bits);
- hdr->huffman_mask_ = (num_bits == 0) ? ~0 : (1 << num_bits) - 1;
-}
-
-static int DecodeImageStream(int xsize, int ysize,
- int is_level0,
- VP8LDecoder* const dec,
- uint32_t** const decoded_data) {
- int ok = 1;
- int transform_xsize = xsize;
- int transform_ysize = ysize;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- uint32_t* data = NULL;
- int color_cache_bits = 0;
-
- // Read the transforms (may recurse).
- if (is_level0) {
- while (ok && VP8LReadBits(br, 1)) {
- ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
- }
- }
-
- // Color cache
- if (ok && VP8LReadBits(br, 1)) {
- color_cache_bits = VP8LReadBits(br, 4);
- ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
- if (!ok) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- }
- }
-
- // Read the Huffman codes (may recurse).
- ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
- color_cache_bits, is_level0);
- if (!ok) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto End;
- }
-
- // Finish setting up the color-cache
- if (color_cache_bits > 0) {
- hdr->color_cache_size_ = 1 << color_cache_bits;
- if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- ok = 0;
- goto End;
- }
- } else {
- hdr->color_cache_size_ = 0;
- }
- UpdateDecoder(dec, transform_xsize, transform_ysize);
-
- if (is_level0) { // level 0 complete
- dec->state_ = READ_HDR;
- goto End;
- }
-
- {
- const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
- data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
- if (data == NULL) {
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- ok = 0;
- goto End;
- }
- }
-
- // Use the Huffman trees to decode the LZ77 encoded data.
- ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL);
- ok = ok && !br->error_;
-
- End:
-
- if (!ok) {
- free(data);
- ClearMetadata(hdr);
- // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
- // status appropriately.
- if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
- dec->status_ = VP8_STATUS_SUSPENDED;
- }
- } else {
- if (decoded_data != NULL) {
- *decoded_data = data;
- } else {
- // We allocate image data in this function only for transforms. At level 0
- // (that is: not the transforms), we shouldn't have allocated anything.
- assert(data == NULL);
- assert(is_level0);
- }
- if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// Allocate dec->argb_ and dec->argb_cache_ using dec->width_ and dec->height_
-
-static int AllocateARGBBuffers(VP8LDecoder* const dec, int final_width) {
- const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
- // Scratch buffer corresponding to top-prediction row for transforming the
- // first row in the row-blocks.
- const uint64_t cache_top_pixels = final_width;
- // Scratch buffer for temporary BGRA storage.
- const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
- const uint64_t total_num_pixels =
- num_pixels + cache_top_pixels + cache_pixels;
-
- assert(dec->width_ <= final_width);
- dec->argb_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(*dec->argb_));
- if (dec->argb_ == NULL) {
- dec->argb_cache_ = NULL; // for sanity check
- dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
- return 0;
- }
- dec->argb_cache_ = dec->argb_ + num_pixels + cache_top_pixels;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Special row-processing that only stores the alpha data.
-
-static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
- const int num_rows = row - dec->last_row_;
- const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_;
-
- if (num_rows <= 0) return; // Nothing to be done.
- ApplyInverseTransforms(dec, num_rows, in);
-
- // Extract alpha (which is stored in the green plane).
- {
- const int width = dec->io_->width; // the final width (!= dec->width_)
- const int cache_pixs = width * num_rows;
- uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
- const uint32_t* const src = dec->argb_cache_;
- int i;
- for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
- }
-
- dec->last_row_ = dec->last_out_row_ = row;
-}
-
-int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
- size_t data_size, uint8_t* const output) {
- VP8Io io;
- int ok = 0;
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) return 0;
-
- dec->width_ = width;
- dec->height_ = height;
- dec->io_ = &io;
-
- VP8InitIo(&io);
- WebPInitCustomIo(NULL, &io); // Just a sanity Init. io won't be used.
- io.opaque = output;
- io.width = width;
- io.height = height;
-
- dec->status_ = VP8_STATUS_OK;
- VP8LInitBitReader(&dec->br_, data, data_size);
-
- dec->action_ = READ_HDR;
- if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Err;
-
- // Allocate output (note that dec->width_ may have changed here).
- if (!AllocateARGBBuffers(dec, width)) goto Err;
-
- // Decode (with special row processing).
- dec->action_ = READ_DATA;
- ok = DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
- ExtractAlphaRows);
-
- Err:
- VP8LDelete(dec);
- return ok;
-}
-
-//------------------------------------------------------------------------------
-
-int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
- int width, height, has_alpha;
-
- if (dec == NULL) return 0;
- if (io == NULL) {
- dec->status_ = VP8_STATUS_INVALID_PARAM;
- return 0;
- }
-
- dec->io_ = io;
- dec->status_ = VP8_STATUS_OK;
- VP8LInitBitReader(&dec->br_, io->data, io->data_size);
- if (!ReadImageInfo(&dec->br_, &width, &height, &has_alpha)) {
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- goto Error;
- }
- dec->state_ = READ_DIM;
- io->width = width;
- io->height = height;
-
- dec->action_ = READ_HDR;
- if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
- return 1;
-
- Error:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
-}
-
-int VP8LDecodeImage(VP8LDecoder* const dec) {
- VP8Io* io = NULL;
- WebPDecParams* params = NULL;
-
- // Sanity checks.
- if (dec == NULL) return 0;
-
- io = dec->io_;
- assert(io != NULL);
- params = (WebPDecParams*)io->opaque;
- assert(params != NULL);
- dec->output_ = params->output;
- assert(dec->output_ != NULL);
-
- // Initialization.
- if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
- dec->status_ = VP8_STATUS_INVALID_PARAM;
- goto Err;
- }
-
- if (!AllocateARGBBuffers(dec, io->width)) goto Err;
-
- if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
-
- // Decode.
- dec->action_ = READ_DATA;
- if (!DecodeImageData(dec, dec->argb_, dec->width_, dec->height_,
- ProcessRows)) {
- goto Err;
- }
-
- // Cleanup.
- params->last_y = dec->last_out_row_;
- VP8LClear(dec);
- return 1;
-
- Err:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/vp8li.h b/drivers/webpold/dec/vp8li.h
deleted file mode 100644
index 5f6cd6a01c..0000000000
--- a/drivers/webpold/dec/vp8li.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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/
-// -----------------------------------------------------------------------------
-//
-// Lossless decoder: internal header.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-// Vikas Arora(vikaas.arora@gmail.com)
-
-#ifndef WEBP_DEC_VP8LI_H_
-#define WEBP_DEC_VP8LI_H_
-
-#include <string.h> // for memcpy()
-#include "./webpi.h"
-#include "../utils/bit_reader.h"
-#include "../utils/color_cache.h"
-#include "../utils/huffman.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-typedef enum {
- READ_DATA = 0,
- READ_HDR = 1,
- READ_DIM = 2
-} VP8LDecodeState;
-
-typedef struct VP8LTransform VP8LTransform;
-struct VP8LTransform {
- VP8LImageTransformType type_; // transform type.
- int bits_; // subsampling bits defining transform window.
- int xsize_; // transform window X index.
- int ysize_; // transform window Y index.
- uint32_t *data_; // transform data.
-};
-
-typedef struct {
- HuffmanTree htrees_[HUFFMAN_CODES_PER_META_CODE];
-} HTreeGroup;
-
-typedef struct {
- int color_cache_size_;
- VP8LColorCache color_cache_;
-
- int huffman_mask_;
- int huffman_subsample_bits_;
- int huffman_xsize_;
- uint32_t *huffman_image_;
- int num_htree_groups_;
- HTreeGroup *htree_groups_;
-} VP8LMetadata;
-
-typedef struct {
- VP8StatusCode status_;
- VP8LDecodeState action_;
- VP8LDecodeState state_;
- VP8Io *io_;
-
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
-
- uint32_t *argb_; // Internal data: always in BGRA color mode.
- uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage.
-
- VP8LBitReader br_;
-
- int width_;
- int height_;
- int last_row_; // last input row decoded so far.
- int last_out_row_; // last row output so far.
-
- VP8LMetadata hdr_;
-
- int next_transform_;
- VP8LTransform transforms_[NUM_TRANSFORMS];
- // or'd bitset storing the transforms types.
- uint32_t transforms_seen_;
-
- uint8_t *rescaler_memory; // Working memory for rescaling work.
- WebPRescaler *rescaler; // Common rescaler for all channels.
-} VP8LDecoder;
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// in vp8l.c
-
-// Decodes a raw image stream (without header) and store the alpha data
-// into *output, which must be of size width x height. Returns false in case
-// of error.
-int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data,
- size_t data_size, uint8_t* const output);
-
-// Allocates and initialize a new lossless decoder instance.
-VP8LDecoder* VP8LNew(void);
-
-// Decodes the image header. Returns false in case of error.
-int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io);
-
-// Decodes an image. It's required to decode the lossless header before calling
-// this function. Returns false in case of error, with updated dec->status_.
-int VP8LDecodeImage(VP8LDecoder* const dec);
-
-// Resets the decoder in its initial state, reclaiming memory.
-// Preserves the dec->status_ value.
-void VP8LClear(VP8LDecoder* const dec);
-
-// Clears and deallocate a lossless decoder instance.
-void VP8LDelete(VP8LDecoder* const dec);
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8LI_H_ */
diff --git a/drivers/webpold/dec/webp.c b/drivers/webpold/dec/webp.c
deleted file mode 100644
index f44bc2b8ae..0000000000
--- a/drivers/webpold/dec/webp.c
+++ /dev/null
@@ -1,771 +0,0 @@
-// Copyright 2010 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/
-// -----------------------------------------------------------------------------
-//
-// Main decoding functions for WEBP images.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "./webpi.h"
-#include "../format_constants.h"
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// RIFF layout is:
-// Offset tag
-// 0...3 "RIFF" 4-byte tag
-// 4...7 size of image data (including metadata) starting at offset 8
-// 8...11 "WEBP" our form-type signature
-// The RIFF container (12 bytes) is followed by appropriate chunks:
-// 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format
-// 16..19 size of the raw VP8 image data, starting at offset 20
-// 20.... the VP8 bytes
-// Or,
-// 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format
-// 16..19 size of the raw VP8L image data, starting at offset 20
-// 20.... the VP8L bytes
-// Or,
-// 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk.
-// 16..19 size of the VP8X chunk starting at offset 20.
-// 20..23 VP8X flags bit-map corresponding to the chunk-types present.
-// 24..26 Width of the Canvas Image.
-// 27..29 Height of the Canvas Image.
-// There can be extra chunks after the "VP8X" chunk (ICCP, TILE, FRM, VP8,
-// META ...)
-// All sizes are in little-endian order.
-// Note: chunk data size must be padded to multiple of 2 when written.
-
-static WEBP_INLINE uint32_t get_le24(const uint8_t* const data) {
- return data[0] | (data[1] << 8) | (data[2] << 16);
-}
-
-static WEBP_INLINE uint32_t get_le32(const uint8_t* const data) {
- return (uint32_t)get_le24(data) | (data[3] << 24);
-}
-
-// Validates the RIFF container (if detected) and skips over it.
-// If a RIFF container is detected,
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid header, and
-// VP8_STATUS_OK otherwise.
-// In case there are not enough bytes (partial RIFF container), return 0 for
-// *riff_size. Else return the RIFF size extracted from the header.
-static VP8StatusCode ParseRIFF(const uint8_t** const data,
- size_t* const data_size,
- size_t* const riff_size) {
- assert(data != NULL);
- assert(data_size != NULL);
- assert(riff_size != NULL);
-
- *riff_size = 0; // Default: no RIFF present.
- if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) {
- if (memcmp(*data + 8, "WEBP", TAG_SIZE)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature.
- } else {
- const uint32_t size = get_le32(*data + TAG_SIZE);
- // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn").
- if (size < TAG_SIZE + CHUNK_HEADER_SIZE) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- // We have a RIFF container. Skip it.
- *riff_size = size;
- *data += RIFF_HEADER_SIZE;
- *data_size -= RIFF_HEADER_SIZE;
- }
- }
- return VP8_STATUS_OK;
-}
-
-// Validates the VP8X header and skips over it.
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid VP8X header,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If a VP8X chunk is found, found_vp8x is set to true and *width_ptr,
-// *height_ptr and *flags_ptr are set to the corresponding values extracted
-// from the VP8X chunk.
-static VP8StatusCode ParseVP8X(const uint8_t** const data,
- size_t* const data_size,
- int* const found_vp8x,
- int* const width_ptr, int* const height_ptr,
- uint32_t* const flags_ptr) {
- const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE;
- assert(data != NULL);
- assert(data_size != NULL);
- assert(found_vp8x != NULL);
-
- *found_vp8x = 0;
-
- if (*data_size < CHUNK_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
-
- if (!memcmp(*data, "VP8X", TAG_SIZE)) {
- int width, height;
- uint32_t flags;
- const uint32_t chunk_size = get_le32(*data + TAG_SIZE);
- if (chunk_size != VP8X_CHUNK_SIZE) {
- return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size.
- }
-
- // Verify if enough data is available to validate the VP8X chunk.
- if (*data_size < vp8x_size) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
- flags = get_le32(*data + 8);
- width = 1 + get_le24(*data + 12);
- height = 1 + get_le24(*data + 15);
- if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
- return VP8_STATUS_BITSTREAM_ERROR; // image is too large
- }
-
- if (flags_ptr != NULL) *flags_ptr = flags;
- if (width_ptr != NULL) *width_ptr = width;
- if (height_ptr != NULL) *height_ptr = height;
- // Skip over VP8X header bytes.
- *data += vp8x_size;
- *data_size -= vp8x_size;
- *found_vp8x = 1;
- }
- return VP8_STATUS_OK;
-}
-
-// Skips to the next VP8/VP8L chunk header in the data given the size of the
-// RIFF chunk 'riff_size'.
-// Returns VP8_STATUS_BITSTREAM_ERROR if any invalid chunk size is encountered,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If an alpha chunk is found, *alpha_data and *alpha_size are set
-// appropriately.
-static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
- size_t* const data_size,
- size_t const riff_size,
- const uint8_t** const alpha_data,
- size_t* const alpha_size) {
- const uint8_t* buf;
- size_t buf_size;
- uint32_t total_size = TAG_SIZE + // "WEBP".
- CHUNK_HEADER_SIZE + // "VP8Xnnnn".
- VP8X_CHUNK_SIZE; // data.
- assert(data != NULL);
- assert(data_size != NULL);
- buf = *data;
- buf_size = *data_size;
-
- assert(alpha_data != NULL);
- assert(alpha_size != NULL);
- *alpha_data = NULL;
- *alpha_size = 0;
-
- while (1) {
- uint32_t chunk_size;
- uint32_t disk_chunk_size; // chunk_size with padding
-
- *data = buf;
- *data_size = buf_size;
-
- if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
-
- chunk_size = get_le32(buf + TAG_SIZE);
- // For odd-sized chunk-payload, there's one byte padding at the end.
- disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1;
- total_size += disk_chunk_size;
-
- // Check that total bytes skipped so far does not exceed riff_size.
- if (riff_size > 0 && (total_size > riff_size)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
- }
-
- if (buf_size < disk_chunk_size) { // Insufficient data.
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
-
- if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
- *alpha_data = buf + CHUNK_HEADER_SIZE;
- *alpha_size = chunk_size;
- } else if (!memcmp(buf, "VP8 ", TAG_SIZE) ||
- !memcmp(buf, "VP8L", TAG_SIZE)) { // A valid VP8/VP8L header.
- return VP8_STATUS_OK; // Found.
- }
-
- // We have a full and valid chunk; skip it.
- buf += disk_chunk_size;
- buf_size -= disk_chunk_size;
- }
-}
-
-// Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it.
-// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (chunk larger than
-// riff_size) VP8/VP8L header,
-// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
-// VP8_STATUS_OK otherwise.
-// If a VP8/VP8L chunk is found, *chunk_size is set to the total number of bytes
-// extracted from the VP8/VP8L chunk header.
-// The flag '*is_lossless' is set to 1 in case of VP8L chunk / raw VP8L data.
-static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr,
- size_t* const data_size,
- size_t riff_size,
- size_t* const chunk_size,
- int* const is_lossless) {
- const uint8_t* const data = *data_ptr;
- const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE);
- const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE);
- const uint32_t minimal_size =
- TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR
- // "WEBP" + "VP8Lnnnn"
- assert(data != NULL);
- assert(data_size != NULL);
- assert(chunk_size != NULL);
- assert(is_lossless != NULL);
-
- if (*data_size < CHUNK_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
- }
-
- if (is_vp8 || is_vp8l) {
- // Bitstream contains VP8/VP8L header.
- const uint32_t size = get_le32(data + TAG_SIZE);
- if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) {
- return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information.
- }
- // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header.
- *chunk_size = size;
- *data_ptr += CHUNK_HEADER_SIZE;
- *data_size -= CHUNK_HEADER_SIZE;
- *is_lossless = is_vp8l;
- } else {
- // Raw VP8/VP8L bitstream (no header).
- *is_lossless = VP8LCheckSignature(data, *data_size);
- *chunk_size = *data_size;
- }
-
- return VP8_STATUS_OK;
-}
-
-//------------------------------------------------------------------------------
-
-// Fetch '*width', '*height', '*has_alpha' and fill out 'headers' based on
-// 'data'. All the output parameters may be NULL. If 'headers' is NULL only the
-// minimal amount will be read to fetch the remaining parameters.
-// If 'headers' is non-NULL this function will attempt to locate both alpha
-// data (with or without a VP8X chunk) and the bitstream chunk (VP8/VP8L).
-// Note: The following chunk sequences (before the raw VP8/VP8L data) are
-// considered valid by this function:
-// RIFF + VP8(L)
-// RIFF + VP8X + (optional chunks) + VP8(L)
-// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
-// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
-static VP8StatusCode ParseHeadersInternal(const uint8_t* data,
- size_t data_size,
- int* const width,
- int* const height,
- int* const has_alpha,
- WebPHeaderStructure* const headers) {
- int found_riff = 0;
- int found_vp8x = 0;
- VP8StatusCode status;
- WebPHeaderStructure hdrs;
-
- if (data == NULL || data_size < RIFF_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- memset(&hdrs, 0, sizeof(hdrs));
- hdrs.data = data;
- hdrs.data_size = data_size;
-
- // Skip over RIFF header.
- status = ParseRIFF(&data, &data_size, &hdrs.riff_size);
- if (status != VP8_STATUS_OK) {
- return status; // Wrong RIFF header / insufficient data.
- }
- found_riff = (hdrs.riff_size > 0);
-
- // Skip over VP8X.
- {
- uint32_t flags = 0;
- status = ParseVP8X(&data, &data_size, &found_vp8x, width, height, &flags);
- if (status != VP8_STATUS_OK) {
- return status; // Wrong VP8X / insufficient data.
- }
- if (!found_riff && found_vp8x) {
- // Note: This restriction may be removed in the future, if it becomes
- // necessary to send VP8X chunk to the decoder.
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- if (has_alpha != NULL) *has_alpha = !!(flags & ALPHA_FLAG_BIT);
- if (found_vp8x && headers == NULL) {
- return VP8_STATUS_OK; // Return features from VP8X header.
- }
- }
-
- if (data_size < TAG_SIZE) return VP8_STATUS_NOT_ENOUGH_DATA;
-
- // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH".
- if ((found_riff && found_vp8x) ||
- (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) {
- status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size,
- &hdrs.alpha_data, &hdrs.alpha_data_size);
- if (status != VP8_STATUS_OK) {
- return status; // Found an invalid chunk size / insufficient data.
- }
- }
-
- // Skip over VP8/VP8L header.
- status = ParseVP8Header(&data, &data_size, hdrs.riff_size,
- &hdrs.compressed_size, &hdrs.is_lossless);
- if (status != VP8_STATUS_OK) {
- return status; // Wrong VP8/VP8L chunk-header / insufficient data.
- }
- if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
-
- if (!hdrs.is_lossless) {
- if (data_size < VP8_FRAME_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- // Validates raw VP8 data.
- if (!VP8GetInfo(data, data_size,
- (uint32_t)hdrs.compressed_size, width, height)) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- } else {
- if (data_size < VP8L_FRAME_HEADER_SIZE) {
- return VP8_STATUS_NOT_ENOUGH_DATA;
- }
- // Validates raw VP8L data.
- if (!VP8LGetInfo(data, data_size, width, height, has_alpha)) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- }
-
- if (has_alpha != NULL) {
- // If the data did not contain a VP8X/VP8L chunk the only definitive way
- // to set this is by looking for alpha data (from an ALPH chunk).
- *has_alpha |= (hdrs.alpha_data != NULL);
- }
- if (headers != NULL) {
- *headers = hdrs;
- headers->offset = data - headers->data;
- assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
- assert(headers->offset == headers->data_size - data_size);
- }
- return VP8_STATUS_OK; // Return features from VP8 header.
-}
-
-VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) {
- assert(headers != NULL);
- // fill out headers, ignore width/height/has_alpha.
- return ParseHeadersInternal(headers->data, headers->data_size,
- NULL, NULL, NULL, headers);
-}
-
-//------------------------------------------------------------------------------
-// WebPDecParams
-
-void WebPResetDecParams(WebPDecParams* const params) {
- if (params) {
- memset(params, 0, sizeof(*params));
- }
-}
-
-//------------------------------------------------------------------------------
-// "Into" decoding variants
-
-// Main flow
-static VP8StatusCode DecodeInto(const uint8_t* const data, size_t data_size,
- WebPDecParams* const params) {
- VP8StatusCode status;
- VP8Io io;
- WebPHeaderStructure headers;
-
- headers.data = data;
- headers.data_size = data_size;
- status = WebPParseHeaders(&headers); // Process Pre-VP8 chunks.
- if (status != VP8_STATUS_OK) {
- return status;
- }
-
- assert(params != NULL);
- VP8InitIo(&io);
- io.data = headers.data + headers.offset;
- io.data_size = headers.data_size - headers.offset;
- WebPInitCustomIo(params, &io); // Plug the I/O functions.
-
- if (!headers.is_lossless) {
- VP8Decoder* const dec = VP8New();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
-#ifdef WEBP_USE_THREAD
- dec->use_threads_ = params->options && (params->options->use_threads > 0);
-#else
- dec->use_threads_ = 0;
-#endif
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
-
- // Decode bitstream header, update io->width/io->height.
- if (!VP8GetHeaders(dec, &io)) {
- status = dec->status_; // An error occurred. Grab error status.
- } else {
- // Allocate/check output buffers.
- status = WebPAllocateDecBuffer(io.width, io.height, params->options,
- params->output);
- if (status == VP8_STATUS_OK) { // Decode
- if (!VP8Decode(dec, &io)) {
- status = dec->status_;
- }
- }
- }
- VP8Delete(dec);
- } else {
- VP8LDecoder* const dec = VP8LNew();
- if (dec == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- if (!VP8LDecodeHeader(dec, &io)) {
- status = dec->status_; // An error occurred. Grab error status.
- } else {
- // Allocate/check output buffers.
- status = WebPAllocateDecBuffer(io.width, io.height, params->options,
- params->output);
- if (status == VP8_STATUS_OK) { // Decode
- if (!VP8LDecodeImage(dec)) {
- status = dec->status_;
- }
- }
- }
- VP8LDelete(dec);
- }
-
- if (status != VP8_STATUS_OK) {
- WebPFreeDecBuffer(params->output);
- }
- return status;
-}
-
-// Helpers
-static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
- const uint8_t* const data,
- size_t data_size,
- uint8_t* const rgba,
- int stride, size_t size) {
- WebPDecParams params;
- WebPDecBuffer buf;
- if (rgba == NULL) {
- return NULL;
- }
- WebPInitDecBuffer(&buf);
- WebPResetDecParams(&params);
- params.output = &buf;
- buf.colorspace = colorspace;
- buf.u.RGBA.rgba = rgba;
- buf.u.RGBA.stride = stride;
- buf.u.RGBA.size = size;
- buf.is_external_memory = 1;
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- return rgba;
-}
-
-uint8_t* WebPDecodeRGBInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_RGB, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeRGBAInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_RGBA, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeARGBInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_ARGB, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeBGRInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_BGR, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeBGRAInto(const uint8_t* data, size_t data_size,
- uint8_t* output, size_t size, int stride) {
- return DecodeIntoRGBABuffer(MODE_BGRA, data, data_size, output, stride, size);
-}
-
-uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size,
- uint8_t* luma, size_t luma_size, int luma_stride,
- uint8_t* u, size_t u_size, int u_stride,
- uint8_t* v, size_t v_size, int v_stride) {
- WebPDecParams params;
- WebPDecBuffer output;
- if (luma == NULL) return NULL;
- WebPInitDecBuffer(&output);
- WebPResetDecParams(&params);
- params.output = &output;
- output.colorspace = MODE_YUV;
- output.u.YUVA.y = luma;
- output.u.YUVA.y_stride = luma_stride;
- output.u.YUVA.y_size = luma_size;
- output.u.YUVA.u = u;
- output.u.YUVA.u_stride = u_stride;
- output.u.YUVA.u_size = u_size;
- output.u.YUVA.v = v;
- output.u.YUVA.v_stride = v_stride;
- output.u.YUVA.v_size = v_size;
- output.is_external_memory = 1;
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- return luma;
-}
-
-//------------------------------------------------------------------------------
-
-static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
- size_t data_size, int* const width, int* const height,
- WebPDecBuffer* const keep_info) {
- WebPDecParams params;
- WebPDecBuffer output;
-
- WebPInitDecBuffer(&output);
- WebPResetDecParams(&params);
- params.output = &output;
- output.colorspace = mode;
-
- // Retrieve (and report back) the required dimensions from bitstream.
- if (!WebPGetInfo(data, data_size, &output.width, &output.height)) {
- return NULL;
- }
- if (width != NULL) *width = output.width;
- if (height != NULL) *height = output.height;
-
- // Decode
- if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
- return NULL;
- }
- if (keep_info != NULL) { // keep track of the side-info
- WebPCopyDecBuffer(&output, keep_info);
- }
- // return decoded samples (don't clear 'output'!)
- return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
-}
-
-uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_RGB, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_RGBA, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_ARGB, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_BGR, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- return Decode(MODE_BGRA, data, data_size, width, height, NULL);
-}
-
-uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
- int* width, int* height, uint8_t** u, uint8_t** v,
- int* stride, int* uv_stride) {
- WebPDecBuffer output; // only to preserve the side-infos
- uint8_t* const out = Decode(MODE_YUV, data, data_size,
- width, height, &output);
-
- if (out != NULL) {
- const WebPYUVABuffer* const buf = &output.u.YUVA;
- *u = buf->u;
- *v = buf->v;
- *stride = buf->y_stride;
- *uv_stride = buf->u_stride;
- assert(buf->u_stride == buf->v_stride);
- }
- return out;
-}
-
-static void DefaultFeatures(WebPBitstreamFeatures* const features) {
- assert(features != NULL);
- memset(features, 0, sizeof(*features));
- features->bitstream_version = 0;
-}
-
-static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size,
- WebPBitstreamFeatures* const features) {
- if (features == NULL || data == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
- DefaultFeatures(features);
-
- // Only parse enough of the data to retrieve width/height/has_alpha.
- return ParseHeadersInternal(data, data_size,
- &features->width, &features->height,
- &features->has_alpha, NULL);
-}
-
-//------------------------------------------------------------------------------
-// WebPGetInfo()
-
-int WebPGetInfo(const uint8_t* data, size_t data_size,
- int* width, int* height) {
- WebPBitstreamFeatures features;
-
- if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) {
- return 0;
- }
-
- if (width != NULL) {
- *width = features.width;
- }
- if (height != NULL) {
- *height = features.height;
- }
-
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Advance decoding API
-
-int WebPInitDecoderConfigInternal(WebPDecoderConfig* config,
- int version) {
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return 0; // version mismatch
- }
- if (config == NULL) {
- return 0;
- }
- memset(config, 0, sizeof(*config));
- DefaultFeatures(&config->input);
- WebPInitDecBuffer(&config->output);
- return 1;
-}
-
-VP8StatusCode WebPGetFeaturesInternal(const uint8_t* data, size_t data_size,
- WebPBitstreamFeatures* features,
- int version) {
- VP8StatusCode status;
- if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
- return VP8_STATUS_INVALID_PARAM; // version mismatch
- }
- if (features == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
-
- status = GetFeatures(data, data_size, features);
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
- }
- return status;
-}
-
-VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config) {
- WebPDecParams params;
- VP8StatusCode status;
-
- if (config == NULL) {
- return VP8_STATUS_INVALID_PARAM;
- }
-
- status = GetFeatures(data, data_size, &config->input);
- if (status != VP8_STATUS_OK) {
- if (status == VP8_STATUS_NOT_ENOUGH_DATA) {
- return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error.
- }
- return status;
- }
-
- WebPResetDecParams(&params);
- params.output = &config->output;
- params.options = &config->options;
- status = DecodeInto(data, data_size, &params);
-
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Cropping and rescaling.
-
-int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
- VP8Io* const io, WEBP_CSP_MODE src_colorspace) {
- const int W = io->width;
- const int H = io->height;
- int x = 0, y = 0, w = W, h = H;
-
- // Cropping
- io->use_cropping = (options != NULL) && (options->use_cropping > 0);
- if (io->use_cropping) {
- w = options->crop_width;
- h = options->crop_height;
- x = options->crop_left;
- y = options->crop_top;
- if (!WebPIsRGBMode(src_colorspace)) { // only snap for YUV420 or YUV422
- x &= ~1;
- y &= ~1; // TODO(later): only for YUV420, not YUV422.
- }
- if (x < 0 || y < 0 || w <= 0 || h <= 0 || x + w > W || y + h > H) {
- return 0; // out of frame boundary error
- }
- }
- io->crop_left = x;
- io->crop_top = y;
- io->crop_right = x + w;
- io->crop_bottom = y + h;
- io->mb_w = w;
- io->mb_h = h;
-
- // Scaling
- io->use_scaling = (options != NULL) && (options->use_scaling > 0);
- if (io->use_scaling) {
- if (options->scaled_width <= 0 || options->scaled_height <= 0) {
- return 0;
- }
- io->scaled_width = options->scaled_width;
- io->scaled_height = options->scaled_height;
- }
-
- // Filter
- io->bypass_filtering = options && options->bypass_filtering;
-
- // Fancy upsampler
-#ifdef FANCY_UPSAMPLING
- io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling);
-#endif
-
- if (io->use_scaling) {
- // disable filter (only for large downscaling ratio).
- io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
- (io->scaled_height < H * 3 / 4);
- io->fancy_upsampling = 0;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
diff --git a/drivers/webpold/dec/webpi.h b/drivers/webpold/dec/webpi.h
deleted file mode 100644
index 44e5744411..0000000000
--- a/drivers/webpold/dec/webpi.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2011 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: WebP decoding parameters and custom IO on buffer
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#ifndef WEBP_DEC_WEBPI_H_
-#define WEBP_DEC_WEBPI_H_
-
-#if defined(__cplusplus) || defined(c_plusplus)
-extern "C" {
-#endif
-
-#include "../utils/rescaler.h"
-#include "./decode_vp8.h"
-
-//------------------------------------------------------------------------------
-// WebPDecParams: Decoding output parameters. Transient internal object.
-
-typedef struct WebPDecParams WebPDecParams;
-typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
-typedef int (*OutputRowFunc)(WebPDecParams* const p, int y_pos);
-
-struct WebPDecParams {
- WebPDecBuffer* output; // output buffer.
- uint8_t* tmp_y, *tmp_u, *tmp_v; // cache for the fancy upsampler
- // or used for tmp rescaling
-
- int last_y; // coordinate of the line that was last output
- const WebPDecoderOptions* options; // if not NULL, use alt decoding features
- // rescalers
- WebPRescaler scaler_y, scaler_u, scaler_v, scaler_a;
- void* memory; // overall scratch memory for the output work.
-
- OutputFunc emit; // output RGB or YUV samples
- OutputFunc emit_alpha; // output alpha channel
- OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
-};
-
-// Should be called first, before any use of the WebPDecParams object.
-void WebPResetDecParams(WebPDecParams* const params);
-
-//------------------------------------------------------------------------------
-// Header parsing helpers
-
-// Structure storing a description of the RIFF headers.
-typedef struct {
- const uint8_t* data; // input buffer
- size_t data_size; // input buffer size
- size_t offset; // offset to main data chunk (VP8 or VP8L)
- const uint8_t* alpha_data; // points to alpha chunk (if present)
- size_t alpha_data_size; // alpha chunk size
- size_t compressed_size; // VP8/VP8L compressed data size
- size_t riff_size; // size of the riff payload (or 0 if absent)
- int is_lossless; // true if a VP8L chunk is present
-} WebPHeaderStructure;
-
-// Skips over all valid chunks prior to the first VP8/VP8L frame header.
-// Returns VP8_STATUS_OK on success,
-// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
-// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
-// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
-// fields are updated appropriately upon success.
-VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);
-
-//------------------------------------------------------------------------------
-// Misc utils
-
-// Initializes VP8Io with custom setup, io and teardown functions. The default
-// hooks will use the supplied 'params' as io->opaque handle.
-void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io);
-
-// Setup crop_xxx fields, mb_w and mb_h in io. 'src_colorspace' refers
-// to the *compressed* format, not the output one.
-int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
- VP8Io* const io, WEBP_CSP_MODE src_colorspace);
-
-//------------------------------------------------------------------------------
-// Internal functions regarding WebPDecBuffer memory (in buffer.c).
-// Don't really need to be externally visible for now.
-
-// Prepare 'buffer' with the requested initial dimensions width/height.
-// If no external storage is supplied, initializes buffer by allocating output
-// memory and setting up the stride information. Validate the parameters. Return
-// an error code in case of problem (no memory, or invalid stride / size /
-// dimension / etc.). If *options is not NULL, also verify that the options'
-// parameters are valid and apply them to the width/height dimensions of the
-// output buffer. This takes cropping / scaling / rotation into account.
-VP8StatusCode WebPAllocateDecBuffer(int width, int height,
- const WebPDecoderOptions* const options,
- WebPDecBuffer* const buffer);
-
-// Copy 'src' into 'dst' buffer, making sure 'dst' is not marked as owner of the
-// memory (still held by 'src').
-void WebPCopyDecBuffer(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst);
-
-// Copy and transfer ownership from src to dst (beware of parameter order!)
-void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst);
-
-
-
-//------------------------------------------------------------------------------
-
-#if defined(__cplusplus) || defined(c_plusplus)
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_WEBPI_H_ */