FFmpeg
avf_showspectrum.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2013 Clément Bœsch
3  * Copyright (c) 2013 Rudolf Polzer <divverent@xonotic.org>
4  * Copyright (c) 2015 Paul B Mahol
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /**
24  * @file
25  * audio to spectrum (video) transmedia filter, based on ffplay rdft showmode
26  * (by Michael Niedermayer) and lavfi/avf_showwaves (by Stefano Sabatini).
27  */
28 
29 #include "config_components.h"
30 
31 #include <float.h>
32 #include <math.h>
33 
34 #include "libavutil/tx.h"
35 #include "libavutil/avassert.h"
36 #include "libavutil/avstring.h"
38 #include "libavutil/cpu.h"
39 #include "libavutil/opt.h"
40 #include "libavutil/parseutils.h"
42 #include "audio.h"
43 #include "formats.h"
44 #include "video.h"
45 #include "avfilter.h"
46 #include "filters.h"
47 #include "internal.h"
48 #include "window_func.h"
49 
57 
58 #define DEFAULT_LENGTH 300
59 
60 typedef struct ShowSpectrumContext {
61  const AVClass *class;
62  int w, h;
63  char *rate_str;
72  int sliding; ///< 1 if sliding mode, 0 otherwise
73  int mode; ///< channel display mode
74  int color_mode; ///< display color scheme
75  int scale;
76  int fscale;
77  float saturation; ///< color saturation multiplier
78  float rotation; ///< color rotation
79  int start, stop; ///< zoom mode
80  int data;
81  int xpos; ///< x position (current column)
82  AVTXContext **fft; ///< Fast Fourier Transform context
83  AVTXContext **ifft; ///< Inverse Fast Fourier Transform context
86  int fft_size; ///< number of coeffs (FFT window size)
87  AVComplexFloat **fft_in; ///< input FFT coeffs
88  AVComplexFloat **fft_data; ///< bins holder for each (displayed) channels
89  AVComplexFloat **fft_scratch;///< scratch buffers
90  float *window_func_lut; ///< Window function LUT
91  float **magnitudes;
92  float **phases;
93  int win_func;
94  int win_size;
95  int buf_size;
96  double win_scale;
97  float overlap;
98  float gain;
99  int hop_size;
100  float *combine_buffer; ///< color combining buffer (4 * h items)
101  float **color_buffer; ///< color buffer (4 * h * ch items)
102  int64_t pts;
103  int64_t old_pts;
104  int64_t in_pts;
105  int old_len;
107  int legend;
109  float drange, limit;
110  float dmin, dmax;
111  uint64_t samples;
112  int (*plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
113  int eof;
114 
116 
118  unsigned int nb_frames;
119  unsigned int frames_size;
121 
122 #define OFFSET(x) offsetof(ShowSpectrumContext, x)
123 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
124 
125 static const AVOption showspectrum_options[] = {
126  { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x512"}, 0, 0, FLAGS },
127  { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x512"}, 0, 0, FLAGS },
128  { "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_SLIDES-1, FLAGS, "slide" },
129  { "replace", "replace old columns with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, "slide" },
130  { "scroll", "scroll from right to left", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, "slide" },
131  { "fullframe", "return full frames", 0, AV_OPT_TYPE_CONST, {.i64=FULLFRAME}, 0, 0, FLAGS, "slide" },
132  { "rscroll", "scroll from left to right", 0, AV_OPT_TYPE_CONST, {.i64=RSCROLL}, 0, 0, FLAGS, "slide" },
133  { "lreplace", "replace from right to left", 0, AV_OPT_TYPE_CONST, {.i64=LREPLACE}, 0, 0, FLAGS, "slide" },
134  { "mode", "set channel display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=COMBINED}, COMBINED, NB_MODES-1, FLAGS, "mode" },
135  { "combined", "combined mode", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, "mode" },
136  { "separate", "separate mode", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "mode" },
137  { "color", "set channel coloring", OFFSET(color_mode), AV_OPT_TYPE_INT, {.i64=CHANNEL}, CHANNEL, NB_CLMODES-1, FLAGS, "color" },
138  { "channel", "separate color for each channel", 0, AV_OPT_TYPE_CONST, {.i64=CHANNEL}, 0, 0, FLAGS, "color" },
139  { "intensity", "intensity based coloring", 0, AV_OPT_TYPE_CONST, {.i64=INTENSITY}, 0, 0, FLAGS, "color" },
140  { "rainbow", "rainbow based coloring", 0, AV_OPT_TYPE_CONST, {.i64=RAINBOW}, 0, 0, FLAGS, "color" },
141  { "moreland", "moreland based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MORELAND}, 0, 0, FLAGS, "color" },
142  { "nebulae", "nebulae based coloring", 0, AV_OPT_TYPE_CONST, {.i64=NEBULAE}, 0, 0, FLAGS, "color" },
143  { "fire", "fire based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIRE}, 0, 0, FLAGS, "color" },
144  { "fiery", "fiery based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIERY}, 0, 0, FLAGS, "color" },
145  { "fruit", "fruit based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FRUIT}, 0, 0, FLAGS, "color" },
146  { "cool", "cool based coloring", 0, AV_OPT_TYPE_CONST, {.i64=COOL}, 0, 0, FLAGS, "color" },
147  { "magma", "magma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MAGMA}, 0, 0, FLAGS, "color" },
148  { "green", "green based coloring", 0, AV_OPT_TYPE_CONST, {.i64=GREEN}, 0, 0, FLAGS, "color" },
149  { "viridis", "viridis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=VIRIDIS}, 0, 0, FLAGS, "color" },
150  { "plasma", "plasma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=PLASMA}, 0, 0, FLAGS, "color" },
151  { "cividis", "cividis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=CIVIDIS}, 0, 0, FLAGS, "color" },
152  { "terrain", "terrain based coloring", 0, AV_OPT_TYPE_CONST, {.i64=TERRAIN}, 0, 0, FLAGS, "color" },
153  { "scale", "set display scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=SQRT}, LINEAR, NB_SCALES-1, FLAGS, "scale" },
154  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, "scale" },
155  { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SQRT}, 0, 0, FLAGS, "scale" },
156  { "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=CBRT}, 0, 0, FLAGS, "scale" },
157  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, FLAGS, "scale" },
158  { "4thrt","4th root", 0, AV_OPT_TYPE_CONST, {.i64=FOURTHRT}, 0, 0, FLAGS, "scale" },
159  { "5thrt","5th root", 0, AV_OPT_TYPE_CONST, {.i64=FIFTHRT}, 0, 0, FLAGS, "scale" },
160  { "fscale", "set frequency scale", OFFSET(fscale), AV_OPT_TYPE_INT, {.i64=F_LINEAR}, 0, NB_FSCALES-1, FLAGS, "fscale" },
161  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=F_LINEAR}, 0, 0, FLAGS, "fscale" },
162  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=F_LOG}, 0, 0, FLAGS, "fscale" },
163  { "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS },
164  WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_HANNING),
165  { "orientation", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=VERTICAL}, 0, NB_ORIENTATIONS-1, FLAGS, "orientation" },
166  { "vertical", NULL, 0, AV_OPT_TYPE_CONST, {.i64=VERTICAL}, 0, 0, FLAGS, "orientation" },
167  { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=HORIZONTAL}, 0, 0, FLAGS, "orientation" },
168  { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, 1, FLAGS },
169  { "gain", "set scale gain", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 128, FLAGS },
170  { "data", "set data mode", OFFSET(data), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_DMODES-1, FLAGS, "data" },
171  { "magnitude", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_MAGNITUDE}, 0, 0, FLAGS, "data" },
172  { "phase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_PHASE}, 0, 0, FLAGS, "data" },
173  { "uphase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_UPHASE}, 0, 0, FLAGS, "data" },
174  { "rotation", "color rotation", OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -1, 1, FLAGS },
175  { "start", "start frequency", OFFSET(start), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
176  { "stop", "stop frequency", OFFSET(stop), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
177  { "fps", "set video rate", OFFSET(rate_str), AV_OPT_TYPE_STRING, {.str = "auto"}, 0, 0, FLAGS },
178  { "legend", "draw legend", OFFSET(legend), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
179  { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS },
180  { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS },
181  { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS },
182  { NULL }
183 };
184 
185 AVFILTER_DEFINE_CLASS(showspectrum);
186 
187 static const struct ColorTable {
188  float a, y, u, v;
189 } color_table[][8] = {
190  [INTENSITY] = {
191  { 0, 0, 0, 0 },
192  { 0.13, .03587126228984074, .1573300977624594, -.02548747583751842 },
193  { 0.30, .18572281794568020, .1772436246393981, .17475554840414750 },
194  { 0.60, .28184980583656130, -.1593064119945782, .47132074554608920 },
195  { 0.73, .65830621175547810, -.3716070802232764, .24352759331252930 },
196  { 0.78, .76318535758242900, -.4307467689263783, .16866496622310430 },
197  { 0.91, .95336363636363640, -.2045454545454546, .03313636363636363 },
198  { 1, 1, 0, 0 }},
199  [RAINBOW] = {
200  { 0, 0, 0, 0 },
201  { 0.13, 44/256., (189-128)/256., (138-128)/256. },
202  { 0.25, 29/256., (186-128)/256., (119-128)/256. },
203  { 0.38, 119/256., (194-128)/256., (53-128)/256. },
204  { 0.60, 111/256., (73-128)/256., (59-128)/256. },
205  { 0.73, 205/256., (19-128)/256., (149-128)/256. },
206  { 0.86, 135/256., (83-128)/256., (200-128)/256. },
207  { 1, 73/256., (95-128)/256., (225-128)/256. }},
208  [MORELAND] = {
209  { 0, 44/256., (181-128)/256., (112-128)/256. },
210  { 0.13, 126/256., (177-128)/256., (106-128)/256. },
211  { 0.25, 164/256., (163-128)/256., (109-128)/256. },
212  { 0.38, 200/256., (140-128)/256., (120-128)/256. },
213  { 0.60, 201/256., (117-128)/256., (141-128)/256. },
214  { 0.73, 177/256., (103-128)/256., (165-128)/256. },
215  { 0.86, 136/256., (100-128)/256., (183-128)/256. },
216  { 1, 68/256., (117-128)/256., (203-128)/256. }},
217  [NEBULAE] = {
218  { 0, 10/256., (134-128)/256., (132-128)/256. },
219  { 0.23, 21/256., (137-128)/256., (130-128)/256. },
220  { 0.45, 35/256., (134-128)/256., (134-128)/256. },
221  { 0.57, 51/256., (130-128)/256., (139-128)/256. },
222  { 0.67, 104/256., (116-128)/256., (162-128)/256. },
223  { 0.77, 120/256., (105-128)/256., (188-128)/256. },
224  { 0.87, 140/256., (105-128)/256., (188-128)/256. },
225  { 1, 1, 0, 0 }},
226  [FIRE] = {
227  { 0, 0, 0, 0 },
228  { 0.23, 44/256., (132-128)/256., (127-128)/256. },
229  { 0.45, 62/256., (116-128)/256., (140-128)/256. },
230  { 0.57, 75/256., (105-128)/256., (152-128)/256. },
231  { 0.67, 95/256., (91-128)/256., (166-128)/256. },
232  { 0.77, 126/256., (74-128)/256., (172-128)/256. },
233  { 0.87, 164/256., (73-128)/256., (162-128)/256. },
234  { 1, 1, 0, 0 }},
235  [FIERY] = {
236  { 0, 0, 0, 0 },
237  { 0.23, 36/256., (116-128)/256., (163-128)/256. },
238  { 0.45, 52/256., (102-128)/256., (200-128)/256. },
239  { 0.57, 116/256., (84-128)/256., (196-128)/256. },
240  { 0.67, 157/256., (67-128)/256., (181-128)/256. },
241  { 0.77, 193/256., (40-128)/256., (155-128)/256. },
242  { 0.87, 221/256., (101-128)/256., (134-128)/256. },
243  { 1, 1, 0, 0 }},
244  [FRUIT] = {
245  { 0, 0, 0, 0 },
246  { 0.20, 29/256., (136-128)/256., (119-128)/256. },
247  { 0.30, 60/256., (119-128)/256., (90-128)/256. },
248  { 0.40, 85/256., (91-128)/256., (85-128)/256. },
249  { 0.50, 116/256., (70-128)/256., (105-128)/256. },
250  { 0.60, 151/256., (50-128)/256., (146-128)/256. },
251  { 0.70, 191/256., (63-128)/256., (178-128)/256. },
252  { 1, 98/256., (80-128)/256., (221-128)/256. }},
253  [COOL] = {
254  { 0, 0, 0, 0 },
255  { .15, 0, .5, -.5 },
256  { 1, 1, -.5, .5 }},
257  [MAGMA] = {
258  { 0, 0, 0, 0 },
259  { 0.10, 23/256., (175-128)/256., (120-128)/256. },
260  { 0.23, 43/256., (158-128)/256., (144-128)/256. },
261  { 0.35, 85/256., (138-128)/256., (179-128)/256. },
262  { 0.48, 96/256., (128-128)/256., (189-128)/256. },
263  { 0.64, 128/256., (103-128)/256., (214-128)/256. },
264  { 0.92, 205/256., (80-128)/256., (152-128)/256. },
265  { 1, 1, 0, 0 }},
266  [GREEN] = {
267  { 0, 0, 0, 0 },
268  { .75, .5, 0, -.5 },
269  { 1, 1, 0, 0 }},
270  [VIRIDIS] = {
271  { 0, 0, 0, 0 },
272  { 0.10, 0x39/255., (0x9D -128)/255., (0x8F -128)/255. },
273  { 0.23, 0x5C/255., (0x9A -128)/255., (0x68 -128)/255. },
274  { 0.35, 0x69/255., (0x93 -128)/255., (0x57 -128)/255. },
275  { 0.48, 0x76/255., (0x88 -128)/255., (0x4B -128)/255. },
276  { 0.64, 0x8A/255., (0x72 -128)/255., (0x4F -128)/255. },
277  { 0.80, 0xA3/255., (0x50 -128)/255., (0x66 -128)/255. },
278  { 1, 0xCC/255., (0x2F -128)/255., (0x87 -128)/255. }},
279  [PLASMA] = {
280  { 0, 0, 0, 0 },
281  { 0.10, 0x27/255., (0xC2 -128)/255., (0x82 -128)/255. },
282  { 0.58, 0x5B/255., (0x9A -128)/255., (0xAE -128)/255. },
283  { 0.70, 0x89/255., (0x44 -128)/255., (0xAB -128)/255. },
284  { 0.80, 0xB4/255., (0x2B -128)/255., (0x9E -128)/255. },
285  { 0.91, 0xD2/255., (0x38 -128)/255., (0x92 -128)/255. },
286  { 1, 1, 0, 0. }},
287  [CIVIDIS] = {
288  { 0, 0, 0, 0 },
289  { 0.20, 0x28/255., (0x98 -128)/255., (0x6F -128)/255. },
290  { 0.50, 0x48/255., (0x95 -128)/255., (0x74 -128)/255. },
291  { 0.63, 0x69/255., (0x84 -128)/255., (0x7F -128)/255. },
292  { 0.76, 0x89/255., (0x75 -128)/255., (0x84 -128)/255. },
293  { 0.90, 0xCE/255., (0x35 -128)/255., (0x95 -128)/255. },
294  { 1, 1, 0, 0. }},
295  [TERRAIN] = {
296  { 0, 0, 0, 0 },
297  { 0.15, 0, .5, 0 },
298  { 0.60, 1, -.5, -.5 },
299  { 0.85, 1, -.5, .5 },
300  { 1, 1, 0, 0 }},
301 };
302 
304 {
305  ShowSpectrumContext *s = ctx->priv;
306  int i;
307 
308  av_freep(&s->combine_buffer);
309  if (s->fft) {
310  for (i = 0; i < s->nb_display_channels; i++)
311  av_tx_uninit(&s->fft[i]);
312  }
313  av_freep(&s->fft);
314  if (s->ifft) {
315  for (i = 0; i < s->nb_display_channels; i++)
316  av_tx_uninit(&s->ifft[i]);
317  }
318  av_freep(&s->ifft);
319  if (s->fft_data) {
320  for (i = 0; i < s->nb_display_channels; i++)
321  av_freep(&s->fft_data[i]);
322  }
323  av_freep(&s->fft_data);
324  if (s->fft_in) {
325  for (i = 0; i < s->nb_display_channels; i++)
326  av_freep(&s->fft_in[i]);
327  }
328  av_freep(&s->fft_in);
329  if (s->fft_scratch) {
330  for (i = 0; i < s->nb_display_channels; i++)
331  av_freep(&s->fft_scratch[i]);
332  }
333  av_freep(&s->fft_scratch);
334  if (s->color_buffer) {
335  for (i = 0; i < s->nb_display_channels; i++)
336  av_freep(&s->color_buffer[i]);
337  }
338  av_freep(&s->color_buffer);
339  av_freep(&s->window_func_lut);
340  if (s->magnitudes) {
341  for (i = 0; i < s->nb_display_channels; i++)
342  av_freep(&s->magnitudes[i]);
343  }
344  av_freep(&s->magnitudes);
345  av_frame_free(&s->outpicref);
346  av_frame_free(&s->in_frame);
347  if (s->phases) {
348  for (i = 0; i < s->nb_display_channels; i++)
349  av_freep(&s->phases[i]);
350  }
351  av_freep(&s->phases);
352 
353  while (s->nb_frames > 0) {
354  av_frame_free(&s->frames[s->nb_frames - 1]);
355  s->nb_frames--;
356  }
357 
358  av_freep(&s->frames);
359 }
360 
362 {
365  AVFilterLink *inlink = ctx->inputs[0];
366  AVFilterLink *outlink = ctx->outputs[0];
369  int ret;
370 
371  /* set input audio formats */
373  if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0)
374  return ret;
375 
377  if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0)
378  return ret;
379 
381  if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0)
382  return ret;
383 
384  /* set output video format */
386  if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0)
387  return ret;
388 
389  return 0;
390 }
391 
392 static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
393 {
394  ShowSpectrumContext *s = ctx->priv;
395  AVFilterLink *inlink = ctx->inputs[0];
396  const float *window_func_lut = s->window_func_lut;
397  AVFrame *fin = arg;
398  const int ch = jobnr;
399  int n;
400 
401  /* fill FFT input with the number of samples available */
402  const float *p = (float *)fin->extended_data[ch];
403  float *in_frame = (float *)s->in_frame->extended_data[ch];
404 
405  memmove(in_frame, in_frame + s->hop_size, (s->fft_size - s->hop_size) * sizeof(float));
406  memcpy(in_frame + s->fft_size - s->hop_size, p, fin->nb_samples * sizeof(float));
407 
408  for (int i = fin->nb_samples; i < s->hop_size; i++)
409  in_frame[i + s->fft_size - s->hop_size] = 0.f;
410 
411  if (s->stop) {
412  float theta, phi, psi, a, b, S, c;
413  AVComplexFloat *f = s->fft_in[ch];
414  AVComplexFloat *g = s->fft_data[ch];
415  AVComplexFloat *h = s->fft_scratch[ch];
416  int L = s->buf_size;
417  int N = s->win_size;
418  int M = s->win_size / 2;
419 
420  for (n = 0; n < s->win_size; n++) {
421  s->fft_data[ch][n].re = in_frame[n] * window_func_lut[n];
422  s->fft_data[ch][n].im = 0;
423  }
424 
425  phi = 2.f * M_PI * (s->stop - s->start) / (float)inlink->sample_rate / (M - 1);
426  theta = 2.f * M_PI * s->start / (float)inlink->sample_rate;
427 
428  for (int n = 0; n < M; n++) {
429  h[n].re = cosf(n * n / 2.f * phi);
430  h[n].im = sinf(n * n / 2.f * phi);
431  }
432 
433  for (int n = M; n < L; n++) {
434  h[n].re = 0.f;
435  h[n].im = 0.f;
436  }
437 
438  for (int n = L - N; n < L; n++) {
439  h[n].re = cosf((L - n) * (L - n) / 2.f * phi);
440  h[n].im = sinf((L - n) * (L - n) / 2.f * phi);
441  }
442 
443  for (int n = N; n < L; n++) {
444  g[n].re = 0.f;
445  g[n].im = 0.f;
446  }
447 
448  for (int n = 0; n < N; n++) {
449  psi = n * theta + n * n / 2.f * phi;
450  c = cosf(psi);
451  S = -sinf(psi);
452  a = c * g[n].re - S * g[n].im;
453  b = S * g[n].re + c * g[n].im;
454  g[n].re = a;
455  g[n].im = b;
456  }
457 
458  memcpy(f, h, s->buf_size * sizeof(*f));
459  s->tx_fn(s->fft[ch], h, f, sizeof(AVComplexFloat));
460 
461  memcpy(f, g, s->buf_size * sizeof(*f));
462  s->tx_fn(s->fft[ch], g, f, sizeof(AVComplexFloat));
463 
464  for (int n = 0; n < L; n++) {
465  c = g[n].re;
466  S = g[n].im;
467  a = c * h[n].re - S * h[n].im;
468  b = S * h[n].re + c * h[n].im;
469 
470  g[n].re = a / L;
471  g[n].im = b / L;
472  }
473 
474  memcpy(f, g, s->buf_size * sizeof(*f));
475  s->itx_fn(s->ifft[ch], g, f, sizeof(AVComplexFloat));
476 
477  for (int k = 0; k < M; k++) {
478  psi = k * k / 2.f * phi;
479  c = cosf(psi);
480  S = -sinf(psi);
481  a = c * g[k].re - S * g[k].im;
482  b = S * g[k].re + c * g[k].im;
483  s->fft_data[ch][k].re = a;
484  s->fft_data[ch][k].im = b;
485  }
486  } else {
487  for (n = 0; n < s->win_size; n++) {
488  s->fft_in[ch][n].re = in_frame[n] * window_func_lut[n];
489  s->fft_in[ch][n].im = 0;
490  }
491 
492  /* run FFT on each samples set */
493  s->tx_fn(s->fft[ch], s->fft_data[ch], s->fft_in[ch], sizeof(AVComplexFloat));
494  }
495 
496  return 0;
497 }
498 
499 static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
500 {
501  const uint8_t *font;
502  int font_height;
503 
504  font = avpriv_cga_font, font_height = 8;
505 
506  for (int i = 0; txt[i]; i++) {
507  int char_y, mask;
508 
509  if (o) {
510  for (char_y = font_height - 1; char_y >= 0; char_y--) {
511  uint8_t *p = pic->data[0] + (y + i * 10) * pic->linesize[0] + x;
512  for (mask = 0x80; mask; mask >>= 1) {
513  if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
514  p[char_y] = ~p[char_y];
515  p += pic->linesize[0];
516  }
517  }
518  } else {
519  uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8);
520  for (char_y = 0; char_y < font_height; char_y++) {
521  for (mask = 0x80; mask; mask >>= 1) {
522  if (font[txt[i] * font_height + char_y] & mask)
523  *p = ~(*p);
524  p++;
525  }
526  p += pic->linesize[0] - 8;
527  }
528  }
529  }
530 
531  for (int i = 0; txt[i] && pic->data[3]; i++) {
532  int char_y, mask;
533 
534  if (o) {
535  for (char_y = font_height - 1; char_y >= 0; char_y--) {
536  uint8_t *p = pic->data[3] + (y + i * 10) * pic->linesize[3] + x;
537  for (mask = 0x80; mask; mask >>= 1) {
538  for (int k = 0; k < 8; k++)
539  p[k] = 255;
540  p += pic->linesize[3];
541  }
542  }
543  } else {
544  uint8_t *p = pic->data[3] + y*pic->linesize[3] + (x + i*8);
545  for (char_y = 0; char_y < font_height; char_y++) {
546  for (mask = 0x80; mask; mask >>= 1)
547  *p++ = 255;
548  p += pic->linesize[3] - 8;
549  }
550  }
551  }
552 }
553 
554 static void color_range(ShowSpectrumContext *s, int ch,
555  float *yf, float *uf, float *vf)
556 {
557  switch (s->mode) {
558  case COMBINED:
559  // reduce range by channel count
560  *yf = 256.0f / s->nb_display_channels;
561  switch (s->color_mode) {
562  case RAINBOW:
563  case MORELAND:
564  case NEBULAE:
565  case FIRE:
566  case FIERY:
567  case FRUIT:
568  case COOL:
569  case GREEN:
570  case VIRIDIS:
571  case PLASMA:
572  case CIVIDIS:
573  case TERRAIN:
574  case MAGMA:
575  case INTENSITY:
576  *uf = *yf;
577  *vf = *yf;
578  break;
579  case CHANNEL:
580  /* adjust saturation for mixed UV coloring */
581  /* this factor is correct for infinite channels, an approximation otherwise */
582  *uf = *yf * M_PI;
583  *vf = *yf * M_PI;
584  break;
585  default:
586  av_assert0(0);
587  }
588  break;
589  case SEPARATE:
590  // full range
591  *yf = 256.0f;
592  *uf = 256.0f;
593  *vf = 256.0f;
594  break;
595  default:
596  av_assert0(0);
597  }
598 
599  if (s->color_mode == CHANNEL) {
600  if (s->nb_display_channels > 1) {
601  *uf *= 0.5f * sinf((2 * M_PI * ch) / s->nb_display_channels + M_PI * s->rotation);
602  *vf *= 0.5f * cosf((2 * M_PI * ch) / s->nb_display_channels + M_PI * s->rotation);
603  } else {
604  *uf *= 0.5f * sinf(M_PI * s->rotation);
605  *vf *= 0.5f * cosf(M_PI * s->rotation + M_PI_2);
606  }
607  } else {
608  *uf += *uf * sinf(M_PI * s->rotation);
609  *vf += *vf * cosf(M_PI * s->rotation + M_PI_2);
610  }
611 
612  *uf *= s->saturation;
613  *vf *= s->saturation;
614 }
615 
617  float yf, float uf, float vf,
618  float a, float *out)
619 {
620  const float af = s->opacity_factor * 255.f;
621 
622  if (s->color_mode > CHANNEL) {
623  const int cm = s->color_mode;
624  float y, u, v;
625  int i;
626 
627  for (i = 1; i < FF_ARRAY_ELEMS(color_table[cm]) - 1; i++)
628  if (color_table[cm][i].a >= a)
629  break;
630  // i now is the first item >= the color
631  // now we know to interpolate between item i - 1 and i
632  if (a <= color_table[cm][i - 1].a) {
633  y = color_table[cm][i - 1].y;
634  u = color_table[cm][i - 1].u;
635  v = color_table[cm][i - 1].v;
636  } else if (a >= color_table[cm][i].a) {
637  y = color_table[cm][i].y;
638  u = color_table[cm][i].u;
639  v = color_table[cm][i].v;
640  } else {
641  float start = color_table[cm][i - 1].a;
642  float end = color_table[cm][i].a;
643  float lerpfrac = (a - start) / (end - start);
644  y = color_table[cm][i - 1].y * (1.0f - lerpfrac)
645  + color_table[cm][i].y * lerpfrac;
646  u = color_table[cm][i - 1].u * (1.0f - lerpfrac)
647  + color_table[cm][i].u * lerpfrac;
648  v = color_table[cm][i - 1].v * (1.0f - lerpfrac)
649  + color_table[cm][i].v * lerpfrac;
650  }
651 
652  out[0] = y * yf;
653  out[1] = u * uf;
654  out[2] = v * vf;
655  out[3] = a * af;
656  } else {
657  out[0] = a * yf;
658  out[1] = a * uf;
659  out[2] = a * vf;
660  out[3] = a * af;
661  }
662 }
663 
664 static char *get_time(AVFilterContext *ctx, float seconds, int x)
665 {
666  char *units;
667 
668  if (x == 0)
669  units = av_asprintf("0");
670  else if (log10(seconds) > 6)
671  units = av_asprintf("%.2fh", seconds / (60 * 60));
672  else if (log10(seconds) > 3)
673  units = av_asprintf("%.2fm", seconds / 60);
674  else
675  units = av_asprintf("%.2fs", seconds);
676  return units;
677 }
678 
679 static float log_scale(const float bin,
680  const float bmin, const float bmax,
681  const float min, const float max)
682 {
683  return exp2f(((bin - bmin) / (bmax - bmin)) * (log2f(max) - log2f(min)) + log2f(min));
684 }
685 
686 static float get_hz(const float bin, const float bmax,
687  const float min, const float max,
688  int fscale)
689 {
690  switch (fscale) {
691  case F_LINEAR:
692  return min + (bin / bmax) * (max - min);
693  case F_LOG:
694  return min + log_scale(bin, 0, bmax, 20.f, max - min);
695  default:
696  return 0.f;
697  }
698 }
699 
700 static float inv_log_scale(float bin,
701  float bmin, float bmax,
702  float min, float max)
703 {
704  return (min * exp2f((bin * (log2f(max) - log2f(20.f))) / bmax) + min) * bmax / max;
705 }
706 
707 static float bin_pos(const int bin, const int num_bins, const float min, const float max)
708 {
709  return inv_log_scale(bin, 0.f, num_bins, 20.f, max - min);
710 }
711 
712 static float get_scale(AVFilterContext *ctx, int scale, float a)
713 {
714  ShowSpectrumContext *s = ctx->priv;
715  const float dmin = s->dmin;
716  const float dmax = s->dmax;
717 
718  a = av_clipf(a, dmin, dmax);
719  if (scale != LOG)
720  a = (a - dmin) / (dmax - dmin);
721 
722  switch (scale) {
723  case LINEAR:
724  break;
725  case SQRT:
726  a = sqrtf(a);
727  break;
728  case CBRT:
729  a = cbrtf(a);
730  break;
731  case FOURTHRT:
732  a = sqrtf(sqrtf(a));
733  break;
734  case FIFTHRT:
735  a = powf(a, 0.2f);
736  break;
737  case LOG:
738  a = (s->drange - s->limit + log10f(a) * 20.f) / s->drange;
739  break;
740  default:
741  av_assert0(0);
742  }
743 
744  return a;
745 }
746 
747 static float get_iscale(AVFilterContext *ctx, int scale, float a)
748 {
749  ShowSpectrumContext *s = ctx->priv;
750  const float dmin = s->dmin;
751  const float dmax = s->dmax;
752 
753  switch (scale) {
754  case LINEAR:
755  break;
756  case SQRT:
757  a = a * a;
758  break;
759  case CBRT:
760  a = a * a * a;
761  break;
762  case FOURTHRT:
763  a = a * a * a * a;
764  break;
765  case FIFTHRT:
766  a = a * a * a * a * a;
767  break;
768  case LOG:
769  a = expf(M_LN10 * (a * s->drange - s->drange + s->limit) / 20.f);
770  break;
771  default:
772  av_assert0(0);
773  }
774 
775  if (scale != LOG)
776  a = a * (dmax - dmin) + dmin;
777 
778  return a;
779 }
780 
781 static int draw_legend(AVFilterContext *ctx, uint64_t samples)
782 {
783  ShowSpectrumContext *s = ctx->priv;
784  AVFilterLink *inlink = ctx->inputs[0];
785  AVFilterLink *outlink = ctx->outputs[0];
786  int ch, y, x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
787  int multi = (s->mode == SEPARATE && s->color_mode == CHANNEL);
788  float spp = samples / (float)sz;
789  char *text;
790  uint8_t *dst;
791  char chlayout_str[128];
792 
793  av_channel_layout_describe(&inlink->ch_layout, chlayout_str, sizeof(chlayout_str));
794 
795  text = av_asprintf("%d Hz | %s", inlink->sample_rate, chlayout_str);
796  if (!text)
797  return AVERROR(ENOMEM);
798 
799  drawtext(s->outpicref, 2, outlink->h - 10, "CREATED BY LIBAVFILTER", 0);
800  drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, outlink->h - 10, text, 0);
801  av_freep(&text);
802  if (s->stop) {
803  text = av_asprintf("Zoom: %d Hz - %d Hz", s->start, s->stop);
804  if (!text)
805  return AVERROR(ENOMEM);
806  drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, 3, text, 0);
807  av_freep(&text);
808  }
809 
810  dst = s->outpicref->data[0] + (s->start_y - 1) * s->outpicref->linesize[0] + s->start_x - 1;
811  for (x = 0; x < s->w + 1; x++)
812  dst[x] = 200;
813  dst = s->outpicref->data[0] + (s->start_y + s->h) * s->outpicref->linesize[0] + s->start_x - 1;
814  for (x = 0; x < s->w + 1; x++)
815  dst[x] = 200;
816  for (y = 0; y < s->h + 2; y++) {
817  dst = s->outpicref->data[0] + (y + s->start_y - 1) * s->outpicref->linesize[0];
818  dst[s->start_x - 1] = 200;
819  dst[s->start_x + s->w] = 200;
820  }
821  if (s->orientation == VERTICAL) {
822  int h = s->mode == SEPARATE ? s->h / s->nb_display_channels : s->h;
823  int hh = s->mode == SEPARATE ? -(s->h % s->nb_display_channels) + 1 : 1;
824  for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {
825  for (y = 0; y < h; y += 20) {
826  dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - hh) * s->outpicref->linesize[0];
827  dst[s->start_x - 2] = 200;
828  dst[s->start_x + s->w + 1] = 200;
829  }
830  for (y = 0; y < h; y += 40) {
831  dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - hh) * s->outpicref->linesize[0];
832  dst[s->start_x - 3] = 200;
833  dst[s->start_x + s->w + 2] = 200;
834  }
835  dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x;
836  for (x = 0; x < s->w; x+=40)
837  dst[x] = 200;
838  dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x;
839  for (x = 0; x < s->w; x+=80)
840  dst[x] = 200;
841  dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x;
842  for (x = 0; x < s->w; x+=40) {
843  dst[x] = 200;
844  }
845  dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x;
846  for (x = 0; x < s->w; x+=80) {
847  dst[x] = 200;
848  }
849  for (y = 0; y < h; y += 40) {
850  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
851  float hertz = get_hz(y, h, s->start, s->start + range, s->fscale);
852  char *units;
853 
854  if (hertz == 0)
855  units = av_asprintf("DC");
856  else
857  units = av_asprintf("%.2f", hertz);
858  if (!units)
859  return AVERROR(ENOMEM);
860 
861  drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, h * (ch + 1) + s->start_y - y - 4 - hh, units, 0);
862  av_free(units);
863  }
864  }
865 
866  for (x = 0; x < s->w && s->single_pic; x+=80) {
867  float seconds = x * spp / inlink->sample_rate;
868  char *units = get_time(ctx, seconds, x);
869  if (!units)
870  return AVERROR(ENOMEM);
871 
872  drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->h + s->start_y + 6, units, 0);
873  drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->start_y - 12, units, 0);
874  av_free(units);
875  }
876 
877  drawtext(s->outpicref, outlink->w / 2 - 4 * 4, outlink->h - s->start_y / 2, "TIME", 0);
878  drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 14 * 4, "FREQUENCY (Hz)", 1);
879  } else {
880  int w = s->mode == SEPARATE ? s->w / s->nb_display_channels : s->w;
881  for (y = 0; y < s->h; y += 20) {
882  dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];
883  dst[s->start_x - 2] = 200;
884  dst[s->start_x + s->w + 1] = 200;
885  }
886  for (y = 0; y < s->h; y += 40) {
887  dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];
888  dst[s->start_x - 3] = 200;
889  dst[s->start_x + s->w + 2] = 200;
890  }
891  for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {
892  dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x + w * ch;
893  for (x = 0; x < w; x+=40)
894  dst[x] = 200;
895  dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x + w * ch;
896  for (x = 0; x < w; x+=80)
897  dst[x] = 200;
898  dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x + w * ch;
899  for (x = 0; x < w; x+=40) {
900  dst[x] = 200;
901  }
902  dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x + w * ch;
903  for (x = 0; x < w; x+=80) {
904  dst[x] = 200;
905  }
906  for (x = 0; x < w - 79; x += 80) {
907  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
908  float hertz = get_hz(x, w, s->start, s->start + range, s->fscale);
909  char *units;
910 
911  if (hertz == 0)
912  units = av_asprintf("DC");
913  else
914  units = av_asprintf("%.2f", hertz);
915  if (!units)
916  return AVERROR(ENOMEM);
917 
918  drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->start_y - 12, units, 0);
919  drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->h + s->start_y + 6, units, 0);
920  av_free(units);
921  }
922  }
923  for (y = 0; y < s->h && s->single_pic; y+=40) {
924  float seconds = y * spp / inlink->sample_rate;
925  char *units = get_time(ctx, seconds, x);
926  if (!units)
927  return AVERROR(ENOMEM);
928 
929  drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, s->start_y + y - 4, units, 0);
930  av_free(units);
931  }
932  drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 4 * 4, "TIME", 1);
933  drawtext(s->outpicref, outlink->w / 2 - 14 * 4, outlink->h - s->start_y / 2, "FREQUENCY (Hz)", 0);
934  }
935 
936  for (ch = 0; ch < (multi ? s->nb_display_channels : 1); ch++) {
937  int h = multi ? s->h / s->nb_display_channels : s->h;
938 
939  for (y = 0; y < h; y++) {
940  float out[4] = { 0., 127.5, 127.5, 0.f};
941  int chn;
942 
943  for (chn = 0; chn < (s->mode == SEPARATE ? 1 : s->nb_display_channels); chn++) {
944  float yf, uf, vf;
945  int channel = (multi) ? s->nb_display_channels - ch - 1 : chn;
946  float lout[4];
947 
948  color_range(s, channel, &yf, &uf, &vf);
949  pick_color(s, yf, uf, vf, y / (float)h, lout);
950  out[0] += lout[0];
951  out[1] += lout[1];
952  out[2] += lout[2];
953  out[3] += lout[3];
954  }
955  memset(s->outpicref->data[0]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0] + s->w + s->start_x + 20, av_clip_uint8(out[0]), 10);
956  memset(s->outpicref->data[1]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[1] + s->w + s->start_x + 20, av_clip_uint8(out[1]), 10);
957  memset(s->outpicref->data[2]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[2] + s->w + s->start_x + 20, av_clip_uint8(out[2]), 10);
958  if (s->outpicref->data[3])
959  memset(s->outpicref->data[3]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[3] + s->w + s->start_x + 20, av_clip_uint8(out[3]), 10);
960  }
961 
962  for (y = 0; ch == 0 && y < h + 5; y += 25) {
963  static const char *log_fmt = "%.0f";
964  static const char *lin_fmt = "%.3f";
965  const float a = av_clipf(1.f - y / (float)(h - 1), 0.f, 1.f);
966  const float value = s->scale == LOG ? log10f(get_iscale(ctx, s->scale, a)) * 20.f : get_iscale(ctx, s->scale, a);
967  char *text;
968 
969  text = av_asprintf(s->scale == LOG ? log_fmt : lin_fmt, value);
970  if (!text)
971  continue;
972  drawtext(s->outpicref, s->w + s->start_x + 35, s->start_y + y - 3, text, 0);
973  av_free(text);
974  }
975  }
976 
977  if (s->scale == LOG)
978  drawtext(s->outpicref, s->w + s->start_x + 22, s->start_y + s->h + 20, "dBFS", 0);
979 
980  return 0;
981 }
982 
983 static float get_value(AVFilterContext *ctx, int ch, int y)
984 {
985  ShowSpectrumContext *s = ctx->priv;
986  float *magnitudes = s->magnitudes[ch];
987  float *phases = s->phases[ch];
988  float a;
989 
990  switch (s->data) {
991  case D_MAGNITUDE:
992  /* get magnitude */
993  a = magnitudes[y];
994  break;
995  case D_UPHASE:
996  case D_PHASE:
997  /* get phase */
998  a = phases[y];
999  break;
1000  default:
1001  av_assert0(0);
1002  }
1003 
1004  return av_clipf(get_scale(ctx, s->scale, a), 0.f, 1.f);
1005 }
1006 
1007 static int plot_channel_lin(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1008 {
1009  ShowSpectrumContext *s = ctx->priv;
1010  const int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width;
1011  const int ch = jobnr;
1012  float yf, uf, vf;
1013  int y;
1014 
1015  /* decide color range */
1016  color_range(s, ch, &yf, &uf, &vf);
1017 
1018  /* draw the channel */
1019  for (y = 0; y < h; y++) {
1020  int row = (s->mode == COMBINED) ? y : ch * h + y;
1021  float *out = &s->color_buffer[ch][4 * row];
1022  float a = get_value(ctx, ch, y);
1023 
1024  pick_color(s, yf, uf, vf, a, out);
1025  }
1026 
1027  return 0;
1028 }
1029 
1030 static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1031 {
1032  ShowSpectrumContext *s = ctx->priv;
1033  AVFilterLink *inlink = ctx->inputs[0];
1034  const int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width;
1035  const int ch = jobnr;
1036  float yf, uf, vf;
1037 
1038  /* decide color range */
1039  color_range(s, ch, &yf, &uf, &vf);
1040 
1041  /* draw the channel */
1042  for (int yy = 0; yy < h; yy++) {
1043  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
1044  float pos = bin_pos(yy, h, s->start, s->start + range);
1045  float delta = pos - floorf(pos);
1046  float a0, a1;
1047 
1048  a0 = get_value(ctx, ch, av_clip(pos, 0, h-1));
1049  a1 = get_value(ctx, ch, av_clip(pos+1, 0, h-1));
1050  {
1051  int row = (s->mode == COMBINED) ? yy : ch * h + yy;
1052  float *out = &s->color_buffer[ch][4 * row];
1053 
1054  pick_color(s, yf, uf, vf, delta * a1 + (1.f - delta) * a0, out);
1055  }
1056  }
1057 
1058  return 0;
1059 }
1060 
1061 static int config_output(AVFilterLink *outlink)
1062 {
1063  AVFilterContext *ctx = outlink->src;
1064  AVFilterLink *inlink = ctx->inputs[0];
1065  ShowSpectrumContext *s = ctx->priv;
1066  int i, fft_size, h, w, ret;
1067  float overlap;
1068 
1069  s->old_pts = AV_NOPTS_VALUE;
1070  s->dmax = expf(s->limit * M_LN10 / 20.f);
1071  s->dmin = expf((s->limit - s->drange) * M_LN10 / 20.f);
1072 
1073  switch (s->fscale) {
1074  case F_LINEAR: s->plot_channel = plot_channel_lin; break;
1075  case F_LOG: s->plot_channel = plot_channel_log; break;
1076  default: return AVERROR_BUG;
1077  }
1078 
1079  s->stop = FFMIN(s->stop, inlink->sample_rate / 2);
1080  if ((s->stop || s->start) && s->stop <= s->start) {
1081  av_log(ctx, AV_LOG_ERROR, "Stop frequency should be greater than start.\n");
1082  return AVERROR(EINVAL);
1083  }
1084 
1085  if (!strcmp(ctx->filter->name, "showspectrumpic"))
1086  s->single_pic = 1;
1087 
1088  outlink->w = s->w;
1089  outlink->h = s->h;
1090  outlink->sample_aspect_ratio = (AVRational){1,1};
1091 
1092  if (s->legend) {
1093  s->start_x = (log10(inlink->sample_rate) + 1) * 25;
1094  s->start_y = 64;
1095  outlink->w += s->start_x * 2;
1096  outlink->h += s->start_y * 2;
1097  }
1098 
1099  h = (s->mode == COMBINED || s->orientation == HORIZONTAL) ? s->h : s->h / inlink->ch_layout.nb_channels;
1100  w = (s->mode == COMBINED || s->orientation == VERTICAL) ? s->w : s->w / inlink->ch_layout.nb_channels;
1101  s->channel_height = h;
1102  s->channel_width = w;
1103 
1104  if (s->orientation == VERTICAL) {
1105  /* FFT window size (precision) according to the requested output frame height */
1106  fft_size = h * 2;
1107  } else {
1108  /* FFT window size (precision) according to the requested output frame width */
1109  fft_size = w * 2;
1110  }
1111 
1112  s->win_size = fft_size;
1113  s->buf_size = FFALIGN(s->win_size << (!!s->stop), av_cpu_max_align());
1114 
1115  if (!s->fft) {
1116  s->fft = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->fft));
1117  if (!s->fft)
1118  return AVERROR(ENOMEM);
1119  }
1120 
1121  if (s->stop) {
1122  if (!s->ifft) {
1123  s->ifft = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->ifft));
1124  if (!s->ifft)
1125  return AVERROR(ENOMEM);
1126  }
1127  }
1128 
1129  /* (re-)configuration if the video output changed (or first init) */
1130  if (fft_size != s->fft_size) {
1131  AVFrame *outpicref;
1132 
1133  s->fft_size = fft_size;
1134 
1135  /* FFT buffers: x2 for each (display) channel buffer.
1136  * Note: we use free and malloc instead of a realloc-like function to
1137  * make sure the buffer is aligned in memory for the FFT functions. */
1138  for (i = 0; i < s->nb_display_channels; i++) {
1139  if (s->stop) {
1140  av_tx_uninit(&s->ifft[i]);
1141  av_freep(&s->fft_scratch[i]);
1142  }
1143  av_tx_uninit(&s->fft[i]);
1144  av_freep(&s->fft_in[i]);
1145  av_freep(&s->fft_data[i]);
1146  }
1147  av_freep(&s->fft_data);
1148 
1149  s->nb_display_channels = inlink->ch_layout.nb_channels;
1150  for (i = 0; i < s->nb_display_channels; i++) {
1151  float scale = 1.f;
1152 
1153  ret = av_tx_init(&s->fft[i], &s->tx_fn, AV_TX_FLOAT_FFT, 0, fft_size << (!!s->stop), &scale, 0);
1154  if (s->stop) {
1155  ret = av_tx_init(&s->ifft[i], &s->itx_fn, AV_TX_FLOAT_FFT, 1, fft_size << (!!s->stop), &scale, 0);
1156  if (ret < 0) {
1157  av_log(ctx, AV_LOG_ERROR, "Unable to create Inverse FFT context. "
1158  "The window size might be too high.\n");
1159  return ret;
1160  }
1161  }
1162  if (ret < 0) {
1163  av_log(ctx, AV_LOG_ERROR, "Unable to create FFT context. "
1164  "The window size might be too high.\n");
1165  return ret;
1166  }
1167  }
1168 
1169  s->magnitudes = av_calloc(s->nb_display_channels, sizeof(*s->magnitudes));
1170  if (!s->magnitudes)
1171  return AVERROR(ENOMEM);
1172  for (i = 0; i < s->nb_display_channels; i++) {
1173  s->magnitudes[i] = av_calloc(s->orientation == VERTICAL ? s->h : s->w, sizeof(**s->magnitudes));
1174  if (!s->magnitudes[i])
1175  return AVERROR(ENOMEM);
1176  }
1177 
1178  s->phases = av_calloc(s->nb_display_channels, sizeof(*s->phases));
1179  if (!s->phases)
1180  return AVERROR(ENOMEM);
1181  for (i = 0; i < s->nb_display_channels; i++) {
1182  s->phases[i] = av_calloc(s->orientation == VERTICAL ? s->h : s->w, sizeof(**s->phases));
1183  if (!s->phases[i])
1184  return AVERROR(ENOMEM);
1185  }
1186 
1187  av_freep(&s->color_buffer);
1188  s->color_buffer = av_calloc(s->nb_display_channels, sizeof(*s->color_buffer));
1189  if (!s->color_buffer)
1190  return AVERROR(ENOMEM);
1191  for (i = 0; i < s->nb_display_channels; i++) {
1192  s->color_buffer[i] = av_calloc(s->orientation == VERTICAL ? s->h * 4 : s->w * 4, sizeof(**s->color_buffer));
1193  if (!s->color_buffer[i])
1194  return AVERROR(ENOMEM);
1195  }
1196 
1197  s->fft_in = av_calloc(s->nb_display_channels, sizeof(*s->fft_in));
1198  if (!s->fft_in)
1199  return AVERROR(ENOMEM);
1200  s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data));
1201  if (!s->fft_data)
1202  return AVERROR(ENOMEM);
1203  s->fft_scratch = av_calloc(s->nb_display_channels, sizeof(*s->fft_scratch));
1204  if (!s->fft_scratch)
1205  return AVERROR(ENOMEM);
1206  for (i = 0; i < s->nb_display_channels; i++) {
1207  s->fft_in[i] = av_calloc(s->buf_size, sizeof(**s->fft_in));
1208  if (!s->fft_in[i])
1209  return AVERROR(ENOMEM);
1210 
1211  s->fft_data[i] = av_calloc(s->buf_size, sizeof(**s->fft_data));
1212  if (!s->fft_data[i])
1213  return AVERROR(ENOMEM);
1214 
1215  s->fft_scratch[i] = av_calloc(s->buf_size, sizeof(**s->fft_scratch));
1216  if (!s->fft_scratch[i])
1217  return AVERROR(ENOMEM);
1218  }
1219 
1220  /* pre-calc windowing function */
1221  s->window_func_lut =
1222  av_realloc_f(s->window_func_lut, s->win_size,
1223  sizeof(*s->window_func_lut));
1224  if (!s->window_func_lut)
1225  return AVERROR(ENOMEM);
1226  generate_window_func(s->window_func_lut, s->win_size, s->win_func, &overlap);
1227  if (s->overlap == 1)
1228  s->overlap = overlap;
1229  s->hop_size = (1.f - s->overlap) * s->win_size;
1230  if (s->hop_size < 1) {
1231  av_log(ctx, AV_LOG_ERROR, "overlap %f too big\n", s->overlap);
1232  return AVERROR(EINVAL);
1233  }
1234 
1235  for (s->win_scale = 0, i = 0; i < s->win_size; i++) {
1236  s->win_scale += s->window_func_lut[i] * s->window_func_lut[i];
1237  }
1238  s->win_scale = 1.f / sqrtf(s->win_scale);
1239 
1240  /* prepare the initial picref buffer (black frame) */
1241  av_frame_free(&s->outpicref);
1242  s->outpicref = outpicref =
1243  ff_get_video_buffer(outlink, outlink->w, outlink->h);
1244  if (!outpicref)
1245  return AVERROR(ENOMEM);
1246  outpicref->sample_aspect_ratio = (AVRational){1,1};
1247  for (i = 0; i < outlink->h; i++) {
1248  memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w);
1249  memset(outpicref->data[1] + i * outpicref->linesize[1], 128, outlink->w);
1250  memset(outpicref->data[2] + i * outpicref->linesize[2], 128, outlink->w);
1251  if (outpicref->data[3])
1252  memset(outpicref->data[3] + i * outpicref->linesize[3], 0, outlink->w);
1253  }
1254  outpicref->color_range = AVCOL_RANGE_JPEG;
1255 
1256  if (!s->single_pic && s->legend)
1257  draw_legend(ctx, 0);
1258  }
1259 
1260  if ((s->orientation == VERTICAL && s->xpos >= s->w) ||
1261  (s->orientation == HORIZONTAL && s->xpos >= s->h))
1262  s->xpos = 0;
1263 
1264  if (s->sliding == LREPLACE) {
1265  if (s->orientation == VERTICAL)
1266  s->xpos = s->w - 1;
1267  if (s->orientation == HORIZONTAL)
1268  s->xpos = s->h - 1;
1269  }
1270 
1271  s->auto_frame_rate = av_make_q(inlink->sample_rate, s->hop_size);
1272  if (s->orientation == VERTICAL && s->sliding == FULLFRAME)
1273  s->auto_frame_rate = av_mul_q(s->auto_frame_rate, av_make_q(1, s->w));
1274  if (s->orientation == HORIZONTAL && s->sliding == FULLFRAME)
1275  s->auto_frame_rate = av_mul_q(s->auto_frame_rate, av_make_q(1, s->h));
1276  if (!s->single_pic && strcmp(s->rate_str, "auto")) {
1277  int ret = av_parse_video_rate(&s->frame_rate, s->rate_str);
1278  if (ret < 0)
1279  return ret;
1280  } else if (s->single_pic) {
1281  s->frame_rate = av_make_q(1, 1);
1282  } else {
1283  s->frame_rate = s->auto_frame_rate;
1284  }
1285  outlink->frame_rate = s->frame_rate;
1286  outlink->time_base = av_inv_q(outlink->frame_rate);
1287 
1288  if (s->orientation == VERTICAL) {
1289  s->combine_buffer =
1290  av_realloc_f(s->combine_buffer, s->h * 4,
1291  sizeof(*s->combine_buffer));
1292  } else {
1293  s->combine_buffer =
1294  av_realloc_f(s->combine_buffer, s->w * 4,
1295  sizeof(*s->combine_buffer));
1296  }
1297  if (!s->combine_buffer)
1298  return AVERROR(ENOMEM);
1299 
1300  av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d FFT window size:%d\n",
1301  s->w, s->h, s->win_size);
1302 
1303  s->in_frame = ff_get_audio_buffer(inlink, s->win_size);
1304  if (!s->in_frame)
1305  return AVERROR(ENOMEM);
1306 
1307  s->frames = av_fast_realloc(NULL, &s->frames_size,
1308  DEFAULT_LENGTH * sizeof(*(s->frames)));
1309  if (!s->frames)
1310  return AVERROR(ENOMEM);
1311 
1312  return 0;
1313 }
1314 
1315 #define RE(y, ch) s->fft_data[ch][y].re
1316 #define IM(y, ch) s->fft_data[ch][y].im
1317 #define MAGNITUDE(y, ch) hypotf(RE(y, ch), IM(y, ch))
1318 #define PHASE(y, ch) atan2f(IM(y, ch), RE(y, ch))
1319 
1320 static int calc_channel_magnitudes(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1321 {
1322  ShowSpectrumContext *s = ctx->priv;
1323  const double w = s->win_scale * (s->scale == LOG ? s->win_scale : 1);
1324  int y, h = s->orientation == VERTICAL ? s->h : s->w;
1325  const float f = s->gain * w;
1326  const int ch = jobnr;
1327  float *magnitudes = s->magnitudes[ch];
1328 
1329  for (y = 0; y < h; y++)
1330  magnitudes[y] = MAGNITUDE(y, ch) * f;
1331 
1332  return 0;
1333 }
1334 
1335 static int calc_channel_phases(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1336 {
1337  ShowSpectrumContext *s = ctx->priv;
1338  const int h = s->orientation == VERTICAL ? s->h : s->w;
1339  const int ch = jobnr;
1340  float *phases = s->phases[ch];
1341  int y;
1342 
1343  for (y = 0; y < h; y++)
1344  phases[y] = (PHASE(y, ch) / M_PI + 1) / 2;
1345 
1346  return 0;
1347 }
1348 
1349 static void unwrap(float *x, int N, float tol, float *mi, float *ma)
1350 {
1351  const float rng = 2.f * M_PI;
1352  float prev_p = 0.f;
1353  float max = -FLT_MAX;
1354  float min = FLT_MAX;
1355 
1356  for (int i = 0; i < N; i++) {
1357  const float d = x[FFMIN(i + 1, N)] - x[i];
1358  const float p = ceilf(fabsf(d) / rng) * rng * (((d < tol) > 0.f) - ((d > -tol) > 0.f));
1359 
1360  x[i] += p + prev_p;
1361  prev_p += p;
1362  max = fmaxf(x[i], max);
1363  min = fminf(x[i], min);
1364  }
1365 
1366  *mi = min;
1367  *ma = max;
1368 }
1369 
1370 static int calc_channel_uphases(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1371 {
1372  ShowSpectrumContext *s = ctx->priv;
1373  const int h = s->orientation == VERTICAL ? s->h : s->w;
1374  const int ch = jobnr;
1375  float *phases = s->phases[ch];
1376  float min, max, scale;
1377  int y;
1378 
1379  for (y = 0; y < h; y++)
1380  phases[y] = PHASE(y, ch);
1381  unwrap(phases, h, M_PI, &min, &max);
1382  scale = 1.f / (max - min + FLT_MIN);
1383  for (y = 0; y < h; y++)
1384  phases[y] = fabsf((phases[y] - min) * scale);
1385 
1386  return 0;
1387 }
1388 
1390 {
1391  const double w = s->win_scale * (s->scale == LOG ? s->win_scale : 1);
1392  int ch, y, h = s->orientation == VERTICAL ? s->h : s->w;
1393  const float f = s->gain * w;
1394 
1395  for (ch = 0; ch < s->nb_display_channels; ch++) {
1396  float *magnitudes = s->magnitudes[ch];
1397 
1398  for (y = 0; y < h; y++)
1399  magnitudes[y] += MAGNITUDE(y, ch) * f;
1400  }
1401 }
1402 
1404 {
1405  int ch, y, h = s->orientation == VERTICAL ? s->h : s->w;
1406 
1407  for (ch = 0; ch < s->nb_display_channels; ch++) {
1408  float *magnitudes = s->magnitudes[ch];
1409 
1410  for (y = 0; y < h; y++)
1411  magnitudes[y] *= scale;
1412  }
1413 }
1414 
1416 {
1417  int y;
1418 
1419  for (y = 0; y < size; y++) {
1420  s->combine_buffer[4 * y ] = 0;
1421  s->combine_buffer[4 * y + 1] = 127.5;
1422  s->combine_buffer[4 * y + 2] = 127.5;
1423  s->combine_buffer[4 * y + 3] = 0;
1424  }
1425 }
1426 
1428 {
1429  AVFilterContext *ctx = inlink->dst;
1430  AVFilterLink *outlink = ctx->outputs[0];
1431  ShowSpectrumContext *s = ctx->priv;
1432  AVFrame *outpicref = s->outpicref;
1433  int ret, plane, x, y, z = s->orientation == VERTICAL ? s->h : s->w;
1434  const int alpha = outpicref->data[3] != NULL;
1435 
1436  /* fill a new spectrum column */
1437  /* initialize buffer for combining to black */
1438  clear_combine_buffer(s, z);
1439 
1440  ff_filter_execute(ctx, s->plot_channel, NULL, NULL, s->nb_display_channels);
1441 
1442  for (y = 0; y < z * 4; y++) {
1443  for (x = 0; x < s->nb_display_channels; x++) {
1444  s->combine_buffer[y] += s->color_buffer[x][y];
1445  }
1446  }
1447 
1448  ret = ff_inlink_make_frame_writable(outlink, &s->outpicref);
1449  if (ret < 0)
1450  return ret;
1451  outpicref = s->outpicref;
1452  /* copy to output */
1453  if (s->orientation == VERTICAL) {
1454  if (s->sliding == SCROLL) {
1455  for (plane = 0; plane < 3 + alpha; plane++) {
1456  for (y = 0; y < s->h; y++) {
1457  uint8_t *p = outpicref->data[plane] + s->start_x +
1458  (y + s->start_y) * outpicref->linesize[plane];
1459  memmove(p, p + 1, s->w - 1);
1460  }
1461  }
1462  s->xpos = s->w - 1;
1463  } else if (s->sliding == RSCROLL) {
1464  for (plane = 0; plane < 3 + alpha; plane++) {
1465  for (y = 0; y < s->h; y++) {
1466  uint8_t *p = outpicref->data[plane] + s->start_x +
1467  (y + s->start_y) * outpicref->linesize[plane];
1468  memmove(p + 1, p, s->w - 1);
1469  }
1470  }
1471  s->xpos = 0;
1472  }
1473  for (plane = 0; plane < 3; plane++) {
1474  uint8_t *p = outpicref->data[plane] + s->start_x +
1475  (outlink->h - 1 - s->start_y) * outpicref->linesize[plane] +
1476  s->xpos;
1477  for (y = 0; y < s->h; y++) {
1478  *p = lrintf(av_clipf(s->combine_buffer[4 * y + plane], 0, 255));
1479  p -= outpicref->linesize[plane];
1480  }
1481  }
1482  if (alpha) {
1483  uint8_t *p = outpicref->data[3] + s->start_x +
1484  (outlink->h - 1 - s->start_y) * outpicref->linesize[3] +
1485  s->xpos;
1486  for (y = 0; y < s->h; y++) {
1487  *p = lrintf(av_clipf(s->combine_buffer[4 * y + 3], 0, 255));
1488  p -= outpicref->linesize[3];
1489  }
1490  }
1491  } else {
1492  if (s->sliding == SCROLL) {
1493  for (plane = 0; plane < 3 + alpha; plane++) {
1494  for (y = 1; y < s->h; y++) {
1495  memmove(outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x,
1496  outpicref->data[plane] + (y + s->start_y) * outpicref->linesize[plane] + s->start_x,
1497  s->w);
1498  }
1499  }
1500  s->xpos = s->h - 1;
1501  } else if (s->sliding == RSCROLL) {
1502  for (plane = 0; plane < 3 + alpha; plane++) {
1503  for (y = s->h - 1; y >= 1; y--) {
1504  memmove(outpicref->data[plane] + (y + s->start_y) * outpicref->linesize[plane] + s->start_x,
1505  outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x,
1506  s->w);
1507  }
1508  }
1509  s->xpos = 0;
1510  }
1511  for (plane = 0; plane < 3; plane++) {
1512  uint8_t *p = outpicref->data[plane] + s->start_x +
1513  (s->xpos + s->start_y) * outpicref->linesize[plane];
1514  for (x = 0; x < s->w; x++) {
1515  *p = lrintf(av_clipf(s->combine_buffer[4 * x + plane], 0, 255));
1516  p++;
1517  }
1518  }
1519  if (alpha) {
1520  uint8_t *p = outpicref->data[3] + s->start_x +
1521  (s->xpos + s->start_y) * outpicref->linesize[3];
1522  for (x = 0; x < s->w; x++) {
1523  *p = lrintf(av_clipf(s->combine_buffer[4 * x + 3], 0, 255));
1524  p++;
1525  }
1526  }
1527  }
1528 
1529  if (s->sliding != FULLFRAME || s->xpos == 0)
1530  s->pts = outpicref->pts = av_rescale_q(s->in_pts, inlink->time_base, outlink->time_base);
1531 
1532  if (s->sliding == LREPLACE) {
1533  s->xpos--;
1534  if (s->orientation == VERTICAL && s->xpos < 0)
1535  s->xpos = s->w - 1;
1536  if (s->orientation == HORIZONTAL && s->xpos < 0)
1537  s->xpos = s->h - 1;
1538  } else {
1539  s->xpos++;
1540  if (s->orientation == VERTICAL && s->xpos >= s->w)
1541  s->xpos = 0;
1542  if (s->orientation == HORIZONTAL && s->xpos >= s->h)
1543  s->xpos = 0;
1544  }
1545 
1546  if (!s->single_pic && (s->sliding != FULLFRAME || s->xpos == 0)) {
1547  if (s->old_pts < outpicref->pts || s->sliding == FULLFRAME ||
1548  (s->eof && ff_inlink_queued_samples(inlink) <= s->hop_size)) {
1549  AVFrame *clone;
1550 
1551  if (s->legend) {
1552  char *units = get_time(ctx, insamples->pts /(float)inlink->sample_rate, x);
1553  if (!units)
1554  return AVERROR(ENOMEM);
1555 
1556  if (s->orientation == VERTICAL) {
1557  for (y = 0; y < 10; y++) {
1558  memset(s->outpicref->data[0] + outlink->w / 2 - 4 * s->old_len +
1559  (outlink->h - s->start_y / 2 - 20 + y) * s->outpicref->linesize[0], 0, 10 * s->old_len);
1560  }
1561  drawtext(s->outpicref,
1562  outlink->w / 2 - 4 * strlen(units),
1563  outlink->h - s->start_y / 2 - 20,
1564  units, 0);
1565  } else {
1566  for (y = 0; y < 10 * s->old_len; y++) {
1567  memset(s->outpicref->data[0] + s->start_x / 7 + 20 +
1568  (outlink->h / 2 - 4 * s->old_len + y) * s->outpicref->linesize[0], 0, 10);
1569  }
1570  drawtext(s->outpicref,
1571  s->start_x / 7 + 20,
1572  outlink->h / 2 - 4 * strlen(units),
1573  units, 1);
1574  }
1575  s->old_len = strlen(units);
1576  av_free(units);
1577  }
1578  s->old_pts = outpicref->pts;
1579  clone = av_frame_clone(s->outpicref);
1580  if (!clone)
1581  return AVERROR(ENOMEM);
1582  ret = ff_filter_frame(outlink, clone);
1583  if (ret < 0)
1584  return ret;
1585  return 0;
1586  }
1587  }
1588 
1589  return 1;
1590 }
1591 
1592 #if CONFIG_SHOWSPECTRUM_FILTER
1593 
1594 static int activate(AVFilterContext *ctx)
1595 {
1596  AVFilterLink *inlink = ctx->inputs[0];
1597  AVFilterLink *outlink = ctx->outputs[0];
1598  ShowSpectrumContext *s = ctx->priv;
1599  int ret, status;
1600  int64_t pts;
1601 
1603 
1604  if (s->outpicref && ff_inlink_queued_samples(inlink) > 0) {
1605  AVFrame *fin;
1606 
1607  ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &fin);
1608  if (ret < 0)
1609  return ret;
1610  if (ret > 0) {
1611  ff_filter_execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
1612 
1613  if (s->data == D_MAGNITUDE)
1614  ff_filter_execute(ctx, calc_channel_magnitudes, NULL, NULL, s->nb_display_channels);
1615 
1616  if (s->data == D_PHASE)
1617  ff_filter_execute(ctx, calc_channel_phases, NULL, NULL, s->nb_display_channels);
1618 
1619  if (s->data == D_UPHASE)
1620  ff_filter_execute(ctx, calc_channel_uphases, NULL, NULL, s->nb_display_channels);
1621 
1622  if (s->sliding != FULLFRAME || s->xpos == 0)
1623  s->in_pts = fin->pts;
1625  av_frame_free(&fin);
1626  if (ret <= 0)
1627  return ret;
1628  }
1629  }
1630 
1631  if (s->eof && s->sliding == FULLFRAME &&
1632  s->xpos > 0 && s->outpicref) {
1633 
1634  if (s->orientation == VERTICAL) {
1635  for (int i = 0; i < outlink->h; i++) {
1636  memset(s->outpicref->data[0] + i * s->outpicref->linesize[0] + s->xpos, 0, outlink->w - s->xpos);
1637  memset(s->outpicref->data[1] + i * s->outpicref->linesize[1] + s->xpos, 128, outlink->w - s->xpos);
1638  memset(s->outpicref->data[2] + i * s->outpicref->linesize[2] + s->xpos, 128, outlink->w - s->xpos);
1639  if (s->outpicref->data[3])
1640  memset(s->outpicref->data[3] + i * s->outpicref->linesize[3] + s->xpos, 0, outlink->w - s->xpos);
1641  }
1642  } else {
1643  for (int i = s->xpos; i < outlink->h; i++) {
1644  memset(s->outpicref->data[0] + i * s->outpicref->linesize[0], 0, outlink->w);
1645  memset(s->outpicref->data[1] + i * s->outpicref->linesize[1], 128, outlink->w);
1646  memset(s->outpicref->data[2] + i * s->outpicref->linesize[2], 128, outlink->w);
1647  if (s->outpicref->data[3])
1648  memset(s->outpicref->data[3] + i * s->outpicref->linesize[3], 0, outlink->w);
1649  }
1650  }
1651  s->outpicref->pts = av_rescale_q(s->in_pts, inlink->time_base, outlink->time_base);
1652  pts = s->outpicref->pts;
1653  ret = ff_filter_frame(outlink, s->outpicref);
1654  s->outpicref = NULL;
1656  return 0;
1657  }
1658 
1659  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
1660  s->eof = status == AVERROR_EOF;
1661  ff_filter_set_ready(ctx, 100);
1662  return 0;
1663  }
1664 
1665  if (s->eof) {
1666  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
1667  return 0;
1668  }
1669 
1670  if (ff_inlink_queued_samples(inlink) >= s->hop_size) {
1671  ff_filter_set_ready(ctx, 10);
1672  return 0;
1673  }
1674 
1675  if (ff_outlink_frame_wanted(outlink)) {
1677  return 0;
1678  }
1679 
1680  return FFERROR_NOT_READY;
1681 }
1682 
1683 static const AVFilterPad showspectrum_outputs[] = {
1684  {
1685  .name = "default",
1686  .type = AVMEDIA_TYPE_VIDEO,
1687  .config_props = config_output,
1688  },
1689 };
1690 
1691 const AVFilter ff_avf_showspectrum = {
1692  .name = "showspectrum",
1693  .description = NULL_IF_CONFIG_SMALL("Convert input audio to a spectrum video output."),
1694  .uninit = uninit,
1695  .priv_size = sizeof(ShowSpectrumContext),
1697  FILTER_OUTPUTS(showspectrum_outputs),
1699  .activate = activate,
1700  .priv_class = &showspectrum_class,
1701  .flags = AVFILTER_FLAG_SLICE_THREADS,
1702 };
1703 #endif // CONFIG_SHOWSPECTRUM_FILTER
1704 
1705 #if CONFIG_SHOWSPECTRUMPIC_FILTER
1706 
1707 static const AVOption showspectrumpic_options[] = {
1708  { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "4096x2048"}, 0, 0, FLAGS },
1709  { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "4096x2048"}, 0, 0, FLAGS },
1710  { "mode", "set channel display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=COMBINED}, 0, NB_MODES-1, FLAGS, "mode" },
1711  { "combined", "combined mode", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, "mode" },
1712  { "separate", "separate mode", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "mode" },
1713  { "color", "set channel coloring", OFFSET(color_mode), AV_OPT_TYPE_INT, {.i64=INTENSITY}, 0, NB_CLMODES-1, FLAGS, "color" },
1714  { "channel", "separate color for each channel", 0, AV_OPT_TYPE_CONST, {.i64=CHANNEL}, 0, 0, FLAGS, "color" },
1715  { "intensity", "intensity based coloring", 0, AV_OPT_TYPE_CONST, {.i64=INTENSITY}, 0, 0, FLAGS, "color" },
1716  { "rainbow", "rainbow based coloring", 0, AV_OPT_TYPE_CONST, {.i64=RAINBOW}, 0, 0, FLAGS, "color" },
1717  { "moreland", "moreland based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MORELAND}, 0, 0, FLAGS, "color" },
1718  { "nebulae", "nebulae based coloring", 0, AV_OPT_TYPE_CONST, {.i64=NEBULAE}, 0, 0, FLAGS, "color" },
1719  { "fire", "fire based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIRE}, 0, 0, FLAGS, "color" },
1720  { "fiery", "fiery based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIERY}, 0, 0, FLAGS, "color" },
1721  { "fruit", "fruit based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FRUIT}, 0, 0, FLAGS, "color" },
1722  { "cool", "cool based coloring", 0, AV_OPT_TYPE_CONST, {.i64=COOL}, 0, 0, FLAGS, "color" },
1723  { "magma", "magma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MAGMA}, 0, 0, FLAGS, "color" },
1724  { "green", "green based coloring", 0, AV_OPT_TYPE_CONST, {.i64=GREEN}, 0, 0, FLAGS, "color" },
1725  { "viridis", "viridis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=VIRIDIS}, 0, 0, FLAGS, "color" },
1726  { "plasma", "plasma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=PLASMA}, 0, 0, FLAGS, "color" },
1727  { "cividis", "cividis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=CIVIDIS}, 0, 0, FLAGS, "color" },
1728  { "terrain", "terrain based coloring", 0, AV_OPT_TYPE_CONST, {.i64=TERRAIN}, 0, 0, FLAGS, "color" },
1729  { "scale", "set display scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=LOG}, 0, NB_SCALES-1, FLAGS, "scale" },
1730  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, "scale" },
1731  { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SQRT}, 0, 0, FLAGS, "scale" },
1732  { "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=CBRT}, 0, 0, FLAGS, "scale" },
1733  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, FLAGS, "scale" },
1734  { "4thrt","4th root", 0, AV_OPT_TYPE_CONST, {.i64=FOURTHRT}, 0, 0, FLAGS, "scale" },
1735  { "5thrt","5th root", 0, AV_OPT_TYPE_CONST, {.i64=FIFTHRT}, 0, 0, FLAGS, "scale" },
1736  { "fscale", "set frequency scale", OFFSET(fscale), AV_OPT_TYPE_INT, {.i64=F_LINEAR}, 0, NB_FSCALES-1, FLAGS, "fscale" },
1737  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=F_LINEAR}, 0, 0, FLAGS, "fscale" },
1738  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=F_LOG}, 0, 0, FLAGS, "fscale" },
1739  { "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS },
1740  WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_HANNING),
1741  { "orientation", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=VERTICAL}, 0, NB_ORIENTATIONS-1, FLAGS, "orientation" },
1742  { "vertical", NULL, 0, AV_OPT_TYPE_CONST, {.i64=VERTICAL}, 0, 0, FLAGS, "orientation" },
1743  { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=HORIZONTAL}, 0, 0, FLAGS, "orientation" },
1744  { "gain", "set scale gain", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 128, FLAGS },
1745  { "legend", "draw legend", OFFSET(legend), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS },
1746  { "rotation", "color rotation", OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -1, 1, FLAGS },
1747  { "start", "start frequency", OFFSET(start), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
1748  { "stop", "stop frequency", OFFSET(stop), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
1749  { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS },
1750  { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS },
1751  { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS },
1752  { NULL }
1753 };
1754 
1755 AVFILTER_DEFINE_CLASS(showspectrumpic);
1756 
1757 static int showspectrumpic_request_frame(AVFilterLink *outlink)
1758 {
1759  AVFilterContext *ctx = outlink->src;
1760  ShowSpectrumContext *s = ctx->priv;
1761  AVFilterLink *inlink = ctx->inputs[0];
1762  int ret;
1763 
1765  if (ret == AVERROR_EOF && s->outpicref && s->samples > 0) {
1766  int consumed = 0;
1767  int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
1768  unsigned int nb_frame = 0;
1769  int ch, spf, spb;
1770  int src_offset = 0;
1771  AVFrame *fin;
1772 
1773  spf = s->win_size * (s->samples / ((s->win_size * sz) * ceil(s->samples / (float)(s->win_size * sz))));
1774  spf = FFMAX(1, spf);
1775  s->hop_size = spf;
1776 
1777  spb = (s->samples / (spf * sz)) * spf;
1778 
1779  fin = ff_get_audio_buffer(inlink, spf);
1780  if (!fin)
1781  return AVERROR(ENOMEM);
1782 
1783  while (x < sz) {
1784  int acc_samples = 0;
1785  int dst_offset = 0;
1786 
1787  while (nb_frame < s->nb_frames) {
1788  AVFrame *cur_frame = s->frames[nb_frame];
1789  int cur_frame_samples = cur_frame->nb_samples;
1790  int nb_samples = 0;
1791 
1792  if (acc_samples < spf) {
1793  nb_samples = FFMIN(spf - acc_samples, cur_frame_samples - src_offset);
1794  acc_samples += nb_samples;
1795  av_samples_copy(fin->extended_data, cur_frame->extended_data,
1796  dst_offset, src_offset, nb_samples,
1798  }
1799 
1800  src_offset += nb_samples;
1801  dst_offset += nb_samples;
1802  if (cur_frame_samples <= src_offset) {
1803  av_frame_free(&s->frames[nb_frame]);
1804  nb_frame++;
1805  src_offset = 0;
1806  }
1807 
1808  if (acc_samples == spf)
1809  break;
1810  }
1811 
1812  ff_filter_execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
1814 
1815  consumed += spf;
1816  if (consumed >= spb) {
1817  int h = s->orientation == VERTICAL ? s->h : s->w;
1818 
1819  scale_magnitudes(s, 1.f / (consumed / spf));
1821  consumed = 0;
1822  x++;
1823  for (ch = 0; ch < s->nb_display_channels; ch++)
1824  memset(s->magnitudes[ch], 0, h * sizeof(float));
1825  }
1826  }
1827 
1828  av_frame_free(&fin);
1829  s->outpicref->pts = 0;
1830 
1831  if (s->legend)
1832  draw_legend(ctx, s->samples);
1833 
1834  ret = ff_filter_frame(outlink, s->outpicref);
1835  s->outpicref = NULL;
1836  }
1837 
1838  return ret;
1839 }
1840 
1841 static int showspectrumpic_filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1842 {
1843  AVFilterContext *ctx = inlink->dst;
1844  ShowSpectrumContext *s = ctx->priv;
1845  void *ptr;
1846 
1847  if (s->nb_frames + 1ULL > s->frames_size / sizeof(*(s->frames))) {
1848  ptr = av_fast_realloc(s->frames, &s->frames_size, s->frames_size * 2);
1849  if (!ptr)
1850  return AVERROR(ENOMEM);
1851  s->frames = ptr;
1852  }
1853 
1854  s->frames[s->nb_frames] = insamples;
1855  s->samples += insamples->nb_samples;
1856  s->nb_frames++;
1857 
1858  return 0;
1859 }
1860 
1861 static const AVFilterPad showspectrumpic_inputs[] = {
1862  {
1863  .name = "default",
1864  .type = AVMEDIA_TYPE_AUDIO,
1865  .filter_frame = showspectrumpic_filter_frame,
1866  },
1867 };
1868 
1869 static const AVFilterPad showspectrumpic_outputs[] = {
1870  {
1871  .name = "default",
1872  .type = AVMEDIA_TYPE_VIDEO,
1873  .config_props = config_output,
1874  .request_frame = showspectrumpic_request_frame,
1875  },
1876 };
1877 
1879  .name = "showspectrumpic",
1880  .description = NULL_IF_CONFIG_SMALL("Convert input audio to a spectrum video output single picture."),
1881  .uninit = uninit,
1882  .priv_size = sizeof(ShowSpectrumContext),
1883  FILTER_INPUTS(showspectrumpic_inputs),
1884  FILTER_OUTPUTS(showspectrumpic_outputs),
1886  .priv_class = &showspectrumpic_class,
1887  .flags = AVFILTER_FLAG_SLICE_THREADS,
1888 };
1889 
1890 #endif // CONFIG_SHOWSPECTRUMPIC_FILTER
M
#define M(a, b)
Definition: vp3dsp.c:48
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:108
av_samples_copy
int av_samples_copy(uint8_t *const *dst, uint8_t *const *src, int dst_offset, int src_offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Copy samples from src to dst.
Definition: samplefmt.c:222
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:107
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
ShowSpectrumContext::win_size
int win_size
Definition: avf_showspectrum.c:94
AVFilterChannelLayouts
A list of supported channel layouts.
Definition: formats.h:85
AVFrame::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: frame.h:656
plot_channel_lin
static int plot_channel_lin(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:1007
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
SCROLL
@ SCROLL
Definition: avf_showspectrum.c:55
av_clip
#define av_clip
Definition: common.h:96
ShowSpectrumContext::eof
int eof
Definition: avf_showspectrum.c:113
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: avf_showspectrum.c:303
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
ShowSpectrumContext::data
int data
Definition: avf_showspectrum.c:80
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:401
ShowSpectrumContext::frame_rate
AVRational frame_rate
Definition: avf_showspectrum.c:65
out
FILE * out
Definition: movenc.c:54
ff_avf_showspectrum
const AVFilter ff_avf_showspectrum
ShowSpectrumContext::nb_frames
unsigned int nb_frames
Definition: avf_showspectrum.c:118
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:250
ShowSpectrumContext::frames
AVFrame ** frames
Definition: avf_showspectrum.c:117
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:978
log2f
#define log2f(x)
Definition: libm.h:409
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:947
pick_color
static void pick_color(ShowSpectrumContext *s, float yf, float uf, float vf, float a, float *out)
Definition: avf_showspectrum.c:616
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:612
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:326
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
ShowSpectrumContext::xpos
int xpos
x position (current column)
Definition: avf_showspectrum.c:81
ShowSpectrumContext::mode
int mode
channel display mode
Definition: avf_showspectrum.c:73
ShowSpectrumContext::overlap
float overlap
Definition: avf_showspectrum.c:97
AVTXContext
Definition: tx_priv.h:235
ShowSpectrumContext::gain
float gain
Definition: avf_showspectrum.c:98
floorf
static __device__ float floorf(float a)
Definition: cuda_runtime.h:172
draw_legend
static int draw_legend(AVFilterContext *ctx, uint64_t samples)
Definition: avf_showspectrum.c:781
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
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
ShowSpectrumContext::in_pts
int64_t in_pts
Definition: avf_showspectrum.c:104
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
ff_all_channel_counts
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition.
Definition: formats.c:587
SQRT
@ SQRT
Definition: avf_showspectrum.c:53
PHASE
#define PHASE(y, ch)
Definition: avf_showspectrum.c:1318
ShowSpectrumContext::old_len
int old_len
Definition: avf_showspectrum.c:105
ColorTable::y
float y
Definition: avf_showspectrum.c:188
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
ShowSpectrumContext::w
int w
Definition: avf_showspectrum.c:62
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:452
w
uint8_t w
Definition: llviddspenc.c:38
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:673
M_PI_2
#define M_PI_2
Definition: mathematics.h:73
calc_channel_magnitudes
static int calc_channel_magnitudes(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:1320
AVOption
AVOption.
Definition: opt.h:251
clear_combine_buffer
static void clear_combine_buffer(ShowSpectrumContext *s, int size)
Definition: avf_showspectrum.c:1415
b
#define b
Definition: input.c:41
GREEN
@ GREEN
Definition: avf_showspectrum.c:54
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:169
config_output
static int config_output(AVFilterLink *outlink)
Definition: avf_showspectrum.c:1061
data
const char data[16]
Definition: mxf.c:148
expf
#define expf(x)
Definition: libm.h:283
ff_request_frame
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:431
D_UPHASE
@ D_UPHASE
Definition: avf_showspectrum.c:51
calc_channel_uphases
static int calc_channel_uphases(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:1370
ShowSpectrumContext::ifft
AVTXContext ** ifft
Inverse Fast Fourier Transform context.
Definition: avf_showspectrum.c:83
ShowSpectrumContext::hop_size
int hop_size
Definition: avf_showspectrum.c:99
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
float.h
AVComplexFloat
Definition: tx.h:27
WIN_FUNC_OPTION
#define WIN_FUNC_OPTION(win_func_opt_name, win_func_offset, flag, default_window_func)
Definition: window_func.h:37
ShowSpectrumContext::saturation
float saturation
color saturation multiplier
Definition: avf_showspectrum.c:77
max
#define max(a, b)
Definition: cuda_runtime.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
COOL
@ COOL
Definition: avf_showspectrum.c:54
ShowSpectrumContext::channel_width
int channel_width
Definition: avf_showspectrum.c:70
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:317
OFFSET
#define OFFSET(x)
Definition: avf_showspectrum.c:122
video.h
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
acalc_magnitudes
static void acalc_magnitudes(ShowSpectrumContext *s)
Definition: avf_showspectrum.c:1389
ceilf
static __device__ float ceilf(float a)
Definition: cuda_runtime.h:175
FIFTHRT
@ FIFTHRT
Definition: avf_showspectrum.c:53
scale_magnitudes
static void scale_magnitudes(ShowSpectrumContext *s, float scale)
Definition: avf_showspectrum.c:1403
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:901
get_value
static float get_value(AVFilterContext *ctx, int ch, int y)
Definition: avf_showspectrum.c:983
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
ShowSpectrumContext::magnitudes
float ** magnitudes
Definition: avf_showspectrum.c:91
MORELAND
@ MORELAND
Definition: avf_showspectrum.c:54
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
formats.h
S
#define S(s, c, i)
Definition: flacdsp_template.c:46
ShowSpectrumContext::win_func
int win_func
Definition: avf_showspectrum.c:93
ShowSpectrumContext::outpicref
AVFrame * outpicref
Definition: avf_showspectrum.c:66
ShowSpectrumContext::rotation
float rotation
color rotation
Definition: avf_showspectrum.c:78
ShowSpectrumContext::fft_scratch
AVComplexFloat ** fft_scratch
scratch buffers
Definition: avf_showspectrum.c:89
calc_channel_phases
static int calc_channel_phases(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:1335
ShowSpectrumContext::fft_in
AVComplexFloat ** fft_in
input FFT coeffs
Definition: avf_showspectrum.c:87
ColorMode
ColorMode
Definition: avf_showspectrum.c:54
cosf
#define cosf(x)
Definition: libm.h:78
ShowSpectrumContext::color_mode
int color_mode
display color scheme
Definition: avf_showspectrum.c:74
log10f
#define log10f(x)
Definition: libm.h:414
ShowSpectrumContext::color_buffer
float ** color_buffer
color buffer (4 * h * ch items)
Definition: avf_showspectrum.c:101
ShowSpectrumContext::window_func_lut
float * window_func_lut
Window function LUT.
Definition: avf_showspectrum.c:90
FULLFRAME
@ FULLFRAME
Definition: avf_showspectrum.c:55
unwrap
static void unwrap(float *x, int N, float tol, float *mi, float *ma)
Definition: avf_showspectrum.c:1349
AVFrame::ch_layout
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition: frame.h:802
NB_FSCALES
@ NB_FSCALES
Definition: avf_showspectrum.c:52
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
pts
static int64_t pts
Definition: transcode_aac.c:643
RAINBOW
@ RAINBOW
Definition: avf_showspectrum.c:54
ShowSpectrumContext::buf_size
int buf_size
Definition: avf_showspectrum.c:95
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:47
a1
#define a1
Definition: regdef.h:47
D_PHASE
@ D_PHASE
Definition: avf_showspectrum.c:51
FIERY
@ FIERY
Definition: avf_showspectrum.c:54
INTENSITY
@ INTENSITY
Definition: avf_showspectrum.c:54
avassert.h
ceil
static __device__ float ceil(float a)
Definition: cuda_runtime.h:176
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
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:151
mask
static const uint16_t mask[17]
Definition: lzw.c:38
av_channel_layout_describe
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
Definition: channel_layout.c:786
float
float
Definition: af_crystalizer.c:121
ff_outlink_set_status
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
NB_DMODES
@ NB_DMODES
Definition: avf_showspectrum.c:51
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:495
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1506
s
#define s(width, name)
Definition: cbs_vp9.c:198
get_scale
static float get_scale(AVFilterContext *ctx, int scale, float a)
Definition: avf_showspectrum.c:712
Orientation
Orientation
Definition: avf_showspectrum.c:56
FRUIT
@ FRUIT
Definition: avf_showspectrum.c:54
mi
#define mi
Definition: vf_colormatrix.c:106
CHANNEL
@ CHANNEL
Definition: avf_showspectrum.c:54
g
const char * g
Definition: vf_curves.c:127
VIRIDIS
@ VIRIDIS
Definition: avf_showspectrum.c:54
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:617
fminf
float fminf(float, float)
ShowSpectrumContext::h
int h
Definition: avf_showspectrum.c:62
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
filters.h
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:304
plot_channel_log
static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:1030
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition: tx.h:47
ShowSpectrumContext::fft
AVTXContext ** fft
Fast Fourier Transform context.
Definition: avf_showspectrum.c:82
ctx
AVFormatContext * ctx
Definition: movenc.c:48
exp2f
#define exp2f(x)
Definition: libm.h:293
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:609
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
inv_log_scale
static float inv_log_scale(float bin, float bmin, float bmax, float min, float max)
Definition: avf_showspectrum.c:700
color_range
color_range
Definition: vf_selectivecolor.c:43
VERTICAL
@ VERTICAL
Definition: avf_showspectrum.c:56
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:192
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
TERRAIN
@ TERRAIN
Definition: avf_showspectrum.c:54
ff_inlink_make_frame_writable
int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
Make sure a frame is writable.
Definition: avfilter.c:1427
arg
const char * arg
Definition: jacosubdec.c:67
COMBINED
@ COMBINED
Definition: avf_showspectrum.c:50
if
if(ret)
Definition: filter_design.txt:179
av_realloc_f
#define av_realloc_f(p, o, n)
Definition: tableprint_vlc.h:32
ShowSpectrumContext::win_scale
double win_scale
Definition: avf_showspectrum.c:96
ShowSpectrumContext::combine_buffer
float * combine_buffer
color combining buffer (4 * h items)
Definition: avf_showspectrum.c:100
ShowSpectrumContext::in_frame
AVFrame * in_frame
Definition: avf_showspectrum.c:67
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ShowSpectrumContext::dmax
float dmax
Definition: avf_showspectrum.c:110
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:1402
NULL
#define NULL
Definition: coverity.c:32
NB_SLIDES
@ NB_SLIDES
Definition: avf_showspectrum.c:55
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ShowSpectrumContext::fft_data
AVComplexFloat ** fft_data
bins holder for each (displayed) channels
Definition: avf_showspectrum.c:88
activate
filter_frame For filters that do not use the activate() callback
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:235
CIVIDIS
@ CIVIDIS
Definition: avf_showspectrum.c:54
parseutils.h
ShowSpectrumContext::start
int start
Definition: avf_showspectrum.c:79
get_time
static char * get_time(AVFilterContext *ctx, float seconds, int x)
Definition: avf_showspectrum.c:664
MAGNITUDE
#define MAGNITUDE(y, ch)
Definition: avf_showspectrum.c:1317
ff_audio_default_filterpad
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition: audio.c:32
sqrtf
static __device__ float sqrtf(float a)
Definition: cuda_runtime.h:184
av_cpu_max_align
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
Definition: cpu.c:268
generate_window_func
static void generate_window_func(float *lut, int N, int win_func, float *overlap)
Definition: window_func.h:63
SEPARATE
@ SEPARATE
Definition: avf_showspectrum.c:50
WFUNC_HANNING
@ WFUNC_HANNING
Definition: window_func.h:29
sinf
#define sinf(x)
Definition: libm.h:419
av_clipf
av_clipf
Definition: af_crystalizer.c:121
log_scale
static float log_scale(const float bin, const float bmin, const float bmax, const float min, const float max)
Definition: avf_showspectrum.c:679
ShowSpectrumContext::limit
float limit
Definition: avf_showspectrum.c:109
ff_inlink_acknowledge_status
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:1337
get_iscale
static float get_iscale(AVFilterContext *ctx, int scale, float a)
Definition: avf_showspectrum.c:747
ShowSpectrumContext::samples
uint64_t samples
Definition: avf_showspectrum.c:111
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ShowSpectrumContext::auto_frame_rate
AVRational auto_frame_rate
Definition: avf_showspectrum.c:64
ShowSpectrumContext::pts
int64_t pts
Definition: avf_showspectrum.c:102
ShowSpectrumContext::dmin
float dmin
Definition: avf_showspectrum.c:110
ShowSpectrumContext::single_pic
int single_pic
Definition: avf_showspectrum.c:106
f
f
Definition: af_crystalizer.c:121
DataMode
DataMode
Definition: avf_showfreqs.c:39
DEFAULT_LENGTH
#define DEFAULT_LENGTH
Definition: avf_showspectrum.c:58
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:106
powf
#define powf(x, y)
Definition: libm.h:50
RSCROLL
@ RSCROLL
Definition: avf_showspectrum.c:55
D_MAGNITUDE
@ D_MAGNITUDE
Definition: avf_showspectrum.c:51
cpu.h
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
fmaxf
float fmaxf(float, float)
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
size
int size
Definition: twinvq_data.h:10344
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
PLASMA
@ PLASMA
Definition: avf_showspectrum.c:54
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2646
LREPLACE
@ LREPLACE
Definition: avf_showspectrum.c:55
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
FrequencyScale
FrequencyScale
Definition: avf_showcwt.c:39
ColorTable::a
float a
Definition: avf_showspectrum.c:188
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:167
xga_font_data.h
N
#define N
Definition: af_mcompand.c:53
a0
#define a0
Definition: regdef.h:46
M_PI
#define M_PI
Definition: mathematics.h:67
ShowSpectrumContext::nb_display_channels
int nb_display_channels
Definition: avf_showspectrum.c:68
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:294
ff_avf_showspectrumpic
const AVFilter ff_avf_showspectrumpic
internal.h
ShowSpectrumContext::scale
int scale
Definition: avf_showspectrum.c:75
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
plot_spectrum_column
static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
Definition: avf_showspectrum.c:1427
ShowSpectrumContext::rate_str
char * rate_str
Definition: avf_showspectrum.c:63
av_parse_video_rate
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:181
ShowSpectrumContext::old_pts
int64_t old_pts
Definition: avf_showspectrum.c:103
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:420
ShowSpectrumContext::phases
float ** phases
Definition: avf_showspectrum.c:92
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
FLAGS
#define FLAGS
Definition: avf_showspectrum.c:123
ShowSpectrumContext::channel_height
int channel_height
Definition: avf_showspectrum.c:71
ShowSpectrumContext
Definition: avf_showspectrum.c:60
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:401
bin_pos
static float bin_pos(const int bin, const int num_bins, const float min, const float max)
Definition: avf_showspectrum.c:707
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
delta
float delta
Definition: vorbis_enc_data.h:430
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
cbrtf
static av_always_inline float cbrtf(float x)
Definition: libm.h:61
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
NB_CLMODES
@ NB_CLMODES
Definition: avf_showspectrum.c:54
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:53
ff_inlink_queued_samples
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1362
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
limit
static double limit(double x)
Definition: vf_pseudocolor.c:142
HORIZONTAL
@ HORIZONTAL
Definition: avf_showspectrum.c:56
F_LINEAR
@ F_LINEAR
Definition: avf_showspectrum.c:52
AVFilter
Filter definition.
Definition: avfilter.h:166
ret
ret
Definition: filter_design.txt:187
NB_ORIENTATIONS
@ NB_ORIENTATIONS
Definition: avf_showspectrum.c:56
color_range
static void color_range(ShowSpectrumContext *s, int ch, float *yf, float *uf, float *vf)
Definition: avf_showspectrum.c:554
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(showspectrum)
pos
unsigned int pos
Definition: spdifenc.c:413
AVFrame::sample_aspect_ratio
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition: frame.h:447
ShowSpectrumContext::legend
int legend
Definition: avf_showspectrum.c:107
run_channel_fft
static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:392
ShowSpectrumContext::fscale
int fscale
Definition: avf_showspectrum.c:76
window_func.h
NEBULAE
@ NEBULAE
Definition: avf_showspectrum.c:54
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: avf_showspectrum.c:361
ShowSpectrumContext::start_x
int start_x
Definition: avf_showspectrum.c:108
ShowSpectrumContext::stop
int stop
zoom mode
Definition: avf_showspectrum.c:79
ff_all_samplerates
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:572
status
ov_status_e status
Definition: dnn_backend_openvino.c:119
ShowSpectrumContext::orientation
int orientation
Definition: avf_showspectrum.c:69
channel_layout.h
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
LOG
@ LOG
Definition: avf_showspectrum.c:53
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
ShowSpectrumContext::fft_size
int fft_size
number of coeffs (FFT window size)
Definition: avf_showspectrum.c:86
avfilter.h
FOURTHRT
@ FOURTHRT
Definition: avf_showspectrum.c:53
NB_MODES
@ NB_MODES
Definition: avf_showspectrum.c:50
cm
#define cm
Definition: dvbsubdec.c:39
F_LOG
@ F_LOG
Definition: avf_showspectrum.c:52
L
#define L(x)
Definition: vpx_arith.h:36
samples
Filter the word “frame” indicates either a video frame or a group of audio samples
Definition: filter_design.txt:8
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
ShowSpectrumContext::opacity_factor
float opacity_factor
Definition: avf_showspectrum.c:115
av_clip_uint8
#define av_clip_uint8
Definition: common.h:102
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:397
DisplayMode
DisplayMode
Definition: avf_ahistogram.c:34
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
ColorTable::v
float v
Definition: avf_showspectrum.c:188
LINEAR
@ LINEAR
Definition: avf_showspectrum.c:53
audio.h
ShowSpectrumContext::start_y
int start_y
Definition: avf_showspectrum.c:108
M_LN10
#define M_LN10
Definition: mathematics.h:49
AVFilterFormatsConfig::formats
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:505
DisplayScale
DisplayScale
Definition: avf_ahistogram.c:31
ShowSpectrumContext::itx_fn
av_tx_fn itx_fn
Definition: avf_showspectrum.c:85
ShowSpectrumContext::tx_fn
av_tx_fn tx_fn
Definition: avf_showspectrum.c:84
avpriv_cga_font
const uint8_t avpriv_cga_font[2048]
Definition: xga_font_data.c:29
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
NB_SCALES
@ NB_SCALES
Definition: avf_showspectrum.c:53
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:193
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
ShowSpectrumContext::sliding
int sliding
1 if sliding mode, 0 otherwise
Definition: avf_showspectrum.c:72
d
d
Definition: ffmpeg_filter.c:368
ColorTable::u
float u
Definition: avf_showspectrum.c:188
ShowSpectrumContext::drange
float drange
Definition: avf_showspectrum.c:109
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:385
CBRT
@ CBRT
Definition: avf_showspectrum.c:53
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ma
#define ma
Definition: vf_colormatrix.c:98
h
h
Definition: vp9dsp_template.c:2038
MAGMA
@ MAGMA
Definition: avf_showspectrum.c:54
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
color_table
static const struct ColorTable color_table[][8]
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
showspectrum_options
static const AVOption showspectrum_options[]
Definition: avf_showspectrum.c:125
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:144
ColorTable
Definition: avf_showspectrum.c:187
get_hz
static float get_hz(const float bin, const float bmax, const float min, const float max, int fscale)
Definition: avf_showspectrum.c:686
int
int
Definition: ffmpeg_filter.c:368
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
REPLACE
@ REPLACE
Definition: avf_showspectrum.c:55
FIRE
@ FIRE
Definition: avf_showspectrum.c:54
drawtext
static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
Definition: avf_showspectrum.c:499
channel
channel
Definition: ebur128.h:39
ShowSpectrumContext::frames_size
unsigned int frames_size
Definition: avf_showspectrum.c:119
SlideMode
SlideMode
Definition: avf_ahistogram.c:33
ff_filter_set_ready
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Definition: avfilter.c:216
tx.h
min
float min
Definition: vorbis_enc_data.h:429
ShowSpectrumContext::plot_channel
int(* plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:112