OLD | NEW |
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 // Macroblock analysis | 10 // Macroblock analysis |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 #define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. | 104 #define ALPHA_SCALE (2 * MAX_ALPHA) // scaling factor for alpha. |
105 #define DEFAULT_ALPHA (-1) | 105 #define DEFAULT_ALPHA (-1) |
106 #define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) | 106 #define IS_BETTER_ALPHA(alpha, best_alpha) ((alpha) > (best_alpha)) |
107 | 107 |
108 static int FinalAlphaValue(int alpha) { | 108 static int FinalAlphaValue(int alpha) { |
109 alpha = MAX_ALPHA - alpha; | 109 alpha = MAX_ALPHA - alpha; |
110 return clip(alpha, 0, MAX_ALPHA); | 110 return clip(alpha, 0, MAX_ALPHA); |
111 } | 111 } |
112 | 112 |
113 static int GetAlpha(const VP8Histogram* const histo) { | 113 static int GetAlpha(const VP8Histogram* const histo) { |
114 int max_value = 0, last_non_zero = 1; | |
115 int k; | |
116 int alpha; | |
117 for (k = 0; k <= MAX_COEFF_THRESH; ++k) { | |
118 const int value = histo->distribution[k]; | |
119 if (value > 0) { | |
120 if (value > max_value) max_value = value; | |
121 last_non_zero = k; | |
122 } | |
123 } | |
124 // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer | 114 // 'alpha' will later be clipped to [0..MAX_ALPHA] range, clamping outer |
125 // values which happen to be mostly noise. This leaves the maximum precision | 115 // values which happen to be mostly noise. This leaves the maximum precision |
126 // for handling the useful small values which contribute most. | 116 // for handling the useful small values which contribute most. |
127 alpha = (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; | 117 const int max_value = histo->max_value; |
| 118 const int last_non_zero = histo->last_non_zero; |
| 119 const int alpha = |
| 120 (max_value > 1) ? ALPHA_SCALE * last_non_zero / max_value : 0; |
128 return alpha; | 121 return alpha; |
129 } | 122 } |
130 | 123 |
| 124 static void InitHistogram(VP8Histogram* const histo) { |
| 125 histo->max_value = 0; |
| 126 histo->last_non_zero = 1; |
| 127 } |
| 128 |
131 static void MergeHistograms(const VP8Histogram* const in, | 129 static void MergeHistograms(const VP8Histogram* const in, |
132 VP8Histogram* const out) { | 130 VP8Histogram* const out) { |
133 int i; | 131 if (in->max_value > out->max_value) { |
134 for (i = 0; i <= MAX_COEFF_THRESH; ++i) { | 132 out->max_value = in->max_value; |
135 out->distribution[i] += in->distribution[i]; | 133 } |
| 134 if (in->last_non_zero > out->last_non_zero) { |
| 135 out->last_non_zero = in->last_non_zero; |
136 } | 136 } |
137 } | 137 } |
138 | 138 |
139 //------------------------------------------------------------------------------ | 139 //------------------------------------------------------------------------------ |
140 // Simplified k-Means, to assign Nb segments based on alpha-histogram | 140 // Simplified k-Means, to assign Nb segments based on alpha-histogram |
141 | 141 |
142 static void AssignSegments(VP8Encoder* const enc, | 142 static void AssignSegments(VP8Encoder* const enc, |
143 const int alphas[MAX_ALPHA + 1]) { | 143 const int alphas[MAX_ALPHA + 1]) { |
144 // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an | 144 // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an |
145 // explicit check is needed to avoid spurious warning about 'n + 1' exceeding | 145 // explicit check is needed to avoid spurious warning about 'n + 1' exceeding |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 #define MAX_UV_MODE 2 | 238 #define MAX_UV_MODE 2 |
239 | 239 |
240 static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { | 240 static int MBAnalyzeBestIntra16Mode(VP8EncIterator* const it) { |
241 const int max_mode = MAX_INTRA16_MODE; | 241 const int max_mode = MAX_INTRA16_MODE; |
242 int mode; | 242 int mode; |
243 int best_alpha = DEFAULT_ALPHA; | 243 int best_alpha = DEFAULT_ALPHA; |
244 int best_mode = 0; | 244 int best_mode = 0; |
245 | 245 |
246 VP8MakeLuma16Preds(it); | 246 VP8MakeLuma16Preds(it); |
247 for (mode = 0; mode < max_mode; ++mode) { | 247 for (mode = 0; mode < max_mode; ++mode) { |
248 VP8Histogram histo = { { 0 } }; | 248 VP8Histogram histo; |
249 int alpha; | 249 int alpha; |
250 | 250 |
251 VP8CollectHistogram(it->yuv_in_ + Y_OFF, | 251 InitHistogram(&histo); |
| 252 VP8CollectHistogram(it->yuv_in_ + Y_OFF_ENC, |
252 it->yuv_p_ + VP8I16ModeOffsets[mode], | 253 it->yuv_p_ + VP8I16ModeOffsets[mode], |
253 0, 16, &histo); | 254 0, 16, &histo); |
254 alpha = GetAlpha(&histo); | 255 alpha = GetAlpha(&histo); |
255 if (IS_BETTER_ALPHA(alpha, best_alpha)) { | 256 if (IS_BETTER_ALPHA(alpha, best_alpha)) { |
256 best_alpha = alpha; | 257 best_alpha = alpha; |
257 best_mode = mode; | 258 best_mode = mode; |
258 } | 259 } |
259 } | 260 } |
260 VP8SetIntra16Mode(it, best_mode); | 261 VP8SetIntra16Mode(it, best_mode); |
261 return best_alpha; | 262 return best_alpha; |
262 } | 263 } |
263 | 264 |
264 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, | 265 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, |
265 int best_alpha) { | 266 int best_alpha) { |
266 uint8_t modes[16]; | 267 uint8_t modes[16]; |
267 const int max_mode = MAX_INTRA4_MODE; | 268 const int max_mode = MAX_INTRA4_MODE; |
268 int i4_alpha; | 269 int i4_alpha; |
269 VP8Histogram total_histo = { { 0 } }; | 270 VP8Histogram total_histo; |
270 int cur_histo = 0; | 271 int cur_histo = 0; |
| 272 InitHistogram(&total_histo); |
271 | 273 |
272 VP8IteratorStartI4(it); | 274 VP8IteratorStartI4(it); |
273 do { | 275 do { |
274 int mode; | 276 int mode; |
275 int best_mode_alpha = DEFAULT_ALPHA; | 277 int best_mode_alpha = DEFAULT_ALPHA; |
276 VP8Histogram histos[2]; | 278 VP8Histogram histos[2]; |
277 const uint8_t* const src = it->yuv_in_ + Y_OFF + VP8Scan[it->i4_]; | 279 const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_]; |
278 | 280 |
279 VP8MakeIntra4Preds(it); | 281 VP8MakeIntra4Preds(it); |
280 for (mode = 0; mode < max_mode; ++mode) { | 282 for (mode = 0; mode < max_mode; ++mode) { |
281 int alpha; | 283 int alpha; |
282 | 284 |
283 memset(&histos[cur_histo], 0, sizeof(histos[cur_histo])); | 285 InitHistogram(&histos[cur_histo]); |
284 VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode], | 286 VP8CollectHistogram(src, it->yuv_p_ + VP8I4ModeOffsets[mode], |
285 0, 1, &histos[cur_histo]); | 287 0, 1, &histos[cur_histo]); |
286 alpha = GetAlpha(&histos[cur_histo]); | 288 alpha = GetAlpha(&histos[cur_histo]); |
287 if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) { | 289 if (IS_BETTER_ALPHA(alpha, best_mode_alpha)) { |
288 best_mode_alpha = alpha; | 290 best_mode_alpha = alpha; |
289 modes[it->i4_] = mode; | 291 modes[it->i4_] = mode; |
290 cur_histo ^= 1; // keep track of best histo so far. | 292 cur_histo ^= 1; // keep track of best histo so far. |
291 } | 293 } |
292 } | 294 } |
293 // accumulate best histogram | 295 // accumulate best histogram |
294 MergeHistograms(&histos[cur_histo ^ 1], &total_histo); | 296 MergeHistograms(&histos[cur_histo ^ 1], &total_histo); |
295 // Note: we reuse the original samples for predictors | 297 // Note: we reuse the original samples for predictors |
296 } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF)); | 298 } while (VP8IteratorRotateI4(it, it->yuv_in_ + Y_OFF_ENC)); |
297 | 299 |
298 i4_alpha = GetAlpha(&total_histo); | 300 i4_alpha = GetAlpha(&total_histo); |
299 if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { | 301 if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) { |
300 VP8SetIntra4Mode(it, modes); | 302 VP8SetIntra4Mode(it, modes); |
301 best_alpha = i4_alpha; | 303 best_alpha = i4_alpha; |
302 } | 304 } |
303 return best_alpha; | 305 return best_alpha; |
304 } | 306 } |
305 | 307 |
306 static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { | 308 static int MBAnalyzeBestUVMode(VP8EncIterator* const it) { |
307 int best_alpha = DEFAULT_ALPHA; | 309 int best_alpha = DEFAULT_ALPHA; |
308 int best_mode = 0; | 310 int best_mode = 0; |
309 const int max_mode = MAX_UV_MODE; | 311 const int max_mode = MAX_UV_MODE; |
310 int mode; | 312 int mode; |
311 | 313 |
312 VP8MakeChroma8Preds(it); | 314 VP8MakeChroma8Preds(it); |
313 for (mode = 0; mode < max_mode; ++mode) { | 315 for (mode = 0; mode < max_mode; ++mode) { |
314 VP8Histogram histo = { { 0 } }; | 316 VP8Histogram histo; |
315 int alpha; | 317 int alpha; |
316 VP8CollectHistogram(it->yuv_in_ + U_OFF, | 318 InitHistogram(&histo); |
| 319 VP8CollectHistogram(it->yuv_in_ + U_OFF_ENC, |
317 it->yuv_p_ + VP8UVModeOffsets[mode], | 320 it->yuv_p_ + VP8UVModeOffsets[mode], |
318 16, 16 + 4 + 4, &histo); | 321 16, 16 + 4 + 4, &histo); |
319 alpha = GetAlpha(&histo); | 322 alpha = GetAlpha(&histo); |
320 if (IS_BETTER_ALPHA(alpha, best_alpha)) { | 323 if (IS_BETTER_ALPHA(alpha, best_alpha)) { |
321 best_alpha = alpha; | 324 best_alpha = alpha; |
322 best_mode = mode; | 325 best_mode = mode; |
323 } | 326 } |
324 } | 327 } |
325 VP8SetIntraUVMode(it, best_mode); | 328 VP8SetIntraUVMode(it, best_mode); |
326 return best_alpha; | 329 return best_alpha; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 int alphas[MAX_ALPHA + 1]; | 398 int alphas[MAX_ALPHA + 1]; |
396 int alpha, uv_alpha; | 399 int alpha, uv_alpha; |
397 VP8EncIterator it; | 400 VP8EncIterator it; |
398 int delta_progress; | 401 int delta_progress; |
399 } SegmentJob; | 402 } SegmentJob; |
400 | 403 |
401 // main work call | 404 // main work call |
402 static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) { | 405 static int DoSegmentsJob(SegmentJob* const job, VP8EncIterator* const it) { |
403 int ok = 1; | 406 int ok = 1; |
404 if (!VP8IteratorIsDone(it)) { | 407 if (!VP8IteratorIsDone(it)) { |
405 uint8_t tmp[32 + ALIGN_CST]; | 408 uint8_t tmp[32 + WEBP_ALIGN_CST]; |
406 uint8_t* const scratch = (uint8_t*)DO_ALIGN(tmp); | 409 uint8_t* const scratch = (uint8_t*)WEBP_ALIGN(tmp); |
407 do { | 410 do { |
408 // Let's pretend we have perfect lossless reconstruction. | 411 // Let's pretend we have perfect lossless reconstruction. |
409 VP8IteratorImport(it, scratch); | 412 VP8IteratorImport(it, scratch); |
410 MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); | 413 MBAnalyze(it, job->alphas, &job->alpha, &job->uv_alpha); |
411 ok = VP8IteratorProgress(it, job->delta_progress); | 414 ok = VP8IteratorProgress(it, job->delta_progress); |
412 } while (ok && VP8IteratorNext(it)); | 415 } while (ok && VP8IteratorNext(it)); |
413 } | 416 } |
414 return ok; | 417 return ok; |
415 } | 418 } |
416 | 419 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 enc->alpha_ = main_job.alpha / total_mb; | 492 enc->alpha_ = main_job.alpha / total_mb; |
490 enc->uv_alpha_ = main_job.uv_alpha / total_mb; | 493 enc->uv_alpha_ = main_job.uv_alpha / total_mb; |
491 AssignSegments(enc, main_job.alphas); | 494 AssignSegments(enc, main_job.alphas); |
492 } | 495 } |
493 } else { // Use only one default segment. | 496 } else { // Use only one default segment. |
494 ResetAllMBInfo(enc); | 497 ResetAllMBInfo(enc); |
495 } | 498 } |
496 return ok; | 499 return ok; |
497 } | 500 } |
498 | 501 |
OLD | NEW |