FFmpeg
avf_showfreqs.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, 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 <float.h>
22 #include <math.h>
23 
24 #include "libavutil/tx.h"
25 #include "libavutil/audio_fifo.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/avstring.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/parseutils.h"
32 #include "audio.h"
33 #include "filters.h"
34 #include "video.h"
35 #include "avfilter.h"
36 #include "internal.h"
37 #include "window_func.h"
38 
44 
45 typedef struct ShowFreqsContext {
46  const AVClass *class;
47  int w, h;
48  int mode;
49  int data_mode;
50  int cmode;
51  int fft_size;
52  int ascale, fscale;
53  int avg;
54  int win_func;
59  float **avg_data;
61  float overlap;
62  float minamp;
63  int hop_size;
65  int nb_freq;
66  int win_size;
67  float scale;
68  char *colors;
70  int64_t pts;
72 
73 #define OFFSET(x) offsetof(ShowFreqsContext, x)
74 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
75 
76 static const AVOption showfreqs_options[] = {
77  { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1024x512"}, 0, 0, FLAGS },
78  { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1024x512"}, 0, 0, FLAGS },
79  { "mode", "set display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=BAR}, 0, NB_MODES-1, FLAGS, "mode" },
80  { "line", "show lines", 0, AV_OPT_TYPE_CONST, {.i64=LINE}, 0, 0, FLAGS, "mode" },
81  { "bar", "show bars", 0, AV_OPT_TYPE_CONST, {.i64=BAR}, 0, 0, FLAGS, "mode" },
82  { "dot", "show dots", 0, AV_OPT_TYPE_CONST, {.i64=DOT}, 0, 0, FLAGS, "mode" },
83  { "ascale", "set amplitude scale", OFFSET(ascale), AV_OPT_TYPE_INT, {.i64=AS_LOG}, 0, NB_ASCALES-1, FLAGS, "ascale" },
84  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=AS_LINEAR}, 0, 0, FLAGS, "ascale" },
85  { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=AS_SQRT}, 0, 0, FLAGS, "ascale" },
86  { "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=AS_CBRT}, 0, 0, FLAGS, "ascale" },
87  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=AS_LOG}, 0, 0, FLAGS, "ascale" },
88  { "fscale", "set frequency scale", OFFSET(fscale), AV_OPT_TYPE_INT, {.i64=FS_LINEAR}, 0, NB_FSCALES-1, FLAGS, "fscale" },
89  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=FS_LINEAR}, 0, 0, FLAGS, "fscale" },
90  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_LOG}, 0, 0, FLAGS, "fscale" },
91  { "rlog", "reverse logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_RLOG}, 0, 0, FLAGS, "fscale" },
92  { "win_size", "set window size", OFFSET(fft_size), AV_OPT_TYPE_INT, {.i64=2048}, 16, 65536, FLAGS },
93  { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_HANNING}, 0, NB_WFUNC-1, FLAGS, "win_func" },
94  { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" },
95  { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" },
96  { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" },
97  { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, FLAGS, "win_func" },
98  { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, FLAGS, "win_func" },
99  { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, FLAGS, "win_func" },
100  { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, FLAGS, "win_func" },
101  { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, FLAGS, "win_func" },
102  { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, FLAGS, "win_func" },
103  { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, FLAGS, "win_func" },
104  { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, FLAGS, "win_func" },
105  { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, FLAGS, "win_func" },
106  { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, FLAGS, "win_func" },
107  { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, FLAGS, "win_func" },
108  { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, FLAGS, "win_func" },
109  { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, FLAGS, "win_func" },
110  { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, FLAGS, "win_func" },
111  { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, FLAGS, "win_func" },
112  { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, FLAGS, "win_func" },
113  { "bohman", "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN} , 0, 0, FLAGS, "win_func" },
114  { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=1.}, 0., 1., FLAGS },
115  { "averaging", "set time averaging", OFFSET(avg), AV_OPT_TYPE_INT, {.i64=1}, 0, INT32_MAX, FLAGS },
116  { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, FLAGS },
117  { "cmode", "set channel mode", OFFSET(cmode), AV_OPT_TYPE_INT, {.i64=COMBINED}, 0, NB_CMODES-1, FLAGS, "cmode" },
118  { "combined", "show all channels in same window", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, "cmode" },
119  { "separate", "show each channel in own window", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "cmode" },
120  { "minamp", "set minimum amplitude", OFFSET(minamp), AV_OPT_TYPE_FLOAT, {.dbl=1e-6}, FLT_MIN, 1e-6, FLAGS },
121  { "data", "set data mode", OFFSET(data_mode), AV_OPT_TYPE_INT, {.i64=MAGNITUDE}, 0, NB_DATA-1, FLAGS, "data" },
122  { "magnitude", "show magnitude", 0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" },
123  { "phase", "show phase", 0, AV_OPT_TYPE_CONST, {.i64=PHASE}, 0, 0, FLAGS, "data" },
124  { "delay", "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY}, 0, 0, FLAGS, "data" },
125  { NULL }
126 };
127 
128 AVFILTER_DEFINE_CLASS(showfreqs);
129 
131 {
134  AVFilterLink *inlink = ctx->inputs[0];
135  AVFilterLink *outlink = ctx->outputs[0];
137  static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE };
138  int ret;
139 
140  /* set input audio formats */
142  if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0)
143  return ret;
144 
146  if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0)
147  return ret;
148 
150  if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0)
151  return ret;
152 
153  /* set output video format */
155  if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0)
156  return ret;
157 
158  return 0;
159 }
160 
162 {
163  ShowFreqsContext *s = ctx->priv;
164 
165  s->pts = AV_NOPTS_VALUE;
166 
167  return 0;
168 }
169 
170 static int config_output(AVFilterLink *outlink)
171 {
172  AVFilterContext *ctx = outlink->src;
173  AVFilterLink *inlink = ctx->inputs[0];
174  ShowFreqsContext *s = ctx->priv;
175  float overlap, scale;
176  int i, ret;
177 
178  s->nb_freq = s->fft_size / 2;
179  s->win_size = s->fft_size;
180  av_audio_fifo_free(s->fifo);
181  av_tx_uninit(&s->fft);
182  ret = av_tx_init(&s->fft, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0);
183  if (ret < 0) {
184  av_log(ctx, AV_LOG_ERROR, "Unable to create FFT context. "
185  "The window size might be too high.\n");
186  return ret;
187  }
188 
189  /* FFT buffers: x2 for each (display) channel buffer.
190  * Note: we use free and malloc instead of a realloc-like function to
191  * make sure the buffer is aligned in memory for the FFT functions. */
192  for (i = 0; i < s->nb_channels; i++) {
193  av_freep(&s->fft_input[i]);
194  av_freep(&s->fft_data[i]);
195  av_freep(&s->avg_data[i]);
196  }
197  av_freep(&s->fft_input);
198  av_freep(&s->fft_data);
199  av_freep(&s->avg_data);
200  s->nb_channels = inlink->channels;
201 
202  s->fft_input = av_calloc(s->nb_channels, sizeof(*s->fft_input));
203  if (!s->fft_input)
204  return AVERROR(ENOMEM);
205  s->fft_data = av_calloc(s->nb_channels, sizeof(*s->fft_data));
206  if (!s->fft_data)
207  return AVERROR(ENOMEM);
208  s->avg_data = av_calloc(s->nb_channels, sizeof(*s->avg_data));
209  if (!s->avg_data)
210  return AVERROR(ENOMEM);
211  for (i = 0; i < s->nb_channels; i++) {
212  s->fft_input[i] = av_calloc(FFALIGN(s->win_size, 512), sizeof(**s->fft_input));
213  s->fft_data[i] = av_calloc(FFALIGN(s->win_size, 512), sizeof(**s->fft_data));
214  s->avg_data[i] = av_calloc(s->nb_freq, sizeof(**s->avg_data));
215  if (!s->fft_data[i] || !s->avg_data[i] || !s->fft_input[i])
216  return AVERROR(ENOMEM);
217  }
218 
219  /* pre-calc windowing function */
220  s->window_func_lut = av_realloc_f(s->window_func_lut, s->win_size,
221  sizeof(*s->window_func_lut));
222  if (!s->window_func_lut)
223  return AVERROR(ENOMEM);
224  generate_window_func(s->window_func_lut, s->win_size, s->win_func, &overlap);
225  if (s->overlap == 1.)
226  s->overlap = overlap;
227  s->hop_size = (1. - s->overlap) * s->win_size;
228  if (s->hop_size < 1) {
229  av_log(ctx, AV_LOG_ERROR, "overlap %f too big\n", s->overlap);
230  return AVERROR(EINVAL);
231  }
232 
233  for (s->scale = 0, i = 0; i < s->win_size; i++) {
234  s->scale += s->window_func_lut[i] * s->window_func_lut[i];
235  }
236 
237  outlink->frame_rate = av_make_q(inlink->sample_rate, s->win_size * (1.-s->overlap));
238  outlink->sample_aspect_ratio = (AVRational){1,1};
239  outlink->w = s->w;
240  outlink->h = s->h;
241 
242  s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->win_size);
243  if (!s->fifo)
244  return AVERROR(ENOMEM);
245  return 0;
246 }
247 
248 static inline void draw_dot(AVFrame *out, int x, int y, uint8_t fg[4])
249 {
250 
251  uint32_t color = AV_RL32(out->data[0] + y * out->linesize[0] + x * 4);
252 
253  if ((color & 0xffffff) != 0)
254  AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg) | color);
255  else
256  AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg));
257 }
258 
259 static int get_sx(ShowFreqsContext *s, int f)
260 {
261  switch (s->fscale) {
262  case FS_LINEAR:
263  return (s->w/(float)s->nb_freq)*f;
264  case FS_LOG:
265  return s->w-pow(s->w, (s->nb_freq-f-1)/(s->nb_freq-1.));
266  case FS_RLOG:
267  return pow(s->w, f/(s->nb_freq-1.));
268  }
269 
270  return 0;
271 }
272 
273 static float get_bsize(ShowFreqsContext *s, int f)
274 {
275  switch (s->fscale) {
276  case FS_LINEAR:
277  return s->w/(float)s->nb_freq;
278  case FS_LOG:
279  return pow(s->w, (s->nb_freq-f-1)/(s->nb_freq-1.))-
280  pow(s->w, (s->nb_freq-f-2)/(s->nb_freq-1.));
281  case FS_RLOG:
282  return pow(s->w, (f+1)/(s->nb_freq-1.))-
283  pow(s->w, f /(s->nb_freq-1.));
284  }
285 
286  return 1.;
287 }
288 
289 static inline void plot_freq(ShowFreqsContext *s, int ch,
290  double a, int f, uint8_t fg[4], int *prev_y,
291  AVFrame *out, AVFilterLink *outlink)
292 {
293  const int w = s->w;
294  const float min = s->minamp;
295  const float avg = s->avg_data[ch][f];
296  const float bsize = get_bsize(s, f);
297  const int sx = get_sx(s, f);
298  int end = outlink->h;
299  int x, y, i;
300 
301  switch(s->ascale) {
302  case AS_SQRT:
303  a = 1.0 - sqrt(a);
304  break;
305  case AS_CBRT:
306  a = 1.0 - cbrt(a);
307  break;
308  case AS_LOG:
309  a = log(av_clipd(a, min, 1)) / log(min);
310  break;
311  case AS_LINEAR:
312  a = 1.0 - a;
313  break;
314  }
315 
316  switch (s->cmode) {
317  case COMBINED:
318  y = a * outlink->h - 1;
319  break;
320  case SEPARATE:
321  end = (outlink->h / s->nb_channels) * (ch + 1);
322  y = (outlink->h / s->nb_channels) * ch + a * (outlink->h / s->nb_channels) - 1;
323  break;
324  default:
325  av_assert0(0);
326  }
327  if (y < 0)
328  return;
329 
330  switch (s->avg) {
331  case 0:
332  y = s->avg_data[ch][f] = !outlink->frame_count_in ? y : FFMIN(avg, y);
333  break;
334  case 1:
335  break;
336  default:
337  s->avg_data[ch][f] = avg + y * (y - avg) / (FFMIN(outlink->frame_count_in + 1, s->avg) * y);
338  y = s->avg_data[ch][f];
339  break;
340  }
341 
342  switch(s->mode) {
343  case LINE:
344  if (*prev_y == -1) {
345  *prev_y = y;
346  }
347  if (y <= *prev_y) {
348  for (x = sx + 1; x < sx + bsize && x < w; x++)
349  draw_dot(out, x, y, fg);
350  for (i = y; i <= *prev_y; i++)
351  draw_dot(out, sx, i, fg);
352  } else {
353  for (i = *prev_y; i <= y; i++)
354  draw_dot(out, sx, i, fg);
355  for (x = sx + 1; x < sx + bsize && x < w; x++)
356  draw_dot(out, x, i - 1, fg);
357  }
358  *prev_y = y;
359  break;
360  case BAR:
361  for (x = sx; x < sx + bsize && x < w; x++)
362  for (i = y; i < end; i++)
363  draw_dot(out, x, i, fg);
364  break;
365  case DOT:
366  for (x = sx; x < sx + bsize && x < w; x++)
367  draw_dot(out, x, y, fg);
368  break;
369  }
370 }
371 
373 {
374  AVFilterContext *ctx = inlink->dst;
375  AVFilterLink *outlink = ctx->outputs[0];
376  ShowFreqsContext *s = ctx->priv;
377  const int win_size = s->win_size;
378  char *colors, *color, *saveptr = NULL;
379  AVFrame *out;
380  int ch, n;
381 
382  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
383  if (!out)
384  return AVERROR(ENOMEM);
385 
386  for (n = 0; n < outlink->h; n++)
387  memset(out->data[0] + out->linesize[0] * n, 0, outlink->w * 4);
388 
389  /* fill FFT input with the number of samples available */
390  for (ch = 0; ch < s->nb_channels; ch++) {
391  const float *p = (float *)in->extended_data[ch];
392 
393  for (n = 0; n < in->nb_samples; n++) {
394  s->fft_input[ch][n].re = p[n] * s->window_func_lut[n];
395  s->fft_input[ch][n].im = 0;
396  }
397  for (; n < win_size; n++) {
398  s->fft_input[ch][n].re = 0;
399  s->fft_input[ch][n].im = 0;
400  }
401  }
402 
403  /* run FFT on each samples set */
404  for (ch = 0; ch < s->nb_channels; ch++) {
405  s->tx_fn(s->fft, s->fft_data[ch], s->fft_input[ch], sizeof(float));
406  }
407 
408 #define RE(x, ch) s->fft_data[ch][x].re
409 #define IM(x, ch) s->fft_data[ch][x].im
410 #define M(a, b) (sqrt((a) * (a) + (b) * (b)))
411 #define P(a, b) (atan2((b), (a)))
412 
413  colors = av_strdup(s->colors);
414  if (!colors) {
415  av_frame_free(&out);
416  return AVERROR(ENOMEM);
417  }
418 
419  for (ch = 0; ch < s->nb_channels; ch++) {
420  uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };
421  int prev_y = -1, f;
422  double a;
423 
424  color = av_strtok(ch == 0 ? colors : NULL, " |", &saveptr);
425  if (color)
426  av_parse_color(fg, color, -1, ctx);
427 
428  switch (s->data_mode) {
429  case MAGNITUDE:
430  a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1);
431  plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink);
432 
433  for (f = 1; f < s->nb_freq; f++) {
434  a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1);
435 
436  plot_freq(s, ch, a, f, fg, &prev_y, out, outlink);
437  }
438  break;
439  case PHASE:
440  a = av_clipd((M_PI + P(RE(0, ch), 0)) / (2. * M_PI), 0, 1);
441  plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink);
442 
443  for (f = 1; f < s->nb_freq; f++) {
444  a = av_clipd((M_PI + P(RE(f, ch), IM(f, ch))) / (2. * M_PI), 0, 1);
445 
446  plot_freq(s, ch, a, f, fg, &prev_y, out, outlink);
447  }
448  break;
449  case DELAY:
450  plot_freq(s, ch, 0, 0, fg, &prev_y, out, outlink);
451 
452  for (f = 1; f < s->nb_freq; f++) {
453  a = av_clipd((M_PI - P(IM(f, ch) * RE(f-1, ch) - IM(f-1, ch) * RE(f, ch),
454  RE(f, ch) * RE(f-1, ch) + IM(f, ch) * IM(f-1, ch))) / (2. * M_PI), 0, 1);
455 
456  plot_freq(s, ch, a, f, fg, &prev_y, out, outlink);
457  }
458  break;
459  }
460  }
461 
462  av_free(colors);
463  out->pts = in->pts;
464  out->sample_aspect_ratio = (AVRational){1,1};
465  return ff_filter_frame(outlink, out);
466 }
467 
469 {
470  AVFilterContext *ctx = inlink->dst;
471  ShowFreqsContext *s = ctx->priv;
472  AVFrame *fin = NULL;
473  int ret = 0;
474 
475  fin = ff_get_audio_buffer(inlink, s->win_size);
476  if (!fin) {
477  ret = AVERROR(ENOMEM);
478  goto fail;
479  }
480 
481  fin->pts = s->pts;
482  s->pts += s->hop_size;
483  ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size);
484  if (ret < 0)
485  goto fail;
486 
487  ret = plot_freqs(inlink, fin);
488  av_frame_free(&fin);
489  av_audio_fifo_drain(s->fifo, s->hop_size);
490 
491 fail:
492  av_frame_free(&fin);
493  return ret;
494 }
495 
497 {
498  AVFilterLink *inlink = ctx->inputs[0];
499  AVFilterLink *outlink = ctx->outputs[0];
500  ShowFreqsContext *s = ctx->priv;
501  AVFrame *in = NULL;
502  int ret = 0;
503 
505 
506  if (av_audio_fifo_size(s->fifo) < s->win_size)
507  ret = ff_inlink_consume_samples(inlink, s->win_size, s->win_size, &in);
508  if (ret < 0)
509  return ret;
510  if (ret > 0) {
511  av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples);
512  if (s->pts == AV_NOPTS_VALUE)
513  s->pts = in->pts;
514  av_frame_free(&in);
515  }
516 
517  if (av_audio_fifo_size(s->fifo) >= s->win_size) {
519  if (ret <= 0)
520  return ret;
521  }
522 
525 
526  return FFERROR_NOT_READY;
527 }
528 
530 {
531  ShowFreqsContext *s = ctx->priv;
532  int i;
533 
534  av_tx_uninit(&s->fft);
535  for (i = 0; i < s->nb_channels; i++) {
536  if (s->fft_input)
537  av_freep(&s->fft_input[i]);
538  if (s->fft_data)
539  av_freep(&s->fft_data[i]);
540  if (s->avg_data)
541  av_freep(&s->avg_data[i]);
542  }
543  av_freep(&s->fft_input);
544  av_freep(&s->fft_data);
545  av_freep(&s->avg_data);
546  av_freep(&s->window_func_lut);
547  av_audio_fifo_free(s->fifo);
548 }
549 
550 static const AVFilterPad showfreqs_inputs[] = {
551  {
552  .name = "default",
553  .type = AVMEDIA_TYPE_AUDIO,
554  },
555  { NULL }
556 };
557 
558 static const AVFilterPad showfreqs_outputs[] = {
559  {
560  .name = "default",
561  .type = AVMEDIA_TYPE_VIDEO,
562  .config_props = config_output,
563  },
564  { NULL }
565 };
566 
568  .name = "showfreqs",
569  .description = NULL_IF_CONFIG_SMALL("Convert input audio to a frequencies video output."),
570  .init = init,
571  .uninit = uninit,
572  .query_formats = query_formats,
573  .priv_size = sizeof(ShowFreqsContext),
574  .activate = activate,
577  .priv_class = &showfreqs_class,
578 };
av_audio_fifo_free
void av_audio_fifo_free(AVAudioFifo *af)
Free an AVAudioFifo.
Definition: audio_fifo.c:45
formats
formats
Definition: signature.h:48
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:97
ShowFreqsContext::tx_fn
av_tx_fn tx_fn
Definition: avf_showfreqs.c:56
ff_get_audio_buffer
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
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:69
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:85
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
ShowFreqsContext::fscale
int fscale
Definition: avf_showfreqs.c:52
AVERROR
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
opt.h
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
out
FILE * out
Definition: movenc.c:54
M
#define M(a, b)
ShowFreqsContext::win_func
int win_func
Definition: avf_showfreqs.c:54
color
Definition: vf_paletteuse.c:583
FrequencyScale
FrequencyScale
Definition: avf_showfreqs.c:42
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:978
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:948
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:454
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
ShowFreqsContext::scale
float scale
Definition: avf_showfreqs.c:67
av_parse_color
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition: parseutils.c:354
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
AVTXContext
Definition: tx_priv.h:110
inlink
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
Definition: filter_design.txt:212
NB_CMODES
@ NB_CMODES
Definition: avf_showfreqs.c:41
LINE
@ LINE
Definition: avf_showfreqs.c:40
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
RE
#define RE(x, ch)
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:396
w
uint8_t w
Definition: llviddspenc.c:38
draw_dot
static void draw_dot(AVFrame *out, int x, int y, uint8_t fg[4])
Definition: avf_showfreqs.c:248
ShowFreqsContext::fft
AVTXContext * fft
Definition: avf_showfreqs.c:55
showfreqs_inputs
static const AVFilterPad showfreqs_inputs[]
Definition: avf_showfreqs.c:550
DELAY
@ DELAY
Definition: avf_showfreqs.c:39
AVOption
AVOption.
Definition: opt.h:247
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: avf_showfreqs.c:130
NB_ASCALES
@ NB_ASCALES
Definition: avf_showfreqs.c:43
float.h
AVComplexFloat
Definition: tx.h:27
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:149
ff_avf_showfreqs
const AVFilter ff_avf_showfreqs
Definition: avf_showfreqs.c:567
P
#define P(a, b)
video.h
ShowFreqsContext::w
int w
Definition: avf_showfreqs.c:47
FF_FILTER_FORWARD_STATUS_BACK
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
WFUNC_FLATTOP
@ WFUNC_FLATTOP
Definition: window_func.h:29
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:227
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
WFUNC_BLACKMAN
@ WFUNC_BLACKMAN
Definition: af_firequalizer.c:37
WFUNC_PARZEN
@ WFUNC_PARZEN
Definition: window_func.h:32
OFFSET
#define OFFSET(x)
Definition: avf_showfreqs.c:73
ShowFreqsContext::fft_data
AVComplexFloat ** fft_data
Definition: avf_showfreqs.c:58
AVAudioFifo
Context for an Audio FIFO Buffer.
Definition: audio_fifo.c:34
ShowFreqsContext::h
int h
Definition: avf_showfreqs.c:47
av_audio_fifo_drain
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
Drain data from an AVAudioFifo.
Definition: audio_fifo.c:201
fail
#define fail()
Definition: checkasm.h:136
FS_LOG
@ FS_LOG
Definition: avf_showfreqs.c:42
WFUNC_BHANN
@ WFUNC_BHANN
Definition: window_func.h:31
ChannelMode
ChannelMode
Definition: avf_showfreqs.c:41
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
cbrt
#define cbrt
Definition: tablegen.h:35
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
WFUNC_DOLPH
@ WFUNC_DOLPH
Definition: window_func.h:32
av_cold
#define av_cold
Definition: attributes.h:90
AmplitudeScale
AmplitudeScale
Definition: avf_ahistogram.c:32
inputs
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 inputs
Definition: filter_design.txt:243
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:102
BAR
@ BAR
Definition: avf_showfreqs.c:40
WFUNC_NUTTALL
@ WFUNC_NUTTALL
Definition: af_firequalizer.c:40
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
ShowFreqsContext::nb_channels
int nb_channels
Definition: avf_showfreqs.c:64
config_output
static int config_output(AVFilterLink *outlink)
Definition: avf_showfreqs.c:170
av_audio_fifo_write
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
Write data to an AVAudioFifo.
Definition: audio_fifo.c:112
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
ff_formats_ref
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:459
av_strtok
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:186
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
WFUNC_LANCZOS
@ WFUNC_LANCZOS
Definition: window_func.h:31
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
filters.h
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:290
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type AVComplexFloat.
Definition: tx.h:45
WFUNC_RECT
@ WFUNC_RECT
Definition: window_func.h:28
ShowFreqsContext::colors
char * colors
Definition: avf_showfreqs.c:68
ctx
AVFormatContext * ctx
Definition: movenc.c:48
WFUNC_BHARRIS
@ WFUNC_BHARRIS
Definition: af_firequalizer.c:42
filter_frame
static int filter_frame(AVFilterLink *inlink)
Definition: avf_showfreqs.c:468
FS_LINEAR
@ FS_LINEAR
Definition: avf_showfreqs.c:42
f
#define f(width, name)
Definition: cbs_vp9.c:255
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
ShowFreqsContext::fft_size
int fft_size
Definition: avf_showfreqs.c:51
if
if(ret)
Definition: filter_design.txt:179
SEPARATE
@ SEPARATE
Definition: avf_showfreqs.c:41
ShowFreqsContext::nb_freq
int nb_freq
Definition: avf_showfreqs.c:65
av_realloc_f
#define av_realloc_f(p, o, n)
Definition: tableprint_vlc.h:33
FLAGS
#define FLAGS
Definition: avf_showfreqs.c:74
ShowFreqsContext::fft_input
AVComplexFloat ** fft_input
Definition: avf_showfreqs.c:57
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ff_inlink_consume_samples
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition: avfilter.c:1395
NULL
#define NULL
Definition: coverity.c:32
ShowFreqsContext::cmode
int cmode
Definition: avf_showfreqs.c:50
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_audio_fifo_alloc
AVAudioFifo * av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, int nb_samples)
Allocate an AVAudioFifo.
Definition: audio_fifo.c:59
WFUNC_HAMMING
@ WFUNC_HAMMING
Definition: af_firequalizer.c:36
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:234
init
static av_cold int init(AVFilterContext *ctx)
Definition: avf_showfreqs.c:161
parseutils.h
ShowFreqsContext::minamp
float minamp
Definition: avf_showfreqs.c:62
generate_window_func
static void generate_window_func(float *lut, int N, int win_func, float *overlap)
Definition: window_func.h:36
WFUNC_HANNING
@ WFUNC_HANNING
Definition: window_func.h:28
WFUNC_BARTLETT
@ WFUNC_BARTLETT
Definition: window_func.h:29
WFUNC_BOHMAN
@ WFUNC_BOHMAN
Definition: window_func.h:33
ShowFreqsContext::ascale
int ascale
Definition: avf_showfreqs.c:52
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
ShowFreqsContext::avg_data
float ** avg_data
Definition: avf_showfreqs.c:59
ShowFreqsContext::hop_size
int hop_size
Definition: avf_showfreqs.c:63
DataMode
DataMode
Definition: avf_showfreqs.c:39
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:116
av_clipd
#define av_clipd
Definition: common.h:147
activate
static int activate(AVFilterContext *ctx)
Definition: avf_showfreqs.c:496
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:59
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
ShowFreqsContext::mode
int mode
Definition: avf_showfreqs.c:48
WFUNC_TUKEY
@ WFUNC_TUKEY
Definition: af_firequalizer.c:43
avg
#define avg(a, b, c, d)
Definition: colorspacedsp_template.c:28
plot_freqs
static int plot_freqs(AVFilterLink *inlink, AVFrame *in)
Definition: avf_showfreqs.c:372
IM
#define IM(x, ch)
ShowFreqsContext
Definition: avf_showfreqs.c:45
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
MAGNITUDE
@ MAGNITUDE
Definition: avf_showfreqs.c:39
FF_FILTER_FORWARD_WANTED
FF_FILTER_FORWARD_WANTED(outlink, inlink)
ff_all_channel_layouts
AVFilterChannelLayouts * ff_all_channel_layouts(void)
Construct an empty AVFilterChannelLayouts/AVFilterFormats struct – representing any channel layout (w...
Definition: formats.c:420
av_audio_fifo_size
int av_audio_fifo_size(AVAudioFifo *af)
Get the current number of samples in the AVAudioFifo available for reading.
Definition: audio_fifo.c:228
M_PI
#define M_PI
Definition: mathematics.h:52
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets ctx to NULL, does nothing when ctx == NULL.
Definition: tx.c:212
internal.h
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:227
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:369
i
int i
Definition: input.c:406
AS_LINEAR
@ AS_LINEAR
Definition: avf_showfreqs.c:43
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:350
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
FS_RLOG
@ FS_RLOG
Definition: avf_showfreqs.c:42
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
get_sx
static int get_sx(ShowFreqsContext *s, int f)
Definition: avf_showfreqs.c:259
audio_fifo.h
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
AVFilter
Filter definition.
Definition: avfilter.h:145
NB_MODES
@ NB_MODES
Definition: avf_showfreqs.c:40
ret
ret
Definition: filter_design.txt:187
plot_freq
static void plot_freq(ShowFreqsContext *s, int ch, double a, int f, uint8_t fg[4], int *prev_y, AVFrame *out, AVFilterLink *outlink)
Definition: avf_showfreqs.c:289
showfreqs_outputs
static const AVFilterPad showfreqs_outputs[]
Definition: avf_showfreqs.c:558
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
ShowFreqsContext::window_func_lut
float * window_func_lut
Definition: avf_showfreqs.c:60
window_func.h
NB_FSCALES
@ NB_FSCALES
Definition: avf_showfreqs.c:42
ShowFreqsContext::pts
int64_t pts
Definition: avf_showfreqs.c:70
showfreqs_options
static const AVOption showfreqs_options[]
Definition: avf_showfreqs.c:76
NB_WFUNC
@ NB_WFUNC
Definition: af_firequalizer.c:44
ff_all_samplerates
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:414
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:251
channel_layout.h
WFUNC_SINE
@ WFUNC_SINE
Definition: window_func.h:30
WFUNC_CAUCHY
@ WFUNC_CAUCHY
Definition: window_func.h:32
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
avfilter.h
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: avf_showfreqs.c:529
ShowFreqsContext::data_mode
int data_mode
Definition: avf_showfreqs.c:49
AVFilterContext
An instance of a filter.
Definition: avfilter.h:333
ShowFreqsContext::win_size
int win_size
Definition: avf_showfreqs.c:66
DisplayMode
DisplayMode
Definition: avf_ahistogram.c:34
ShowFreqsContext::avg
int avg
Definition: avf_showfreqs.c:53
get_bsize
static float get_bsize(ShowFreqsContext *s, int f)
Definition: avf_showfreqs.c:273
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:259
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
WFUNC_GAUSS
@ WFUNC_GAUSS
Definition: window_func.h:31
WFUNC_BNUTTALL
@ WFUNC_BNUTTALL
Definition: af_firequalizer.c:41
audio.h
NB_DATA
@ NB_DATA
Definition: avf_showfreqs.c:39
AVFilterFormatsConfig::formats
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:437
WFUNC_POISSON
@ WFUNC_POISSON
Definition: window_func.h:32
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FF_FILTER_FORWARD_STATUS
FF_FILTER_FORWARD_STATUS(inlink, outlink)
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AS_CBRT
@ AS_CBRT
Definition: avf_showfreqs.c:43
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
COMBINED
@ COMBINED
Definition: avf_showfreqs.c:41
PHASE
@ PHASE
Definition: avf_showfreqs.c:39
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
ShowFreqsContext::fifo
AVAudioFifo * fifo
Definition: avf_showfreqs.c:69
DOT
@ DOT
Definition: avf_showfreqs.c:40
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(showfreqs)
av_audio_fifo_peek
int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
Peek data from an AVAudioFifo.
Definition: audio_fifo.c:138
AS_LOG
@ AS_LOG
Definition: avf_showfreqs.c:43
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
WFUNC_WELCH
@ WFUNC_WELCH
Definition: window_func.h:29
ShowFreqsContext::overlap
float overlap
Definition: avf_showfreqs.c:61
AS_SQRT
@ AS_SQRT
Definition: avf_showfreqs.c:43
tx.h
min
float min
Definition: vorbis_enc_data.h:429