[FFmpeg-devel] [PATCH] x86/hevc_idct: replace old and unused idct functions
James Almer
jamrial at gmail.com
Sat Jul 26 09:47:14 CEST 2014
Only 8-bit and 10-bit idct_dc() functions are included (adding others should be trivial).
Benchmarks on an Intel Core i5-4200U:
idct8x8_dc
SSE2 MMXEXT C
cycles 22 26 57
idct16x16_dc
AVX2 SSE2 C
cycles 27 32 249
idct32x32_dc
AVX2 SSE2 C
cycles 62 126 1375
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavcodec/hevcdsp.h | 2 -
libavcodec/x86/hevc_idct.asm | 249 +++++++++++-------------------------------
libavcodec/x86/hevcdsp.h | 28 -----
libavcodec/x86/hevcdsp_init.c | 95 +++++-----------
libavutil/x86/x86util.asm | 4 +-
5 files changed, 93 insertions(+), 285 deletions(-)
diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h
index ba42984..03d4246 100644
--- a/libavcodec/hevcdsp.h
+++ b/libavcodec/hevcdsp.h
@@ -56,8 +56,6 @@ typedef struct HEVCDSPContext {
void (*idct_dc[4])(int16_t *coeffs);
- void (*transform_dc_add[4])(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride);
-
void (*sao_band_filter)(uint8_t *_dst, uint8_t *_src, ptrdiff_t _stride_dst, ptrdiff_t _stride_src,
struct SAOParams *sao, int *borders,
int width, int height, int c_idx);
diff --git a/libavcodec/x86/hevc_idct.asm b/libavcodec/x86/hevc_idct.asm
index c97c82a..7a44f08 100644
--- a/libavcodec/x86/hevc_idct.asm
+++ b/libavcodec/x86/hevc_idct.asm
@@ -1,6 +1,7 @@
; /*
-; * Provide SSE & MMX idct functions for HEVC decoding
+; * SIMD optimized idct functions for HEVC decoding
; * Copyright (c) 2014 Pierre-Edouard LEPERE
+; * Copyright (c) 2014 James Almer
; *
; * This file is part of FFmpeg.
; *
@@ -20,206 +21,86 @@
; */
%include "libavutil/x86/x86util.asm"
-SECTION_RODATA 32
-max_pixels_10: times 16 dw ((1 << 10)-1)
-dc_add_10: times 4 dd ((1 << 14-10) + 1)
-
-
SECTION_TEXT 32
-;the idct_dc_add macros and functions were largely inspired by x264 project's code in the h264_idct.asm file
-
-%macro DC_ADD_INIT 2
- add %1w, ((1 << 14-8) + 1)
- sar %1w, (15-8)
- movd m0, %1d
- lea %1, [%2*3]
- SPLATW m0, m0, 0
- pxor m1, m1
- psubw m1, m0
- packuswb m0, m0
- packuswb m1, m1
-%endmacro
-
-%macro DC_ADD_INIT_AVX2 2
- add %1w, ((1 << 14-8) + 1)
- sar %1w, (15-8)
- movd xm0, %1d
- vpbroadcastw m0, xm0 ;SPLATW
- lea %1, [%2*3]
- pxor m1, m1
- psubw m1, m0
- packuswb m0, m0
- packuswb m1, m1
+; void ff_hevc_idctHxW_dc_{8,10}_<opt>(int16_t *coeffs)
+; %1 = HxW
+; %2 = number of loops
+; %3 = bitdepth
+%macro IDCT_DC 3
+cglobal hevc_idct%1x%1_dc_%3, 1, 2, 1, coeff, tmp
+ movsx tmpq, word [coeffq]
+ add tmpw, ((1 << 14-%3) + 1)
+ sar tmpw, (15-%3)
+ movd xm0, tmpd
+ SPLATW m0, xm0
+ DEFINE_ARGS coeff, cnt
+ mov cntd, %2
+.loop
+ mova [coeffq+mmsize*0], m0
+ mova [coeffq+mmsize*1], m0
+ mova [coeffq+mmsize*2], m0
+ mova [coeffq+mmsize*3], m0
+ mova [coeffq+mmsize*4], m0
+ mova [coeffq+mmsize*5], m0
+ mova [coeffq+mmsize*6], m0
+ mova [coeffq+mmsize*7], m0
+ add coeffq, mmsize*8
+ dec cntd
+ jg .loop
+ RET
%endmacro
-%macro DC_ADD_OP 4
- %1 m2, [%2 ]
- %1 m3, [%2+%3 ]
- %1 m4, [%2+%3*2]
- %1 m5, [%2+%4 ]
- paddusb m2, m0
- paddusb m3, m0
- paddusb m4, m0
- paddusb m5, m0
- psubusb m2, m1
- psubusb m3, m1
- psubusb m4, m1
- psubusb m5, m1
- %1 [%2 ], m2
- %1 [%2+%3 ], m3
- %1 [%2+%3*2], m4
- %1 [%2+%4 ], m5
+; %1 = HxW
+; %2 = bitdepth
+%macro IDCT_DC_NL 2 ; No loop
+cglobal hevc_idct%1x%1_dc_%2, 1, 2, 1, coeff, tmp
+ movsx tmpq, word [coeffq]
+ add tmpw, ((1 << 14-%2) + 1)
+ sar tmpw, (15-%2)
+ movd m0, tmpd
+ SPLATW m0, xm0
+ mova [coeffq+mmsize*0], m0
+ mova [coeffq+mmsize*1], m0
+ mova [coeffq+mmsize*2], m0
+ mova [coeffq+mmsize*3], m0
+%if mmsize == 16
+ mova [coeffq+mmsize*4], m0
+ mova [coeffq+mmsize*5], m0
+ mova [coeffq+mmsize*6], m0
+ mova [coeffq+mmsize*7], m0
+%endif
+ RET
%endmacro
+; 8-bit
INIT_MMX mmxext
-; void ff_hevc_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-%if ARCH_X86_64
-cglobal hevc_idct4_dc_add_8, 3, 4, 0
- movsx r3, word [r1]
- DC_ADD_INIT r3, r2
- DC_ADD_OP movh, r0, r2, r3
- RET
-
-; void ff_hevc_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-cglobal hevc_idct8_dc_add_8, 3, 4, 0
- movsx r3, word [r1]
- DC_ADD_INIT r3, r2
- DC_ADD_OP mova, r0, r2, r3
- lea r0, [r0+r2*4]
- DC_ADD_OP mova, r0, r2, r3
- RET
-%else
-; void ff_hevc_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-cglobal hevc_idct4_dc_add_8, 2, 3, 0
- movsx r2, word [r1]
- mov r1, r2m
- DC_ADD_INIT r2, r1
- DC_ADD_OP movh, r0, r1, r2
- RET
-
-; void ff_hevc_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-cglobal hevc_idct8_dc_add_8, 2, 3, 0
- movsx r2, word [r1]
- mov r1, r2m
- DC_ADD_INIT r2, r1
- DC_ADD_OP mova, r0, r1, r2
- lea r0, [r0+r1*4]
- DC_ADD_OP mova, r0, r1, r2
- RET
-%endif
-
+IDCT_DC_NL 4, 8
+IDCT_DC 8, 2, 8
INIT_XMM sse2
-; void ff_hevc_idct16_dc_add_8_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-cglobal hevc_idct16_dc_add_8, 3, 4, 6
- movsx r3, word [r1]
- DC_ADD_INIT r3, r2
- DC_ADD_OP mova, r0, r2, r3
- lea r0, [r0+r2*4]
- DC_ADD_OP mova, r0, r2, r3
- lea r0, [r0+r2*4]
- DC_ADD_OP mova, r0, r2, r3
- lea r0, [r0+r2*4]
- DC_ADD_OP mova, r0, r2, r3
- RET
+IDCT_DC_NL 8, 8
+IDCT_DC 16, 4, 8
+IDCT_DC 32, 16, 8
%if HAVE_AVX2_EXTERNAL
INIT_YMM avx2
-; void ff_hevc_idct32_dc_add_8_avx2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-cglobal hevc_idct32_dc_add_8, 3, 4, 6
- movsx r3, word [r1]
- DC_ADD_INIT_AVX2 r3, r2
- DC_ADD_OP mova, r0, r2, r3,
- %rep 7
- lea r0, [r0+r2*4]
- DC_ADD_OP mova, r0, r2, r3
-%endrep
- RET
+IDCT_DC 16, 2, 8
+IDCT_DC 32, 8, 8
%endif ;HAVE_AVX2_EXTERNAL
-;-----------------------------------------------------------------------------
-; void ff_hevc_idct_dc_add_10(pixel *dst, int16_t *block, int stride)
-;-----------------------------------------------------------------------------
-%macro IDCT_DC_ADD_OP_10 3
- pxor m5, m5
-%if avx_enabled
- paddw m1, m0, [%1+0 ]
- paddw m2, m0, [%1+%2 ]
- paddw m3, m0, [%1+%2*2]
- paddw m4, m0, [%1+%3 ]
-%else
- mova m1, [%1+0 ]
- mova m2, [%1+%2 ]
- mova m3, [%1+%2*2]
- mova m4, [%1+%3 ]
- paddw m1, m0
- paddw m2, m0
- paddw m3, m0
- paddw m4, m0
-%endif
- CLIPW m1, m5, m6
- CLIPW m2, m5, m6
- CLIPW m3, m5, m6
- CLIPW m4, m5, m6
- mova [%1+0 ], m1
- mova [%1+%2 ], m2
- mova [%1+%2*2], m3
- mova [%1+%3 ], m4
-%endmacro
+; 10-bit
INIT_MMX mmxext
-cglobal hevc_idct4_dc_add_10,3,3
- mov r1w, [r1]
- add r1w, ((1 << 4) + 1)
- sar r1w, 5
- movd m0, r1d
- lea r1, [r2*3]
- SPLATW m0, m0, 0
- mova m6, [max_pixels_10]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- RET
-
-;-----------------------------------------------------------------------------
-; void ff_hevc_idct8_dc_add_10(pixel *dst, int16_t *block, int stride)
-;-----------------------------------------------------------------------------
-%macro IDCT8_DC_ADD 0
-cglobal hevc_idct8_dc_add_10,3,4,7
- mov r1w, [r1]
- add r1w, ((1 << 4) + 1)
- sar r1w, 5
- movd m0, r1d
- lea r1, [r2*3]
- SPLATW m0, m0, 0
- mova m6, [max_pixels_10]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- lea r0, [r0+r2*4]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- RET
-%endmacro
+IDCT_DC_NL 4, 10
+IDCT_DC 8, 2, 10
INIT_XMM sse2
-IDCT8_DC_ADD
-%if HAVE_AVX_EXTERNAL
-INIT_XMM avx
-IDCT8_DC_ADD
-%endif
+IDCT_DC_NL 8, 10
+IDCT_DC 16, 4, 10
+IDCT_DC 32, 16, 10
%if HAVE_AVX2_EXTERNAL
INIT_YMM avx2
-cglobal hevc_idct16_dc_add_10,3,4,7
- mov r1w, [r1]
- add r1w, ((1 << 4) + 1)
- sar r1w, 5
- movd xm0, r1d
- lea r1, [r2*3]
- vpbroadcastw m0, xm0 ;SPLATW
- mova m6, [max_pixels_10]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- lea r0, [r0+r2*4]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- lea r0, [r0+r2*4]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- lea r0, [r0+r2*4]
- IDCT_DC_ADD_OP_10 r0, r2, r1
- RET
-%endif ;HAVE_AVX_EXTERNAL
+IDCT_DC 16, 2, 10
+IDCT_DC 32, 8, 10
+%endif ;HAVE_AVX2_EXTERNAL
diff --git a/libavcodec/x86/hevcdsp.h b/libavcodec/x86/hevcdsp.h
index 6062d8e..4bcc8dc 100644
--- a/libavcodec/x86/hevcdsp.h
+++ b/libavcodec/x86/hevcdsp.h
@@ -131,32 +131,4 @@ WEIGHTING_PROTOTYPES(8, sse4);
WEIGHTING_PROTOTYPES(10, sse4);
WEIGHTING_PROTOTYPES(12, sse4);
-///////////////////////////////////////////////////////////////////////////////
-// IDCT
-///////////////////////////////////////////////////////////////////////////////
-
-
-idct_dc_proto(4, 8,mmxext);
-idct_dc_proto(8, 8,mmxext);
-idct_dc_proto(16,8, sse2);
-idct_dc_proto(32,8, sse2);
-
-idct_dc_proto(32,8, avx2);
-
-
-idct_dc_proto(4, 10,mmxext);
-idct_dc_proto(8, 10, sse2);
-idct_dc_proto(16,10, sse2);
-idct_dc_proto(32,10, sse2);
-idct_dc_proto(8, 10, avx);
-idct_dc_proto(16,10, avx);
-idct_dc_proto(32,10, avx);
-
-idct_dc_proto(16,10, avx2);
-idct_dc_proto(32,10, avx2);
-
-
-
-
-
#endif // AVCODEC_X86_HEVCDSP_H
diff --git a/libavcodec/x86/hevcdsp_init.c b/libavcodec/x86/hevcdsp_init.c
index 6fb94aa..fb3357b 100644
--- a/libavcodec/x86/hevcdsp_init.c
+++ b/libavcodec/x86/hevcdsp_init.c
@@ -54,59 +54,17 @@ LFL_FUNCS(uint8_t, 8, ssse3)
LFL_FUNCS(uint8_t, 10, ssse3)
LFL_FUNCS(uint8_t, 12, ssse3)
-#if HAVE_SSE2_EXTERNAL
-void ff_hevc_idct32_dc_add_8_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct16_dc_add_8_sse2(dst, coeffs, stride);
- ff_hevc_idct16_dc_add_8_sse2(dst+16, coeffs, stride);
- ff_hevc_idct16_dc_add_8_sse2(dst+16*stride, coeffs, stride);
- ff_hevc_idct16_dc_add_8_sse2(dst+16*stride+16, coeffs, stride);
-}
-
-void ff_hevc_idct16_dc_add_10_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct8_dc_add_10_sse2(dst, coeffs, stride);
- ff_hevc_idct8_dc_add_10_sse2(dst+16, coeffs, stride);
- ff_hevc_idct8_dc_add_10_sse2(dst+8*stride, coeffs, stride);
- ff_hevc_idct8_dc_add_10_sse2(dst+8*stride+16, coeffs, stride);
-}
-
-void ff_hevc_idct32_dc_add_10_sse2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct16_dc_add_10_sse2(dst, coeffs, stride);
- ff_hevc_idct16_dc_add_10_sse2(dst+32, coeffs, stride);
- ff_hevc_idct16_dc_add_10_sse2(dst+16*stride, coeffs, stride);
- ff_hevc_idct16_dc_add_10_sse2(dst+16*stride+32, coeffs, stride);
-}
-#endif //HAVE_SSE2_EXTERNAL
-#if HAVE_AVX_EXTERNAL
-void ff_hevc_idct16_dc_add_10_avx(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct8_dc_add_10_avx(dst, coeffs, stride);
- ff_hevc_idct8_dc_add_10_avx(dst+16, coeffs, stride);
- ff_hevc_idct8_dc_add_10_avx(dst+8*stride, coeffs, stride);
- ff_hevc_idct8_dc_add_10_avx(dst+8*stride+16, coeffs, stride);
-}
-
-void ff_hevc_idct32_dc_add_10_avx(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct16_dc_add_10_avx(dst, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx(dst+32, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx(dst+16*stride, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx(dst+16*stride+32, coeffs, stride);
-}
-#endif //HAVE_AVX_EXTERNAL
-
-#if HAVE_AVX2_EXTERNAL
-
-void ff_hevc_idct32_dc_add_10_avx2(uint8_t *dst, int16_t *coeffs, ptrdiff_t stride)
-{
- ff_hevc_idct16_dc_add_10_avx2(dst, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx2(dst+32, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx2(dst+16*stride, coeffs, stride);
- ff_hevc_idct16_dc_add_10_avx2(dst+16*stride+32, coeffs, stride);
-}
-#endif //HAVE_AVX2_EXTERNAL
+#define IDCT_FUNCS(W, opt) \
+void ff_hevc_idct##W##_dc_8_##opt(int16_t *coeffs); \
+void ff_hevc_idct##W##_dc_10_##opt(int16_t *coeffs)
+
+IDCT_FUNCS(4x4, mmxext);
+IDCT_FUNCS(8x8, mmxext);
+IDCT_FUNCS(8x8, sse2);
+IDCT_FUNCS(16x16, sse2);
+IDCT_FUNCS(32x32, sse2);
+IDCT_FUNCS(16x16, avx2);
+IDCT_FUNCS(32x32, avx2);
#define mc_rep_func(name, bitd, step, W, opt) \
void ff_hevc_put_hevc_##name##W##_##bitd##_##opt(int16_t *_dst, ptrdiff_t dststride, \
@@ -504,8 +462,8 @@ void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth)
if (bit_depth == 8) {
if (EXTERNAL_MMXEXT(mm_flags)) {
- c->transform_dc_add[0] = ff_hevc_idct4_dc_add_8_mmxext;
- c->transform_dc_add[1] = ff_hevc_idct8_dc_add_8_mmxext;
+ c->idct_dc[0] = ff_hevc_idct4x4_dc_8_mmxext;
+ c->idct_dc[1] = ff_hevc_idct8x8_dc_8_mmxext;
}
if (EXTERNAL_SSE2(mm_flags)) {
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_8_sse2;
@@ -515,8 +473,9 @@ void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth)
c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_8_sse2;
}
- c->transform_dc_add[2] = ff_hevc_idct16_dc_add_8_sse2;
- c->transform_dc_add[3] = ff_hevc_idct32_dc_add_8_sse2;
+ c->idct_dc[1] = ff_hevc_idct8x8_dc_8_sse2;
+ c->idct_dc[2] = ff_hevc_idct16x16_dc_8_sse2;
+ c->idct_dc[3] = ff_hevc_idct32x32_dc_8_sse2;
}
if (EXTERNAL_SSSE3(mm_flags) && ARCH_X86_64) {
c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_8_ssse3;
@@ -535,12 +494,13 @@ void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth)
QPEL_LINKS(c->put_hevc_qpel, 1, 1, qpel_hv, 8, sse4);
}
if (EXTERNAL_AVX2(mm_flags)) {
- c->transform_dc_add[3] = ff_hevc_idct32_dc_add_8_avx2;
+ c->idct_dc[2] = ff_hevc_idct16x16_dc_8_avx2;
+ c->idct_dc[3] = ff_hevc_idct32x32_dc_8_avx2;
}
} else if (bit_depth == 10) {
if (EXTERNAL_MMXEXT(mm_flags)) {
- c->transform_dc_add[0] = ff_hevc_idct4_dc_add_10_mmxext;
-
+ c->idct_dc[0] = ff_hevc_idct4x4_dc_10_mmxext;
+ c->idct_dc[1] = ff_hevc_idct8x8_dc_10_mmxext;
}
if (EXTERNAL_SSE2(mm_flags)) {
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2;
@@ -550,9 +510,9 @@ void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth)
c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_10_sse2;
}
- c->transform_dc_add[1] = ff_hevc_idct8_dc_add_10_sse2;
- c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_sse2;
- c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_sse2;
+ c->idct_dc[1] = ff_hevc_idct8x8_dc_10_sse2;
+ c->idct_dc[2] = ff_hevc_idct16x16_dc_10_sse2;
+ c->idct_dc[3] = ff_hevc_idct32x32_dc_10_sse2;
}
if (EXTERNAL_SSSE3(mm_flags) && ARCH_X86_64) {
c->hevc_v_loop_filter_luma = ff_hevc_v_loop_filter_luma_10_ssse3;
@@ -569,14 +529,9 @@ void ff_hevcdsp_init_x86(HEVCDSPContext *c, const int bit_depth)
QPEL_LINKS(c->put_hevc_qpel, 1, 0, qpel_v, 10, sse4);
QPEL_LINKS(c->put_hevc_qpel, 1, 1, qpel_hv, 10, sse4);
}
- if (EXTERNAL_AVX(mm_flags)) {
- c->transform_dc_add[1] = ff_hevc_idct8_dc_add_10_avx;
- c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_avx;
- c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_avx;
- }
if (EXTERNAL_AVX2(mm_flags)) {
- c->transform_dc_add[2] = ff_hevc_idct16_dc_add_10_avx2;
- c->transform_dc_add[3] = ff_hevc_idct32_dc_add_10_avx2;
+ c->idct_dc[2] = ff_hevc_idct16x16_dc_10_avx2;
+ c->idct_dc[3] = ff_hevc_idct32x32_dc_10_avx2;
}
} else if (bit_depth == 12) {
diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm
index 9fb4778..824e449 100644
--- a/libavutil/x86/x86util.asm
+++ b/libavutil/x86/x86util.asm
@@ -598,7 +598,9 @@
%endmacro
%macro SPLATW 2-3 0
-%if mmsize == 16
+%if cpuflag(avx2) && %3 == 0
+ vpbroadcastw %1, %2
+%elif mmsize == 16
pshuflw %1, %2, (%3)*0x55
punpcklqdq %1, %1
%elif cpuflag(mmxext)
--
1.8.5.5
More information about the ffmpeg-devel
mailing list