// Copyright 2010 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 decoding functions, default plain-C implementations. // // Author: Skal (pascal.massimino@gmail.com)
#define STORE2(y, dc, d, c) do { \ constint DC = (dc); \
STORE(0, y, DC + (d)); \
STORE(1, y, DC + (c)); \
STORE(2, y, DC - (c)); \
STORE(3, y, DC - (d)); \
} while (0)
#if !WEBP_NEON_OMIT_C_CODE staticvoid TransformOne_C(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]; // [-4096, 4094] constint b = in[0] - in[8]; // [-4095, 4095] constint c = WEBP_TRANSFORM_AC3_MUL2(in[4]) -
WEBP_TRANSFORM_AC3_MUL1(in[12]); // [-3783, 3783] constint d = WEBP_TRANSFORM_AC3_MUL1(in[4]) +
WEBP_TRANSFORM_AC3_MUL2(in[12]); // [-3785, 3781]
tmp[0] = a + d; // [-7881, 7875]
tmp[1] = b + c; // [-7878, 7878]
tmp[2] = b - c; // [-7878, 7878]
tmp[3] = a - d; // [-7877, 7879]
tmp += 4;
in++;
} // Each pass is expanding the dynamic range by ~3.85 (upper bound). // The exact value is (2. + (20091 + 35468) / 65536). // After the second pass, maximum interval is [-3794, 3794], assuming // an input in [-2048, 2047] interval. We then need to add a dst value // in the [0, 255] range. // In the worst case scenario, the input to clip_8b() can be as large as // [-60713, 60968].
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, 0, a + d);
STORE(1, 0, b + c);
STORE(2, 0, b - c);
STORE(3, 0, a - d);
tmp++;
dst += BPS;
}
}
// Simplified transform when only in[0], in[1] and in[4] are non-zero staticvoid TransformAC3_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst) { constint a = in[0] + 4; constint c4 = WEBP_TRANSFORM_AC3_MUL2(in[4]); constint d4 = WEBP_TRANSFORM_AC3_MUL1(in[4]); constint c1 = WEBP_TRANSFORM_AC3_MUL2(in[1]); constint d1 = WEBP_TRANSFORM_AC3_MUL1(in[1]);
STORE2(0, a + d4, d1, c1);
STORE2(1, a + c4, d1, c1);
STORE2(2, a - c4, d1, c1);
STORE2(3, a - d4, d1, c1);
} #undef STORE2
staticvoid TransformTwo_C(const int16_t* WEBP_RESTRICT in,
uint8_t* WEBP_RESTRICT dst, int do_two) {
TransformOne_C(in, dst); if (do_two) {
TransformOne_C(in + 16, dst + 4);
}
} #endif// !WEBP_NEON_OMIT_C_CODE
staticvoid DC16_C(uint8_t* dst) { // DC int DC = 16; int j; for (j = 0; j < 16; ++j) {
DC += dst[-1 + j * BPS] + dst[j - BPS];
}
Put16(DC >> 5, dst);
}
staticvoid DC16NoTop_C(uint8_t* dst) { // DC with top samples not available int DC = 8; int j; for (j = 0; j < 16; ++j) {
DC += dst[-1 + j * BPS];
}
Put16(DC >> 4, dst);
}
staticvoid DC16NoLeft_C(uint8_t* dst) { // DC with left samples not available int DC = 8; int i; for (i = 0; i < 16; ++i) {
DC += dst[i - BPS];
}
Put16(DC >> 4, dst);
}
staticvoid DC16NoTopLeft_C(uint8_t* dst) { // DC with no top and left samples
Put16(0x80, dst);
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE staticvoid DC4_C(uint8_t* dst) { // DC
uint32_t dc = 4; int i; for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS];
dc >>= 3; for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4);
}
staticvoid DC8uv_C(uint8_t* dst) { // DC int dc0 = 8; int i; for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS] + dst[-1 + i * BPS];
}
Put8x8uv(dc0 >> 4, dst);
}
staticvoid DC8uvNoLeft_C(uint8_t* dst) { // DC with no left samples int dc0 = 4; int i; for (i = 0; i < 8; ++i) {
dc0 += dst[i - BPS];
}
Put8x8uv(dc0 >> 3, dst);
}
staticvoid DC8uvNoTop_C(uint8_t* dst) { // DC with no top samples int dc0 = 4; int i; for (i = 0; i < 8; ++i) {
dc0 += dst[-1 + i * BPS];
}
Put8x8uv(dc0 >> 3, dst);
}
staticvoid DC8uvNoTopLeft_C(uint8_t* dst) { // DC with nothing
Put8x8uv(0x80, dst);
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE staticvoid SimpleVFilter16_C(uint8_t* p, int stride, int thresh) { int i; constint thresh2 = 2 * thresh + 1; for (i = 0; i < 16; ++i) { if (NeedsFilter_C(p + i, stride, thresh2)) {
DoFilter2_C(p + i, stride);
}
}
}
staticvoid SimpleHFilter16_C(uint8_t* p, int stride, int thresh) { int i; constint thresh2 = 2 * thresh + 1; for (i = 0; i < 16; ++i) { if (NeedsFilter_C(p + i * stride, 1, thresh2)) {
DoFilter2_C(p + i * stride, 1);
}
}
}
staticvoid SimpleVFilter16i_C(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) {
p += 4 * stride;
SimpleVFilter16_C(p, stride, thresh);
}
}
staticvoid SimpleHFilter16i_C(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) {
p += 4;
SimpleHFilter16_C(p, stride, thresh);
}
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC static WEBP_INLINE void FilterLoop26_C(uint8_t* p, int hstride, int vstride, int size, int thresh, int ithresh, int hev_thresh) { constint thresh2 = 2 * thresh + 1; while (size-- > 0) { if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { if (Hev(p, hstride, hev_thresh)) {
DoFilter2_C(p, hstride);
} else {
DoFilter6_C(p, hstride);
}
}
p += vstride;
}
}
static WEBP_INLINE void FilterLoop24_C(uint8_t* p, int hstride, int vstride, int size, int thresh, int ithresh, int hev_thresh) { constint thresh2 = 2 * thresh + 1; while (size-- > 0) { if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { if (Hev(p, hstride, hev_thresh)) {
DoFilter2_C(p, hstride);
} else {
DoFilter4_C(p, hstride);
}
}
p += vstride;
}
} #endif// !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
#if !WEBP_NEON_OMIT_C_CODE // on macroblock edges staticvoid VFilter16_C(uint8_t* p, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh);
}
staticvoid HFilter16_C(uint8_t* p, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh);
}
// on three inner edges staticvoid VFilter16i_C(uint8_t* p, int stride, int thresh, int ithresh, int hev_thresh) { int k; for (k = 3; k > 0; --k) {
p += 4 * stride;
FilterLoop24_C(p, stride, 1, 16, thresh, ithresh, hev_thresh);
}
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC staticvoid HFilter16i_C(uint8_t* p, int stride, int thresh, int ithresh, int hev_thresh) { int k; for (k = 3; k > 0; --k) {
p += 4;
FilterLoop24_C(p, 1, stride, 16, thresh, ithresh, hev_thresh);
}
} #endif// !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
#if !WEBP_NEON_OMIT_C_CODE // 8-pixels wide variant, for chroma filtering staticvoid VFilter8_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(u, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop26_C(v, stride, 1, 8, thresh, ithresh, hev_thresh);
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC staticvoid HFilter8_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop26_C(u, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop26_C(v, 1, stride, 8, thresh, ithresh, hev_thresh);
} #endif// !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
#if !WEBP_NEON_OMIT_C_CODE staticvoid VFilter8i_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24_C(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
FilterLoop24_C(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh);
} #endif// !WEBP_NEON_OMIT_C_CODE
#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC staticvoid HFilter8i_C(uint8_t* WEBP_RESTRICT u, uint8_t* WEBP_RESTRICT v, int stride, int thresh, int ithresh, int hev_thresh) {
FilterLoop24_C(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
FilterLoop24_C(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh);
} #endif// !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC
// If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { #ifdefined(WEBP_HAVE_SSE2) if (VP8GetCPUInfo(kSSE2)) {
VP8DspInitSSE2(); #ifdefined(WEBP_HAVE_SSE41) if (VP8GetCPUInfo(kSSE4_1)) {
VP8DspInitSSE41();
} #endif
} #endif #ifdefined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) {
VP8DspInitMIPS32();
} #endif #ifdefined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) {
VP8DspInitMIPSdspR2();
} #endif #ifdefined(WEBP_USE_MSA) if (VP8GetCPUInfo(kMSA)) {
VP8DspInitMSA();
} #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.