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

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

Issue 116213006: Update libwebp to 0.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After Blink Roll Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/enc/vp8li.h ('k') | third_party/libwebp/libwebp.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "./vp8enci.h" 19 #include "./vp8enci.h"
20 #include "./vp8li.h" 20 #include "./vp8li.h"
21 #include "../utils/utils.h" 21 #include "../utils/utils.h"
22 22
23 // #define PRINT_MEMORY_INFO 23 // #define PRINT_MEMORY_INFO
24 24
25 #if defined(__cplusplus) || defined(c_plusplus)
26 extern "C" {
27 #endif
28
29 #ifdef PRINT_MEMORY_INFO 25 #ifdef PRINT_MEMORY_INFO
30 #include <stdio.h> 26 #include <stdio.h>
31 #endif 27 #endif
32 28
33 //------------------------------------------------------------------------------ 29 //------------------------------------------------------------------------------
34 30
35 int WebPGetEncoderVersion(void) { 31 int WebPGetEncoderVersion(void) {
36 return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; 32 return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
37 } 33 }
38 34
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 : RD_OPT_NONE; 125 : RD_OPT_NONE;
130 enc->max_i4_header_bits_ = 126 enc->max_i4_header_bits_ =
131 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block 127 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block
132 (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. 128 (limit * limit) / (100 * 100); // ... modulated with a quadratic curve.
133 129
134 enc->thread_level_ = config->thread_level; 130 enc->thread_level_ = config->thread_level;
135 131
136 enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); 132 enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0);
137 if (!config->low_memory) { 133 if (!config->low_memory) {
138 #if !defined(DISABLE_TOKEN_BUFFER) 134 #if !defined(DISABLE_TOKEN_BUFFER)
139 enc->use_tokens_ = (method >= 3) && !enc->do_search_; 135 enc->use_tokens_ = (enc->rd_opt_level_ >= RD_OPT_BASIC); // need rd stats
140 #endif 136 #endif
141 if (enc->use_tokens_) { 137 if (enc->use_tokens_) {
142 enc->num_parts_ = 1; // doesn't work with multi-partition 138 enc->num_parts_ = 1; // doesn't work with multi-partition
143 } 139 }
144 } 140 }
145 } 141 }
146 142
147 // Memory scaling with dimensions: 143 // Memory scaling with dimensions:
148 // memory (bytes) ~= 2.25 * w + 0.0625 * w * h 144 // memory (bytes) ~= 2.25 * w + 0.0625 * w * h
149 // 145 //
150 // Typical memory footprint (768x510 picture) 146 // Typical memory footprint (768x510 picture)
151 // Memory used: 147 // Memory used:
152 // encoder: 33919 148 // encoder: 33919
153 // block cache: 2880 149 // block cache: 2880
154 // info: 3072 150 // info: 3072
155 // preds: 24897 151 // preds: 24897
156 // top samples: 1623 152 // top samples: 1623
157 // non-zero: 196 153 // non-zero: 196
158 // lf-stats: 2048 154 // lf-stats: 2048
159 // total: 68635 155 // total: 68635
160 // Transcient object sizes: 156 // Transient object sizes:
161 // VP8EncIterator: 352 157 // VP8EncIterator: 352
162 // VP8ModeScore: 912 158 // VP8ModeScore: 912
163 // VP8SegmentInfo: 532 159 // VP8SegmentInfo: 532
164 // VP8Proba: 31032 160 // VP8Proba: 31032
165 // LFStats: 2048 161 // LFStats: 2048
166 // Picture size (yuv): 589824 162 // Picture size (yuv): 589824
167 163
168 static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, 164 static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
169 WebPPicture* const picture) { 165 WebPPicture* const picture) {
170 const int use_filter = 166 const int use_filter =
171 (config->filter_strength > 0) || (config->autofilter > 0); 167 (config->filter_strength > 0) || (config->autofilter > 0);
172 const int mb_w = (picture->width + 15) >> 4; 168 const int mb_w = (picture->width + 15) >> 4;
173 const int mb_h = (picture->height + 15) >> 4; 169 const int mb_h = (picture->height + 15) >> 4;
174 const int preds_w = 4 * mb_w + 1; 170 const int preds_w = 4 * mb_w + 1;
175 const int preds_h = 4 * mb_h + 1; 171 const int preds_h = 4 * mb_h + 1;
176 const size_t preds_size = preds_w * preds_h * sizeof(uint8_t); 172 const size_t preds_size = preds_w * preds_h * sizeof(uint8_t);
177 const int top_stride = mb_w * 16; 173 const int top_stride = mb_w * 16;
178 const size_t nz_size = (mb_w + 1) * sizeof(uint32_t); 174 const size_t nz_size = (mb_w + 1) * sizeof(uint32_t) + ALIGN_CST;
179 const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t);
180 const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo); 175 const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo);
181 const size_t samples_size = (2 * top_stride + // top-luma/u/v 176 const size_t samples_size = 2 * top_stride * sizeof(uint8_t) // top-luma/u/v
182 16 + 16 + 16 + 8 + 1 + // left y/u/v 177 + ALIGN_CST; // align all
183 2 * ALIGN_CST) // align all
184 * sizeof(uint8_t);
185 const size_t lf_stats_size = 178 const size_t lf_stats_size =
186 config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0; 179 config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0;
187 VP8Encoder* enc; 180 VP8Encoder* enc;
188 uint8_t* mem; 181 uint8_t* mem;
189 const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct 182 const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct
190 + ALIGN_CST // cache alignment 183 + ALIGN_CST // cache alignment
191 + cache_size // working caches
192 + info_size // modes info 184 + info_size // modes info
193 + preds_size // prediction modes 185 + preds_size // prediction modes
194 + samples_size // top/left samples 186 + samples_size // top/left samples
195 + nz_size // coeff context bits 187 + nz_size // coeff context bits
196 + lf_stats_size; // autofilter stats 188 + lf_stats_size; // autofilter stats
197 189
198 #ifdef PRINT_MEMORY_INFO 190 #ifdef PRINT_MEMORY_INFO
199 printf("===================================\n"); 191 printf("===================================\n");
200 printf("Memory used:\n" 192 printf("Memory used:\n"
201 " encoder: %ld\n" 193 " encoder: %ld\n"
202 " block cache: %ld\n"
203 " info: %ld\n" 194 " info: %ld\n"
204 " preds: %ld\n" 195 " preds: %ld\n"
205 " top samples: %ld\n" 196 " top samples: %ld\n"
206 " non-zero: %ld\n" 197 " non-zero: %ld\n"
207 " lf-stats: %ld\n" 198 " lf-stats: %ld\n"
208 " total: %ld\n", 199 " total: %ld\n",
209 sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size, 200 sizeof(VP8Encoder) + ALIGN_CST, info_size,
210 preds_size, samples_size, nz_size, lf_stats_size, size); 201 preds_size, samples_size, nz_size, lf_stats_size, size);
211 printf("Transcient object sizes:\n" 202 printf("Transient object sizes:\n"
212 " VP8EncIterator: %ld\n" 203 " VP8EncIterator: %ld\n"
213 " VP8ModeScore: %ld\n" 204 " VP8ModeScore: %ld\n"
214 " VP8SegmentInfo: %ld\n" 205 " VP8SegmentInfo: %ld\n"
215 " VP8Proba: %ld\n" 206 " VP8Proba: %ld\n"
216 " LFStats: %ld\n", 207 " LFStats: %ld\n",
217 sizeof(VP8EncIterator), sizeof(VP8ModeScore), 208 sizeof(VP8EncIterator), sizeof(VP8ModeScore),
218 sizeof(VP8SegmentInfo), sizeof(VP8Proba), 209 sizeof(VP8SegmentInfo), sizeof(VP8Proba),
219 sizeof(LFStats)); 210 sizeof(LFStats));
220 printf("Picture size (yuv): %ld\n", 211 printf("Picture size (yuv): %ld\n",
221 mb_w * mb_h * 384 * sizeof(uint8_t)); 212 mb_w * mb_h * 384 * sizeof(uint8_t));
222 printf("===================================\n"); 213 printf("===================================\n");
223 #endif 214 #endif
224 mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); 215 mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
225 if (mem == NULL) { 216 if (mem == NULL) {
226 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 217 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
227 return NULL; 218 return NULL;
228 } 219 }
229 enc = (VP8Encoder*)mem; 220 enc = (VP8Encoder*)mem;
230 mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc)); 221 mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc));
231 memset(enc, 0, sizeof(*enc)); 222 memset(enc, 0, sizeof(*enc));
232 enc->num_parts_ = 1 << config->partitions; 223 enc->num_parts_ = 1 << config->partitions;
233 enc->mb_w_ = mb_w; 224 enc->mb_w_ = mb_w;
234 enc->mb_h_ = mb_h; 225 enc->mb_h_ = mb_h;
235 enc->preds_w_ = preds_w; 226 enc->preds_w_ = preds_w;
236 enc->yuv_in_ = (uint8_t*)mem;
237 mem += YUV_SIZE;
238 enc->yuv_out_ = (uint8_t*)mem;
239 mem += YUV_SIZE;
240 enc->yuv_out2_ = (uint8_t*)mem;
241 mem += YUV_SIZE;
242 enc->yuv_p_ = (uint8_t*)mem;
243 mem += PRED_SIZE;
244 enc->mb_info_ = (VP8MBInfo*)mem; 227 enc->mb_info_ = (VP8MBInfo*)mem;
245 mem += info_size; 228 mem += info_size;
246 enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; 229 enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
247 mem += preds_w * preds_h * sizeof(uint8_t); 230 mem += preds_w * preds_h * sizeof(uint8_t);
248 enc->nz_ = 1 + (uint32_t*)mem; 231 enc->nz_ = 1 + (uint32_t*)DO_ALIGN(mem);
249 mem += nz_size; 232 mem += nz_size;
250 enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL; 233 enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL;
251 mem += lf_stats_size; 234 mem += lf_stats_size;
252 235
253 // top samples (all 16-aligned) 236 // top samples (all 16-aligned)
254 mem = (uint8_t*)DO_ALIGN(mem); 237 mem = (uint8_t*)DO_ALIGN(mem);
255 enc->y_top_ = (uint8_t*)mem; 238 enc->y_top_ = (uint8_t*)mem;
256 enc->uv_top_ = enc->y_top_ + top_stride; 239 enc->uv_top_ = enc->y_top_ + top_stride;
257 mem += 2 * top_stride; 240 mem += 2 * top_stride;
258 mem = (uint8_t*)DO_ALIGN(mem + 1); 241 assert(mem <= (uint8_t*)enc + size);
259 enc->y_left_ = (uint8_t*)mem;
260 mem += 16 + 16;
261 enc->u_left_ = (uint8_t*)mem;
262 mem += 16;
263 enc->v_left_ = (uint8_t*)mem;
264 mem += 8;
265 242
266 enc->config_ = config; 243 enc->config_ = config;
267 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; 244 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
268 enc->pic_ = picture; 245 enc->pic_ = picture;
269 enc->percent_ = 0; 246 enc->percent_ = 0;
270 247
271 MapConfigToTools(enc); 248 MapConfigToTools(enc);
272 VP8EncDspInit(); 249 VP8EncDspInit();
273 VP8DefaultProbas(enc); 250 VP8DefaultProbas(enc);
274 ResetSegmentHeader(enc); 251 ResetSegmentHeader(enc);
(...skipping 18 matching lines...) Expand all
293 #endif 270 #endif
294 VP8TBufferClear(&enc->tokens_); 271 VP8TBufferClear(&enc->tokens_);
295 free(enc); 272 free(enc);
296 } 273 }
297 return ok; 274 return ok;
298 } 275 }
299 276
300 //------------------------------------------------------------------------------ 277 //------------------------------------------------------------------------------
301 278
302 static double GetPSNR(uint64_t err, uint64_t size) { 279 static double GetPSNR(uint64_t err, uint64_t size) {
303 return err ? 10. * log10(255. * 255. * size / err) : 99.; 280 return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.;
304 } 281 }
305 282
306 static void FinalizePSNR(const VP8Encoder* const enc) { 283 static void FinalizePSNR(const VP8Encoder* const enc) {
307 WebPAuxStats* stats = enc->pic_->stats; 284 WebPAuxStats* stats = enc->pic_->stats;
308 const uint64_t size = enc->sse_count_; 285 const uint64_t size = enc->sse_count_;
309 const uint64_t* const sse = enc->sse_; 286 const uint64_t* const sse = enc->sse_;
310 stats->PSNR[0] = (float)GetPSNR(sse[0], size); 287 stats->PSNR[0] = (float)GetPSNR(sse[0], size);
311 stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); 288 stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4);
312 stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); 289 stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4);
313 stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); 290 stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 347 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
371 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) 348 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
372 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 349 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
373 350
374 if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); 351 if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
375 352
376 if (!config->lossless) { 353 if (!config->lossless) {
377 VP8Encoder* enc = NULL; 354 VP8Encoder* enc = NULL;
378 if (pic->y == NULL || pic->u == NULL || pic->v == NULL) { 355 if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
379 // Make sure we have YUVA samples. 356 // Make sure we have YUVA samples.
380 if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0; 357 float dithering = 0.f;
358 if (config->preprocessing & 2) {
359 const float x = config->quality / 100.f;
360 const float x2 = x * x;
361 // slowly decreasing from max dithering at low quality (q->0)
362 // to 0.5 dithering amplitude at high quality (q->100)
363 dithering = 1.0f + (0.5f - 1.0f) * x2 * x2;
364 }
365 if (!WebPPictureARGBToYUVADithered(pic, WEBP_YUV420, dithering)) {
366 return 0;
367 }
381 } 368 }
382 369
383 enc = InitVP8Encoder(config, pic); 370 enc = InitVP8Encoder(config, pic);
384 if (enc == NULL) return 0; // pic->error is already set. 371 if (enc == NULL) return 0; // pic->error is already set.
385 // Note: each of the tasks below account for 20% in the progress report. 372 // Note: each of the tasks below account for 20% in the progress report.
386 ok = VP8EncAnalyze(enc); 373 ok = VP8EncAnalyze(enc);
387 374
388 // Analysis is done, proceed to actual coding. 375 // Analysis is done, proceed to actual coding.
389 ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel 376 ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel
390 if (!enc->use_tokens_) { 377 if (!enc->use_tokens_) {
(...skipping 17 matching lines...) Expand all
408 if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { 395 if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
409 return 0; 396 return 0;
410 } 397 }
411 398
412 ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. 399 ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
413 } 400 }
414 401
415 return ok; 402 return ok;
416 } 403 }
417 404
418 #if defined(__cplusplus) || defined(c_plusplus)
419 } // extern "C"
420 #endif
OLDNEW
« no previous file with comments | « third_party/libwebp/enc/vp8li.h ('k') | third_party/libwebp/libwebp.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698