FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_waveform.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2015 Paul B Mahol
3  * Copyright (c) 2013 Marton Balint
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/avassert.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/parseutils.h"
25 #include "libavutil/pixdesc.h"
26 #include "avfilter.h"
27 #include "formats.h"
28 #include "internal.h"
29 #include "video.h"
30 
31 enum FilterType {
39 };
40 
41 typedef struct WaveformContext {
42  const AVClass *class;
43  int mode;
44  int ncomp;
45  int pcomp;
46  const uint8_t *bg_color;
47  float fintensity;
48  int intensity;
49  int mirror;
50  int display;
51  int envelope;
52  int estart[4];
53  int eend[4];
54  int *emax[4][4];
55  int *emin[4][4];
56  int *peak;
57  int filter;
58  int bits;
59  int max;
60  int size;
62  int component, int intensity, int offset, int column);
65 
66 #define OFFSET(x) offsetof(WaveformContext, x)
67 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
68 
69 static const AVOption waveform_options[] = {
70  { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
71  { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
72  { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
73  { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
74  { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
75  { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
76  { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
77  { "r", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
78  { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display" },
79  { "d", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display" },
80  { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display" },
81  { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display" },
82  { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
83  { "c", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
84  { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
85  { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
86  { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" },
87  { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" },
88  { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" },
89  { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" },
90  { "filter", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
91  { "f", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
92  { "lowpass", NULL, 0, AV_OPT_TYPE_CONST, {.i64=LOWPASS}, 0, 0, FLAGS, "filter" },
93  { "flat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "filter" },
94  { "aflat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=AFLAT}, 0, 0, FLAGS, "filter" },
95  { "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA}, 0, 0, FLAGS, "filter" },
96  { "achroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACHROMA}, 0, 0, FLAGS, "filter" },
97  { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" },
98  { NULL }
99 };
100 
102 
103 static const enum AVPixelFormat lowpass_pix_fmts[] = {
118 };
119 
120 static const enum AVPixelFormat flat_pix_fmts[] = {
122 };
123 
124 static const enum AVPixelFormat color_pix_fmts[] = {
130 };
131 
133 {
134  WaveformContext *s = ctx->priv;
135  AVFilterFormats *fmts_list;
136  const enum AVPixelFormat *pix_fmts;
137 
138  switch (s->filter) {
139  case LOWPASS: pix_fmts = lowpass_pix_fmts; break;
140  case FLAT:
141  case AFLAT:
142  case CHROMA:
143  case ACHROMA: pix_fmts = flat_pix_fmts; break;
144  case COLOR: pix_fmts = color_pix_fmts; break;
145  }
146 
147  fmts_list = ff_make_format_list(pix_fmts);
148  if (!fmts_list)
149  return AVERROR(ENOMEM);
150  return ff_set_common_formats(ctx, fmts_list);
151 }
152 
153 static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component)
154 {
155  const int dst_linesize = out->linesize[component] / 2;
156  const int bg = s->bg_color[component] * (s->max / 256);
157  const int limit = s->max - 1;
158  const int is_chroma = (component == 1 || component == 2);
159  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
160  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
161  const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
162  const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
163  const int start = s->estart[plane];
164  const int end = s->eend[plane];
165  uint16_t *dst;
166  int x, y;
167 
168  if (s->mode) {
169  for (x = 0; x < dst_w; x++) {
170  for (y = start; y < end; y++) {
171  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
172  if (dst[0] != bg) {
173  dst[0] = limit;
174  break;
175  }
176  }
177  for (y = end - 1; y >= start; y--) {
178  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
179  if (dst[0] != bg) {
180  dst[0] = limit;
181  break;
182  }
183  }
184  }
185  } else {
186  for (y = 0; y < dst_h; y++) {
187  dst = (uint16_t *)out->data[component] + y * dst_linesize;
188  for (x = start; x < end; x++) {
189  if (dst[x] != bg) {
190  dst[x] = limit;
191  break;
192  }
193  }
194  for (x = end - 1; x >= start; x--) {
195  if (dst[x] != bg) {
196  dst[x] = limit;
197  break;
198  }
199  }
200  }
201  }
202 }
203 
204 static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component)
205 {
206  const int dst_linesize = out->linesize[component];
207  const uint8_t bg = s->bg_color[component];
208  const int is_chroma = (component == 1 || component == 2);
209  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
210  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
211  const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
212  const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
213  const int start = s->estart[plane];
214  const int end = s->eend[plane];
215  uint8_t *dst;
216  int x, y;
217 
218  if (s->mode) {
219  for (x = 0; x < dst_w; x++) {
220  for (y = start; y < end; y++) {
221  dst = out->data[component] + y * dst_linesize + x;
222  if (dst[0] != bg) {
223  dst[0] = 255;
224  break;
225  }
226  }
227  for (y = end - 1; y >= start; y--) {
228  dst = out->data[component] + y * dst_linesize + x;
229  if (dst[0] != bg) {
230  dst[0] = 255;
231  break;
232  }
233  }
234  }
235  } else {
236  for (y = 0; y < dst_h; y++) {
237  dst = out->data[component] + y * dst_linesize;
238  for (x = start; x < end; x++) {
239  if (dst[x] != bg) {
240  dst[x] = 255;
241  break;
242  }
243  }
244  for (x = end - 1; x >= start; x--) {
245  if (dst[x] != bg) {
246  dst[x] = 255;
247  break;
248  }
249  }
250  }
251  }
252 }
253 
254 static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component)
255 {
256  const int dst_linesize = out->linesize[component] / 2;
257  const int bg = s->bg_color[component] * (s->max / 256);
258  const int limit = s->max - 1;
259  const int is_chroma = (component == 1 || component == 2);
260  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
261  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
262  const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
263  const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
264  const int start = s->estart[plane];
265  const int end = s->eend[plane];
266  int *emax = s->emax[plane][component];
267  int *emin = s->emin[plane][component];
268  uint16_t *dst;
269  int x, y;
270 
271  if (s->mode) {
272  for (x = 0; x < dst_w; x++) {
273  for (y = start; y < end && y < emin[x]; y++) {
274  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
275  if (dst[0] != bg) {
276  emin[x] = y;
277  break;
278  }
279  }
280  for (y = end - 1; y >= start && y >= emax[x]; y--) {
281  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
282  if (dst[0] != bg) {
283  emax[x] = y;
284  break;
285  }
286  }
287  }
288 
289  if (s->envelope == 3)
290  envelope_instant16(s, out, plane, component);
291 
292  for (x = 0; x < dst_w; x++) {
293  dst = (uint16_t *)out->data[component] + emin[x] * dst_linesize + x;
294  dst[0] = limit;
295  dst = (uint16_t *)out->data[component] + emax[x] * dst_linesize + x;
296  dst[0] = limit;
297  }
298  } else {
299  for (y = 0; y < dst_h; y++) {
300  dst = (uint16_t *)out->data[component] + y * dst_linesize;
301  for (x = start; x < end && x < emin[y]; x++) {
302  if (dst[x] != bg) {
303  emin[y] = x;
304  break;
305  }
306  }
307  for (x = end - 1; x >= start && x >= emax[y]; x--) {
308  if (dst[x] != bg) {
309  emax[y] = x;
310  break;
311  }
312  }
313  }
314 
315  if (s->envelope == 3)
316  envelope_instant16(s, out, plane, component);
317 
318  for (y = 0; y < dst_h; y++) {
319  dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y];
320  dst[0] = limit;
321  dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y];
322  dst[0] = limit;
323  }
324  }
325 }
326 
327 static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component)
328 {
329  const int dst_linesize = out->linesize[component];
330  const int bg = s->bg_color[component];
331  const int is_chroma = (component == 1 || component == 2);
332  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
333  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
334  const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
335  const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
336  const int start = s->estart[plane];
337  const int end = s->eend[plane];
338  int *emax = s->emax[plane][component];
339  int *emin = s->emin[plane][component];
340  uint8_t *dst;
341  int x, y;
342 
343  if (s->mode) {
344  for (x = 0; x < dst_w; x++) {
345  for (y = start; y < end && y < emin[x]; y++) {
346  dst = out->data[component] + y * dst_linesize + x;
347  if (dst[0] != bg) {
348  emin[x] = y;
349  break;
350  }
351  }
352  for (y = end - 1; y >= start && y >= emax[x]; y--) {
353  dst = out->data[component] + y * dst_linesize + x;
354  if (dst[0] != bg) {
355  emax[x] = y;
356  break;
357  }
358  }
359  }
360 
361  if (s->envelope == 3)
362  envelope_instant(s, out, plane, component);
363 
364  for (x = 0; x < dst_w; x++) {
365  dst = out->data[component] + emin[x] * dst_linesize + x;
366  dst[0] = 255;
367  dst = out->data[component] + emax[x] * dst_linesize + x;
368  dst[0] = 255;
369  }
370  } else {
371  for (y = 0; y < dst_h; y++) {
372  dst = out->data[component] + y * dst_linesize;
373  for (x = start; x < end && x < emin[y]; x++) {
374  if (dst[x] != bg) {
375  emin[y] = x;
376  break;
377  }
378  }
379  for (x = end - 1; x >= start && x >= emax[y]; x--) {
380  if (dst[x] != bg) {
381  emax[y] = x;
382  break;
383  }
384  }
385  }
386 
387  if (s->envelope == 3)
388  envelope_instant(s, out, plane, component);
389 
390  for (y = 0; y < dst_h; y++) {
391  dst = out->data[component] + y * dst_linesize + emin[y];
392  dst[0] = 255;
393  dst = out->data[component] + y * dst_linesize + emax[y];
394  dst[0] = 255;
395  }
396  }
397 }
398 
399 static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component)
400 {
401  if (s->envelope == 0) {
402  return;
403  } else if (s->envelope == 1) {
404  envelope_instant16(s, out, plane, component);
405  } else {
406  envelope_peak16(s, out, plane, component);
407  }
408 }
409 
410 static void envelope(WaveformContext *s, AVFrame *out, int plane, int component)
411 {
412  if (s->envelope == 0) {
413  return;
414  } else if (s->envelope == 1) {
415  envelope_instant(s, out, plane, component);
416  } else {
417  envelope_peak(s, out, plane, component);
418  }
419 }
420 
421 static void update16(uint16_t *target, int max, int intensity, int limit)
422 {
423  if (*target <= max)
424  *target += intensity;
425  else
426  *target = limit;
427 }
428 
429 static void update(uint8_t *target, int max, int intensity)
430 {
431  if (*target <= max)
432  *target += intensity;
433  else
434  *target = 255;
435 }
436 
438  int component, int intensity, int offset, int column)
439 {
440  const int plane = s->desc->comp[component].plane;
441  const int mirror = s->mirror;
442  const int is_chroma = (component == 1 || component == 2);
443  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
444  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
445  const int src_linesize = in->linesize[plane] / 2;
446  const int dst_linesize = out->linesize[plane] / 2;
447  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
448  const int limit = s->max - 1;
449  const int max = limit - intensity;
450  const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
451  const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
452  const uint16_t *src_data = (const uint16_t *)in->data[plane];
453  uint16_t *dst_data = (uint16_t *)out->data[plane] + (column ? (offset >> shift_h) * dst_linesize : offset >> shift_w);
454  uint16_t * const dst_bottom_line = dst_data + dst_linesize * ((s->size >> shift_h) - 1);
455  uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
456  const uint16_t *p;
457  int y;
458 
459  if (!column && mirror)
460  dst_data += s->size >> shift_w;
461 
462  for (y = 0; y < src_h; y++) {
463  const uint16_t *src_data_end = src_data + src_w;
464  uint16_t *dst = dst_line;
465 
466  for (p = src_data; p < src_data_end; p++) {
467  uint16_t *target;
468  int v = FFMIN(*p, limit);
469 
470  if (column) {
471  target = dst++ + dst_signed_linesize * (v >> shift_h);
472  } else {
473  if (mirror)
474  target = dst_data - (v >> shift_w) - 1;
475  else
476  target = dst_data + (v >> shift_w);
477  }
478  update16(target, max, intensity, limit);
479  }
480  src_data += src_linesize;
481  dst_data += dst_linesize;
482  }
483 
484  envelope16(s, out, plane, plane);
485 }
486 
488  int component, int intensity, int offset, int column)
489 {
490  const int plane = s->desc->comp[component].plane;
491  const int mirror = s->mirror;
492  const int is_chroma = (component == 1 || component == 2);
493  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
494  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
495  const int src_linesize = in->linesize[plane];
496  const int dst_linesize = out->linesize[plane];
497  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
498  const int max = 255 - intensity;
499  const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
500  const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
501  const uint8_t *src_data = in->data[plane];
502  uint8_t *dst_data = out->data[plane] + (column ? (offset >> shift_h) * dst_linesize : offset >> shift_w);
503  uint8_t * const dst_bottom_line = dst_data + dst_linesize * ((s->size >> shift_h) - 1);
504  uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
505  const uint8_t *p;
506  int y;
507 
508  if (!column && mirror)
509  dst_data += s->size >> shift_w;
510 
511  for (y = 0; y < src_h; y++) {
512  const uint8_t *src_data_end = src_data + src_w;
513  uint8_t *dst = dst_line;
514 
515  for (p = src_data; p < src_data_end; p++) {
516  uint8_t *target;
517  if (column) {
518  target = dst++ + dst_signed_linesize * (*p >> shift_h);
519  } else {
520  if (mirror)
521  target = dst_data - (*p >> shift_w) - 1;
522  else
523  target = dst_data + (*p >> shift_w);
524  }
525  update(target, max, intensity);
526  }
527  src_data += src_linesize;
528  dst_data += dst_linesize;
529  }
530 
531  envelope(s, out, plane, plane);
532 }
533 
535  int component, int intensity, int offset, int column)
536 {
537  const int plane = s->desc->comp[component].plane;
538  const int mirror = s->mirror;
539  const int c0_linesize = in->linesize[ plane + 0 ];
540  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
541  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
542  const int d0_linesize = out->linesize[ plane + 0 ];
543  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
544  const int max = 255 - intensity;
545  const int src_h = in->height;
546  const int src_w = in->width;
547  int x, y;
548 
549  if (column) {
550  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
551  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
552 
553  for (x = 0; x < src_w; x++) {
554  const uint8_t *c0_data = in->data[plane + 0];
555  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
556  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
557  uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
558  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
559  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
560  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
561  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
562  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
563 
564  for (y = 0; y < src_h; y++) {
565  const int c0 = c0_data[x] + 256;
566  const int c1 = FFABS(c1_data[x] - 128) + FFABS(c2_data[x] - 128);
567  uint8_t *target;
568 
569  target = d0 + x + d0_signed_linesize * c0;
570  update(target, max, intensity);
571  target = d1 + x + d1_signed_linesize * (c0 - c1);
572  update(target, max, 1);
573  target = d1 + x + d1_signed_linesize * (c0 + c1);
574  update(target, max, 1);
575 
576  c0_data += c0_linesize;
577  c1_data += c1_linesize;
578  c2_data += c2_linesize;
579  d0_data += d0_linesize;
580  d1_data += d1_linesize;
581  }
582  }
583  } else {
584  const uint8_t *c0_data = in->data[plane];
585  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
586  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
587  uint8_t *d0_data = out->data[plane] + offset;
588  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
589 
590  if (mirror) {
591  d0_data += s->size - 1;
592  d1_data += s->size - 1;
593  }
594 
595  for (y = 0; y < src_h; y++) {
596  for (x = 0; x < src_w; x++) {
597  int c0 = c0_data[x] + 256;
598  const int c1 = FFABS(c1_data[x] - 128) + FFABS(c2_data[x] - 128);
599  uint8_t *target;
600 
601  if (mirror) {
602  target = d0_data - c0;
603  update(target, max, intensity);
604  target = d1_data - (c0 - c1);
605  update(target, max, 1);
606  target = d1_data - (c0 + c1);
607  update(target, max, 1);
608  } else {
609  target = d0_data + c0;
610  update(target, max, intensity);
611  target = d1_data + (c0 - c1);
612  update(target, max, 1);
613  target = d1_data + (c0 + c1);
614  update(target, max, 1);
615  }
616  }
617 
618  c0_data += c0_linesize;
619  c1_data += c1_linesize;
620  c2_data += c2_linesize;
621  d0_data += d0_linesize;
622  d1_data += d1_linesize;
623  }
624  }
625 
626  envelope(s, out, plane, plane);
627  envelope(s, out, plane, (plane + 1) % s->ncomp);
628 }
629 
631  int component, int intensity, int offset, int column)
632 {
633  const int plane = s->desc->comp[component].plane;
634  const int mirror = s->mirror;
635  const int c0_linesize = in->linesize[ plane + 0 ];
636  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
637  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
638  const int d0_linesize = out->linesize[ plane + 0 ];
639  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
640  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
641  const int max = 255 - intensity;
642  const int src_h = in->height;
643  const int src_w = in->width;
644  int x, y;
645 
646  if (column) {
647  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
648  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
649  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
650 
651  for (x = 0; x < src_w; x++) {
652  const uint8_t *c0_data = in->data[plane + 0];
653  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
654  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
655  uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
656  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
657  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
658  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
659  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
660  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
661  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
662  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
663  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
664 
665  for (y = 0; y < src_h; y++) {
666  const int c0 = c0_data[x] + 128;
667  const int c1 = c1_data[x] - 128;
668  const int c2 = c2_data[x] - 128;
669  uint8_t *target;
670 
671  target = d0 + x + d0_signed_linesize * c0;
672  update(target, max, intensity);
673 
674  target = d1 + x + d1_signed_linesize * (c0 + c1);
675  update(target, max, 1);
676 
677  target = d2 + x + d2_signed_linesize * (c0 + c2);
678  update(target, max, 1);
679 
680  c0_data += c0_linesize;
681  c1_data += c1_linesize;
682  c2_data += c2_linesize;
683  d0_data += d0_linesize;
684  d1_data += d1_linesize;
685  d2_data += d2_linesize;
686  }
687  }
688  } else {
689  const uint8_t *c0_data = in->data[plane];
690  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
691  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
692  uint8_t *d0_data = out->data[plane] + offset;
693  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
694  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
695 
696  if (mirror) {
697  d0_data += s->size - 1;
698  d1_data += s->size - 1;
699  d2_data += s->size - 1;
700  }
701 
702  for (y = 0; y < src_h; y++) {
703  for (x = 0; x < src_w; x++) {
704  const int c0 = c0_data[x] + 128;
705  const int c1 = c1_data[x] - 128;
706  const int c2 = c2_data[x] - 128;
707  uint8_t *target;
708 
709  if (mirror) {
710  target = d0_data - c0;
711  update(target, max, intensity);
712  target = d1_data - (c0 + c1);
713  update(target, max, 1);
714  target = d2_data - (c0 + c2);
715  update(target, max, 1);
716  } else {
717  target = d0_data + c0;
718  update(target, max, intensity);
719  target = d1_data + (c0 + c1);
720  update(target, max, 1);
721  target = d2_data + (c0 + c2);
722  update(target, max, 1);
723  }
724  }
725 
726  c0_data += c0_linesize;
727  c1_data += c1_linesize;
728  c2_data += c2_linesize;
729  d0_data += d0_linesize;
730  d1_data += d1_linesize;
731  d2_data += d2_linesize;
732  }
733  }
734 
735  envelope(s, out, plane, (plane + 0) % s->ncomp);
736  envelope(s, out, plane, (plane + 1) % s->ncomp);
737  envelope(s, out, plane, (plane + 2) % s->ncomp);
738 }
739 
741  int component, int intensity, int offset, int column)
742 {
743  const int plane = s->desc->comp[component].plane;
744  const int mirror = s->mirror;
745  const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
746  const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
747  const int dst_linesize = out->linesize[plane];
748  const int max = 255 - intensity;
749  const int src_h = in->height;
750  const int src_w = in->width;
751  int x, y;
752 
753  if (column) {
754  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
755 
756  for (x = 0; x < src_w; x++) {
757  const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
758  const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
759  uint8_t *dst_data = out->data[plane] + offset * dst_linesize;
760  uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
761  uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
762  uint8_t *dst = dst_line;
763 
764  for (y = 0; y < src_h; y++) {
765  const int sum = FFABS(c0_data[x] - 128) + FFABS(c1_data[x] - 128);
766  uint8_t *target;
767 
768  target = dst + x + dst_signed_linesize * (256 - sum);
769  update(target, max, intensity);
770  target = dst + x + dst_signed_linesize * (255 + sum);
771  update(target, max, intensity);
772 
773  c0_data += c0_linesize;
774  c1_data += c1_linesize;
775  dst_data += dst_linesize;
776  }
777  }
778  } else {
779  const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
780  const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
781  uint8_t *dst_data = out->data[plane] + offset;
782 
783  if (mirror)
784  dst_data += s->size - 1;
785  for (y = 0; y < src_h; y++) {
786  for (x = 0; x < src_w; x++) {
787  const int sum = FFABS(c0_data[x] - 128) + FFABS(c1_data[x] - 128);
788  uint8_t *target;
789 
790  if (mirror) {
791  target = dst_data - (256 - sum);
792  update(target, max, intensity);
793  target = dst_data - (255 + sum);
794  update(target, max, intensity);
795  } else {
796  target = dst_data + (256 - sum);
797  update(target, max, intensity);
798  target = dst_data + (255 + sum);
799  update(target, max, intensity);
800  }
801  }
802 
803  c0_data += c0_linesize;
804  c1_data += c1_linesize;
805  dst_data += dst_linesize;
806  }
807  }
808 
809  envelope(s, out, plane, (plane + 0) % s->ncomp);
810 }
811 
813  int component, int intensity, int offset, int column)
814 {
815  const int plane = s->desc->comp[component].plane;
816  const int mirror = s->mirror;
817  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
818  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
819  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
820  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
821  const int max = 255 - intensity;
822  const int src_h = in->height;
823  const int src_w = in->width;
824  int x, y;
825 
826  if (column) {
827  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
828  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
829 
830  for (x = 0; x < src_w; x++) {
831  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
832  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
833  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
834  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
835  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
836  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
837  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
838  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
839 
840  for (y = 0; y < src_h; y++) {
841  const int c1 = c1_data[x] - 128;
842  const int c2 = c2_data[x] - 128;
843  uint8_t *target;
844 
845  target = d1 + x + d1_signed_linesize * (128 + c1);
846  update(target, max, intensity);
847 
848  target = d2 + x + d2_signed_linesize * (128 + c2);
849  update(target, max, intensity);
850 
851  c1_data += c1_linesize;
852  c2_data += c2_linesize;
853  d1_data += d1_linesize;
854  d2_data += d2_linesize;
855  }
856  }
857  } else {
858  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
859  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
860  uint8_t *d0_data = out->data[plane] + offset;
861  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
862  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
863 
864  if (mirror) {
865  d0_data += s->size - 1;
866  d1_data += s->size - 1;
867  d2_data += s->size - 1;
868  }
869 
870  for (y = 0; y < src_h; y++) {
871  for (x = 0; x < src_w; x++) {
872  const int c1 = c1_data[x] - 128;
873  const int c2 = c2_data[x] - 128;
874  uint8_t *target;
875 
876  if (mirror) {
877  target = d1_data - (128 + c1);
878  update(target, max, intensity);
879  target = d2_data - (128 + c2);
880  update(target, max, intensity);
881  } else {
882  target = d1_data + (128 + c1);
883  update(target, max, intensity);
884  target = d2_data + (128 + c2);
885  update(target, max, intensity);
886  }
887  }
888 
889  c1_data += c1_linesize;
890  c2_data += c2_linesize;
891  d1_data += d1_linesize;
892  d2_data += d2_linesize;
893  }
894  }
895 
896  envelope(s, out, plane, (plane + 1) % s->ncomp);
897  envelope(s, out, plane, (plane + 2) % s->ncomp);
898 }
899 
901  int component, int intensity, int offset, int column)
902 {
903  const int plane = s->desc->comp[component].plane;
904  const int mirror = s->mirror;
905  const int limit = s->max - 1;
906  const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0];
907  const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp];
908  const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp];
909  const int c0_linesize = in->linesize[ plane + 0 ] / 2;
910  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
911  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
912  const int d0_linesize = out->linesize[ plane + 0 ] / 2;
913  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
914  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
915  const int src_h = in->height;
916  const int src_w = in->width;
917  int x, y;
918 
919  if (s->mode) {
920  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
921  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
922  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
923  uint16_t *d0_data = (uint16_t *)out->data[plane] + offset * d0_linesize;
924  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
925  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
926  uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
927  uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
928  uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
929  uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
930  uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
931  uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
932 
933  for (y = 0; y < src_h; y++) {
934  for (x = 0; x < src_w; x++) {
935  const int c0 = FFMIN(c0_data[x], limit);
936  const int c1 = c1_data[x];
937  const int c2 = c2_data[x];
938 
939  *(d0 + d0_signed_linesize * c0 + x) = c0;
940  *(d1 + d1_signed_linesize * c0 + x) = c1;
941  *(d2 + d2_signed_linesize * c0 + x) = c2;
942  }
943 
944  c0_data += c0_linesize;
945  c1_data += c1_linesize;
946  c2_data += c2_linesize;
947  d0_data += d0_linesize;
948  d1_data += d1_linesize;
949  d2_data += d2_linesize;
950  }
951  } else {
952  uint16_t *d0_data = (uint16_t *)out->data[plane] + offset;
953  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset;
954  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset;
955 
956  if (mirror) {
957  d0_data += s->size - 1;
958  d1_data += s->size - 1;
959  d2_data += s->size - 1;
960  }
961 
962  for (y = 0; y < src_h; y++) {
963  for (x = 0; x < src_w; x++) {
964  const int c0 = FFMIN(c0_data[x], limit);
965  const int c1 = c1_data[x];
966  const int c2 = c2_data[x];
967 
968  if (mirror) {
969  *(d0_data - c0) = c0;
970  *(d1_data - c0) = c1;
971  *(d2_data - c0) = c2;
972  } else {
973  *(d0_data + c0) = c0;
974  *(d1_data + c0) = c1;
975  *(d2_data + c0) = c2;
976  }
977  }
978 
979  c0_data += c0_linesize;
980  c1_data += c1_linesize;
981  c2_data += c2_linesize;
982  d0_data += d0_linesize;
983  d1_data += d1_linesize;
984  d2_data += d2_linesize;
985  }
986  }
987 
988  envelope16(s, out, plane, plane);
989 }
990 
992  int component, int intensity, int offset, int column)
993 {
994  const int plane = s->desc->comp[component].plane;
995  const int mirror = s->mirror;
996  const uint8_t *c0_data = in->data[plane + 0];
997  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
998  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
999  const int c0_linesize = in->linesize[ plane + 0 ];
1000  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
1001  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
1002  const int d0_linesize = out->linesize[ plane + 0 ];
1003  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
1004  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
1005  const int src_h = in->height;
1006  const int src_w = in->width;
1007  int x, y;
1008 
1009  if (s->mode) {
1010  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
1011  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
1012  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
1013  uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
1014  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
1015  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
1016  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
1017  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
1018  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
1019  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
1020  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
1021  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
1022 
1023  for (y = 0; y < src_h; y++) {
1024  for (x = 0; x < src_w; x++) {
1025  const int c0 = c0_data[x];
1026  const int c1 = c1_data[x];
1027  const int c2 = c2_data[x];
1028 
1029  *(d0 + d0_signed_linesize * c0 + x) = c0;
1030  *(d1 + d1_signed_linesize * c0 + x) = c1;
1031  *(d2 + d2_signed_linesize * c0 + x) = c2;
1032  }
1033 
1034  c0_data += c0_linesize;
1035  c1_data += c1_linesize;
1036  c2_data += c2_linesize;
1037  d0_data += d0_linesize;
1038  d1_data += d1_linesize;
1039  d2_data += d2_linesize;
1040  }
1041  } else {
1042  uint8_t *d0_data = out->data[plane] + offset;
1043  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
1044  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
1045 
1046  if (mirror) {
1047  d0_data += s->size - 1;
1048  d1_data += s->size - 1;
1049  d2_data += s->size - 1;
1050  }
1051 
1052  for (y = 0; y < src_h; y++) {
1053  for (x = 0; x < src_w; x++) {
1054  const int c0 = c0_data[x];
1055  const int c1 = c1_data[x];
1056  const int c2 = c2_data[x];
1057 
1058  if (mirror) {
1059  *(d0_data - c0) = c0;
1060  *(d1_data - c0) = c1;
1061  *(d2_data - c0) = c2;
1062  } else {
1063  *(d0_data + c0) = c0;
1064  *(d1_data + c0) = c1;
1065  *(d2_data + c0) = c2;
1066  }
1067  }
1068 
1069  c0_data += c0_linesize;
1070  c1_data += c1_linesize;
1071  c2_data += c2_linesize;
1072  d0_data += d0_linesize;
1073  d1_data += d1_linesize;
1074  d2_data += d2_linesize;
1075  }
1076  }
1077 
1078  envelope(s, out, plane, plane);
1079 }
1080 
1081 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
1082 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
1083 
1084 static int config_input(AVFilterLink *inlink)
1085 {
1086  AVFilterContext *ctx = inlink->dst;
1087  WaveformContext *s = ctx->priv;
1088 
1089  s->desc = av_pix_fmt_desc_get(inlink->format);
1090  s->ncomp = s->desc->nb_components;
1091  s->bits = s->desc->comp[0].depth;
1092  s->max = 1 << s->bits;
1093  s->intensity = s->fintensity * (s->max - 1);
1094 
1095  switch (s->filter) {
1096  case LOWPASS:
1097  s->size = 256;
1098  s->waveform = s->bits > 8 ? lowpass16 : lowpass; break;
1099  case FLAT:
1100  s->size = 256 * 3;
1101  s->waveform = flat; break;
1102  case AFLAT:
1103  s->size = 256 * 2;
1104  s->waveform = aflat; break;
1105  case CHROMA:
1106  s->size = 256 * 2;
1107  s->waveform = chroma; break;
1108  case ACHROMA:
1109  s->size = 256;
1110  s->waveform = achroma; break;
1111  case COLOR:
1112  s->size = 256;
1113  s->waveform = s->bits > 8 ? color16 : color; break;
1114  }
1115 
1116  s->size = s->size << (s->bits - 8);
1117 
1118  switch (inlink->format) {
1119  case AV_PIX_FMT_GBRAP:
1120  case AV_PIX_FMT_GBRP:
1121  case AV_PIX_FMT_GBRP9:
1122  case AV_PIX_FMT_GBRP10:
1124  break;
1125  default:
1127  }
1128 
1129  return 0;
1130 }
1131 
1132 static int config_output(AVFilterLink *outlink)
1133 {
1134  AVFilterContext *ctx = outlink->src;
1135  AVFilterLink *inlink = ctx->inputs[0];
1136  WaveformContext *s = ctx->priv;
1137  int comp = 0, i, j = 0, k, p, size, shift;
1138 
1139  for (i = 0; i < s->ncomp; i++) {
1140  if ((1 << i) & s->pcomp)
1141  comp++;
1142  }
1143 
1144  av_freep(&s->peak);
1145 
1146  if (s->mode) {
1147  outlink->h = s->size * FFMAX(comp * s->display, 1);
1148  size = inlink->w;
1149  } else {
1150  outlink->w = s->size * FFMAX(comp * s->display, 1);
1151  size = inlink->h;
1152  }
1153 
1154  s->peak = av_malloc_array(size, 32 * sizeof(*s->peak));
1155  if (!s->peak)
1156  return AVERROR(ENOMEM);
1157 
1158  for (p = 0; p < 4; p++) {
1159  const int is_chroma = (p == 1 || p == 2);
1160  const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
1161  const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
1162  const int plane = s->desc->comp[p].plane;
1163  int offset;
1164 
1165  if (!((1 << p) & s->pcomp))
1166  continue;
1167 
1168  shift = s->mode ? shift_h : shift_w;
1169 
1170  for (k = 0; k < 4; k++) {
1171  s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0);
1172  s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16);
1173  }
1174 
1175  offset = j++ * s->size * s->display;
1176  s->estart[plane] = offset >> shift;
1177  s->eend[plane] = (offset + s->size - 1) >> shift;
1178  for (i = 0; i < size; i++) {
1179  for (k = 0; k < 4; k++) {
1180  s->emax[plane][k][i] = s->estart[plane];
1181  s->emin[plane][k][i] = s->eend[plane];
1182  }
1183  }
1184  }
1185 
1186  outlink->sample_aspect_ratio = (AVRational){1,1};
1187 
1188  return 0;
1189 }
1190 
1191 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
1192 {
1193  AVFilterContext *ctx = inlink->dst;
1194  WaveformContext *s = ctx->priv;
1195  AVFilterLink *outlink = ctx->outputs[0];
1196  AVFrame *out;
1197  int i, j, k;
1198 
1199  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1200  if (!out) {
1201  av_frame_free(&in);
1202  return AVERROR(ENOMEM);
1203  }
1204  out->pts = in->pts;
1205 
1206  for (k = 0; k < s->ncomp; k++) {
1207  const int is_chroma = (k == 1 || k == 2);
1208  const int dst_h = AV_CEIL_RSHIFT(outlink->h, (is_chroma ? s->desc->log2_chroma_h : 0));
1209  const int dst_w = AV_CEIL_RSHIFT(outlink->w, (is_chroma ? s->desc->log2_chroma_w : 0));
1210  if (s->bits <= 8) {
1211  for (i = 0; i < dst_h ; i++)
1212  memset(out->data[s->desc->comp[k].plane] +
1213  i * out->linesize[s->desc->comp[k].plane],
1214  s->bg_color[k], dst_w);
1215  } else {
1216  const int mult = s->size / 256;
1217  uint16_t *dst = (uint16_t *)out->data[s->desc->comp[k].plane];
1218 
1219  for (i = 0; i < dst_h ; i++) {
1220  for (j = 0; j < dst_w; j++)
1221  dst[j] = s->bg_color[k] * mult;
1222  dst += out->linesize[s->desc->comp[k].plane] / 2;
1223  }
1224  }
1225  }
1226 
1227  for (k = 0, i = 0; k < s->ncomp; k++) {
1228  if ((1 << k) & s->pcomp) {
1229  const int offset = i++ * s->size * s->display;
1230  s->waveform(s, in, out, k, s->intensity, offset, s->mode);
1231  }
1232  }
1233 
1234  av_frame_free(&in);
1235  return ff_filter_frame(outlink, out);
1236 }
1237 
1239 {
1240  WaveformContext *s = ctx->priv;
1241 
1242  av_freep(&s->peak);
1243 }
1244 
1245 static const AVFilterPad inputs[] = {
1246  {
1247  .name = "default",
1248  .type = AVMEDIA_TYPE_VIDEO,
1249  .filter_frame = filter_frame,
1250  .config_props = config_input,
1251  },
1252  { NULL }
1253 };
1254 
1255 static const AVFilterPad outputs[] = {
1256  {
1257  .name = "default",
1258  .type = AVMEDIA_TYPE_VIDEO,
1259  .config_props = config_output,
1260  },
1261  { NULL }
1262 };
1263 
1265  .name = "waveform",
1266  .description = NULL_IF_CONFIG_SMALL("Video waveform monitor."),
1267  .priv_size = sizeof(WaveformContext),
1268  .priv_class = &waveform_class,
1270  .uninit = uninit,
1271  .inputs = inputs,
1272  .outputs = outputs,
1273 };
int plane
Definition: avisynth_c.h:291
int plane
Which of the 4 planes contains the component.
Definition: pixdesc.h:35
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
static int shift(int a, int b)
Definition: sonic.c:82
static void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:437
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:359
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2157
This structure describes decoded (raw) audio or video data.
Definition: frame.h:181
AVOption.
Definition: opt.h:245
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:361
AVFormatContext * ctx
Definition: movenc-test.c:48
static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:327
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:362
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:68
Main libavfilter public API header.
static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:153
static int config_input(AVFilterLink *inlink)
Definition: vf_waveform.c:1084
static enum AVPixelFormat color_pix_fmts[]
Definition: vf_waveform.c:124
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:181
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:346
static void update(uint8_t *target, int max, int intensity)
Definition: vf_waveform.c:429
static int config_output(AVFilterLink *outlink)
Definition: vf_waveform.c:1132
static const AVFilterPad inputs[]
Definition: vf_waveform.c:1245
static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:399
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
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
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
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:312
#define FLAGS
Definition: vf_waveform.c:67
FilterType
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1163
static enum AVPixelFormat lowpass_pix_fmts[]
Definition: vf_waveform.c:103
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:103
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:82
mode
Definition: f_perms.c:27
static void lowpass(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:487
AVOptions.
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
static int query_formats(AVFilterContext *ctx)
Definition: vf_waveform.c:132
static const uint8_t black_gbrp_color[4]
Definition: vf_waveform.c:1082
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:262
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, uint8_t clip)
Definition: cfhd.c:82
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:358
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:345
AVFilter ff_vf_waveform
Definition: vf_waveform.c:1264
static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:204
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range...
Definition: pixfmt.h:102
static void color(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:991
static void update16(uint16_t *target, int max, int intensity, int limit)
Definition: vf_waveform.c:421
static const uint64_t c1
Definition: murmur3.c:49
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:76
ptrdiff_t size
Definition: opengl_enc.c:101
A filter pad used for either input or output.
Definition: internal.h:53
static void flat(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:534
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
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
AVFILTER_DEFINE_CLASS(waveform)
static void color16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:900
#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
void * priv
private data for use by the filter
Definition: avfilter.h:319
simple assert() macros that are a bit more flexible than ISO C assert().
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:333
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
#define FFMAX(a, b)
Definition: common.h:94
static void aflat(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:630
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:67
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:328
#define OFFSET(x)
Definition: vf_waveform.c:66
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
#define FFMIN(a, b)
Definition: common.h:96
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:75
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static enum AVPixelFormat flat_pix_fmts[]
Definition: vf_waveform.c:120
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:254
const uint8_t * bg_color
Definition: vf_waveform.c:46
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:363
static void achroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:812
static void envelope(WaveformContext *s, AVFrame *out, int plane, int component)
Definition: vf_waveform.c:410
int * emax[4][4]
Definition: vf_waveform.c:54
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:329
FILE * out
Definition: movenc-test.c:54
static const AVOption waveform_options[]
Definition: vf_waveform.c:69
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:209
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:189
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
static const AVFilterPad outputs[]
Definition: vf_waveform.c:1255
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_waveform.c:1238
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:55
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:330
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:69
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:141
rational number numerator/denominator
Definition: rational.h:43
static void chroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:740
const char * name
Filter name.
Definition: avfilter.h:145
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:327
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:316
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:262
int * emin[4][4]
Definition: vf_waveform.c:55
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:331
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:192
void(* waveform)(struct WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset, int column)
Definition: vf_waveform.c:61
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:63
Y , 8bpp.
Definition: pixfmt.h:71
if(ret< 0)
Definition: vf_mcdeint.c:282
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:229
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:360
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:77
static const uint64_t c2
Definition: murmur3.c:50
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:70
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_waveform.c:1191
static const uint8_t black_yuva_color[4]
Definition: vf_waveform.c:1081
A list of supported formats for one end of a filter link.
Definition: formats.h:64
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:266
An instance of a filter.
Definition: avfilter.h:304
int height
Definition: frame.h:230
#define av_freep(p)
static void comp(unsigned char *dst, int dst_stride, unsigned char *src, int src_stride, int add)
Definition: eamad.c:83
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:101
void INT64 start
Definition: avisynth_c.h:553
#define av_malloc_array(a, b)
internal API functions
int depth
Number of bits in the component.
Definition: pixdesc.h:58
const AVPixFmtDescriptor * desc
Definition: vf_waveform.c:63
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
for(j=16;j >0;--j)
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58