diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index d197eeb6..98782c88 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -86,6 +86,11 @@ typedef int (*VP8QuantizeBlock)(int16_t in[16], int16_t out[16], int n, const struct VP8Matrix* const mtx); extern VP8QuantizeBlock VP8EncQuantizeBlock; +// specific to 2nd transform: +typedef int (*VP8QuantizeBlockWHT)(int16_t in[16], int16_t out[16], + const struct VP8Matrix* const mtx); +extern VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; + // Collect histogram for susceptibility calculation and accumulate in histo[]. struct VP8Histogram; typedef void (*VP8CHisto)(const uint8_t* ref, const uint8_t* pred, diff --git a/src/dsp/enc.c b/src/dsp/enc.c index 3eeadbef..aa71068a 100644 --- a/src/dsp/enc.c +++ b/src/dsp/enc.c @@ -11,7 +11,9 @@ // // Author: Skal (pascal.massimino@gmail.com) +#include #include // for abs() + #include "./dsp.h" #include "../enc/vp8enci.h" @@ -652,6 +654,31 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return (last >= 0); } +static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + int n, last = -1; + for (n = 0; n < 16; ++n) { + const int j = kZigzag[n]; + const int sign = (in[j] < 0); + const int coeff = sign ? -in[j] : in[j]; + assert(mtx->sharpen_[j] == 0); + if (coeff > mtx->zthresh_[j]) { + const int Q = mtx->q_[j]; + const int iQ = mtx->iq_[j]; + const int B = mtx->bias_[j]; + out[n] = QUANTDIV(coeff, iQ, B); + if (out[n] > MAX_LEVEL) out[n] = MAX_LEVEL; + if (sign) out[n] = -out[n]; + in[j] = out[n] * Q; + if (out[n]) last = n; + } else { + out[n] = 0; + in[j] = 0; + } + } + return (last >= 0); +} + //------------------------------------------------------------------------------ // Block copy @@ -686,6 +713,7 @@ VP8Metric VP8SSE4x4; VP8WMetric VP8TDisto4x4; VP8WMetric VP8TDisto16x16; VP8QuantizeBlock VP8EncQuantizeBlock; +VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT; VP8BlockCopy VP8Copy4x4; extern void VP8EncDspInitSSE2(void); @@ -710,6 +738,7 @@ void VP8EncDspInit(void) { VP8TDisto4x4 = Disto4x4; VP8TDisto16x16 = Disto16x16; VP8EncQuantizeBlock = QuantizeBlock; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT; VP8Copy4x4 = Copy4x4; // If defined, use CPUInfo() to overwrite some pointers with faster versions. diff --git a/src/dsp/enc_sse2.c b/src/dsp/enc_sse2.c index acc71edb..e47b1089 100644 --- a/src/dsp/enc_sse2.c +++ b/src/dsp/enc_sse2.c @@ -930,6 +930,11 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16], } } +static int QuantizeBlockWHTSSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return QuantizeBlockSSE2(in, out, 0, mtx); +} + #endif // WEBP_USE_SSE2 //------------------------------------------------------------------------------ @@ -941,6 +946,7 @@ void VP8EncDspInitSSE2(void) { #if defined(WEBP_USE_SSE2) VP8CollectHistogram = CollectHistogramSSE2; VP8EncQuantizeBlock = QuantizeBlockSSE2; + VP8EncQuantizeBlockWHT = QuantizeBlockWHTSSE2; VP8ITransform = ITransformSSE2; VP8FTransform = FTransformSSE2; VP8FTransformWHT = FTransformWHTSSE2; diff --git a/src/enc/quant.c b/src/enc/quant.c index 3ad49499..75e097dd 100644 --- a/src/enc/quant.c +++ b/src/enc/quant.c @@ -723,7 +723,7 @@ static int ReconstructIntra16(VP8EncIterator* const it, VP8FTransform(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]); } VP8FTransformWHT(tmp[0], dc_tmp); - nz |= VP8EncQuantizeBlock(dc_tmp, rd->y_dc_levels, 0, &dqm->y2_) << 24; + nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &dqm->y2_) << 24; if (DO_TRELLIS_I16 && it->do_trellis_) { int x, y;