From 64eed3877900ece29be78e28c08d702642ed6926 Mon Sep 17 00:00:00 2001 From: Pascal Massimino Date: Fri, 18 Mar 2016 15:36:58 +0100 Subject: [PATCH] Pass stride parameter to WebPDequantizeLevels() and also pass 'VP8Io* io' extra param to VP8DecompressAlphaRows() This is somehow in preparation for some memory optimizations in the 'cropping' case. For now, only the easy crop_bottom case is optimized. Change-Id: Ib54531ba057bf62b98422dbb6c181dda626c72c2 --- src/dec/alpha.c | 18 ++++++++++++------ src/dec/frame.c | 2 +- src/dec/vp8i.h | 1 + src/utils/quant_levels_dec.c | 12 +++++++----- src/utils/quant_levels_dec.h | 4 ++-- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/dec/alpha.c b/src/dec/alpha.c index 52216fc4..6d54b92a 100644 --- a/src/dec/alpha.c +++ b/src/dec/alpha.c @@ -120,16 +120,18 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) { // Main entry point. const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, int row, int num_rows) { const int width = dec->pic_hdr_.width_; const int height = dec->pic_hdr_.height_; + assert(dec != NULL && io != NULL); + if (row < 0 || num_rows <= 0 || row + num_rows > height) { return NULL; // sanity check. } - if (row == 0) { - // Initialize decoding. + if (dec->alph_dec_ == NULL) { // Initialize decoder. assert(dec->alpha_plane_ != NULL); dec->alph_dec_ = ALPHNew(); if (dec->alph_dec_ == NULL) return NULL; @@ -147,12 +149,17 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, } } + if (io->use_cropping) { + if (row + num_rows > io->crop_bottom) { + num_rows = io->crop_bottom - row; + } + } + if (!dec->is_alpha_decoded_) { - int ok = 0; + int ok = ALPHDecode(dec, row, num_rows); assert(dec->alph_dec_ != NULL); - ok = ALPHDecode(dec, row, num_rows); if (ok && dec->alpha_dithering_ > 0) { - ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, + ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, width, dec->alpha_dithering_); } if (!ok || dec->is_alpha_decoded_) { @@ -161,7 +168,6 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, } if (!ok) return NULL; // Error. } - // Return a pointer to the current decoded row. return dec->alpha_plane_ + row * width; } diff --git a/src/dec/frame.c b/src/dec/frame.c index b882133e..541347ce 100644 --- a/src/dec/frame.c +++ b/src/dec/frame.c @@ -462,7 +462,7 @@ static int FinishRow(VP8Decoder* const dec, VP8Io* const io) { if (dec->alpha_data_ != NULL && y_start < y_end) { // TODO(skal): testing presence of alpha with dec->alpha_data_ is not a // good idea. - io->a = VP8DecompressAlphaRows(dec, y_start, y_end - y_start); + io->a = VP8DecompressAlphaRows(dec, io, y_start, y_end - y_start); if (io->a == NULL) { return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, "Could not decode alpha data."); diff --git a/src/dec/vp8i.h b/src/dec/vp8i.h index 59606998..6b9afd75 100644 --- a/src/dec/vp8i.h +++ b/src/dec/vp8i.h @@ -306,6 +306,7 @@ int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br); // in alpha.c const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, + const VP8Io* const io, int row, int num_rows); //------------------------------------------------------------------------------ diff --git a/src/utils/quant_levels_dec.c b/src/utils/quant_levels_dec.c index 5b8b8b49..05b42616 100644 --- a/src/utils/quant_levels_dec.c +++ b/src/utils/quant_levels_dec.c @@ -44,6 +44,7 @@ static const uint8_t kOrderedDither[DSIZE][DSIZE] = { typedef struct { int width_, height_; // dimension + int stride_; // stride in bytes int row_; // current input row being processed uint8_t* src_; // input pointer uint8_t* dst_; // output pointer @@ -99,7 +100,7 @@ static void VFilter(SmoothParams* const p) { // We replicate edges, as it's somewhat easier as a boundary condition. // That's why we don't update the 'src' pointer on top/bottom area: if (p->row_ >= 0 && p->row_ < p->height_ - 1) { - p->src_ += p->width_; + p->src_ += p->stride_; } } @@ -149,7 +150,7 @@ static void ApplyFilter(SmoothParams* const p) { #endif } } - p->dst_ += w; // advance output pointer + p->dst_ += p->stride_; // advance output pointer } //------------------------------------------------------------------------------ @@ -208,7 +209,7 @@ static void CountLevels(const uint8_t* const data, int size, } // Initialize all params. -static int InitParams(uint8_t* const data, int width, int height, +static int InitParams(uint8_t* const data, int width, int height, int stride, int radius, SmoothParams* const p) { const int R = 2 * radius + 1; // total size of the kernel @@ -233,6 +234,7 @@ static int InitParams(uint8_t* const data, int width, int height, p->width_ = width; p->height_ = height; + p->stride_ = stride; p->src_ = data; p->dst_ = data; p->radius_ = radius; @@ -253,7 +255,7 @@ static void CleanupParams(SmoothParams* const p) { WebPSafeFree(p->mem_); } -int WebPDequantizeLevels(uint8_t* const data, int width, int height, +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, int strength) { const int radius = 4 * strength / 100; if (strength < 0 || strength > 100) return 0; @@ -261,7 +263,7 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, if (radius > 0) { SmoothParams p; memset(&p, 0, sizeof(p)); - if (!InitParams(data, width, height, radius, &p)) return 0; + if (!InitParams(data, width, height, stride, radius, &p)) return 0; if (p.num_levels_ > 2) { for (; p.row_ < p.height_; ++p.row_) { VFilter(&p); // accumulate average of input diff --git a/src/utils/quant_levels_dec.h b/src/utils/quant_levels_dec.h index 9aab0680..59a13495 100644 --- a/src/utils/quant_levels_dec.h +++ b/src/utils/quant_levels_dec.h @@ -21,11 +21,11 @@ extern "C" { #endif // Apply post-processing to input 'data' of size 'width'x'height' assuming that -// the source was quantized to a reduced number of levels. +// the source was quantized to a reduced number of levels. 'stride' is in bytes. // Strength is in [0..100] and controls the amount of dithering applied. // Returns false in case of error (data is NULL, invalid parameters, // malloc failure, ...). -int WebPDequantizeLevels(uint8_t* const data, int width, int height, +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, int strength); #ifdef __cplusplus