| Index: third_party/libwebp/dec/io.c
|
| diff --git a/third_party/libwebp/dec/io.c b/third_party/libwebp/dec/io.c
|
| index 1ba376ed27e0dbb2a8fee895aa6a91e592fb78ce..8094e44f632ed4338c31d7225c5bde8af209d852 100644
|
| --- a/third_party/libwebp/dec/io.c
|
| +++ b/third_party/libwebp/dec/io.c
|
| @@ -17,6 +17,7 @@
|
| #include "./webpi.h"
|
| #include "../dsp/dsp.h"
|
| #include "../dsp/yuv.h"
|
| +#include "../utils/utils.h"
|
|
|
| //------------------------------------------------------------------------------
|
| // Main YUV<->RGB conversion functions
|
| @@ -44,27 +45,13 @@ static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) {
|
|
|
| // 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);
|
| - }
|
| + WebPDecBuffer* const output = p->output;
|
| + WebPRGBABuffer* const buf = &output->u.RGBA;
|
| + uint8_t* const dst = buf->rgba + io->mb_y * buf->stride;
|
| + WebPSamplerProcessPlane(io->y, io->y_stride,
|
| + io->u, io->v, io->uv_stride,
|
| + dst, buf->stride, io->mb_w, io->mb_h,
|
| + WebPSamplers[output->colorspace]);
|
| return io->mb_h;
|
| }
|
|
|
| @@ -250,7 +237,11 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
|
| int num_rows;
|
| const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
|
| uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
|
| +#ifdef WEBP_SWAP_16BIT_CSP
|
| + uint8_t* alpha_dst = base_rgba;
|
| +#else
|
| uint8_t* alpha_dst = base_rgba + 1;
|
| +#endif
|
| uint32_t alpha_mask = 0x0f;
|
| int i, j;
|
|
|
| @@ -289,7 +280,17 @@ static int Rescale(const uint8_t* src, int src_stride,
|
| 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);
|
| + WebPRescaler* const scaler = &p->scaler_y;
|
| + int num_lines_out = 0;
|
| + if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) {
|
| + // Before rescaling, we premultiply the luma directly into the io->y
|
| + // internal buffer. This is OK since these samples are not used for
|
| + // intra-prediction (the top samples are saved in cache_y_/u_/v_).
|
| + // But we need to cast the const away, though.
|
| + WebPMultRows((uint8_t*)io->y, io->y_stride,
|
| + io->a, io->width, io->mb_w, mb_h, 0);
|
| + }
|
| + num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler);
|
| 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;
|
| @@ -297,7 +298,14 @@ static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) {
|
|
|
| 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);
|
| + const WebPYUVABuffer* const buf = &p->output->u.YUVA;
|
| + uint8_t* dst_y = buf->y + p->last_y * buf->y_stride;
|
| + const uint8_t* src_a = buf->a + p->last_y * buf->a_stride;
|
| + const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a);
|
| + if (num_lines_out > 0) { // unmultiply the Y
|
| + WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride,
|
| + p->scaler_a.dst_width, num_lines_out, 1);
|
| + }
|
| }
|
| return 0;
|
| }
|
| @@ -316,11 +324,11 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| size_t tmp_size;
|
| int32_t* work;
|
|
|
| - tmp_size = work_size + 2 * uv_work_size;
|
| + tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
|
| if (has_alpha) {
|
| - tmp_size += work_size;
|
| + tmp_size += work_size * sizeof(*work);
|
| }
|
| - p->memory = calloc(1, tmp_size * sizeof(*work));
|
| + p->memory = WebPSafeCalloc(1ULL, tmp_size);
|
| if (p->memory == NULL) {
|
| return 0; // memory error
|
| }
|
| @@ -347,6 +355,7 @@ static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| io->mb_w, out_width, io->mb_h, out_height,
|
| work + work_size + 2 * uv_work_size);
|
| p->emit_alpha = EmitRescaledAlphaYUV;
|
| + WebPInitAlphaProcessing();
|
| }
|
| return 1;
|
| }
|
| @@ -366,9 +375,9 @@ static int ExportRGB(WebPDecParams* const p, int y_pos) {
|
| 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);
|
| + WebPRescalerExportRow(&p->scaler_y, 0);
|
| + WebPRescalerExportRow(&p->scaler_u, 0);
|
| + WebPRescalerExportRow(&p->scaler_v, 0);
|
| convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst,
|
| dst, p->scaler_y.dst_width);
|
| dst += buf->stride;
|
| @@ -416,7 +425,7 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos) {
|
| while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
|
| int i;
|
| assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| - WebPRescalerExportRow(&p->scaler_a);
|
| + WebPRescalerExportRow(&p->scaler_a, 0);
|
| for (i = 0; i < width; ++i) {
|
| const uint32_t alpha_value = p->scaler_a.dst[i];
|
| dst[4 * i] = alpha_value;
|
| @@ -435,7 +444,11 @@ static int ExportAlpha(WebPDecParams* const p, int y_pos) {
|
| 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;
|
| +#ifdef WEBP_SWAP_16BIT_CSP
|
| + uint8_t* alpha_dst = base_rgba;
|
| +#else
|
| uint8_t* alpha_dst = base_rgba + 1;
|
| +#endif
|
| int num_lines_out = 0;
|
| const WEBP_CSP_MODE colorspace = p->output->colorspace;
|
| const int width = p->scaler_a.dst_width;
|
| @@ -445,7 +458,7 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
|
| while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
|
| int i;
|
| assert(p->last_y + y_pos + num_lines_out < p->output->height);
|
| - WebPRescalerExportRow(&p->scaler_a);
|
| + WebPRescalerExportRow(&p->scaler_a, 0);
|
| 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;
|
| @@ -484,7 +497,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| 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;
|
| + size_t tmp_size1, tmp_size2, total_size;
|
|
|
| tmp_size1 = 3 * work_size;
|
| tmp_size2 = 3 * out_width;
|
| @@ -492,7 +505,8 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| tmp_size1 += work_size;
|
| tmp_size2 += out_width;
|
| }
|
| - p->memory = calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
|
| + total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
|
| + p->memory = WebPSafeCalloc(1ULL, total_size);
|
| if (p->memory == NULL) {
|
| return 0; // memory error
|
| }
|
| @@ -524,6 +538,7 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) {
|
| } else {
|
| p->emit_alpha_row = ExportAlpha;
|
| }
|
| + WebPInitAlphaProcessing();
|
| }
|
| return 1;
|
| }
|
| @@ -544,7 +559,9 @@ static int CustomSetup(VP8Io* io) {
|
| if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) {
|
| return 0;
|
| }
|
| -
|
| + if (is_alpha && WebPIsPremultipliedMode(colorspace)) {
|
| + WebPInitUpsamplers();
|
| + }
|
| if (io->use_scaling) {
|
| const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p);
|
| if (!ok) {
|
| @@ -553,10 +570,10 @@ static int CustomSetup(VP8Io* io) {
|
| } else {
|
| if (is_rgb) {
|
| p->emit = EmitSampledRGB; // default
|
| -#ifdef FANCY_UPSAMPLING
|
| if (io->fancy_upsampling) {
|
| +#ifdef FANCY_UPSAMPLING
|
| const int uv_width = (io->mb_w + 1) >> 1;
|
| - p->memory = malloc(io->mb_w + 2 * uv_width);
|
| + p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width));
|
| if (p->memory == NULL) {
|
| return 0; // memory error.
|
| }
|
| @@ -565,18 +582,22 @@ static int CustomSetup(VP8Io* io) {
|
| p->tmp_v = p->tmp_u + uv_width;
|
| p->emit = EmitFancyRGB;
|
| WebPInitUpsamplers();
|
| - }
|
| #endif
|
| + } else {
|
| + WebPInitSamplers();
|
| + }
|
| } 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) {
|
| + WebPInitAlphaProcessing();
|
| + }
|
| }
|
| }
|
|
|
| @@ -610,7 +631,7 @@ static int CustomPut(const VP8Io* io) {
|
|
|
| static void CustomTeardown(const VP8Io* io) {
|
| WebPDecParams* const p = (WebPDecParams*)io->opaque;
|
| - free(p->memory);
|
| + WebPSafeFree(p->memory);
|
| p->memory = NULL;
|
| }
|
|
|
| @@ -625,4 +646,3 @@ void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) {
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| -
|
|
|