diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-02-13 22:49:50 +0300 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-02-15 01:58:20 +0300 |
commit | 7539a1fee2c4935eb3318d625f881df85f2c9c04 (patch) | |
tree | 79b531353a0c98dc0268ac0bc985284042f7236d /libavcodec/x86 | |
parent | e590448c65b7f9cd1a9bcf39ee6874882034edc9 (diff) |
ac3enc: Add x86-optimized function to speed up log2_tab().
AC3DSPContext.ac3_max_msb_abs_int16() finds the maximum MSB of the absolute
value of each element in an array of int16_t.
Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
(cherry picked from commit fbb6b49dabc3398440c6dfa838aa090a7a6ebc0d)
Diffstat (limited to 'libavcodec/x86')
-rw-r--r-- | libavcodec/x86/ac3dsp.asm | 69 | ||||
-rw-r--r-- | libavcodec/x86/ac3dsp_mmx.c | 11 |
2 files changed, 80 insertions, 0 deletions
diff --git a/libavcodec/x86/ac3dsp.asm b/libavcodec/x86/ac3dsp.asm index e71c51cf33..dc71ccf91c 100644 --- a/libavcodec/x86/ac3dsp.asm +++ b/libavcodec/x86/ac3dsp.asm @@ -65,3 +65,72 @@ AC3_EXPONENT_MIN sse2 %endif %undef PMINUB %undef LOOP_ALIGN + +;----------------------------------------------------------------------------- +; int ff_ac3_max_msb_abs_int16(const int16_t *src, int len) +; +; This function uses 2 different methods to calculate a valid result. +; 1) logical 'or' of abs of each element +; This is used for ssse3 because of the pabsw instruction. +; It is also used for mmx because of the lack of min/max instructions. +; 2) calculate min/max for the array, then or(abs(min),abs(max)) +; This is used for mmxext and sse2 because they have pminsw/pmaxsw. +;----------------------------------------------------------------------------- + +%macro AC3_MAX_MSB_ABS_INT16 2 +cglobal ac3_max_msb_abs_int16_%1, 2,2,5, src, len + pxor m2, m2 + pxor m3, m3 +.loop: +%ifidn %2, min_max + mova m0, [srcq] + mova m1, [srcq+mmsize] + pminsw m2, m0 + pminsw m2, m1 + pmaxsw m3, m0 + pmaxsw m3, m1 +%else ; or_abs +%ifidn %1, mmx + mova m0, [srcq] + mova m1, [srcq+mmsize] + ABS2 m0, m1, m3, m4 +%else ; ssse3 + ; using memory args is faster for ssse3 + pabsw m0, [srcq] + pabsw m1, [srcq+mmsize] +%endif + por m2, m0 + por m2, m1 +%endif + add srcq, mmsize*2 + sub lend, mmsize + ja .loop +%ifidn %2, min_max + ABS2 m2, m3, m0, m1 + por m2, m3 +%endif +%ifidn mmsize, 16 + mova m0, m2 + punpckhqdq m0, m0 + por m2, m0 +%endif + PSHUFLW m0, m2, 0xe + por m2, m0 + PSHUFLW m0, m2, 0x1 + por m2, m0 + movd eax, m2 + and eax, 0xFFFF + RET +%endmacro + +INIT_MMX +%define ABS2 ABS2_MMX +%define PSHUFLW pshufw +AC3_MAX_MSB_ABS_INT16 mmx, or_abs +%define ABS2 ABS2_MMX2 +AC3_MAX_MSB_ABS_INT16 mmxext, min_max +INIT_XMM +%define PSHUFLW pshuflw +AC3_MAX_MSB_ABS_INT16 sse2, min_max +%define ABS2 ABS2_SSSE3 +AC3_MAX_MSB_ABS_INT16 ssse3, or_abs diff --git a/libavcodec/x86/ac3dsp_mmx.c b/libavcodec/x86/ac3dsp_mmx.c index 7ce3aa358d..d8af59ce8d 100644 --- a/libavcodec/x86/ac3dsp_mmx.c +++ b/libavcodec/x86/ac3dsp_mmx.c @@ -27,6 +27,11 @@ extern void ff_ac3_exponent_min_mmx (uint8_t *exp, int num_reuse_blocks, int n extern void ff_ac3_exponent_min_mmxext(uint8_t *exp, int num_reuse_blocks, int nb_coefs); extern void ff_ac3_exponent_min_sse2 (uint8_t *exp, int num_reuse_blocks, int nb_coefs); +extern int ff_ac3_max_msb_abs_int16_mmx (const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_mmxext(const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_sse2 (const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_ssse3 (const int16_t *src, int len); + av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c) { int mm_flags = av_get_cpu_flags(); @@ -34,12 +39,18 @@ av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c) #if HAVE_YASM if (mm_flags & AV_CPU_FLAG_MMX) { c->ac3_exponent_min = ff_ac3_exponent_min_mmx; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmx; } if (mm_flags & AV_CPU_FLAG_MMX2 && HAVE_MMX2) { c->ac3_exponent_min = ff_ac3_exponent_min_mmxext; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmxext; } if (mm_flags & AV_CPU_FLAG_SSE2 && HAVE_SSE) { c->ac3_exponent_min = ff_ac3_exponent_min_sse2; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_sse2; + } + if (mm_flags & AV_CPU_FLAG_SSSE3 && HAVE_SSSE3) { + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_ssse3; } #endif } |