OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |