From 7abc8e7ae3aa9221dddafe2a08b07eb3744428fa Mon Sep 17 00:00:00 2001 From: Matthieu Bouron Date: Thu, 7 Apr 2016 14:52:00 +0000 Subject: swscale/arm: add ff_hscale_8_to_15_neon --- libswscale/arm/Makefile | 6 ++-- libswscale/arm/hscale.S | 70 +++++++++++++++++++++++++++++++++++++++++++ libswscale/arm/swscale.c | 37 +++++++++++++++++++++++ libswscale/swscale.c | 2 ++ libswscale/swscale_internal.h | 1 + 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 libswscale/arm/hscale.S create mode 100644 libswscale/arm/swscale.c diff --git a/libswscale/arm/Makefile b/libswscale/arm/Makefile index 9ccec3bbc0..b8b013465c 100644 --- a/libswscale/arm/Makefile +++ b/libswscale/arm/Makefile @@ -1,5 +1,7 @@ -OBJS += arm/swscale_unscaled.o +OBJS += arm/swscale.o \ + arm/swscale_unscaled.o \ NEON-OBJS += arm/rgb2yuv_neon_32.o NEON-OBJS += arm/rgb2yuv_neon_16.o -NEON-OBJS += arm/yuv2rgb_neon.o +NEON-OBJS += arm/hscale.o \ + arm/yuv2rgb_neon.o \ diff --git a/libswscale/arm/hscale.S b/libswscale/arm/hscale.S new file mode 100644 index 0000000000..dd4d453957 --- /dev/null +++ b/libswscale/arm/hscale.S @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Clément Bœsch + * Copyright (c) 2016 Matthieu Bouron + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_hscale_8_to_15_neon, export=1 + push {r4-r12, lr} + vpush {q4-q7} + ldr r4, [sp, #104] @ filter + ldr r5, [sp, #108] @ filterPos + ldr r6, [sp, #112] @ filterSize + add r10, r4, r6, lsl #1 @ filter2 = filter + filterSize * 2 +1: ldr r8, [r5], #4 @ filterPos[0] + ldr r9, [r5], #4 @ filterPos[1] + vmov.s32 q4, #0 @ val accumulator + vmov.s32 q5, #0 @ val accumulator + mov r7, r6 @ tmpfilterSize = filterSize + mov r0, r3 @ srcp +2: add r11, r0, r8 @ srcp + filterPos[0] + add r12, r0, r9 @ srcp + filterPos[1] + vld1.8 d0, [r11] @ srcp[filterPos[0] + {0..7}] + vld1.8 d2, [r12] @ srcp[filterPos[1] + {0..7}] + vld1.16 {q2}, [r4]! @ load 8x16-bit filter values + vld1.16 {q3}, [r10]! @ load 8x16-bit filter values + vmovl.u8 q0, d0 @ unpack src values to 16-bit + vmovl.u8 q1, d2 @ unpack src values to 16-bit + vmull.s16 q8, d0, d4 @ srcp[filterPos[0] + {0..7}] * filter[{0..7}] (part 1) + vmull.s16 q9, d1, d5 @ srcp[filterPos[0] + {0..7}] * filter[{0..7}] (part 2) + vmull.s16 q10, d2, d6 @ srcp[filterPos[1] + {0..7}] * filter[{0..7}] (part 1) + vmull.s16 q11, d3, d7 @ srcp[filterPos[1] + {0..7}] * filter[{0..7}] (part 2) + vpadd.s32 d16, d16, d17 @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 1) + vpadd.s32 d17, d18, d19 @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 2) + vpadd.s32 d20, d20, d21 @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 1) + vpadd.s32 d21, d22, d23 @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 2) + vadd.s32 q4, q8 @ update val accumulator + vadd.s32 q5, q10 @ update val accumulator + add r0, #8 @ srcp += 8 + subs r7, #8 @ tmpfilterSize -= 8 + bgt 2b @ loop until tmpfilterSize is consumed + mov r4, r10 @ filter = filter2 + add r10, r10, r6, lsl #1 @ filter2 += filterSize * 2 + vpadd.s32 d8, d8, d9 @ horizontal pair adding of the 8x32-bit sums into 4x32-bit (part 1) + vpadd.s32 d9, d10, d11 @ horizontal pair adding of the 8x32-bit sums into 4x32-bit (part 2) + vpadd.s32 d8, d8, d9 @ horizontal pair adding of the 4x32-bit sums into 2x32-bit + vqshrn.s32 d8, q4, #7 @ shift and clip the 2x16-bit final values + vst1.32 {d8[0]},[r1]! @ write destination + subs r2, #2 @ dstW -= 2 + bgt 1b @ loop until end of line + vpop {q4-q7} + pop {r4-r12, lr} + mov pc, lr +endfunc diff --git a/libswscale/arm/swscale.c b/libswscale/arm/swscale.c new file mode 100644 index 0000000000..6301ac5a62 --- /dev/null +++ b/libswscale/arm/swscale.c @@ -0,0 +1,37 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libswscale/swscale.h" +#include "libswscale/swscale_internal.h" +#include "libavutil/arm/cpu.h" + +void ff_hscale_8_to_15_neon(SwsContext *c, int16_t *dst, int dstW, + const uint8_t *src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + +av_cold void ff_sws_init_swscale_arm(SwsContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + if (c->srcBpc == 8 && c->dstBpc <= 14) { + c->hyScale = c->hcScale = ff_hscale_8_to_15_neon; + } + } +} diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 76b0317d0c..2e246d9997 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -597,6 +597,8 @@ SwsFunc ff_getSwsFunc(SwsContext *c) ff_sws_init_swscale_x86(c); if (ARCH_AARCH64) ff_sws_init_swscale_aarch64(c); + if (ARCH_ARM) + ff_sws_init_swscale_arm(c); return swscale; } diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 566c6d560b..3f72f9873a 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -892,6 +892,7 @@ void ff_sws_init_output_funcs(SwsContext *c, void ff_sws_init_swscale_ppc(SwsContext *c); void ff_sws_init_swscale_x86(SwsContext *c); void ff_sws_init_swscale_aarch64(SwsContext *c); +void ff_sws_init_swscale_arm(SwsContext *c); void ff_hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth, const uint8_t *src, int srcW, int xInc); -- cgit v1.2.3