summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sessak <vitor1001@gmail.com>2009-08-27 14:49:36 +0000
committerVitor Sessak <vitor1001@gmail.com>2009-08-27 14:49:36 +0000
commit0a68cd876e14f76a00df7bb8edbfeb350f8ef617 (patch)
tree5563e4fb33e663dbbaf813bd83e2c010bd82c68d
parent8fc9376c590d2998820bb27b4465636a3f3257a8 (diff)
SSE optimized vector_clipf(). 10% faster TwinVQ decoding.
Originally committed as revision 19728 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/dsputil.c46
-rw-r--r--libavcodec/dsputil.h1
-rw-r--r--libavcodec/twinvq.c5
-rw-r--r--libavcodec/x86/dsputil_mmx.c35
4 files changed, 84 insertions, 3 deletions
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
index 92d613a93d..758f613c11 100644
--- a/libavcodec/dsputil.c
+++ b/libavcodec/dsputil.c
@@ -4093,6 +4093,51 @@ static void int32_to_float_fmul_scalar_c(float *dst, const int *src, float mul,
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 @@ void dsputil_init(DSPContext* c, AVCodecContext *avctx)
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;
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index 2d15bd3538..032dd1d43c 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -396,6 +396,7 @@ typedef struct DSPContext {
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 */
diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c
index 1c05238efc..ba38ddcc78 100644
--- a/libavcodec/twinvq.c
+++ b/libavcodec/twinvq.c
@@ -825,7 +825,6 @@ static int twin_decode_frame(AVCodecContext * avctx, void *data,
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 @@ static int twin_decode_frame(AVCodecContext * avctx, void *data,
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;
diff --git a/libavcodec/x86/dsputil_mmx.c b/libavcodec/x86/dsputil_mmx.c
index da0f76412b..374aa64107 100644
--- a/libavcodec/x86/dsputil_mmx.c
+++ b/libavcodec/x86/dsputil_mmx.c
@@ -2346,6 +2346,40 @@ static void int32_to_float_fmul_scalar_sse2(float *dst, const int *src, float mu
);
}
+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 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
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;
}