blob: c22ee0dfeeb69164c5fc3c33d451409a2624c738 [file]
// 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 "../webp/decode_vp8.h"
//------------------------------------------------------------------------------
// WebPDecParams: Decoding output parameters. Transient internal object.
typedef struct WebPDecParams WebPDecParams;
typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
// Structure use for on-the-fly rescaling
typedef struct {
int x_expand; // true if we're expanding in the x direction
int num_channels; // bytes to jump between pixels
int fy_scale, fx_scale; // fixed-point scaling factor
int64_t fxy_scale; // ''
// we need hpel-precise add/sub increments, for the downsampled U/V planes.
int y_accum; // vertical accumulator
int y_add, y_sub; // vertical increments (add ~= src, sub ~= dst)
int x_add, x_sub; // horizontal increments (add ~= src, sub ~= dst)
int src_width, src_height; // source dimensions
int dst_width, dst_height; // destination dimensions
uint8_t* dst;
int dst_stride;
int32_t* irow, *frow; // work buffer
} WebPRescaler;
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
};
// Should be called first, before any use of the WebPDecParams object.
void WebPResetDecParams(WebPDecParams* const params);
//------------------------------------------------------------------------------
// Header parsing helpers
#define TAG_SIZE 4
#define CHUNK_HEADER_SIZE 8
#define RIFF_HEADER_SIZE 12
#define FRAME_CHUNK_SIZE 20
#define LOOP_CHUNK_SIZE 4
#define TILE_CHUNK_SIZE 8
#define VP8X_CHUNK_SIZE 12
#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data.
// 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.
VP8StatusCode WebPParseRIFF(const uint8_t** data, uint32_t* data_size,
uint32_t* riff_size);
// 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 VP8 chunk is found, bytes_skipped is set to the total number of bytes
// that are skipped; also Width, Height & Flags are set to the corresponding
// fields extracted from the VP8X chunk.
VP8StatusCode WebPParseVP8X(const uint8_t** data, uint32_t* data_size,
uint32_t* bytes_skipped,
int* width, int* height, uint32_t* flags);
// Skips to the next VP8 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 a VP8 chunk is found, bytes_skipped is set to the total number of bytes
// that are skipped. Also, if an alpha chunk is found, alpha_data and alpha_size
// are set appropriately.
VP8StatusCode WebPParseOptionalChunks(const uint8_t** data, uint32_t* data_size,
uint32_t riff_size,
uint32_t* bytes_skipped,
const uint8_t** alpha_data,
uint32_t* alpha_size);
// Validates the VP8 Header ("VP8 nnnn") and skips over it.
// Returns VP8_STATUS_BITSTREAM_ERROR for invalid (vp8_chunk_size greater than
// riff_size) VP8 header,
// VP8_STATUS_NOT_ENOUGH_DATA in case of insufficient data, and
// VP8_STATUS_OK otherwise.
// If a VP8 chunk is found, bytes_skipped is set to the total number of bytes
// that are skipped and vp8_chunk_size is set to the corresponding size
// extracted from the VP8 chunk header.
// For a partial VP8 chunk, vp8_chunk_size is set to 0.
VP8StatusCode WebPParseVP8Header(const uint8_t** data, uint32_t* data_size,
uint32_t riff_size, uint32_t* bytes_skipped,
uint32_t* vp8_chunk_size);
// Skips over all valid chunks prior to the first VP8 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.
// Also, data, data_size, vp8_size, bytes_skipped, alpha_data & alpha_size are
// updated appropriately on success, where
// vp8_size is the size of VP8 chunk data (extracted from VP8 chunk header) and
// bytes_skipped is set to the total number of bytes that are skipped.
VP8StatusCode WebPParseHeaders(const uint8_t** data, uint32_t* data_size,
uint32_t* vp8_size, uint32_t* bytes_skipped,
const uint8_t** alpha_data,
uint32_t* alpha_size);
//------------------------------------------------------------------------------
// 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);
//------------------------------------------------------------------------------
// 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);
//------------------------------------------------------------------------------
// Cropping and rescaling.
// Setup crop_xxx fields, mb_w and mb_h
int WebPIoInitFromOptions(const WebPDecoderOptions* const options,
VP8Io* const io);
// Initialize a rescaler given scratch area 'work' and dimensions of src & dst.
void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
uint8_t* const dst, int dst_width, int dst_height,
int dst_stride, int num_channels, int x_add, int x_sub,
int y_add, int y_sub, int32_t* const work);
// Import a row of data and save its contribution in the rescaler.
// 'channel' denotes the channel number to be imported.
void WebPRescalerImportRow(const uint8_t* const src, int channel,
WebPRescaler* const wrk);
// Export a row from rescaler.
void WebPRescalerExportRow(WebPRescaler* const wrk);
//------------------------------------------------------------------------------
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
#endif /* WEBP_DEC_WEBPI_H_ */