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

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

Issue 10832153: libwebp: update snapshot to v0.2.0-rc1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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
OLDNEW
1 // Copyright 2011 Google Inc. 1 // Copyright 2011 Google Inc. All Rights Reserved.
2 // 2 //
3 // This code is licensed under the same terms as WebM: 3 // This code is licensed under the same terms as WebM:
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // Software License Agreement: http://www.webmproject.org/license/software/
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/
6 // ----------------------------------------------------------------------------- 6 // -----------------------------------------------------------------------------
7 // 7 //
8 // WebP encoder: main entry point 8 // WebP encoder: main entry point
9 // 9 //
10 // Author: Skal (pascal.massimino@gmail.com) 10 // Author: Skal (pascal.massimino@gmail.com)
11 11
12 #include <assert.h> 12 #include <assert.h>
13 #include <stdlib.h> 13 #include <stdlib.h>
14 #include <string.h> 14 #include <string.h>
15 #include <math.h> 15 #include <math.h>
16 16
17 #include "vp8enci.h" 17 #include "./vp8enci.h"
18 #include "./vp8li.h"
19 #include "../utils/utils.h"
18 20
19 // #define PRINT_MEMORY_INFO 21 // #define PRINT_MEMORY_INFO
20 22
21 #if defined(__cplusplus) || defined(c_plusplus) 23 #if defined(__cplusplus) || defined(c_plusplus)
22 extern "C" { 24 extern "C" {
23 #endif 25 #endif
24 26
25 #ifdef PRINT_MEMORY_INFO 27 #ifdef PRINT_MEMORY_INFO
26 #include <stdio.h> 28 #include <stdio.h>
27 #endif 29 #endif
(...skipping 10 matching lines...) Expand all
38 40
39 static int DummyWriter(const uint8_t* data, size_t data_size, 41 static int DummyWriter(const uint8_t* data, size_t data_size,
40 const WebPPicture* const picture) { 42 const WebPPicture* const picture) {
41 // The following are to prevent 'unused variable' error message. 43 // The following are to prevent 'unused variable' error message.
42 (void)data; 44 (void)data;
43 (void)data_size; 45 (void)data_size;
44 (void)picture; 46 (void)picture;
45 return 1; 47 return 1;
46 } 48 }
47 49
48 int WebPPictureInitInternal(WebPPicture* const picture, int version) { 50 int WebPPictureInitInternal(WebPPicture* picture, int version) {
49 if (version != WEBP_ENCODER_ABI_VERSION) { 51 if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
50 return 0; // caller/system version mismatch! 52 return 0; // caller/system version mismatch!
51 } 53 }
52 if (picture) { 54 if (picture != NULL) {
53 memset(picture, 0, sizeof(*picture)); 55 memset(picture, 0, sizeof(*picture));
54 picture->writer = DummyWriter; 56 picture->writer = DummyWriter;
55 WebPEncodingSetError(picture, VP8_ENC_OK); 57 WebPEncodingSetError(picture, VP8_ENC_OK);
56 } 58 }
57 return 1; 59 return 1;
58 } 60 }
59 61
60 //------------------------------------------------------------------------------ 62 //------------------------------------------------------------------------------
61 // VP8Encoder 63 // VP8Encoder
62 //------------------------------------------------------------------------------ 64 //------------------------------------------------------------------------------
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // lf-stats: 2048 137 // lf-stats: 2048
136 // total: 68635 138 // total: 68635
137 // Transcient object sizes: 139 // Transcient object sizes:
138 // VP8EncIterator: 352 140 // VP8EncIterator: 352
139 // VP8ModeScore: 912 141 // VP8ModeScore: 912
140 // VP8SegmentInfo: 532 142 // VP8SegmentInfo: 532
141 // VP8Proba: 31032 143 // VP8Proba: 31032
142 // LFStats: 2048 144 // LFStats: 2048
143 // Picture size (yuv): 589824 145 // Picture size (yuv): 589824
144 146
145 static VP8Encoder* InitEncoder(const WebPConfig* const config, 147 static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
146 WebPPicture* const picture) { 148 WebPPicture* const picture) {
147 const int use_filter = 149 const int use_filter =
148 (config->filter_strength > 0) || (config->autofilter > 0); 150 (config->filter_strength > 0) || (config->autofilter > 0);
149 const int mb_w = (picture->width + 15) >> 4; 151 const int mb_w = (picture->width + 15) >> 4;
150 const int mb_h = (picture->height + 15) >> 4; 152 const int mb_h = (picture->height + 15) >> 4;
151 const int preds_w = 4 * mb_w + 1; 153 const int preds_w = 4 * mb_w + 1;
152 const int preds_h = 4 * mb_h + 1; 154 const int preds_h = 4 * mb_h + 1;
153 const size_t preds_size = preds_w * preds_h * sizeof(uint8_t); 155 const size_t preds_size = preds_w * preds_h * sizeof(uint8_t);
154 const int top_stride = mb_w * 16; 156 const int top_stride = mb_w * 16;
155 const size_t nz_size = (mb_w + 1) * sizeof(uint32_t); 157 const size_t nz_size = (mb_w + 1) * sizeof(uint32_t);
156 const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t); 158 const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t);
157 const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo); 159 const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo);
158 const size_t samples_size = (2 * top_stride + // top-luma/u/v 160 const size_t samples_size = (2 * top_stride + // top-luma/u/v
159 16 + 16 + 16 + 8 + 1 + // left y/u/v 161 16 + 16 + 16 + 8 + 1 + // left y/u/v
160 2 * ALIGN_CST) // align all 162 2 * ALIGN_CST) // align all
161 * sizeof(uint8_t); 163 * sizeof(uint8_t);
162 const size_t lf_stats_size = 164 const size_t lf_stats_size =
163 config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0; 165 config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0;
164 VP8Encoder* enc; 166 VP8Encoder* enc;
165 uint8_t* mem; 167 uint8_t* mem;
166 size_t size = sizeof(VP8Encoder) + ALIGN_CST // main struct 168 const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct
167 + cache_size // working caches 169 + ALIGN_CST // cache alignment
168 + info_size // modes info 170 + cache_size // working caches
169 + preds_size // prediction modes 171 + info_size // modes info
170 + samples_size // top/left samples 172 + preds_size // prediction modes
171 + nz_size // coeff context bits 173 + samples_size // top/left samples
172 + lf_stats_size; // autofilter stats 174 + nz_size // coeff context bits
175 + lf_stats_size; // autofilter stats
173 176
174 #ifdef PRINT_MEMORY_INFO 177 #ifdef PRINT_MEMORY_INFO
175 printf("===================================\n"); 178 printf("===================================\n");
176 printf("Memory used:\n" 179 printf("Memory used:\n"
177 " encoder: %ld\n" 180 " encoder: %ld\n"
178 " block cache: %ld\n" 181 " block cache: %ld\n"
179 " info: %ld\n" 182 " info: %ld\n"
180 " preds: %ld\n" 183 " preds: %ld\n"
181 " top samples: %ld\n" 184 " top samples: %ld\n"
182 " non-zero: %ld\n" 185 " non-zero: %ld\n"
183 " lf-stats: %ld\n" 186 " lf-stats: %ld\n"
184 " total: %ld\n", 187 " total: %ld\n",
185 sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size, 188 sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size,
186 preds_size, samples_size, nz_size, lf_stats_size, size); 189 preds_size, samples_size, nz_size, lf_stats_size, size);
187 printf("Transcient object sizes:\n" 190 printf("Transcient object sizes:\n"
188 " VP8EncIterator: %ld\n" 191 " VP8EncIterator: %ld\n"
189 " VP8ModeScore: %ld\n" 192 " VP8ModeScore: %ld\n"
190 " VP8SegmentInfo: %ld\n" 193 " VP8SegmentInfo: %ld\n"
191 " VP8Proba: %ld\n" 194 " VP8Proba: %ld\n"
192 " LFStats: %ld\n", 195 " LFStats: %ld\n",
193 sizeof(VP8EncIterator), sizeof(VP8ModeScore), 196 sizeof(VP8EncIterator), sizeof(VP8ModeScore),
194 sizeof(VP8SegmentInfo), sizeof(VP8Proba), 197 sizeof(VP8SegmentInfo), sizeof(VP8Proba),
195 sizeof(LFStats)); 198 sizeof(LFStats));
196 printf("Picture size (yuv): %ld\n", 199 printf("Picture size (yuv): %ld\n",
197 mb_w * mb_h * 384 * sizeof(uint8_t)); 200 mb_w * mb_h * 384 * sizeof(uint8_t));
198 printf("===================================\n"); 201 printf("===================================\n");
199 #endif 202 #endif
200 mem = (uint8_t*)malloc(size); 203 mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem));
201 if (mem == NULL) { 204 if (mem == NULL) {
202 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 205 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
203 return NULL; 206 return NULL;
204 } 207 }
205 enc = (VP8Encoder*)mem; 208 enc = (VP8Encoder*)mem;
206 mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc)); 209 mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc));
207 memset(enc, 0, sizeof(*enc)); 210 memset(enc, 0, sizeof(*enc));
208 enc->num_parts_ = 1 << config->partitions; 211 enc->num_parts_ = 1 << config->partitions;
209 enc->mb_w_ = mb_w; 212 enc->mb_w_ = mb_w;
210 enc->mb_h_ = mb_h; 213 enc->mb_h_ = mb_h;
(...skipping 24 matching lines...) Expand all
235 enc->y_left_ = (uint8_t*)mem; 238 enc->y_left_ = (uint8_t*)mem;
236 mem += 16 + 16; 239 mem += 16 + 16;
237 enc->u_left_ = (uint8_t*)mem; 240 enc->u_left_ = (uint8_t*)mem;
238 mem += 16; 241 mem += 16;
239 enc->v_left_ = (uint8_t*)mem; 242 enc->v_left_ = (uint8_t*)mem;
240 mem += 8; 243 mem += 8;
241 244
242 enc->config_ = config; 245 enc->config_ = config;
243 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; 246 enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2;
244 enc->pic_ = picture; 247 enc->pic_ = picture;
248 enc->percent_ = 0;
245 249
246 MapConfigToTools(enc); 250 MapConfigToTools(enc);
247 VP8EncDspInit(); 251 VP8EncDspInit();
248 VP8DefaultProbas(enc); 252 VP8DefaultProbas(enc);
249 ResetSegmentHeader(enc); 253 ResetSegmentHeader(enc);
250 ResetFilterHeader(enc); 254 ResetFilterHeader(enc);
251 ResetBoundaryPredictions(enc); 255 ResetBoundaryPredictions(enc);
252 256
257 VP8EncInitAlpha(enc);
253 #ifdef WEBP_EXPERIMENTAL_FEATURES 258 #ifdef WEBP_EXPERIMENTAL_FEATURES
254 VP8EncInitAlpha(enc);
255 VP8EncInitLayer(enc); 259 VP8EncInitLayer(enc);
256 #endif 260 #endif
257 261
258 return enc; 262 return enc;
259 } 263 }
260 264
261 static void DeleteEncoder(VP8Encoder* enc) { 265 static void DeleteVP8Encoder(VP8Encoder* enc) {
262 if (enc) { 266 if (enc != NULL) {
267 VP8EncDeleteAlpha(enc);
263 #ifdef WEBP_EXPERIMENTAL_FEATURES 268 #ifdef WEBP_EXPERIMENTAL_FEATURES
264 VP8EncDeleteAlpha(enc);
265 VP8EncDeleteLayer(enc); 269 VP8EncDeleteLayer(enc);
266 #endif 270 #endif
267 free(enc); 271 free(enc);
268 } 272 }
269 } 273 }
270 274
271 //------------------------------------------------------------------------------ 275 //------------------------------------------------------------------------------
272 276
273 static double GetPSNR(uint64_t err, uint64_t size) { 277 static double GetPSNR(uint64_t err, uint64_t size) {
274 return err ? 10. * log10(255. * 255. * size / err) : 99.; 278 return err ? 10. * log10(255. * 255. * size / err) : 99.;
275 } 279 }
276 280
277 static void FinalizePSNR(const VP8Encoder* const enc) { 281 static void FinalizePSNR(const VP8Encoder* const enc) {
278 WebPAuxStats* stats = enc->pic_->stats; 282 WebPAuxStats* stats = enc->pic_->stats;
279 const uint64_t size = enc->sse_count_; 283 const uint64_t size = enc->sse_count_;
280 const uint64_t* const sse = enc->sse_; 284 const uint64_t* const sse = enc->sse_;
281 stats->PSNR[0] = (float)GetPSNR(sse[0], size); 285 stats->PSNR[0] = (float)GetPSNR(sse[0], size);
282 stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); 286 stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4);
283 stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); 287 stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4);
284 stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); 288 stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2);
289 stats->PSNR[4] = (float)GetPSNR(sse[3], size);
285 } 290 }
286 291
287 static void StoreStats(VP8Encoder* const enc) { 292 static void StoreStats(VP8Encoder* const enc) {
288 WebPAuxStats* const stats = enc->pic_->stats; 293 WebPAuxStats* const stats = enc->pic_->stats;
289 if (stats) { 294 if (stats != NULL) {
290 int i, s; 295 int i, s;
291 for (i = 0; i < NUM_MB_SEGMENTS; ++i) { 296 for (i = 0; i < NUM_MB_SEGMENTS; ++i) {
292 stats->segment_level[i] = enc->dqm_[i].fstrength_; 297 stats->segment_level[i] = enc->dqm_[i].fstrength_;
293 stats->segment_quant[i] = enc->dqm_[i].quant_; 298 stats->segment_quant[i] = enc->dqm_[i].quant_;
294 for (s = 0; s <= 2; ++s) { 299 for (s = 0; s <= 2; ++s) {
295 stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; 300 stats->residual_bytes[s][i] = enc->residual_bytes_[s][i];
296 } 301 }
297 } 302 }
298 FinalizePSNR(enc); 303 FinalizePSNR(enc);
299 stats->coded_size = enc->coded_size_; 304 stats->coded_size = enc->coded_size_;
300 for (i = 0; i < 3; ++i) { 305 for (i = 0; i < 3; ++i) {
301 stats->block_count[i] = enc->block_count_[i]; 306 stats->block_count[i] = enc->block_count_[i];
302 } 307 }
303 } 308 }
309 WebPReportProgress(enc->pic_, 100, &enc->percent_); // done!
304 } 310 }
305 311
306 int WebPEncodingSetError(WebPPicture* const pic, WebPEncodingError error) { 312 int WebPEncodingSetError(const WebPPicture* const pic,
307 assert((int)error <= VP8_ENC_ERROR_BAD_WRITE); 313 WebPEncodingError error) {
314 assert((int)error < VP8_ENC_ERROR_LAST);
308 assert((int)error >= VP8_ENC_OK); 315 assert((int)error >= VP8_ENC_OK);
309 pic->error_code = error; 316 ((WebPPicture*)pic)->error_code = error;
310 return 0; 317 return 0;
311 } 318 }
312 319
320 int WebPReportProgress(const WebPPicture* const pic,
321 int percent, int* const percent_store) {
322 if (percent_store != NULL && percent != *percent_store) {
323 *percent_store = percent;
324 if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
325 // user abort requested
326 WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
327 return 0;
328 }
329 }
330 return 1; // ok
331 }
313 //------------------------------------------------------------------------------ 332 //------------------------------------------------------------------------------
314 333
315 int WebPEncode(const WebPConfig* const config, WebPPicture* const pic) { 334 int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
316 VP8Encoder* enc;
317 int ok; 335 int ok;
318 336
319 if (pic == NULL) 337 if (pic == NULL)
320 return 0; 338 return 0;
321 WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far 339 WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far
322 if (config == NULL) // bad params 340 if (config == NULL) // bad params
323 return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); 341 return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
324 if (!WebPValidateConfig(config)) 342 if (!WebPValidateConfig(config))
325 return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); 343 return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
326 if (pic->width <= 0 || pic->height <= 0) 344 if (pic->width <= 0 || pic->height <= 0)
327 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 345 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
328 if (pic->y == NULL || pic->u == NULL || pic->v == NULL)
329 return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
330 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) 346 if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION)
331 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 347 return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION);
332 348
333 enc = InitEncoder(config, pic); 349 if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats));
334 if (enc == NULL) return 0; // pic->error is already set. 350
335 ok = VP8EncAnalyze(enc) 351 if (!config->lossless) {
336 && VP8StatLoop(enc) 352 VP8Encoder* enc = NULL;
337 && VP8EncLoop(enc) 353 if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
354 if (pic->argb != NULL) {
355 if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0;
356 } else {
357 return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
358 }
359 }
360
361 enc = InitVP8Encoder(config, pic);
362 if (enc == NULL) return 0; // pic->error is already set.
363 // Note: each of the tasks below account for 20% in the progress report.
364 ok = VP8EncAnalyze(enc)
365 && VP8StatLoop(enc)
366 && VP8EncLoop(enc)
367 && VP8EncFinishAlpha(enc)
338 #ifdef WEBP_EXPERIMENTAL_FEATURES 368 #ifdef WEBP_EXPERIMENTAL_FEATURES
339 && VP8EncFinishAlpha(enc) 369 && VP8EncFinishLayer(enc)
340 && VP8EncFinishLayer(enc)
341 #endif 370 #endif
342 && VP8EncWrite(enc); 371 && VP8EncWrite(enc);
343 StoreStats(enc); 372 StoreStats(enc);
344 DeleteEncoder(enc); 373 if (!ok) {
374 VP8EncFreeBitWriters(enc);
375 }
376 DeleteVP8Encoder(enc);
377 } else {
378 if (pic->argb == NULL)
379 return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
380
381 ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
382 }
345 383
346 return ok; 384 return ok;
347 } 385 }
348 386
349 #if defined(__cplusplus) || defined(c_plusplus) 387 #if defined(__cplusplus) || defined(c_plusplus)
350 } // extern "C" 388 } // extern "C"
351 #endif 389 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698