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 "internal.h"
49 #include "window_func.h"
50 
58 
59 #define DEFAULT_LENGTH 300
60 
61 typedef struct ShowSpectrumContext {
62  const AVClass *class;
63  int w, h;
64  char *rate_str;
73  int sliding; ///< 1 if sliding mode, 0 otherwise
74  int mode; ///< channel display mode
75  int color_mode; ///< display color scheme
76  int scale;
77  int fscale;
78  float saturation; ///< color saturation multiplier
79  float rotation; ///< color rotation
80  int start, stop; ///< zoom mode
81  int data;
82  int xpos; ///< x position (current column)
83  AVTXContext **fft; ///< Fast Fourier Transform context
84  AVTXContext **ifft; ///< Inverse Fast Fourier Transform context
87  int fft_size; ///< number of coeffs (FFT window size)
88  AVComplexFloat **fft_in; ///< input FFT coeffs
89  AVComplexFloat **fft_data; ///< bins holder for each (displayed) channels
90  AVComplexFloat **fft_scratch;///< scratch buffers
91  float *window_func_lut; ///< Window function LUT
92  float **magnitudes;
93  float **phases;
94  int win_func;
95  int win_size;
96  int buf_size;
97  double win_scale;
98  float overlap;
99  float gain;
100  int hop_size;
101  float *combine_buffer; ///< color combining buffer (4 * h items)
102  float **color_buffer; ///< color buffer (4 * h * ch items)
103  int64_t pts;
104  int64_t old_pts;
105  int64_t in_pts;
106  int old_len;
108  int legend;
110  float drange, limit;
111  float dmin, dmax;
112  uint64_t samples;
113  int (*plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
114  int eof;
115 
117 
119  unsigned int nb_frames;
120  unsigned int frames_size;
122 
123 #define OFFSET(x) offsetof(ShowSpectrumContext, x)
124 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
125 
126 static const AVOption showspectrum_options[] = {
127  { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x512"}, 0, 0, FLAGS },
128  { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x512"}, 0, 0, FLAGS },
129  { "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_SLIDES-1, FLAGS, .unit = "slide" },
130  { "replace", "replace old columns with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, .unit = "slide" },
131  { "scroll", "scroll from right to left", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, .unit = "slide" },
132  { "fullframe", "return full frames", 0, AV_OPT_TYPE_CONST, {.i64=FULLFRAME}, 0, 0, FLAGS, .unit = "slide" },
133  { "rscroll", "scroll from left to right", 0, AV_OPT_TYPE_CONST, {.i64=RSCROLL}, 0, 0, FLAGS, .unit = "slide" },
134  { "lreplace", "replace from right to left", 0, AV_OPT_TYPE_CONST, {.i64=LREPLACE}, 0, 0, FLAGS, .unit = "slide" },
135  { "mode", "set channel display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=COMBINED}, COMBINED, NB_MODES-1, FLAGS, .unit = "mode" },
136  { "combined", "combined mode", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, .unit = "mode" },
137  { "separate", "separate mode", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, .unit = "mode" },
138  { "color", "set channel coloring", OFFSET(color_mode), AV_OPT_TYPE_INT, {.i64=CHANNEL}, CHANNEL, NB_CLMODES-1, FLAGS, .unit = "color" },
139  { "channel", "separate color for each channel", 0, AV_OPT_TYPE_CONST, {.i64=CHANNEL}, 0, 0, FLAGS, .unit = "color" },
140  { "intensity", "intensity based coloring", 0, AV_OPT_TYPE_CONST, {.i64=INTENSITY}, 0, 0, FLAGS, .unit = "color" },
141  { "rainbow", "rainbow based coloring", 0, AV_OPT_TYPE_CONST, {.i64=RAINBOW}, 0, 0, FLAGS, .unit = "color" },
142  { "moreland", "moreland based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MORELAND}, 0, 0, FLAGS, .unit = "color" },
143  { "nebulae", "nebulae based coloring", 0, AV_OPT_TYPE_CONST, {.i64=NEBULAE}, 0, 0, FLAGS, .unit = "color" },
144  { "fire", "fire based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIRE}, 0, 0, FLAGS, .unit = "color" },
145  { "fiery", "fiery based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FIERY}, 0, 0, FLAGS, .unit = "color" },
146  { "fruit", "fruit based coloring", 0, AV_OPT_TYPE_CONST, {.i64=FRUIT}, 0, 0, FLAGS, .unit = "color" },
147  { "cool", "cool based coloring", 0, AV_OPT_TYPE_CONST, {.i64=COOL}, 0, 0, FLAGS, .unit = "color" },
148  { "magma", "magma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=MAGMA}, 0, 0, FLAGS, .unit = "color" },
149  { "green", "green based coloring", 0, AV_OPT_TYPE_CONST, {.i64=GREEN}, 0, 0, FLAGS, .unit = "color" },
150  { "viridis", "viridis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=VIRIDIS}, 0, 0, FLAGS, .unit = "color" },
151  { "plasma", "plasma based coloring", 0, AV_OPT_TYPE_CONST, {.i64=PLASMA}, 0, 0, FLAGS, .unit = "color" },
152  { "cividis", "cividis based coloring", 0, AV_OPT_TYPE_CONST, {.i64=CIVIDIS}, 0, 0, FLAGS, .unit = "color" },
153  { "terrain", "terrain based coloring", 0, AV_OPT_TYPE_CONST, {.i64=TERRAIN}, 0, 0, FLAGS, .unit = "color" },
154  { "scale", "set display scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=SQRT}, LINEAR, NB_SCALES-1, FLAGS, .unit = "scale" },
155  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, FLAGS, .unit = "scale" },
156  { "sqrt", "square root", 0, AV_OPT_TYPE_CONST, {.i64=SQRT}, 0, 0, FLAGS, .unit = "scale" },
157  { "cbrt", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64=CBRT}, 0, 0, FLAGS, .unit = "scale" },
158  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, FLAGS, .unit = "scale" },
159  { "4thrt","4th root", 0, AV_OPT_TYPE_CONST, {.i64=FOURTHRT}, 0, 0, FLAGS, .unit = "scale" },
160  { "5thrt","5th root", 0, AV_OPT_TYPE_CONST, {.i64=FIFTHRT}, 0, 0, FLAGS, .unit = "scale" },
161  { "fscale", "set frequency scale", OFFSET(fscale), AV_OPT_TYPE_INT, {.i64=F_LINEAR}, 0, NB_FSCALES-1, FLAGS, .unit = "fscale" },
162  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=F_LINEAR}, 0, 0, FLAGS, .unit = "fscale" },
163  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=F_LOG}, 0, 0, FLAGS, .unit = "fscale" },
164  { "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS },
165  WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_HANNING),
166  { "orientation", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=VERTICAL}, 0, NB_ORIENTATIONS-1, FLAGS, .unit = "orientation" },
167  { "vertical", NULL, 0, AV_OPT_TYPE_CONST, {.i64=VERTICAL}, 0, 0, FLAGS, .unit = "orientation" },
168  { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=HORIZONTAL}, 0, 0, FLAGS, .unit = "orientation" },
169  { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, 1, FLAGS },
170  { "gain", "set scale gain", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 128, FLAGS },
171  { "data", "set data mode", OFFSET(data), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_DMODES-1, FLAGS, .unit = "data" },
172  { "magnitude", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_MAGNITUDE}, 0, 0, FLAGS, .unit = "data" },
173  { "phase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_PHASE}, 0, 0, FLAGS, .unit = "data" },
174  { "uphase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_UPHASE}, 0, 0, FLAGS, .unit = "data" },
175  { "rotation", "color rotation", OFFSET(rotation), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -1, 1, FLAGS },
176  { "start", "start frequency", OFFSET(start), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
177  { "stop", "stop frequency", OFFSET(stop), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS },
178  { "fps", "set video rate", OFFSET(rate_str), AV_OPT_TYPE_STRING, {.str = "auto"}, 0, 0, FLAGS },
179  { "legend", "draw legend", OFFSET(legend), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
180  { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS },
181  { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS },
182  { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS },
183  { NULL }
184 };
185 
186 AVFILTER_DEFINE_CLASS(showspectrum);
187 
188 static const struct ColorTable {
189  float a, y, u, v;
190 } color_table[][8] = {
191  [INTENSITY] = {
192  { 0, 0, 0, 0 },
193  { 0.13, .03587126228984074, .1573300977624594, -.02548747583751842 },
194  { 0.30, .18572281794568020, .1772436246393981, .17475554840414750 },
195  { 0.60, .28184980583656130, -.1593064119945782, .47132074554608920 },
196  { 0.73, .65830621175547810, -.3716070802232764, .24352759331252930 },
197  { 0.78, .76318535758242900, -.4307467689263783, .16866496622310430 },
198  { 0.91, .95336363636363640, -.2045454545454546, .03313636363636363 },
199  { 1, 1, 0, 0 }},
200  [RAINBOW] = {
201  { 0, 0, 0, 0 },
202  { 0.13, 44/256., (189-128)/256., (138-128)/256. },
203  { 0.25, 29/256., (186-128)/256., (119-128)/256. },
204  { 0.38, 119/256., (194-128)/256., (53-128)/256. },
205  { 0.60, 111/256., (73-128)/256., (59-128)/256. },
206  { 0.73, 205/256., (19-128)/256., (149-128)/256. },
207  { 0.86, 135/256., (83-128)/256., (200-128)/256. },
208  { 1, 73/256., (95-128)/256., (225-128)/256. }},
209  [MORELAND] = {
210  { 0, 44/256., (181-128)/256., (112-128)/256. },
211  { 0.13, 126/256., (177-128)/256., (106-128)/256. },
212  { 0.25, 164/256., (163-128)/256., (109-128)/256. },
213  { 0.38, 200/256., (140-128)/256., (120-128)/256. },
214  { 0.60, 201/256., (117-128)/256., (141-128)/256. },
215  { 0.73, 177/256., (103-128)/256., (165-128)/256. },
216  { 0.86, 136/256., (100-128)/256., (183-128)/256. },
217  { 1, 68/256., (117-128)/256., (203-128)/256. }},
218  [NEBULAE] = {
219  { 0, 10/256., (134-128)/256., (132-128)/256. },
220  { 0.23, 21/256., (137-128)/256., (130-128)/256. },
221  { 0.45, 35/256., (134-128)/256., (134-128)/256. },
222  { 0.57, 51/256., (130-128)/256., (139-128)/256. },
223  { 0.67, 104/256., (116-128)/256., (162-128)/256. },
224  { 0.77, 120/256., (105-128)/256., (188-128)/256. },
225  { 0.87, 140/256., (105-128)/256., (188-128)/256. },
226  { 1, 1, 0, 0 }},
227  [FIRE] = {
228  { 0, 0, 0, 0 },
229  { 0.23, 44/256., (132-128)/256., (127-128)/256. },
230  { 0.45, 62/256., (116-128)/256., (140-128)/256. },
231  { 0.57, 75/256., (105-128)/256., (152-128)/256. },
232  { 0.67, 95/256., (91-128)/256., (166-128)/256. },
233  { 0.77, 126/256., (74-128)/256., (172-128)/256. },
234  { 0.87, 164/256., (73-128)/256., (162-128)/256. },
235  { 1, 1, 0, 0 }},
236  [FIERY] = {
237  { 0, 0, 0, 0 },
238  { 0.23, 36/256., (116-128)/256., (163-128)/256. },
239  { 0.45, 52/256., (102-128)/256., (200-128)/256. },
240  { 0.57, 116/256., (84-128)/256., (196-128)/256. },
241  { 0.67, 157/256., (67-128)/256., (181-128)/256. },
242  { 0.77, 193/256., (40-128)/256., (155-128)/256. },
243  { 0.87, 221/256., (101-128)/256., (134-128)/256. },
244  { 1, 1, 0, 0 }},
245  [FRUIT] = {
246  { 0, 0, 0, 0 },
247  { 0.20, 29/256., (136-128)/256., (119-128)/256. },
248  { 0.30, 60/256., (119-128)/256., (90-128)/256. },
249  { 0.40, 85/256., (91-128)/256., (85-128)/256. },
250  { 0.50, 116/256., (70-128)/256., (105-128)/256. },
251  { 0.60, 151/256., (50-128)/256., (146-128)/256. },
252  { 0.70, 191/256., (63-128)/256., (178-128)/256. },
253  { 1, 98/256., (80-128)/256., (221-128)/256. }},
254  [COOL] = {
255  { 0, 0, 0, 0 },
256  { .15, 0, .5, -.5 },
257  { 1, 1, -.5, .5 }},
258  [MAGMA] = {
259  { 0, 0, 0, 0 },
260  { 0.10, 23/256., (175-128)/256., (120-128)/256. },
261  { 0.23, 43/256., (158-128)/256., (144-128)/256. },
262  { 0.35, 85/256., (138-128)/256., (179-128)/256. },
263  { 0.48, 96/256., (128-128)/256., (189-128)/256. },
264  { 0.64, 128/256., (103-128)/256., (214-128)/256. },
265  { 0.92, 205/256., (80-128)/256., (152-128)/256. },
266  { 1, 1, 0, 0 }},
267  [GREEN] = {
268  { 0, 0, 0, 0 },
269  { .75, .5, 0, -.5 },
270  { 1, 1, 0, 0 }},
271  [VIRIDIS] = {
272  { 0, 0, 0, 0 },
273  { 0.10, 0x39/255., (0x9D -128)/255., (0x8F -128)/255. },
274  { 0.23, 0x5C/255., (0x9A -128)/255., (0x68 -128)/255. },
275  { 0.35, 0x69/255., (0x93 -128)/255., (0x57 -128)/255. },
276  { 0.48, 0x76/255., (0x88 -128)/255., (0x4B -128)/255. },
277  { 0.64, 0x8A/255., (0x72 -128)/255., (0x4F -128)/255. },
278  { 0.80, 0xA3/255., (0x50 -128)/255., (0x66 -128)/255. },
279  { 1, 0xCC/255., (0x2F -128)/255., (0x87 -128)/255. }},
280  [PLASMA] = {
281  { 0, 0, 0, 0 },
282  { 0.10, 0x27/255., (0xC2 -128)/255., (0x82 -128)/255. },
283  { 0.58, 0x5B/255., (0x9A -128)/255., (0xAE -128)/255. },
284  { 0.70, 0x89/255., (0x44 -128)/255., (0xAB -128)/255. },
285  { 0.80, 0xB4/255., (0x2B -128)/255., (0x9E -128)/255. },
286  { 0.91, 0xD2/255., (0x38 -128)/255., (0x92 -128)/255. },
287  { 1, 1, 0, 0. }},
288  [CIVIDIS] = {
289  { 0, 0, 0, 0 },
290  { 0.20, 0x28/255., (0x98 -128)/255., (0x6F -128)/255. },
291  { 0.50, 0x48/255., (0x95 -128)/255., (0x74 -128)/255. },
292  { 0.63, 0x69/255., (0x84 -128)/255., (0x7F -128)/255. },
293  { 0.76, 0x89/255., (0x75 -128)/255., (0x84 -128)/255. },
294  { 0.90, 0xCE/255., (0x35 -128)/255., (0x95 -128)/255. },
295  { 1, 1, 0, 0. }},
296  [TERRAIN] = {
297  { 0, 0, 0, 0 },
298  { 0.15, 0, .5, 0 },
299  { 0.60, 1, -.5, -.5 },
300  { 0.85, 1, -.5, .5 },
301  { 1, 1, 0, 0 }},
302 };
303 
305 {
306  ShowSpectrumContext *s = ctx->priv;
307  int i;
308 
309  av_freep(&s->combine_buffer);
310  if (s->fft) {
311  for (i = 0; i < s->nb_display_channels; i++)
312  av_tx_uninit(&s->fft[i]);
313  }
314  av_freep(&s->fft);
315  if (s->ifft) {
316  for (i = 0; i < s->nb_display_channels; i++)
317  av_tx_uninit(&s->ifft[i]);
318  }
319  av_freep(&s->ifft);
320  if (s->fft_data) {
321  for (i = 0; i < s->nb_display_channels; i++)
322  av_freep(&s->fft_data[i]);
323  }
324  av_freep(&s->fft_data);
325  if (s->fft_in) {
326  for (i = 0; i < s->nb_display_channels; i++)
327  av_freep(&s->fft_in[i]);
328  }
329  av_freep(&s->fft_in);
330  if (s->fft_scratch) {
331  for (i = 0; i < s->nb_display_channels; i++)
332  av_freep(&s->fft_scratch[i]);
333  }
334  av_freep(&s->fft_scratch);
335  if (s->color_buffer) {
336  for (i = 0; i < s->nb_display_channels; i++)
337  av_freep(&s->color_buffer[i]);
338  }
339  av_freep(&s->color_buffer);
340  av_freep(&s->window_func_lut);
341  if (s->magnitudes) {
342  for (i = 0; i < s->nb_display_channels; i++)
343  av_freep(&s->magnitudes[i]);
344  }
345  av_freep(&s->magnitudes);
346  av_frame_free(&s->outpicref);
347  av_frame_free(&s->in_frame);
348  if (s->phases) {
349  for (i = 0; i < s->nb_display_channels; i++)
350  av_freep(&s->phases[i]);
351  }
352  av_freep(&s->phases);
353 
354  while (s->nb_frames > 0) {
355  av_frame_free(&s->frames[s->nb_frames - 1]);
356  s->nb_frames--;
357  }
358 
359  av_freep(&s->frames);
360 }
361 
363 {
366  AVFilterLink *inlink = ctx->inputs[0];
367  AVFilterLink *outlink = ctx->outputs[0];
370  int ret;
371 
372  /* set input audio formats */
374  if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0)
375  return ret;
376 
378  if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0)
379  return ret;
380 
382  if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0)
383  return ret;
384 
385  /* set output video format */
387  if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0)
388  return ret;
389 
390  return 0;
391 }
392 
393 static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
394 {
395  ShowSpectrumContext *s = ctx->priv;
396  AVFilterLink *inlink = ctx->inputs[0];
397  const float *window_func_lut = s->window_func_lut;
398  AVFrame *fin = arg;
399  const int ch = jobnr;
400  int n;
401 
402  /* fill FFT input with the number of samples available */
403  const float *p = (float *)fin->extended_data[ch];
404  float *in_frame = (float *)s->in_frame->extended_data[ch];
405 
406  memmove(in_frame, in_frame + s->hop_size, (s->fft_size - s->hop_size) * sizeof(float));
407  memcpy(in_frame + s->fft_size - s->hop_size, p, fin->nb_samples * sizeof(float));
408 
409  for (int i = fin->nb_samples; i < s->hop_size; i++)
410  in_frame[i + s->fft_size - s->hop_size] = 0.f;
411 
412  if (s->stop) {
413  float theta, phi, psi, a, b, S, c;
414  AVComplexFloat *f = s->fft_in[ch];
415  AVComplexFloat *g = s->fft_data[ch];
416  AVComplexFloat *h = s->fft_scratch[ch];
417  int L = s->buf_size;
418  int N = s->win_size;
419  int M = s->win_size / 2;
420 
421  for (n = 0; n < s->win_size; n++) {
422  s->fft_data[ch][n].re = in_frame[n] * window_func_lut[n];
423  s->fft_data[ch][n].im = 0;
424  }
425 
426  phi = 2.f * M_PI * (s->stop - s->start) / (float)inlink->sample_rate / (M - 1);
427  theta = 2.f * M_PI * s->start / (float)inlink->sample_rate;
428 
429  for (int n = 0; n < M; n++) {
430  h[n].re = cosf(n * n / 2.f * phi);
431  h[n].im = sinf(n * n / 2.f * phi);
432  }
433 
434  for (int n = M; n < L; n++) {
435  h[n].re = 0.f;
436  h[n].im = 0.f;
437  }
438 
439  for (int n = L - N; n < L; n++) {
440  h[n].re = cosf((L - n) * (L - n) / 2.f * phi);
441  h[n].im = sinf((L - n) * (L - n) / 2.f * phi);
442  }
443 
444  for (int n = N; n < L; n++) {
445  g[n].re = 0.f;
446  g[n].im = 0.f;
447  }
448 
449  for (int n = 0; n < N; n++) {
450  psi = n * theta + n * n / 2.f * phi;
451  c = cosf(psi);
452  S = -sinf(psi);
453  a = c * g[n].re - S * g[n].im;
454  b = S * g[n].re + c * g[n].im;
455  g[n].re = a;
456  g[n].im = b;
457  }
458 
459  memcpy(f, h, s->buf_size * sizeof(*f));
460  s->tx_fn(s->fft[ch], h, f, sizeof(AVComplexFloat));
461 
462  memcpy(f, g, s->buf_size * sizeof(*f));
463  s->tx_fn(s->fft[ch], g, f, sizeof(AVComplexFloat));
464 
465  for (int n = 0; n < L; n++) {
466  c = g[n].re;
467  S = g[n].im;
468  a = c * h[n].re - S * h[n].im;
469  b = S * h[n].re + c * h[n].im;
470 
471  g[n].re = a / L;
472  g[n].im = b / L;
473  }
474 
475  memcpy(f, g, s->buf_size * sizeof(*f));
476  s->itx_fn(s->ifft[ch], g, f, sizeof(AVComplexFloat));
477 
478  for (int k = 0; k < M; k++) {
479  psi = k * k / 2.f * phi;
480  c = cosf(psi);
481  S = -sinf(psi);
482  a = c * g[k].re - S * g[k].im;
483  b = S * g[k].re + c * g[k].im;
484  s->fft_data[ch][k].re = a;
485  s->fft_data[ch][k].im = b;
486  }
487  } else {
488  for (n = 0; n < s->win_size; n++) {
489  s->fft_in[ch][n].re = in_frame[n] * window_func_lut[n];
490  s->fft_in[ch][n].im = 0;
491  }
492 
493  /* run FFT on each samples set */
494  s->tx_fn(s->fft[ch], s->fft_data[ch], s->fft_in[ch], sizeof(AVComplexFloat));
495  }
496 
497  return 0;
498 }
499 
500 static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
501 {
502  const uint8_t *font;
503  int font_height;
504 
505  font = avpriv_cga_font, font_height = 8;
506 
507  for (int i = 0; txt[i]; i++) {
508  int char_y, mask;
509 
510  if (o) {
511  for (char_y = font_height - 1; char_y >= 0; char_y--) {
512  uint8_t *p = pic->data[0] + (y + i * 10) * pic->linesize[0] + x;
513  for (mask = 0x80; mask; mask >>= 1) {
514  if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
515  p[char_y] = ~p[char_y];
516  p += pic->linesize[0];
517  }
518  }
519  } else {
520  uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8);
521  for (char_y = 0; char_y < font_height; char_y++) {
522  for (mask = 0x80; mask; mask >>= 1) {
523  if (font[txt[i] * font_height + char_y] & mask)
524  *p = ~(*p);
525  p++;
526  }
527  p += pic->linesize[0] - 8;
528  }
529  }
530  }
531 
532  for (int i = 0; txt[i] && pic->data[3]; i++) {
533  int char_y, mask;
534 
535  if (o) {
536  for (char_y = font_height - 1; char_y >= 0; char_y--) {
537  uint8_t *p = pic->data[3] + (y + i * 10) * pic->linesize[3] + x;
538  for (mask = 0x80; mask; mask >>= 1) {
539  for (int k = 0; k < 8; k++)
540  p[k] = 255;
541  p += pic->linesize[3];
542  }
543  }
544  } else {
545  uint8_t *p = pic->data[3] + y*pic->linesize[3] + (x + i*8);
546  for (char_y = 0; char_y < font_height; char_y++) {
547  for (mask = 0x80; mask; mask >>= 1)
548  *p++ = 255;
549  p += pic->linesize[3] - 8;
550  }
551  }
552  }
553 }
554 
555 static void color_range(ShowSpectrumContext *s, int ch,
556  float *yf, float *uf, float *vf)
557 {
558  switch (s->mode) {
559  case COMBINED:
560  // reduce range by channel count
561  *yf = 256.0f / s->nb_display_channels;
562  switch (s->color_mode) {
563  case RAINBOW:
564  case MORELAND:
565  case NEBULAE:
566  case FIRE:
567  case FIERY:
568  case FRUIT:
569  case COOL:
570  case GREEN:
571  case VIRIDIS:
572  case PLASMA:
573  case CIVIDIS:
574  case TERRAIN:
575  case MAGMA:
576  case INTENSITY:
577  *uf = *yf;
578  *vf = *yf;
579  break;
580  case CHANNEL:
581  /* adjust saturation for mixed UV coloring */
582  /* this factor is correct for infinite channels, an approximation otherwise */
583  *uf = *yf * M_PI;
584  *vf = *yf * M_PI;
585  break;
586  default:
587  av_assert0(0);
588  }
589  break;
590  case SEPARATE:
591  // full range
592  *yf = 256.0f;
593  *uf = 256.0f;
594  *vf = 256.0f;
595  break;
596  default:
597  av_assert0(0);
598  }
599 
600  if (s->color_mode == CHANNEL) {
601  if (s->nb_display_channels > 1) {
602  *uf *= 0.5f * sinf((2 * M_PI * ch) / s->nb_display_channels + M_PI * s->rotation);
603  *vf *= 0.5f * cosf((2 * M_PI * ch) / s->nb_display_channels + M_PI * s->rotation);
604  } else {
605  *uf *= 0.5f * sinf(M_PI * s->rotation);
606  *vf *= 0.5f * cosf(M_PI * s->rotation + M_PI_2);
607  }
608  } else {
609  *uf += *uf * sinf(M_PI * s->rotation);
610  *vf += *vf * cosf(M_PI * s->rotation + M_PI_2);
611  }
612 
613  *uf *= s->saturation;
614  *vf *= s->saturation;
615 }
616 
618  float yf, float uf, float vf,
619  float a, float *out)
620 {
621  const float af = s->opacity_factor * 255.f;
622 
623  if (s->color_mode > CHANNEL) {
624  const int cm = s->color_mode;
625  float y, u, v;
626  int i;
627 
628  for (i = 1; i < FF_ARRAY_ELEMS(color_table[cm]) - 1; i++)
629  if (color_table[cm][i].a >= a)
630  break;
631  // i now is the first item >= the color
632  // now we know to interpolate between item i - 1 and i
633  if (a <= color_table[cm][i - 1].a) {
634  y = color_table[cm][i - 1].y;
635  u = color_table[cm][i - 1].u;
636  v = color_table[cm][i - 1].v;
637  } else if (a >= color_table[cm][i].a) {
638  y = color_table[cm][i].y;
639  u = color_table[cm][i].u;
640  v = color_table[cm][i].v;
641  } else {
642  float start = color_table[cm][i - 1].a;
643  float end = color_table[cm][i].a;
644  float lerpfrac = (a - start) / (end - start);
645  y = color_table[cm][i - 1].y * (1.0f - lerpfrac)
646  + color_table[cm][i].y * lerpfrac;
647  u = color_table[cm][i - 1].u * (1.0f - lerpfrac)
648  + color_table[cm][i].u * lerpfrac;
649  v = color_table[cm][i - 1].v * (1.0f - lerpfrac)
650  + color_table[cm][i].v * lerpfrac;
651  }
652 
653  out[0] = y * yf;
654  out[1] = u * uf;
655  out[2] = v * vf;
656  out[3] = a * af;
657  } else {
658  out[0] = a * yf;
659  out[1] = a * uf;
660  out[2] = a * vf;
661  out[3] = a * af;
662  }
663 }
664 
665 static char *get_time(AVFilterContext *ctx, float seconds, int x)
666 {
667  char *units;
668 
669  if (x == 0)
670  units = av_asprintf("0");
671  else if (log10(seconds) > 6)
672  units = av_asprintf("%.2fh", seconds / (60 * 60));
673  else if (log10(seconds) > 3)
674  units = av_asprintf("%.2fm", seconds / 60);
675  else
676  units = av_asprintf("%.2fs", seconds);
677  return units;
678 }
679 
680 static float log_scale(const float bin,
681  const float bmin, const float bmax,
682  const float min, const float max)
683 {
684  return exp2f(((bin - bmin) / (bmax - bmin)) * (log2f(max) - log2f(min)) + log2f(min));
685 }
686 
687 static float get_hz(const float bin, const float bmax,
688  const float min, const float max,
689  int fscale)
690 {
691  switch (fscale) {
692  case F_LINEAR:
693  return min + (bin / bmax) * (max - min);
694  case F_LOG:
695  return min + log_scale(bin, 0, bmax, 20.f, max - min);
696  default:
697  return 0.f;
698  }
699 }
700 
701 static float inv_log_scale(float bin,
702  float bmin, float bmax,
703  float min, float max)
704 {
705  return (min * exp2f((bin * (log2f(max) - log2f(20.f))) / bmax) + min) * bmax / max;
706 }
707 
708 static float bin_pos(const int bin, const int num_bins, const float min, const float max)
709 {
710  return inv_log_scale(bin, 0.f, num_bins, 20.f, max - min);
711 }
712 
713 static float get_scale(AVFilterContext *ctx, int scale, float a)
714 {
715  ShowSpectrumContext *s = ctx->priv;
716  const float dmin = s->dmin;
717  const float dmax = s->dmax;
718 
719  a = av_clipf(a, dmin, dmax);
720  if (scale != LOG)
721  a = (a - dmin) / (dmax - dmin);
722 
723  switch (scale) {
724  case LINEAR:
725  break;
726  case SQRT:
727  a = sqrtf(a);
728  break;
729  case CBRT:
730  a = cbrtf(a);
731  break;
732  case FOURTHRT:
733  a = sqrtf(sqrtf(a));
734  break;
735  case FIFTHRT:
736  a = powf(a, 0.2f);
737  break;
738  case LOG:
739  a = (s->drange - s->limit + log10f(a) * 20.f) / s->drange;
740  break;
741  default:
742  av_assert0(0);
743  }
744 
745  return a;
746 }
747 
748 static float get_iscale(AVFilterContext *ctx, int scale, float a)
749 {
750  ShowSpectrumContext *s = ctx->priv;
751  const float dmin = s->dmin;
752  const float dmax = s->dmax;
753 
754  switch (scale) {
755  case LINEAR:
756  break;
757  case SQRT:
758  a = a * a;
759  break;
760  case CBRT:
761  a = a * a * a;
762  break;
763  case FOURTHRT:
764  a = a * a * a * a;
765  break;
766  case FIFTHRT:
767  a = a * a * a * a * a;
768  break;
769  case LOG:
770  a = expf(M_LN10 * (a * s->drange - s->drange + s->limit) / 20.f);
771  break;
772  default:
773  av_assert0(0);
774  }
775 
776  if (scale != LOG)
777  a = a * (dmax - dmin) + dmin;
778 
779  return a;
780 }
781 
782 static int draw_legend(AVFilterContext *ctx, uint64_t samples)
783 {
784  ShowSpectrumContext *s = ctx->priv;
785  AVFilterLink *inlink = ctx->inputs[0];
786  AVFilterLink *outlink = ctx->outputs[0];
787  int ch, y, x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
788  int multi = (s->mode == SEPARATE && s->color_mode == CHANNEL);
789  float spp = samples / (float)sz;
790  char *text;
791  uint8_t *dst;
792  char chlayout_str[128];
793 
794  av_channel_layout_describe(&inlink->ch_layout, chlayout_str, sizeof(chlayout_str));
795 
796  text = av_asprintf("%d Hz | %s", inlink->sample_rate, chlayout_str);
797  if (!text)
798  return AVERROR(ENOMEM);
799 
800  drawtext(s->outpicref, 2, outlink->h - 10, "CREATED BY LIBAVFILTER", 0);
801  drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, outlink->h - 10, text, 0);
802  av_freep(&text);
803  if (s->stop) {
804  text = av_asprintf("Zoom: %d Hz - %d Hz", s->start, s->stop);
805  if (!text)
806  return AVERROR(ENOMEM);
807  drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, 3, text, 0);
808  av_freep(&text);
809  }
810 
811  dst = s->outpicref->data[0] + (s->start_y - 1) * s->outpicref->linesize[0] + s->start_x - 1;
812  for (x = 0; x < s->w + 1; x++)
813  dst[x] = 200;
814  dst = s->outpicref->data[0] + (s->start_y + s->h) * s->outpicref->linesize[0] + s->start_x - 1;
815  for (x = 0; x < s->w + 1; x++)
816  dst[x] = 200;
817  for (y = 0; y < s->h + 2; y++) {
818  dst = s->outpicref->data[0] + (y + s->start_y - 1) * s->outpicref->linesize[0];
819  dst[s->start_x - 1] = 200;
820  dst[s->start_x + s->w] = 200;
821  }
822  if (s->orientation == VERTICAL) {
823  int h = s->mode == SEPARATE ? s->h / s->nb_display_channels : s->h;
824  int hh = s->mode == SEPARATE ? -(s->h % s->nb_display_channels) + 1 : 1;
825  for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {
826  for (y = 0; y < h; y += 20) {
827  dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - hh) * s->outpicref->linesize[0];
828  dst[s->start_x - 2] = 200;
829  dst[s->start_x + s->w + 1] = 200;
830  }
831  for (y = 0; y < h; y += 40) {
832  dst = s->outpicref->data[0] + (s->start_y + h * (ch + 1) - y - hh) * s->outpicref->linesize[0];
833  dst[s->start_x - 3] = 200;
834  dst[s->start_x + s->w + 2] = 200;
835  }
836  dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x;
837  for (x = 0; x < s->w; x+=40)
838  dst[x] = 200;
839  dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x;
840  for (x = 0; x < s->w; x+=80)
841  dst[x] = 200;
842  dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x;
843  for (x = 0; x < s->w; x+=40) {
844  dst[x] = 200;
845  }
846  dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x;
847  for (x = 0; x < s->w; x+=80) {
848  dst[x] = 200;
849  }
850  for (y = 0; y < h; y += 40) {
851  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
852  float hertz = get_hz(y, h, s->start, s->start + range, s->fscale);
853  char *units;
854 
855  if (hertz == 0)
856  units = av_asprintf("DC");
857  else
858  units = av_asprintf("%.2f", hertz);
859  if (!units)
860  return AVERROR(ENOMEM);
861 
862  drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, h * (ch + 1) + s->start_y - y - 4 - hh, units, 0);
863  av_free(units);
864  }
865  }
866 
867  for (x = 0; x < s->w && s->single_pic; x+=80) {
868  float seconds = x * spp / inlink->sample_rate;
869  char *units = get_time(ctx, seconds, x);
870  if (!units)
871  return AVERROR(ENOMEM);
872 
873  drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->h + s->start_y + 6, units, 0);
874  drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->start_y - 12, units, 0);
875  av_free(units);
876  }
877 
878  drawtext(s->outpicref, outlink->w / 2 - 4 * 4, outlink->h - s->start_y / 2, "TIME", 0);
879  drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 14 * 4, "FREQUENCY (Hz)", 1);
880  } else {
881  int w = s->mode == SEPARATE ? s->w / s->nb_display_channels : s->w;
882  for (y = 0; y < s->h; y += 20) {
883  dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];
884  dst[s->start_x - 2] = 200;
885  dst[s->start_x + s->w + 1] = 200;
886  }
887  for (y = 0; y < s->h; y += 40) {
888  dst = s->outpicref->data[0] + (s->start_y + y) * s->outpicref->linesize[0];
889  dst[s->start_x - 3] = 200;
890  dst[s->start_x + s->w + 2] = 200;
891  }
892  for (ch = 0; ch < (s->mode == SEPARATE ? s->nb_display_channels : 1); ch++) {
893  dst = s->outpicref->data[0] + (s->start_y - 2) * s->outpicref->linesize[0] + s->start_x + w * ch;
894  for (x = 0; x < w; x+=40)
895  dst[x] = 200;
896  dst = s->outpicref->data[0] + (s->start_y - 3) * s->outpicref->linesize[0] + s->start_x + w * ch;
897  for (x = 0; x < w; x+=80)
898  dst[x] = 200;
899  dst = s->outpicref->data[0] + (s->h + s->start_y + 1) * s->outpicref->linesize[0] + s->start_x + w * ch;
900  for (x = 0; x < w; x+=40) {
901  dst[x] = 200;
902  }
903  dst = s->outpicref->data[0] + (s->h + s->start_y + 2) * s->outpicref->linesize[0] + s->start_x + w * ch;
904  for (x = 0; x < w; x+=80) {
905  dst[x] = 200;
906  }
907  for (x = 0; x < w - 79; x += 80) {
908  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
909  float hertz = get_hz(x, w, s->start, s->start + range, s->fscale);
910  char *units;
911 
912  if (hertz == 0)
913  units = av_asprintf("DC");
914  else
915  units = av_asprintf("%.2f", hertz);
916  if (!units)
917  return AVERROR(ENOMEM);
918 
919  drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->start_y - 12, units, 0);
920  drawtext(s->outpicref, s->start_x - 4 * strlen(units) + x + w * ch, s->h + s->start_y + 6, units, 0);
921  av_free(units);
922  }
923  }
924  for (y = 0; y < s->h && s->single_pic; y+=40) {
925  float seconds = y * spp / inlink->sample_rate;
926  char *units = get_time(ctx, seconds, x);
927  if (!units)
928  return AVERROR(ENOMEM);
929 
930  drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, s->start_y + y - 4, units, 0);
931  av_free(units);
932  }
933  drawtext(s->outpicref, s->start_x / 7, outlink->h / 2 - 4 * 4, "TIME", 1);
934  drawtext(s->outpicref, outlink->w / 2 - 14 * 4, outlink->h - s->start_y / 2, "FREQUENCY (Hz)", 0);
935  }
936 
937  for (ch = 0; ch < (multi ? s->nb_display_channels : 1); ch++) {
938  int h = multi ? s->h / s->nb_display_channels : s->h;
939 
940  for (y = 0; y < h; y++) {
941  float out[4] = { 0., 127.5, 127.5, 0.f};
942  int chn;
943 
944  for (chn = 0; chn < (s->mode == SEPARATE ? 1 : s->nb_display_channels); chn++) {
945  float yf, uf, vf;
946  int channel = (multi) ? s->nb_display_channels - ch - 1 : chn;
947  float lout[4];
948 
949  color_range(s, channel, &yf, &uf, &vf);
950  pick_color(s, yf, uf, vf, y / (float)h, lout);
951  out[0] += lout[0];
952  out[1] += lout[1];
953  out[2] += lout[2];
954  out[3] += lout[3];
955  }
956  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);
957  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);
958  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);
959  if (s->outpicref->data[3])
960  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);
961  }
962 
963  for (y = 0; ch == 0 && y < h + 5; y += 25) {
964  static const char *log_fmt = "%.0f";
965  static const char *lin_fmt = "%.3f";
966  const float a = av_clipf(1.f - y / (float)(h - 1), 0.f, 1.f);
967  const float value = s->scale == LOG ? log10f(get_iscale(ctx, s->scale, a)) * 20.f : get_iscale(ctx, s->scale, a);
968  char *text;
969 
970  text = av_asprintf(s->scale == LOG ? log_fmt : lin_fmt, value);
971  if (!text)
972  continue;
973  drawtext(s->outpicref, s->w + s->start_x + 35, s->start_y + y - 3, text, 0);
974  av_free(text);
975  }
976  }
977 
978  if (s->scale == LOG)
979  drawtext(s->outpicref, s->w + s->start_x + 22, s->start_y + s->h + 20, "dBFS", 0);
980 
981  return 0;
982 }
983 
984 static float get_value(AVFilterContext *ctx, int ch, int y)
985 {
986  ShowSpectrumContext *s = ctx->priv;
987  float *magnitudes = s->magnitudes[ch];
988  float *phases = s->phases[ch];
989  float a;
990 
991  switch (s->data) {
992  case D_MAGNITUDE:
993  /* get magnitude */
994  a = magnitudes[y];
995  break;
996  case D_UPHASE:
997  case D_PHASE:
998  /* get phase */
999  a = phases[y];
1000  break;
1001  default:
1002  av_assert0(0);
1003  }
1004 
1005  return av_clipf(get_scale(ctx, s->scale, a), 0.f, 1.f);
1006 }
1007 
1008 static int plot_channel_lin(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1009 {
1010  ShowSpectrumContext *s = ctx->priv;
1011  const int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width;
1012  const int ch = jobnr;
1013  float yf, uf, vf;
1014  int y;
1015 
1016  /* decide color range */
1017  color_range(s, ch, &yf, &uf, &vf);
1018 
1019  /* draw the channel */
1020  for (y = 0; y < h; y++) {
1021  int row = (s->mode == COMBINED) ? y : ch * h + y;
1022  float *out = &s->color_buffer[ch][4 * row];
1023  float a = get_value(ctx, ch, y);
1024 
1025  pick_color(s, yf, uf, vf, a, out);
1026  }
1027 
1028  return 0;
1029 }
1030 
1031 static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1032 {
1033  ShowSpectrumContext *s = ctx->priv;
1034  AVFilterLink *inlink = ctx->inputs[0];
1035  const int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width;
1036  const int ch = jobnr;
1037  float yf, uf, vf;
1038 
1039  /* decide color range */
1040  color_range(s, ch, &yf, &uf, &vf);
1041 
1042  /* draw the channel */
1043  for (int yy = 0; yy < h; yy++) {
1044  float range = s->stop ? s->stop - s->start : inlink->sample_rate / 2;
1045  float pos = bin_pos(yy, h, s->start, s->start + range);
1046  float delta = pos - floorf(pos);
1047  float a0, a1;
1048 
1049  a0 = get_value(ctx, ch, av_clip(pos, 0, h-1));
1050  a1 = get_value(ctx, ch, av_clip(pos+1, 0, h-1));
1051  {
1052  int row = (s->mode == COMBINED) ? yy : ch * h + yy;
1053  float *out = &s->color_buffer[ch][4 * row];
1054 
1055  pick_color(s, yf, uf, vf, delta * a1 + (1.f - delta) * a0, out);
1056  }
1057  }
1058 
1059  return 0;
1060 }
1061 
1062 static int config_output(AVFilterLink *outlink)
1063 {
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  outlink->frame_rate = s->frame_rate;
1287  outlink->time_base = av_inv_q(outlink->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:48
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:112
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:97
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
ShowSpectrumContext::win_size
int win_size
Definition: avf_showspectrum.c:95
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:1008
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
SCROLL
@ SCROLL
Definition: avf_showspectrum.c:56
av_clip
#define av_clip
Definition: common.h:99
ShowSpectrumContext::eof
int eof
Definition: avf_showspectrum.c:114
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: avf_showspectrum.c:304
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:81
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:436
ShowSpectrumContext::frame_rate
AVRational frame_rate
Definition: avf_showspectrum.c:66
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:119
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
ShowSpectrumContext::frames
AVFrame ** frames
Definition: avf_showspectrum.c:118
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1015
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:617
ff_channel_layouts_ref
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:674
layouts
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:337
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:82
ShowSpectrumContext::mode
int mode
channel display mode
Definition: avf_showspectrum.c:74
ShowSpectrumContext::overlap
float overlap
Definition: avf_showspectrum.c:98
AVTXContext
Definition: tx_priv.h:235
ShowSpectrumContext::gain
float gain
Definition: avf_showspectrum.c:99
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:782
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:105
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:622
SQRT
@ SQRT
Definition: avf_showspectrum.c:54
PHASE
#define PHASE(y, ch)
Definition: avf_showspectrum.c:1319
ShowSpectrumContext::old_len
int old_len
Definition: avf_showspectrum.c:106
ColorTable::y
float y
Definition: avf_showspectrum.c:189
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
ShowSpectrumContext::w
int w
Definition: avf_showspectrum.c:63
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:357
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:55
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:159
config_output
static int config_output(AVFilterLink *outlink)
Definition: avf_showspectrum.c:1062
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:463
D_UPHASE
@ D_UPHASE
Definition: avf_showspectrum.c:52
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:84
ShowSpectrumContext::hop_size
int hop_size
Definition: avf_showspectrum.c:100
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:78
max
#define max(a, b)
Definition: cuda_runtime.h:33
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
COOL
@ COOL
Definition: avf_showspectrum.c:55
ShowSpectrumContext::channel_width
int channel_width
Definition: avf_showspectrum.c:71
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:313
OFFSET
#define OFFSET(x)
Definition: avf_showspectrum.c:123
video.h
FF_FILTER_FORWARD_STATUS_BACK
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
acalc_magnitudes
static void acalc_magnitudes(ShowSpectrumContext *s)
Definition: avf_showspectrum.c:1390
ceilf
static __device__ float ceilf(float a)
Definition: cuda_runtime.h:175
FIFTHRT
@ FIFTHRT
Definition: avf_showspectrum.c:54
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:984
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:92
MORELAND
@ MORELAND
Definition: avf_showspectrum.c:55
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:94
ShowSpectrumContext::outpicref
AVFrame * outpicref
Definition: avf_showspectrum.c:67
ShowSpectrumContext::rotation
float rotation
color rotation
Definition: avf_showspectrum.c:79
ShowSpectrumContext::fft_scratch
AVComplexFloat ** fft_scratch
scratch buffers
Definition: avf_showspectrum.c:90
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:88
ColorMode
ColorMode
Definition: avf_showspectrum.c:55
cosf
#define cosf(x)
Definition: libm.h:78
ShowSpectrumContext::color_mode
int color_mode
display color scheme
Definition: avf_showspectrum.c:75
log10f
#define log10f(x)
Definition: libm.h:414
ShowSpectrumContext::color_buffer
float ** color_buffer
color buffer (4 * h * ch items)
Definition: avf_showspectrum.c:102
ShowSpectrumContext::window_func_lut
float * window_func_lut
Window function LUT.
Definition: avf_showspectrum.c:91
FULLFRAME
@ FULLFRAME
Definition: avf_showspectrum.c:56
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:53
pts
static int64_t pts
Definition: transcode_aac.c:644
RAINBOW
@ RAINBOW
Definition: avf_showspectrum.c:55
ShowSpectrumContext::buf_size
int buf_size
Definition: avf_showspectrum.c:96
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:33
a1
#define a1
Definition: regdef.h:47
D_PHASE
@ D_PHASE
Definition: avf_showspectrum.c:52
FIERY
@ FIERY
Definition: avf_showspectrum.c:55
INTENSITY
@ INTENSITY
Definition: avf_showspectrum.c:55
avassert.h
ceil
static __device__ float ceil(float a)
Definition: cuda_runtime.h:176
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:151
mask
static const uint16_t mask[17]
Definition: lzw.c:38
av_channel_layout_describe
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
Definition: channel_layout.c:645
float
float
Definition: af_crystalizer.c:121
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
NB_DMODES
@ NB_DMODES
Definition: avf_showspectrum.c:52
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:1568
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:713
Orientation
Orientation
Definition: avf_showspectrum.c:57
FRUIT
@ FRUIT
Definition: avf_showspectrum.c:55
mi
#define mi
Definition: vf_colormatrix.c:106
CHANNEL
@ CHANNEL
Definition: avf_showspectrum.c:55
g
const char * g
Definition: vf_curves.c:128
VIRIDIS
@ VIRIDIS
Definition: avf_showspectrum.c:55
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:679
fminf
float fminf(float, float)
ShowSpectrumContext::h
int h
Definition: avf_showspectrum.c:63
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:1031
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:83
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:593
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:701
color_range
color_range
Definition: vf_selectivecolor.c:43
VERTICAL
@ VERTICAL
Definition: avf_showspectrum.c:57
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:182
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:55
ff_inlink_make_frame_writable
int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
Make sure a frame is writable.
Definition: avfilter.c:1489
arg
const char * arg
Definition: jacosubdec.c:67
COMBINED
@ COMBINED
Definition: avf_showspectrum.c:51
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:97
ShowSpectrumContext::combine_buffer
float * combine_buffer
color combining buffer (4 * h items)
Definition: avf_showspectrum.c:101
ShowSpectrumContext::in_frame
AVFrame * in_frame
Definition: avf_showspectrum.c:68
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ShowSpectrumContext::dmax
float dmax
Definition: avf_showspectrum.c:111
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:1462
NULL
#define NULL
Definition: coverity.c:32
NB_SLIDES
@ NB_SLIDES
Definition: avf_showspectrum.c:56
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:89
activate
filter_frame For filters that do not use the activate() callback
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive ints
Definition: opt.h:255
CIVIDIS
@ CIVIDIS
Definition: avf_showspectrum.c:55
parseutils.h
ShowSpectrumContext::start
int start
Definition: avf_showspectrum.c:80
get_time
static char * get_time(AVFilterContext *ctx, float seconds, int x)
Definition: avf_showspectrum.c:665
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:33
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:270
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:51
WFUNC_HANNING
@ WFUNC_HANNING
Definition: window_func.h:29
sinf
#define sinf(x)
Definition: libm.h:419
av_clipf
av_clipf
Definition: af_crystalizer.c:121
log_scale
static float log_scale(const float bin, const float bmin, const float bmax, const float min, const float max)
Definition: avf_showspectrum.c:680
ShowSpectrumContext::limit
float limit
Definition: avf_showspectrum.c:110
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:1389
get_iscale
static float get_iscale(AVFilterContext *ctx, int scale, float a)
Definition: avf_showspectrum.c:748
ShowSpectrumContext::samples
uint64_t samples
Definition: avf_showspectrum.c:112
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:65
ShowSpectrumContext::pts
int64_t pts
Definition: avf_showspectrum.c:103
ShowSpectrumContext::dmin
float dmin
Definition: avf_showspectrum.c:111
ShowSpectrumContext::single_pic
int single_pic
Definition: avf_showspectrum.c:107
f
f
Definition: af_crystalizer.c:121
DataMode
DataMode
Definition: avf_showfreqs.c:40
DEFAULT_LENGTH
#define DEFAULT_LENGTH
Definition: avf_showspectrum.c:59
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:56
D_MAGNITUDE
@ D_MAGNITUDE
Definition: avf_showspectrum.c:52
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:55
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:56
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:38
ColorTable::a
float a
Definition: avf_showspectrum.c:189
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
xga_font_data.h
N
#define N
Definition: af_mcompand.c:54
a0
#define a0
Definition: regdef.h:46
M_PI
#define M_PI
Definition: mathematics.h:67
ShowSpectrumContext::nb_display_channels
int nb_display_channels
Definition: avf_showspectrum.c:69
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
internal.h
ShowSpectrumContext::scale
int scale
Definition: avf_showspectrum.c:76
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:248
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:64
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:104
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:93
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:124
ShowSpectrumContext::channel_height
int channel_height
Definition: avf_showspectrum.c:72
ShowSpectrumContext
Definition: avf_showspectrum.c:61
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:708
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:55
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:39
ff_inlink_queued_samples
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1417
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:57
F_LINEAR
@ F_LINEAR
Definition: avf_showspectrum.c:53
AVFilter
Filter definition.
Definition: avfilter.h:166
ret
ret
Definition: filter_design.txt:187
NB_ORIENTATIONS
@ NB_ORIENTATIONS
Definition: avf_showspectrum.c:57
color_range
static void color_range(ShowSpectrumContext *s, int ch, float *yf, float *uf, float *vf)
Definition: avf_showspectrum.c:555
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:108
run_channel_fft
static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showspectrum.c:393
ShowSpectrumContext::fscale
int fscale
Definition: avf_showspectrum.c:77
window_func.h
NEBULAE
@ NEBULAE
Definition: avf_showspectrum.c:55
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: avf_showspectrum.c:362
ShowSpectrumContext::start_x
int start_x
Definition: avf_showspectrum.c:109
ShowSpectrumContext::stop
int stop
zoom mode
Definition: avf_showspectrum.c:80
ff_all_samplerates
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:607
status
ov_status_e status
Definition: dnn_backend_openvino.c:101
ShowSpectrumContext::orientation
int orientation
Definition: avf_showspectrum.c:70
channel_layout.h
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
LOG
@ LOG
Definition: avf_showspectrum.c:54
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:245
ShowSpectrumContext::fft_size
int fft_size
number of coeffs (FFT window size)
Definition: avf_showspectrum.c:87
avfilter.h
FOURTHRT
@ FOURTHRT
Definition: avf_showspectrum.c:54
NB_MODES
@ NB_MODES
Definition: avf_showspectrum.c:51
cm
#define cm
Definition: dvbsubdec.c:40
F_LOG
@ F_LOG
Definition: avf_showspectrum.c:53
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:116
av_clip_uint8
#define av_clip_uint8
Definition: common.h:105
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:407
DisplayMode
DisplayMode
Definition: avf_ahistogram.c:33
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
ColorTable::v
float v
Definition: avf_showspectrum.c:189
LINEAR
@ LINEAR
Definition: avf_showspectrum.c:54
mem.h
audio.h
ShowSpectrumContext::start_y
int start_y
Definition: avf_showspectrum.c:109
M_LN10
#define M_LN10
Definition: mathematics.h:49
AVFilterFormatsConfig::formats
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:510
DisplayScale
DisplayScale
Definition: avf_ahistogram.c:30
ShowSpectrumContext::itx_fn
av_tx_fn itx_fn
Definition: avf_showspectrum.c:86
ShowSpectrumContext::tx_fn
av_tx_fn tx_fn
Definition: avf_showspectrum.c:85
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:54
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:261
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:183
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:73
d
d
Definition: ffmpeg_filter.c:424
ColorTable::u
float u
Definition: avf_showspectrum.c:189
ShowSpectrumContext::drange
float drange
Definition: avf_showspectrum.c:110
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:54
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ma
#define ma
Definition: vf_colormatrix.c:98
h
h
Definition: vp9dsp_template.c:2038
MAGMA
@ MAGMA
Definition: avf_showspectrum.c:55
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
color_table
static const struct ColorTable color_table[][8]
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:249
showspectrum_options
static const AVOption showspectrum_options[]
Definition: avf_showspectrum.c:126
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:134
ColorTable
Definition: avf_showspectrum.c:188
get_hz
static float get_hz(const float bin, const float bmax, const float min, const float max, int fscale)
Definition: avf_showspectrum.c:687
int
int
Definition: ffmpeg_filter.c:424
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:254
REPLACE
@ REPLACE
Definition: avf_showspectrum.c:56
FIRE
@ FIRE
Definition: avf_showspectrum.c:55
drawtext
static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
Definition: avf_showspectrum.c:500
channel
channel
Definition: ebur128.h:39
ShowSpectrumContext::frames_size
unsigned int frames_size
Definition: avf_showspectrum.c:120
SlideMode
SlideMode
Definition: avf_ahistogram.c:32
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:235
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:113