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 "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 
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 }
stride
int stride
Definition: mace.c:144
test_hybrid_analysis
static void test_hybrid_analysis(void)
Definition: aacpsdsp.c:75
r
const char * r
Definition: vf_curves.c:114
N
#define N
Definition: aacpsdsp.c:23
test_mul_pair_single
static void test_mul_pair_single(void)
Definition: aacpsdsp.c:56
out
FILE * out
Definition: movenc.c:54
n
int n
Definition: avisynth_c.h:760
float_near_abs_eps_array
int float_near_abs_eps_array(const float *a, const float *b, float eps, unsigned len)
Definition: checkasm.c:317
randomize
#define randomize(buf, len)
Definition: aacpsdsp.c:27
test_add_squares
static void test_add_squares(void)
Definition: aacpsdsp.c:37
check_func
#define check_func(func,...)
Definition: checkasm.h:111
checkasm_check_aacpsdsp
void checkasm_check_aacpsdsp(void)
Definition: aacpsdsp.c:215
BUF_SIZE
#define BUF_SIZE
Definition: aacpsdsp.c:25
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
call_ref
#define call_ref(...)
Definition: checkasm.h:126
PSDSPContext::add_squares
void(* add_squares)(INTFLOAT *dst, const INTFLOAT(*src)[2], int n)
Definition: aacpsdsp.h:33
fail
#define fail()
Definition: checkasm.h:120
checkasm.h
src
#define src
Definition: vp8dsp.c:254
aacpsdsp.h
call_new
#define call_new(...)
Definition: checkasm.h:193
PSDSPContext::hybrid_synthesis_deint
void(* hybrid_synthesis_deint)(INTFLOAT out[2][38][64], INTFLOAT(*in)[32][2], int i, int len)
Definition: aacpsdsp.h:41
PSDSPContext::mul_pair_single
void(* mul_pair_single)(INTFLOAT(*dst)[2], INTFLOAT(*src0)[2], INTFLOAT *src1, int n)
Definition: aacpsdsp.h:34
PSDSPContext::hybrid_analysis_ileave
void(* hybrid_analysis_ileave)(INTFLOAT(*out)[32][2], INTFLOAT L[2][38][64], int i, int len)
Definition: aacpsdsp.h:39
src0
#define src0
Definition: h264pred.c:138
src1
#define src1
Definition: h264pred.c:139
in
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)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
report
#define report
Definition: checkasm.h:123
bench_new
#define bench_new(...)
Definition: checkasm.h:253
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
test_hybrid_analysis_ileave
static void test_hybrid_analysis_ileave(void)
Definition: aacpsdsp.c:100
len
int len
Definition: vorbis_enc_data.h:452
test_hybrid_synthesis_deint
static void test_hybrid_synthesis_deint(void)
Definition: aacpsdsp.c:137
test_stereo_interpolate
static void test_stereo_interpolate(PSDSPContext *psdsp)
Definition: aacpsdsp.c:174
L
#define L(x)
Definition: vp56_arith.h:36
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:212
PSDSPContext
Definition: aacpsdsp.h:32
declare_func
#define declare_func(ret,...)
Definition: checkasm.h:115
LOCAL_ALIGNED_16
#define LOCAL_ALIGNED_16(t, v,...)
Definition: internal.h:131
h
h
Definition: vp9dsp_template.c:2038
PSDSPContext::hybrid_analysis
void(* hybrid_analysis)(INTFLOAT(*out)[2], INTFLOAT(*in)[2], const INTFLOAT(*filter)[8][2], ptrdiff_t stride, int n)
Definition: aacpsdsp.h:36
STRIDE
#define STRIDE
Definition: aacpsdsp.c:24
INTFLOAT
float INTFLOAT
Definition: aac_defines.h:86
EPS
#define EPS
Definition: aacpsdsp.c:35