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