From cc4d3dd3e2171f63cd4297292349b58788fff260 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 8 Mar 2011 13:18:57 -0500 Subject: [PATCH] ac3enc: add SIMD-optimized shifting functions for use with the fixed-point AC3 encoder Signed-off-by: Michael Niedermayer --- libavcodec/ac3dsp.c | 26 +++++++++++++ libavcodec/ac3dsp.h | 22 +++++++++++ libavcodec/ac3enc_fixed.c | 44 ++-------------------- libavcodec/x86/ac3dsp.asm | 74 +++++++++++++++++++++++++++++++++++++ libavcodec/x86/ac3dsp_mmx.c | 13 +++++++ 5 files changed, 138 insertions(+), 41 deletions(-) diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index da3a123e9b5..05b1aa809dc 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -50,10 +50,36 @@ static int ac3_max_msb_abs_int16_c(const int16_t *src, int len) return v; } +static void ac3_lshift_int16_c(int16_t *src, int len, unsigned int shift) +{ + int i; + + if (shift > 0) { + for (i = 0; i < len; i++) + src[i] <<= shift; + } +} + +static void ac3_shift_int32_c(int32_t *src, int len, int shift) +{ + int i; + + if (shift > 0) { + for (i = 0; i < len; i++) + src[i] <<= shift; + } else if (shift < 0) { + shift = -shift; + for (i = 0; i < len; i++) + src[i] >>= shift; + } +} + av_cold void ff_ac3dsp_init(AC3DSPContext *c) { c->ac3_exponent_min = ac3_exponent_min_c; c->ac3_max_msb_abs_int16 = ac3_max_msb_abs_int16_c; + c->ac3_lshift_int16 = ac3_lshift_int16_c; + c->ac3_shift_int32 = ac3_shift_int32_c; if (HAVE_MMX) ff_ac3dsp_init_x86(c); diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index a4f141f2f53..62351e9b7c7 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -46,6 +46,28 @@ typedef struct AC3DSPContext { * @return a value with the same MSB as max(abs(src[])) */ int (*ac3_max_msb_abs_int16)(const int16_t *src, int len); + + /* + * Left-shift each value in an array of int16_t by a specified amount. + * @param src input array + * constraints: align 16 + * @param len number of values in the array + * constraints: multiple of 32 greater than 0 + * @param shift left shift amount + * constraints: range [0,15] + */ + void (*ac3_lshift_int16)(int16_t *src, int len, unsigned int shift); + + /** + * Shift each value in an array of int32_t by a specified amount. + * @param src input array + * constraints: align 16 + * @param len number of values in the array + * constraints: multiple of 16 greater than 0 + * @param shift shift amount (negative = right, positive = left) + * constraints: range [-31,31] + */ + void (*ac3_shift_int32)(int32_t *src, int len, int shift); } AC3DSPContext; void ff_ac3dsp_init (AC3DSPContext *c); diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index e5853a35307..0440407c130 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -277,44 +277,6 @@ static int log2_tab(AC3EncodeContext *s, int16_t *src, int len) } -/** - * Left-shift each value in an array by a specified amount. - * @param tab input array - * @param n number of values in the array - * @param lshift left shift amount - */ -static void lshift_tab(int16_t *tab, int n, unsigned int lshift) -{ - int i; - - if (lshift > 0) { - for (i = 0; i < n; i++) - tab[i] <<= lshift; - } -} - - -/** - * Shift each value in an array by a specified amount. - * @param src input array - * @param n number of values in the array - * @param shift shift amount (negative=right, positive=left) - */ -static void shift_int32(int32_t *src, int n, int shift) -{ - int i; - - if (shift > 0) { - for (i = 0; i < n; i++) - src[i] <<= shift; - } else if (shift < 0) { - shift = -shift; - for (i = 0; i < n; i++) - src[i] >>= shift; - } -} - - /** * Normalize the input samples to use the maximum available precision. * This assumes signed 16-bit input samples. @@ -324,7 +286,7 @@ static void shift_int32(int32_t *src, int n, int shift) static int normalize_samples(AC3EncodeContext *s) { int v = 14 - log2_tab(s, s->windowed_samples, AC3_WINDOW_SIZE); - lshift_tab(s->windowed_samples, AC3_WINDOW_SIZE, v); + s->ac3dsp.ac3_lshift_int16(s->windowed_samples, AC3_WINDOW_SIZE, v); return 9 - v; } @@ -339,8 +301,8 @@ static void scale_coefficients(AC3EncodeContext *s) for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { AC3Block *block = &s->blocks[blk]; for (ch = 0; ch < s->channels; ch++) { - shift_int32(block->mdct_coef[ch], AC3_MAX_COEFS, - block->coeff_shift[ch]); + s->ac3dsp.ac3_shift_int32(block->mdct_coef[ch], AC3_MAX_COEFS, + block->coeff_shift[ch]); } } } diff --git a/libavcodec/x86/ac3dsp.asm b/libavcodec/x86/ac3dsp.asm index b1eeca9cd23..a7ec6cb0607 100644 --- a/libavcodec/x86/ac3dsp.asm +++ b/libavcodec/x86/ac3dsp.asm @@ -133,3 +133,77 @@ INIT_XMM AC3_MAX_MSB_ABS_INT16 sse2, min_max %define ABS2 ABS2_SSSE3 AC3_MAX_MSB_ABS_INT16 ssse3, or_abs + +;----------------------------------------------------------------------------- +; macro used for ff_ac3_lshift_int16() and ff_ac3_shift_int32() +;----------------------------------------------------------------------------- + +%macro AC3_SHIFT_4MM 3 ; src/dst, shift instruction, shift amount + mova m1, [%1 ] + mova m2, [%1+mmsize ] + mova m3, [%1+mmsize*2] + mova m4, [%1+mmsize*3] + %2 m1, %3 + %2 m2, %3 + %2 m3, %3 + %2 m4, %3 + mova [%1 ], m1 + mova [%1+mmsize ], m2 + mova [%1+mmsize*2], m3 + mova [%1+mmsize*3], m4 + add %1, mmsize*4 +%endmacro + +;----------------------------------------------------------------------------- +; void ff_ac3_lshift_int16(int16_t *src, int len, unsigned int shift) +;----------------------------------------------------------------------------- + +%macro AC3_LSHIFT_INT16 1 +cglobal ac3_lshift_int16_%1, 3,3,5, src, len, shift + test shiftd, shiftd + jz .end + movd m0, shiftd + ALIGN 8 +.loop: + AC3_SHIFT_4MM srcq, psllw, m0 + sub lend, mmsize*2 + ja .loop +.end: + REP_RET +%endmacro + +INIT_MMX +AC3_LSHIFT_INT16 mmx +INIT_XMM +AC3_LSHIFT_INT16 sse2 + +;----------------------------------------------------------------------------- +; void ff_ac3_shift_int32(int32_t *src, int len, int shift) +;----------------------------------------------------------------------------- + +%macro AC3_SHIFT_INT32 1 +cglobal ac3_shift_int32_%1, 3,3,5, src, len, shift + test shiftd, shiftd + je .end + js .shift_right + movd m0, shiftd +.loop_left: + AC3_SHIFT_4MM srcq, pslld, m0 + sub lend, mmsize + ja .loop_left + jmp .end +.shift_right: + neg shiftd + movd m0, shiftd +.loop_right: + AC3_SHIFT_4MM srcq, psrad, m0 + sub lend, mmsize + ja .loop_right +.end: + REP_RET +%endmacro + +INIT_MMX +AC3_SHIFT_INT32 mmx +INIT_XMM +AC3_SHIFT_INT32 sse2 diff --git a/libavcodec/x86/ac3dsp_mmx.c b/libavcodec/x86/ac3dsp_mmx.c index d8af59ce8df..7560d34f8d8 100644 --- a/libavcodec/x86/ac3dsp_mmx.c +++ b/libavcodec/x86/ac3dsp_mmx.c @@ -32,6 +32,12 @@ 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); +extern void ff_ac3_lshift_int16_mmx (int16_t *src, int len, unsigned int lshift); +extern void ff_ac3_lshift_int16_sse2(int16_t *src, int len, unsigned int lshift); + +extern void ff_ac3_shift_int32_mmx (int32_t *src, int len, int shift); +extern void ff_ac3_shift_int32_sse2(int32_t *src, int len, int shift); + av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c) { int mm_flags = av_get_cpu_flags(); @@ -40,6 +46,8 @@ av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c) 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; + c->ac3_lshift_int16 = ff_ac3_lshift_int16_mmx; + c->ac3_shift_int32 = ff_ac3_shift_int32_mmx; } if (mm_flags & AV_CPU_FLAG_MMX2 && HAVE_MMX2) { c->ac3_exponent_min = ff_ac3_exponent_min_mmxext; @@ -48,6 +56,11 @@ av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c) 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_SSE2SLOW)) { + c->ac3_lshift_int16 = ff_ac3_lshift_int16_sse2; + c->ac3_shift_int32 = ff_ac3_shift_int32_sse2; + } } if (mm_flags & AV_CPU_FLAG_SSSE3 && HAVE_SSSE3) { c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_ssse3; -- 2.39.2