From 4ccf6e397139ad83bc7413f8cf7ec667be6ace3a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 19 Jun 2012 03:08:19 +0200 Subject: swr: MMX2 & SSSE3 int16 resample core about 4 times faster Signed-off-by: Michael Niedermayer --- libswresample/resample.c | 64 +++++++++++++++++++++++++++++++++--- libswresample/resample_template.c | 4 +++ libswresample/x86/resample_mmx.h | 69 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 libswresample/x86/resample_mmx.h diff --git a/libswresample/resample.c b/libswresample/resample.c index 81da0ff..4e6672c 100644 --- a/libswresample/resample.c +++ b/libswresample/resample.c @@ -356,15 +356,71 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio #define OUT(d, v) d = v #include "resample_template.c" +#undef RENAME +#undef FELEM +#undef FELEM2 +#undef DELEM +#undef FELEML +#undef OUT +#undef FELEM_MIN +#undef FELEM_MAX +#undef FILTER_SHIFT + +// XXX FIXME the whole C loop should be written in asm so this x86 specific code here isnt needed +#if ARCH_X86 +#include "x86/resample_mmx.h" +#define COMMON_CORE COMMON_CORE_INT16_MMX2 +#define RENAME(N) N ## _int16_mmx2 +#define FILTER_SHIFT 15 +#define DELEM int16_t +#define FELEM int16_t +#define FELEM2 int32_t +#define FELEML int64_t +#define FELEM_MAX INT16_MAX +#define FELEM_MIN INT16_MIN +#define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\ + d = (unsigned)(v + 32768) > 65535 ? (v>>31) ^ 32767 : v +#include "resample_template.c" + +#undef COMMON_CORE +#undef RENAME +#undef FELEM +#undef FELEM2 +#undef DELEM +#undef FELEML +#undef OUT +#undef FELEM_MIN +#undef FELEM_MAX +#undef FILTER_SHIFT + +#define COMMON_CORE COMMON_CORE_INT16_SSSE3 +#define RENAME(N) N ## _int16_ssse3 +#define FILTER_SHIFT 15 +#define DELEM int16_t +#define FELEM int16_t +#define FELEM2 int32_t +#define FELEML int64_t +#define FELEM_MAX INT16_MAX +#define FELEM_MIN INT16_MIN +#define OUT(d, v) v = (v + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT;\ + d = (unsigned)(v + 32768) > 65535 ? (v>>31) ^ 32767 : v +#include "resample_template.c" +#endif // ARCH_X86 int swri_multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ int i, ret= -1; + int mm_flags = av_get_cpu_flags(); for(i=0; ich_count; i++){ - if(c->format == AV_SAMPLE_FMT_S16P) ret= swri_resample_int16(c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - if(c->format == AV_SAMPLE_FMT_S32P) ret= swri_resample_int32(c, (int32_t*)dst->ch[i], (const int32_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - if(c->format == AV_SAMPLE_FMT_FLTP) ret= swri_resample_float(c, (float *)dst->ch[i], (const float *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); - if(c->format == AV_SAMPLE_FMT_DBLP) ret= swri_resample_double(c,(double *)dst->ch[i], (const double *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); +#if ARCH_X86 + if(c->format == AV_SAMPLE_FMT_S16P && (mm_flags&AV_CPU_FLAG_SSSE3)) ret= swri_resample_int16_ssse3(c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + else if(c->format == AV_SAMPLE_FMT_S16P && (mm_flags&AV_CPU_FLAG_MMX2 )) ret= swri_resample_int16_mmx2 (c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + else +#endif + if(c->format == AV_SAMPLE_FMT_S16P) ret= swri_resample_int16(c, (int16_t*)dst->ch[i], (const int16_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + else if(c->format == AV_SAMPLE_FMT_S32P) ret= swri_resample_int32(c, (int32_t*)dst->ch[i], (const int32_t*)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + else if(c->format == AV_SAMPLE_FMT_FLTP) ret= swri_resample_float(c, (float *)dst->ch[i], (const float *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); + else if(c->format == AV_SAMPLE_FMT_DBLP) ret= swri_resample_double(c,(double *)dst->ch[i], (const double *)src->ch[i], consumed, src_size, dst_size, i+1==dst->ch_count); } return ret; diff --git a/libswresample/resample_template.c b/libswresample/resample_template.c index 13d7189..ad84070 100644 --- a/libswresample/resample_template.c +++ b/libswresample/resample_template.c @@ -56,11 +56,15 @@ int RENAME(swri_resample)(ResampleContext *c, DELEM *dst, const DELEM *src, int if(sample_index + c->filter_length > src_size){ break; }else{ +#ifdef COMMON_CORE + COMMON_CORE +#else FELEM2 val=0; for(i=0; ifilter_length; i++){ val += src[sample_index + i] * (FELEM2)filter[i]; } OUT(dst[dst_index], val); +#endif } frac += dst_incr_frac; diff --git a/libswresample/x86/resample_mmx.h b/libswresample/x86/resample_mmx.h new file mode 100644 index 0000000..bbf23ad --- /dev/null +++ b/libswresample/x86/resample_mmx.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/x86_cpu.h" +#include "libavutil/cpu.h" + +int swri_resample_int16_mmx2 (struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); +int swri_resample_int16_ssse3(struct ResampleContext *c, int16_t *dst, const int16_t *src, int *consumed, int src_size, int dst_size, int update_ctx); + +DECLARE_ALIGNED(16, const uint64_t, ff_resample_int16_rounder)[2] = { 0x0000000000004000ULL, 0x0000000000000000ULL}; + +#define COMMON_CORE_INT16_MMX2 \ + x86_reg len= -2*c->filter_length;\ +__asm volatile(\ + "movq "MANGLE(ff_resample_int16_rounder)", %%mm0 \n\t"\ + "1: \n\t"\ + "movq (%1, %0), %%mm1 \n\t"\ + "pmaddwd (%2, %0), %%mm1 \n\t"\ + "paddd %%mm1, %%mm0 \n\t"\ + "add $8, %0 \n\t"\ + " js 1b \n\t"\ + "pshufw $0x0E, %%mm0, %%mm1 \n\t"\ + "paddd %%mm1, %%mm0 \n\t"\ + "psrad $15, %%mm0 \n\t"\ + "packssdw %%mm0, %%mm0 \n\t"\ + "movd %%mm0, (%3) \n\t"\ + : "+r" (len)\ + : "r" (((uint8_t*)(src+sample_index))-len),\ + "r" (((uint8_t*)filter)-len),\ + "r" (dst+dst_index)\ +); + +#define COMMON_CORE_INT16_SSSE3 \ + x86_reg len= -2*c->filter_length;\ +__asm volatile(\ + "movdqa "MANGLE(ff_resample_int16_rounder)", %%xmm0 \n\t"\ + "1: \n\t"\ + "movdqu (%1, %0), %%xmm1 \n\t"\ + "pmaddwd (%2, %0), %%xmm1 \n\t"\ + "paddd %%xmm1, %%xmm0 \n\t"\ + "add $16, %0 \n\t"\ + " js 1b \n\t"\ + "phaddd %%xmm0, %%xmm0 \n\t"\ + "phaddd %%xmm0, %%xmm0 \n\t"\ + "psrad $15, %%xmm0 \n\t"\ + "packssdw %%xmm0, %%xmm0 \n\t"\ + "movd %%xmm0, (%3) \n\t"\ + : "+r" (len)\ + : "r" (((uint8_t*)(src+sample_index))-len),\ + "r" (((uint8_t*)filter)-len),\ + "r" (dst+dst_index)\ +); -- cgit v1.1