summaryrefslogtreecommitdiff
path: root/src/dec/vp8.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dec/vp8.c')
-rw-r--r--src/dec/vp8.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/src/dec/vp8.c b/src/dec/vp8.c
index 61682540..9b54389f 100644
--- a/src/dec/vp8.c
+++ b/src/dec/vp8.c
@@ -27,6 +27,16 @@ int WebPGetDecoderVersion(void) {
}
//------------------------------------------------------------------------------
+// Signature and pointer-to-function for GetCoeffs() variants below.
+
+typedef int (*GetCoeffsFunc)(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out);
+static volatile GetCoeffsFunc GetCoeffs = NULL;
+
+static void InitGetCoeffs(void);
+
+//------------------------------------------------------------------------------
// VP8Decoder
static void SetOk(VP8Decoder* const dec) {
@@ -51,6 +61,7 @@ VP8Decoder* VP8New(void) {
WebPGetWorkerInterface()->Init(&dec->worker_);
dec->ready_ = 0;
dec->num_parts_minus_one_ = 0;
+ InitGetCoeffs();
}
return dec;
}
@@ -422,8 +433,9 @@ static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) {
}
// Returns the position of the last non-zero coeff plus one
-static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[],
- int ctx, const quant_t dq, int n, int16_t* out) {
+static int GetCoeffsFast(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out) {
const uint8_t* p = prob[n]->probas_[ctx];
for (; n < 16; ++n) {
if (!VP8GetBit(br, p[0])) {
@@ -449,6 +461,46 @@ static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[],
return 16;
}
+// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version
+// of VP8GetBitAlt() targeting specific platforms.
+static int GetCoeffsAlt(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out) {
+ const uint8_t* p = prob[n]->probas_[ctx];
+ for (; n < 16; ++n) {
+ if (!VP8GetBitAlt(br, p[0])) {
+ return n; // previous coeff was last non-zero coeff
+ }
+ while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs
+ p = prob[++n]->probas_[0];
+ if (n == 16) return 16;
+ }
+ { // non zero coeff
+ const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0];
+ int v;
+ if (!VP8GetBitAlt(br, p[2])) {
+ v = 1;
+ p = p_ctx[1];
+ } else {
+ v = GetLargeValue(br, p);
+ p = p_ctx[2];
+ }
+ out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
+ }
+ }
+ return 16;
+}
+
+WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) {
+ if (GetCoeffs == NULL) {
+ if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
+ GetCoeffs = GetCoeffsAlt;
+ } else {
+ GetCoeffs = GetCoeffsFast;
+ }
+ }
+}
+
static WEBP_INLINE uint32_t NzCodeBits(uint32_t nz_coeffs, int nz, int dc_nz) {
nz_coeffs <<= 2;
nz_coeffs |= (nz > 3) ? 3 : (nz > 1) ? 2 : dc_nz;