FFmpeg  4.0
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 "libavcodec/aacpsdsp.h"
20 
21 #include "checkasm.h"
22 
23 #define N 32
24 #define STRIDE 128
25 #define BUF_SIZE (N * STRIDE)
26 
27 #define randomize(buf, len) do { \
28  int i; \
29  for (i = 0; i < len; i++) { \
30  const INTFLOAT f = (INTFLOAT)rnd() / UINT_MAX; \
31  (buf)[i] = f; \
32  } \
33 } while (0)
34 
35 #define EPS 0.005
36 
37 static void test_add_squares(void)
38 {
42 
43  declare_func(void, INTFLOAT *dst,
44  const INTFLOAT (*src)[2], int n);
45 
46  randomize((INTFLOAT *)src, BUF_SIZE * 2);
47  randomize(dst0, BUF_SIZE);
48  memcpy(dst1, dst0, BUF_SIZE * sizeof(INTFLOAT));
49  call_ref(dst0, src, BUF_SIZE);
50  call_new(dst1, src, BUF_SIZE);
51  if (!float_near_abs_eps_array(dst0, dst1, EPS, BUF_SIZE))
52  fail();
53  bench_new(dst1, src, BUF_SIZE);
54 }
55 
56 static void test_mul_pair_single(void)
57 {
58  LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
59  LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
62 
63  declare_func(void, INTFLOAT (*dst)[2],
64  INTFLOAT (*src0)[2], INTFLOAT *src1, int n);
65 
67  randomize(src1, BUF_SIZE);
68  call_ref(dst0, src0, src1, BUF_SIZE);
69  call_new(dst1, src0, src1, BUF_SIZE);
70  if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
71  fail();
72  bench_new(dst1, src0, src1, BUF_SIZE);
73 }
74 
75 static void test_hybrid_analysis(void)
76 {
77  LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
78  LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
79  LOCAL_ALIGNED_16(INTFLOAT, in, [13], [2]);
80  LOCAL_ALIGNED_16(INTFLOAT, filter, [N], [8][2]);
81 
82  declare_func(void, INTFLOAT (*out)[2], INTFLOAT (*in)[2],
83  const INTFLOAT (*filter)[8][2],
84  ptrdiff_t stride, int n);
85 
86  randomize((INTFLOAT *)in, 13 * 2);
87  randomize((INTFLOAT *)filter, N * 8 * 2);
88 
89  randomize((INTFLOAT *)dst0, BUF_SIZE * 2);
90  memcpy(dst1, dst0, BUF_SIZE * 2 * sizeof(INTFLOAT));
91 
92  call_ref(dst0, in, filter, STRIDE, N);
93  call_new(dst1, in, filter, STRIDE, N);
94 
95  if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
96  fail();
97  bench_new(dst1, in, filter, STRIDE, N);
98 }
99 
101 {
102  LOCAL_ALIGNED_16(INTFLOAT, in, [2], [38][64]);
103  LOCAL_ALIGNED_16(INTFLOAT, out0, [91], [32][2]);
104  LOCAL_ALIGNED_16(INTFLOAT, out1, [91], [32][2]);
105 
106  declare_func(void, INTFLOAT (*out)[32][2], INTFLOAT L[2][38][64],
107  int i, int len);
108 
109  randomize((INTFLOAT *)out0, 91 * 32 * 2);
110  randomize((INTFLOAT *)in, 2 * 38 * 64);
111  memcpy(out1, out0, 91 * 32 * 2 * sizeof(INTFLOAT));
112 
113  /* len is hardcoded to 32 as that's the only value used in
114  libavcodec. asm functions are likely to be optimized
115  hardcoding this value in their loops and could fail with
116  anything else.
117  i is hardcoded to the two values currently used by the
118  aac decoder because the arm neon implementation is
119  micro-optimized for them and will fail for almost every
120  other value. */
121  call_ref(out0, in, 3, 32);
122  call_new(out1, in, 3, 32);
123 
124  /* the function just moves data around, so memcmp is enough */
125  if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
126  fail();
127 
128  call_ref(out0, in, 5, 32);
129  call_new(out1, in, 5, 32);
130 
131  if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
132  fail();
133 
134  bench_new(out1, in, 3, 32);
135 }
136 
138 {
139  LOCAL_ALIGNED_16(INTFLOAT, out0, [2], [38][64]);
140  LOCAL_ALIGNED_16(INTFLOAT, out1, [2], [38][64]);
141  LOCAL_ALIGNED_16(INTFLOAT, in, [91], [32][2]);
142 
143  declare_func(void, INTFLOAT out[2][38][64], INTFLOAT (*in)[32][2],
144  int i, int len);
145 
146  randomize((INTFLOAT *)in, 91 * 32 * 2);
147  randomize((INTFLOAT *)out0, 2 * 38 * 64);
148  memcpy(out1, out0, 2 * 38 * 64 * sizeof(INTFLOAT));
149 
150  /* len is hardcoded to 32 as that's the only value used in
151  libavcodec. asm functions are likely to be optimized
152  hardcoding this value in their loops and could fail with
153  anything else.
154  i is hardcoded to the two values currently used by the
155  aac decoder because the arm neon implementation is
156  micro-optimized for them and will fail for almost every
157  other value. */
158  call_ref(out0, in, 3, 32);
159  call_new(out1, in, 3, 32);
160 
161  /* the function just moves data around, so memcmp is enough */
162  if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
163  fail();
164 
165  call_ref(out0, in, 5, 32);
166  call_new(out1, in, 5, 32);
167 
168  if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
169  fail();
170 
171  bench_new(out1, in, 3, 32);
172 }
173 
175 {
176  int i;
177  LOCAL_ALIGNED_16(INTFLOAT, l, [BUF_SIZE], [2]);
179  LOCAL_ALIGNED_16(INTFLOAT, l0, [BUF_SIZE], [2]);
180  LOCAL_ALIGNED_16(INTFLOAT, r0, [BUF_SIZE], [2]);
181  LOCAL_ALIGNED_16(INTFLOAT, l1, [BUF_SIZE], [2]);
182  LOCAL_ALIGNED_16(INTFLOAT, r1, [BUF_SIZE], [2]);
183  LOCAL_ALIGNED_16(INTFLOAT, h, [2], [4]);
184  LOCAL_ALIGNED_16(INTFLOAT, h_step, [2], [4]);
185 
186  declare_func(void, INTFLOAT (*l)[2], INTFLOAT (*r)[2],
187  INTFLOAT h[2][4], INTFLOAT h_step[2][4], int len);
188 
189  randomize((INTFLOAT *)l, BUF_SIZE * 2);
190  randomize((INTFLOAT *)r, BUF_SIZE * 2);
191 
192  for (i = 0; i < 2; i++) {
193  if (check_func(psdsp->stereo_interpolate[i], "ps_stereo_interpolate%s", i ? "_ipdopd" : "")) {
194  memcpy(l0, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
195  memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
196  memcpy(r0, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
197  memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
198 
199  randomize((INTFLOAT *)h, 2 * 4);
200  randomize((INTFLOAT *)h_step, 2 * 4);
201 
202  call_ref(l0, r0, h, h_step, BUF_SIZE);
203  call_new(l1, r1, h, h_step, BUF_SIZE);
204  if (!float_near_abs_eps_array((float *)l0, (float *)l1, EPS, BUF_SIZE * 2) ||
205  !float_near_abs_eps_array((float *)r0, (float *)r1, EPS, BUF_SIZE * 2))
206  fail();
207 
208  memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
209  memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
210  bench_new(l1, r1, h, h_step, BUF_SIZE);
211  }
212  }
213 }
214 
216 {
217  PSDSPContext psdsp;
218 
219  ff_psdsp_init(&psdsp);
220 
221  if (check_func(psdsp.add_squares, "ps_add_squares"))
223  report("add_squares");
224 
225  if (check_func(psdsp.mul_pair_single, "ps_mul_pair_single"))
227  report("mul_pair_single");
228 
229  if (check_func(psdsp.hybrid_analysis, "ps_hybrid_analysis"))
231  report("hybrid_analysis");
232 
233  if (check_func(psdsp.hybrid_analysis_ileave, "ps_hybrid_analysis_ileave"))
235  report("hybrid_analysis_ileave");
236 
237  if (check_func(psdsp.hybrid_synthesis_deint, "ps_hybrid_synthesis_deint"))
239  report("hybrid_synthesis_deint");
240 
241  test_stereo_interpolate(&psdsp);
242  report("stereo_interpolate");
243 }
void AAC_RENAME() ff_psdsp_init(PSDSPContext *s)
void(* mul_pair_single)(INTFLOAT(*dst)[2], INTFLOAT(*src0)[2], INTFLOAT *src1, int n)
Definition: aacpsdsp.h:34
int float_near_abs_eps_array(const float *a, const float *b, float eps, unsigned len)
Definition: checkasm.c:305
#define EPS
Definition: aacpsdsp.c:35
#define N
Definition: aacpsdsp.c:23
#define src
Definition: vp8dsp.c:254
int stride
Definition: mace.c:144
void(* hybrid_synthesis_deint)(INTFLOAT out[2][38][64], INTFLOAT(*in)[32][2], int i, int len)
Definition: aacpsdsp.h:41
#define report
Definition: checkasm.h:119
void checkasm_check_aacpsdsp(void)
Definition: aacpsdsp.c:215
float INTFLOAT
Definition: aac_defines.h:86
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhd.c:114
static void test_hybrid_synthesis_deint(void)
Definition: aacpsdsp.c:137
void(* add_squares)(INTFLOAT *dst, const INTFLOAT(*src)[2], int n)
Definition: aacpsdsp.h:33
#define declare_func(ret,...)
Definition: checkasm.h:111
const char * r
Definition: vf_curves.c:111
void(* hybrid_analysis)(INTFLOAT(*out)[2], INTFLOAT(*in)[2], const INTFLOAT(*filter)[8][2], ptrdiff_t stride, int n)
Definition: aacpsdsp.h:36
#define STRIDE
Definition: aacpsdsp.c:24
#define fail()
Definition: checkasm.h:116
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
int n
Definition: avisynth_c.h:684
#define L(x)
Definition: vp56_arith.h:36
#define call_ref(...)
Definition: checkasm.h:122
static void test_hybrid_analysis_ileave(void)
Definition: aacpsdsp.c:100
static void test_add_squares(void)
Definition: aacpsdsp.c:37
static void test_mul_pair_single(void)
Definition: aacpsdsp.c:56
#define src1
Definition: h264pred.c:139
#define randomize(buf, len)
Definition: aacpsdsp.c:27
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define check_func(func,...)
Definition: checkasm.h:107
#define BUF_SIZE
Definition: aacpsdsp.c:25
#define src0
Definition: h264pred.c:138
void(* hybrid_analysis_ileave)(INTFLOAT(*out)[32][2], INTFLOAT L[2][38][64], int i, int len)
Definition: aacpsdsp.h:39
static void test_stereo_interpolate(PSDSPContext *psdsp)
Definition: aacpsdsp.c:174
int len
#define bench_new(...)
Definition: checkasm.h:249
static void test_hybrid_analysis(void)
Definition: aacpsdsp.c:75
FILE * out
Definition: movenc.c:54
#define LOCAL_ALIGNED_16(t, v,...)
Definition: internal.h:131
#define call_new(...)
Definition: checkasm.h:189