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