Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/libwebp/enc/webpenc.c

Issue 1546003002: libwebp: update to 0.5.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase around clang-cl fix Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 Google Inc. All Rights Reserved. 1 // Copyright 2011 Google Inc. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source 4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
9 // 9 //
10 // WebP encoder: main entry point 10 // WebP encoder: main entry point
11 // 11 //
12 // Author: Skal (pascal.massimino@gmail.com) 12 // Author: Skal (pascal.massimino@gmail.com)
13 13
14 #include <assert.h> 14 #include <assert.h>
15 #include <stdlib.h> 15 #include <stdlib.h>
16 #include <string.h> 16 #include <string.h>
17 #include <math.h> 17 #include <math.h>
18 18
19 #include "./cost.h"
19 #include "./vp8enci.h" 20 #include "./vp8enci.h"
20 #include "./vp8li.h" 21 #include "./vp8li.h"
21 #include "./cost.h"
22 #include "../utils/utils.h" 22 #include "../utils/utils.h"
23 23
24 // #define PRINT_MEMORY_INFO 24 // #define PRINT_MEMORY_INFO
25 25
26 #ifdef PRINT_MEMORY_INFO 26 #ifdef PRINT_MEMORY_INFO
27 #include <stdio.h> 27 #include <stdio.h>
28 #endif 28 #endif
29 29
30 //------------------------------------------------------------------------------ 30 //------------------------------------------------------------------------------
31 31
32 int WebPGetEncoderVersion(void) { 32 int WebPGetEncoderVersion(void) {
33 return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; 33 return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
34 } 34 }
35 35
36 //------------------------------------------------------------------------------ 36 //------------------------------------------------------------------------------
37 // VP8Encoder 37 // VP8Encoder
38 //------------------------------------------------------------------------------ 38 //------------------------------------------------------------------------------
39 39
40 static void ResetSegmentHeader(VP8Encoder* const enc) { 40 static void ResetSegmentHeader(VP8Encoder* const enc) {
41 VP8SegmentHeader* const hdr = &enc->segment_hdr_; 41 VP8EncSegmentHeader* const hdr = &enc->segment_hdr_;
42 hdr->num_segments_ = enc->config_->segments; 42 hdr->num_segments_ = enc->config_->segments;
43 hdr->update_map_ = (hdr->num_segments_ > 1); 43 hdr->update_map_ = (hdr->num_segments_ > 1);
44 hdr->size_ = 0; 44 hdr->size_ = 0;
45 } 45 }
46 46
47 static void ResetFilterHeader(VP8Encoder* const enc) { 47 static void ResetFilterHeader(VP8Encoder* const enc) {
48 VP8FilterHeader* const hdr = &enc->filter_hdr_; 48 VP8EncFilterHeader* const hdr = &enc->filter_hdr_;
49 hdr->simple_ = 1; 49 hdr->simple_ = 1;
50 hdr->level_ = 0; 50 hdr->level_ = 0;
51 hdr->sharpness_ = 0; 51 hdr->sharpness_ = 0;
52 hdr->i4x4_lf_delta_ = 0; 52 hdr->i4x4_lf_delta_ = 0;
53 } 53 }
54 54
55 static void ResetBoundaryPredictions(VP8Encoder* const enc) { 55 static void ResetBoundaryPredictions(VP8Encoder* const enc) {
56 // init boundary values once for all 56 // init boundary values once for all
57 // Note: actually, initializing the preds_[] is only needed for intra4. 57 // Note: actually, initializing the preds_[] is only needed for intra4.
58 int i; 58 int i;
(...skipping 13 matching lines...) Expand all
72 // Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | 72 // Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 |
73 //-------------------+---+---+---+---+---+---+---+ 73 //-------------------+---+---+---+---+---+---+---+
74 // fast probe | x | | | x | | | | 74 // fast probe | x | | | x | | | |
75 //-------------------+---+---+---+---+---+---+---+ 75 //-------------------+---+---+---+---+---+---+---+
76 // dynamic proba | ~ | x | x | x | x | x | x | 76 // dynamic proba | ~ | x | x | x | x | x | x |
77 //-------------------+---+---+---+---+---+---+---+ 77 //-------------------+---+---+---+---+---+---+---+
78 // fast mode analysis| | | | | x | x | x | 78 // fast mode analysis| | | | | x | x | x |
79 //-------------------+---+---+---+---+---+---+---+ 79 //-------------------+---+---+---+---+---+---+---+
80 // basic rd-opt | | | | x | x | x | x | 80 // basic rd-opt | | | | x | x | x | x |
81 //-------------------+---+---+---+---+---+---+---+ 81 //-------------------+---+---+---+---+---+---+---+
82 // disto-score i4/16 | | | x | | | | | 82 // disto-refine i4/16| x | x | x | | | | |
83 //-------------------+---+---+---+---+---+---+---+
84 // disto-refine uv | | x | x | | | | |
83 //-------------------+---+---+---+---+---+---+---+ 85 //-------------------+---+---+---+---+---+---+---+
84 // rd-opt i4/16 | | | ~ | x | x | x | x | 86 // rd-opt i4/16 | | | ~ | x | x | x | x |
85 //-------------------+---+---+---+---+---+---+---+ 87 //-------------------+---+---+---+---+---+---+---+
86 // token buffer (opt)| | | | x | x | x | x | 88 // token buffer (opt)| | | | x | x | x | x |
87 //-------------------+---+---+---+---+---+---+---+ 89 //-------------------+---+---+---+---+---+---+---+
88 // Trellis | | | | | | x |Ful| 90 // Trellis | | | | | | x |Ful|
89 //-------------------+---+---+---+---+---+---+---+ 91 //-------------------+---+---+---+---+---+---+---+
90 // full-SNS | | | | | x | x | x | 92 // full-SNS | | | | | x | x | x |
91 //-------------------+---+---+---+---+---+---+---+ 93 //-------------------+---+---+---+---+---+---+---+
92 94
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 // info: 4368 126 // info: 4368
125 // preds: 17741 127 // preds: 17741
126 // top samples: 1263 128 // top samples: 1263
127 // non-zero: 175 129 // non-zero: 175
128 // lf-stats: 0 130 // lf-stats: 0
129 // total: 45658 131 // total: 45658
130 // Transient object sizes: 132 // Transient object sizes:
131 // VP8EncIterator: 3360 133 // VP8EncIterator: 3360
132 // VP8ModeScore: 872 134 // VP8ModeScore: 872
133 // VP8SegmentInfo: 732 135 // VP8SegmentInfo: 732
134 // VP8Proba: 18352 136 // VP8EncProba: 18352
135 // LFStats: 2048 137 // LFStats: 2048
136 // Picture size (yuv): 419328 138 // Picture size (yuv): 419328
137 139
138 static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, 140 static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
139 WebPPicture* const picture) { 141 WebPPicture* const picture) {
142 VP8Encoder* enc;
140 const int use_filter = 143 const int use_filter =
141 (config->filter_strength > 0) || (config->autofilter > 0); 144 (config->filter_strength > 0) || (config->autofilter > 0);
142 const int mb_w = (picture->width + 15) >> 4; 145 const int mb_w = (picture->width + 15) >> 4;
143 const int mb_h = (picture->height + 15) >> 4; 146 const int mb_h = (picture->height + 15) >> 4;
144 const int preds_w = 4 * mb_w + 1; 147 const int preds_w = 4 * mb_w + 1;
145 const int preds_h = 4 * mb_h + 1; 148 const int preds_h = 4 * mb_h + 1;
146 const size_t preds_size = preds_w * preds_h * sizeof(uint8_t); 149 const size_t preds_size = preds_w * preds_h * sizeof(*enc->preds_);
147 const int top_stride = mb_w * 16; 150 const int top_stride = mb_w * 16;
148 const size_t nz_size = (mb_w + 1) * sizeof(uint32_t) + ALIGN_CST; 151 const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST;
149 const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo); 152 const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_);
150 const size_t samples_size = 2 * top_stride * sizeof(uint8_t) // top-luma/u/v 153 const size_t samples_size =
151 + ALIGN_CST; // align all 154 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v
155 + WEBP_ALIGN_CST; // align all
152 const size_t lf_stats_size = 156 const size_t lf_stats_size =
153 config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0; 157 config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0;
154 VP8Encoder* enc;
155 uint8_t* mem; 158 uint8_t* mem;
156 const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct 159 const uint64_t size = (uint64_t)sizeof(*enc) // main struct
157 + ALIGN_CST // cache alignment 160 + WEBP_ALIGN_CST // cache alignment
158 + info_size // modes info 161 + info_size // modes info
159 + preds_size // prediction modes 162 + preds_size // prediction modes
160 + samples_size // top/left samples 163 + samples_size // top/left samples
161 + nz_size // coeff context bits 164 + nz_size // coeff context bits
162 + lf_stats_size; // autofilter stats 165 + lf_stats_size; // autofilter stats
163 166
164 #ifdef PRINT_MEMORY_INFO 167 #ifdef PRINT_MEMORY_INFO
165 printf("===================================\n"); 168 printf("===================================\n");
166 printf("Memory used:\n" 169 printf("Memory used:\n"
167 " encoder: %ld\n" 170 " encoder: %ld\n"
168 " info: %ld\n" 171 " info: %ld\n"
169 " preds: %ld\n" 172 " preds: %ld\n"
170 " top samples: %ld\n" 173 " top samples: %ld\n"
171 " non-zero: %ld\n" 174 " non-zero: %ld\n"
172 " lf-stats: %ld\n" 175 " lf-stats: %ld\n"
173 " total: %ld\n", 176 " total: %ld\n",
174 sizeof(VP8Encoder) + ALIGN_CST, info_size, 177 sizeof(*enc) + WEBP_ALIGN_CST, info_size,
175 preds_size, samples_size, nz_size, lf_stats_size, size); 178 preds_size, samples_size, nz_size, lf_stats_size, size);
176 printf("Transient object sizes:\n" 179 printf("Transient object sizes:\n"
177 " VP8EncIterator: %ld\n" 180 " VP8EncIterator: %ld\n"
178 " VP8ModeScore: %ld\n" 181 " VP8ModeScore: %ld\n"
179 " VP8SegmentInfo: %ld\n" 182 " VP8SegmentInfo: %ld\n"
180 " VP8Proba: %ld\n" 183 " VP8EncProba: %ld\n"
181 " LFStats: %ld\n", 184 " LFStats: %ld\n",
182 sizeof(VP8EncIterator), sizeof(VP8ModeScore), 185 sizeof(VP8EncIterator), sizeof(VP8ModeScore),
183 sizeof(VP8SegmentInfo), sizeof(VP8Proba), 186 sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
184 sizeof(LFStats)); 187 sizeof(LFStats));
185 printf("Picture size (yuv): %ld\n", 188 printf("Picture size (yuv): %ld\n",
186 mb_w * mb_h * 384 * sizeof(uint8_t)); 189 mb_w * mb_h * 384 * sizeof(uint8_t));
187 printf("===================================\n"); 190 printf("===================================\n");
188 #endif 191 #endif
189 mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); 192 mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
190 if (mem == NULL) { 193 if (mem == NULL) {
191 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 194 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
192 return NULL; 195 return NULL;
193 } 196 }
194 enc = (VP8Encoder*)mem; 197 enc = (VP8Encoder*)mem;
195 mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc)); 198 mem = (uint8_t*)WEBP_ALIGN(mem + sizeof(*enc));
196 memset(enc, 0, sizeof(*enc)); 199 memset(enc, 0, sizeof(*enc));
197 enc->num_parts_ = 1 << config->partitions; 200 enc->num_parts_ = 1 << config->partitions;
198 enc->mb_w_ = mb_w; 201 enc->mb_w_ = mb_w;
199 enc->mb_h_ = mb_h; 202 enc->mb_h_ = mb_h;
200 enc->preds_w_ = preds_w; 203 enc->preds_w_ = preds_w;
201 enc->mb_info_ = (VP8MBInfo*)mem; 204 enc->mb_info_ = (VP8MBInfo*)mem;
202 mem += info_size; 205 mem += info_size;
203 enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; 206 enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
204 mem += preds_w * preds_h * sizeof(uint8_t); 207 mem += preds_size;
205 enc->nz_ = 1 + (uint32_t*)DO_ALIGN(mem); 208 enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem);
206 mem += nz_size; 209 mem += nz_size;
207 enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL; 210 enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL;
208 mem += lf_stats_size; 211 mem += lf_stats_size;
209 212
210 // top samples (all 16-aligned) 213 // top samples (all 16-aligned)
211 mem = (uint8_t*)DO_ALIGN(mem); 214 mem = (uint8_t*)WEBP_ALIGN(mem);
212 enc->y_top_ = (uint8_t*)mem; 215 enc->y_top_ = (uint8_t*)mem;
213 enc->uv_top_ = enc->y_top_ + top_stride; 216 enc->uv_top_ = enc->y_top_ + top_stride;
214 mem += 2 * top_stride; 217 mem += 2 * top_stride;
215 assert(mem <= (uint8_t*)enc + size); 218 assert(mem <= (uint8_t*)enc + size);
216 219
217 enc->config_ = config; 220 enc->config_ = config;
218 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; 221 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
219 enc->pic_ = picture; 222 enc->pic_ = picture;
220 enc->percent_ = 0; 223 enc->percent_ = 0;
221 224
222 MapConfigToTools(enc); 225 MapConfigToTools(enc);
223 VP8EncDspInit(); 226 VP8EncDspInit();
224 VP8DefaultProbas(enc); 227 VP8DefaultProbas(enc);
225 ResetSegmentHeader(enc); 228 ResetSegmentHeader(enc);
226 ResetFilterHeader(enc); 229 ResetFilterHeader(enc);
227 ResetBoundaryPredictions(enc); 230 ResetBoundaryPredictions(enc);
228 VP8GetResidualCostInit(); 231 VP8EncDspCostInit();
229 VP8SetResidualCoeffsInit();
230 VP8EncInitAlpha(enc); 232 VP8EncInitAlpha(enc);
231 233
232 // lower quality means smaller output -> we modulate a little the page 234 // lower quality means smaller output -> we modulate a little the page
233 // size based on quality. This is just a crude 1rst-order prediction. 235 // size based on quality. This is just a crude 1rst-order prediction.
234 { 236 {
235 const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6] 237 const float scale = 1.f + config->quality * 5.f / 100.f; // in [1,6]
236 VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale)); 238 VP8TBufferInit(&enc->tokens_, (int)(mb_w * mb_h * 4 * scale));
237 } 239 }
238 return enc; 240 return enc;
239 } 241 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); 321 return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
320 if (pic->width <= 0 || pic->height <= 0) 322 if (pic->width <= 0 || pic->height <= 0)
321 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 323 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
322 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) 324 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
323 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 325 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
324 326
325 if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); 327 if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
326 328
327 if (!config->lossless) { 329 if (!config->lossless) {
328 VP8Encoder* enc = NULL; 330 VP8Encoder* enc = NULL;
331
332 if (!config->exact) {
333 WebPCleanupTransparentArea(pic);
334 }
335
329 if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { 336 if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) {
330 // Make sure we have YUVA samples. 337 // Make sure we have YUVA samples.
331 if (config->preprocessing & 4) { 338 if (config->preprocessing & 4) {
332 #if WEBP_ENCODER_ABI_VERSION > 0x0204
333 if (!WebPPictureSmartARGBToYUVA(pic)) { 339 if (!WebPPictureSmartARGBToYUVA(pic)) {
334 return 0; 340 return 0;
335 } 341 }
336 #endif
337 } else { 342 } else {
338 float dithering = 0.f; 343 float dithering = 0.f;
339 if (config->preprocessing & 2) { 344 if (config->preprocessing & 2) {
340 const float x = config->quality / 100.f; 345 const float x = config->quality / 100.f;
341 const float x2 = x * x; 346 const float x2 = x * x;
342 // slowly decreasing from max dithering at low quality (q->0) 347 // slowly decreasing from max dithering at low quality (q->0)
343 // to 0.5 dithering amplitude at high quality (q->100) 348 // to 0.5 dithering amplitude at high quality (q->100)
344 dithering = 1.0f + (0.5f - 1.0f) * x2 * x2; 349 dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
345 } 350 }
346 if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) { 351 if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
(...skipping 21 matching lines...) Expand all
368 if (!ok) { 373 if (!ok) {
369 VP8EncFreeBitWriters(enc); 374 VP8EncFreeBitWriters(enc);
370 } 375 }
371 ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok 376 ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
372 } else { 377 } else {
373 // Make sure we have ARGB samples. 378 // Make sure we have ARGB samples.
374 if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { 379 if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
375 return 0; 380 return 0;
376 } 381 }
377 382
383 if (!config->exact) {
384 WebPCleanupTransparentAreaLossless(pic);
385 }
386
378 ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. 387 ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
379 } 388 }
380 389
381 return ok; 390 return ok;
382 } 391 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698