| 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 |