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