FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
avf_showcqt.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015 Muhammad Faiz <mfcc64@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <math.h>
22 #include <stdlib.h>
23 
24 #include "config.h"
25 #include "libavcodec/avfft.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/opt.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/pixdesc.h"
31 #include "avfilter.h"
32 #include "internal.h"
33 #include "lavfutils.h"
34 #include "lswsutils.h"
35 
36 #if CONFIG_LIBFREETYPE
37 #include <ft2build.h>
38 #include FT_FREETYPE_H
39 #endif
40 
41 #include "avf_showcqt.h"
42 
43 #define BASEFREQ 20.01523126408007475
44 #define ENDFREQ 20495.59681441799654
45 #define TLENGTH "384*tc/(384+tc*f)"
46 #define TLENGTH_MIN 0.001
47 #define VOLUME_MAX 100.0
48 #define FONTCOLOR "st(0, (midi(f)-59.5)/12);" \
49  "st(1, if(between(ld(0),0,1), 0.5-0.5*cos(2*PI*ld(0)), 0));" \
50  "r(1-ld(1)) + b(ld(1))"
51 
52 #define OFFSET(x) offsetof(ShowCQTContext, x)
53 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
54 
55 static const AVOption showcqt_options[] = {
56  { "size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },
57  { "s", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" }, 0, 0, FLAGS },
58  { "fps", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, 0, FLAGS },
59  { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, 0, FLAGS },
60  { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, 0, FLAGS },
61  { "bar_h", "set bargraph height", OFFSET(bar_h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS },
62  { "axis_h", "set axis height", OFFSET(axis_h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS },
63  { "sono_h", "set sonogram height", OFFSET(sono_h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS },
64  { "fullhd", "set fullhd size", OFFSET(fullhd), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
65  { "sono_v", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, CHAR_MIN, CHAR_MAX, FLAGS },
66  { "volume", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, CHAR_MIN, CHAR_MAX, FLAGS },
67  { "bar_v", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, CHAR_MIN, CHAR_MAX, FLAGS },
68  { "volume2", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, CHAR_MIN, CHAR_MAX, FLAGS },
69  { "sono_g", "set sonogram gamma", OFFSET(sono_g), AV_OPT_TYPE_FLOAT, { .dbl = 3.0 }, 1.0, 7.0, FLAGS },
70  { "gamma", "set sonogram gamma", OFFSET(sono_g), AV_OPT_TYPE_FLOAT, { .dbl = 3.0 }, 1.0, 7.0, FLAGS },
71  { "bar_g", "set bargraph gamma", OFFSET(bar_g), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 1.0, 7.0, FLAGS },
72  { "gamma2", "set bargraph gamma", OFFSET(bar_g), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 1.0, 7.0, FLAGS },
73  { "timeclamp", "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 }, 0.1, 1.0, FLAGS },
74  { "tc", "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 }, 0.1, 1.0, FLAGS },
75  { "basefreq", "set base frequency", OFFSET(basefreq), AV_OPT_TYPE_DOUBLE, { .dbl = BASEFREQ }, 10.0, 100000.0, FLAGS },
76  { "endfreq", "set end frequency", OFFSET(endfreq), AV_OPT_TYPE_DOUBLE, { .dbl = ENDFREQ }, 10.0, 100000.0, FLAGS },
77  { "coeffclamp", "set coeffclamp", OFFSET(coeffclamp), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.1, 10.0, FLAGS },
78  { "tlength", "set tlength", OFFSET(tlength), AV_OPT_TYPE_STRING, { .str = TLENGTH }, CHAR_MIN, CHAR_MAX, FLAGS },
79  { "count", "set transform count", OFFSET(count), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, 30, FLAGS },
80  { "fcount", "set frequency count", OFFSET(fcount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 10, FLAGS },
81  { "fontfile", "set axis font", OFFSET(fontfile), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS },
82  { "fontcolor", "set font color", OFFSET(fontcolor), AV_OPT_TYPE_STRING, { .str = FONTCOLOR }, CHAR_MIN, CHAR_MAX, FLAGS },
83  { "axisfile", "set axis image", OFFSET(axisfile), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS },
84  { "axis", "draw axis", OFFSET(axis), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
85  { "text", "draw axis", OFFSET(axis), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
86  { NULL }
87 };
88 
89 AVFILTER_DEFINE_CLASS(showcqt);
90 
92 {
93  int k;
94 
95  /* axis_frame may be non reference counted frame */
96  if (s->axis_frame && !s->axis_frame->buf[0]) {
98  for (k = 0; k < 4; k++)
99  s->axis_frame->data[k] = NULL;
100  }
101 
104  av_fft_end(s->fft_ctx);
105  s->fft_ctx = NULL;
106  if (s->coeffs)
107  for (k = 0; k < s->cqt_len * 2; k++)
108  av_freep(&s->coeffs[k].val);
109  av_freep(&s->coeffs);
110  av_freep(&s->fft_data);
111  av_freep(&s->fft_result);
112  av_freep(&s->cqt_result);
113  av_freep(&s->c_buf);
114  av_freep(&s->h_buf);
115  av_freep(&s->rcp_h_buf);
116  av_freep(&s->freq);
117  av_freep(&s->sono_v_buf);
118  av_freep(&s->bar_v_buf);
119 }
120 
121 static double *create_freq_table(double base, double end, int n)
122 {
123  double log_base, log_end;
124  double rcp_n = 1.0 / n;
125  double *freq;
126  int x;
127 
128  freq = av_malloc_array(n, sizeof(*freq));
129  if (!freq)
130  return NULL;
131 
132  log_base = log(base);
133  log_end = log(end);
134  for (x = 0; x < n; x++) {
135  double log_freq = log_base + (x + 0.5) * (log_end - log_base) * rcp_n;
136  freq[x] = exp(log_freq);
137  }
138  return freq;
139 }
140 
141 static double clip_with_log(void *log_ctx, const char *name,
142  double val, double min, double max,
143  double nan_replace, int idx)
144 {
145  int level = AV_LOG_WARNING;
146  if (isnan(val)) {
147  av_log(log_ctx, level, "[%d] %s is nan, setting it to %g.\n",
148  idx, name, nan_replace);
149  val = nan_replace;
150  } else if (val < min) {
151  av_log(log_ctx, level, "[%d] %s is too low (%g), setting it to %g.\n",
152  idx, name, val, min);
153  val = min;
154  } else if (val > max) {
155  av_log(log_ctx, level, "[%d] %s it too high (%g), setting it to %g.\n",
156  idx, name, val, max);
157  val = max;
158  }
159  return val;
160 }
161 
162 static double a_weighting(void *p, double f)
163 {
164  double ret = 12200.0*12200.0 * (f*f*f*f);
165  ret /= (f*f + 20.6*20.6) * (f*f + 12200.0*12200.0) *
166  sqrt((f*f + 107.7*107.7) * (f*f + 737.9*737.9));
167  return ret;
168 }
169 
170 static double b_weighting(void *p, double f)
171 {
172  double ret = 12200.0*12200.0 * (f*f*f);
173  ret /= (f*f + 20.6*20.6) * (f*f + 12200.0*12200.0) * sqrt(f*f + 158.5*158.5);
174  return ret;
175 }
176 
177 static double c_weighting(void *p, double f)
178 {
179  double ret = 12200.0*12200.0 * (f*f);
180  ret /= (f*f + 20.6*20.6) * (f*f + 12200.0*12200.0);
181  return ret;
182 }
183 
185 {
186  const char *func_names[] = { "a_weighting", "b_weighting", "c_weighting", NULL };
187  const char *sono_names[] = { "timeclamp", "tc", "frequency", "freq", "f", "bar_v", NULL };
188  const char *bar_names[] = { "timeclamp", "tc", "frequency", "freq", "f", "sono_v", NULL };
189  double (*funcs[])(void *, double) = { a_weighting, b_weighting, c_weighting };
190  AVExpr *sono = NULL, *bar = NULL;
191  int x, ret = AVERROR(ENOMEM);
192 
193  s->sono_v_buf = av_malloc_array(s->cqt_len, sizeof(*s->sono_v_buf));
194  s->bar_v_buf = av_malloc_array(s->cqt_len, sizeof(*s->bar_v_buf));
195  if (!s->sono_v_buf || !s->bar_v_buf)
196  goto error;
197 
198  if ((ret = av_expr_parse(&sono, s->sono_v, sono_names, func_names, funcs, NULL, NULL, 0, s->ctx)) < 0)
199  goto error;
200 
201  if ((ret = av_expr_parse(&bar, s->bar_v, bar_names, func_names, funcs, NULL, NULL, 0, s->ctx)) < 0)
202  goto error;
203 
204  for (x = 0; x < s->cqt_len; x++) {
205  double vars[] = { s->timeclamp, s->timeclamp, s->freq[x], s->freq[x], s->freq[x], 0.0 };
206  double vol = clip_with_log(s->ctx, "sono_v", av_expr_eval(sono, vars, NULL), 0.0, VOLUME_MAX, 0.0, x);
207  vars[5] = vol;
208  vol = clip_with_log(s->ctx, "bar_v", av_expr_eval(bar, vars, NULL), 0.0, VOLUME_MAX, 0.0, x);
209  s->bar_v_buf[x] = vol * vol;
210  vars[5] = vol;
211  vol = clip_with_log(s->ctx, "sono_v", av_expr_eval(sono, vars, NULL), 0.0, VOLUME_MAX, 0.0, x);
212  s->sono_v_buf[x] = vol * vol;
213  }
214  av_expr_free(sono);
215  av_expr_free(bar);
216  return 0;
217 
218 error:
219  av_freep(&s->sono_v_buf);
220  av_freep(&s->bar_v_buf);
221  av_expr_free(sono);
222  av_expr_free(bar);
223  return ret;
224 }
225 
226 static void cqt_calc(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs,
227  int len, int fft_len)
228 {
229  int k, x, i, j;
230  for (k = 0; k < len; k++) {
231  FFTComplex l, r, a = {0,0}, b = {0,0};
232 
233  for (x = 0; x < coeffs[k].len; x++) {
234  FFTSample u = coeffs[k].val[x];
235  i = coeffs[k].start + x;
236  j = fft_len - i;
237  a.re += u * src[i].re;
238  a.im += u * src[i].im;
239  b.re += u * src[j].re;
240  b.im += u * src[j].im;
241  }
242 
243  /* separate left and right, (and multiply by 2.0) */
244  l.re = a.re + b.re;
245  l.im = a.im - b.im;
246  r.re = b.im + a.im;
247  r.im = b.re - a.re;
248  dst[k].re = l.re * l.re + l.im * l.im;
249  dst[k].im = r.re * r.re + r.im * r.im;
250  }
251 }
252 
253 #if 0
254 static void cqt_calc_interleave(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs,
255  int len, int fft_len)
256 {
257  int k, x, i, m;
258 
259  for (k = 0; k < len; k++) {
260  FFTComplex l, r, a = {0,0}, b = {0,0};
261 
262  m = 2 * k;
263  for (x = 0; x < coeffs[m].len; x++) {
264  FFTSample u = coeffs[m].val[x];
265  i = coeffs[m].start + x;
266  a.re += u * src[i].re;
267  a.im += u * src[i].im;
268  }
269 
270  m++;
271  for (x = 0; x < coeffs[m].len; x++) {
272  FFTSample u = coeffs[m].val[x];
273  i = coeffs[m].start + x;
274  b.re += u * src[i].re;
275  b.im += u * src[i].im;
276  }
277 
278  /* separate left and right, (and multiply by 2.0) */
279  l.re = a.re + b.re;
280  l.im = a.im - b.im;
281  r.re = b.im + a.im;
282  r.im = b.re - a.re;
283  dst[k].re = l.re * l.re + l.im * l.im;
284  dst[k].im = r.re * r.re + r.im * r.im;
285  }
286 }
287 #endif
288 
290 {
291  const char *var_names[] = { "timeclamp", "tc", "frequency", "freq", "f", NULL };
292  AVExpr *expr = NULL;
293  int rate = s->ctx->inputs[0]->sample_rate;
294  int nb_cqt_coeffs = 0, nb_cqt_coeffs_r = 0;
295  int k, x, ret;
296 
297  if ((ret = av_expr_parse(&expr, s->tlength, var_names, NULL, NULL, NULL, NULL, 0, s->ctx)) < 0)
298  goto error;
299 
300  ret = AVERROR(ENOMEM);
301  if (!(s->coeffs = av_calloc(s->cqt_len * 2, sizeof(*s->coeffs))))
302  goto error;
303 
304  for (k = 0; k < s->cqt_len; k++) {
305  double vars[] = { s->timeclamp, s->timeclamp, s->freq[k], s->freq[k], s->freq[k] };
306  double flen, center, tlength;
307  int start, end, m = (s->cqt_coeffs_type == COEFFS_TYPE_INTERLEAVE) ? (2 * k) : k;
308 
309  if (s->freq[k] > 0.5 * rate)
310  continue;
311  tlength = clip_with_log(s->ctx, "tlength", av_expr_eval(expr, vars, NULL),
312  TLENGTH_MIN, s->timeclamp, s->timeclamp, k);
313 
314  flen = 8.0 * s->fft_len / (tlength * rate);
315  center = s->freq[k] * s->fft_len / rate;
316  start = FFMAX(0, ceil(center - 0.5 * flen));
317  end = FFMIN(s->fft_len, floor(center + 0.5 * flen));
318 
319  s->coeffs[m].start = start & ~(s->cqt_align - 1);
320  s->coeffs[m].len = (end | (s->cqt_align - 1)) + 1 - s->coeffs[m].start;
321  nb_cqt_coeffs += s->coeffs[m].len;
322  if (!(s->coeffs[m].val = av_calloc(s->coeffs[m].len, sizeof(*s->coeffs[m].val))))
323  goto error;
324 
326  s->coeffs[m+1].start = (s->fft_len - end) & ~(s->cqt_align - 1);
327  s->coeffs[m+1].len = ((s->fft_len - start) | (s->cqt_align - 1)) + 1 - s->coeffs[m+1].start;
328  nb_cqt_coeffs_r += s->coeffs[m+1].len;
329  if (!(s->coeffs[m+1].val = av_calloc(s->coeffs[m+1].len, sizeof(*s->coeffs[m+1].val))))
330  goto error;
331  }
332 
333  for (x = start; x <= end; x++) {
334  int sign = (x & 1) ? (-1) : 1;
335  double y = 2.0 * M_PI * (x - center) * (1.0 / flen);
336  /* nuttall window */
337  double w = 0.355768 + 0.487396 * cos(y) + 0.144232 * cos(2*y) + 0.012604 * cos(3*y);
338  w *= sign * (1.0 / s->fft_len);
339  s->coeffs[m].val[x - s->coeffs[m].start] = w;
341  s->coeffs[m+1].val[(s->fft_len - x) - s->coeffs[m+1].start] = w;
342  }
343  }
344 
345  av_expr_free(expr);
347  av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = %d.\n", nb_cqt_coeffs);
348  else
349  av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = {%d,%d}.\n", nb_cqt_coeffs, nb_cqt_coeffs_r);
350  return 0;
351 
352 error:
353  av_expr_free(expr);
354  if (s->coeffs)
355  for (k = 0; k < s->cqt_len * 2; k++)
356  av_freep(&s->coeffs[k].val);
357  av_freep(&s->coeffs);
358  return ret;
359 }
360 
361 static AVFrame *alloc_frame_empty(enum AVPixelFormat format, int w, int h)
362 {
363  AVFrame *out;
364  out = av_frame_alloc();
365  if (!out)
366  return NULL;
367  out->format = format;
368  out->width = w;
369  out->height = h;
370  if (av_frame_get_buffer(out, 32) < 0) {
371  av_frame_free(&out);
372  return NULL;
373  }
374  if (format == AV_PIX_FMT_RGB24 || format == AV_PIX_FMT_RGBA) {
375  memset(out->data[0], 0, out->linesize[0] * h);
376  } else {
377  int hh = (format == AV_PIX_FMT_YUV420P || format == AV_PIX_FMT_YUVA420P) ? h / 2 : h;
378  memset(out->data[0], 16, out->linesize[0] * h);
379  memset(out->data[1], 128, out->linesize[1] * hh);
380  memset(out->data[2], 128, out->linesize[2] * hh);
381  if (out->data[3])
382  memset(out->data[3], 0, out->linesize[3] * h);
383  }
384  return out;
385 }
386 
388 {
389  switch (format) {
390  case AV_PIX_FMT_RGB24: format = AV_PIX_FMT_RGBA; break;
391  case AV_PIX_FMT_YUV444P: format = AV_PIX_FMT_YUVA444P; break;
392  case AV_PIX_FMT_YUV422P: format = AV_PIX_FMT_YUVA422P; break;
393  case AV_PIX_FMT_YUV420P: format = AV_PIX_FMT_YUVA420P; break;
394  }
395  return format;
396 }
397 
399 {
401  return AVERROR(ENOMEM);
402  return 0;
403 }
404 
406 {
407  uint8_t *tmp_data[4] = { NULL };
408  int tmp_linesize[4];
409  enum AVPixelFormat tmp_format;
410  int tmp_w, tmp_h, ret;
411 
412  if ((ret = ff_load_image(tmp_data, tmp_linesize, &tmp_w, &tmp_h, &tmp_format,
413  s->axisfile, s->ctx)) < 0)
414  goto error;
415 
416  ret = AVERROR(ENOMEM);
417  if (!(s->axis_frame = av_frame_alloc()))
418  goto error;
419 
420  if ((ret = ff_scale_image(s->axis_frame->data, s->axis_frame->linesize, s->width, s->axis_h,
421  convert_axis_pixel_format(s->format), tmp_data, tmp_linesize, tmp_w, tmp_h,
422  tmp_format, s->ctx)) < 0)
423  goto error;
424 
425  s->axis_frame->width = s->width;
426  s->axis_frame->height = s->axis_h;
428  av_freep(tmp_data);
429  return 0;
430 
431 error:
433  av_freep(tmp_data);
434  return ret;
435 }
436 
437 static double midi(void *p, double f)
438 {
439  return log2(f/440.0) * 12.0 + 69.0;
440 }
441 
442 static double r_func(void *p, double x)
443 {
444  x = av_clipd(x, 0.0, 1.0);
445  return (int)(x*255.0+0.5) << 16;
446 }
447 
448 static double g_func(void *p, double x)
449 {
450  x = av_clipd(x, 0.0, 1.0);
451  return (int)(x*255.0+0.5) << 8;
452 }
453 
454 static double b_func(void *p, double x)
455 {
456  x = av_clipd(x, 0.0, 1.0);
457  return (int)(x*255.0+0.5);
458 }
459 
461 {
462  const char *var_names[] = { "timeclamp", "tc", "frequency", "freq", "f", NULL };
463  const char *func_names[] = { "midi", "r", "g", "b", NULL };
464  double (*funcs[])(void *, double) = { midi, r_func, g_func, b_func };
465  AVExpr *expr = NULL;
466  double *freq = NULL;
467  int x, y, ret;
468 
469  if (s->basefreq != (double) BASEFREQ || s->endfreq != (double) ENDFREQ) {
470  av_log(s->ctx, AV_LOG_WARNING, "font axis rendering is not implemented in non-default frequency range,"
471  " please use axisfile option instead.\n");
472  return AVERROR(EINVAL);
473  }
474 
475  if (s->cqt_len == 1920)
476  freq = s->freq;
477  else if (!(freq = create_freq_table(s->basefreq, s->endfreq, 1920)))
478  return AVERROR(ENOMEM);
479 
480  if ((ret = av_expr_parse(&expr, s->fontcolor, var_names, func_names, funcs, NULL, NULL, 0, s->ctx)) < 0) {
481  if (freq != s->freq)
482  av_freep(&freq);
483  return ret;
484  }
485 
486  for (x = 0; x < 1920; x++) {
487  double vars[] = { s->timeclamp, s->timeclamp, freq[x], freq[x], freq[x] };
488  int color = (int) av_expr_eval(expr, vars, NULL);
489  uint8_t r = (color >> 16) & 0xFF, g = (color >> 8) & 0xFF, b = color & 0xFF;
490  uint8_t *data = tmp->data[0];
491  int linesize = tmp->linesize[0];
492  for (y = 0; y < 32; y++) {
493  data[linesize * y + 4 * x] = r;
494  data[linesize * y + 4 * x + 1] = g;
495  data[linesize * y + 4 * x + 2] = b;
496  data[linesize * y + 4 * x + 3] = 0;
497  }
498  }
499 
500  av_expr_free(expr);
501  if (freq != s->freq)
502  av_freep(&freq);
503  return 0;
504 }
505 
507 {
508 #if CONFIG_LIBFREETYPE
509  const char *str = "EF G A BC D ";
510  uint8_t *data = tmp->data[0];
511  int linesize = tmp->linesize[0];
512  FT_Library lib = NULL;
513  FT_Face face = NULL;
514  int font_width = 16, font_height = 32;
515  int font_repeat = font_width * 12;
516  int linear_hori_advance = font_width * 65536;
517  int non_monospace_warning = 0;
518  int x;
519 
520  if (!s->fontfile)
521  return AVERROR(EINVAL);
522 
523  if (FT_Init_FreeType(&lib))
524  goto fail;
525 
526  if (FT_New_Face(lib, s->fontfile, 0, &face))
527  goto fail;
528 
529  if (FT_Set_Char_Size(face, 16*64, 0, 0, 0))
530  goto fail;
531 
532  if (FT_Load_Char(face, 'A', FT_LOAD_RENDER))
533  goto fail;
534 
535  if (FT_Set_Char_Size(face, 16*64 * linear_hori_advance / face->glyph->linearHoriAdvance, 0, 0, 0))
536  goto fail;
537 
538  for (x = 0; x < 12; x++) {
539  int sx, sy, rx, bx, by, dx, dy;
540 
541  if (str[x] == ' ')
542  continue;
543 
544  if (FT_Load_Char(face, str[x], FT_LOAD_RENDER))
545  goto fail;
546 
547  if (face->glyph->advance.x != font_width*64 && !non_monospace_warning) {
548  av_log(s->ctx, AV_LOG_WARNING, "font is not monospace.\n");
549  non_monospace_warning = 1;
550  }
551 
552  sy = font_height - 8 - face->glyph->bitmap_top;
553  for (rx = 0; rx < 10; rx++) {
554  sx = rx * font_repeat + x * font_width + face->glyph->bitmap_left;
555  for (by = 0; by < face->glyph->bitmap.rows; by++) {
556  dy = by + sy;
557  if (dy < 0)
558  continue;
559  if (dy >= font_height)
560  break;
561 
562  for (bx = 0; bx < face->glyph->bitmap.width; bx++) {
563  dx = bx + sx;
564  if (dx < 0)
565  continue;
566  if (dx >= 1920)
567  break;
568  data[dy*linesize+4*dx+3] = face->glyph->bitmap.buffer[by*face->glyph->bitmap.width+bx];
569  }
570  }
571  }
572  }
573 
574  FT_Done_Face(face);
575  FT_Done_FreeType(lib);
576  return 0;
577 
578 fail:
579  av_log(s->ctx, AV_LOG_WARNING, "error while loading freetype font, using default font instead.\n");
580  FT_Done_Face(face);
581  FT_Done_FreeType(lib);
582  return AVERROR(EINVAL);
583 #else
584  if (s->fontfile)
585  av_log(s->ctx, AV_LOG_WARNING, "freetype is not available, ignoring fontfile option.\n");
586  return AVERROR(EINVAL);
587 #endif
588 }
589 
590 static int render_default_font(AVFrame *tmp)
591 {
592  const char *str = "EF G A BC D ";
593  int x, u, v, mask;
594  uint8_t *data = tmp->data[0];
595  int linesize = tmp->linesize[0];
596 
597  for (x = 0; x < 1920; x += 192) {
598  uint8_t *startptr = data + 4 * x;
599  for (u = 0; u < 12; u++) {
600  for (v = 0; v < 16; v++) {
601  uint8_t *p = startptr + 2 * v * linesize + 16 * 4 * u;
602  for (mask = 0x80; mask; mask >>= 1, p += 8) {
603  if (mask & avpriv_vga16_font[str[u] * 16 + v]) {
604  p[3] = 255;
605  p[7] = 255;
606  p[linesize+3] = 255;
607  p[linesize+7] = 255;
608  }
609  }
610  }
611  }
612  }
613 
614  return 0;
615 }
616 
618 {
619  AVFrame *tmp = NULL;
620  int ret = AVERROR(ENOMEM);
621 
622  if (!(tmp = alloc_frame_empty(AV_PIX_FMT_RGBA, 1920, 32)))
623  goto fail;
624 
625  if (!(s->axis_frame = av_frame_alloc()))
626  goto fail;
627 
628  if ((ret = init_axis_color(s, tmp)) < 0)
629  goto fail;
630 
631  if (render_freetype(s, tmp) < 0 && (ret = render_default_font(tmp)) < 0)
632  goto fail;
633 
634  if ((ret = ff_scale_image(s->axis_frame->data, s->axis_frame->linesize, s->width, s->axis_h,
636  1920, 32, AV_PIX_FMT_RGBA, s->ctx)) < 0)
637  goto fail;
638 
639  av_frame_free(&tmp);
640  s->axis_frame->width = s->width;
641  s->axis_frame->height = s->axis_h;
643  return 0;
644 
645 fail:
646  av_frame_free(&tmp);
648  return ret;
649 }
650 
651 static float calculate_gamma(float v, float g)
652 {
653  if (g == 1.0f)
654  return v;
655  if (g == 2.0f)
656  return sqrtf(v);
657  if (g == 3.0f)
658  return cbrtf(v);
659  if (g == 4.0f)
660  return sqrtf(sqrtf(v));
661  return expf(logf(v) / g);
662 }
663 
664 static void rgb_from_cqt(ColorFloat *c, const FFTComplex *v, float g, int len)
665 {
666  int x;
667  for (x = 0; x < len; x++) {
668  c[x].rgb.r = 255.0f * calculate_gamma(FFMIN(1.0f, v[x].re), g);
669  c[x].rgb.g = 255.0f * calculate_gamma(FFMIN(1.0f, 0.5f * (v[x].re + v[x].im)), g);
670  c[x].rgb.b = 255.0f * calculate_gamma(FFMIN(1.0f, v[x].im), g);
671  }
672 }
673 
674 static void yuv_from_cqt(ColorFloat *c, const FFTComplex *v, float gamma, int len)
675 {
676  int x;
677  for (x = 0; x < len; x++) {
678  float r, g, b;
679  r = calculate_gamma(FFMIN(1.0f, v[x].re), gamma);
680  g = calculate_gamma(FFMIN(1.0f, 0.5f * (v[x].re + v[x].im)), gamma);
681  b = calculate_gamma(FFMIN(1.0f, v[x].im), gamma);
682  c[x].yuv.y = 65.481f * r + 128.553f * g + 24.966f * b;
683  c[x].yuv.u = -37.797f * r - 74.203f * g + 112.0f * b;
684  c[x].yuv.v = 112.0f * r - 93.786f * g - 18.214 * b;
685  }
686 }
687 
688 static void draw_bar_rgb(AVFrame *out, const float *h, const float *rcp_h,
689  const ColorFloat *c, int bar_h)
690 {
691  int x, y, w = out->width;
692  float mul, ht, rcp_bar_h = 1.0f / bar_h;
693  uint8_t *v = out->data[0], *lp;
694  int ls = out->linesize[0];
695 
696  for (y = 0; y < bar_h; y++) {
697  ht = (bar_h - y) * rcp_bar_h;
698  lp = v + y * ls;
699  for (x = 0; x < w; x++) {
700  if (h[x] <= ht) {
701  *lp++ = 0;
702  *lp++ = 0;
703  *lp++ = 0;
704  } else {
705  mul = (h[x] - ht) * rcp_h[x];
706  *lp++ = mul * c[x].rgb.r + 0.5f;
707  *lp++ = mul * c[x].rgb.g + 0.5f;
708  *lp++ = mul * c[x].rgb.b + 0.5f;
709  }
710  }
711  }
712 }
713 
714 static void draw_bar_yuv(AVFrame *out, const float *h, const float *rcp_h,
715  const ColorFloat *c, int bar_h)
716 {
717  int x, y, yh, w = out->width;
718  float mul, ht, rcp_bar_h = 1.0f / bar_h;
719  uint8_t *vy = out->data[0], *vu = out->data[1], *vv = out->data[2];
720  uint8_t *lpy, *lpu, *lpv;
721  int lsy = out->linesize[0], lsu = out->linesize[1], lsv = out->linesize[2];
722  int fmt = out->format;
723 
724  for (y = 0; y < bar_h; y += 2) {
725  yh = (fmt == AV_PIX_FMT_YUV420P) ? y / 2 : y;
726  ht = (bar_h - y) * rcp_bar_h;
727  lpy = vy + y * lsy;
728  lpu = vu + yh * lsu;
729  lpv = vv + yh * lsv;
730  for (x = 0; x < w; x += 2) {
731  if (h[x] <= ht) {
732  *lpy++ = 16;
733  *lpu++ = 128;
734  *lpv++ = 128;
735  } else {
736  mul = (h[x] - ht) * rcp_h[x];
737  *lpy++ = mul * c[x].yuv.y + 16.5f;
738  *lpu++ = mul * c[x].yuv.u + 128.5f;
739  *lpv++ = mul * c[x].yuv.v + 128.5f;
740  }
741  /* u and v are skipped on yuv422p and yuv420p */
742  if (fmt == AV_PIX_FMT_YUV444P) {
743  if (h[x+1] <= ht) {
744  *lpy++ = 16;
745  *lpu++ = 128;
746  *lpv++ = 128;
747  } else {
748  mul = (h[x+1] - ht) * rcp_h[x+1];
749  *lpy++ = mul * c[x+1].yuv.y + 16.5f;
750  *lpu++ = mul * c[x+1].yuv.u + 128.5f;
751  *lpv++ = mul * c[x+1].yuv.v + 128.5f;
752  }
753  } else {
754  if (h[x+1] <= ht) {
755  *lpy++ = 16;
756  } else {
757  mul = (h[x+1] - ht) * rcp_h[x+1];
758  *lpy++ = mul * c[x+1].yuv.y + 16.5f;
759  }
760  }
761  }
762 
763  ht = (bar_h - (y+1)) * rcp_bar_h;
764  lpy = vy + (y+1) * lsy;
765  lpu = vu + (y+1) * lsu;
766  lpv = vv + (y+1) * lsv;
767  for (x = 0; x < w; x += 2) {
768  /* u and v are skipped on yuv420p */
769  if (fmt != AV_PIX_FMT_YUV420P) {
770  if (h[x] <= ht) {
771  *lpy++ = 16;
772  *lpu++ = 128;
773  *lpv++ = 128;
774  } else {
775  mul = (h[x] - ht) * rcp_h[x];
776  *lpy++ = mul * c[x].yuv.y + 16.5f;
777  *lpu++ = mul * c[x].yuv.u + 128.5f;
778  *lpv++ = mul * c[x].yuv.v + 128.5f;
779  }
780  } else {
781  if (h[x] <= ht) {
782  *lpy++ = 16;
783  } else {
784  mul = (h[x] - ht) * rcp_h[x];
785  *lpy++ = mul * c[x].yuv.y + 16.5f;
786  }
787  }
788  /* u and v are skipped on yuv422p and yuv420p */
789  if (out->format == AV_PIX_FMT_YUV444P) {
790  if (h[x+1] <= ht) {
791  *lpy++ = 16;
792  *lpu++ = 128;
793  *lpv++ = 128;
794  } else {
795  mul = (h[x+1] - ht) * rcp_h[x+1];
796  *lpy++ = mul * c[x+1].yuv.y + 16.5f;
797  *lpu++ = mul * c[x+1].yuv.u + 128.5f;
798  *lpv++ = mul * c[x+1].yuv.v + 128.5f;
799  }
800  } else {
801  if (h[x+1] <= ht) {
802  *lpy++ = 16;
803  } else {
804  mul = (h[x+1] - ht) * rcp_h[x+1];
805  *lpy++ = mul * c[x+1].yuv.y + 16.5f;
806  }
807  }
808  }
809  }
810 }
811 
812 static void draw_axis_rgb(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
813 {
814  int x, y, w = axis->width, h = axis->height;
815  float a, rcp_255 = 1.0f / 255.0f;
816  uint8_t *lp, *lpa;
817 
818  for (y = 0; y < h; y++) {
819  lp = out->data[0] + (off + y) * out->linesize[0];
820  lpa = axis->data[0] + y * axis->linesize[0];
821  for (x = 0; x < w; x++) {
822  a = rcp_255 * lpa[3];
823  *lp++ = a * lpa[0] + (1.0f - a) * c[x].rgb.r + 0.5f;
824  *lp++ = a * lpa[1] + (1.0f - a) * c[x].rgb.g + 0.5f;
825  *lp++ = a * lpa[2] + (1.0f - a) * c[x].rgb.b + 0.5f;
826  lpa += 4;
827  }
828  }
829 }
830 
831 static void draw_axis_yuv(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
832 {
833  int fmt = out->format, x, y, yh, w = axis->width, h = axis->height;
834  int offh = (fmt == AV_PIX_FMT_YUV420P) ? off / 2 : off;
835  float a, rcp_255 = 1.0f / 255.0f;
836  uint8_t *vy = out->data[0], *vu = out->data[1], *vv = out->data[2];
837  uint8_t *vay = axis->data[0], *vau = axis->data[1], *vav = axis->data[2], *vaa = axis->data[3];
838  int lsy = out->linesize[0], lsu = out->linesize[1], lsv = out->linesize[2];
839  int lsay = axis->linesize[0], lsau = axis->linesize[1], lsav = axis->linesize[2], lsaa = axis->linesize[3];
840  uint8_t *lpy, *lpu, *lpv, *lpay, *lpau, *lpav, *lpaa;
841 
842  for (y = 0; y < h; y += 2) {
843  yh = (fmt == AV_PIX_FMT_YUV420P) ? y / 2 : y;
844  lpy = vy + (off + y) * lsy;
845  lpu = vu + (offh + yh) * lsu;
846  lpv = vv + (offh + yh) * lsv;
847  lpay = vay + y * lsay;
848  lpau = vau + yh * lsau;
849  lpav = vav + yh * lsav;
850  lpaa = vaa + y * lsaa;
851  for (x = 0; x < w; x += 2) {
852  a = rcp_255 * (*lpaa++);
853  *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x].yuv.y + 16.0f) + 0.5f;
854  *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x].yuv.u + 128.0f) + 0.5f;
855  *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x].yuv.v + 128.0f) + 0.5f;
856  /* u and v are skipped on yuv422p and yuv420p */
857  a = rcp_255 * (*lpaa++);
858  *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x+1].yuv.y + 16.0f) + 0.5f;
859  if (fmt == AV_PIX_FMT_YUV444P) {
860  *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x+1].yuv.u + 128.0f) + 0.5f;
861  *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x+1].yuv.v + 128.0f) + 0.5f;
862  }
863  }
864 
865  lpy = vy + (off + y + 1) * lsy;
866  lpu = vu + (off + y + 1) * lsu;
867  lpv = vv + (off + y + 1) * lsv;
868  lpay = vay + (y + 1) * lsay;
869  lpau = vau + (y + 1) * lsau;
870  lpav = vav + (y + 1) * lsav;
871  lpaa = vaa + (y + 1) * lsaa;
872  for (x = 0; x < out->width; x += 2) {
873  /* u and v are skipped on yuv420p */
874  a = rcp_255 * (*lpaa++);
875  *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x].yuv.y + 16.0f) + 0.5f;
876  if (fmt != AV_PIX_FMT_YUV420P) {
877  *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x].yuv.u + 128.0f) + 0.5f;
878  *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x].yuv.v + 128.0f) + 0.5f;
879  }
880  /* u and v are skipped on yuv422p and yuv420p */
881  a = rcp_255 * (*lpaa++);
882  *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x+1].yuv.y + 16.0f) + 0.5f;
883  if (fmt == AV_PIX_FMT_YUV444P) {
884  *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x+1].yuv.u + 128.0f) + 0.5f;
885  *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x+1].yuv.v + 128.0f) + 0.5f;
886  }
887  }
888  }
889 }
890 
891 static void draw_sono(AVFrame *out, AVFrame *sono, int off, int idx)
892 {
893  int fmt = out->format, h = sono->height;
894  int nb_planes = (fmt == AV_PIX_FMT_RGB24) ? 1 : 3;
895  int offh = (fmt == AV_PIX_FMT_YUV420P) ? off / 2 : off;
896  int inc = (fmt == AV_PIX_FMT_YUV420P) ? 2 : 1;
897  int ls, i, y, yh;
898 
899  ls = FFMIN(out->linesize[0], sono->linesize[0]);
900  for (y = 0; y < h; y++) {
901  memcpy(out->data[0] + (off + y) * out->linesize[0],
902  sono->data[0] + (idx + y) % h * sono->linesize[0], ls);
903  }
904 
905  for (i = 1; i < nb_planes; i++) {
906  ls = FFMIN(out->linesize[i], sono->linesize[i]);
907  for (y = 0; y < h; y += inc) {
908  yh = (fmt == AV_PIX_FMT_YUV420P) ? y / 2 : y;
909  memcpy(out->data[i] + (offh + yh) * out->linesize[i],
910  sono->data[i] + (idx + y) % h * sono->linesize[i], ls);
911  }
912  }
913 }
914 
915 static void update_sono_rgb(AVFrame *sono, const ColorFloat *c, int idx)
916 {
917  int x, w = sono->width;
918  uint8_t *lp = sono->data[0] + idx * sono->linesize[0];
919 
920  for (x = 0; x < w; x++) {
921  *lp++ = c[x].rgb.r + 0.5f;
922  *lp++ = c[x].rgb.g + 0.5f;
923  *lp++ = c[x].rgb.b + 0.5f;
924  }
925 }
926 
927 static void update_sono_yuv(AVFrame *sono, const ColorFloat *c, int idx)
928 {
929  int x, fmt = sono->format, w = sono->width;
930  uint8_t *lpy = sono->data[0] + idx * sono->linesize[0];
931  uint8_t *lpu = sono->data[1] + idx * sono->linesize[1];
932  uint8_t *lpv = sono->data[2] + idx * sono->linesize[2];
933 
934  for (x = 0; x < w; x += 2) {
935  *lpy++ = c[x].yuv.y + 16.5f;
936  *lpu++ = c[x].yuv.u + 128.5f;
937  *lpv++ = c[x].yuv.v + 128.5f;
938  *lpy++ = c[x+1].yuv.y + 16.5f;
939  if (fmt == AV_PIX_FMT_YUV444P) {
940  *lpu++ = c[x+1].yuv.u + 128.5f;
941  *lpv++ = c[x+1].yuv.v + 128.5f;
942  }
943  }
944 }
945 
947 {
948  int x, i;
949  if (!s->sono_count) {
950  for (x = 0; x < s->cqt_len; x++) {
951  s->h_buf[x] = s->bar_v_buf[x] * 0.5f * (s->cqt_result[x].re + s->cqt_result[x].im);
952  }
953  if (s->fcount > 1) {
954  float rcp_fcount = 1.0f / s->fcount;
955  for (x = 0; x < s->width; x++) {
956  float h = 0.0f;
957  for (i = 0; i < s->fcount; i++)
958  h += s->h_buf[s->fcount * x + i];
959  s->h_buf[x] = rcp_fcount * h;
960  }
961  }
962  for (x = 0; x < s->width; x++) {
963  s->h_buf[x] = calculate_gamma(s->h_buf[x], s->bar_g);
964  s->rcp_h_buf[x] = 1.0f / (s->h_buf[x] + 0.0001f);
965  }
966  }
967 
968  for (x = 0; x < s->cqt_len; x++) {
969  s->cqt_result[x].re *= s->sono_v_buf[x];
970  s->cqt_result[x].im *= s->sono_v_buf[x];
971  }
972 
973  if (s->fcount > 1) {
974  float rcp_fcount = 1.0f / s->fcount;
975  for (x = 0; x < s->width; x++) {
976  FFTComplex result = {0.0f, 0.0f};
977  for (i = 0; i < s->fcount; i++) {
978  result.re += s->cqt_result[s->fcount * x + i].re;
979  result.im += s->cqt_result[s->fcount * x + i].im;
980  }
981  s->cqt_result[x].re = rcp_fcount * result.re;
982  s->cqt_result[x].im = rcp_fcount * result.im;
983  }
984  }
985 
986  if (s->format == AV_PIX_FMT_RGB24)
987  rgb_from_cqt(s->c_buf, s->cqt_result, s->sono_g, s->width);
988  else
989  yuv_from_cqt(s->c_buf, s->cqt_result, s->sono_g, s->width);
990 }
991 
993 {
994  AVFilterLink *outlink = ctx->outputs[0];
995  ShowCQTContext *s = ctx->priv;
996  int ret = 0;
997 
998  memcpy(s->fft_result, s->fft_data, s->fft_len * sizeof(*s->fft_data));
1000  av_fft_calc(s->fft_ctx, s->fft_result);
1001  s->fft_result[s->fft_len] = s->fft_result[0];
1002  s->cqt_calc(s->cqt_result, s->fft_result, s->coeffs, s->cqt_len, s->fft_len);
1003  process_cqt(s);
1004  if (s->sono_h)
1005  s->update_sono(s->sono_frame, s->c_buf, s->sono_idx);
1006  if (!s->sono_count) {
1007  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1008  if (!out)
1009  return AVERROR(ENOMEM);
1010  if (s->bar_h)
1011  s->draw_bar(out, s->h_buf, s->rcp_h_buf, s->c_buf, s->bar_h);
1012  if (s->axis_h)
1013  s->draw_axis(out, s->axis_frame, s->c_buf, s->bar_h);
1014  if (s->sono_h)
1015  s->draw_sono(out, s->sono_frame, s->bar_h + s->axis_h, s->sono_idx);
1016  out->pts = s->frame_count;
1017  ret = ff_filter_frame(outlink, out);
1018  s->frame_count++;
1019  }
1020  s->sono_count = (s->sono_count + 1) % s->count;
1021  if (s->sono_h)
1022  s->sono_idx = (s->sono_idx + s->sono_h - 1) % s->sono_h;
1023  return ret;
1024 }
1025 
1026 /* main filter control */
1028 {
1029  ShowCQTContext *s = ctx->priv;
1030  s->ctx = ctx;
1031 
1032  if (!s->fullhd) {
1033  av_log(ctx, AV_LOG_WARNING, "fullhd option is deprecated, use size/s option instead.\n");
1034  if (s->width != 1920 || s->height != 1080) {
1035  av_log(ctx, AV_LOG_ERROR, "fullhd set to 0 but with custom dimension.\n");
1036  return AVERROR(EINVAL);
1037  }
1038  s->width /= 2;
1039  s->height /= 2;
1040  s->fullhd = 1;
1041  }
1042 
1043  if (s->axis_h < 0) {
1044  s->axis_h = s->width / 60;
1045  if (s->axis_h & 1)
1046  s->axis_h++;
1047  if (s->bar_h >= 0 && s->sono_h >= 0)
1048  s->axis_h = s->height - s->bar_h - s->sono_h;
1049  if (s->bar_h >= 0 && s->sono_h < 0)
1050  s->axis_h = FFMIN(s->axis_h, s->height - s->bar_h);
1051  if (s->bar_h < 0 && s->sono_h >= 0)
1052  s->axis_h = FFMIN(s->axis_h, s->height - s->sono_h);
1053  }
1054 
1055  if (s->bar_h < 0) {
1056  s->bar_h = (s->height - s->axis_h) / 2;
1057  if (s->bar_h & 1)
1058  s->bar_h--;
1059  if (s->sono_h >= 0)
1060  s->bar_h = s->height - s->sono_h - s->axis_h;
1061  }
1062 
1063  if (s->sono_h < 0)
1064  s->sono_h = s->height - s->axis_h - s->bar_h;
1065 
1066  if ((s->width & 1) || (s->height & 1) || (s->bar_h & 1) || (s->axis_h & 1) || (s->sono_h & 1) ||
1067  (s->bar_h < 0) || (s->axis_h < 0) || (s->sono_h < 0) || (s->bar_h > s->height) ||
1068  (s->axis_h > s->height) || (s->sono_h > s->height) || (s->bar_h + s->axis_h + s->sono_h != s->height)) {
1069  av_log(ctx, AV_LOG_ERROR, "invalid dimension.\n");
1070  return AVERROR(EINVAL);
1071  }
1072 
1073  if (!s->fcount) {
1074  do {
1075  s->fcount++;
1076  } while(s->fcount * s->width < 1920 && s->fcount < 10);
1077  }
1078 
1079  return 0;
1080 }
1081 
1083 {
1084  common_uninit(ctx->priv);
1085 }
1086 
1088 {
1091  AVFilterLink *inlink = ctx->inputs[0];
1092  AVFilterLink *outlink = ctx->outputs[0];
1094  enum AVPixelFormat pix_fmts[] = {
1097  };
1098  int64_t channel_layouts[] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO_DOWNMIX, -1 };
1099  int ret;
1100 
1101  /* set input audio formats */
1102  formats = ff_make_format_list(sample_fmts);
1103  if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0)
1104  return ret;
1105 
1106  layouts = avfilter_make_format64_list(channel_layouts);
1107  if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0)
1108  return ret;
1109 
1110  formats = ff_all_samplerates();
1111  if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0)
1112  return ret;
1113 
1114  /* set output video format */
1115  formats = ff_make_format_list(pix_fmts);
1116  if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0)
1117  return ret;
1118 
1119  return 0;
1120 }
1121 
1122 static int config_output(AVFilterLink *outlink)
1123 {
1124  AVFilterContext *ctx = outlink->src;
1125  AVFilterLink *inlink = ctx->inputs[0];
1126  ShowCQTContext *s = ctx->priv;
1127  int ret;
1128 
1129  common_uninit(s);
1130 
1131  outlink->w = s->width;
1132  outlink->h = s->height;
1133  s->format = outlink->format;
1134  outlink->sample_aspect_ratio = av_make_q(1, 1);
1135  outlink->frame_rate = s->rate;
1136  outlink->time_base = av_inv_q(s->rate);
1137  av_log(ctx, AV_LOG_INFO, "video: %dx%d %s %d/%d fps, bar_h = %d, axis_h = %d, sono_h = %d.\n",
1138  s->width, s->height, av_get_pix_fmt_name(s->format), s->rate.num, s->rate.den,
1139  s->bar_h, s->axis_h, s->sono_h);
1140 
1141  s->cqt_len = s->width * s->fcount;
1142  if (!(s->freq = create_freq_table(s->basefreq, s->endfreq, s->cqt_len)))
1143  return AVERROR(ENOMEM);
1144 
1145  if ((ret = init_volume(s)) < 0)
1146  return ret;
1147 
1148  s->fft_bits = ceil(log2(inlink->sample_rate * s->timeclamp));
1149  s->fft_len = 1 << s->fft_bits;
1150  av_log(ctx, AV_LOG_INFO, "fft_len = %d, cqt_len = %d.\n", s->fft_len, s->cqt_len);
1151 
1152  s->fft_ctx = av_fft_init(s->fft_bits, 0);
1153  s->fft_data = av_calloc(s->fft_len, sizeof(*s->fft_data));
1154  s->fft_result = av_calloc(s->fft_len + 64, sizeof(*s->fft_result));
1155  s->cqt_result = av_malloc_array(s->cqt_len, sizeof(*s->cqt_result));
1156  if (!s->fft_ctx || !s->fft_data || !s->fft_result || !s->cqt_result)
1157  return AVERROR(ENOMEM);
1158 
1159  s->cqt_align = 1;
1161  s->cqt_calc = cqt_calc;
1162  s->draw_sono = draw_sono;
1163  if (s->format == AV_PIX_FMT_RGB24) {
1164  s->draw_bar = draw_bar_rgb;
1165  s->draw_axis = draw_axis_rgb;
1167  } else {
1168  s->draw_bar = draw_bar_yuv;
1169  s->draw_axis = draw_axis_yuv;
1171  }
1172 
1173  if ((ret = init_cqt(s)) < 0)
1174  return ret;
1175 
1176  if (s->axis_h) {
1177  if (!s->axis) {
1178  if ((ret = init_axis_empty(s)) < 0)
1179  return ret;
1180  } else if (s->axisfile) {
1181  if (init_axis_from_file(s) < 0) {
1182  av_log(ctx, AV_LOG_WARNING, "loading axis image failed, fallback to font rendering.\n");
1183  if (init_axis_from_font(s) < 0) {
1184  av_log(ctx, AV_LOG_WARNING, "loading axis font failed, disable text drawing.\n");
1185  if ((ret = init_axis_empty(s)) < 0)
1186  return ret;
1187  }
1188  }
1189  } else {
1190  if (init_axis_from_font(s) < 0) {
1191  av_log(ctx, AV_LOG_WARNING, "loading axis font failed, disable text drawing.\n");
1192  if ((ret = init_axis_empty(s)) < 0)
1193  return ret;
1194  }
1195  }
1196  }
1197 
1198  if (s->sono_h) {
1200  AV_PIX_FMT_YUV422P : outlink->format, s->width, s->sono_h);
1201  if (!s->sono_frame)
1202  return AVERROR(ENOMEM);
1203  }
1204 
1205  s->h_buf = av_malloc_array(s->cqt_len, sizeof (*s->h_buf));
1206  s->rcp_h_buf = av_malloc_array(s->width, sizeof(*s->rcp_h_buf));
1207  s->c_buf = av_malloc_array(s->width, sizeof(*s->c_buf));
1208  if (!s->h_buf || !s->rcp_h_buf || !s->c_buf)
1209  return AVERROR(ENOMEM);
1210 
1211  s->sono_count = 0;
1212  s->frame_count = 0;
1213  s->sono_idx = 0;
1214  s->remaining_fill = s->fft_len / 2;
1215  s->remaining_frac = 0;
1216  s->step_frac = av_div_q(av_make_q(inlink->sample_rate, s->count) , s->rate);
1217  s->step = (int)(s->step_frac.num / s->step_frac.den);
1218  s->step_frac.num %= s->step_frac.den;
1219  if (s->step_frac.num) {
1220  av_log(ctx, AV_LOG_INFO, "audio: %d Hz, step = %d + %d/%d.\n",
1221  inlink->sample_rate, s->step, s->step_frac.num, s->step_frac.den);
1222  av_log(ctx, AV_LOG_WARNING, "fractional step.\n");
1223  } else {
1224  av_log(ctx, AV_LOG_INFO, "audio: %d Hz, step = %d.\n",
1225  inlink->sample_rate, s->step);
1226  }
1227 
1228  return 0;
1229 }
1230 
1231 
1232 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1233 {
1234  AVFilterContext *ctx = inlink->dst;
1235  ShowCQTContext *s = ctx->priv;
1236  int remaining, step, ret, x, i, j, m;
1237  float *audio_data;
1238 
1239  if (!insamples) {
1240  while (s->remaining_fill < s->fft_len / 2) {
1241  memset(&s->fft_data[s->fft_len - s->remaining_fill], 0, sizeof(*s->fft_data) * s->remaining_fill);
1242  ret = plot_cqt(ctx);
1243  if (ret < 0)
1244  return ret;
1245 
1246  step = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den;
1248  for (x = 0; x < (s->fft_len-step); x++)
1249  s->fft_data[x] = s->fft_data[x+step];
1250  s->remaining_fill += step;
1251  }
1252  return AVERROR_EOF;
1253  }
1254 
1255  remaining = insamples->nb_samples;
1256  audio_data = (float*) insamples->data[0];
1257 
1258  while (remaining) {
1259  i = insamples->nb_samples - remaining;
1260  j = s->fft_len - s->remaining_fill;
1261  if (remaining >= s->remaining_fill) {
1262  for (m = 0; m < s->remaining_fill; m++) {
1263  s->fft_data[j+m].re = audio_data[2*(i+m)];
1264  s->fft_data[j+m].im = audio_data[2*(i+m)+1];
1265  }
1266  ret = plot_cqt(ctx);
1267  if (ret < 0) {
1268  av_frame_free(&insamples);
1269  return ret;
1270  }
1271  remaining -= s->remaining_fill;
1272  step = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den;
1274  for (m = 0; m < s->fft_len-step; m++)
1275  s->fft_data[m] = s->fft_data[m+step];
1276  s->remaining_fill = step;
1277  } else {
1278  for (m = 0; m < remaining; m++) {
1279  s->fft_data[j+m].re = audio_data[2*(i+m)];
1280  s->fft_data[j+m].im = audio_data[2*(i+m)+1];
1281  }
1282  s->remaining_fill -= remaining;
1283  remaining = 0;
1284  }
1285  }
1286  av_frame_free(&insamples);
1287  return 0;
1288 }
1289 
1290 static int request_frame(AVFilterLink *outlink)
1291 {
1292  AVFilterLink *inlink = outlink->src->inputs[0];
1293  int ret;
1294 
1295  ret = ff_request_frame(inlink);
1296  if (ret == AVERROR_EOF)
1297  filter_frame(inlink, NULL);
1298  return ret;
1299 }
1300 
1301 static const AVFilterPad showcqt_inputs[] = {
1302  {
1303  .name = "default",
1304  .type = AVMEDIA_TYPE_AUDIO,
1305  .filter_frame = filter_frame,
1306  },
1307  { NULL }
1308 };
1309 
1310 static const AVFilterPad showcqt_outputs[] = {
1311  {
1312  .name = "default",
1313  .type = AVMEDIA_TYPE_VIDEO,
1314  .config_props = config_output,
1315  .request_frame = request_frame,
1316  },
1317  { NULL }
1318 };
1319 
1321  .name = "showcqt",
1322  .description = NULL_IF_CONFIG_SMALL("Convert input audio to a CQT (Constant/Clamped Q Transform) spectrum video output."),
1323  .init = init,
1324  .uninit = uninit,
1325  .query_formats = query_formats,
1326  .priv_size = sizeof(ShowCQTContext),
1327  .inputs = showcqt_inputs,
1328  .outputs = showcqt_outputs,
1329  .priv_class = &showcqt_class,
1330 };
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:634
#define FLAGS
Definition: avf_showcqt.c:53
const char * s
Definition: avisynth_c.h:631
This structure describes decoded (raw) audio or video data.
Definition: frame.h:181
void(* update_sono)(AVFrame *sono, const ColorFloat *c, int idx)
Definition: avf_showcqt.h:87
AVOption.
Definition: opt.h:245
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
int start
Definition: avf_showcqt.h:30
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
static const AVOption showcqt_options[]
Definition: avf_showcqt.c:55
AVFormatContext * ctx
Definition: movenc-test.c:48
const char * fmt
Definition: avisynth_c.h:632
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:68
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
Coeffs * coeffs
Definition: avf_showcqt.h:66
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:65
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:357
const char * g
Definition: vf_curves.c:108
static int init_cqt(ShowCQTContext *s)
Definition: avf_showcqt.c:289
static av_cold int init(AVFilterContext *ctx)
Definition: avf_showcqt.c:1027
YUVFloat yuv
Definition: avf_showcqt.h:48
Miscellaneous utilities which make use of the libswscale library.
int num
numerator
Definition: rational.h:44
AVFilter ff_avf_showcqt
Definition: avf_showcqt.c:1320
const char * b
Definition: vf_curves.c:109
#define BASEFREQ
Definition: avf_showcqt.c:43
FFTSample re
Definition: avfft.h:38
static av_cold void uninit(AVFilterContext *ctx)
Definition: avf_showcqt.c:1082
double timeclamp
Definition: avf_showcqt.h:99
const uint8_t avpriv_vga16_font[4096]
static void yuv_from_cqt(ColorFloat *c, const FFTComplex *v, float gamma, int len)
Definition: avf_showcqt.c:674
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
static enum AVSampleFormat formats[]
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:657
static int render_default_font(AVFrame *tmp)
Definition: avf_showcqt.c:590
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:76
#define AV_CH_LAYOUT_STEREO
static AVRational av_make_q(int num, int den)
Create a rational.
Definition: rational.h:53
#define log2(x)
Definition: libm.h:404
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
const char * name
Pad name.
Definition: internal.h:59
static int render_freetype(ShowCQTContext *s, AVFrame *tmp)
Definition: avf_showcqt.c:506
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:312
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:435
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1163
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:103
uint8_t
float * rcp_h_buf
Definition: avf_showcqt.h:77
#define av_cold
Definition: attributes.h:82
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:141
static int init_axis_empty(ShowCQTContext *s)
Definition: avf_showcqt.c:398
AVOptions.
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:262
Definition: eval.c:148
static double a_weighting(void *p, double f)
Definition: avf_showcqt.c:162
int ff_scale_image(uint8_t *dst_data[4], int dst_linesize[4], int dst_w, int dst_h, enum AVPixelFormat dst_pix_fmt, uint8_t *const src_data[4], int src_linesize[4], int src_w, int src_h, enum AVPixelFormat src_pix_fmt, void *log_ctx)
Scale image using libswscale.
Definition: lswsutils.c:22
float u
Definition: avf_showcqt.h:43
static void draw_axis_rgb(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
Definition: avf_showcqt.c:812
static enum AVPixelFormat convert_axis_pixel_format(enum AVPixelFormat format)
Definition: avf_showcqt.c:387
AVRational step_frac
Definition: avf_showcqt.h:60
#define AVERROR_EOF
End of file.
Definition: error.h:55
double * freq
Definition: avf_showcqt.h:64
static const char *const var_names[]
Definition: aeval.c:36
CheckasmFunc * funcs
Definition: checkasm.c:172
FFTComplex * cqt_result
Definition: avf_showcqt.h:69
#define av_log(a,...)
static double b_func(void *p, double x)
Definition: avf_showcqt.c:454
unsigned m
Definition: audioconvert.c:187
static void update_sono_rgb(AVFrame *sono, const ColorFloat *c, int idx)
Definition: avf_showcqt.c:915
A filter pad used for either input or output.
Definition: internal.h:53
int len
Definition: avf_showcqt.h:30
float * sono_v_buf
Definition: avf_showcqt.h:78
#define expf(x)
Definition: libm.h:283
#define TLENGTH_MIN
Definition: avf_showcqt.c:46
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:188
int width
width and height of the video frame
Definition: frame.h:230
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static const uint16_t mask[17]
Definition: lzw.c:38
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:154
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:176
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition: rational.c:88
const char * r
Definition: vf_curves.c:107
void * priv
private data for use by the filter
Definition: avfilter.h:319
static int init_axis_from_file(ShowCQTContext *s)
Definition: avf_showcqt.c:405
static double b_weighting(void *p, double f)
Definition: avf_showcqt.c:170
simple assert() macros that are a bit more flexible than ISO C assert().
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
static void cqt_calc(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs, int len, int fft_len)
Definition: avf_showcqt.c:226
static const AVFilterPad showcqt_outputs[]
Definition: avf_showcqt.c:1310
GLsizei count
Definition: opengl_enc.c:109
#define FFMAX(a, b)
Definition: common.h:94
float FFTSample
Definition: avfft.h:35
#define fail()
Definition: checkasm.h:80
void(* cqt_calc)(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs, int len, int fft_len)
Definition: avf_showcqt.h:81
int8_t exp
Definition: eval.c:63
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:95
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:67
static const AVFilterPad showcqt_inputs[]
Definition: avf_showcqt.c:1301
AVFrame * axis_frame
Definition: avf_showcqt.h:54
static void update_sono_yuv(AVFrame *sono, const ColorFloat *c, int idx)
Definition: avf_showcqt.c:927
AVRational rate
Definition: avf_showcqt.h:90
float g
Definition: avf_showcqt.h:39
#define AV_CH_LAYOUT_STEREO_DOWNMIX
float b
Definition: avf_showcqt.h:39
#define FFMIN(a, b)
Definition: common.h:96
char * fontcolor
Definition: avf_showcqt.h:107
static int init_axis_color(ShowCQTContext *s, AVFrame *tmp)
Definition: avf_showcqt.c:460
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
#define FONTCOLOR
Definition: avf_showcqt.c:48
int ff_load_image(uint8_t *data[4], int linesize[4], int *w, int *h, enum AVPixelFormat *pix_fmt, const char *filename, void *log_ctx)
Load image from filename and put the resulting image in data.
Definition: lavfutils.c:24
static int init_axis_from_font(ShowCQTContext *s)
Definition: avf_showcqt.c:617
int n
Definition: avisynth_c.h:547
static void rgb_from_cqt(ColorFloat *c, const FFTComplex *v, float g, int len)
Definition: avf_showcqt.c:664
FFTComplex * fft_data
Definition: avf_showcqt.h:67
static double r_func(void *p, double x)
Definition: avf_showcqt.c:442
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:385
#define src
Definition: vp9dsp.c:530
RGBFloat rgb
Definition: avf_showcqt.h:47
static double g_func(void *p, double x)
Definition: avf_showcqt.c:448
A list of supported channel layouts.
Definition: formats.h:85
FILE * out
Definition: movenc-test.c:54
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:242
static const uint8_t vars[2][12]
Definition: camellia.c:179
static void draw_sono(AVFrame *out, AVFrame *sono, int off, int idx)
Definition: avf_showcqt.c:891
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:375
AVFilterChannelLayouts * avfilter_make_format64_list(const int64_t *fmts)
Definition: formats.c:303
float im
Definition: fft-test.c:73
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:59
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:317
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:209
FFTComplex * fft_result
Definition: avf_showcqt.h:68
static AVFrame * alloc_frame_empty(enum AVPixelFormat format, int w, int h)
Definition: avf_showcqt.c:361
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:189
FFT functions.
static const char * format
Definition: movenc-test.c:47
AVFILTER_DEFINE_CLASS(showcqt)
static av_always_inline float cbrtf(float x)
Definition: libm.h:61
static double * create_freq_table(double base, double end, int n)
Definition: avf_showcqt.c:121
Filter definition.
Definition: avfilter.h:141
#define OFFSET(x)
Definition: avf_showcqt.c:52
static int plot_cqt(AVFilterContext *ctx)
Definition: avf_showcqt.c:992
#define isnan(x)
Definition: libm.h:340
static double clip_with_log(void *log_ctx, const char *name, double val, double min, double max, double nan_replace, int idx)
Definition: avf_showcqt.c:141
float * h_buf
Definition: avf_showcqt.h:76
static double midi(void *p, double f)
Definition: avf_showcqt.c:437
FFTSample * val
Definition: avf_showcqt.h:29
offset must point to AVRational
Definition: opt.h:235
#define VOLUME_MAX
Definition: avf_showcqt.c:47
const char * name
Filter name.
Definition: avfilter.h:145
int64_t frame_count
Definition: avf_showcqt.h:63
static void draw_bar_yuv(AVFrame *out, const float *h, const float *rcp_h, const ColorFloat *c, int bar_h)
Definition: avf_showcqt.c:714
static void common_uninit(ShowCQTContext *s)
Definition: avf_showcqt.c:91
float v
Definition: avf_showcqt.h:43
offset must point to two consecutive integers
Definition: opt.h:232
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
Definition: avf_showcqt.c:1232
float * bar_v_buf
Definition: avf_showcqt.h:79
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:316
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:262
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:395
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:271
static int config_output(AVFilterLink *outlink)
Definition: avf_showcqt.c:1122
void * av_calloc(size_t nmemb, size_t size)
Allocate a block of nmemb * size bytes with alignment suitable for all memory accesses (including vec...
Definition: mem.c:260
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:133
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:192
static int request_frame(AVFilterLink *outlink)
Definition: avf_showcqt.c:1290
uint8_t level
Definition: svq3.c:150
FFTContext * fft_ctx
Definition: avf_showcqt.h:65
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:63
FFTSample im
Definition: avfft.h:38
if(ret< 0)
Definition: vf_mcdeint.c:282
void(* draw_bar)(AVFrame *out, const float *h, const float *rcp_h, const ColorFloat *c, int bar_h)
Definition: avf_showcqt.h:83
static double c[64]
enum AVPixelFormat format
Definition: avf_showcqt.h:56
int den
denominator
Definition: rational.h:45
float y
Definition: avf_showcqt.h:43
AVFrame * sono_frame
Definition: avf_showcqt.h:55
float r
Definition: avf_showcqt.h:39
#define TLENGTH
Definition: avf_showcqt.c:45
float re
Definition: fft-test.c:73
static int query_formats(AVFilterContext *ctx)
Definition: avf_showcqt.c:1087
static const int16_t coeffs[]
int len
ColorFloat * c_buf
Definition: avf_showcqt.h:75
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:712
static int init_volume(ShowCQTContext *s)
Definition: avf_showcqt.c:184
A list of supported formats for one end of a filter link.
Definition: formats.h:64
static double c_weighting(void *p, double f)
Definition: avf_showcqt.c:177
An instance of a filter.
Definition: avfilter.h:304
#define ENDFREQ
Definition: avf_showcqt.c:44
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
static void draw_axis_yuv(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
Definition: avf_showcqt.c:831
int height
Definition: frame.h:230
#define av_freep(p)
static float calculate_gamma(float v, float g)
Definition: avf_showcqt.c:651
void INT64 start
Definition: avisynth_c.h:553
static void process_cqt(ShowCQTContext *s)
Definition: avf_showcqt.c:946
void(* draw_sono)(AVFrame *out, AVFrame *sono, int off, int idx)
Definition: avf_showcqt.h:86
#define M_PI
Definition: mathematics.h:46
#define av_malloc_array(a, b)
enum CoeffsType cqt_coeffs_type
Definition: avf_showcqt.h:74
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:356
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2078
internal API functions
AVFilterContext * ctx
Definition: avf_showcqt.h:53
float min
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
static void draw_bar_rgb(AVFrame *out, const float *h, const float *rcp_h, const ColorFloat *c, int bar_h)
Definition: avf_showcqt.c:688
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:235
for(j=16;j >0;--j)
CGA/EGA/VGA ROM font data.
void(* draw_axis)(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
Definition: avf_showcqt.h:85
Miscellaneous utilities which make use of the libavformat library.
simple arithmetic expression evaluator
const char * name
Definition: opengl_enc.c:103
static int width