[FFmpeg-devel] [PATCH v2 2/4] swscale/x86: add sse4 {lum, chr}ConvertRange
Ramiro Polla
ramiro.polla at gmail.com
Tue Jun 11 15:28:56 EEST 2024
chrRangeFromJpeg_8_c: 28.7
chrRangeFromJpeg_8_sse4: 16.2
chrRangeFromJpeg_24_c: 152.7
chrRangeFromJpeg_24_sse4: 29.7
chrRangeFromJpeg_128_c: 366.5
chrRangeFromJpeg_128_sse4: 233.0
chrRangeFromJpeg_144_c: 408.0
chrRangeFromJpeg_144_sse4: 182.5
chrRangeFromJpeg_256_c: 698.7
chrRangeFromJpeg_256_sse4: 325.5
chrRangeFromJpeg_512_c: 1348.7
chrRangeFromJpeg_512_sse4: 660.2
chrRangeToJpeg_8_c: 37.7
chrRangeToJpeg_8_sse4: 16.2
chrRangeToJpeg_24_c: 115.7
chrRangeToJpeg_24_sse4: 36.2
chrRangeToJpeg_128_c: 631.2
chrRangeToJpeg_128_sse4: 163.7
chrRangeToJpeg_144_c: 710.7
chrRangeToJpeg_144_sse4: 183.0
chrRangeToJpeg_256_c: 1253.0
chrRangeToJpeg_256_sse4: 343.5
chrRangeToJpeg_512_c: 2491.2
chrRangeToJpeg_512_sse4: 654.2
lumRangeFromJpeg_8_c: 11.7
lumRangeFromJpeg_8_sse4: 10.5
lumRangeFromJpeg_24_c: 38.5
lumRangeFromJpeg_24_sse4: 19.0
lumRangeFromJpeg_128_c: 237.5
lumRangeFromJpeg_128_sse4: 79.2
lumRangeFromJpeg_144_c: 255.7
lumRangeFromJpeg_144_sse4: 90.5
lumRangeFromJpeg_256_c: 441.5
lumRangeFromJpeg_256_sse4: 161.7
lumRangeFromJpeg_512_c: 879.0
lumRangeFromJpeg_512_sse4: 333.2
lumRangeToJpeg_8_c: 20.0
lumRangeToJpeg_8_sse4: 11.7
lumRangeToJpeg_24_c: 61.5
lumRangeToJpeg_24_sse4: 17.7
lumRangeToJpeg_128_c: 357.5
lumRangeToJpeg_128_sse4: 80.0
lumRangeToJpeg_144_c: 371.5
lumRangeToJpeg_144_sse4: 93.2
lumRangeToJpeg_256_c: 651.5
lumRangeToJpeg_256_sse4: 164.5
lumRangeToJpeg_512_c: 1279.0
lumRangeToJpeg_512_sse4: 333.7
---
libswscale/swscale_internal.h | 1 +
libswscale/utils.c | 2 +
libswscale/x86/Makefile | 1 +
libswscale/x86/range_convert.asm | 130 +++++++++++++++++++++++++++++++
libswscale/x86/swscale.c | 36 +++++++++
5 files changed, 170 insertions(+)
create mode 100644 libswscale/x86/range_convert.asm
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 5007dd422f..d5e7b5e71c 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -698,6 +698,7 @@ void ff_updateMMXDitherTables(SwsContext *c, int dstY);
av_cold void ff_sws_init_range_convert(SwsContext *c);
av_cold void ff_sws_init_range_convert_loongarch(SwsContext *c);
+av_cold void ff_sws_init_range_convert_x86(SwsContext *c);
SwsFunc ff_yuv2rgb_init_x86(SwsContext *c);
SwsFunc ff_yuv2rgb_init_ppc(SwsContext *c);
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 476a24fea5..8dfa57b5ff 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -1082,6 +1082,8 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
ff_sws_init_range_convert(c);
#if ARCH_LOONGARCH64
ff_sws_init_range_convert_loongarch(c);
+#elif ARCH_X86
+ ff_sws_init_range_convert_x86(c);
#endif
}
diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile
index 68391494be..f00154941d 100644
--- a/libswscale/x86/Makefile
+++ b/libswscale/x86/Makefile
@@ -12,6 +12,7 @@ X86ASM-OBJS += x86/input.o \
x86/output.o \
x86/scale.o \
x86/scale_avx2.o \
+ x86/range_convert.o \
x86/rgb_2_rgb.o \
x86/yuv_2_rgb.o \
x86/yuv2yuvX.o \
diff --git a/libswscale/x86/range_convert.asm b/libswscale/x86/range_convert.asm
new file mode 100644
index 0000000000..13983a386b
--- /dev/null
+++ b/libswscale/x86/range_convert.asm
@@ -0,0 +1,130 @@
+;******************************************************************************
+;* Copyright (c) 2024 Ramiro Polla
+;*
+;* 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/x86/x86util.asm"
+
+SECTION_RODATA
+
+chr_to_mult: times 4 dd 4663
+chr_to_offset: times 4 dd -9289992
+%define chr_to_shift 12
+
+chr_from_mult: times 4 dd 1799
+chr_from_offset: times 4 dd 4081085
+%define chr_from_shift 11
+
+lum_to_mult: times 4 dd 19077
+lum_to_offset: times 4 dd -39057361
+%define lum_to_shift 14
+
+lum_from_mult: times 4 dd 14071
+lum_from_offset: times 4 dd 33561947
+%define lum_from_shift 14
+
+SECTION .text
+
+; NOTE: there is no need to clamp the input when converting to jpeg range
+; (like we do in the C code) because packssdw will saturate the output.
+
+;-----------------------------------------------------------------------------
+; lumConvertRange
+;
+; void ff_lumRangeToJpeg_<opt>(int16_t *dst, int width);
+; void ff_lumRangeFromJpeg_<opt>(int16_t *dst, int width);
+;
+;-----------------------------------------------------------------------------
+
+%macro LUMCONVERTRANGE 4
+cglobal %1, 2, 3, 3, dst, width, x
+ movsxdifnidn widthq, widthd
+ xor xq, xq
+ mova m4, [%2]
+ mova m5, [%3]
+.loop:
+ pmovsxwd m0, [dstq+xq*2]
+ pmovsxwd m1, [dstq+xq*2+mmsize/2]
+ pmulld m0, m4
+ pmulld m1, m4
+ paddd m0, m5
+ paddd m1, m5
+ psrad m0, %4
+ psrad m1, %4
+ packssdw m0, m0
+ packssdw m1, m1
+ movq [dstq+xq*2], m0
+ movq [dstq+xq*2+mmsize/2], m1
+ add xq, mmsize / 2
+ cmp xd, widthd
+ jl .loop
+ RET
+%endmacro
+
+;-----------------------------------------------------------------------------
+; chrConvertRange
+;
+; void ff_chrRangeToJpeg_<opt>(int16_t *dstU, int16_t *dstV, int width);
+; void ff_chrRangeFromJpeg_<opt>(int16_t *dstU, int16_t *dstV, int width);
+;
+;-----------------------------------------------------------------------------
+
+%macro CHRCONVERTRANGE 4
+cglobal %1, 3, 4, 4, dstU, dstV, width, x
+ movsxdifnidn widthq, widthd
+ xor xq, xq
+ mova m4, [%2]
+ mova m5, [%3]
+.loop:
+ pmovsxwd m0, [dstUq+xq*2]
+ pmovsxwd m1, [dstUq+xq*2+mmsize/2]
+ pmovsxwd m2, [dstVq+xq*2]
+ pmovsxwd m3, [dstVq+xq*2+mmsize/2]
+ pmulld m0, m4
+ pmulld m1, m4
+ pmulld m2, m4
+ pmulld m3, m4
+ paddd m0, m5
+ paddd m1, m5
+ paddd m2, m5
+ paddd m3, m5
+ psrad m0, %4
+ psrad m1, %4
+ psrad m2, %4
+ psrad m3, %4
+ packssdw m0, m0
+ packssdw m1, m1
+ packssdw m2, m2
+ packssdw m3, m3
+ movq [dstUq+xq*2], m0
+ movq [dstUq+xq*2+mmsize/2], m1
+ movq [dstVq+xq*2], m2
+ movq [dstVq+xq*2+mmsize/2], m3
+ add xq, mmsize / 2
+ cmp xd, widthd
+ jl .loop
+ RET
+%endmacro
+
+%if ARCH_X86_64
+INIT_XMM sse4
+LUMCONVERTRANGE lumRangeToJpeg, lum_to_mult, lum_to_offset, lum_to_shift
+CHRCONVERTRANGE chrRangeToJpeg, chr_to_mult, chr_to_offset, chr_to_shift
+LUMCONVERTRANGE lumRangeFromJpeg, lum_from_mult, lum_from_offset, lum_from_shift
+CHRCONVERTRANGE chrRangeFromJpeg, chr_from_mult, chr_from_offset, chr_from_shift
+%endif
diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c
index 5a9da23265..8f477b7b72 100644
--- a/libswscale/x86/swscale.c
+++ b/libswscale/x86/swscale.c
@@ -453,6 +453,38 @@ INPUT_PLANAR_RGB_UV_ALL_DECL(avx2);
INPUT_PLANAR_RGB_A_ALL_DECL(avx2);
#endif
+#if ARCH_X86_64
+#define RANGE_CONVERT_FUNCS(opt) do { \
+ if (c->dstBpc <= 14) { \
+ if (c->srcRange) { \
+ c->lumConvertRange = ff_lumRangeFromJpeg_ ##opt; \
+ c->chrConvertRange = ff_chrRangeFromJpeg_ ##opt; \
+ } else { \
+ c->lumConvertRange = ff_lumRangeToJpeg_ ##opt; \
+ c->chrConvertRange = ff_chrRangeToJpeg_ ##opt; \
+ } \
+ } \
+} while (0)
+
+#define RANGE_CONVERT_FUNCS_DECL(opt) \
+void ff_lumRangeFromJpeg_ ##opt(int16_t *dst, int width); \
+void ff_chrRangeFromJpeg_ ##opt(int16_t *dstU, int16_t *dstV, int width); \
+void ff_lumRangeToJpeg_ ##opt(int16_t *dst, int width); \
+void ff_chrRangeToJpeg_ ##opt(int16_t *dstU, int16_t *dstV, int width); \
+
+RANGE_CONVERT_FUNCS_DECL(sse4);
+
+av_cold void ff_sws_init_range_convert_x86(SwsContext *c)
+{
+ if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
+ int cpu_flags = av_get_cpu_flags();
+ if (EXTERNAL_SSE4(cpu_flags)) {
+ RANGE_CONVERT_FUNCS(sse4);
+ }
+ }
+}
+#endif
+
av_cold void ff_sws_init_swscale_x86(SwsContext *c)
{
int cpu_flags = av_get_cpu_flags();
@@ -820,4 +852,8 @@ switch(c->dstBpc){ \
}
#endif
+
+#if ARCH_X86_64
+ ff_sws_init_range_convert_x86(c);
+#endif
}
--
2.30.2
More information about the ffmpeg-devel
mailing list