diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c index 57423138..b584d3ff 100644 --- a/src/dec/vp8l_dec.c +++ b/src/dec/vp8l_dec.c @@ -822,7 +822,10 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr, //------------------------------------------------------------------------------ // Main loop, with custom row-processing function -typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); +// If 'wait_for_biggest_batch' is true, wait for enough data to fill the +// argb_cache as much as possible (usually NUM_ARGB_CACHE_ROWS). +typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row, + int wait_for_biggest_batch); static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row, int num_rows, const uint32_t* const rows) { @@ -846,16 +849,26 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row, // Processes (transforms, scales & color-converts) the rows decoded after the // last call. -static void ProcessRows(VP8LDecoder* const dec, int row) { +static void ProcessRows(VP8LDecoder* const dec, int row, + int wait_for_biggest_batch) { const uint32_t* const rows = dec->pixels + dec->width * dec->last_row; int num_rows; // In case of YUV conversion and if we do not need to get to the last row. - if (!WebPIsRGBMode(dec->output->colorspace) && row >= dec->io->crop_top && - row < dec->io->crop_bottom) { - // Make sure the number of rows to process is even. - if ((row - dec->io->crop_top) % 2 == 1) { - --row; + if (wait_for_biggest_batch) { + // In case of YUV conversion, and if we do not use the whole cropping + // region. + if (!WebPIsRGBMode(dec->output->colorspace) && row >= dec->io->crop_top && + row < dec->io->crop_bottom) { + // Make sure the number of rows to process is even. + if ((row - dec->io->crop_top) % 2 != 0) return; + // Make sure the cache is as full as possible. + if (row % NUM_ARGB_CACHE_ROWS != 0 && + (row + 1) % NUM_ARGB_CACHE_ROWS != 0) { + return; + } + } else { + if (row % NUM_ARGB_CACHE_ROWS != 0) return; } } num_rows = row - dec->last_row; @@ -1249,8 +1262,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, col = 0; ++row; if (process_func != NULL) { - if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { - process_func(dec, row); + if (row <= last_row) { + process_func(dec, row, /*wait_for_biggest_batch=*/1); } } if (color_cache != NULL) { @@ -1280,8 +1293,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, col -= width; ++row; if (process_func != NULL) { - if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { - process_func(dec, row); + if (row <= last_row) { + process_func(dec, row, /*wait_for_biggest_batch=*/1); } } } @@ -1324,7 +1337,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, } else if ((dec->incremental && src >= src_last) || !br->eos) { // Process the remaining rows corresponding to last row-block. if (process_func != NULL) { - process_func(dec, row > last_row ? last_row : row); + process_func(dec, row > last_row ? last_row : row, + /*wait_for_biggest_batch=*/0); } dec->status = VP8_STATUS_OK; dec->last_pixel = (int)(src - data); // end-of-scan marker @@ -1634,11 +1648,15 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) { //------------------------------------------------------------------------------ // Special row-processing that only stores the alpha data. -static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) { +static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row, + int wait_for_biggest_batch) { int cur_row = dec->last_row; int num_rows = last_row - cur_row; const uint32_t* in = dec->pixels + dec->width * cur_row; + if (wait_for_biggest_batch && last_row % NUM_ARGB_CACHE_ROWS != 0) { + return; + } assert(last_row <= dec->io->crop_bottom); while (num_rows > 0) { const int num_rows_to_process =