From patchwork Sat Dec 15 16:32:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lauri Kasanen X-Patchwork-Id: 11429 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 461FC44CBA7 for ; Sat, 15 Dec 2018 18:30:13 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6E25868AB15; Sat, 15 Dec 2018 18:30:13 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout.gmx.net (mout.gmx.net [212.227.15.18]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1180768AA9D for ; Sat, 15 Dec 2018 18:30:07 +0200 (EET) Received: from Valinor ([84.250.81.169]) by mail.gmx.com (mrgmx003 [212.227.17.184]) with ESMTPSA (Nemesis) id 0LyEqr-1hSDL000CD-015akQ for ; Sat, 15 Dec 2018 17:30:07 +0100 Date: Sat, 15 Dec 2018 18:32:31 +0200 From: Lauri Kasanen To: ffmpeg-devel@ffmpeg.org Message-Id: <20181215183231.bad5528b207e6cf74ea8c43c@gmx.com> X-Mailer: Sylpheed 3.5.0 (GTK+ 2.18.6; x86_64-unknown-linux-gnu) Mime-Version: 1.0 X-Provags-ID: V03:K1:RdCEnKKlGQ9OMK9flQQ3t4sBAjNsF9M5s/kQRJXM97R5Bp4DxCw AyB5ZG1qewgz7wLCUbw77idb3O2pS3DXbt4nliRJJGHIabcmbsecBjtpsZkaeAGH4Gs67Pc QTkuDA7AWysYrR4a5RhdQXWbFfthQU39PmzjVt7tCIld+VvPoL90awnGUfHeKoS1NtJ40Km WovMHvtly+3sPMiJEw8kg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1; V03:K0:5AZ/1sQXhaU=:9+ZyRvrRHRdLaMd+dQAx3J MBSRgaP+rSYHx7igNzNjf1o8Xb1AaVtPLXkx8SY9INmu99p4Chx3cVLqtAoKbI0zCj2HNUQur 9WOr4kswh4rQhjr/sHebmwQzQBVXOxjeN8OxcijX5fCZnUsA57A5Ba3/w+07pmagtryj21l6G ynKqcBfeoRK7jbd/F4oCCBKMbagAmtQhIILivMrOqVUBgBk6bJJbE/1a6uKBJ4oVpxDLhXu++ yCuqCugdoqAbcHTOEn2hBtgw6WrUZoHlbqzjPQNbocrk4YWbsL/3gaZEmva3cEBz57ZjIOXkT jrJnMlRfWcL8WwK0GL6xl9I0sZakMG2YChTcDmM1/vZlpUDDYN3DtK2HVzmNVT0EKMRhqikPS q8VxCm+sDzgN/ZVJRlkvfv1S5VfBAYRbWB4U0mmkTiPiSDEJC811ig8WfD/oVfUwo3Nlaf/9D aetLWgwaAv/9moy2HkE9Q7u9tAwU7JuUNeqUOW6UiHOWjAIAsVsTsgXOm3sIHKIp+kAwB5DNY h+yX8uLDoPcyO2eVzU5OidyEKTNqzDv6IdAABpBPQaRMRTUYZbovZDUbC4Xt1H+ZqWRQ8Kmhz SppcNmrFVh9skDU+E6l5e6sWMyNBicjkW/n3YxdBn3jp5JXeWyPNgUGagjAB9vVR7zhND/s+X j6zETt/0vIrIz1gbtAX4j0WIq1KULvdHTXdUOOpCznkG9KzQOw1gD79vX1pl4reiWZM3sPAXA 8HKyQzCz1f9YTtAvdUPVrggAzz9ZaeD26BIkzLD7XFBa4co+fiE5LYJPTrp6IN4kZ5WiqwSmQ sdORhhNuWWSyTh4VgWmcif+cR0qdOZ5/p2UOIyHNj9AmKAVbLj5tli/AdBAXaOyVjAFiq+Frx syu/xTzqekA9uuHjuFtPyHhcbplY9k6IzRGicTIHBeq1/rKvOmIasObDfzEXHw Subject: [FFmpeg-devel] [PATCH] swscale/output: Altivec-optimize float yuv2plane1 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This function wouldn't benefit from VSX instructions, and input and output share alignment, so I put it under altivec. ./ffmpeg_g -f rawvideo -pix_fmt rgb24 -s hd1080 -i /dev/zero -pix_fmt grayf32le \ -f null -vframes 100 -v error -nostats - 3743 UNITS in planar1, 65495 runs, 41 skips -cpuflags 0 23511 UNITS in planar1, 65530 runs, 6 skips grayf32be 4647 UNITS in planar1, 65449 runs, 87 skips -cpuflags 0 28608 UNITS in planar1, 65530 runs, 6 skips The native speedup is 6.28133, and the bswapping one 6.15623. Fate passes, each format tested with an image to video conversion. Signed-off-by: Lauri Kasanen --- Tested on POWER8 LE. Testing on earlier ppc and/or BE appreciated. libswscale/ppc/swscale_altivec.c | 139 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 2 deletions(-) diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 1d2b2fa..2ef5257 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -31,7 +31,8 @@ #include "yuv2rgb_altivec.h" #include "libavutil/ppc/util_altivec.h" -#if HAVE_ALTIVEC && HAVE_BIGENDIAN +#if HAVE_ALTIVEC +#if HAVE_BIGENDIAN #define vzero vec_splat_s32(0) #define GET_LS(a,b,c,s) {\ @@ -102,7 +103,135 @@ #include "swscale_ppc_template.c" #undef FUNC -#endif /* HAVE_ALTIVEC && HAVE_BIGENDIAN */ +#endif /* HAVE_BIGENDIAN */ + +#define output_pixel(pos, val, bias, signedness) \ + if (big_endian) { \ + AV_WB16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \ + } else { \ + AV_WL16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \ + } + +static void +yuv2plane1_float_u(const int32_t *src, float *dest, int dstW, int start) +{ + static const int big_endian = HAVE_BIGENDIAN; + static const int shift = 3; + static const float float_mult = 1.0f / 65535.0f; + int i, val; + uint16_t val_uint; + + for (i = start; i < dstW; ++i){ + val = src[i] + (1 << (shift - 1)); + output_pixel(&val_uint, val, 0, uint); + dest[i] = float_mult * (float)val_uint; + } +} + +static void +yuv2plane1_float_bswap_u(const int32_t *src, uint32_t *dest, int dstW, int start) +{ + static const int big_endian = HAVE_BIGENDIAN; + static const int shift = 3; + static const float float_mult = 1.0f / 65535.0f; + int i, val; + uint16_t val_uint; + + for (i = start; i < dstW; ++i){ + val = src[i] + (1 << (shift - 1)); + output_pixel(&val_uint, val, 0, uint); + dest[i] = av_bswap32(av_float2int(float_mult * (float)val_uint)); + } +} + +static void yuv2plane1_float_altivec(const int32_t *src, float *dest, int dstW) +{ + const int dst_u = -(uintptr_t)dest & 3; + const int shift = 3; + const int add = (1 << (shift - 1)); + const int clip = (1 << 16) - 1; + const float fmult = 1.0f / 65535.0f; + const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; + const vector uint32_t vshift = (vector uint32_t) vec_splat_u32(shift); + const vector uint32_t vlargest = (vector uint32_t) {clip, clip, clip, clip}; + const vector float vmul = (vector float) {fmult, fmult, fmult, fmult}; + const vector float vzero = (vector float) {0, 0, 0, 0}; + vector uint32_t v; + vector float vd; + int i; + + yuv2plane1_float_u(src, dest, dst_u, 0); + + for (i = dst_u; i < dstW - 3; i += 4) { + v = vec_ld(0, (const uint32_t *) &src[i]); + v = vec_add(v, vadd); + v = vec_sr(v, vshift); + v = vec_min(v, vlargest); + + vd = vec_ctf(v, 0); + vd = vec_madd(vd, vmul, vzero); + + vec_st(vd, 0, &dest[i]); + } + + yuv2plane1_float_u(src, dest, dstW, i); +} + +static void yuv2plane1_float_bswap_altivec(const int32_t *src, uint32_t *dest, int dstW) +{ + const int dst_u = -(uintptr_t)dest & 3; + const int shift = 3; + const int add = (1 << (shift - 1)); + const int clip = (1 << 16) - 1; + const float fmult = 1.0f / 65535.0f; + const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; + const vector uint32_t vshift = (vector uint32_t) vec_splat_u32(shift); + const vector uint32_t vlargest = (vector uint32_t) {clip, clip, clip, clip}; + const vector float vmul = (vector float) {fmult, fmult, fmult, fmult}; + const vector float vzero = (vector float) {0, 0, 0, 0}; + const vector uint32_t vswapbig = (vector uint32_t) {16, 16, 16, 16}; + const vector uint16_t vswapsmall = vec_splat_u16(8); + vector uint32_t v; + vector float vd; + int i; + + yuv2plane1_float_bswap_u(src, dest, dst_u, 0); + + for (i = dst_u; i < dstW - 3; i += 4) { + v = vec_ld(0, (const uint32_t *) &src[i]); + v = vec_add(v, vadd); + v = vec_sr(v, vshift); + v = vec_min(v, vlargest); + + vd = vec_ctf(v, 0); + vd = vec_madd(vd, vmul, vzero); + + vd = (vector float) vec_rl((vector uint32_t) vd, vswapbig); + vd = (vector float) vec_rl((vector uint16_t) vd, vswapsmall); + + vec_st(vd, 0, (float *) &dest[i]); + } + + yuv2plane1_float_bswap_u(src, dest, dstW, i); +} + +#define yuv2plane1_float(template, dest_type, BE_LE) \ +static void yuv2plane1_float ## BE_LE ## _altivec(const int16_t *src, uint8_t *dest, \ + int dstW, \ + const uint8_t *dither, int offset) \ +{ \ + template((const int32_t *)src, (dest_type *)dest, dstW); \ +} + +#if HAVE_BIGENDIAN +yuv2plane1_float(yuv2plane1_float_altivec, float, BE) +yuv2plane1_float(yuv2plane1_float_bswap_altivec, uint32_t, LE) +#else +yuv2plane1_float(yuv2plane1_float_altivec, float, LE) +yuv2plane1_float(yuv2plane1_float_bswap_altivec, uint32_t, BE) +#endif + +#endif /* HAVE_ALTIVEC */ av_cold void ff_sws_init_swscale_ppc(SwsContext *c) { @@ -124,6 +253,12 @@ av_cold void ff_sws_init_swscale_ppc(SwsContext *c) } #endif + if (dstFormat == AV_PIX_FMT_GRAYF32BE) { + c->yuv2plane1 = yuv2plane1_floatBE_altivec; + } else if (dstFormat == AV_PIX_FMT_GRAYF32LE) { + c->yuv2plane1 = yuv2plane1_floatLE_altivec; + } + /* The following list of supported dstFormat values should * match what's found in the body of ff_yuv2packedX_altivec() */ if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {