// Copyright 2011 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Speed-critical encoding functions. // // Author: Skal (pascal.massimino@gmail.com)
#include <assert.h> #include <stdlib.h> // for abs()
#if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE int clip_max(int v, int max) { return (v > max) ? max : v;
} #endif// !WEBP_NEON_OMIT_C_CODE
//------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms: // the higher, the "easier" the macroblock is to compress.
// We declare this variable 'volatile' to prevent instruction reordering // and make sure it's set to true _last_ (so as to be thread-safe) staticvolatileint tables_ok = 0;
static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { if (!tables_ok) { int i; for (i = -255; i <= 255 + 255; ++i) {
clip1[255 + i] = clip_8b(i);
}
tables_ok = 1;
}
}
static WEBP_INLINE void ITransformOne(const uint8_t* WEBP_RESTRICT ref, const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) { int C[4 * 4], *tmp; int i;
tmp = C; for (i = 0; i < 4; ++i) { // vertical pass constint a = in[0] + in[8]; constint b = in[0] - in[8]; constint c =
WEBP_TRANSFORM_AC3_MUL2(in[4]) - WEBP_TRANSFORM_AC3_MUL1(in[12]); constint d =
WEBP_TRANSFORM_AC3_MUL1(in[4]) + WEBP_TRANSFORM_AC3_MUL2(in[12]);
tmp[0] = a + d;
tmp[1] = b + c;
tmp[2] = b - c;
tmp[3] = a - d;
tmp += 4;
in++;
}
tmp = C; for (i = 0; i < 4; ++i) { // horizontal pass constint dc = tmp[0] + 4; constint a = dc + tmp[8]; constint b = dc - tmp[8]; constint c =
WEBP_TRANSFORM_AC3_MUL2(tmp[4]) - WEBP_TRANSFORM_AC3_MUL1(tmp[12]); constint d =
WEBP_TRANSFORM_AC3_MUL1(tmp[4]) + WEBP_TRANSFORM_AC3_MUL2(tmp[12]);
STORE(0, i, a + d);
STORE(1, i, b + c);
STORE(2, i, b - c);
STORE(3, i, a - d);
tmp++;
}
}
staticvoid ITransform_C(const uint8_t* WEBP_RESTRICT ref, const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
ITransformOne(ref, in, dst); if (do_two) {
ITransformOne(ref + 4, in + 16, dst + 4);
}
}
static WEBP_INLINE void TrueMotion(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT left, const uint8_t* WEBP_RESTRICT top, int size) { int y; if (left != NULL) { if (top != NULL) { const uint8_t* const clip = clip1 + 255 - left[-1]; for (y = 0; y < size; ++y) { const uint8_t* const clip_table = clip + left[y]; int x; for (x = 0; x < size; ++x) {
dst[x] = clip_table[top[x]];
}
dst += BPS;
}
} else {
HorizontalPred(dst, left, size);
}
} else { // true motion without left samples (hence: with default 129 value) // is equivalent to VE prediction where you just copy the top samples. // Note that if top samples are not available, the default value is // then 129, and not 127 as in the VerticalPred case. if (top != NULL) {
VerticalPred(dst, top, size);
} else {
Fill(dst, 129, size);
}
}
}
static WEBP_INLINE void DCMode(uint8_t* WEBP_RESTRICT dst, const uint8_t* WEBP_RESTRICT left, const uint8_t* WEBP_RESTRICT top, int size, int round, int shift) { int DC = 0; int j; if (top != NULL) { for (j = 0; j < size; ++j) DC += top[j]; if (left != NULL) { // top and left present for (j = 0; j < size; ++j) DC += left[j];
} else { // top, but no left
DC += DC;
}
DC = (DC + round) >> shift;
} elseif (left != NULL) { // left but no top for (j = 0; j < size; ++j) DC += left[j];
DC += DC;
DC = (DC + round) >> shift;
} else { // no top, no left, nothing.
DC = 0x80;
}
Fill(dst, DC, size);
}
#if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE int GetSSE(const uint8_t* WEBP_RESTRICT a, const uint8_t* WEBP_RESTRICT b, int w, int h) { int count = 0; int y, x; for (y = 0; y < h; ++y) { for (x = 0; x < w; ++x) { constint diff = (int)a[x] - b[x];
count += diff * diff;
}
a += BPS;
b += BPS;
} return count;
}
staticint SSE16x16_C(const uint8_t* WEBP_RESTRICT a, const uint8_t* WEBP_RESTRICT b) { return GetSSE(a, b, 16, 16);
} staticint SSE16x8_C(const uint8_t* WEBP_RESTRICT a, const uint8_t* WEBP_RESTRICT b) { return GetSSE(a, b, 16, 8);
} staticint SSE8x8_C(const uint8_t* WEBP_RESTRICT a, const uint8_t* WEBP_RESTRICT b) { return GetSSE(a, b, 8, 8);
} staticint SSE4x4_C(const uint8_t* WEBP_RESTRICT a, const uint8_t* WEBP_RESTRICT b) { return GetSSE(a, b, 4, 4);
} #endif// !WEBP_NEON_OMIT_C_CODE
staticvoid Mean16x4_C(const uint8_t* WEBP_RESTRICT ref, uint32_t dc[4]) { int k, x, y; for (k = 0; k < 4; ++k) {
uint32_t avg = 0; for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) {
avg += ref[x + y * BPS];
}
}
dc[k] = avg;
ref += 4; // go to next 4x4 block.
}
}
//------------------------------------------------------------------------------ // Texture distortion // // We try to match the spectral content (weighted) between source and // reconstructed samples.
#if !WEBP_NEON_OMIT_C_CODE // Hadamard transform // Returns the weighted sum of the absolute value of transformed coefficients. // w[] contains a row-major 4 by 4 symmetric matrix. staticint TTransform(const uint8_t* WEBP_RESTRICT in, const uint16_t* WEBP_RESTRICT w) { int sum = 0; int tmp[16]; int i; // horizontal pass for (i = 0; i < 4; ++i, in += BPS) { constint a0 = in[0] + in[2]; constint a1 = in[1] + in[3]; constint a2 = in[1] - in[3]; constint a3 = in[0] - in[2];
tmp[0 + i * 4] = a0 + a1;
tmp[1 + i * 4] = a3 + a2;
tmp[2 + i * 4] = a3 - a2;
tmp[3 + i * 4] = a0 - a1;
} // vertical pass for (i = 0; i < 4; ++i, ++w) { constint a0 = tmp[0 + i] + tmp[8 + i]; constint a1 = tmp[4 + i] + tmp[12+ i]; constint a2 = tmp[4 + i] - tmp[12+ i]; constint a3 = tmp[0 + i] - tmp[8 + i]; constint b0 = a0 + a1; constint b1 = a3 + a2; constint b2 = a3 - a2; constint b3 = a0 - a1;
sum += w[ 0] * abs(b0);
sum += w[ 4] * abs(b1);
sum += w[ 8] * abs(b2);
sum += w[12] * abs(b3);
} return sum;
}
staticint Disto16x16_C(const uint8_t* WEBP_RESTRICT const a, const uint8_t* WEBP_RESTRICT const b, const uint16_t* WEBP_RESTRICT const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) {
D += Disto4x4_C(a + x + y, b + x + y, w);
}
} return D;
} #endif// !WEBP_NEON_OMIT_C_CODE
// If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { #ifdefined(WEBP_HAVE_SSE2) if (VP8GetCPUInfo(kSSE2)) {
VP8EncDspInitSSE2(); #ifdefined(WEBP_HAVE_SSE41) if (VP8GetCPUInfo(kSSE4_1)) {
VP8EncDspInitSSE41();
} #endif
} #endif #ifdefined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) {
VP8EncDspInitMIPS32();
} #endif #ifdefined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) {
VP8EncDspInitMIPSdspR2();
} #endif #ifdefined(WEBP_USE_MSA) if (VP8GetCPUInfo(kMSA)) {
VP8EncDspInitMSA();
} #endif
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.