History

mips: Optimization of IIR filter function

Bojan Zivkovic committed 13 years ago

Commit 7d29c6e1 parent 26f39246 files · +243 −2Browse files

Unified · Split

6 files
  1. doc/mips.txt +1 −0
  2. libavcodec/iirfilter.c +7 −0
  3. libavcodec/iirfilter.h +23 −0
  4. libavcodec/mips/Makefile +1 −0
  5. libavcodec/mips/iirfilter_mips.c +204 −0
  6. libavcodec/psymodel.c +7 −2
doc/mips.txt+1−0
@@ -64,5 +64,6 @@ Files that have MIPS copyright notice in them: · 63 unmodified lines
6464 fft_table.h
6565 fft_init_table.c
6666 fmtconvert_mips.c
67+ iirfilter_mips.c
6768 mpegaudiodsp_mips_fixed.c
6869 mpegaudiodsp_mips_float.c
libavcodec/iirfilter.c+7−0
@@ -311,6 +311,13 @@ av_cold void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs *coeffs) · 310 unmodified lines
311311 av_free(coeffs);
312312 }
313313
314+void ff_iir_filter_init(FFIIRFilterContext *f) {
315+ f->filter_flt = ff_iir_filter_flt;
316+
317+ if (HAVE_MIPSFPU)
318+ ff_iir_filter_init_mips(f);
319+}
320+
314321 #ifdef TEST
315322 #include <stdio.h>
316323
libavcodec/iirfilter.h+23−0
@@ -47,6 +47,29 @@ enum IIRFilterMode{ · 46 unmodified lines
4747 FF_FILTER_MODE_BANDSTOP,
4848 };
4949
50+typedef struct FFIIRFilterContext {
51+ /**
52+ * Perform IIR filtering on floating-point input samples.
53+ *
54+ * @param coeffs pointer to filter coefficients
55+ * @param state pointer to filter state
56+ * @param size input length
57+ * @param src source samples
58+ * @param sstep source stride
59+ * @param dst filtered samples (destination may be the same as input)
60+ * @param dstep destination stride
61+ */
62+ void (*filter_flt)(const struct FFIIRFilterCoeffs *coeffs,
63+ struct FFIIRFilterState *state, int size,
64+ const float *src, int sstep, float *dst, int dstep);
65+} FFIIRFilterContext;
66+
67+/**
68+ * Initialize FFIIRFilterContext
69+ */
70+void ff_iir_filter_init(FFIIRFilterContext *f);
71+void ff_iir_filter_init_mips(FFIIRFilterContext *f);
72+
5073 /**
5174 * Initialize filter coefficients.
5275 *
libavcodec/mips/Makefile+1−0
@@ -18,3 +18,4 @@ OBJS-$(CONFIG_AAC_DECODER) += mips/aacdec_mips.o \ · 17 unmodified lines
1818 mips/sbrdsp_mips.o \
1919 mips/aacpsdsp_mips.o
2020 MIPSDSPR1-OBJS-$(CONFIG_AAC_ENCODER) += mips/aaccoder_mips.o
21+MIPSFPU-OBJS-$(CONFIG_AAC_ENCODER) += mips/iirfilter_mips.o
libavcodec/mips/iirfilter_mips.c+204−0
@@ -0,0 +1,204 @@
1+/*
2+ * Copyright (c) 2012
3+ * MIPS Technologies, Inc., California.
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions
7+ * are met:
8+ * 1. Redistributions of source code must retain the above copyright
9+ * notice, this list of conditions and the following disclaimer.
10+ * 2. Redistributions in binary form must reproduce the above copyright
11+ * notice, this list of conditions and the following disclaimer in the
12+ * documentation and/or other materials provided with the distribution.
13+ * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
14+ * contributors may be used to endorse or promote products derived from
15+ * this software without specific prior written permission.
16+ *
17+ * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
18+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+ * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
21+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27+ * SUCH DAMAGE.
28+ *
29+ * Author: Bojan Zivkovic (bojan@mips.com)
30+ *
31+ * IIR filter optimized for MIPS floating-point architecture
32+ *
33+ * This file is part of FFmpeg.
34+ *
35+ * FFmpeg is free software; you can redistribute it and/or
36+ * modify it under the terms of the GNU Lesser General Public
37+ * License as published by the Free Software Foundation; either
38+ * version 2.1 of the License, or (at your option) any later version.
39+ *
40+ * FFmpeg is distributed in the hope that it will be useful,
41+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
42+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43+ * Lesser General Public License for more details.
44+ *
45+ * You should have received a copy of the GNU Lesser General Public
46+ * License along with FFmpeg; if not, write to the Free Software
47+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
48+ */
49+
50+ /**
51+ * @file
52+ * Reference: libavcodec/iirfilter.c
53+ */
54+
55+#include "libavcodec/iirfilter.h"
56+
57+#if HAVE_INLINE_ASM
58+typedef struct FFIIRFilterCoeffs {
59+ int order;
60+ float gain;
61+ int *cx;
62+ float *cy;
63+} FFIIRFilterCoeffs;
64+
65+typedef struct FFIIRFilterState {
66+ float x[1];
67+} FFIIRFilterState;
68+
69+static void ff_iir_filter_flt_mips(const struct FFIIRFilterCoeffs *c,
70+ struct FFIIRFilterState *s, int size,
71+ const float *src, int sstep, float *dst, int dstep)
72+{
73+ if (c->order == 2) {
74+ int i;
75+ const float *src0 = src;
76+ float *dst0 = dst;
77+ for (i = 0; i < size; i++) {
78+ float in = *src0 * c->gain + s->x[0] * c->cy[0] + s->x[1] * c->cy[1];
79+ *dst0 = s->x[0] + in + s->x[1] * c->cx[1];
80+ s->x[0] = s->x[1];
81+ s->x[1] = in;
82+ src0 += sstep;
83+ dst0 += dstep;
84+ }
85+ } else if (c->order == 4) {
86+ int i;
87+ const float *src0 = src;
88+ float *dst0 = dst;
89+ float four = 4.0;
90+ float six = 6.0;
91+ for (i = 0; i < size; i += 4) {
92+ float in1, in2, in3, in4;
93+ float res1, res2, res3, res4;
94+ float *x = s->x;
95+ float *cy = c->cy;
96+ float gain = c->gain;
97+ float src0_0 = src0[0 ];
98+ float src0_1 = src0[sstep ];
99+ float src0_2 = src0[2*sstep];
100+ float src0_3 = src0[3*sstep];
101+
102+ __asm__ volatile (
103+ "lwc1 $f0, 0(%[cy]) \n\t"
104+ "lwc1 $f4, 0(%[x]) \n\t"
105+ "lwc1 $f5, 4(%[x]) \n\t"
106+ "lwc1 $f6, 8(%[x]) \n\t"
107+ "lwc1 $f7, 12(%[x]) \n\t"
108+ "mul.s %[in1], %[src0_0], %[gain] \n\t"
109+ "mul.s %[in2], %[src0_1], %[gain] \n\t"
110+ "mul.s %[in3], %[src0_2], %[gain] \n\t"
111+ "mul.s %[in4], %[src0_3], %[gain] \n\t"
112+ "lwc1 $f1, 4(%[cy]) \n\t"
113+ "madd.s %[in1], %[in1], $f0, $f4 \n\t"
114+ "madd.s %[in2], %[in2], $f0, $f5 \n\t"
115+ "madd.s %[in3], %[in3], $f0, $f6 \n\t"
116+ "madd.s %[in4], %[in4], $f0, $f7 \n\t"
117+ "lwc1 $f2, 8(%[cy]) \n\t"
118+ "madd.s %[in1], %[in1], $f1, $f5 \n\t"
119+ "madd.s %[in2], %[in2], $f1, $f6 \n\t"
120+ "madd.s %[in3], %[in3], $f1, $f7 \n\t"
121+ "lwc1 $f3, 12(%[cy]) \n\t"
122+ "add.s $f8, $f5, $f7 \n\t"
123+ "madd.s %[in1], %[in1], $f2, $f6 \n\t"
124+ "madd.s %[in2], %[in2], $f2, $f7 \n\t"
125+ "mul.s $f9, $f6, %[six] \n\t"
126+ "mul.s $f10, $f7, %[six] \n\t"
127+ "madd.s %[in1], %[in1], $f3, $f7 \n\t"
128+ "madd.s %[in2], %[in2], $f3, %[in1] \n\t"
129+ "madd.s %[in3], %[in3], $f2, %[in1] \n\t"
130+ "madd.s %[in4], %[in4], $f1, %[in1] \n\t"
131+ "add.s %[res1], $f4, %[in1] \n\t"
132+ "swc1 %[in1], 0(%[x]) \n\t"
133+ "add.s $f0, $f6, %[in1] \n\t"
134+ "madd.s %[in3], %[in3], $f3, %[in2] \n\t"
135+ "madd.s %[in4], %[in4], $f2, %[in2] \n\t"
136+ "add.s %[res2], $f5, %[in2] \n\t"
137+ "madd.s %[res1], %[res1], $f8, %[four] \n\t"
138+ "add.s $f8, $f7, %[in2] \n\t"
139+ "swc1 %[in2], 4(%[x]) \n\t"
140+ "madd.s %[in4], %[in4], $f3, %[in3] \n\t"
141+ "add.s %[res3], $f6, %[in3] \n\t"
142+ "add.s %[res1], %[res1], $f9 \n\t"
143+ "madd.s %[res2], %[res2], $f0, %[four] \n\t"
144+ "swc1 %[in3], 8(%[x]) \n\t"
145+ "add.s %[res4], $f7, %[in4] \n\t"
146+ "madd.s %[res3], %[res3], $f8, %[four] \n\t"
147+ "swc1 %[in4], 12(%[x]) \n\t"
148+ "add.s %[res2], %[res2], $f10 \n\t"
149+ "add.s $f8, %[in1], %[in3] \n\t"
150+ "madd.s %[res3], %[res3], %[in1], %[six] \n\t"
151+ "madd.s %[res4], %[res4], $f8, %[four] \n\t"
152+ "madd.s %[res4], %[res4], %[in2], %[six] \n\t"
153+
154+ : [in1]"=&f"(in1), [in2]"=&f"(in2),
155+ [in3]"=&f"(in3), [in4]"=&f"(in4),
156+ [res1]"=&f"(res1), [res2]"=&f"(res2),
157+ [res3]"=&f"(res3), [res4]"=&f"(res4)
158+ : [src0_0]"f"(src0_0), [src0_1]"f"(src0_1),
159+ [src0_2]"f"(src0_2), [src0_3]"f"(src0_3),
160+ [gain]"f"(gain), [x]"r"(x), [cy]"r"(cy),
161+ [four]"f"(four), [six]"f"(six)
162+ : "$f0", "$f1", "$f2", "$f3",
163+ "$f4", "$f5", "$f6", "$f7",
164+ "$f8", "$f9", "$f10",
165+ "memory"
166+ );
167+
168+ dst0[0 ] = res1;
169+ dst0[sstep ] = res2;
170+ dst0[2*sstep] = res3;
171+ dst0[3*sstep] = res4;
172+
173+ src0 += 4*sstep;
174+ dst0 += 4*dstep;
175+ }
176+ } else {
177+ int i;
178+ const float *src0 = src;
179+ float *dst0 = dst;
180+ for (i = 0; i < size; i++) {
181+ int j;
182+ float in, res;
183+ in = *src0 * c->gain;
184+ for(j = 0; j < c->order; j++)
185+ in += c->cy[j] * s->x[j];
186+ res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1];
187+ for(j = 1; j < c->order >> 1; j++)
188+ res += (s->x[j] + s->x[c->order - j]) * c->cx[j];
189+ for(j = 0; j < c->order - 1; j++)
190+ s->x[j] = s->x[j + 1];
191+ *dst0 = res;
192+ s->x[c->order - 1] = in;
193+ src0 += sstep;
194+ dst0 += dstep;
195+ }
196+ }
197+}
198+#endif /* HAVE_INLINE_ASM */
199+
200+void ff_iir_filter_init_mips(FFIIRFilterContext *f) {
201+#if HAVE_INLINE_ASM
202+ f->filter_flt = ff_iir_filter_flt_mips;
203+#endif /* HAVE_INLINE_ASM */
204+}
libavcodec/psymodel.c+7−2
@@ -88,6 +88,7 @@ typedef struct FFPsyPreprocessContext{ · 87 unmodified lines
8888 float stereo_att;
8989 struct FFIIRFilterCoeffs *fcoeffs;
9090 struct FFIIRFilterState **fstate;
91+ struct FFIIRFilterContext fiir;
9192 }FFPsyPreprocessContext;
9293
9394 #define FILT_ORDER 4
@@ -115,6 +116,9 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av · 21 unmodified lines
115116 for (i = 0; i < avctx->channels; i++)
116117 ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER);
117118 }
119+
120+ ff_iir_filter_init(&ctx->fiir);
121+
118122 return ctx;
119123 }
120124
@@ -122,11 +126,12 @@ void ff_psy_preprocess(struct FFPsyPreprocessContext *ctx, float **audio, int ch · 1 unmodified line
122126 {
123127 int ch;
124128 int frame_size = ctx->avctx->frame_size;
129+ FFIIRFilterContext *iir = &ctx->fiir;
125130
126131 if (ctx->fstate) {
127132 for (ch = 0; ch < channels; ch++)
128− ff_iir_filter_flt(ctx->fcoeffs, ctx->fstate[ch], frame_size,
129− &audio[ch][frame_size], 1, &audio[ch][frame_size], 1);
133+ iir->filter_flt(ctx->fcoeffs, ctx->fstate[ch], frame_size,
134+ &audio[ch][frame_size], 1, &audio[ch][frame_size], 1);
130135 }
131136 }
132137

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t