Have C encoding predictors use decoding predictors.

libwebp.a in Release mode with no symbols size in bytes:
986430 -> 975114  (-1.1%)

Change-Id: Ia96192a6be2911779e359b72132bdba60b60a13d
This commit is contained in:
Vincent Rabaud 2020-12-02 11:20:35 +01:00
parent 7656f0b335
commit fc14fc038b
4 changed files with 70 additions and 189 deletions

View File

@ -107,62 +107,62 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Predictors // Predictors
static uint32_t Predictor0_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top) {
(void)top; (void)top;
(void)left; (void)left;
return ARGB_BLACK; return ARGB_BLACK;
} }
static uint32_t Predictor1_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top) {
(void)top; (void)top;
return left; return left;
} }
static uint32_t Predictor2_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top) {
(void)left; (void)left;
return top[0]; return top[0];
} }
static uint32_t Predictor3_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top) {
(void)left; (void)left;
return top[1]; return top[1];
} }
static uint32_t Predictor4_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top) {
(void)left; (void)left;
return top[-1]; return top[-1];
} }
static uint32_t Predictor5_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]); const uint32_t pred = Average3(left, top[0], top[1]);
return pred; return pred;
} }
static uint32_t Predictor6_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]); const uint32_t pred = Average2(left, top[-1]);
return pred; return pred;
} }
static uint32_t Predictor7_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]); const uint32_t pred = Average2(left, top[0]);
return pred; return pred;
} }
static uint32_t Predictor8_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]); const uint32_t pred = Average2(top[-1], top[0]);
(void)left; (void)left;
return pred; return pred;
} }
static uint32_t Predictor9_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]); const uint32_t pred = Average2(top[0], top[1]);
(void)left; (void)left;
return pred; return pred;
} }
static uint32_t Predictor10_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]); const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
return pred; return pred;
} }
static uint32_t Predictor11_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]); const uint32_t pred = Select(top[0], left, top[-1]);
return pred; return pred;
} }
static uint32_t Predictor12_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
return pred; return pred;
} }
static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) { uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred; return pred;
} }
@ -182,18 +182,18 @@ static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
out[i] = left = VP8LAddPixels(in[i], left); out[i] = left = VP8LAddPixels(in[i], left);
} }
} }
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C) GENERATE_PREDICTOR_ADD(VP8LPredictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C) GENERATE_PREDICTOR_ADD(VP8LPredictor3_C, PredictorAdd3_C)
GENERATE_PREDICTOR_ADD(Predictor4_C, PredictorAdd4_C) GENERATE_PREDICTOR_ADD(VP8LPredictor4_C, PredictorAdd4_C)
GENERATE_PREDICTOR_ADD(Predictor5_C, PredictorAdd5_C) GENERATE_PREDICTOR_ADD(VP8LPredictor5_C, PredictorAdd5_C)
GENERATE_PREDICTOR_ADD(Predictor6_C, PredictorAdd6_C) GENERATE_PREDICTOR_ADD(VP8LPredictor6_C, PredictorAdd6_C)
GENERATE_PREDICTOR_ADD(Predictor7_C, PredictorAdd7_C) GENERATE_PREDICTOR_ADD(VP8LPredictor7_C, PredictorAdd7_C)
GENERATE_PREDICTOR_ADD(Predictor8_C, PredictorAdd8_C) GENERATE_PREDICTOR_ADD(VP8LPredictor8_C, PredictorAdd8_C)
GENERATE_PREDICTOR_ADD(Predictor9_C, PredictorAdd9_C) GENERATE_PREDICTOR_ADD(VP8LPredictor9_C, PredictorAdd9_C)
GENERATE_PREDICTOR_ADD(Predictor10_C, PredictorAdd10_C) GENERATE_PREDICTOR_ADD(VP8LPredictor10_C, PredictorAdd10_C)
GENERATE_PREDICTOR_ADD(Predictor11_C, PredictorAdd11_C) GENERATE_PREDICTOR_ADD(VP8LPredictor11_C, PredictorAdd11_C)
GENERATE_PREDICTOR_ADD(Predictor12_C, PredictorAdd12_C) GENERATE_PREDICTOR_ADD(VP8LPredictor12_C, PredictorAdd12_C)
GENERATE_PREDICTOR_ADD(Predictor13_C, PredictorAdd13_C) GENERATE_PREDICTOR_ADD(VP8LPredictor13_C, PredictorAdd13_C)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -562,7 +562,6 @@ VP8LPredictorFunc VP8LPredictors[16];
// exposed plain-C implementations // exposed plain-C implementations
VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16]; VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16];
VP8LPredictorFunc VP8LPredictors_C[16];
VP8LTransformColorInverseFunc VP8LTransformColorInverse; VP8LTransformColorInverseFunc VP8LTransformColorInverse;
@ -600,8 +599,7 @@ extern void VP8LDspInitMSA(void);
} while (0); } while (0);
WEBP_DSP_INIT_FUNC(VP8LDspInit) { WEBP_DSP_INIT_FUNC(VP8LDspInit) {
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors) COPY_PREDICTOR_ARRAY(VP8LPredictor, VP8LPredictors)
COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd)
COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C) COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C)

View File

