| Index: third_party/libwebp/enc/webpenc.c
|
| diff --git a/third_party/libwebp/enc/webpenc.c b/third_party/libwebp/enc/webpenc.c
|
| index 00c7d61cca9872c503f596eebe00807d9af9db57..3c275589fc17809d542f618373bab6383a6adeb0 100644
|
| --- a/third_party/libwebp/enc/webpenc.c
|
| +++ b/third_party/libwebp/enc/webpenc.c
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 Google Inc.
|
| +// 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/
|
| @@ -14,7 +14,9 @@
|
| #include <string.h>
|
| #include <math.h>
|
|
|
| -#include "vp8enci.h"
|
| +#include "./vp8enci.h"
|
| +#include "./vp8li.h"
|
| +#include "../utils/utils.h"
|
|
|
| // #define PRINT_MEMORY_INFO
|
|
|
| @@ -45,11 +47,11 @@ static int DummyWriter(const uint8_t* data, size_t data_size,
|
| return 1;
|
| }
|
|
|
| -int WebPPictureInitInternal(WebPPicture* const picture, int version) {
|
| - if (version != WEBP_ENCODER_ABI_VERSION) {
|
| +int WebPPictureInitInternal(WebPPicture* picture, int version) {
|
| + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
|
| return 0; // caller/system version mismatch!
|
| }
|
| - if (picture) {
|
| + if (picture != NULL) {
|
| memset(picture, 0, sizeof(*picture));
|
| picture->writer = DummyWriter;
|
| WebPEncodingSetError(picture, VP8_ENC_OK);
|
| @@ -142,8 +144,8 @@ static void MapConfigToTools(VP8Encoder* const enc) {
|
| // LFStats: 2048
|
| // Picture size (yuv): 589824
|
|
|
| -static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
| - WebPPicture* const picture) {
|
| +static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
|
| + WebPPicture* const picture) {
|
| const int use_filter =
|
| (config->filter_strength > 0) || (config->autofilter > 0);
|
| const int mb_w = (picture->width + 15) >> 4;
|
| @@ -163,13 +165,14 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
| config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0;
|
| VP8Encoder* enc;
|
| uint8_t* mem;
|
| - size_t size = sizeof(VP8Encoder) + ALIGN_CST // main struct
|
| - + cache_size // working caches
|
| - + info_size // modes info
|
| - + preds_size // prediction modes
|
| - + samples_size // top/left samples
|
| - + nz_size // coeff context bits
|
| - + lf_stats_size; // autofilter stats
|
| + const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct
|
| + + ALIGN_CST // cache alignment
|
| + + cache_size // working caches
|
| + + info_size // modes info
|
| + + preds_size // prediction modes
|
| + + samples_size // top/left samples
|
| + + nz_size // coeff context bits
|
| + + lf_stats_size; // autofilter stats
|
|
|
| #ifdef PRINT_MEMORY_INFO
|
| printf("===================================\n");
|
| @@ -197,7 +200,7 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
| mb_w * mb_h * 384 * sizeof(uint8_t));
|
| printf("===================================\n");
|
| #endif
|
| - mem = (uint8_t*)malloc(size);
|
| + mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
|
| if (mem == NULL) {
|
| WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
|
| return NULL;
|
| @@ -242,6 +245,7 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
| enc->config_ = config;
|
| enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
|
| enc->pic_ = picture;
|
| + enc->percent_ = 0;
|
|
|
| MapConfigToTools(enc);
|
| VP8EncDspInit();
|
| @@ -250,18 +254,18 @@ static VP8Encoder* InitEncoder(const WebPConfig* const config,
|
| ResetFilterHeader(enc);
|
| ResetBoundaryPredictions(enc);
|
|
|
| -#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| VP8EncInitAlpha(enc);
|
| +#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| VP8EncInitLayer(enc);
|
| #endif
|
|
|
| return enc;
|
| }
|
|
|
| -static void DeleteEncoder(VP8Encoder* enc) {
|
| - if (enc) {
|
| -#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| +static void DeleteVP8Encoder(VP8Encoder* enc) {
|
| + if (enc != NULL) {
|
| VP8EncDeleteAlpha(enc);
|
| +#ifdef WEBP_EXPERIMENTAL_FEATURES
|
| VP8EncDeleteLayer(enc);
|
| #endif
|
| free(enc);
|
| @@ -282,11 +286,12 @@ static void FinalizePSNR(const VP8Encoder* const enc) {
|
| stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4);
|
| stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4);
|
| stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2);
|
| + stats->PSNR[4] = (float)GetPSNR(sse[3], size);
|
| }
|
|
|
| static void StoreStats(VP8Encoder* const enc) {
|
| WebPAuxStats* const stats = enc->pic_->stats;
|
| - if (stats) {
|
| + if (stats != NULL) {
|
| int i, s;
|
| for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
|
| stats->segment_level[i] = enc->dqm_[i].fstrength_;
|
| @@ -301,19 +306,32 @@ static void StoreStats(VP8Encoder* const enc) {
|
| stats->block_count[i] = enc->block_count_[i];
|
| }
|
| }
|
| + WebPReportProgress(enc->pic_, 100, &enc->percent_); // done!
|
| }
|
|
|
| -int WebPEncodingSetError(WebPPicture* const pic, WebPEncodingError error) {
|
| - assert((int)error <= VP8_ENC_ERROR_BAD_WRITE);
|
| +int WebPEncodingSetError(const WebPPicture* const pic,
|
| + WebPEncodingError error) {
|
| + assert((int)error < VP8_ENC_ERROR_LAST);
|
| assert((int)error >= VP8_ENC_OK);
|
| - pic->error_code = error;
|
| + ((WebPPicture*)pic)->error_code = error;
|
| return 0;
|
| }
|
|
|
| +int WebPReportProgress(const WebPPicture* const pic,
|
| + int percent, int* const percent_store) {
|
| + if (percent_store != NULL && percent != *percent_store) {
|
| + *percent_store = percent;
|
| + if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
|
| + // user abort requested
|
| + WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
|
| + return 0;
|
| + }
|
| + }
|
| + return 1; // ok
|
| +}
|
| //------------------------------------------------------------------------------
|
|
|
| -int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
|
| - VP8Encoder* enc;
|
| +int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
|
| int ok;
|
|
|
| if (pic == NULL)
|
| @@ -325,23 +343,43 @@ int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) {
|
| return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
|
| if (pic->width <= 0 || pic->height <= 0)
|
| return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
|
| - if (pic->y == NULL || pic->u == NULL || pic->v == NULL)
|
| - return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
|
| if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
|
| return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
|
|
|
| - enc = InitEncoder(config, pic);
|
| - if (enc == NULL) return 0; // pic->error is already set.
|
| - ok = VP8EncAnalyze(enc)
|
| - && VP8StatLoop(enc)
|
| - && VP8EncLoop(enc)
|
| + if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
|
| +
|
| + if (!config->lossless) {
|
| + VP8Encoder* enc = NULL;
|
| + if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
|
| + if (pic->argb != NULL) {
|
| + if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0;
|
| + } else {
|
| + return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
|
| + }
|
| + }
|
| +
|
| + enc = InitVP8Encoder(config, pic);
|
| + if (enc == NULL) return 0; // pic->error is already set.
|
| + // Note: each of the tasks below account for 20% in the progress report.
|
| + ok = VP8EncAnalyze(enc)
|
| + && VP8StatLoop(enc)
|
| + && VP8EncLoop(enc)
|
| + && VP8EncFinishAlpha(enc)
|
| #ifdef WEBP_EXPERIMENTAL_FEATURES
|
| - && VP8EncFinishAlpha(enc)
|
| - && VP8EncFinishLayer(enc)
|
| + && VP8EncFinishLayer(enc)
|
| #endif
|
| - && VP8EncWrite(enc);
|
| - StoreStats(enc);
|
| - DeleteEncoder(enc);
|
| + && VP8EncWrite(enc);
|
| + StoreStats(enc);
|
| + if (!ok) {
|
| + VP8EncFreeBitWriters(enc);
|
| + }
|
| + DeleteVP8Encoder(enc);
|
| + } else {
|
| + if (pic->argb == NULL)
|
| + return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
|
| +
|
| + ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
|
| + }
|
|
|
| return ok;
|
| }
|
|
|