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