| 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 |
| 11 // | 11 // |
| 12 // Author: Skal (pascal.massimino@gmail.com) | 12 // Author: Skal (pascal.massimino@gmail.com) |
| 13 | 13 |
| 14 #include <stdlib.h> | 14 #include <stdlib.h> |
| 15 #include <string.h> | 15 #include <string.h> |
| 16 #include <assert.h> | 16 #include <assert.h> |
| 17 | 17 |
| 18 #include "./vp8enci.h" | 18 #include "./vp8i_enc.h" |
| 19 #include "./cost.h" | 19 #include "./cost_enc.h" |
| 20 #include "../utils/utils.h" | 20 #include "../utils/utils.h" |
| 21 | 21 |
| 22 #define MAX_ITERS_K_MEANS 6 | 22 #define MAX_ITERS_K_MEANS 6 |
| 23 | 23 |
| 24 //------------------------------------------------------------------------------ | 24 //------------------------------------------------------------------------------ |
| 25 // Smooth the segment map by replacing isolated block by the majority of its | 25 // Smooth the segment map by replacing isolated block by the majority of its |
| 26 // neighbours. | 26 // neighbours. |
| 27 | 27 |
| 28 static void SmoothSegmentMap(VP8Encoder* const enc) { | 28 static void SmoothSegmentMap(VP8Encoder* const enc) { |
| 29 int n, x, y; | 29 int n, x, y; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 alpha = GetAlpha(&histo); | 255 alpha = GetAlpha(&histo); |
| 256 if (IS_BETTER_ALPHA(alpha, best_alpha)) { | 256 if (IS_BETTER_ALPHA(alpha, best_alpha)) { |
| 257 best_alpha = alpha; | 257 best_alpha = alpha; |
| 258 best_mode = mode; | 258 best_mode = mode; |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 VP8SetIntra16Mode(it, best_mode); | 261 VP8SetIntra16Mode(it, best_mode); |
| 262 return best_alpha; | 262 return best_alpha; |
| 263 } | 263 } |
| 264 | 264 |
| 265 static int FastMBAnalyze(VP8EncIterator* const it) { |
| 266 // Empirical cut-off value, should be around 16 (~=block size). We use the |
| 267 // [8-17] range and favor intra4 at high quality, intra16 for low quality. |
| 268 const int q = (int)it->enc_->config_->quality; |
| 269 const uint32_t kThreshold = 8 + (17 - 8) * q / 100; |
| 270 int k; |
| 271 uint32_t dc[16], m, m2; |
| 272 for (k = 0; k < 16; k += 4) { |
| 273 VP8Mean16x4(it->yuv_in_ + Y_OFF_ENC + k * BPS, &dc[k]); |
| 274 } |
| 275 for (m = 0, m2 = 0, k = 0; k < 16; ++k) { |
| 276 m += dc[k]; |
| 277 m2 += dc[k] * dc[k]; |
| 278 } |
| 279 if (kThreshold * m2 < m * m) { |
| 280 VP8SetIntra16Mode(it, 0); // DC16 |
| 281 } else { |
| 282 const uint8_t modes[16] = { 0 }; // DC4 |
| 283 VP8SetIntra4Mode(it, modes); |
| 284 } |
| 285 return 0; |
| 286 } |
| 287 |
| 265 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, | 288 static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it, |
| 266 int best_alpha) { | 289 int best_alpha) { |
| 267 uint8_t modes[16]; | 290 uint8_t modes[16]; |
| 268 const int max_mode = MAX_INTRA4_MODE; | 291 const int max_mode = MAX_INTRA4_MODE; |
| 269 int i4_alpha; | 292 int i4_alpha; |
| 270 VP8Histogram total_histo; | 293 VP8Histogram total_histo; |
| 271 int cur_histo = 0; | 294 int cur_histo = 0; |
| 272 InitHistogram(&total_histo); | 295 InitHistogram(&total_histo); |
| 273 | 296 |
| 274 VP8IteratorStartI4(it); | 297 VP8IteratorStartI4(it); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 static void MBAnalyze(VP8EncIterator* const it, | 360 static void MBAnalyze(VP8EncIterator* const it, |
| 338 int alphas[MAX_ALPHA + 1], | 361 int alphas[MAX_ALPHA + 1], |
| 339 int* const alpha, int* const uv_alpha) { | 362 int* const alpha, int* const uv_alpha) { |
| 340 const VP8Encoder* const enc = it->enc_; | 363 const VP8Encoder* const enc = it->enc_; |
| 341 int best_alpha, best_uv_alpha; | 364 int best_alpha, best_uv_alpha; |
| 342 | 365 |
| 343 VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED | 366 VP8SetIntra16Mode(it, 0); // default: Intra16, DC_PRED |
| 344 VP8SetSkip(it, 0); // not skipped | 367 VP8SetSkip(it, 0); // not skipped |
| 345 VP8SetSegment(it, 0); // default segment, spec-wise. | 368 VP8SetSegment(it, 0); // default segment, spec-wise. |
| 346 | 369 |
| 347 best_alpha = MBAnalyzeBestIntra16Mode(it); | 370 if (enc->method_ <= 1) { |
| 348 if (enc->method_ >= 5) { | 371 best_alpha = FastMBAnalyze(it); |
| 349 // We go and make a fast decision for intra4/intra16. | 372 } else { |
| 350 // It's usually not a good and definitive pick, but helps seeding the stats | 373 best_alpha = MBAnalyzeBestIntra16Mode(it); |
| 351 // about level bit-cost. | 374 if (enc->method_ >= 5) { |
| 352 // TODO(skal): improve criterion. | 375 // We go and make a fast decision for intra4/intra16. |
| 353 best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha); | 376 // It's usually not a good and definitive pick, but helps seeding the |
| 377 // stats about level bit-cost. |
| 378 // TODO(skal): improve criterion. |
| 379 best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha); |
| 380 } |
| 354 } | 381 } |
| 355 best_uv_alpha = MBAnalyzeBestUVMode(it); | 382 best_uv_alpha = MBAnalyzeBestUVMode(it); |
| 356 | 383 |
| 357 // Final susceptibility mix | 384 // Final susceptibility mix |
| 358 best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; | 385 best_alpha = (3 * best_alpha + best_uv_alpha + 2) >> 2; |
| 359 best_alpha = FinalAlphaValue(best_alpha); | 386 best_alpha = FinalAlphaValue(best_alpha); |
| 360 alphas[best_alpha]++; | 387 alphas[best_alpha]++; |
| 361 it->mb_->alpha_ = best_alpha; // for later remapping. | 388 it->mb_->alpha_ = best_alpha; // for later remapping. |
| 362 | 389 |
| 363 // Accumulate for later complexity analysis. | 390 // Accumulate for later complexity analysis. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 // expect the user's hook to be multi-thread safe | 473 // expect the user's hook to be multi-thread safe |
| 447 job->delta_progress = (start_row == 0) ? 20 : 0; | 474 job->delta_progress = (start_row == 0) ? 20 : 0; |
| 448 } | 475 } |
| 449 | 476 |
| 450 // main entry point | 477 // main entry point |
| 451 int VP8EncAnalyze(VP8Encoder* const enc) { | 478 int VP8EncAnalyze(VP8Encoder* const enc) { |
| 452 int ok = 1; | 479 int ok = 1; |
| 453 const int do_segments = | 480 const int do_segments = |
| 454 enc->config_->emulate_jpeg_size || // We need the complexity evaluation. | 481 enc->config_->emulate_jpeg_size || // We need the complexity evaluation. |
| 455 (enc->segment_hdr_.num_segments_ > 1) || | 482 (enc->segment_hdr_.num_segments_ > 1) || |
| 456 (enc->method_ == 0); // for method 0, we need preds_[] to be filled. | 483 (enc->method_ <= 1); // for method 0 - 1, we need preds_[] to be filled. |
| 457 if (do_segments) { | 484 if (do_segments) { |
| 458 const int last_row = enc->mb_h_; | 485 const int last_row = enc->mb_h_; |
| 459 // We give a little more than a half work to the main thread. | 486 // We give a little more than a half work to the main thread. |
| 460 const int split_row = (9 * last_row + 15) >> 4; | 487 const int split_row = (9 * last_row + 15) >> 4; |
| 461 const int total_mb = last_row * enc->mb_w_; | 488 const int total_mb = last_row * enc->mb_w_; |
| 462 #ifdef WEBP_USE_THREAD | 489 #ifdef WEBP_USE_THREAD |
| 463 const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it | 490 const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it |
| 464 const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); | 491 const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); |
| 465 #else | 492 #else |
| 466 const int do_mt = 0; | 493 const int do_mt = 0; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 497 enc->alpha_ = main_job.alpha / total_mb; | 524 enc->alpha_ = main_job.alpha / total_mb; |
| 498 enc->uv_alpha_ = main_job.uv_alpha / total_mb; | 525 enc->uv_alpha_ = main_job.uv_alpha / total_mb; |
| 499 AssignSegments(enc, main_job.alphas); | 526 AssignSegments(enc, main_job.alphas); |
| 500 } | 527 } |
| 501 } else { // Use only one default segment. | 528 } else { // Use only one default segment. |
| 502 ResetAllMBInfo(enc); | 529 ResetAllMBInfo(enc); |
| 503 } | 530 } |
| 504 return ok; | 531 return ok; |
| 505 } | 532 } |
| 506 | 533 |
| OLD | NEW |