Index: third_party/libwebp/dsp/enc.c |
diff --git a/third_party/libwebp/dsp/enc.c b/third_party/libwebp/dsp/enc.c |
index 8899d50015c69051dc1624f84ebd5f9483ce1fad..f639f5570c436bc6b914376ab93fe786aa1083fb 100644 |
--- a/third_party/libwebp/dsp/enc.c |
+++ b/third_party/libwebp/dsp/enc.c |
@@ -69,7 +69,7 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, |
// Convert coefficients to bin. |
for (k = 0; k < 16; ++k) { |
- const int v = abs(out[k]) >> 3; // TODO(skal): add rounding? |
+ const int v = abs(out[k]) >> 3; |
const int clipped_value = clip_max(v, MAX_COEFF_THRESH); |
++distribution[clipped_value]; |
} |
@@ -559,6 +559,7 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) { |
// Hadamard transform |
// Returns the weighted sum of the absolute value of transformed coefficients. |
+// w[] contains a row-major 4 by 4 symmetric matrix. |
static int TTransform(const uint8_t* in, const uint16_t* w) { |
int sum = 0; |
int tmp[16]; |
@@ -636,7 +637,7 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], |
int level = QUANTDIV(coeff, iQ, B); |
if (level > MAX_LEVEL) level = MAX_LEVEL; |
if (sign) level = -level; |
- in[j] = level * Q; |
+ in[j] = level * (int)Q; |
out[n] = level; |
if (level) last = n; |
} else { |
@@ -670,7 +671,7 @@ static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], |
int level = QUANTDIV(coeff, iQ, B); |
if (level > MAX_LEVEL) level = MAX_LEVEL; |
if (sign) level = -level; |
- in[j] = level * Q; |
+ in[j] = level * (int)Q; |
out[n] = level; |
if (level) last = n; |
} else { |
@@ -702,6 +703,68 @@ static void Copy16x8(const uint8_t* src, uint8_t* dst) { |
} |
//------------------------------------------------------------------------------ |
+ |
+static void SSIMAccumulateClipped(const uint8_t* src1, int stride1, |
+ const uint8_t* src2, int stride2, |
+ int xo, int yo, int W, int H, |
+ VP8DistoStats* const stats) { |
+ const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; |
+ const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 |
+ : yo + VP8_SSIM_KERNEL; |
+ const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; |
+ const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 |
+ : xo + VP8_SSIM_KERNEL; |
+ int x, y; |
+ src1 += ymin * stride1; |
+ src2 += ymin * stride2; |
+ for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { |
+ for (x = xmin; x <= xmax; ++x) { |
+ const int s1 = src1[x]; |
+ const int s2 = src2[x]; |
+ stats->w += 1; |
+ stats->xm += s1; |
+ stats->ym += s2; |
+ stats->xxm += s1 * s1; |
+ stats->xym += s1 * s2; |
+ stats->yym += s2 * s2; |
+ } |
+ } |
+} |
+ |
+static void SSIMAccumulate(const uint8_t* src1, int stride1, |
+ const uint8_t* src2, int stride2, |
+ VP8DistoStats* const stats) { |
+ int x, y; |
+ for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { |
+ for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { |
+ const int s1 = src1[x]; |
+ const int s2 = src2[x]; |
+ stats->w += 1; |
+ stats->xm += s1; |
+ stats->ym += s2; |
+ stats->xxm += s1 * s1; |
+ stats->xym += s1 * s2; |
+ stats->yym += s2 * s2; |
+ } |
+ } |
+} |
+ |
+VP8SSIMAccumulateFunc VP8SSIMAccumulate; |
+VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; |
+ |
+static volatile VP8CPUInfo ssim_last_cpuinfo_used = |
+ (VP8CPUInfo)&ssim_last_cpuinfo_used; |
+ |
+WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { |
+ if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return; |
+ |
+ VP8SSIMAccumulate = SSIMAccumulate; |
+ VP8SSIMAccumulateClipped = SSIMAccumulateClipped; |
+ |
+ ssim_last_cpuinfo_used = VP8GetCPUInfo; |
+} |
+ |
+//------------------------------------------------------------------------------ |
// Initialization |
// Speed-critical function pointers. We have to initialize them to the default |