From b0ffc43700565119b89ba7211320b42572c0a190 Mon Sep 17 00:00:00 2001 From: Urvang Joshi Date: Thu, 2 May 2013 18:24:46 -0700 Subject: [PATCH] Alpha decoding: significantly reduce memory usage Simply get rid of an intermediate buffer of size width x height, by using the fact that stride == width in this case. Change-Id: I92376a2561a3beb6e723e8bcf7340c7f348e02c2 (cherry picked from commit edccd194362f86ed3b8106dd2474688e4a2a305e) --- src/dec/alpha.c | 52 ++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/src/dec/alpha.c b/src/dec/alpha.c index 630e367f..5c173718 100644 --- a/src/dec/alpha.c +++ b/src/dec/alpha.c @@ -20,20 +20,10 @@ 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. +// dimension 'height'x'width', as that of the image. // // Returns 1 on successfully decoding the compressed alpha and // 0 if either: @@ -41,16 +31,16 @@ static void CopyPlane(const uint8_t* src, int src_stride, // 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; + int width, int height, uint8_t* output) { WEBP_FILTER_TYPE filter; int pre_processing; int rsrv; int ok = 0; int method; + const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN; + const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN; - assert(width > 0 && height > 0 && stride >= width); + assert(width > 0 && height > 0); assert(data != NULL && output != NULL); if (data_size <= ALPHA_HEADER_LEN) { @@ -70,15 +60,12 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, } if (method == ALPHA_NO_COMPRESSION) { - ok = (data_size >= decoded_size); - decoded_data = (uint8_t*)data + ALPHA_HEADER_LEN; + const size_t alpha_decoded_size = height * width; + ok = (alpha_data_size >= alpha_decoded_size); + if (ok) memcpy(output, alpha_data, alpha_decoded_size); } 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); + ok = VP8LDecodeAlphaImageStream(width, height, alpha_data, alpha_data_size, + output); } if (ok) { @@ -86,18 +73,13 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, if (unfilter_func != NULL) { // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode // and apply filter per image-row. - unfilter_func(width, height, width, decoded_data); + unfilter_func(width, height, width, output); } - // 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); + ok = DequantizeLevels(output, width, height); } } - if (method != ALPHA_NO_COMPRESSION) { - free(decoded_data); - } return ok; } @@ -105,9 +87,10 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, int row, int num_rows) { - const int stride = dec->pic_hdr_.width_; + const int width = dec->pic_hdr_.width_; + const int height = dec->pic_hdr_.height_; - if (row < 0 || num_rows < 0 || row + num_rows > dec->pic_hdr_.height_) { + if (row < 0 || num_rows < 0 || row + num_rows > height) { return NULL; // sanity check. } @@ -115,15 +98,14 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, // Decode everything during the first call. assert(!dec->is_alpha_decoded_); if (!DecodeAlpha(dec->alpha_data_, (size_t)dec->alpha_data_size_, - dec->pic_hdr_.width_, dec->pic_hdr_.height_, stride, - dec->alpha_plane_)) { + width, height, dec->alpha_plane_)) { return NULL; // Error. } dec->is_alpha_decoded_ = 1; } // Return a pointer to the current decoded row. - return dec->alpha_plane_ + row * stride; + return dec->alpha_plane_ + row * width; } #if defined(__cplusplus) || defined(c_plusplus)