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 // Speed-critical encoding functions. | 10 // Speed-critical encoding functions. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 int j; | 62 int j; |
63 int distribution[MAX_COEFF_THRESH + 1] = { 0 }; | 63 int distribution[MAX_COEFF_THRESH + 1] = { 0 }; |
64 for (j = start_block; j < end_block; ++j) { | 64 for (j = start_block; j < end_block; ++j) { |
65 int k; | 65 int k; |
66 int16_t out[16]; | 66 int16_t out[16]; |
67 | 67 |
68 VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); | 68 VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); |
69 | 69 |
70 // Convert coefficients to bin. | 70 // Convert coefficients to bin. |
71 for (k = 0; k < 16; ++k) { | 71 for (k = 0; k < 16; ++k) { |
72 const int v = abs(out[k]) >> 3; // TODO(skal): add rounding? | 72 const int v = abs(out[k]) >> 3; |
73 const int clipped_value = clip_max(v, MAX_COEFF_THRESH); | 73 const int clipped_value = clip_max(v, MAX_COEFF_THRESH); |
74 ++distribution[clipped_value]; | 74 ++distribution[clipped_value]; |
75 } | 75 } |
76 } | 76 } |
77 VP8SetHistogramData(distribution, histo); | 77 VP8SetHistogramData(distribution, histo); |
78 } | 78 } |
79 | 79 |
80 //------------------------------------------------------------------------------ | 80 //------------------------------------------------------------------------------ |
81 // run-time tables (~4k) | 81 // run-time tables (~4k) |
82 | 82 |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 } | 552 } |
553 | 553 |
554 //------------------------------------------------------------------------------ | 554 //------------------------------------------------------------------------------ |
555 // Texture distortion | 555 // Texture distortion |
556 // | 556 // |
557 // We try to match the spectral content (weighted) between source and | 557 // We try to match the spectral content (weighted) between source and |
558 // reconstructed samples. | 558 // reconstructed samples. |
559 | 559 |
560 // Hadamard transform | 560 // Hadamard transform |
561 // Returns the weighted sum of the absolute value of transformed coefficients. | 561 // Returns the weighted sum of the absolute value of transformed coefficients. |
| 562 // w[] contains a row-major 4 by 4 symmetric matrix. |
562 static int TTransform(const uint8_t* in, const uint16_t* w) { | 563 static int TTransform(const uint8_t* in, const uint16_t* w) { |
563 int sum = 0; | 564 int sum = 0; |
564 int tmp[16]; | 565 int tmp[16]; |
565 int i; | 566 int i; |
566 // horizontal pass | 567 // horizontal pass |
567 for (i = 0; i < 4; ++i, in += BPS) { | 568 for (i = 0; i < 4; ++i, in += BPS) { |
568 const int a0 = in[0] + in[2]; | 569 const int a0 = in[0] + in[2]; |
569 const int a1 = in[1] + in[3]; | 570 const int a1 = in[1] + in[3]; |
570 const int a2 = in[1] - in[3]; | 571 const int a2 = in[1] - in[3]; |
571 const int a3 = in[0] - in[2]; | 572 const int a3 = in[0] - in[2]; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 const int j = kZigzag[n]; | 630 const int j = kZigzag[n]; |
630 const int sign = (in[j] < 0); | 631 const int sign = (in[j] < 0); |
631 const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; | 632 const uint32_t coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; |
632 if (coeff > mtx->zthresh_[j]) { | 633 if (coeff > mtx->zthresh_[j]) { |
633 const uint32_t Q = mtx->q_[j]; | 634 const uint32_t Q = mtx->q_[j]; |
634 const uint32_t iQ = mtx->iq_[j]; | 635 const uint32_t iQ = mtx->iq_[j]; |
635 const uint32_t B = mtx->bias_[j]; | 636 const uint32_t B = mtx->bias_[j]; |
636 int level = QUANTDIV(coeff, iQ, B); | 637 int level = QUANTDIV(coeff, iQ, B); |
637 if (level > MAX_LEVEL) level = MAX_LEVEL; | 638 if (level > MAX_LEVEL) level = MAX_LEVEL; |
638 if (sign) level = -level; | 639 if (sign) level = -level; |
639 in[j] = level * Q; | 640 in[j] = level * (int)Q; |
640 out[n] = level; | 641 out[n] = level; |
641 if (level) last = n; | 642 if (level) last = n; |
642 } else { | 643 } else { |
643 out[n] = 0; | 644 out[n] = 0; |
644 in[j] = 0; | 645 in[j] = 0; |
645 } | 646 } |
646 } | 647 } |
647 return (last >= 0); | 648 return (last >= 0); |
648 } | 649 } |
649 | 650 |
(...skipping 13 matching lines...) Expand all Loading... |
663 const int sign = (in[j] < 0); | 664 const int sign = (in[j] < 0); |
664 const uint32_t coeff = sign ? -in[j] : in[j]; | 665 const uint32_t coeff = sign ? -in[j] : in[j]; |
665 assert(mtx->sharpen_[j] == 0); | 666 assert(mtx->sharpen_[j] == 0); |
666 if (coeff > mtx->zthresh_[j]) { | 667 if (coeff > mtx->zthresh_[j]) { |
667 const uint32_t Q = mtx->q_[j]; | 668 const uint32_t Q = mtx->q_[j]; |
668 const uint32_t iQ = mtx->iq_[j]; | 669 const uint32_t iQ = mtx->iq_[j]; |
669 const uint32_t B = mtx->bias_[j]; | 670 const uint32_t B = mtx->bias_[j]; |
670 int level = QUANTDIV(coeff, iQ, B); | 671 int level = QUANTDIV(coeff, iQ, B); |
671 if (level > MAX_LEVEL) level = MAX_LEVEL; | 672 if (level > MAX_LEVEL) level = MAX_LEVEL; |
672 if (sign) level = -level; | 673 if (sign) level = -level; |
673 in[j] = level * Q; | 674 in[j] = level * (int)Q; |
674 out[n] = level; | 675 out[n] = level; |
675 if (level) last = n; | 676 if (level) last = n; |
676 } else { | 677 } else { |
677 out[n] = 0; | 678 out[n] = 0; |
678 in[j] = 0; | 679 in[j] = 0; |
679 } | 680 } |
680 } | 681 } |
681 return (last >= 0); | 682 return (last >= 0); |
682 } | 683 } |
683 | 684 |
(...skipping 11 matching lines...) Expand all Loading... |
695 | 696 |
696 static void Copy4x4(const uint8_t* src, uint8_t* dst) { | 697 static void Copy4x4(const uint8_t* src, uint8_t* dst) { |
697 Copy(src, dst, 4, 4); | 698 Copy(src, dst, 4, 4); |
698 } | 699 } |
699 | 700 |
700 static void Copy16x8(const uint8_t* src, uint8_t* dst) { | 701 static void Copy16x8(const uint8_t* src, uint8_t* dst) { |
701 Copy(src, dst, 16, 8); | 702 Copy(src, dst, 16, 8); |
702 } | 703 } |
703 | 704 |
704 //------------------------------------------------------------------------------ | 705 //------------------------------------------------------------------------------ |
| 706 |
| 707 static void SSIMAccumulateClipped(const uint8_t* src1, int stride1, |
| 708 const uint8_t* src2, int stride2, |
| 709 int xo, int yo, int W, int H, |
| 710 VP8DistoStats* const stats) { |
| 711 const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; |
| 712 const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 |
| 713 : yo + VP8_SSIM_KERNEL; |
| 714 const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; |
| 715 const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 |
| 716 : xo + VP8_SSIM_KERNEL; |
| 717 int x, y; |
| 718 src1 += ymin * stride1; |
| 719 src2 += ymin * stride2; |
| 720 for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { |
| 721 for (x = xmin; x <= xmax; ++x) { |
| 722 const int s1 = src1[x]; |
| 723 const int s2 = src2[x]; |
| 724 stats->w += 1; |
| 725 stats->xm += s1; |
| 726 stats->ym += s2; |
| 727 stats->xxm += s1 * s1; |
| 728 stats->xym += s1 * s2; |
| 729 stats->yym += s2 * s2; |
| 730 } |
| 731 } |
| 732 } |
| 733 |
| 734 static void SSIMAccumulate(const uint8_t* src1, int stride1, |
| 735 const uint8_t* src2, int stride2, |
| 736 VP8DistoStats* const stats) { |
| 737 int x, y; |
| 738 for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { |
| 739 for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { |
| 740 const int s1 = src1[x]; |
| 741 const int s2 = src2[x]; |
| 742 stats->w += 1; |
| 743 stats->xm += s1; |
| 744 stats->ym += s2; |
| 745 stats->xxm += s1 * s1; |
| 746 stats->xym += s1 * s2; |
| 747 stats->yym += s2 * s2; |
| 748 } |
| 749 } |
| 750 } |
| 751 |
| 752 VP8SSIMAccumulateFunc VP8SSIMAccumulate; |
| 753 VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; |
| 754 |
| 755 static volatile VP8CPUInfo ssim_last_cpuinfo_used = |
| 756 (VP8CPUInfo)&ssim_last_cpuinfo_used; |
| 757 |
| 758 WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { |
| 759 if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return; |
| 760 |
| 761 VP8SSIMAccumulate = SSIMAccumulate; |
| 762 VP8SSIMAccumulateClipped = SSIMAccumulateClipped; |
| 763 |
| 764 ssim_last_cpuinfo_used = VP8GetCPUInfo; |
| 765 } |
| 766 |
| 767 //------------------------------------------------------------------------------ |
705 // Initialization | 768 // Initialization |
706 | 769 |
707 // Speed-critical function pointers. We have to initialize them to the default | 770 // Speed-critical function pointers. We have to initialize them to the default |
708 // implementations within VP8EncDspInit(). | 771 // implementations within VP8EncDspInit(). |
709 VP8CHisto VP8CollectHistogram; | 772 VP8CHisto VP8CollectHistogram; |
710 VP8Idct VP8ITransform; | 773 VP8Idct VP8ITransform; |
711 VP8Fdct VP8FTransform; | 774 VP8Fdct VP8FTransform; |
712 VP8Fdct VP8FTransform2; | 775 VP8Fdct VP8FTransform2; |
713 VP8WHT VP8FTransformWHT; | 776 VP8WHT VP8FTransformWHT; |
714 VP8Intra4Preds VP8EncPredLuma4; | 777 VP8Intra4Preds VP8EncPredLuma4; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 } | 854 } |
792 #endif | 855 #endif |
793 #if defined(WEBP_USE_MIPS_DSP_R2) | 856 #if defined(WEBP_USE_MIPS_DSP_R2) |
794 if (VP8GetCPUInfo(kMIPSdspR2)) { | 857 if (VP8GetCPUInfo(kMIPSdspR2)) { |
795 VP8EncDspInitMIPSdspR2(); | 858 VP8EncDspInitMIPSdspR2(); |
796 } | 859 } |
797 #endif | 860 #endif |
798 } | 861 } |
799 enc_last_cpuinfo_used = VP8GetCPUInfo; | 862 enc_last_cpuinfo_used = VP8GetCPUInfo; |
800 } | 863 } |
OLD | NEW |