Ports the majority of IDCT functions for 10-bit H.264. Some code was ported from x264. --- libavcodec/x86/Makefile | 3 +- libavcodec/x86/h264_idct_10bit.asm | 433 ++++++++++++++++++++++++++++++++++++ libavcodec/x86/h264dsp_mmx.c | 59 +++++ 3 files changed, 494 insertions(+), 1 deletions(-) create mode 100644 libavcodec/x86/h264_idct_10bit.asm
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index ba664ab..38b736e 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -12,8 +12,9 @@ YASM-OBJS-$(CONFIG_FFT) += x86/fft_mmx.o \ MMX-OBJS-$(CONFIG_H264DSP) += x86/h264dsp_mmx.o YASM-OBJS-$(CONFIG_H264DSP) += x86/h264_deblock.o \ x86/h264_deblock_10bit.o \ - x86/h264_weight.o \ x86/h264_idct.o \ + x86/h264_idct_10bit.o \ + x86/h264_weight.o \ YASM-OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred.o MMX-OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred_init.o diff --git a/libavcodec/x86/h264_idct_10bit.asm b/libavcodec/x86/h264_idct_10bit.asm new file mode 100644 index 0000000..c16489a --- /dev/null +++ b/libavcodec/x86/h264_idct_10bit.asm @@ -0,0 +1,433 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 iDCT code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Daniel Kang <daniel.d.k...@gmail.com> +;* +;* This file is part of Libav. +;* +;* Libav 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. +;* +;* Libav 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 Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "x86inc.asm" +%include "x86util.asm" + +SECTION_RODATA + +pw_pixel_max: times 8 dw ((1 << 10)-1) +pd_32: times 4 dd 32 +scan8_mem: db 4+1*8, 5+1*8, 4+2*8, 5+2*8 + db 6+1*8, 7+1*8, 6+2*8, 7+2*8 + db 4+3*8, 5+3*8, 4+4*8, 5+4*8 + db 6+3*8, 7+3*8, 6+4*8, 7+4*8 + db 1+1*8, 2+1*8 + db 1+2*8, 2+2*8 + db 1+4*8, 2+4*8 + db 1+5*8, 2+5*8 + +%ifdef PIC +%define scan8 r11 +%else +%define scan8 scan8_mem +%endif + +SECTION .text + +;----------------------------------------------------------------------------- +; void h264_idct_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro STORE_DIFFx2 6 + psrad %1, 6 + psrad %2, 6 + packssdw %1, %2 + movq %3, [%5] + movhps %3, [%5+%6] + paddsw %1, %3 + CLIPW %1, %4, [pw_pixel_max] + movq [%5], %1 + movhps [%5+%6], %1 +%endmacro + +;dst, in, stride +%macro IDCT4_ADD_10 3 + mova m0, [%2+ 0] + mova m1, [%2+16] + mova m2, [%2+32] + mova m3, [%2+48] + IDCT4_1D d,0,1,2,3,4,5 + TRANSPOSE4x4D 0,1,2,3,4 + paddd m0, [pd_32] + IDCT4_1D d,0,1,2,3,4,5 + pxor m5, m5 + STORE_DIFFx2 m0, m1, m4, m5, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m4, m5, %1, %3 +%endmacro + +%macro IDCT_ADD_10 1 +cglobal h264_idct_add_10_%1, 3,3 + IDCT4_ADD_10 r0, r1, r2 + RET +%endmacro + +INIT_XMM +IDCT_ADD_10 sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT_ADD_10 avx +%endif + +;----------------------------------------------------------------------------- +; h264_idct_add16(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +;;;;;;; NO FATE SAMPLES TRIGGER THIS +%macro IDCT_ADD16_10 1 +cglobal h264_idct_add16_10_%1, 5,7 + xor r5, r5 +%ifdef PIC + lea r11, [scan8_mem] +%endif +.nextblock + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + cmp byte [r4+r6], 0 + jz .skipblock + mov r6d, dword [r1+r5*4] + add r6, r0 + IDCT4_ADD_10 r6, r2, r3 +.skipblock + inc r5 + add r2, 64 + cmp r5, 16 + jl .nextblock + REP_RET +%endmacro + +INIT_XMM +IDCT_ADD16_10 sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT_ADD16_10 avx +%endif + +;----------------------------------------------------------------------------- +; h264_idct_add16intra(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +%macro IDCT_ADD16INTRA_10 1 +cglobal h264_idct_add16intra_10_%1,5,7 + xor r5, r5 +%ifdef PIC + lea r11, [scan8_mem] +%endif +.nextblock + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + or r6d, dword [r2] + test r6, r6 + jz .skipblock + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6] + IDCT4_ADD_10 r6, r2, r3 +.skipblock + inc r5 + add r2, 64 + cmp r5, 16 + jl .nextblock + REP_RET +%endmacro + +INIT_XMM +IDCT_ADD16INTRA_10 sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT_ADD16INTRA_10 avx +%endif + + +;----------------------------------------------------------------------------- +; h264_idct_add8(pixel **dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +%macro IDCT_ADD8 1 +h264_idct_add8_10_plane_%1: +.nextblock + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + or r6d, dword [r2] + test r6, r6 + jz .skipblock +%ifdef ARCH_X86_64 + mov r0d, dword [r1+r5*4] + add r0, [r10] +%else + mov r0, r1m ; XXX r1m here is actually r0m of the calling func + mov r0, [r0] + add r0, dword [r1+r5*4] +%endif + IDCT4_ADD_10 r0, r2, r3 +.skipblock + inc r5 + add r2, 64 + test r5, 3 + jnz .nextblock + rep ret + +cglobal h264_idct_add8_10_%1,5,7,0 + mov r5, 16 + add r2, 1024 +%ifdef PIC + lea r11, [scan8_mem] +%endif +%ifdef ARCH_X86_64 + mov r10, r0 +%endif + call h264_idct_add8_10_plane_%1 +%ifdef ARCH_X86_64 + add r10, gprsize +%else + add r0mp, gprsize +%endif + call h264_idct_add8_10_plane_%1 + RET +%endmacro ; IDCT_ADD8 + +INIT_XMM +IDCT_ADD8 sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT_ADD8 avx +%endif + +;----------------------------------------------------------------------------- +; void h264_idct_dc_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT_DC_ADD_OP_10 0 + mova m1, [r0+ 0] + mova m2, [r0+r2] + mova m3, [r1+ 0] + mova m4, [r1+r2] + pxor m5, m5 + paddw m1, m0 + paddw m2, m0 + paddw m3, m0 + paddw m4, m0 + CLIPW m1, m5, m6 + CLIPW m2, m5, m6 + CLIPW m3, m5, m6 + CLIPW m4, m5, m6 + mova [r0+ 0], m1 + mova [r0+r2], m2 + mova [r1+ 0], m3 + mova [r1+r2], m4 +%endmacro + +INIT_MMX +cglobal h264_idct_dc_add_10_mmx2,3,3 + movd m0, dword [r1] + paddd m0, [pd_32] + psrad m0, 6 + lea r1, [r0+r2*2] + pshufw m0, m0, 0 + mova m6, [pw_pixel_max] + IDCT_DC_ADD_OP_10 + RET + +;----------------------------------------------------------------------------- +; void h264_idct8_dc_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT8_DC_ADD 1 +cglobal h264_idct8_dc_add_10_%1,3,3,7 + mov r1d, dword [r1] + add r1, 32 + sar r1, 6 + movd m0, r1d + lea r1, [r0+r2*2] + SPLATW m0, m0, 0 + mova m6, [pw_pixel_max] + IDCT_DC_ADD_OP_10 + lea r0, [r0+r2*4] + lea r1, [r0+r2*2] + IDCT_DC_ADD_OP_10 + RET +%endmacro + +INIT_XMM +IDCT8_DC_ADD sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT8_DC_ADD avx +%endif + +;----------------------------------------------------------------------------- +; void h264_idct8_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT8_1D 2 + SWAP 0, 1 + psrad m4, m5, 1 + psrad m1, m0, 1 + paddd m4, m5 + paddd m1, m0 + paddd m4, m7 + paddd m1, m5 + psubd m4, m0 + paddd m1, m3 + + psubd m0, m3 + psubd m5, m3 + paddd m0, m7 + psubd m5, m7 + psrad m3, 1 + psrad m7, 1 + psubd m0, m3 + psubd m5, m7 + + SWAP 1, 7 + psrad m1, m7, 2 + psrad m3, m4, 2 + paddd m3, m0 + psrad m0, 2 + paddd m1, m5 + psrad m5, 2 + psubd m0, m4 + psubd m7, m5 + + SWAP 5, 6 + psrad m4, m2, 1 + psrad m6, m5, 1 + psubd m4, m5 + paddd m6, m2 + + mova m2, %1 + mova m5, %2 + SUMSUB_BA d, 5, 2 + SUMSUB_BA d, 6, 5 + SUMSUB_BA d, 4, 2 + SUMSUB_BA d, 7, 6 + SUMSUB_BA d, 0, 4 + SUMSUB_BA d, 3, 2 + SUMSUB_BA d, 1, 5 + SWAP 7, 6, 4, 5, 2, 3, 1, 0 ; 70315246 -> 01234567 +%endmacro + +%macro IDCT8_1D_FULL 1 + mova m7, [%1+112*2] + mova m6, [%1+ 96*2] + mova m5, [%1+ 80*2] + mova m3, [%1+ 48*2] + mova m2, [%1+ 32*2] + mova m1, [%1+ 16*2] + IDCT8_1D [%1], [%1+ 64*2] +%endmacro + +; %1=int16_t *block, %2=int16_t *dstblock +%macro IDCT8_ADD_SSE_START 2 + IDCT8_1D_FULL %1 + mova [%1], m7 + TRANSPOSE4x4D 0,1,2,3,7 + mova m7, [%1] + mova [%2 ], m0 + mova [%2+16*2], m1 + mova [%2+32*2], m2 + mova [%2+48*2], m3 + TRANSPOSE4x4D 4,5,6,7,3 + mova [%2+ 8*2], m4 + mova [%2+24*2], m5 + mova [%2+40*2], m6 + mova [%2+56*2], m7 +%endmacro + +; %1=uint8_t *dst, %2=int16_t *block, %3=int stride +%macro IDCT8_ADD_SSE_END 3 + IDCT8_1D_FULL %2 + mova [%2 ], m5 + mova [%2+16*2], m6 + mova [%2+32*2], m7 + + pxor m7, m7 + STORE_DIFFx2 m0, m1, m5, m7, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m5, m7, %1, %3 + mova m0, [%2 ] + mova m1, [%2+16*2] + mova m2, [%2+32*2] + lea %1, [%1+%3*2] + STORE_DIFFx2 m4, m0, m5, m7, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m1, m2, m5, m7, %1, %3 +%endmacro + +%macro IDCT8_ADD 1 +cglobal h264_idct8_add_10_%1, 3,4,8 + %assign pad 256+16-gprsize-(stack_offset&15) + SUB rsp, pad + + add dword [r1], 32 + IDCT8_ADD_SSE_START r1 , rsp + IDCT8_ADD_SSE_START r1+16, rsp+128 + lea r3, [r0+8] + IDCT8_ADD_SSE_END r0 , rsp, r2 + IDCT8_ADD_SSE_END r3 , rsp+16, r2 + + ADD rsp, pad + RET +%endmacro + +INIT_XMM +IDCT8_ADD sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT8_ADD avx +%endif + +;----------------------------------------------------------------------------- +; h264_idct8_add4(pixel **dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +%macro IDCT8_ADD4 1 +cglobal h264_idct8_add4_10_%1, 5,7,8 + %assign pad 256+16-gprsize-(stack_offset&15) + SUB rsp, pad + xor r5, r5 +%ifdef PIC + lea r11, [scan8_mem] +%endif +.nextblock + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6] + add dword [r2], 32 + IDCT8_ADD_SSE_START r2 , rsp + IDCT8_ADD_SSE_START r2+16, rsp+128 + IDCT8_ADD_SSE_END r6 , rsp, r3 + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6+8] + IDCT8_ADD_SSE_END r6 , rsp+16, r3 +.skipblock + add r5, 4 + add r2, 256 + cmp r5, 16 + jl .nextblock + ADD rsp, pad + RET +%endmacro ; IDCT8_ADD4 + +INIT_XMM +IDCT8_ADD4 sse2 +%ifdef HAVE_AVX +INIT_AVX +IDCT8_ADD4 avx +%endif diff --git a/libavcodec/x86/h264dsp_mmx.c b/libavcodec/x86/h264dsp_mmx.c index 1c07d14..d60fbd5 100644 --- a/libavcodec/x86/h264dsp_mmx.c +++ b/libavcodec/x86/h264dsp_mmx.c @@ -27,6 +27,43 @@ DECLARE_ALIGNED(8, static const uint64_t, ff_pb_3_1 ) = 0x0103010301030103ULL; /***********************************/ /* IDCT */ +#define IDCT_ADD_FUNC(NUM, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add_ ## DEPTH ## _ ## OPT (uint8_t *dst, int16_t *block, int stride); + +IDCT_ADD_FUNC(, 10, sse2) +IDCT_ADD_FUNC(_dc, 10, mmx2) +IDCT_ADD_FUNC(8_dc, 10, sse2) +IDCT_ADD_FUNC(8, 10, sse2) +#if HAVE_AVX +IDCT_ADD_FUNC(, 10, avx) +IDCT_ADD_FUNC(8_dc, 10, avx) +IDCT_ADD_FUNC(8, 10, avx) +#endif + + +#define IDCT_ADD_REP_FUNC(NUM, REP, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ + (uint8_t *dst, const int *block_offset, \ + DCTELEM *block, int stride, const uint8_t nnzc[6*8]); + +IDCT_ADD_REP_FUNC(8, 4, 10, sse2) +IDCT_ADD_REP_FUNC(8, 4, 10, avx) +IDCT_ADD_REP_FUNC(, 16, 10, sse2) +IDCT_ADD_REP_FUNC(, 16intra, 10, sse2) +#if HAVE_AVX +IDCT_ADD_REP_FUNC(, 16, 10, avx) +IDCT_ADD_REP_FUNC(, 16intra, 10, avx) +#endif + + +#define IDCT_ADD_REP_FUNC2(NUM, REP, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ + (uint8_t **dst, const int *block_offset, \ + DCTELEM *block, int stride, const uint8_t nnzc[6*8]); +IDCT_ADD_REP_FUNC2(, 8, 10, sse2) +#if HAVE_AVX +IDCT_ADD_REP_FUNC2(, 8, 10, avx) +#endif void ff_h264_idct_add_mmx (uint8_t *dst, int16_t *block, int stride); void ff_h264_idct8_add_mmx (uint8_t *dst, int16_t *block, int stride); @@ -418,7 +455,17 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth) c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_10_mmxext; c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_mmxext; #endif + c->h264_idct_dc_add= ff_h264_idct_dc_add_10_mmx2; if (mm_flags&AV_CPU_FLAG_SSE2) { + c->h264_idct_add = ff_h264_idct_add_10_sse2; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_10_sse2; + c->h264_idct8_add = ff_h264_idct8_add_10_sse2; + + c->h264_idct_add16 = ff_h264_idct_add16_10_sse2; + c->h264_idct8_add4 = ff_h264_idct8_add4_10_sse2; + c->h264_idct_add8 = ff_h264_idct_add8_10_sse2; + c->h264_idct_add16intra= ff_h264_idct_add16intra_10_sse2; + c->h264_v_loop_filter_chroma= ff_deblock_v_chroma_10_sse2; c->h264_v_loop_filter_chroma_intra= ff_deblock_v_chroma_intra_10_sse2; #if HAVE_ALIGNED_STACK @@ -428,7 +475,18 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth) c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_sse2; #endif } +#if HAVE_AVX if (mm_flags&AV_CPU_FLAG_AVX) { + c->h264_idct_dc_add = + c->h264_idct_add = ff_h264_idct_add_10_avx; + c->h264_idct8_add = ff_h264_idct8_add_10_avx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_10_avx; + + c->h264_idct_add16 = ff_h264_idct_add16_10_avx; + c->h264_idct8_add4 = ff_h264_idct8_add4_10_avx; + c->h264_idct_add8 = ff_h264_idct_add8_10_avx; + c->h264_idct_add16intra= ff_h264_idct_add16intra_10_avx; + c->h264_v_loop_filter_chroma= ff_deblock_v_chroma_10_avx; c->h264_v_loop_filter_chroma_intra= ff_deblock_v_chroma_intra_10_avx; #if HAVE_ALIGNED_STACK @@ -438,6 +496,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth) c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_avx; #endif } +#endif /* HAVE_AVX */ } } #endif -- 1.7.5.1 _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel