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