simplify upsampler calls: only allow 'bottom' to be NULL

If 'top' was meant to be NULL, then bottom and top can be
swapped. Logic is simpler.

+ fix compilation in non-FANCY_UPSAMPLING mode

Change-Id: I7c62bbb59454017f072c0945d1ff2d24d89286ff
This commit is contained in:
skal 2013-08-19 12:40:25 -07:00
parent 43a7c8ebee
commit ad6ac32d7c
6 changed files with 48 additions and 29 deletions

View File

@ -119,7 +119,7 @@ static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) {
if (y == 0) { if (y == 0) {
// First line is special cased. We mirror the u/v samples at boundary. // First line is special cased. We mirror the u/v samples at boundary.
upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w); upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w);
} else { } else {
// We can finish the left-over line from previous call. // We can finish the left-over line from previous call.
upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,

View File

@ -146,6 +146,8 @@ void VP8DspInit(void);
#define FANCY_UPSAMPLING // undefined to remove fancy upsampling support #define FANCY_UPSAMPLING // undefined to remove fancy upsampling support
// Convert a pair of y/u/v lines together to the output rgb/a colorspace.
// bottom_y can be NULL if only one line of output is needed (at top/bottom).
typedef void (*WebPUpsampleLinePairFunc)( typedef void (*WebPUpsampleLinePairFunc)(
const uint8_t* top_y, const uint8_t* bottom_y, const uint8_t* top_y, const uint8_t* bottom_y,
const uint8_t* top_u, const uint8_t* top_v, const uint8_t* top_u, const uint8_t* top_v,

View File

@ -18,6 +18,8 @@
extern "C" { extern "C" {
#endif #endif
#include <assert.h>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Fancy upsampler // Fancy upsampler
@ -45,11 +47,12 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const int last_pixel_pair = (len - 1) >> 1; \ const int last_pixel_pair = (len - 1) >> 1; \
uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \
uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \
if (top_y) { \ assert(top_y != NULL); \
{ \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \
} \ } \
@ -60,7 +63,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \
const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \
const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \
if (top_y) { \ { \
const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \
const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ const uint32_t uv1 = (diag_03 + t_uv) >> 1; \
FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
@ -68,7 +71,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \
top_dst + (2 * x - 0) * XSTEP); \ top_dst + (2 * x - 0) * XSTEP); \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ const uint32_t uv0 = (diag_03 + l_uv) >> 1; \
const uint32_t uv1 = (diag_12 + uv) >> 1; \ const uint32_t uv1 = (diag_12 + uv) >> 1; \
FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \
@ -80,12 +83,12 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
l_uv = uv; \ l_uv = uv; \
} \ } \
if (!(len & 1)) { \ if (!(len & 1)) { \
if (top_y) { \ { \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
top_dst + (len - 1) * XSTEP); \ top_dst + (len - 1) * XSTEP); \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \
bottom_dst + (len - 1) * XSTEP); \ bottom_dst + (len - 1) * XSTEP); \
@ -168,7 +171,8 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
uint8_t* top_dst, uint8_t* bot_dst, int len) { \ uint8_t* top_dst, uint8_t* bot_dst, int len) { \
const int half_len = len >> 1; \ const int half_len = len >> 1; \
int x; \ int x; \
if (top_dst != NULL) { \ assert(top_dst != NULL); \
{ \
for (x = 0; x < half_len; ++x) { \ for (x = 0; x < half_len; ++x) { \
FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \
FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \

View File

@ -189,20 +189,16 @@ static const int16_t coef[4] = { CVR / 4, CUG, CVG / 2, CUB / 4 };
#define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \ #define CONVERT2RGB_8(FMT, XSTEP, top_y, bottom_y, uv, \
top_dst, bottom_dst, cur_x, len) { \ top_dst, bottom_dst, cur_x, len) { \
if (top_y) { \ CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x) \
CONVERT8(FMT, XSTEP, len, top_y, uv, top_dst, cur_x) \ if (bottom_y != NULL) { \
} \
if (bottom_y) { \
CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x) \ CONVERT8(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x) \
} \ } \
} }
#define CONVERT2RGB_1(FMT, XSTEP, top_y, bottom_y, uv, \ #define CONVERT2RGB_1(FMT, XSTEP, top_y, bottom_y, uv, \
top_dst, bottom_dst, cur_x, len) { \ top_dst, bottom_dst, cur_x, len) { \
if (top_y) { \ CONVERT1(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \
CONVERT1(FMT, XSTEP, len, top_y, uv, top_dst, cur_x); \ if (bottom_y != NULL) { \
} \
if (bottom_y) { \
CONVERT1(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \ CONVERT1(FMT, XSTEP, len, bottom_y, (uv) + 32, bottom_dst, cur_x); \
} \ } \
} }
@ -231,12 +227,13 @@ static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \
const uint8x8_t u128 = vmov_n_u8(128); \ const uint8x8_t u128 = vmov_n_u8(128); \
\ \
/* Treat the first pixel in regular way */ \ /* Treat the first pixel in regular way */ \
if (top_y) { \ assert(top_y != NULL); \
{ \
const int u0 = (top_u[0] + u_diag) >> 1; \ const int u0 = (top_u[0] + u_diag) >> 1; \
const int v0 = (top_v[0] + v_diag) >> 1; \ const int v0 = (top_v[0] + v_diag) >> 1; \
VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \ VP8YuvTo ## FMT(top_y[0], u0, v0, top_dst); \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
const int u0 = (cur_u[0] + u_diag) >> 1; \ const int u0 = (cur_u[0] + u_diag) >> 1; \
const int v0 = (cur_v[0] + v_diag) >> 1; \ const int v0 = (cur_v[0] + v_diag) >> 1; \
VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \ VP8YuvTo ## FMT(bottom_y[0], u0, v0, bottom_dst); \
@ -271,6 +268,8 @@ NEON_UPSAMPLE_FUNC(UpsampleBgraLinePairNEON, Bgra, 4)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef FANCY_UPSAMPLING
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
void WebPInitUpsamplersNEON(void) { void WebPInitUpsamplersNEON(void) {
@ -289,6 +288,14 @@ void WebPInitPremultiplyNEON(void) {
#endif // WEBP_USE_NEON #endif // WEBP_USE_NEON
} }
#else
// this empty function is to avoid an empty .o
void WebPInitPremultiplyNEON(void) {}
#endif // FANCY_UPSAMPLING
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
} // extern "C" } // extern "C"
#endif #endif

View File

@ -111,13 +111,11 @@ static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[],
#define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, uv, \ #define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, uv, \
top_dst, bottom_dst, cur_x, num_pixels) { \ top_dst, bottom_dst, cur_x, num_pixels) { \
int n; \ int n; \
if (top_y) { \ for (n = 0; n < (num_pixels); ++n) { \
for (n = 0; n < (num_pixels); ++n) { \ FUNC(top_y[(cur_x) + n], (uv)[n], (uv)[32 + n], \
FUNC(top_y[(cur_x) + n], (uv)[n], (uv)[32 + n], \ top_dst + ((cur_x) + n) * XSTEP); \
top_dst + ((cur_x) + n) * XSTEP); \
} \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
for (n = 0; n < (num_pixels); ++n) { \ for (n = 0; n < (num_pixels); ++n) { \
FUNC(bottom_y[(cur_x) + n], (uv)[64 + n], (uv)[64 + 32 + n], \ FUNC(bottom_y[(cur_x) + n], (uv)[64 + n], (uv)[64 + 32 + n], \
bottom_dst + ((cur_x) + n) * XSTEP); \ bottom_dst + ((cur_x) + n) * XSTEP); \
@ -145,12 +143,13 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
\ \
assert(len > 0); \ assert(len > 0); \
/* Treat the first pixel in regular way */ \ /* Treat the first pixel in regular way */ \
if (top_y) { \ assert(top_y != NULL); \
{ \
const int u0 = (top_u[0] + u_diag) >> 1; \ const int u0 = (top_u[0] + u_diag) >> 1; \
const int v0 = (top_v[0] + v_diag) >> 1; \ const int v0 = (top_v[0] + v_diag) >> 1; \
FUNC(top_y[0], u0, v0, top_dst); \ FUNC(top_y[0], u0, v0, top_dst); \
} \ } \
if (bottom_y) { \ if (bottom_y != NULL) { \
const int u0 = (cur_u[0] + u_diag) >> 1; \ const int u0 = (cur_u[0] + u_diag) >> 1; \
const int v0 = (cur_v[0] + v_diag) >> 1; \ const int v0 = (cur_v[0] + v_diag) >> 1; \
FUNC(bottom_y[0], u0, v0, bottom_dst); \ FUNC(bottom_y[0], u0, v0, bottom_dst); \
@ -192,6 +191,8 @@ SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePairSSE2, VP8YuvToBgra, 4)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef FANCY_UPSAMPLING
extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
void WebPInitUpsamplersSSE2(void) { void WebPInitUpsamplersSSE2(void) {
@ -210,8 +211,13 @@ void WebPInitPremultiplySSE2(void) {
#endif // WEBP_USE_SSE2 #endif // WEBP_USE_SSE2
} }
#else
// this empty function is to avoid an empty .o
void WebPInitPremultiplySSE2(void);
#endif // FANCY_UPSAMPLING
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
} // extern "C" } // extern "C"
#endif #endif

View File

@ -820,7 +820,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST); WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST);
// First row, with replicated top samples. // First row, with replicated top samples.
upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, width); upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
cur_y += picture->y_stride; cur_y += picture->y_stride;
dst += argb_stride; dst += argb_stride;
// Center rows. // Center rows.