FFmpeg
af_afftfilt.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2.1 of the License,
9  * or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/audio_fifo.h"
22 #include "libavutil/avstring.h"
23 #include "libavfilter/internal.h"
24 #include "libavutil/common.h"
25 #include "libavutil/opt.h"
26 #include "libavcodec/avfft.h"
27 #include "libavutil/eval.h"
28 #include "audio.h"
29 #include "filters.h"
30 #include "window_func.h"
31 
32 typedef struct AFFTFiltContext {
33  const AVClass *class;
34  char *real_str;
35  char *img_str;
36  int fft_size;
37  int fft_bits;
38 
42  int nb_exprs;
47  int64_t pts;
48  int hop_size;
49  float overlap;
51  int eof;
52  int win_func;
55 
56 static const char *const var_names[] = { "sr", "b", "nb", "ch", "chs", "pts", "re", "im", NULL };
58 
59 #define OFFSET(x) offsetof(AFFTFiltContext, x)
60 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
61 
62 static const AVOption afftfilt_options[] = {
63  { "real", "set channels real expressions", OFFSET(real_str), AV_OPT_TYPE_STRING, {.str = "re" }, 0, 0, A },
64  { "imag", "set channels imaginary expressions", OFFSET(img_str), AV_OPT_TYPE_STRING, {.str = "im" }, 0, 0, A },
65  { "win_size", "set window size", OFFSET(fft_size), AV_OPT_TYPE_INT, {.i64=4096}, 16, 131072, A },
66  { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64 = WFUNC_HANNING}, 0, NB_WFUNC-1, A, "win_func" },
67  { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, A, "win_func" },
68  { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, A, "win_func" },
69  { "hann", "Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, A, "win_func" },
70  { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, A, "win_func" },
71  { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, A, "win_func" },
72  { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, A, "win_func" },
73  { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, A, "win_func" },
74  { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, A, "win_func" },
75  { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, A, "win_func" },
76  { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, A, "win_func" },
77  { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, A, "win_func" },
78  { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, A, "win_func" },
79  { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, A, "win_func" },
80  { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, A, "win_func" },
81  { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, A, "win_func" },
82  { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, A, "win_func" },
83  { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, A, "win_func" },
84  { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, A, "win_func" },
85  { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, A, "win_func" },
86  { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, A, "win_func" },
87  { "bohman", "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN}, 0, 0, A, "win_func" },
88  { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, A },
89  { NULL },
90 };
91 
92 AVFILTER_DEFINE_CLASS(afftfilt);
93 
94 static inline double getreal(void *priv, double x, double ch)
95 {
96  AFFTFiltContext *s = priv;
97  int ich, ix;
98 
99  ich = av_clip(ch, 0, s->nb_exprs - 1);
100  ix = av_clip(x, 0, s->window_size / 2);
101 
102  return s->fft_data[ich][ix].re;
103 }
104 
105 static inline double getimag(void *priv, double x, double ch)
106 {
107  AFFTFiltContext *s = priv;
108  int ich, ix;
109 
110  ich = av_clip(ch, 0, s->nb_exprs - 1);
111  ix = av_clip(x, 0, s->window_size / 2);
112 
113  return s->fft_data[ich][ix].im;
114 }
115 
116 static double realf(void *priv, double x, double ch) { return getreal(priv, x, ch); }
117 static double imagf(void *priv, double x, double ch) { return getimag(priv, x, ch); }
118 
119 static const char *const func2_names[] = { "real", "imag", NULL };
120 double (*func2[])(void *, double, double) = { realf, imagf, NULL };
121 
123 {
124  AVFilterContext *ctx = inlink->dst;
125  AFFTFiltContext *s = ctx->priv;
126  char *saveptr = NULL;
127  int ret = 0, ch;
128  float overlap;
129  char *args;
130  const char *last_expr = "1";
131 
132  s->pts = AV_NOPTS_VALUE;
133  s->fft_bits = av_log2(s->fft_size);
134  s->fft = av_fft_init(s->fft_bits, 0);
135  s->ifft = av_fft_init(s->fft_bits, 1);
136  if (!s->fft || !s->ifft)
137  return AVERROR(ENOMEM);
138 
139  s->window_size = 1 << s->fft_bits;
140 
141  s->fft_data = av_calloc(inlink->channels, sizeof(*s->fft_data));
142  if (!s->fft_data)
143  return AVERROR(ENOMEM);
144 
145  s->fft_temp = av_calloc(inlink->channels, sizeof(*s->fft_temp));
146  if (!s->fft_temp)
147  return AVERROR(ENOMEM);
148 
149  for (ch = 0; ch < inlink->channels; ch++) {
150  s->fft_data[ch] = av_calloc(s->window_size, sizeof(**s->fft_data));
151  if (!s->fft_data[ch])
152  return AVERROR(ENOMEM);
153  }
154 
155  for (ch = 0; ch < inlink->channels; ch++) {
156  s->fft_temp[ch] = av_calloc(s->window_size, sizeof(**s->fft_temp));
157  if (!s->fft_temp[ch])
158  return AVERROR(ENOMEM);
159  }
160 
161  s->real = av_calloc(inlink->channels, sizeof(*s->real));
162  if (!s->real)
163  return AVERROR(ENOMEM);
164 
165  s->imag = av_calloc(inlink->channels, sizeof(*s->imag));
166  if (!s->imag)
167  return AVERROR(ENOMEM);
168 
169  args = av_strdup(s->real_str);
170  if (!args)
171  return AVERROR(ENOMEM);
172 
173  for (ch = 0; ch < inlink->channels; ch++) {
174  char *arg = av_strtok(ch == 0 ? args : NULL, "|", &saveptr);
175 
176  ret = av_expr_parse(&s->real[ch], arg ? arg : last_expr, var_names,
177  NULL, NULL, func2_names, func2, 0, ctx);
178  if (ret < 0)
179  break;
180  if (arg)
181  last_expr = arg;
182  s->nb_exprs++;
183  }
184 
185  av_free(args);
186 
187  args = av_strdup(s->img_str ? s->img_str : s->real_str);
188  if (!args)
189  return AVERROR(ENOMEM);
190 
191  for (ch = 0; ch < inlink->channels; ch++) {
192  char *arg = av_strtok(ch == 0 ? args : NULL, "|", &saveptr);
193 
194  ret = av_expr_parse(&s->imag[ch], arg ? arg : last_expr, var_names,
195  NULL, NULL, func2_names, func2, 0, ctx);
196  if (ret < 0)
197  break;
198  if (arg)
199  last_expr = arg;
200  }
201 
202  av_free(args);
203 
204  s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size);
205  if (!s->fifo)
206  return AVERROR(ENOMEM);
207 
209  sizeof(*s->window_func_lut));
210  if (!s->window_func_lut)
211  return AVERROR(ENOMEM);
213  if (s->overlap == 1)
214  s->overlap = overlap;
215 
216  s->hop_size = s->window_size * (1 - s->overlap);
217  if (s->hop_size <= 0)
218  return AVERROR(EINVAL);
219 
220  s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2);
221  if (!s->buffer)
222  return AVERROR(ENOMEM);
223 
224  return ret;
225 }
226 
228 {
229  AVFilterContext *ctx = inlink->dst;
230  AVFilterLink *outlink = ctx->outputs[0];
231  AFFTFiltContext *s = ctx->priv;
232  const int window_size = s->window_size;
233  const float f = 1. / (s->window_size / 2);
234  double values[VAR_VARS_NB];
235  AVFrame *out, *in = NULL;
236  int ch, n, ret, i;
237 
238  if (!in) {
239  in = ff_get_audio_buffer(outlink, window_size);
240  if (!in)
241  return AVERROR(ENOMEM);
242  }
243 
244  ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size);
245  if (ret < 0)
246  goto fail;
247 
248  for (ch = 0; ch < inlink->channels; ch++) {
249  const float *src = (float *)in->extended_data[ch];
250  FFTComplex *fft_data = s->fft_data[ch];
251 
252  for (n = 0; n < in->nb_samples; n++) {
253  fft_data[n].re = src[n] * s->window_func_lut[n];
254  fft_data[n].im = 0;
255  }
256 
257  for (; n < window_size; n++) {
258  fft_data[n].re = 0;
259  fft_data[n].im = 0;
260  }
261  }
262 
263  values[VAR_PTS] = s->pts;
264  values[VAR_SAMPLE_RATE] = inlink->sample_rate;
265  values[VAR_NBBINS] = window_size / 2;
266  values[VAR_CHANNELS] = inlink->channels;
267 
268  for (ch = 0; ch < inlink->channels; ch++) {
270 
271  av_fft_permute(s->fft, fft_data);
272  av_fft_calc(s->fft, fft_data);
273  }
274 
275  for (ch = 0; ch < inlink->channels; ch++) {
278  float *buf = (float *)s->buffer->extended_data[ch];
279  int x;
280  values[VAR_CHANNEL] = ch;
281 
282  for (n = 0; n <= window_size / 2; n++) {
283  float fr, fi;
284 
285  values[VAR_BIN] = n;
286  values[VAR_REAL] = fft_data[n].re;
287  values[VAR_IMAG] = fft_data[n].im;
288 
289  fr = av_expr_eval(s->real[ch], values, s);
290  fi = av_expr_eval(s->imag[ch], values, s);
291 
292  fft_temp[n].re = fr;
293  fft_temp[n].im = fi;
294  }
295 
296  for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) {
297  fft_temp[n].re = fft_temp[x].re;
298  fft_temp[n].im = -fft_temp[x].im;
299  }
300 
301  av_fft_permute(s->ifft, fft_temp);
302  av_fft_calc(s->ifft, fft_temp);
303 
304  for (i = 0; i < window_size; i++) {
305  buf[i] += s->fft_temp[ch][i].re * f;
306  }
307  }
308 
309  out = ff_get_audio_buffer(outlink, s->hop_size);
310  if (!out) {
311  ret = AVERROR(ENOMEM);
312  goto fail;
313  }
314 
315  out->pts = s->pts;
316  s->pts += s->hop_size;
317 
318  for (ch = 0; ch < inlink->channels; ch++) {
319  float *dst = (float *)out->extended_data[ch];
320  float *buf = (float *)s->buffer->extended_data[ch];
321 
322  for (n = 0; n < s->hop_size; n++)
323  dst[n] = buf[n] * (1.f - s->overlap);
324  memmove(buf, buf + s->hop_size, window_size * 4);
325  }
326 
327  ret = ff_filter_frame(outlink, out);
328  if (ret < 0)
329  goto fail;
330 
332 
333 fail:
334  av_frame_free(&in);
335  return ret < 0 ? ret : 0;
336 }
337 
339 {
340  AVFilterLink *inlink = ctx->inputs[0];
341  AVFilterLink *outlink = ctx->outputs[0];
342  AFFTFiltContext *s = ctx->priv;
343  AVFrame *in = NULL;
344  int ret = 0, status;
345  int64_t pts;
346 
347  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
348 
349  if (!s->eof && av_audio_fifo_size(s->fifo) < s->window_size) {
350  ret = ff_inlink_consume_frame(inlink, &in);
351  if (ret < 0)
352  return ret;
353 
354  if (ret > 0) {
355  ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data,
356  in->nb_samples);
357  if (ret >= 0 && s->pts == AV_NOPTS_VALUE)
358  s->pts = in->pts;
359 
360  av_frame_free(&in);
361  if (ret < 0)
362  return ret;
363  }
364  }
365 
366  if ((av_audio_fifo_size(s->fifo) >= s->window_size) ||
367  (av_audio_fifo_size(s->fifo) > 0 && s->eof)) {
368  ret = filter_frame(inlink);
369  if (av_audio_fifo_size(s->fifo) >= s->window_size)
370  ff_filter_set_ready(ctx, 100);
371  return ret;
372  }
373 
374  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
375  if (status == AVERROR_EOF) {
376  s->eof = 1;
377  if (av_audio_fifo_size(s->fifo) >= 0) {
378  ff_filter_set_ready(ctx, 100);
379  return 0;
380  }
381  }
382  }
383 
384  if (s->eof && av_audio_fifo_size(s->fifo) <= 0) {
385  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
386  return 0;
387  }
388 
389  if (!s->eof)
390  FF_FILTER_FORWARD_WANTED(outlink, inlink);
391 
392  return FFERROR_NOT_READY;
393 }
394 
396 {
399  static const enum AVSampleFormat sample_fmts[] = {
402  };
403  int ret;
404 
405  layouts = ff_all_channel_counts();
406  if (!layouts)
407  return AVERROR(ENOMEM);
408  ret = ff_set_common_channel_layouts(ctx, layouts);
409  if (ret < 0)
410  return ret;
411 
412  formats = ff_make_format_list(sample_fmts);
413  if (!formats)
414  return AVERROR(ENOMEM);
415  ret = ff_set_common_formats(ctx, formats);
416  if (ret < 0)
417  return ret;
418 
419  formats = ff_all_samplerates();
420  if (!formats)
421  return AVERROR(ENOMEM);
422  return ff_set_common_samplerates(ctx, formats);
423 }
424 
426 {
427  AFFTFiltContext *s = ctx->priv;
428  int i;
429 
430  av_fft_end(s->fft);
431  av_fft_end(s->ifft);
432 
433  for (i = 0; i < s->nb_exprs; i++) {
434  if (s->fft_data)
435  av_freep(&s->fft_data[i]);
436  if (s->fft_temp)
437  av_freep(&s->fft_temp[i]);
438  }
439  av_freep(&s->fft_data);
440  av_freep(&s->fft_temp);
441 
442  for (i = 0; i < s->nb_exprs; i++) {
443  av_expr_free(s->real[i]);
444  av_expr_free(s->imag[i]);
445  }
446 
447  av_freep(&s->real);
448  av_freep(&s->imag);
449  av_frame_free(&s->buffer);
451 
453 }
454 
455 static const AVFilterPad inputs[] = {
456  {
457  .name = "default",
458  .type = AVMEDIA_TYPE_AUDIO,
459  .config_props = config_input,
460  },
461  { NULL }
462 };
463 
464 static const AVFilterPad outputs[] = {
465  {
466  .name = "default",
467  .type = AVMEDIA_TYPE_AUDIO,
468  },
469  { NULL }
470 };
471 
473  .name = "afftfilt",
474  .description = NULL_IF_CONFIG_SMALL("Apply arbitrary expressions to samples in frequency domain."),
475  .priv_size = sizeof(AFFTFiltContext),
476  .priv_class = &afftfilt_class,
477  .inputs = inputs,
478  .outputs = outputs,
479  .activate = activate,
481  .uninit = uninit,
482 };
float, planar
Definition: samplefmt.h:69
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1481
#define NULL
Definition: coverity.c:32
int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:549
FFTContext * fft
Definition: af_afftfilt.c:39
AVAudioFifo * av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, int nb_samples)
Allocate an AVAudioFifo.
Definition: audio_fifo.c:59
#define av_realloc_f(p, o, n)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
AVAudioFifo * fifo
Definition: af_afftfilt.c:46
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
void av_audio_fifo_free(AVAudioFifo *af)
Free an AVAudioFifo.
Definition: audio_fifo.c:45
AVExpr ** real
Definition: af_afftfilt.c:44
static int config_input(AVFilterLink *inlink)
Definition: af_afftfilt.c:122
static const char *const var_names[]
Definition: af_afftfilt.c:56
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(INT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
static double realf(void *priv, double x, double ch)
Definition: af_afftfilt.c:116
int av_log2(unsigned v)
Definition: intmath.c:26
#define OFFSET(x)
Definition: af_afftfilt.c:59
FFTSample re
Definition: avfft.h:38
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
static void generate_window_func(float *lut, int N, int win_func, float *overlap)
Definition: window_func.h:36
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:679
return FFERROR_NOT_READY
#define src
Definition: vp8dsp.c:254
static int filter_frame(AVFilterLink *inlink)
Definition: af_afftfilt.c:227
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_afftfilt.c:425
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
AVFilter ff_af_afftfilt
Definition: af_afftfilt.c:472
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
FFTComplex ** fft_data
Definition: af_afftfilt.c:40
#define av_cold
Definition: attributes.h:82
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
Definition: eval.c:157
FFTComplex ** fft_temp
Definition: af_afftfilt.c:41
#define A
Definition: af_afftfilt.c:60
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
A filter pad used for either input or output.
Definition: internal.h:54
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1436
static double imagf(void *priv, double x, double ch)
Definition: af_afftfilt.c:117
AVS_FilterInfo ** fi
Definition: avisynth_c.h:807
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:86
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * priv
private data for use by the filter
Definition: avfilter.h:353
const char * arg
Definition: jacosubdec.c:66
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
#define fail()
Definition: checkasm.h:120
Context for an Audio FIFO Buffer.
Definition: audio_fifo.c:34
int av_audio_fifo_size(AVAudioFifo *af)
Get the current number of samples in the AVAudioFifo available for reading.
Definition: audio_fifo.c:228
Definition: fft.h:88
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return values
static int query_formats(AVFilterContext *ctx)
Definition: af_afftfilt.c:395
AVS_Value args
Definition: avisynth_c.h:775
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:760
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:464
A list of supported channel layouts.
Definition: formats.h:85
static double getreal(void *priv, double x, double ch)
Definition: af_afftfilt.c:94
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:455
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:334
FFT functions.
float * window_func_lut
Definition: af_afftfilt.c:53
double(* func2[])(void *, double, double)
Definition: af_afftfilt.c:120
void * buf
Definition: avisynth_c.h:766
AVExpr ** imag
Definition: af_afftfilt.c:45
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
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
FFTContext * ifft
Definition: af_afftfilt.c:39
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
static const AVOption afftfilt_options[]
Definition: af_afftfilt.c:62
const char * name
Filter name.
Definition: avfilter.h:148
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:395
AVFrame * buffer
Definition: af_afftfilt.c:50
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:112
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
Drain data from an AVAudioFifo.
Definition: audio_fifo.c:201
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:184
FFTSample im
Definition: avfft.h:38
common internal and external API header
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Definition: avfilter.c:193
AVFILTER_DEFINE_CLASS(afftfilt)
FF_FILTER_FORWARD_WANTED(outlink, inlink)
static const char *const func2_names[]
Definition: af_afftfilt.c:119
static double getimag(void *priv, double x, double ch)
Definition: af_afftfilt.c:105
#define av_free(p)
Audio FIFO Buffer.
static int activate(AVFilterContext *ctx)
Definition: af_afftfilt.c:338
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:734
A list of supported formats for one end of a filter link.
Definition: formats.h:64
int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
Peek data from an AVAudioFifo.
Definition: audio_fifo.c:138
An instance of a filter.
Definition: avfilter.h:338
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
FILE * out
Definition: movenc.c:54
#define av_freep(p)
formats
Definition: signature.h:48
internal API functions
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition...
Definition: formats.c:410
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:361
for(j=16;j >0;--j)
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:556
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
simple arithmetic expression evaluator