@ -30,7 +30,22 @@ extern "C" {
typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top); typedef uint32_t (*VP8LPredictorFunc)(uint32_t left, const uint32_t* const top);
extern VP8LPredictorFunc VP8LPredictors[16]; extern VP8LPredictorFunc VP8LPredictors[16];
extern VP8LPredictorFunc VP8LPredictors_C[16];
uint32_t VP8LPredictor0_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor1_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor2_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor3_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor4_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor5_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor6_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor7_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor8_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor9_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor10_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor11_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor12_C(uint32_t left, const uint32_t* const top);
uint32_t VP8LPredictor13_C(uint32_t left, const uint32_t* const top);
// These Add/Sub function expects upper[-1] and out[-1] to be readable. // These Add/Sub function expects upper[-1] and out[-1] to be readable.
typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in, typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in,
const uint32_t* upper, int num_pixels, const uint32_t* upper, int num_pixels,

View File

@ -184,19 +184,6 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
} \ } \
} }
// It subtracts the prediction from the input pixel and stores the residual
// in the output pixel.
#define GENERATE_PREDICTOR_SUB(PREDICTOR, PREDICTOR_SUB) \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \
int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \
} \
}
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -702,140 +702,6 @@ void VP8LHistogramAdd(const VP8LHistogram* const a,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Image transforms. // Image transforms.
static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
}
static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
return Average2(Average2(a0, a2), a1);
}
static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3) {
return Average2(Average2(a0, a1), Average2(a2, a3));
}
static WEBP_INLINE uint32_t Clip255(uint32_t a) {
if (a < 256) {
return a;
}
// return 0, when a is a negative integer.
// return 255, when a is positive.
return ~a >> 24;
}
static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
return Clip255(a + b - c);
}
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
uint32_t c2) {
const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
(c1 >> 16) & 0xff,
(c2 >> 16) & 0xff);
const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
(c1 >> 8) & 0xff,
(c2 >> 8) & 0xff);
const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
return Clip255(a + (a - b) / 2);
}
static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
uint32_t c2) {
const uint32_t ave = Average2(c0, c1);
const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
}
// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
#if defined(__arm__) && \
(LOCAL_GCC_VERSION == 0x409 || LOCAL_GCC_VERSION == 0x408)
# define LOCAL_INLINE __attribute__ ((noinline))
#else
# define LOCAL_INLINE WEBP_INLINE
#endif
static LOCAL_INLINE int Sub3(int a, int b, int c) {
const int pb = b - c;
const int pa = a - c;
return abs(pb) - abs(pa);
}
#undef LOCAL_INLINE
static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
const int pa_minus_pb =
Sub3((a >> 24) , (b >> 24) , (c >> 24) ) +
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) +
Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff);
return (pa_minus_pb <= 0) ? a : b;
}
//------------------------------------------------------------------------------
// Predictors
static uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
(void)left;
return top[0];
}
static uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
(void)left;
return top[1];
}
static uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
(void)left;
return top[-1];
}
static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average3(left, top[0], top[1]);
return pred;
}
static uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[-1]);
return pred;
}
static uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(left, top[0]);
return pred;
}
static uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[-1], top[0]);
(void)left;
return pred;
}
static uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average2(top[0], top[1]);
(void)left;
return pred;
}
static uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
return pred;
}
static uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
const uint32_t pred = Select(top[0], left, top[-1]);
return pred;
}
static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
return pred;
}
static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred;
}
//------------------------------------------------------------------------------
static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper, static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
@ -850,18 +716,33 @@ static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper,
(void)upper; (void)upper;
} }
GENERATE_PREDICTOR_SUB(Predictor2, PredictorSub2_C) // It subtracts the prediction from the input pixel and stores the residual
GENERATE_PREDICTOR_SUB(Predictor3, PredictorSub3_C) // in the output pixel.
GENERATE_PREDICTOR_SUB(Predictor4, PredictorSub4_C) #define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \
GENERATE_PREDICTOR_SUB(Predictor5, PredictorSub5_C) static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \
GENERATE_PREDICTOR_SUB(Predictor6, PredictorSub6_C) const uint32_t* upper, \
GENERATE_PREDICTOR_SUB(Predictor7, PredictorSub7_C) int num_pixels, uint32_t* out) { \
GENERATE_PREDICTOR_SUB(Predictor8, PredictorSub8_C) int x; \
GENERATE_PREDICTOR_SUB(Predictor9, PredictorSub9_C) assert(upper != NULL); \
GENERATE_PREDICTOR_SUB(Predictor10, PredictorSub10_C) for (x = 0; x < num_pixels; ++x) { \
GENERATE_PREDICTOR_SUB(Predictor11, PredictorSub11_C) const uint32_t pred = \
GENERATE_PREDICTOR_SUB(Predictor12, PredictorSub12_C) VP8LPredictor##PREDICTOR_I##_C(in[x - 1], upper + x); \
GENERATE_PREDICTOR_SUB(Predictor13, PredictorSub13_C) out[x] = VP8LSubPixels(in[x], pred); \
} \
}
GENERATE_PREDICTOR_SUB(2)
GENERATE_PREDICTOR_SUB(3)
GENERATE_PREDICTOR_SUB(4)
GENERATE_PREDICTOR_SUB(5)
GENERATE_PREDICTOR_SUB(6)
GENERATE_PREDICTOR_SUB(7)
GENERATE_PREDICTOR_SUB(8)
GENERATE_PREDICTOR_SUB(9)
GENERATE_PREDICTOR_SUB(10)
GENERATE_PREDICTOR_SUB(11)
GENERATE_PREDICTOR_SUB(12)
GENERATE_PREDICTOR_SUB(13)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------