Mercurial > libavcodec.hg
changeset 10104:0fa3d21b317e libavcodec
SSE optimized vector_clipf(). 10% faster TwinVQ decoding.
author | vitor |
---|---|
date | Thu, 27 Aug 2009 14:49:36 +0000 |
parents | 2066cbe806ef |
children | 7775f6627612 |
files | dsputil.c dsputil.h twinvq.c x86/dsputil_mmx.c |
diffstat | 4 files changed, 84 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/dsputil.c Thu Aug 27 13:41:29 2009 +0000 +++ b/dsputil.c Thu Aug 27 14:49:36 2009 +0000 @@ -4093,6 +4093,51 @@ dst[i] = src[i] * mul; } +static inline uint32_t clipf_c_one(uint32_t a, uint32_t mini, + uint32_t maxi, uint32_t maxisign) +{ + + if(a > mini) return mini; + else if((a^(1<<31)) > maxisign) return maxi; + else return a; +} + +static void vector_clipf_c_opposite_sign(float *dst, float *src, float *min, float *max, int len){ + int i; + uint32_t mini = *(uint32_t*)min; + uint32_t maxi = *(uint32_t*)max; + uint32_t maxisign = maxi ^ (1<<31); + uint32_t *dsti = (uint32_t*)dst; + uint32_t *srci = (uint32_t*)src; + for(i=0; i<len; i+=8) { + dsti[i + 0] = clipf_c_one(srci[i + 0], mini, maxi, maxisign); + dsti[i + 1] = clipf_c_one(srci[i + 1], mini, maxi, maxisign); + dsti[i + 2] = clipf_c_one(srci[i + 2], mini, maxi, maxisign); + dsti[i + 3] = clipf_c_one(srci[i + 3], mini, maxi, maxisign); + dsti[i + 4] = clipf_c_one(srci[i + 4], mini, maxi, maxisign); + dsti[i + 5] = clipf_c_one(srci[i + 5], mini, maxi, maxisign); + dsti[i + 6] = clipf_c_one(srci[i + 6], mini, maxi, maxisign); + dsti[i + 7] = clipf_c_one(srci[i + 7], mini, maxi, maxisign); + } +} +static void vector_clipf_c(float *dst, float *src, float min, float max, int len){ + int i; + if(min < 0 && max > 0) { + vector_clipf_c_opposite_sign(dst, src, &min, &max, len); + } else { + for(i=0; i < len; i+=8) { + dst[i ] = av_clipf(src[i ], min, max); + dst[i + 1] = av_clipf(src[i + 1], min, max); + dst[i + 2] = av_clipf(src[i + 2], min, max); + dst[i + 3] = av_clipf(src[i + 3], min, max); + dst[i + 4] = av_clipf(src[i + 4], min, max); + dst[i + 5] = av_clipf(src[i + 5], min, max); + dst[i + 6] = av_clipf(src[i + 6], min, max); + dst[i + 7] = av_clipf(src[i + 7], min, max); + } + } +} + static av_always_inline int float_to_int16_one(const float *src){ int_fast32_t tmp = *(const int32_t*)src; if(tmp & 0xf0000){ @@ -4669,6 +4714,7 @@ c->vector_fmul_add_add = ff_vector_fmul_add_add_c; c->vector_fmul_window = ff_vector_fmul_window_c; c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_c; + c->vector_clipf = vector_clipf_c; c->float_to_int16 = ff_float_to_int16_c; c->float_to_int16_interleave = ff_float_to_int16_interleave_c; c->add_int16 = add_int16_c;
--- a/dsputil.h Thu Aug 27 13:41:29 2009 +0000 +++ b/dsputil.h Thu Aug 27 14:49:36 2009 +0000 @@ -396,6 +396,7 @@ void (*vector_fmul_window)(float *dst, const float *src0, const float *src1, const float *win, float add_bias, int len); /* assume len is a multiple of 8, and arrays are 16-byte aligned */ void (*int32_to_float_fmul_scalar)(float *dst, const int *src, float mul, int len); + void (*vector_clipf)(float *dst /* align 16 */, float *src /* align 16 */, float min, float max, int len /* align 16 */); /* C version: convert floats from the range [384.0,386.0] to ints in [-32768,32767] * simd versions: convert floats from [-32768.0,32767.0] without rescaling and arrays are 16byte aligned */
--- a/twinvq.c Thu Aug 27 13:41:29 2009 +0000 +++ b/twinvq.c Thu Aug 27 14:49:36 2009 +0000 @@ -825,7 +825,6 @@ float *out = data; enum FrameType ftype; int window_type; - int i; static const enum FrameType wtype_to_ftype_table[] = { FT_LONG, FT_LONG, FT_SHORT, FT_LONG, FT_MEDIUM, FT_LONG, FT_LONG, FT_MEDIUM, FT_MEDIUM @@ -860,8 +859,8 @@ return buf_size; } - for (i=0; i < avctx->channels * mtab->size; i++) - out[i] = av_clipf(out[i], -32700./(1<<15), 32700./(1<<15)); + tctx->dsp.vector_clipf(out, out, -32700./(1<<15), 32700./(1<<15), + mtab->size); *data_size = mtab->size*avctx->channels*4;
--- a/x86/dsputil_mmx.c Thu Aug 27 13:41:29 2009 +0000 +++ b/x86/dsputil_mmx.c Thu Aug 27 14:49:36 2009 +0000 @@ -2346,6 +2346,40 @@ ); } +static void vector_clipf_sse(float *dst, float *src, float min, float max, + int len) +{ + x86_reg i = (len-16)*4; + __asm__ volatile( + "movss %3, %%xmm4 \n" + "movss %4, %%xmm5 \n" + "shufps $0, %%xmm4, %%xmm4 \n" + "shufps $0, %%xmm5, %%xmm5 \n" + "1: \n\t" + "movaps (%2,%0), %%xmm0 \n\t" // 3/1 on intel + "movaps 16(%2,%0), %%xmm1 \n\t" + "movaps 32(%2,%0), %%xmm2 \n\t" + "movaps 48(%2,%0), %%xmm3 \n\t" + "maxps %%xmm4, %%xmm0 \n\t" + "maxps %%xmm4, %%xmm1 \n\t" + "maxps %%xmm4, %%xmm2 \n\t" + "maxps %%xmm4, %%xmm3 \n\t" + "minps %%xmm5, %%xmm0 \n\t" + "minps %%xmm5, %%xmm1 \n\t" + "minps %%xmm5, %%xmm2 \n\t" + "minps %%xmm5, %%xmm3 \n\t" + "movaps %%xmm0, (%1,%0) \n\t" + "movaps %%xmm1, 16(%1,%0) \n\t" + "movaps %%xmm2, 32(%1,%0) \n\t" + "movaps %%xmm3, 48(%1,%0) \n\t" + "sub $64, %0 \n\t" + "jge 1b \n\t" + :"+r"(i) + :"r"(dst), "r"(src), "m"(min), "m"(max) + :"memory" + ); +} + static void float_to_int16_3dnow(int16_t *dst, const float *src, long len){ x86_reg reglen = len; // not bit-exact: pf2id uses different rounding than C and SSE @@ -3046,6 +3080,7 @@ c->vector_fmul_add_add = vector_fmul_add_add_sse; c->vector_fmul_window = vector_fmul_window_sse; c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_sse; + c->vector_clipf = vector_clipf_sse; c->float_to_int16 = float_to_int16_sse; c->float_to_int16_interleave = float_to_int16_interleave_sse; }