FFmpeg
aacpsdsp.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <string.h>
20 
21 #include "libavcodec/aacpsdsp.h"
22 #include "libavutil/intfloat.h"
23 #include "libavutil/mem_internal.h"
24 
25 #include "checkasm.h"
26 
27 #define N 32
28 #define STRIDE 128
29 #define BUF_SIZE (N * STRIDE)
30 
31 #define randomize(buf, len) do { \
32  int i; \
33  for (i = 0; i < len; i++) { \
34  const INTFLOAT f = (INTFLOAT)rnd() / UINT_MAX; \
35  (buf)[i] = f; \
36  } \
37 } while (0)
38 
39 #define EPS 0.005
40 
41 static void clear_less_significant_bits(INTFLOAT *buf, int len, int bits)
42 {
43  int i;
44  for (i = 0; i < len; i++) {
45  union av_intfloat32 u = { .f = buf[i] };
46  u.i &= (0xffffffff << bits);
47  buf[i] = u.f;
48  }
49 }
50 
51 static void test_add_squares(void)
52 {
56 
57  declare_func(void, INTFLOAT *dst,
58  const INTFLOAT (*src)[2], int n);
59 
60  randomize((INTFLOAT *)src, BUF_SIZE * 2);
61  randomize(dst0, BUF_SIZE);
62  memcpy(dst1, dst0, BUF_SIZE * sizeof(INTFLOAT));
63  call_ref(dst0, src, BUF_SIZE);
64  call_new(dst1, src, BUF_SIZE);
65  if (!float_near_abs_eps_array(dst0, dst1, EPS, BUF_SIZE))
66  fail();
67  bench_new(dst1, src, BUF_SIZE);
68 }
69 
70 static void test_mul_pair_single(void)
71 {
72  LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
73  LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
76 
77  declare_func(void, INTFLOAT (*dst)[2],
78  INTFLOAT (*src0)[2], INTFLOAT *src1, int n);
79 
82  call_ref(dst0, src0, src1, BUF_SIZE);
83  call_new(dst1, src0, src1, BUF_SIZE);
84  if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
85  fail();
86  bench_new(dst1, src0, src1, BUF_SIZE);
87 }
88 
89 static void test_hybrid_analysis(void)
90 {
91  LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
92  LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
93  LOCAL_ALIGNED_16(INTFLOAT, in, [13], [2]);
94  LOCAL_ALIGNED_16(INTFLOAT, filter, [N], [8][2]);
95 
96  declare_func(void, INTFLOAT (*out)[2], INTFLOAT (*in)[2],
97  const INTFLOAT (*filter)[8][2],
98  ptrdiff_t stride, int n);
99 
100  randomize((INTFLOAT *)in, 13 * 2);
101  randomize((INTFLOAT *)filter, N * 8 * 2);
102 
103  randomize((INTFLOAT *)dst0, BUF_SIZE * 2);
104  memcpy(dst1, dst0, BUF_SIZE * 2 * sizeof(INTFLOAT));
105 
106  call_ref(dst0, in, filter, STRIDE, N);
107  call_new(dst1, in, filter, STRIDE, N);
108 
109  if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
110  fail();
111  bench_new(dst1, in, filter, STRIDE, N);
112 }
113 
115 {
116  LOCAL_ALIGNED_16(INTFLOAT, in, [2], [38][64]);
117  LOCAL_ALIGNED_16(INTFLOAT, out0, [91], [32][2]);
118  LOCAL_ALIGNED_16(INTFLOAT, out1, [91], [32][2]);
119 
120  declare_func(void, INTFLOAT (*out)[32][2], INTFLOAT L[2][38][64],
121  int i, int len);
122 
123  randomize((INTFLOAT *)out0, 91 * 32 * 2);
124  randomize((INTFLOAT *)in, 2 * 38 * 64);
125  memcpy(out1, out0, 91 * 32 * 2 * sizeof(INTFLOAT));
126 
127  /* len is hardcoded to 32 as that's the only value used in
128  libavcodec. asm functions are likely to be optimized
129  hardcoding this value in their loops and could fail with
130  anything else.
131  i is hardcoded to the two values currently used by the
132  aac decoder because the arm neon implementation is
133  micro-optimized for them and will fail for almost every
134  other value. */
135  call_ref(out0, in, 3, 32);
136  call_new(out1, in, 3, 32);
137 
138  /* the function just moves data around, so memcmp is enough */
139  if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
140  fail();
141 
142  call_ref(out0, in, 5, 32);
143  call_new(out1, in, 5, 32);
144 
145  if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
146  fail();
147 
148  bench_new(out1, in, 3, 32);
149 }
150 
152 {
153  LOCAL_ALIGNED_16(INTFLOAT, out0, [2], [38][64]);
154  LOCAL_ALIGNED_16(INTFLOAT, out1, [2], [38][64]);
155  LOCAL_ALIGNED_16(INTFLOAT, in, [91], [32][2]);
156 
157  declare_func(void, INTFLOAT out[2][38][64], INTFLOAT (*in)[32][2],
158  int i, int len);
159 
160  randomize((INTFLOAT *)in, 91 * 32 * 2);
161  randomize((INTFLOAT *)out0, 2 * 38 * 64);
162  memcpy(out1, out0, 2 * 38 * 64 * sizeof(INTFLOAT));
163 
164  /* len is hardcoded to 32 as that's the only value used in
165  libavcodec. asm functions are likely to be optimized
166  hardcoding this value in their loops and could fail with
167  anything else.
168  i is hardcoded to the two values currently used by the
169  aac decoder because the arm neon implementation is
170  micro-optimized for them and will fail for almost every
171  other value. */
172  call_ref(out0, in, 3, 32);
173  call_new(out1, in, 3, 32);
174 
175  /* the function just moves data around, so memcmp is enough */
176  if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
177  fail();
178 
179  call_ref(out0, in, 5, 32);
180  call_new(out1, in, 5, 32);
181 
182  if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
183  fail();
184 
185  bench_new(out1, in, 3, 32);
186 }
187 
189 {
190  int i;
191  LOCAL_ALIGNED_16(INTFLOAT, l, [BUF_SIZE], [2]);
193  LOCAL_ALIGNED_16(INTFLOAT, l0, [BUF_SIZE], [2]);
194  LOCAL_ALIGNED_16(INTFLOAT, r0, [BUF_SIZE], [2]);
195  LOCAL_ALIGNED_16(INTFLOAT, l1, [BUF_SIZE], [2]);
196  LOCAL_ALIGNED_16(INTFLOAT, r1, [BUF_SIZE], [2]);
197  LOCAL_ALIGNED_16(INTFLOAT, h, [2], [4]);
198  LOCAL_ALIGNED_16(INTFLOAT, h_step, [2], [4]);
199 
200  declare_func(void, INTFLOAT (*l)[2], INTFLOAT (*r)[2],
201  INTFLOAT h[2][4], INTFLOAT h_step[2][4], int len);
202 
203  randomize((INTFLOAT *)l, BUF_SIZE * 2);
204  randomize((INTFLOAT *)r, BUF_SIZE * 2);
205 
206  for (i = 0; i < 2; i++) {
207  if (check_func(psdsp->stereo_interpolate[i], "ps_stereo_interpolate%s", i ? "_ipdopd" : "")) {
208  memcpy(l0, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
209  memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
210  memcpy(r0, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
211  memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
212 
213  randomize((INTFLOAT *)h, 2 * 4);
214  randomize((INTFLOAT *)h_step, 2 * 4);
215  // Clear the least significant 14 bits of h_step, to avoid
216  // divergence when accumulating h_step BUF_SIZE times into
217  // a float variable which may or may not have extra intermediate
218  // precision. Therefore clear roughly log2(BUF_SIZE) less
219  // significant bits, to get the same result regardless of any
220  // extra precision in the accumulator.
221  clear_less_significant_bits((INTFLOAT *)h_step, 2 * 4, 14);
222 
223  call_ref(l0, r0, h, h_step, BUF_SIZE);
224  call_new(l1, r1, h, h_step, BUF_SIZE);
225  if (!float_near_abs_eps_array((float *)l0, (float *)l1, EPS, BUF_SIZE * 2) ||
226  !float_near_abs_eps_array((float *)r0, (float *)r1, EPS, BUF_SIZE * 2))
227  fail();
228 
229  memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
230  memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
231  bench_new(l1, r1, h, h_step, BUF_SIZE);
232  }
233  }
234 }
235 
237 {
238  PSDSPContext psdsp;
239 
240  ff_psdsp_init(&psdsp);
241 
242  if (check_func(psdsp.add_squares, "ps_add_squares"))
244  report("add_squares");
245 
246  if (check_func(psdsp.mul_pair_single, "ps_mul_pair_single"))
248  report("mul_pair_single");
249 
250  if (check_func(psdsp.hybrid_analysis, "ps_hybrid_analysis"))
252  report("hybrid_analysis");
253 
254  if (check_func(psdsp.hybrid_analysis_ileave, "ps_hybrid_analysis_ileave"))
256  report("hybrid_analysis_ileave");
257 
258  if (check_func(psdsp.hybrid_synthesis_deint, "ps_hybrid_synthesis_deint"))
260  report("hybrid_synthesis_deint");
261 
262  test_stereo_interpolate(&psdsp);
263  report("stereo_interpolate");
264 }
test_hybrid_analysis
static void test_hybrid_analysis(void)
Definition: aacpsdsp.c:89
r
const char * r
Definition: vf_curves.c:127
N
#define N
Definition: aacpsdsp.c:27
mem_internal.h
test_mul_pair_single
static void test_mul_pair_single(void)
Definition: aacpsdsp.c:70
out
static FILE * out
Definition: movenc.c:55
randomize
#define randomize(buf, len)
Definition: aacpsdsp.c:31
src1
const pixel * src1
Definition: h264pred_template.c:420
test_add_squares
static void test_add_squares(void)
Definition: aacpsdsp.c:51
u
#define u(width, name, range_min, range_max)
Definition: cbs_apv.c:68
checkasm_check_aacpsdsp
void checkasm_check_aacpsdsp(void)
Definition: aacpsdsp.c:236
BUF_SIZE
#define BUF_SIZE
Definition: aacpsdsp.c:29
check_func
#define check_func
Definition: test.h:480
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
bench_new
#define bench_new
Definition: test.h:486
intfloat.h
call_ref
#define call_ref
Definition: test.h:484
checkasm.h
aacpsdsp.h
clear_less_significant_bits
static void clear_less_significant_bits(INTFLOAT *buf, int len, int bits)
Definition: aacpsdsp.c:41
declare_func
#define declare_func
Definition: test.h:488
bits
uint8_t bits
Definition: vp3data.h:128
LOCAL_ALIGNED_16
#define LOCAL_ALIGNED_16(t, v,...)
Definition: mem_internal.h:130
PSDSPContext::hybrid_analysis
void(* hybrid_analysis)(INTFLOAT(*restrict out)[2], INTFLOAT(*in)[2], const INTFLOAT(*filter)[8][2], ptrdiff_t stride, int n)
Definition: aacpsdsp.h:36
fail
#define fail
Definition: test.h:478
PSDSPContext::add_squares
void(* add_squares)(INTFLOAT *restrict dst, const INTFLOAT(*src)[2], int n)
Definition: aacpsdsp.h:33
PSDSPContext::hybrid_synthesis_deint
void(* hybrid_synthesis_deint)(INTFLOAT out[2][38][64], INTFLOAT(*restrict in)[32][2], int i, int len)
Definition: aacpsdsp.h:41
PSDSPContext::mul_pair_single
void(* mul_pair_single)(INTFLOAT(*restrict dst)[2], INTFLOAT(*src0)[2], INTFLOAT *src1, int n)
Definition: aacpsdsp.h:34
av_intfloat32
Definition: intfloat.h:27
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
test_hybrid_analysis_ileave
static void test_hybrid_analysis_ileave(void)
Definition: aacpsdsp.c:114
len
int len
Definition: vorbis_enc_data.h:426
call_new
#define call_new
Definition: test.h:485
test_hybrid_synthesis_deint
static void test_hybrid_synthesis_deint(void)
Definition: aacpsdsp.c:151
test_stereo_interpolate
static void test_stereo_interpolate(PSDSPContext *psdsp)
Definition: aacpsdsp.c:188
PSDSPContext::stereo_interpolate
void(* stereo_interpolate[2])(INTFLOAT(*l)[2], INTFLOAT(*r)[2], INTFLOAT h[2][4], INTFLOAT h_step[2][4], int len)
Definition: aacpsdsp.h:49
ff_psdsp_init
void AAC_RENAME() ff_psdsp_init(PSDSPContext *s)
Definition: aacpsdsp_template.c:213
PSDSPContext
Definition: aacpsdsp.h:32
L
#define L(x)
Definition: vpx_arith.h:36
src0
const pixel *const src0
Definition: h264pred_template.c:419
report
#define report
Definition: test.h:479
float_near_abs_eps_array
#define float_near_abs_eps_array
Definition: utils.h:374
h
h
Definition: vp9dsp_template.c:2070
stride
#define stride
Definition: h264pred_template.c:536
PSDSPContext::hybrid_analysis_ileave
void(* hybrid_analysis_ileave)(INTFLOAT(*restrict out)[32][2], INTFLOAT L[2][38][64], int i, int len)
Definition: aacpsdsp.h:39
STRIDE
#define STRIDE
Definition: aacpsdsp.c:28
INTFLOAT
float INTFLOAT
Definition: aac_defines.h:101
src
#define src
Definition: vp8dsp.c:248
EPS
#define EPS
Definition: aacpsdsp.c:39