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

Side by Side Diff: third_party/libwebp/enc/analysis.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 // Macroblock analysis 8 // Macroblock analysis
9 // 9 //
10 // Author: Skal (pascal.massimino@gmail.com) 10 // Author: Skal (pascal.massimino@gmail.com)
11 11
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <string.h> 13 #include <string.h>
14 #include <assert.h> 14 #include <assert.h>
15 15
16 #include "vp8enci.h" 16 #include "./vp8enci.h"
17 #include "cost.h" 17 #include "./cost.h"
18 #include "../utils/utils.h"
18 19
19 #if defined(__cplusplus) || defined(c_plusplus) 20 #if defined(__cplusplus) || defined(c_plusplus)
20 extern "C" { 21 extern "C" {
21 #endif 22 #endif
22 23
23 #define MAX_ITERS_K_MEANS 6 24 #define MAX_ITERS_K_MEANS 6
24 25
25 static int ClipAlpha(int alpha) { 26 static int ClipAlpha(int alpha) {
26 return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha; 27 return alpha < 0 ? 0 : alpha > 255 ? 255 : alpha;
27 } 28 }
28 29
29 //------------------------------------------------------------------------------ 30 //------------------------------------------------------------------------------
30 // Smooth the segment map by replacing isolated block by the majority of its 31 // Smooth the segment map by replacing isolated block by the majority of its
31 // neighbours. 32 // neighbours.
32 33
33 static void SmoothSegmentMap(VP8Encoder* const enc) { 34 static void SmoothSegmentMap(VP8Encoder* const enc) {
34 int n, x, y; 35 int n, x, y;
35 const int w = enc->mb_w_; 36 const int w = enc->mb_w_;
36 const int h = enc->mb_h_; 37 const int h = enc->mb_h_;
37 const int majority_cnt_3_x_3_grid = 5; 38 const int majority_cnt_3_x_3_grid = 5;
38 uint8_t* tmp = (uint8_t*)malloc(w * h * sizeof(uint8_t)); 39 uint8_t* const tmp = (uint8_t*)WebPSafeMalloc((uint64_t)w * h, sizeof(*tmp));
40 assert((uint64_t)(w * h) == (uint64_t)w * h); // no overflow, as per spec
39 41
40 if (tmp == NULL) return; 42 if (tmp == NULL) return;
41 for (y = 1; y < h - 1; ++y) { 43 for (y = 1; y < h - 1; ++y) {
42 for (x = 1; x < w - 1; ++x) { 44 for (x = 1; x < w - 1; ++x) {
43 int cnt[NUM_MB_SEGMENTS] = { 0 }; 45 int cnt[NUM_MB_SEGMENTS] = { 0 };
44 const VP8MBInfo* const mb = &enc->mb_info_[x + w * y]; 46 const VP8MBInfo* const mb = &enc->mb_info_[x + w * y];
45 int majority_seg = mb->segment_; 47 int majority_seg = mb->segment_;
46 // Check the 8 neighbouring segment values. 48 // Check the 8 neighbouring segment values.
47 cnt[mb[-w - 1].segment_]++; // top-left 49 cnt[mb[-w - 1].segment_]++; // top-left
48 cnt[mb[-w + 0].segment_]++; // top 50 cnt[mb[-w + 0].segment_]++; // top
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) + 107 p[0] * (VP8BitCost(0, probas[0]) + VP8BitCost(0, probas[1])) +
106 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) + 108 p[1] * (VP8BitCost(0, probas[0]) + VP8BitCost(1, probas[1])) +
107 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) + 109 p[2] * (VP8BitCost(1, probas[0]) + VP8BitCost(0, probas[2])) +
108 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2])); 110 p[3] * (VP8BitCost(1, probas[0]) + VP8BitCost(1, probas[2]));
109 } else { 111 } else {
110 enc->segment_hdr_.update_map_ = 0; 112 enc->segment_hdr_.update_map_ = 0;
111 enc->segment_hdr_.size_ = 0; 113 enc->segment_hdr_.size_ = 0;
112 } 114 }
113 } 115 }
114 116
115 static inline int clip(int v, int m, int M) { 117 static WEBP_INLINE int clip(int v, int m, int M) {
116 return v < m ? m : v > M ? M : v; 118 return v < m ? m : v > M ? M : v;
117 } 119 }
118 120
119 static void SetSegmentAlphas(VP8Encoder* const enc, 121 static void SetSegmentAlphas(VP8Encoder* const enc,
120 const int centers[NUM_MB_SEGMENTS], 122 const int centers[NUM_MB_SEGMENTS],
121 int mid) { 123 int mid) {
122 const int nb = enc->segment_hdr_.num_segments_; 124 const int nb = enc->segment_hdr_.num_segments_;
123 int min = centers[0], max = centers[0]; 125 int min = centers[0], max = centers[0];
124 int n; 126 int n;
125 127
(...skipping 12 matching lines...) Expand all
138 enc->dqm_[n].beta_ = clip(beta, 0, 255); 140 enc->dqm_[n].beta_ = clip(beta, 0, 255);
139 } 141 }
140 } 142 }
141 143
142 //------------------------------------------------------------------------------ 144 //------------------------------------------------------------------------------
143 // Simplified k-Means, to assign Nb segments based on alpha-histogram 145 // Simplified k-Means, to assign Nb segments based on alpha-histogram
144 146
145 static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) { 147 static void AssignSegments(VP8Encoder* const enc, const int alphas[256]) {
146 const int nb = enc->segment_hdr_.num_segments_; 148 const int nb = enc->segment_hdr_.num_segments_;
147 int centers[NUM_MB_SEGMENTS]; 149 int centers[NUM_MB_SEGMENTS];
148 int weighted_average; 150 int weighted_average = 0;
149 int map[256]; 151 int map[256];
150 int a, n, k; 152 int a, n, k;
151 int min_a = 0, max_a = 255, range_a; 153 int min_a = 0, max_a = 255, range_a;
152 // 'int' type is ok for histo, and won't overflow 154 // 'int' type is ok for histo, and won't overflow
153 int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS]; 155 int accum[NUM_MB_SEGMENTS], dist_accum[NUM_MB_SEGMENTS];
154 156
155 // bracket the input 157 // bracket the input
156 for (n = 0; n < 256 && alphas[n] == 0; ++n) {} 158 for (n = 0; n < 256 && alphas[n] == 0; ++n) {}
157 min_a = n; 159 min_a = n;
158 for (n = 255; n > min_a && alphas[n] == 0; --n) {} 160 for (n = 255; n > min_a && alphas[n] == 0; --n) {}
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 total_weight += accum[n]; 201 total_weight += accum[n];
200 } 202 }
201 } 203 }
202 weighted_average = (weighted_average + total_weight / 2) / total_weight; 204 weighted_average = (weighted_average + total_weight / 2) / total_weight;
203 if (displaced < 5) break; // no need to keep on looping... 205 if (displaced < 5) break; // no need to keep on looping...
204 } 206 }
205 207
206 // Map each original value to the closest centroid 208 // Map each original value to the closest centroid
207 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) { 209 for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
208 VP8MBInfo* const mb = &enc->mb_info_[n]; 210 VP8MBInfo* const mb = &enc->mb_info_[n];
209 const int a = mb->alpha_; 211 const int alpha = mb->alpha_;
210 mb->segment_ = map[a]; 212 mb->segment_ = map[alpha];
211 mb->alpha_ = centers[map[a]]; // just for the record. 213 mb->alpha_ = centers[map[alpha]]; // just for the record.
212 } 214 }
213 215
214 if (nb > 1) { 216 if (nb > 1) {
215 const int smooth = (enc->config_->preprocessing & 1); 217 const int smooth = (enc->config_->preprocessing & 1);
216 if (smooth) SmoothSegmentMap(enc); 218 if (smooth) SmoothSegmentMap(enc);
217 } 219 }
218 220
219 SetSegmentProbas(enc); // Assign final proba 221 SetSegmentProbas(enc); // Assign final proba
220 SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas. 222 SetSegmentAlphas(enc, centers, weighted_average); // pick some alphas.
221 } 223 }
(...skipping 24 matching lines...) Expand all
246 best_alpha = alpha; 248 best_alpha = alpha;
247 best_mode = mode; 249 best_mode = mode;
248 } 250 }
249 } 251 }
250 VP8SetIntra16Mode(it, best_mode); 252 VP8SetIntra16Mode(it, best_mode);
251 return best_alpha; 253 return best_alpha;
252 } 254 }
253 255
254 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, 256 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
255 int best_alpha) { 257 int best_alpha) {
256 int modes[16]; 258 uint8_t modes[16];
257 const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA4_MODE : NUM_BMODES; 259 const int max_mode = (it->enc_->method_ >= 3) ? MAX_INTRA4_MODE : NUM_BMODES;
258 int i4_alpha = 0; 260 int i4_alpha = 0;
259 VP8IteratorStartI4(it); 261 VP8IteratorStartI4(it);
260 do { 262 do {
261 int mode; 263 int mode;
262 int best_mode_alpha = -1; 264 int best_mode_alpha = -1;
263 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; 265 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_];
264 266
265 VP8MakeIntra4Preds(it); 267 VP8MakeIntra4Preds(it);
266 for (mode = 0; mode < max_mode; ++mode) { 268 for (mode = 0; mode < max_mode; ++mode) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 // Main analysis loop: 334 // Main analysis loop:
333 // Collect all susceptibilities for each macroblock and record their 335 // Collect all susceptibilities for each macroblock and record their
334 // distribution in alphas[]. Segments is assigned a-posteriori, based on 336 // distribution in alphas[]. Segments is assigned a-posteriori, based on
335 // this histogram. 337 // this histogram.
336 // We also pick an intra16 prediction mode, which shouldn't be considered 338 // We also pick an intra16 prediction mode, which shouldn't be considered
337 // final except for fast-encode settings. We can also pick some intra4 modes 339 // final except for fast-encode settings. We can also pick some intra4 modes
338 // and decide intra4/intra16, but that's usually almost always a bad choice at 340 // and decide intra4/intra16, but that's usually almost always a bad choice at
339 // this stage. 341 // this stage.
340 342
341 int VP8EncAnalyze(VP8Encoder* const enc) { 343 int VP8EncAnalyze(VP8Encoder* const enc) {
344 int ok = 1;
342 int alphas[256] = { 0 }; 345 int alphas[256] = { 0 };
343 VP8EncIterator it; 346 VP8EncIterator it;
344 347
345 VP8IteratorInit(enc, &it); 348 VP8IteratorInit(enc, &it);
346 enc->uv_alpha_ = 0; 349 enc->uv_alpha_ = 0;
347 do { 350 do {
348 VP8IteratorImport(&it); 351 VP8IteratorImport(&it);
349 MBAnalyze(&it, alphas, &enc->uv_alpha_); 352 MBAnalyze(&it, alphas, &enc->uv_alpha_);
353 ok = VP8IteratorProgress(&it, 20);
350 // Let's pretend we have perfect lossless reconstruction. 354 // Let's pretend we have perfect lossless reconstruction.
351 } while (VP8IteratorNext(&it, it.yuv_in_)); 355 } while (ok && VP8IteratorNext(&it, it.yuv_in_));
352 enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_; 356 enc->uv_alpha_ /= enc->mb_w_ * enc->mb_h_;
353 AssignSegments(enc, alphas); 357 if (ok) AssignSegments(enc, alphas);
354 358
355 return 1; 359 return ok;
356 } 360 }
357 361
358 #if defined(__cplusplus) || defined(c_plusplus) 362 #if defined(__cplusplus) || defined(c_plusplus)
359 } // extern "C" 363 } // extern "C"
360 #endif 364 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698