FFmpeg
vf_waveform.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2016 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"
27 #include "avfilter.h"
28 #include "formats.h"
29 #include "internal.h"
30 #include "video.h"
31 
32 typedef struct ThreadData {
33  AVFrame *in;
34  AVFrame *out;
35  int component;
36  int offset_y;
37  int offset_x;
38 } ThreadData;
39 
40 enum FilterType {
49 };
50 
56 };
57 
58 enum ScaleType {
61  IRE,
63 };
64 
65 typedef struct GraticuleLine {
66  const char *name;
67  uint16_t pos;
69 
70 typedef struct GraticuleLines {
71  struct GraticuleLine line[4];
73 
74 typedef struct WaveformContext {
75  const AVClass *class;
76  int mode;
77  int acomp;
78  int dcomp;
79  int ncomp;
80  int pcomp;
81  uint8_t bg_color[4];
82  float fintensity;
83  int intensity;
84  int mirror;
85  int display;
86  int envelope;
87  int graticule;
88  float opacity;
89  float bgopacity;
90  int estart[4];
91  int eend[4];
92  int *emax[4][4];
93  int *emin[4][4];
94  int *peak;
95  int filter;
96  int flags;
97  int bits;
98  int max;
99  int size;
100  int scale;
101  uint8_t grat_yuva_color[4];
102  int shift_w[4], shift_h[4];
105  int rgb;
106 
107  int (*waveform_slice)(AVFilterContext *ctx, void *arg,
108  int jobnr, int nb_jobs);
109  void (*graticulef)(struct WaveformContext *s, AVFrame *out);
113 
114 #define OFFSET(x) offsetof(WaveformContext, x)
115 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
116 
117 static const AVOption waveform_options[] = {
118  { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
119  { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
120  { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
121  { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
122  { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
123  { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
124  { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
125  { "r", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
126  { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
127  { "d", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
128  { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY}, 0, 0, FLAGS, "display" },
129  { "stack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=STACK}, 0, 0, FLAGS, "display" },
130  { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PARADE}, 0, 0, FLAGS, "display" },
131  { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
132  { "c", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
133  { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
134  { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
135  { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" },
136  { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" },
137  { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" },
138  { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" },
139  { "filter", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
140  { "f", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
141  { "lowpass", NULL, 0, AV_OPT_TYPE_CONST, {.i64=LOWPASS}, 0, 0, FLAGS, "filter" },
142  { "flat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "filter" },
143  { "aflat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=AFLAT}, 0, 0, FLAGS, "filter" },
144  { "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA}, 0, 0, FLAGS, "filter" },
145  { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" },
146  { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" },
147  { "xflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=XFLAT}, 0, 0, FLAGS, "filter" },
148  { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" },
149  { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" },
150  { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" },
151  { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" },
152  { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" },
153  { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
154  { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
155  { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
156  { "fl", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
157  { "numbers", "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
158  { "dots", "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
159  { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
160  { "s", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
161  { "digital", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DIGITAL}, 0, 0, FLAGS, "scale" },
162  { "millivolts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MILLIVOLTS}, 0, 0, FLAGS, "scale" },
163  { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" },
164  { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
165  { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
166  { NULL }
167 };
168 
169 AVFILTER_DEFINE_CLASS(waveform);
170 
171 static const enum AVPixelFormat in_lowpass_pix_fmts[] = {
187 };
188 
189 static const enum AVPixelFormat in_color_pix_fmts[] = {
204 };
205 
206 static const enum AVPixelFormat in_flat_pix_fmts[] = {
219 };
220 
224 };
225 
229 };
230 
234 };
235 
239 };
240 
244 };
245 
249 };
250 
254 };
255 
259 };
260 
264 };
265 
269 };
270 
274 };
275 
279 };
280 
281 static const enum AVPixelFormat flat_pix_fmts[] = {
286 };
287 
289 {
290  WaveformContext *s = ctx->priv;
291  const enum AVPixelFormat *out_pix_fmts;
292  const enum AVPixelFormat *in_pix_fmts;
293  const AVPixFmtDescriptor *desc;
294  AVFilterFormats *avff;
295  int depth, rgb, i, ret, ncomp;
296 
297  if (!ctx->inputs[0]->in_formats ||
298  !ctx->inputs[0]->in_formats->nb_formats) {
299  return AVERROR(EAGAIN);
300  }
301 
302  switch (s->filter) {
303  case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break;
304  case CHROMA:
305  case XFLAT:
306  case AFLAT:
307  case FLAT: in_pix_fmts = in_flat_pix_fmts; break;
308  case ACOLOR:
309  case COLOR: in_pix_fmts = in_color_pix_fmts; break;
310  default: return AVERROR_BUG;
311  }
312 
313  if (!ctx->inputs[0]->out_formats) {
314  if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0)
315  return ret;
316  }
317 
318  avff = ctx->inputs[0]->in_formats;
319  desc = av_pix_fmt_desc_get(avff->formats[0]);
320  ncomp = desc->nb_components;
321  rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
322  depth = desc->comp[0].depth;
323  for (i = 1; i < avff->nb_formats; i++) {
324  desc = av_pix_fmt_desc_get(avff->formats[i]);
325  if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) ||
326  depth != desc->comp[0].depth)
327  return AVERROR(EAGAIN);
328  }
329 
330  if (s->filter == LOWPASS && ncomp == 1 && depth == 8)
331  out_pix_fmts = out_gray8_lowpass_pix_fmts;
332  else if (s->filter == LOWPASS && ncomp == 1 && depth == 9)
333  out_pix_fmts = out_gray9_lowpass_pix_fmts;
334  else if (s->filter == LOWPASS && ncomp == 1 && depth == 10)
335  out_pix_fmts = out_gray10_lowpass_pix_fmts;
336  else if (s->filter == LOWPASS && ncomp == 1 && depth == 12)
337  out_pix_fmts = out_gray12_lowpass_pix_fmts;
338  else if (rgb && depth == 8 && ncomp > 2)
339  out_pix_fmts = out_rgb8_lowpass_pix_fmts;
340  else if (rgb && depth == 9 && ncomp > 2)
341  out_pix_fmts = out_rgb9_lowpass_pix_fmts;
342  else if (rgb && depth == 10 && ncomp > 2)
343  out_pix_fmts = out_rgb10_lowpass_pix_fmts;
344  else if (rgb && depth == 12 && ncomp > 2)
345  out_pix_fmts = out_rgb12_lowpass_pix_fmts;
346  else if (depth == 8 && ncomp > 2)
347  out_pix_fmts = out_yuv8_lowpass_pix_fmts;
348  else if (depth == 9 && ncomp > 2)
349  out_pix_fmts = out_yuv9_lowpass_pix_fmts;
350  else if (depth == 10 && ncomp > 2)
351  out_pix_fmts = out_yuv10_lowpass_pix_fmts;
352  else if (depth == 12 && ncomp > 2)
353  out_pix_fmts = out_yuv12_lowpass_pix_fmts;
354  else
355  return AVERROR(EAGAIN);
356  if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
357  return ret;
358 
359  return 0;
360 }
361 
363 {
364  const int dst_linesize = out->linesize[component] / 2;
365  const int bg = s->bg_color[component] * (s->max / 256);
366  const int limit = s->max - 1;
367  const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
368  const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
369  const int start = s->estart[plane];
370  const int end = s->eend[plane];
371  uint16_t *dst;
372  int x, y;
373 
374  if (s->mode) {
375  for (x = offset; x < offset + dst_w; x++) {
376  for (y = start; y < end; y++) {
377  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
378  if (dst[0] != bg) {
379  dst[0] = limit;
380  break;
381  }
382  }
383  for (y = end - 1; y >= start; y--) {
384  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
385  if (dst[0] != bg) {
386  dst[0] = limit;
387  break;
388  }
389  }
390  }
391  } else {
392  for (y = offset; y < offset + dst_h; y++) {
393  dst = (uint16_t *)out->data[component] + y * dst_linesize;
394  for (x = start; x < end; x++) {
395  if (dst[x] != bg) {
396  dst[x] = limit;
397  break;
398  }
399  }
400  for (x = end - 1; x >= start; x--) {
401  if (dst[x] != bg) {
402  dst[x] = limit;
403  break;
404  }
405  }
406  }
407  }
408 }
409 
411 {
412  const int dst_linesize = out->linesize[component];
413  const uint8_t bg = s->bg_color[component];
414  const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
415  const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
416  const int start = s->estart[plane];
417  const int end = s->eend[plane];
418  uint8_t *dst;
419  int x, y;
420 
421  if (s->mode) {
422  for (x = offset; x < offset + dst_w; x++) {
423  for (y = start; y < end; y++) {
424  dst = out->data[component] + y * dst_linesize + x;
425  if (dst[0] != bg) {
426  dst[0] = 255;
427  break;
428  }
429  }
430  for (y = end - 1; y >= start; y--) {
431  dst = out->data[component] + y * dst_linesize + x;
432  if (dst[0] != bg) {
433  dst[0] = 255;
434  break;
435  }
436  }
437  }
438  } else {
439  for (y = offset; y < offset + dst_h; y++) {
440  dst = out->data[component] + y * dst_linesize;
441  for (x = start; x < end; x++) {
442  if (dst[x] != bg) {
443  dst[x] = 255;
444  break;
445  }
446  }
447  for (x = end - 1; x >= start; x--) {
448  if (dst[x] != bg) {
449  dst[x] = 255;
450  break;
451  }
452  }
453  }
454  }
455 }
456 
458 {
459  const int dst_linesize = out->linesize[component] / 2;
460  const int bg = s->bg_color[component] * (s->max / 256);
461  const int limit = s->max - 1;
462  const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
463  const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
464  const int start = s->estart[plane];
465  const int end = s->eend[plane];
466  int *emax = s->emax[plane][component];
467  int *emin = s->emin[plane][component];
468  uint16_t *dst;
469  int x, y;
470 
471  if (s->mode) {
472  for (x = offset; x < offset + dst_w; x++) {
473  for (y = start; y < end && y < emin[x - offset]; y++) {
474  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
475  if (dst[0] != bg) {
476  emin[x - offset] = y;
477  break;
478  }
479  }
480  for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
481  dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
482  if (dst[0] != bg) {
483  emax[x - offset] = y;
484  break;
485  }
486  }
487  }
488 
489  if (s->envelope == 3)
490  envelope_instant16(s, out, plane, component, offset);
491 
492  for (x = offset; x < offset + dst_w; x++) {
493  dst = (uint16_t *)out->data[component] + emin[x - offset] * dst_linesize + x;
494  dst[0] = limit;
495  dst = (uint16_t *)out->data[component] + emax[x - offset] * dst_linesize + x;
496  dst[0] = limit;
497  }
498  } else {
499  for (y = offset; y < offset + dst_h; y++) {
500  dst = (uint16_t *)out->data[component] + y * dst_linesize;
501  for (x = start; x < end && x < emin[y - offset]; x++) {
502  if (dst[x] != bg) {
503  emin[y - offset] = x;
504  break;
505  }
506  }
507  for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
508  if (dst[x] != bg) {
509  emax[y - offset] = x;
510  break;
511  }
512  }
513  }
514 
515  if (s->envelope == 3)
516  envelope_instant16(s, out, plane, component, offset);
517 
518  for (y = offset; y < offset + dst_h; y++) {
519  dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y - offset];
520  dst[0] = limit;
521  dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y - offset];
522  dst[0] = limit;
523  }
524  }
525 }
526 
528 {
529  const int dst_linesize = out->linesize[component];
530  const int bg = s->bg_color[component];
531  const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
532  const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
533  const int start = s->estart[plane];
534  const int end = s->eend[plane];
535  int *emax = s->emax[plane][component];
536  int *emin = s->emin[plane][component];
537  uint8_t *dst;
538  int x, y;
539 
540  if (s->mode) {
541  for (x = offset; x < offset + dst_w; x++) {
542  for (y = start; y < end && y < emin[x - offset]; y++) {
543  dst = out->data[component] + y * dst_linesize + x;
544  if (dst[0] != bg) {
545  emin[x - offset] = y;
546  break;
547  }
548  }
549  for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
550  dst = out->data[component] + y * dst_linesize + x;
551  if (dst[0] != bg) {
552  emax[x - offset] = y;
553  break;
554  }
555  }
556  }
557 
558  if (s->envelope == 3)
559  envelope_instant(s, out, plane, component, offset);
560 
561  for (x = offset; x < offset + dst_w; x++) {
562  dst = out->data[component] + emin[x - offset] * dst_linesize + x;
563  dst[0] = 255;
564  dst = out->data[component] + emax[x - offset] * dst_linesize + x;
565  dst[0] = 255;
566  }
567  } else {
568  for (y = offset; y < offset + dst_h; y++) {
569  dst = out->data[component] + y * dst_linesize;
570  for (x = start; x < end && x < emin[y - offset]; x++) {
571  if (dst[x] != bg) {
572  emin[y - offset] = x;
573  break;
574  }
575  }
576  for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
577  if (dst[x] != bg) {
578  emax[y - offset] = x;
579  break;
580  }
581  }
582  }
583 
584  if (s->envelope == 3)
585  envelope_instant(s, out, plane, component, offset);
586 
587  for (y = offset; y < offset + dst_h; y++) {
588  dst = out->data[component] + y * dst_linesize + emin[y - offset];
589  dst[0] = 255;
590  dst = out->data[component] + y * dst_linesize + emax[y - offset];
591  dst[0] = 255;
592  }
593  }
594 }
595 
596 static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
597 {
598  if (s->envelope == 0) {
599  return;
600  } else if (s->envelope == 1) {
601  envelope_instant16(s, out, plane, component, offset);
602  } else {
603  envelope_peak16(s, out, plane, component, offset);
604  }
605 }
606 
607 static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
608 {
609  if (s->envelope == 0) {
610  return;
611  } else if (s->envelope == 1) {
612  envelope_instant(s, out, plane, component, offset);
613  } else {
614  envelope_peak(s, out, plane, component, offset);
615  }
616 }
617 
618 static void update16(uint16_t *target, int max, int intensity, int limit)
619 {
620  if (*target <= max)
621  *target += intensity;
622  else
623  *target = limit;
624 }
625 
626 static void update(uint8_t *target, int max, int intensity)
627 {
628  if (*target <= max)
629  *target += intensity;
630  else
631  *target = 255;
632 }
633 
634 static void update_cr(uint8_t *target, int unused, int intensity)
635 {
636  if (*target - intensity > 0)
637  *target -= intensity;
638  else
639  *target = 0;
640 }
641 
642 static void update16_cr(uint16_t *target, int unused, int intensity, int limit)
643 {
644  if (*target - intensity > 0)
645  *target -= intensity;
646  else
647  *target = 0;
648 }
649 
651  AVFrame *in, AVFrame *out,
652  int component, int intensity,
653  int offset_y, int offset_x,
654  int column, int mirror,
655  int jobnr, int nb_jobs)
656 {
657  const int plane = s->desc->comp[component].plane;
658  const int shift_w = s->shift_w[component];
659  const int shift_h = s->shift_h[component];
660  const int src_linesize = in->linesize[plane] / 2;
661  const int dst_linesize = out->linesize[plane] / 2;
662  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
663  const int limit = s->max - 1;
664  const int max = limit - intensity;
665  const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
666  const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
667  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
668  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
669  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
670  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
671  const int step = column ? 1 << shift_w : 1 << shift_h;
672  const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize;
673  uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
674  uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
675  uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
676  const uint16_t *p;
677  int y;
678 
679  if (!column && mirror)
680  dst_data += s->size;
681 
682  for (y = sliceh_start; y < sliceh_end; y++) {
683  const uint16_t *src_data_end = src_data + slicew_end;
684  uint16_t *dst = dst_line + slicew_start * step;
685 
686  for (p = src_data + slicew_start; p < src_data_end; p++) {
687  uint16_t *target;
688  int i = 0, v = FFMIN(*p, limit);
689 
690  if (column) {
691  do {
692  target = dst++ + dst_signed_linesize * v;
693  update16(target, max, intensity, limit);
694  } while (++i < step);
695  } else {
696  uint16_t *row = dst_data;
697  do {
698  if (mirror)
699  target = row - v - 1;
700  else
701  target = row + v;
702  update16(target, max, intensity, limit);
703  row += dst_linesize;
704  } while (++i < step);
705  }
706  }
707  src_data += src_linesize;
708  dst_data += dst_linesize * step;
709  }
710 }
711 
712 #define LOWPASS16_FUNC(name, column, mirror) \
713 static int lowpass16_##name(AVFilterContext *ctx, \
714  void *arg, int jobnr, \
715  int nb_jobs) \
716 { \
717  WaveformContext *s = ctx->priv; \
718  ThreadData *td = arg; \
719  AVFrame *in = td->in; \
720  AVFrame *out = td->out; \
721  int component = td->component; \
722  int offset_y = td->offset_y; \
723  int offset_x = td->offset_x; \
724  \
725  lowpass16(s, in, out, component, s->intensity, \
726  offset_y, offset_x, column, mirror, \
727  jobnr, nb_jobs); \
728  \
729  return 0; \
730 }
731 
732 LOWPASS16_FUNC(column_mirror, 1, 1)
733 LOWPASS16_FUNC(column, 1, 0)
734 LOWPASS16_FUNC(row_mirror, 0, 1)
735 LOWPASS16_FUNC(row, 0, 0)
736 
738  AVFrame *in, AVFrame *out,
739  int component, int intensity,
740  int offset_y, int offset_x,
741  int column, int mirror,
742  int jobnr, int nb_jobs)
743 {
744  const int plane = s->desc->comp[component].plane;
745  const int shift_w = s->shift_w[component];
746  const int shift_h = s->shift_h[component];
747  const int src_linesize = in->linesize[plane];
748  const int dst_linesize = out->linesize[plane];
749  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
750  const int max = 255 - intensity;
751  const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
752  const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
753  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
754  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
755  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
756  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
757  const int step = column ? 1 << shift_w : 1 << shift_h;
758  const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize;
759  uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
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  const uint8_t *p;
763  int y;
764 
765  if (!column && mirror)
766  dst_data += s->size;
767 
768  for (y = sliceh_start; y < sliceh_end; y++) {
769  const uint8_t *src_data_end = src_data + slicew_end;
770  uint8_t *dst = dst_line + slicew_start * step;
771 
772  for (p = src_data + slicew_start; p < src_data_end; p++) {
773  uint8_t *target;
774  if (column) {
775  target = dst + dst_signed_linesize * *p;
776  dst += step;
777  update(target, max, intensity);
778  } else {
779  uint8_t *row = dst_data;
780  if (mirror)
781  target = row - *p - 1;
782  else
783  target = row + *p;
784  update(target, max, intensity);
785  row += dst_linesize;
786  }
787  }
788  src_data += src_linesize;
789  dst_data += dst_linesize * step;
790  }
791 
792  if (column && step > 1) {
793  const int dst_h = 256;
794  uint8_t *dst;
795  int x, z;
796 
797  dst = out->data[plane] + offset_y * dst_linesize + offset_x;
798  for (y = 0; y < dst_h; y++) {
799  for (x = slicew_start * step; x < slicew_end * step; x+=step) {
800  for (z = 1; z < step; z++) {
801  dst[x + z] = dst[x];
802  }
803  }
804  dst += dst_linesize;
805  }
806  } else if (step > 1) {
807  const int dst_w = 256;
808  uint8_t *dst;
809  int z;
810 
811  dst = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
812  for (y = sliceh_start * step; y < sliceh_end * step; y+=step) {
813  for (z = 1; z < step; z++)
814  memcpy(dst + dst_linesize * z, dst, dst_w);
815  dst += dst_linesize * step;
816  }
817  }
818 }
819 
820 #define LOWPASS_FUNC(name, column, mirror) \
821 static int lowpass_##name(AVFilterContext *ctx, \
822  void *arg, int jobnr, \
823  int nb_jobs) \
824 { \
825  WaveformContext *s = ctx->priv; \
826  ThreadData *td = arg; \
827  AVFrame *in = td->in; \
828  AVFrame *out = td->out; \
829  int component = td->component; \
830  int offset_y = td->offset_y; \
831  int offset_x = td->offset_x; \
832  \
833  lowpass(s, in, out, component, s->intensity, \
834  offset_y, offset_x, column, mirror, \
835  jobnr, nb_jobs); \
836  \
837  return 0; \
838 }
839 
840 LOWPASS_FUNC(column_mirror, 1, 1)
841 LOWPASS_FUNC(column, 1, 0)
842 LOWPASS_FUNC(row_mirror, 0, 1)
843 LOWPASS_FUNC(row, 0, 0)
844 
846  AVFrame *in, AVFrame *out,
847  int component, int intensity,
848  int offset_y, int offset_x,
849  int column, int mirror,
850  int jobnr, int nb_jobs)
851 {
852  const int plane = s->desc->comp[component].plane;
853  const int c0_linesize = in->linesize[ plane + 0 ] / 2;
854  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
855  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
856  const int c0_shift_w = s->shift_w[ component + 0 ];
857  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
858  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
859  const int c0_shift_h = s->shift_h[ component + 0 ];
860  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
861  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
862  const int d0_linesize = out->linesize[ plane + 0 ] / 2;
863  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
864  const int limit = s->max - 1;
865  const int max = limit - intensity;
866  const int mid = s->max / 2;
867  const int src_h = in->height;
868  const int src_w = in->width;
869  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
870  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
871  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
872  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
873  int x, y;
874 
875  if (column) {
876  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
877  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
878 
879  for (x = slicew_start; x < slicew_end; x++) {
880  const uint16_t *c0_data = (uint16_t *)in->data[plane + 0];
881  const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
882  const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
883  uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x;
884  uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x;
885  uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
886  uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
887  uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
888  uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
889 
890  for (y = 0; y < src_h; y++) {
891  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
892  const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
893  uint16_t *target;
894 
895  target = d0 + x + d0_signed_linesize * c0;
896  update16(target, max, intensity, limit);
897  target = d1 + x + d1_signed_linesize * (c0 - c1);
898  update16(target, max, intensity, limit);
899  target = d1 + x + d1_signed_linesize * (c0 + c1);
900  update16(target, max, intensity, limit);
901 
902  if (!c0_shift_h || (y & c0_shift_h))
903  c0_data += c0_linesize;
904  if (!c1_shift_h || (y & c1_shift_h))
905  c1_data += c1_linesize;
906  if (!c2_shift_h || (y & c2_shift_h))
907  c2_data += c2_linesize;
908  d0_data += d0_linesize;
909  d1_data += d1_linesize;
910  }
911  }
912  } else {
913  const uint16_t *c0_data = (uint16_t *)(in->data[plane]) + (sliceh_start >> c0_shift_h) * c0_linesize;
914  const uint16_t *c1_data = (uint16_t *)(in->data[(plane + 1) % s->ncomp]) + (sliceh_start >> c1_shift_h) * c1_linesize;
915  const uint16_t *c2_data = (uint16_t *)(in->data[(plane + 2) % s->ncomp]) + (sliceh_start >> c2_shift_h) * c2_linesize;
916  uint16_t *d0_data = (uint16_t *)(out->data[plane]) + (offset_y + sliceh_start) * d0_linesize + offset_x;
917  uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + (offset_y + sliceh_start) * d1_linesize + offset_x;
918 
919  if (mirror) {
920  d0_data += s->size - 1;
921  d1_data += s->size - 1;
922  }
923 
924  for (y = sliceh_start; y < sliceh_end; y++) {
925  for (x = 0; x < src_w; x++) {
926  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
927  const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
928  uint16_t *target;
929 
930  if (mirror) {
931  target = d0_data - c0;
932  update16(target, max, intensity, limit);
933  target = d1_data - (c0 - c1);
934  update16(target, max, intensity, limit);
935  target = d1_data - (c0 + c1);
936  update16(target, max, intensity, limit);
937  } else {
938  target = d0_data + c0;
939  update16(target, max, intensity, limit);
940  target = d1_data + (c0 - c1);
941  update16(target, max, intensity, limit);
942  target = d1_data + (c0 + c1);
943  update16(target, max, intensity, limit);
944  }
945  }
946 
947  if (!c0_shift_h || (y & c0_shift_h))
948  c0_data += c0_linesize;
949  if (!c1_shift_h || (y & c1_shift_h))
950  c1_data += c1_linesize;
951  if (!c2_shift_h || (y & c2_shift_h))
952  c2_data += c2_linesize;
953  d0_data += d0_linesize;
954  d1_data += d1_linesize;
955  }
956  }
957 }
958 
959 #define FLAT16_FUNC(name, column, mirror) \
960 static int flat16_##name(AVFilterContext *ctx, \
961  void *arg, int jobnr, \
962  int nb_jobs) \
963 { \
964  WaveformContext *s = ctx->priv; \
965  ThreadData *td = arg; \
966  AVFrame *in = td->in; \
967  AVFrame *out = td->out; \
968  int component = td->component; \
969  int offset_y = td->offset_y; \
970  int offset_x = td->offset_x; \
971  \
972  flat16(s, in, out, component, s->intensity, \
973  offset_y, offset_x, column, mirror, \
974  jobnr, nb_jobs); \
975  \
976  return 0; \
977 }
978 
979 FLAT16_FUNC(column_mirror, 1, 1)
980 FLAT16_FUNC(column, 1, 0)
981 FLAT16_FUNC(row_mirror, 0, 1)
982 FLAT16_FUNC(row, 0, 0)
983 
985  AVFrame *in, AVFrame *out,
986  int component, int intensity,
987  int offset_y, int offset_x,
988  int column, int mirror,
989  int jobnr, int nb_jobs)
990 {
991  const int plane = s->desc->comp[component].plane;
992  const int c0_linesize = in->linesize[ plane + 0 ];
993  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
994  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
995  const int c0_shift_w = s->shift_w[ component + 0 ];
996  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
997  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
998  const int c0_shift_h = s->shift_h[ component + 0 ];
999  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
1000  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
1001  const int d0_linesize = out->linesize[ plane + 0 ];
1002  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
1003  const int max = 255 - intensity;
1004  const int src_h = in->height;
1005  const int src_w = in->width;
1006  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1007  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1008  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1009  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1010  int x, y;
1011 
1012  if (column) {
1013  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
1014  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
1015 
1016  for (x = slicew_start; x < slicew_end; x++) {
1017  const uint8_t *c0_data = in->data[plane + 0];
1018  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
1019  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
1020  uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
1021  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
1022  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
1023  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
1024  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
1025  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
1026 
1027  for (y = 0; y < src_h; y++) {
1028  const int c0 = c0_data[x >> c0_shift_w] + 256;
1029  const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
1030  uint8_t *target;
1031 
1032  target = d0 + x + d0_signed_linesize * c0;
1033  update(target, max, intensity);
1034  target = d1 + x + d1_signed_linesize * (c0 - c1);
1035  update(target, max, intensity);
1036  target = d1 + x + d1_signed_linesize * (c0 + c1);
1037  update(target, max, intensity);
1038 
1039  if (!c0_shift_h || (y & c0_shift_h))
1040  c0_data += c0_linesize;
1041  if (!c1_shift_h || (y & c1_shift_h))
1042  c1_data += c1_linesize;
1043  if (!c2_shift_h || (y & c2_shift_h))
1044  c2_data += c2_linesize;
1045  d0_data += d0_linesize;
1046  d1_data += d1_linesize;
1047  }
1048  }
1049  } else {
1050  const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize;
1051  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1052  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
1053  uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
1054  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
1055 
1056  if (mirror) {
1057  d0_data += s->size - 1;
1058  d1_data += s->size - 1;
1059  }
1060 
1061  for (y = sliceh_start; y < sliceh_end; y++) {
1062  for (x = 0; x < src_w; x++) {
1063  const int c0 = c0_data[x >> c0_shift_w] + 256;
1064  const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
1065  uint8_t *target;
1066 
1067  if (mirror) {
1068  target = d0_data - c0;
1069  update(target, max, intensity);
1070  target = d1_data - (c0 - c1);
1071  update(target, max, intensity);
1072  target = d1_data - (c0 + c1);
1073  update(target, max, intensity);
1074  } else {
1075  target = d0_data + c0;
1076  update(target, max, intensity);
1077  target = d1_data + (c0 - c1);
1078  update(target, max, intensity);
1079  target = d1_data + (c0 + c1);
1080  update(target, max, intensity);
1081  }
1082  }
1083 
1084  if (!c0_shift_h || (y & c0_shift_h))
1085  c0_data += c0_linesize;
1086  if (!c1_shift_h || (y & c1_shift_h))
1087  c1_data += c1_linesize;
1088  if (!c2_shift_h || (y & c2_shift_h))
1089  c2_data += c2_linesize;
1090  d0_data += d0_linesize;
1091  d1_data += d1_linesize;
1092  }
1093  }
1094 }
1095 
1096 #define FLAT_FUNC(name, column, mirror) \
1097 static int flat_##name(AVFilterContext *ctx, \
1098  void *arg, int jobnr, \
1099  int nb_jobs) \
1100 { \
1101  WaveformContext *s = ctx->priv; \
1102  ThreadData *td = arg; \
1103  AVFrame *in = td->in; \
1104  AVFrame *out = td->out; \
1105  int component = td->component; \
1106  int offset_y = td->offset_y; \
1107  int offset_x = td->offset_x; \
1108  \
1109  flat(s, in, out, component, s->intensity, \
1110  offset_y, offset_x, column, mirror, \
1111  jobnr, nb_jobs); \
1112  \
1113  return 0; \
1114 }
1115 
1116 FLAT_FUNC(column_mirror, 1, 1)
1117 FLAT_FUNC(column, 1, 0)
1118 FLAT_FUNC(row_mirror, 0, 1)
1119 FLAT_FUNC(row, 0, 0)
1120 
1121 #define AFLAT16(name, update_cr, column, mirror) \
1122 static int name(AVFilterContext *ctx, \
1123  void *arg, int jobnr, \
1124  int nb_jobs) \
1125 { \
1126  WaveformContext *s = ctx->priv; \
1127  ThreadData *td = arg; \
1128  AVFrame *in = td->in; \
1129  AVFrame *out = td->out; \
1130  int component = td->component; \
1131  int offset_y = td->offset_y; \
1132  int offset_x = td->offset_x; \
1133  const int intensity = s->intensity; \
1134  const int plane = s->desc->comp[component].plane; \
1135  const int c0_linesize = in->linesize[ plane + 0 ] / 2; \
1136  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; \
1137  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; \
1138  const int c0_shift_w = s->shift_w[ component + 0 ]; \
1139  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \
1140  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \
1141  const int c0_shift_h = s->shift_h[ component + 0 ]; \
1142  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \
1143  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \
1144  const int d0_linesize = out->linesize[ plane + 0 ] / 2; \
1145  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; \
1146  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; \
1147  const int limit = s->max - 1; \
1148  const int max = limit - intensity; \
1149  const int mid = s->max / 2; \
1150  const int src_h = in->height; \
1151  const int src_w = in->width; \
1152  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
1153  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
1154  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
1155  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
1156  int x, y; \
1157  \
1158  if (column) { \
1159  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \
1160  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \
1161  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \
1162  \
1163  for (x = slicew_start; x < slicew_end; x++) { \
1164  const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; \
1165  const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; \
1166  const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; \
1167  uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; \
1168  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \
1169  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \
1170  uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \
1171  uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); \
1172  uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \
1173  uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); \
1174  uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \
1175  uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); \
1176  \
1177  for (y = 0; y < src_h; y++) { \
1178  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \
1179  const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \
1180  const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \
1181  uint16_t *target; \
1182  \
1183  target = d0 + x + d0_signed_linesize * c0; \
1184  update16(target, max, intensity, limit); \
1185  \
1186  target = d1 + x + d1_signed_linesize * (c0 + c1); \
1187  update16(target, max, intensity, limit); \
1188  \
1189  target = d2 + x + d2_signed_linesize * (c0 + c2); \
1190  update_cr(target, max, intensity, limit); \
1191  \
1192  if (!c0_shift_h || (y & c0_shift_h)) \
1193  c0_data += c0_linesize; \
1194  if (!c1_shift_h || (y & c1_shift_h)) \
1195  c1_data += c1_linesize; \
1196  if (!c2_shift_h || (y & c2_shift_h)) \
1197  c2_data += c2_linesize; \
1198  d0_data += d0_linesize; \
1199  d1_data += d1_linesize; \
1200  d2_data += d2_linesize; \
1201  } \
1202  } \
1203  } else { \
1204  const uint16_t *c0_data = (uint16_t *)in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize; \
1205  const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize; \
1206  const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize; \
1207  uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x; \
1208  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x; \
1209  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x; \
1210  \
1211  if (mirror) { \
1212  d0_data += s->size - 1; \
1213  d1_data += s->size - 1; \
1214  d2_data += s->size - 1; \
1215  } \
1216  \
1217  for (y = sliceh_start; y < sliceh_end; y++) { \
1218  for (x = 0; x < src_w; x++) { \
1219  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \
1220  const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \
1221  const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \
1222  uint16_t *target; \
1223  \
1224  if (mirror) { \
1225  target = d0_data - c0; \
1226  update16(target, max, intensity, limit); \
1227  target = d1_data - (c0 + c1); \
1228  update16(target, max, intensity, limit); \
1229  target = d2_data - (c0 + c2); \
1230  update_cr(target, max, intensity, limit); \
1231  } else { \
1232  target = d0_data + c0; \
1233  update16(target, max, intensity, limit); \
1234  target = d1_data + (c0 + c1); \
1235  update16(target, max, intensity, limit); \
1236  target = d2_data + (c0 + c2); \
1237  update_cr(target, max, intensity, limit); \
1238  } \
1239  } \
1240  \
1241  if (!c0_shift_h || (y & c0_shift_h)) \
1242  c0_data += c0_linesize; \
1243  if (!c1_shift_h || (y & c1_shift_h)) \
1244  c1_data += c1_linesize; \
1245  if (!c2_shift_h || (y & c2_shift_h)) \
1246  c2_data += c2_linesize; \
1247  d0_data += d0_linesize; \
1248  d1_data += d1_linesize; \
1249  d2_data += d2_linesize; \
1250  } \
1251  } \
1252  return 0; \
1253 }
1254 
1255 #define AFLAT(name, update_cr, column, mirror) \
1256 static int name(AVFilterContext *ctx, \
1257  void *arg, int jobnr, \
1258  int nb_jobs) \
1259 { \
1260  WaveformContext *s = ctx->priv; \
1261  ThreadData *td = arg; \
1262  AVFrame *in = td->in; \
1263  AVFrame *out = td->out; \
1264  int component = td->component; \
1265  int offset_y = td->offset_y; \
1266  int offset_x = td->offset_x; \
1267  const int src_h = in->height; \
1268  const int src_w = in->width; \
1269  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
1270  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
1271  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
1272  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
1273  const int intensity = s->intensity; \
1274  const int plane = s->desc->comp[component].plane; \
1275  const int c0_linesize = in->linesize[ plane + 0 ]; \
1276  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; \
1277  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; \
1278  const int c0_shift_w = s->shift_w[ component + 0 ]; \
1279  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \
1280  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \
1281  const int c0_shift_h = s->shift_h[ component + 0 ]; \
1282  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \
1283  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \
1284  const int d0_linesize = out->linesize[ plane + 0 ]; \
1285  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; \
1286  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; \
1287  const int max = 255 - intensity; \
1288  int x, y; \
1289  \
1290  if (column) { \
1291  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \
1292  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \
1293  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \
1294  \
1295  for (x = slicew_start; x < slicew_end; x++) { \
1296  const uint8_t *c0_data = in->data[plane + 0]; \
1297  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; \
1298  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; \
1299  uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; \
1300  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \
1301  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \
1302  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \
1303  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); \
1304  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \
1305  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); \
1306  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \
1307  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); \
1308  \
1309  for (y = 0; y < src_h; y++) { \
1310  const int c0 = c0_data[x >> c0_shift_w] + 128; \
1311  const int c1 = c1_data[x >> c1_shift_w] - 128; \
1312  const int c2 = c2_data[x >> c2_shift_w] - 128; \
1313  uint8_t *target; \
1314  \
1315  target = d0 + x + d0_signed_linesize * c0; \
1316  update(target, max, intensity); \
1317  \
1318  target = d1 + x + d1_signed_linesize * (c0 + c1); \
1319  update(target, max, intensity); \
1320  \
1321  target = d2 + x + d2_signed_linesize * (c0 + c2); \
1322  update_cr(target, max, intensity); \
1323  \
1324  if (!c0_shift_h || (y & c0_shift_h)) \
1325  c0_data += c0_linesize; \
1326  if (!c1_shift_h || (y & c1_shift_h)) \
1327  c1_data += c1_linesize; \
1328  if (!c1_shift_h || (y & c1_shift_h)) \
1329  c2_data += c1_linesize; \
1330  d0_data += d0_linesize; \
1331  d1_data += d1_linesize; \
1332  d2_data += d2_linesize; \
1333  } \
1334  } \
1335  } else { \
1336  const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize; \
1337  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize; \
1338  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize; \
1339  uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x; \
1340  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x; \
1341  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x; \
1342  \
1343  if (mirror) { \
1344  d0_data += s->size - 1; \
1345  d1_data += s->size - 1; \
1346  d2_data += s->size - 1; \
1347  } \
1348  \
1349  for (y = sliceh_start; y < sliceh_end; y++) { \
1350  for (x = 0; x < src_w; x++) { \
1351  const int c0 = c0_data[x >> c0_shift_w] + 128; \
1352  const int c1 = c1_data[x >> c1_shift_w] - 128; \
1353  const int c2 = c2_data[x >> c2_shift_w] - 128; \
1354  uint8_t *target; \
1355  \
1356  if (mirror) { \
1357  target = d0_data - c0; \
1358  update(target, max, intensity); \
1359  target = d1_data - (c0 + c1); \
1360  update(target, max, intensity); \
1361  target = d2_data - (c0 + c2); \
1362  update_cr(target, max, intensity); \
1363  } else { \
1364  target = d0_data + c0; \
1365  update(target, max, intensity); \
1366  target = d1_data + (c0 + c1); \
1367  update(target, max, intensity); \
1368  target = d2_data + (c0 + c2); \
1369  update_cr(target, max, intensity); \
1370  } \
1371  } \
1372  \
1373  if (!c0_shift_h || (y & c0_shift_h)) \
1374  c0_data += c0_linesize; \
1375  if (!c1_shift_h || (y & c1_shift_h)) \
1376  c1_data += c1_linesize; \
1377  if (!c2_shift_h || (y & c2_shift_h)) \
1378  c2_data += c2_linesize; \
1379  d0_data += d0_linesize; \
1380  d1_data += d1_linesize; \
1381  d2_data += d2_linesize; \
1382  } \
1383  } \
1384  return 0; \
1385 }
1386 
1387 AFLAT16(aflat16_row, update16, 0, 0)
1388 AFLAT16(aflat16_row_mirror, update16, 0, 1)
1389 AFLAT16(aflat16_column, update16, 1, 0)
1390 AFLAT16(aflat16_column_mirror, update16, 1, 1)
1391 AFLAT16(xflat16_row, update16_cr, 0, 0)
1392 AFLAT16(xflat16_row_mirror, update16_cr, 0, 1)
1393 AFLAT16(xflat16_column, update16_cr, 1, 0)
1394 AFLAT16(xflat16_column_mirror, update16_cr, 1, 1)
1395 
1396 AFLAT(aflat_row, update, 0, 0)
1397 AFLAT(aflat_row_mirror, update, 0, 1)
1398 AFLAT(aflat_column, update, 1, 0)
1399 AFLAT(aflat_column_mirror, update, 1, 1)
1400 AFLAT(xflat_row, update_cr, 0, 0)
1401 AFLAT(xflat_row_mirror, update_cr, 0, 1)
1402 AFLAT(xflat_column, update_cr, 1, 0)
1403 AFLAT(xflat_column_mirror, update_cr, 1, 1)
1404 
1406  AVFrame *in, AVFrame *out,
1407  int component, int intensity,
1408  int offset_y, int offset_x,
1409  int column, int mirror,
1410  int jobnr, int nb_jobs)
1411 {
1412  const int plane = s->desc->comp[component].plane;
1413  const int c0_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
1414  const int c1_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
1415  const int dst_linesize = out->linesize[plane] / 2;
1416  const int limit = s->max - 1;
1417  const int max = limit - intensity;
1418  const int mid = s->max / 2;
1419  const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
1420  const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
1421  const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
1422  const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
1423  const int src_h = in->height;
1424  const int src_w = in->width;
1425  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1426  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1427  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1428  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1429  int x, y;
1430 
1431  if (column) {
1432  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
1433 
1434  for (x = slicew_start; x < slicew_end; x++) {
1435  const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
1436  const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
1437  uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x;
1438  uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
1439  uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
1440  uint16_t *dst = dst_line;
1441 
1442  for (y = 0; y < src_h; y++) {
1443  const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
1444  uint16_t *target;
1445 
1446  target = dst + x + dst_signed_linesize * sum;
1447  update16(target, max, intensity, limit);
1448 
1449  if (!c0_shift_h || (y & c0_shift_h))
1450  c0_data += c0_linesize;
1451  if (!c1_shift_h || (y & c1_shift_h))
1452  c1_data += c1_linesize;
1453  dst_data += dst_linesize;
1454  }
1455  }
1456  } else {
1457  const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c0_shift_h) * c0_linesize;
1458  const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1459  uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * dst_linesize + offset_x;
1460 
1461  if (mirror)
1462  dst_data += s->size - 1;
1463  for (y = sliceh_start; y < sliceh_end; y++) {
1464  for (x = 0; x < src_w; x++) {
1465  const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
1466  uint16_t *target;
1467 
1468  if (mirror) {
1469  target = dst_data - sum;
1470  update16(target, max, intensity, limit);
1471  } else {
1472  target = dst_data + sum;
1473  update16(target, max, intensity, limit);
1474  }
1475  }
1476 
1477  if (!c0_shift_h || (y & c0_shift_h))
1478  c0_data += c0_linesize;
1479  if (!c1_shift_h || (y & c1_shift_h))
1480  c1_data += c1_linesize;
1481  dst_data += dst_linesize;
1482  }
1483  }
1484 }
1485 
1486 #define CHROMA16_FUNC(name, column, mirror) \
1487 static int chroma16_##name(AVFilterContext *ctx, \
1488  void *arg, int jobnr, \
1489  int nb_jobs) \
1490 { \
1491  WaveformContext *s = ctx->priv; \
1492  ThreadData *td = arg; \
1493  AVFrame *in = td->in; \
1494  AVFrame *out = td->out; \
1495  int component = td->component; \
1496  int offset_y = td->offset_y; \
1497  int offset_x = td->offset_x; \
1498  \
1499  chroma16(s, in, out, component, s->intensity,\
1500  offset_y, offset_x, column, mirror, \
1501  jobnr, nb_jobs); \
1502  \
1503  return 0; \
1504 }
1505 
1506 CHROMA16_FUNC(column_mirror, 1, 1)
1507 CHROMA16_FUNC(column, 1, 0)
1508 CHROMA16_FUNC(row_mirror, 0, 1)
1509 CHROMA16_FUNC(row, 0, 0)
1510 
1512  AVFrame *in, AVFrame *out,
1513  int component, int intensity,
1514  int offset_y, int offset_x,
1515  int column, int mirror,
1516  int jobnr, int nb_jobs)
1517 {
1518  const int plane = s->desc->comp[component].plane;
1519  const int src_h = in->height;
1520  const int src_w = in->width;
1521  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1522  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1523  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1524  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1525  const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
1526  const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
1527  const int dst_linesize = out->linesize[plane];
1528  const int max = 255 - intensity;
1529  const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
1530  const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
1531  const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
1532  const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
1533  int x, y;
1534 
1535  if (column) {
1536  const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
1537 
1538  for (x = slicew_start; x < slicew_end; x++) {
1539  const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
1540  const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
1541  uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x;
1542  uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
1543  uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
1544  uint8_t *dst = dst_line;
1545 
1546  for (y = 0; y < src_h; y++) {
1547  const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
1548  uint8_t *target;
1549 
1550  target = dst + x + dst_signed_linesize * sum;
1551  update(target, max, intensity);
1552 
1553  if (!c0_shift_h || (y & c0_shift_h))
1554  c0_data += c0_linesize;
1555  if (!c1_shift_h || (y & c1_shift_h))
1556  c1_data += c1_linesize;
1557  dst_data += dst_linesize;
1558  }
1559  }
1560  } else {
1561  const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c0_shift_h) * c0_linesize;
1562  const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1563  uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start) * dst_linesize + offset_x;
1564 
1565  if (mirror)
1566  dst_data += s->size - 1;
1567  for (y = sliceh_start; y < sliceh_end; y++) {
1568  for (x = 0; x < src_w; x++) {
1569  const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
1570  uint8_t *target;
1571 
1572  if (mirror) {
1573  target = dst_data - sum;
1574  update(target, max, intensity);
1575  } else {
1576  target = dst_data + sum;
1577  update(target, max, intensity);
1578  }
1579  }
1580 
1581  if (!c0_shift_h || (y & c0_shift_h))
1582  c0_data += c0_linesize;
1583  if (!c1_shift_h || (y & c1_shift_h))
1584  c1_data += c1_linesize;
1585  dst_data += dst_linesize;
1586  }
1587  }
1588 }
1589 
1590 #define CHROMA_FUNC(name, column, mirror) \
1591 static int chroma_##name(AVFilterContext *ctx, \
1592  void *arg, int jobnr, \
1593  int nb_jobs) \
1594 { \
1595  WaveformContext *s = ctx->priv; \
1596  ThreadData *td = arg; \
1597  AVFrame *in = td->in; \
1598  AVFrame *out = td->out; \
1599  int component = td->component; \
1600  int offset_y = td->offset_y; \
1601  int offset_x = td->offset_x; \
1602  \
1603  chroma(s, in, out, component, s->intensity, \
1604  offset_y, offset_x, column, mirror, \
1605  jobnr, nb_jobs); \
1606  \
1607  return 0; \
1608 }
1609 
1610 CHROMA_FUNC(column_mirror, 1, 1)
1611 CHROMA_FUNC(column, 1, 0)
1612 CHROMA_FUNC(row_mirror, 0, 1)
1613 CHROMA_FUNC(row, 0, 0)
1614 
1616  AVFrame *in, AVFrame *out,
1617  int component, int intensity,
1618  int offset_y, int offset_x,
1619  int column, int mirror,
1620  int jobnr, int nb_jobs)
1621 {
1622  const int plane = s->desc->comp[component].plane;
1623  const int limit = s->max - 1;
1624  const int src_h = in->height;
1625  const int src_w = in->width;
1626  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1627  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1628  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1629  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1630  const int c0_linesize = in->linesize[ plane + 0 ] / 2;
1631  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
1632  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
1633  const int c0_shift_h = s->shift_h[ component + 0 ];
1634  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
1635  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
1636  const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
1637  const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1638  const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
1639  const int d0_linesize = out->linesize[ plane + 0 ] / 2;
1640  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
1641  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
1642  const int c0_shift_w = s->shift_w[ component + 0 ];
1643  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
1644  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
1645  int x, y;
1646 
1647  if (column) {
1648  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
1649  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
1650  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
1651  uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
1652  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
1653  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
1654  uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
1655  uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
1656  uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
1657  uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
1658  uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
1659  uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
1660 
1661  for (y = 0; y < src_h; y++) {
1662  for (x = slicew_start; x < slicew_end; x++) {
1663  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
1664  const int c1 = c1_data[x >> c1_shift_w];
1665  const int c2 = c2_data[x >> c2_shift_w];
1666 
1667  *(d0 + d0_signed_linesize * c0 + x) = c0;
1668  *(d1 + d1_signed_linesize * c0 + x) = c1;
1669  *(d2 + d2_signed_linesize * c0 + x) = c2;
1670  }
1671 
1672  if (!c0_shift_h || (y & c0_shift_h))
1673  c0_data += c0_linesize;
1674  if (!c1_shift_h || (y & c1_shift_h))
1675  c1_data += c1_linesize;
1676  if (!c2_shift_h || (y & c2_shift_h))
1677  c2_data += c2_linesize;
1678  d0_data += d0_linesize;
1679  d1_data += d1_linesize;
1680  d2_data += d2_linesize;
1681  }
1682  } else {
1683  uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
1684  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
1685  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
1686 
1687  if (mirror) {
1688  d0_data += s->size - 1;
1689  d1_data += s->size - 1;
1690  d2_data += s->size - 1;
1691  }
1692 
1693  for (y = sliceh_start; y < sliceh_end; y++) {
1694  for (x = 0; x < src_w; x++) {
1695  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
1696  const int c1 = c1_data[x >> c1_shift_w];
1697  const int c2 = c2_data[x >> c2_shift_w];
1698 
1699  if (mirror) {
1700  *(d0_data - c0) = c0;
1701  *(d1_data - c0) = c1;
1702  *(d2_data - c0) = c2;
1703  } else {
1704  *(d0_data + c0) = c0;
1705  *(d1_data + c0) = c1;
1706  *(d2_data + c0) = c2;
1707  }
1708  }
1709 
1710  if (!c0_shift_h || (y & c0_shift_h))
1711  c0_data += c0_linesize;
1712  if (!c1_shift_h || (y & c1_shift_h))
1713  c1_data += c1_linesize;
1714  if (!c2_shift_h || (y & c2_shift_h))
1715  c2_data += c2_linesize;
1716  d0_data += d0_linesize;
1717  d1_data += d1_linesize;
1718  d2_data += d2_linesize;
1719  }
1720  }
1721 }
1722 
1723 #define COLOR16_FUNC(name, column, mirror) \
1724 static int color16_##name(AVFilterContext *ctx, \
1725  void *arg, int jobnr, \
1726  int nb_jobs) \
1727 { \
1728  WaveformContext *s = ctx->priv; \
1729  ThreadData *td = arg; \
1730  AVFrame *in = td->in; \
1731  AVFrame *out = td->out; \
1732  int component = td->component; \
1733  int offset_y = td->offset_y; \
1734  int offset_x = td->offset_x; \
1735  \
1736  color16(s, in, out, component, s->intensity, \
1737  offset_y, offset_x, column, mirror, \
1738  jobnr, nb_jobs); \
1739  \
1740  return 0; \
1741 }
1742 
1743 COLOR16_FUNC(column_mirror, 1, 1)
1744 COLOR16_FUNC(column, 1, 0)
1745 COLOR16_FUNC(row_mirror, 0, 1)
1746 COLOR16_FUNC(row, 0, 0)
1747 
1749  AVFrame *in, AVFrame *out,
1750  int component, int intensity,
1751  int offset_y, int offset_x,
1752  int column, int mirror,
1753  int jobnr, int nb_jobs)
1754 {
1755  const int plane = s->desc->comp[component].plane;
1756  const int src_h = in->height;
1757  const int src_w = in->width;
1758  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1759  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1760  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1761  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1762  const int c0_linesize = in->linesize[ plane + 0 ];
1763  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
1764  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
1765  const int c0_shift_h = s->shift_h[ component + 0 ];
1766  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
1767  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
1768  const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize;
1769  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1770  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
1771  const int d0_linesize = out->linesize[ plane + 0 ];
1772  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
1773  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
1774  const int c0_shift_w = s->shift_w[ component + 0 ];
1775  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
1776  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
1777  int x, y;
1778 
1779  if (column) {
1780  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
1781  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
1782  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
1783  uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
1784  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
1785  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
1786  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
1787  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
1788  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
1789  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
1790  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
1791  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
1792 
1793  for (y = 0; y < src_h; y++) {
1794  for (x = slicew_start; x < slicew_end; x++) {
1795  const int c0 = c0_data[x >> c0_shift_w];
1796  const int c1 = c1_data[x >> c1_shift_w];
1797  const int c2 = c2_data[x >> c2_shift_w];
1798 
1799  *(d0 + d0_signed_linesize * c0 + x) = c0;
1800  *(d1 + d1_signed_linesize * c0 + x) = c1;
1801  *(d2 + d2_signed_linesize * c0 + x) = c2;
1802  }
1803 
1804  if (!c0_shift_h || (y & c0_shift_h))
1805  c0_data += c0_linesize;
1806  if (!c1_shift_h || (y & c1_shift_h))
1807  c1_data += c1_linesize;
1808  if (!c2_shift_h || (y & c2_shift_h))
1809  c2_data += c2_linesize;
1810  d0_data += d0_linesize;
1811  d1_data += d1_linesize;
1812  d2_data += d2_linesize;
1813  }
1814  } else {
1815  uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
1816  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
1817  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
1818 
1819  if (mirror) {
1820  d0_data += s->size - 1;
1821  d1_data += s->size - 1;
1822  d2_data += s->size - 1;
1823  }
1824 
1825  for (y = sliceh_start; y < sliceh_end; y++) {
1826  for (x = 0; x < src_w; x++) {
1827  const int c0 = c0_data[x >> c0_shift_w];
1828  const int c1 = c1_data[x >> c1_shift_w];
1829  const int c2 = c2_data[x >> c2_shift_w];
1830 
1831  if (mirror) {
1832  *(d0_data - c0) = c0;
1833  *(d1_data - c0) = c1;
1834  *(d2_data - c0) = c2;
1835  } else {
1836  *(d0_data + c0) = c0;
1837  *(d1_data + c0) = c1;
1838  *(d2_data + c0) = c2;
1839  }
1840  }
1841 
1842  if (!c0_shift_h || (y & c0_shift_h))
1843  c0_data += c0_linesize;
1844  if (!c1_shift_h || (y & c1_shift_h))
1845  c1_data += c1_linesize;
1846  if (!c2_shift_h || (y & c2_shift_h))
1847  c2_data += c2_linesize;
1848  d0_data += d0_linesize;
1849  d1_data += d1_linesize;
1850  d2_data += d2_linesize;
1851  }
1852  }
1853 }
1854 
1855 #define COLOR_FUNC(name, column, mirror) \
1856 static int color_##name(AVFilterContext *ctx, \
1857  void *arg, int jobnr, \
1858  int nb_jobs) \
1859 { \
1860  WaveformContext *s = ctx->priv; \
1861  ThreadData *td = arg; \
1862  AVFrame *in = td->in; \
1863  AVFrame *out = td->out; \
1864  int component = td->component; \
1865  int offset_y = td->offset_y; \
1866  int offset_x = td->offset_x; \
1867  \
1868  color(s, in, out, component, s->intensity, \
1869  offset_y, offset_x, column, mirror, \
1870  jobnr, nb_jobs); \
1871  \
1872  return 0; \
1873 }
1874 
1875 COLOR_FUNC(column_mirror, 1, 1)
1876 COLOR_FUNC(column, 1, 0)
1877 COLOR_FUNC(row_mirror, 0, 1)
1878 COLOR_FUNC(row, 0, 0)
1879 
1881  AVFrame *in, AVFrame *out,
1882  int component, int intensity,
1883  int offset_y, int offset_x,
1884  int column, int mirror,
1885  int jobnr, int nb_jobs)
1886 {
1887  const int plane = s->desc->comp[component].plane;
1888  const int limit = s->max - 1;
1889  const int max = limit - intensity;
1890  const int src_h = in->height;
1891  const int src_w = in->width;
1892  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
1893  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1894  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1895  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
1896  const int c0_shift_h = s->shift_h[ component + 0 ];
1897  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
1898  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
1899  const int c0_linesize = in->linesize[ plane + 0 ] / 2;
1900  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
1901  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
1902  const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
1903  const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
1904  const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
1905  const int d0_linesize = out->linesize[ plane + 0 ] / 2;
1906  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
1907  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
1908  const int c0_shift_w = s->shift_w[ component + 0 ];
1909  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
1910  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
1911  int x, y;
1912 
1913  if (column) {
1914  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
1915  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
1916  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
1917  uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
1918  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
1919  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
1920  uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
1921  uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
1922  uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
1923  uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
1924  uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
1925  uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
1926 
1927  for (y = 0; y < src_h; y++) {
1928  for (x = slicew_start; x < slicew_end; x++) {
1929  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
1930  const int c1 = c1_data[x >> c1_shift_w];
1931  const int c2 = c2_data[x >> c2_shift_w];
1932 
1933  update16(d0 + d0_signed_linesize * c0 + x, max, intensity, limit);
1934  *(d1 + d1_signed_linesize * c0 + x) = c1;
1935  *(d2 + d2_signed_linesize * c0 + x) = c2;
1936  }
1937 
1938  if (!c0_shift_h || (y & c0_shift_h))
1939  c0_data += c0_linesize;
1940  if (!c1_shift_h || (y & c1_shift_h))
1941  c1_data += c1_linesize;
1942  if (!c2_shift_h || (y & c2_shift_h))
1943  c2_data += c2_linesize;
1944  d0_data += d0_linesize;
1945  d1_data += d1_linesize;
1946  d2_data += d2_linesize;
1947  }
1948  } else {
1949  uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
1950  uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
1951  uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
1952 
1953  if (mirror) {
1954  d0_data += s->size - 1;
1955  d1_data += s->size - 1;
1956  d2_data += s->size - 1;
1957  }
1958 
1959  for (y = sliceh_start; y < sliceh_end; y++) {
1960  for (x = 0; x < src_w; x++) {
1961  const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
1962  const int c1 = c1_data[x >> c1_shift_w];
1963  const int c2 = c2_data[x >> c2_shift_w];
1964 
1965  if (mirror) {
1966  update16(d0_data - c0, max, intensity, limit);
1967  *(d1_data - c0) = c1;
1968  *(d2_data - c0) = c2;
1969  } else {
1970  update16(d0_data + c0, max, intensity, limit);
1971  *(d1_data + c0) = c1;
1972  *(d2_data + c0) = c2;
1973  }
1974  }
1975 
1976  if (!c0_shift_h || (y & c0_shift_h))
1977  c0_data += c0_linesize;
1978  if (!c1_shift_h || (y & c1_shift_h))
1979  c1_data += c1_linesize;
1980  if (!c2_shift_h || (y & c2_shift_h))
1981  c2_data += c2_linesize;
1982  d0_data += d0_linesize;
1983  d1_data += d1_linesize;
1984  d2_data += d2_linesize;
1985  }
1986  }
1987 }
1988 
1989 #define ACOLOR16_FUNC(name, column, mirror) \
1990 static int acolor16_##name(AVFilterContext *ctx, \
1991  void *arg, int jobnr, \
1992  int nb_jobs) \
1993 { \
1994  WaveformContext *s = ctx->priv; \
1995  ThreadData *td = arg; \
1996  AVFrame *in = td->in; \
1997  AVFrame *out = td->out; \
1998  int component = td->component; \
1999  int offset_y = td->offset_y; \
2000  int offset_x = td->offset_x; \
2001  \
2002  acolor16(s, in, out, component, s->intensity,\
2003  offset_y, offset_x, column, mirror, \
2004  jobnr, nb_jobs); \
2005  \
2006  return 0; \
2007 }
2008 
2009 ACOLOR16_FUNC(column_mirror, 1, 1)
2010 ACOLOR16_FUNC(column, 1, 0)
2011 ACOLOR16_FUNC(row_mirror, 0, 1)
2012 ACOLOR16_FUNC(row, 0, 0)
2013 
2015  AVFrame *in, AVFrame *out,
2016  int component, int intensity,
2017  int offset_y, int offset_x,
2018  int column, int mirror,
2019  int jobnr, int nb_jobs)
2020 {
2021  const int plane = s->desc->comp[component].plane;
2022  const int src_h = in->height;
2023  const int src_w = in->width;
2024  const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
2025  const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
2026  const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
2027  const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
2028  const int c0_shift_w = s->shift_w[ component + 0 ];
2029  const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
2030  const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
2031  const int c0_shift_h = s->shift_h[ component + 0 ];
2032  const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
2033  const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
2034  const int c0_linesize = in->linesize[ plane + 0 ];
2035  const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
2036  const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
2037  const uint8_t *c0_data = in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
2038  const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
2039  const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
2040  const int d0_linesize = out->linesize[ plane + 0 ];
2041  const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
2042  const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
2043  const int max = 255 - intensity;
2044  int x, y;
2045 
2046  if (column) {
2047  const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
2048  const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
2049  const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
2050  uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
2051  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
2052  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
2053  uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
2054  uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
2055  uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
2056  uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
2057  uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
2058  uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
2059 
2060  for (y = 0; y < src_h; y++) {
2061  for (x = slicew_start; x < slicew_end; x++) {
2062  const int c0 = c0_data[x >> c0_shift_w];
2063  const int c1 = c1_data[x >> c1_shift_w];
2064  const int c2 = c2_data[x >> c2_shift_w];
2065 
2066  update(d0 + d0_signed_linesize * c0 + x, max, intensity);
2067  *(d1 + d1_signed_linesize * c0 + x) = c1;
2068  *(d2 + d2_signed_linesize * c0 + x) = c2;
2069  }
2070 
2071  if (!c0_shift_h || (y & c0_shift_h))
2072  c0_data += c0_linesize;
2073  if (!c1_shift_h || (y & c1_shift_h))
2074  c1_data += c1_linesize;
2075  if (!c2_shift_h || (y & c2_shift_h))
2076  c2_data += c2_linesize;
2077  d0_data += d0_linesize;
2078  d1_data += d1_linesize;
2079  d2_data += d2_linesize;
2080  }
2081  } else {
2082  uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
2083  uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
2084  uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
2085 
2086  if (mirror) {
2087  d0_data += s->size - 1;
2088  d1_data += s->size - 1;
2089  d2_data += s->size - 1;
2090  }
2091 
2092  for (y = sliceh_start; y < sliceh_end; y++) {
2093  for (x = 0; x < src_w; x++) {
2094  const int c0 = c0_data[x >> c0_shift_w];
2095  const int c1 = c1_data[x >> c1_shift_w];
2096  const int c2 = c2_data[x >> c2_shift_w];
2097 
2098  if (mirror) {
2099  update(d0_data - c0, max, intensity);
2100  *(d1_data - c0) = c1;
2101  *(d2_data - c0) = c2;
2102  } else {
2103  update(d0_data + c0, max, intensity);
2104  *(d1_data + c0) = c1;
2105  *(d2_data + c0) = c2;
2106  }
2107  }
2108 
2109  if (!c0_shift_h || (y & c0_shift_h))
2110  c0_data += c0_linesize;
2111  if (!c1_shift_h || (y & c1_shift_h))
2112  c1_data += c1_linesize;
2113  if (!c2_shift_h || (y & c2_shift_h))
2114  c2_data += c2_linesize;
2115  d0_data += d0_linesize;
2116  d1_data += d1_linesize;
2117  d2_data += d2_linesize;
2118  }
2119  }
2120 }
2121 
2122 #define ACOLOR_FUNC(name, column, mirror) \
2123 static int acolor_##name(AVFilterContext *ctx, \
2124  void *arg, int jobnr, \
2125  int nb_jobs) \
2126 { \
2127  WaveformContext *s = ctx->priv; \
2128  ThreadData *td = arg; \
2129  AVFrame *in = td->in; \
2130  AVFrame *out = td->out; \
2131  int component = td->component; \
2132  int offset_y = td->offset_y; \
2133  int offset_x = td->offset_x; \
2134  \
2135  acolor(s, in, out, component, s->intensity, \
2136  offset_y, offset_x, column, mirror, \
2137  jobnr, nb_jobs); \
2138  \
2139  return 0; \
2140 }
2141 
2142 ACOLOR_FUNC(column_mirror, 1, 1)
2143 ACOLOR_FUNC(column, 1, 0)
2144 ACOLOR_FUNC(row_mirror, 0, 1)
2145 ACOLOR_FUNC(row, 0, 0)
2146 
2147 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
2148 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
2149 
2150 static const GraticuleLines aflat_digital8[] = {
2151  { { { "16", 16+128 }, { "16", 16+128 }, { "16", 16+128 }, { "0", 0+128 } } },
2152  { { { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 } } },
2153  { { { "235", 235+128 }, { "240", 240+128 }, { "240", 240+128 }, { "255", 255+128 } } },
2154 };
2155 
2156 static const GraticuleLines aflat_digital9[] = {
2157  { { { "32", 32+256 }, { "32", 32+256 }, { "32", 32+256 }, { "0", 0+256 } } },
2158  { { { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 } } },
2159  { { { "470", 470+256 }, { "480", 480+256 }, { "480", 480+256 }, { "511", 511+256 } } },
2160 };
2161 
2163  { { { "64", 64+512 }, { "64", 64+512 }, { "64", 64+512 }, { "0", 0+512 } } },
2164  { { { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 } } },
2165  { { { "940", 940+512 }, { "960", 960+512 }, { "960", 960+512 }, { "1023", 1023+512 } } },
2166 };
2167 
2169  { { { "256", 256+2048 }, { "256", 256+2048 }, { "256", 256+2048 }, { "0", 0+2048 } } },
2170  { { { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 } } },
2171  { { { "3760", 3760+2048 }, { "3840", 3840+2048 }, { "3840", 3840+2048 }, { "4095", 4095+2048 } } },
2172 };
2173 
2175  { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } },
2176  { { { "175", 71+128 }, { "175", 72+128 }, { "175", 72+128 }, { "175", 64+128 } } },
2177  { { { "350", 126+128 }, { "350", 128+128 }, { "350", 128+128 }, { "350", 128+128 } } },
2178  { { { "525", 180+128 }, { "525", 184+128 }, { "525", 184+128 }, { "525", 192+128 } } },
2179  { { { "700", 235+128 }, { "700", 240+128 }, { "700", 240+128 }, { "700", 255+128 } } },
2180 };
2181 
2183  { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } },
2184  { { { "175", 142+256 }, { "175", 144+256 }, { "175", 144+256 }, { "175", 128+256 } } },
2185  { { { "350", 251+256 }, { "350", 256+256 }, { "350", 256+256 }, { "350", 256+256 } } },
2186  { { { "525", 361+256 }, { "525", 368+256 }, { "525", 368+256 }, { "525", 384+256 } } },
2187  { { { "700", 470+256 }, { "700", 480+256 }, { "700", 480+256 }, { "700", 511+256 } } },
2188 };
2189 
2191  { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } },
2192  { { { "175", 283+512 }, { "175", 288+512 }, { "175", 288+512 }, { "175", 256+512 } } },
2193  { { { "350", 502+512 }, { "350", 512+512 }, { "350", 512+512 }, { "350", 512+512 } } },
2194  { { { "525", 721+512 }, { "525", 736+512 }, { "525", 736+512 }, { "525", 768+512 } } },
2195  { { { "700", 940+512 }, { "700", 960+512 }, { "700", 960+512 }, { "700", 1023+512 } } },
2196 };
2197 
2199  { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } },
2200  { { { "175", 1132+2048 }, { "175", 1152+2048 }, { "175", 1152+2048 }, { "175", 1024+2048 } } },
2201  { { { "350", 2008+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 } } },
2202  { { { "525", 2884+2048 }, { "525", 2944+2048 }, { "525", 2944+2048 }, { "525", 3072+2048 } } },
2203  { { { "700", 3760+2048 }, { "700", 3840+2048 }, { "700", 3840+2048 }, { "700", 4095+2048 } } },
2204 };
2205 
2206 static const GraticuleLines aflat_ire8[] = {
2207  { { { "-25", -39+128 }, { "-25", -40+128 }, { "-25", -40+128 }, { "-25", -64+128 } } },
2208  { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } },
2209  { { { "25", 71+128 }, { "25", 72+128 }, { "25", 72+128 }, { "25", 64+128 } } },
2210  { { { "50", 126+128 }, { "50", 128+128 }, { "50", 128+128 }, { "50", 128+128 } } },
2211  { { { "75", 180+128 }, { "75", 184+128 }, { "75", 184+128 }, { "75", 192+128 } } },
2212  { { { "100", 235+128 }, { "100", 240+128 }, { "100", 240+128 }, { "100", 256+128 } } },
2213  { { { "125", 290+128 }, { "125", 296+128 }, { "125", 296+128 }, { "125", 320+128 } } },
2214 };
2215 
2216 static const GraticuleLines aflat_ire9[] = {
2217  { { { "-25", -78+256 }, { "-25", -80+256 }, { "-25", -80+256 }, { "-25",-128+256 } } },
2218  { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } },
2219  { { { "25", 142+256 }, { "25", 144+256 }, { "25", 144+256 }, { "25", 128+256 } } },
2220  { { { "50", 251+256 }, { "50", 256+256 }, { "50", 256+256 }, { "50", 256+256 } } },
2221  { { { "75", 361+256 }, { "75", 368+256 }, { "75", 368+256 }, { "75", 384+256 } } },
2222  { { { "100", 470+256 }, { "100", 480+256 }, { "100", 480+256 }, { "100", 512+256 } } },
2223  { { { "125", 580+256 }, { "125", 592+256 }, { "125", 592+256 }, { "125", 640+256 } } },
2224 };
2225 
2226 static const GraticuleLines aflat_ire10[] = {
2227  { { { "-25",-156+512 }, { "-25",-160+512 }, { "-25",-160+512 }, { "-25", -256+512 } } },
2228  { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } },
2229  { { { "25", 283+512 }, { "25", 288+512 }, { "25", 288+512 }, { "25", 256+512 } } },
2230  { { { "50", 502+512 }, { "50", 512+512 }, { "50", 512+512 }, { "50", 512+512 } } },
2231  { { { "75", 721+512 }, { "75", 736+512 }, { "75", 736+512 }, { "75", 768+512 } } },
2232  { { { "100", 940+512 }, { "100", 960+512 }, { "100", 960+512 }, { "100", 1024+512 } } },
2233  { { { "125",1160+512 }, { "125",1184+512 }, { "125",1184+512 }, { "125", 1280+512 } } },
2234 };
2235 
2236 static const GraticuleLines aflat_ire12[] = {
2237  { { { "-25", -624+2048 }, { "-25", -640+2048 }, { "-25", -640+2048 }, { "-25",-1024+2048 } } },
2238  { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } },
2239  { { { "25", 1132+2048 }, { "25", 1152+2048 }, { "25", 1152+2048 }, { "25", 1024+2048 } } },
2240  { { { "50", 2008+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 } } },
2241  { { { "75", 2884+2048 }, { "75", 2944+2048 }, { "75", 2944+2048 }, { "75", 3072+2048 } } },
2242  { { { "100", 3760+2048 }, { "100", 3840+2048 }, { "100", 3840+2048 }, { "100", 4096+2048 } } },
2243  { { { "125", 4640+2048 }, { "125", 4736+2048 }, { "125", 4736+2048 }, { "125", 5120+2048 } } },
2244 };
2245 
2246 static const GraticuleLines flat_digital8[] = {
2247  { { { "16", 16+256 }, { "16", 16+256 }, { "16", 16+256 }, { "0", 0+256 } } },
2248  { { { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 } } },
2249  { { { "235", 235+256 }, { "240", 240+256 }, { "240", 240+256 }, { "255", 255+256 } } },
2250 };
2251 
2252 static const GraticuleLines flat_digital9[] = {
2253  { { { "32", 32+512 }, { "32", 32+512 }, { "32", 32+512 }, { "0", 0+512 } } },
2254  { { { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 } } },
2255  { { { "470", 470+512 }, { "480", 480+512 }, { "480", 480+512 }, { "511", 511+512 } } },
2256 };
2257 
2258 static const GraticuleLines flat_digital10[] = {
2259  { { { "64", 64+1024 }, { "64", 64+1024 }, { "64", 64+1024 }, { "0", 0+1024 } } },
2260  { { { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 } } },
2261  { { { "940", 940+1024 }, { "960", 960+1024 }, { "960", 960+1024 }, { "1023", 1023+1024 } } },
2262 };
2263 
2264 static const GraticuleLines flat_digital12[] = {
2265  { { { "256", 256+4096 }, { "256", 256+4096 }, { "256", 256+4096 }, { "0", 0+4096 } } },
2266  { { { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 } } },
2267  { { { "3760", 3760+4096 }, { "3840", 3840+4096 }, { "3840", 3840+4096 }, { "4095", 4095+4096 } } },
2268 };
2269 
2271  { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } },
2272  { { { "175", 71+256 }, { "175", 72+256 }, { "175", 72+256 }, { "175", 64+256 } } },
2273  { { { "350", 126+256 }, { "350", 128+256 }, { "350", 128+256 }, { "350", 128+256 } } },
2274  { { { "525", 180+256 }, { "525", 184+256 }, { "525", 184+256 }, { "525", 192+256 } } },
2275  { { { "700", 235+256 }, { "700", 240+256 }, { "700", 240+256 }, { "700", 255+256 } } },
2276 };
2277 
2279  { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } },
2280  { { { "175", 142+512 }, { "175", 144+512 }, { "175", 144+512 }, { "175", 128+512 } } },
2281  { { { "350", 251+512 }, { "350", 256+512 }, { "350", 256+512 }, { "350", 256+512 } } },
2282  { { { "525", 361+512 }, { "525", 368+512 }, { "525", 368+512 }, { "525", 384+512 } } },
2283  { { { "700", 470+512 }, { "700", 480+512 }, { "700", 480+512 }, { "700", 511+512 } } },
2284 };
2285 
2287  { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } },
2288  { { { "175", 283+1024 }, { "175", 288+1024 }, { "175", 288+1024 }, { "175", 256+1024 } } },
2289  { { { "350", 502+1024 }, { "350", 512+1024 }, { "350", 512+1024 }, { "350", 512+1024 } } },
2290  { { { "525", 721+1024 }, { "525", 736+1024 }, { "525", 736+1024 }, { "525", 768+1024 } } },
2291  { { { "700", 940+1024 }, { "700", 960+1024 }, { "700", 960+1024 }, { "700", 1023+1024 } } },
2292 };
2293 
2295  { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } },
2296  { { { "175", 1132+4096 }, { "175", 1152+4096 }, { "175", 1152+4096 }, { "175", 1024+4096 } } },
2297  { { { "350", 2008+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 } } },
2298  { { { "525", 2884+4096 }, { "525", 2944+4096 }, { "525", 2944+4096 }, { "525", 3072+4096 } } },
2299  { { { "700", 3760+4096 }, { "700", 3840+4096 }, { "700", 3840+4096 }, { "700", 4095+4096 } } },
2300 };
2301 
2302 static const GraticuleLines flat_ire8[] = {
2303  { { { "-25", -39+256 }, { "-25", -40+256 }, { "-25", -40+256 }, { "-25", -64+256 } } },
2304  { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } },
2305  { { { "25", 71+256 }, { "25", 72+256 }, { "25", 72+256 }, { "25", 64+256 } } },
2306  { { { "50", 126+256 }, { "50", 128+256 }, { "50", 128+256 }, { "50", 128+256 } } },
2307  { { { "75", 180+256 }, { "75", 184+256 }, { "75", 184+256 }, { "75", 192+256 } } },
2308  { { { "100", 235+256 }, { "100", 240+256 }, { "100", 240+256 }, { "100", 256+256 } } },
2309  { { { "125", 290+256 }, { "125", 296+256 }, { "125", 296+256 }, { "125", 320+256 } } },
2310 };
2311 
2312 static const GraticuleLines flat_ire9[] = {
2313  { { { "-25", -78+512 }, { "-25", -80+512 }, { "-25", -80+512 }, { "-25",-128+512 } } },
2314  { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } },
2315  { { { "25", 142+512 }, { "25", 144+512 }, { "25", 144+512 }, { "25", 128+512 } } },
2316  { { { "50", 251+512 }, { "50", 256+512 }, { "50", 256+512 }, { "50", 256+512 } } },
2317  { { { "75", 361+512 }, { "75", 368+512 }, { "75", 368+512 }, { "75", 384+512 } } },
2318  { { { "100", 470+512 }, { "100", 480+512 }, { "100", 480+512 }, { "100", 512+512 } } },
2319  { { { "125", 580+512 }, { "125", 592+512 }, { "125", 592+512 }, { "125", 640+512 } } },
2320 };
2321 
2322 static const GraticuleLines flat_ire10[] = {
2323  { { { "-25",-156+1024 }, { "-25",-160+1024 }, { "-25",-160+1024 }, { "-25", -256+1024 } } },
2324  { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } },
2325  { { { "25", 283+1024 }, { "25", 288+1024 }, { "25", 288+1024 }, { "25", 256+1024 } } },
2326  { { { "50", 502+1024 }, { "50", 512+1024 }, { "50", 512+1024 }, { "50", 512+1024 } } },
2327  { { { "75", 721+1024 }, { "75", 736+1024 }, { "75", 736+1024 }, { "75", 768+1024 } } },
2328  { { { "100", 940+1024 }, { "100", 960+1024 }, { "100", 960+1024 }, { "100", 1024+1024 } } },
2329  { { { "125",1160+1024 }, { "125",1184+1024 }, { "125",1184+1024 }, { "125", 1280+1024 } } },
2330 };
2331 
2332 static const GraticuleLines flat_ire12[] = {
2333  { { { "-25", -624+4096 }, { "-25", -640+4096 }, { "-25", -640+4096 }, { "-25",-1024+4096 } } },
2334  { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } },
2335  { { { "25", 1132+4096 }, { "25", 1152+4096 }, { "25", 1152+4096 }, { "25", 1024+4096 } } },
2336  { { { "50", 2008+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 } } },
2337  { { { "75", 2884+4096 }, { "75", 2944+4096 }, { "75", 2944+4096 }, { "75", 3072+4096 } } },
2338  { { { "100", 3760+4096 }, { "100", 3840+4096 }, { "100", 3840+4096 }, { "100", 4096+4096 } } },
2339  { { { "125", 4640+4096 }, { "125", 4736+4096 }, { "125", 4736+4096 }, { "125", 5120+4096 } } },
2340 };
2341 
2342 static const GraticuleLines digital8[] = {
2343  { { { "16", 16 }, { "16", 16 }, { "16", 16 }, { "0", 0 } } },
2344  { { { "128", 128 }, { "128", 128 }, { "128", 128 }, { "128", 128 } } },
2345  { { { "235", 235 }, { "240", 240 }, { "240", 240 }, { "255", 255 } } },
2346 };
2347 
2348 static const GraticuleLines digital9[] = {
2349  { { { "32", 32 }, { "32", 32 }, { "32", 32 }, { "0", 0 } } },
2350  { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "256", 256 } } },
2351  { { { "470", 470 }, { "480", 480 }, { "480", 480 }, { "511", 511 } } },
2352 };
2353 
2354 static const GraticuleLines digital10[] = {
2355  { { { "64", 64 }, { "64", 64 }, { "64", 64 }, { "0", 0 } } },
2356  { { { "512", 512 }, { "512", 512 }, { "512", 512 }, { "512", 512 } } },
2357  { { { "940", 940 }, { "960", 960 }, { "960", 960 }, { "1023", 1023 } } },
2358 };
2359 
2360 static const GraticuleLines digital12[] = {
2361  { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "0", 0 } } },
2362  { { { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 } } },
2363  { { { "3760", 3760 }, { "3840", 3840 }, { "3840", 3840 }, { "4095", 4095 } } },
2364 };
2365 
2366 static const GraticuleLines millivolts8[] = {
2367  { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } },
2368  { { { "175", 71 }, { "175", 72 }, { "175", 72 }, { "175", 64 } } },
2369  { { { "350", 126 }, { "350", 128 }, { "350", 128 }, { "350", 128 } } },
2370  { { { "525", 180 }, { "525", 184 }, { "525", 184 }, { "525", 192 } } },
2371  { { { "700", 235 }, { "700", 240 }, { "700", 240 }, { "700", 255 } } },
2372 };
2373 
2374 static const GraticuleLines millivolts9[] = {
2375  { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } },
2376  { { { "175", 142 }, { "175", 144 }, { "175", 144 }, { "175", 128 } } },
2377  { { { "350", 251 }, { "350", 256 }, { "350", 256 }, { "350", 256 } } },
2378  { { { "525", 361 }, { "525", 368 }, { "525", 368 }, { "525", 384 } } },
2379  { { { "700", 470 }, { "700", 480 }, { "700", 480 }, { "700", 511 } } },
2380 };
2381 
2382 static const GraticuleLines millivolts10[] = {
2383  { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } },
2384  { { { "175", 283 }, { "175", 288 }, { "175", 288 }, { "175", 256 } } },
2385  { { { "350", 502 }, { "350", 512 }, { "350", 512 }, { "350", 512 } } },
2386  { { { "525", 721 }, { "525", 736 }, { "525", 736 }, { "525", 768 } } },
2387  { { { "700", 940 }, { "700", 960 }, { "700", 960 }, { "700", 1023 } } },
2388 };
2389 
2390 static const GraticuleLines millivolts12[] = {
2391  { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } },
2392  { { { "175", 1132 }, { "175", 1152 }, { "175", 1152 }, { "175", 1024 } } },
2393  { { { "350", 2008 }, { "350", 2048 }, { "350", 2048 }, { "350", 2048 } } },
2394  { { { "525", 2884 }, { "525", 2944 }, { "525", 2944 }, { "525", 3072 } } },
2395  { { { "700", 3760 }, { "700", 3840 }, { "700", 3840 }, { "700", 4095 } } },
2396 };
2397 
2398 static const GraticuleLines ire8[] = {
2399  { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } },
2400  { { { "25", 71 }, { "25", 72 }, { "25", 72 }, { "25", 64 } } },
2401  { { { "50", 126 }, { "50", 128 }, { "50", 128 }, { "50", 128 } } },
2402  { { { "75", 180 }, { "75", 184 }, { "75", 184 }, { "75", 192 } } },
2403  { { { "100", 235 }, { "100", 240 }, { "100", 240 }, { "100", 255 } } },
2404 };
2405 
2406 static const GraticuleLines ire9[] = {
2407  { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } },
2408  { { { "25", 142 }, { "25", 144 }, { "25", 144 }, { "25", 128 } } },
2409  { { { "50", 251 }, { "50", 256 }, { "50", 256 }, { "50", 256 } } },
2410  { { { "75", 361 }, { "75", 368 }, { "75", 368 }, { "75", 384 } } },
2411  { { { "100", 470 }, { "100", 480 }, { "100", 480 }, { "100", 511 } } },
2412 };
2413 
2414 static const GraticuleLines ire10[] = {
2415  { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } },
2416  { { { "25", 283 }, { "25", 288 }, { "25", 288 }, { "25", 256 } } },
2417  { { { "50", 502 }, { "50", 512 }, { "50", 512 }, { "50", 512 } } },
2418  { { { "75", 721 }, { "75", 736 }, { "75", 736 }, { "75", 768 } } },
2419  { { { "100", 940 }, { "100", 960 }, { "100", 960 }, { "100", 1023 } } },
2420 };
2421 
2422 static const GraticuleLines ire12[] = {
2423  { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } },
2424  { { { "25", 1132 }, { "25", 1152 }, { "25", 1152 }, { "25", 1024 } } },
2425  { { { "50", 2008 }, { "50", 2048 }, { "50", 2048 }, { "50", 2048 } } },
2426  { { { "75", 2884 }, { "75", 2944 }, { "75", 2944 }, { "75", 3072 } } },
2427  { { { "100", 3760 }, { "100", 3840 }, { "100", 3840 }, { "100", 4095 } } },
2428 };
2429 
2431  { { { "50", 50 }, { "50", 50 }, { "50", 50 }, { "50", 50 } } },
2432  { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
2433  { { { "150", 150 }, { "150", 150 }, { "150", 150 }, { "150", 150 } } },
2434  { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
2435  { { { "255", 255 }, { "255", 255 }, { "255", 255 }, { "255", 255 } } },
2436 };
2437 
2439  { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
2440  { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
2441  { { { "300", 300 }, { "300", 300 }, { "300", 300 }, { "300", 300 } } },
2442  { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
2443  { { { "500", 500 }, { "500", 500 }, { "500", 500 }, { "500", 500 } } },
2444 };
2445 
2447  { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
2448  { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
2449  { { { "600", 600 }, { "600", 600 }, { "600", 600 }, { "600", 600 } } },
2450  { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } },
2451  { { {"1000",1000 }, {"1000",1000 }, {"1000",1000 }, {"1000",1000 } } },
2452 };
2453 
2455  { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } },
2456  { { { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 } } },
2457  { { { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 } } },
2458  { { { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 } } },
2459  { { { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 } } },
2460 };
2461 
2462 static void blend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step)
2463 {
2464  int y;
2465 
2466  for (y = 0; y < height; y += step) {
2467  dst[0] = v * o1 + dst[0] * o2;
2468 
2469  dst += linesize * step;
2470  }
2471 }
2472 
2473 static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step)
2474 {
2475  int y;
2476 
2477  for (y = 0; y < height; y += step) {
2478  dst[0] = v * o1 + dst[0] * o2;
2479 
2480  dst += (linesize / 2) * step;
2481  }
2482 }
2483 
2484 static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step)
2485 {
2486  int x;
2487 
2488  for (x = 0; x < width; x += step) {
2489  dst[x] = v * o1 + dst[x] * o2;
2490  }
2491 }
2492 
2493 static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step)
2494 {
2495  int x;
2496 
2497  for (x = 0; x < width; x += step) {
2498  dst[x] = v * o1 + dst[x] * o2;
2499  }
2500 }
2501 
2502 static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
2503 {
2504  const uint8_t *font;
2505  int font_height;
2506  int i, plane;
2507 
2508  font = avpriv_cga_font, font_height = 8;
2509 
2510  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
2511  for (i = 0; txt[i]; i++) {
2512  int char_y, mask;
2513  int v = color[plane];
2514 
2515  uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
2516  for (char_y = 0; char_y < font_height; char_y++) {
2517  for (mask = 0x80; mask; mask >>= 1) {
2518  if (font[txt[i] * font_height + char_y] & mask)
2519  p[0] = p[0] * o2 + v * o1;
2520  p++;
2521  }
2522  p += out->linesize[plane] - 8;
2523  }
2524  }
2525  }
2526 }
2527 
2528 static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
2529 {
2530  const uint8_t *font;
2531  int font_height;
2532  int i, plane;
2533 
2534  font = avpriv_cga_font, font_height = 8;
2535 
2536  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
2537  for (i = 0; txt[i]; i++) {
2538  int char_y, mask;
2539  int v = color[plane] * mult;
2540 
2541  uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
2542  for (char_y = 0; char_y < font_height; char_y++) {
2543  for (mask = 0x80; mask; mask >>= 1) {
2544  if (font[txt[i] * font_height + char_y] & mask)
2545  p[0] = p[0] * o2 + v * o1;
2546  p++;
2547  }
2548  p += out->linesize[plane] / 2 - 8;
2549  }
2550  }
2551  }
2552 }
2553 
2554 static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
2555 {
2556  const uint8_t *font;
2557  int font_height;
2558  int i, plane;
2559 
2560  font = avpriv_cga_font, font_height = 8;
2561 
2562  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
2563  for (i = 0; txt[i]; i++) {
2564  int char_y, mask;
2565  int v = color[plane];
2566 
2567  for (char_y = font_height - 1; char_y >= 0; char_y--) {
2568  uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x;
2569  for (mask = 0x80; mask; mask >>= 1) {
2570  if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
2571  p[char_y] = p[char_y] * o2 + v * o1;
2572  p += out->linesize[plane];
2573  }
2574  }
2575  }
2576  }
2577 }
2578 
2579 static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
2580 {
2581  const uint8_t *font;
2582  int font_height;
2583  int i, plane;
2584 
2585  font = avpriv_cga_font, font_height = 8;
2586 
2587  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
2588  for (i = 0; txt[i]; i++) {
2589  int char_y, mask;
2590  int v = color[plane] * mult;
2591 
2592  for (char_y = 0; char_y < font_height; char_y++) {
2593  uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x;
2594  for (mask = 0x80; mask; mask >>= 1) {
2595  if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
2596  p[char_y] = p[char_y] * o2 + v * o1;
2597  p += out->linesize[plane] / 2;
2598  }
2599  }
2600  }
2601  }
2602 }
2603 
2605 {
2606 }
2607 
2609 {
2610  const int step = (s->flags & 2) + 1;
2611  const float o1 = s->opacity;
2612  const float o2 = 1. - o1;
2613  const int height = s->display == PARADE ? out->height / s->acomp : out->height;
2614  int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
2615 
2616  for (c = 0; c < s->ncomp; c++) {
2617  if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
2618  continue;
2619 
2620  k++;
2621  C = s->rgb ? 0 : c;
2622  for (p = 0; p < s->ncomp; p++) {
2623  const int v = s->grat_yuva_color[p];
2624  for (l = 0; l < s->nb_glines; l++) {
2625  const uint16_t pos = s->glines[l].line[C].pos;
2626  int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
2627  uint8_t *dst = out->data[p] + offset_y * out->linesize[p] + x;
2628 
2629  blend_vline(dst, height, out->linesize[p], o1, o2, v, step);
2630  }
2631  }
2632 
2633  for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
2634  const char *name = s->glines[l].line[C].name;
2635  const uint16_t pos = s->glines[l].line[C].pos;
2636  int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
2637 
2638  if (x < 0)
2639  x = 4;
2640 
2641  draw_vtext(out, x, offset_y + 2, o1, o2, name, s->grat_yuva_color);
2642  }
2643 
2644  offset_x += s->size * (s->display == STACK);
2645  offset_y += height * (s->display == PARADE);
2646  }
2647 }
2648 
2650 {
2651  const int step = (s->flags & 2) + 1;
2652  const float o1 = s->opacity;
2653  const float o2 = 1. - o1;
2654  const int mult = s->max / 256;
2655  const int height = s->display == PARADE ? out->height / s->acomp : out->height;
2656  int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
2657 
2658  for (c = 0; c < s->ncomp; c++) {
2659  if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
2660  continue;
2661 
2662  k++;
2663  C = s->rgb ? 0 : c;
2664  for (p = 0; p < s->ncomp; p++) {
2665  const int v = s->grat_yuva_color[p] * mult;
2666  for (l = 0; l < s->nb_glines ; l++) {
2667  const uint16_t pos = s->glines[l].line[C].pos;
2668  int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
2669  uint16_t *dst = (uint16_t *)(out->data[p] + offset_y * out->linesize[p]) + x;
2670 
2671  blend_vline16(dst, height, out->linesize[p], o1, o2, v, step);
2672  }
2673  }
2674 
2675  for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
2676  const char *name = s->glines[l].line[C].name;
2677  const uint16_t pos = s->glines[l].line[C].pos;
2678  int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
2679 
2680  if (x < 0)
2681  x = 4;
2682 
2683  draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, s->grat_yuva_color);
2684  }
2685 
2686  offset_x += s->size * (s->display == STACK);
2687  offset_y += height * (s->display == PARADE);
2688  }
2689 }
2690 
2692 {
2693  const int step = (s->flags & 2) + 1;
2694  const float o1 = s->opacity;
2695  const float o2 = 1. - o1;
2696  const int width = s->display == PARADE ? out->width / s->acomp : out->width;
2697  int C, k = 0, c, p, l, offset_y = 0, offset_x = 0;
2698 
2699  for (c = 0; c < s->ncomp; c++) {
2700  if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
2701  continue;
2702 
2703  k++;
2704  C = s->rgb ? 0 : c;
2705  for (p = 0; p < s->ncomp; p++) {
2706  const int v = s->grat_yuva_color[p];
2707  for (l = 0; l < s->nb_glines ; l++) {
2708  const uint16_t pos = s->glines[l].line[C].pos;
2709  int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
2710  uint8_t *dst = out->data[p] + y * out->linesize[p] + offset_x;
2711 
2712  blend_hline(dst, width, o1, o2, v, step);
2713  }
2714  }
2715 
2716  for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
2717  const char *name = s->glines[l].line[C].name;
2718  const uint16_t pos = s->glines[l].line[C].pos;
2719  int y = offset_y + (s->mirror ? s->size - 1 - pos : pos) - 10;
2720 
2721  if (y < 0)
2722  y = 4;
2723 
2724  draw_htext(out, 2 + offset_x, y, o1, o2, name, s->grat_yuva_color);
2725  }
2726 
2727  offset_y += s->size * (s->display == STACK);
2728  offset_x += width * (s->display == PARADE);
2729  }
2730 }
2731 
2733 {
2734  const int step = (s->flags & 2) + 1;
2735  const float o1 = s->opacity;
2736  const float o2 = 1. - o1;
2737  const int mult = s->max / 256;
2738  const int width = s->display == PARADE ? out->width / s->acomp : out->width;
2739  int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
2740 
2741  for (c = 0; c < s->ncomp; c++) {
2742  if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
2743  continue;
2744 
2745  k++;
2746  C = s->rgb ? 0 : c;
2747  for (p = 0; p < s->ncomp; p++) {
2748  const int v = s->grat_yuva_color[p] * mult;
2749  for (l = 0; l < s->nb_glines ; l++) {
2750  const uint16_t pos = s->glines[l].line[C].pos;
2751  int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
2752  uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]) + offset_x;
2753 
2754  blend_hline16(dst, width, o1, o2, v, step);
2755  }
2756  }
2757 
2758  for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
2759  const char *name = s->glines[l].line[C].name;
2760  const uint16_t pos = s->glines[l].line[C].pos;
2761  int y = offset_y + (s->mirror ? s->size - 1 - pos: pos) - 10;
2762 
2763  if (y < 0)
2764  y = 4;
2765 
2766  draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, s->grat_yuva_color);
2767  }
2768 
2769  offset_y += s->size * (s->display == STACK);
2770  offset_x += width * (s->display == PARADE);
2771  }
2772 }
2773 
2775 {
2776  AVFilterContext *ctx = inlink->dst;
2777  WaveformContext *s = ctx->priv;
2778 
2779  s->desc = av_pix_fmt_desc_get(inlink->format);
2780  s->ncomp = s->desc->nb_components;
2781  s->bits = s->desc->comp[0].depth;
2782  s->max = 1 << s->bits;
2783  s->intensity = s->fintensity * (s->max - 1);
2784 
2785  s->shift_w[0] = s->shift_w[3] = 0;
2786  s->shift_h[0] = s->shift_h[3] = 0;
2787  s->shift_w[1] = s->shift_w[2] = s->desc->log2_chroma_w;
2788  s->shift_h[1] = s->shift_h[2] = s->desc->log2_chroma_h;
2789 
2791 
2792  switch (s->filter) {
2793  case XFLAT:
2794  case AFLAT: s->size = 256 * 2; break;
2795  case FLAT: s->size = 256 * 3; break;
2796  default: s->size = 256; break;
2797  }
2798 
2799  switch (s->filter | ((s->bits > 8) << 4) |
2800  (s->mode << 8) | (s->mirror << 12)) {
2801  case 0x1100: s->waveform_slice = lowpass_column_mirror; break;
2802  case 0x1000: s->waveform_slice = lowpass_row_mirror; break;
2803  case 0x0100: s->waveform_slice = lowpass_column; break;
2804  case 0x0000: s->waveform_slice = lowpass_row; break;
2805  case 0x1110: s->waveform_slice = lowpass16_column_mirror; break;
2806  case 0x1010: s->waveform_slice = lowpass16_row_mirror; break;
2807  case 0x0110: s->waveform_slice = lowpass16_column; break;
2808  case 0x0010: s->waveform_slice = lowpass16_row; break;
2809  case 0x1101: s->waveform_slice = flat_column_mirror; break;
2810  case 0x1001: s->waveform_slice = flat_row_mirror; break;
2811  case 0x0101: s->waveform_slice = flat_column; break;
2812  case 0x0001: s->waveform_slice = flat_row; break;
2813  case 0x1111: s->waveform_slice = flat16_column_mirror; break;
2814  case 0x1011: s->waveform_slice = flat16_row_mirror; break;
2815  case 0x0111: s->waveform_slice = flat16_column; break;
2816  case 0x0011: s->waveform_slice = flat16_row; break;
2817  case 0x1102: s->waveform_slice = aflat_column_mirror; break;
2818  case 0x1002: s->waveform_slice = aflat_row_mirror; break;
2819  case 0x0102: s->waveform_slice = aflat_column; break;
2820  case 0x0002: s->waveform_slice = aflat_row; break;
2821  case 0x1112: s->waveform_slice = aflat16_column_mirror; break;
2822  case 0x1012: s->waveform_slice = aflat16_row_mirror; break;
2823  case 0x0112: s->waveform_slice = aflat16_column; break;
2824  case 0x0012: s->waveform_slice = aflat16_row; break;
2825  case 0x1103: s->waveform_slice = chroma_column_mirror; break;
2826  case 0x1003: s->waveform_slice = chroma_row_mirror; break;
2827  case 0x0103: s->waveform_slice = chroma_column; break;
2828  case 0x0003: s->waveform_slice = chroma_row; break;
2829  case 0x1113: s->waveform_slice = chroma16_column_mirror; break;
2830  case 0x1013: s->waveform_slice = chroma16_row_mirror; break;
2831  case 0x0113: s->waveform_slice = chroma16_column; break;
2832  case 0x0013: s->waveform_slice = chroma16_row; break;
2833  case 0x1104: s->waveform_slice = color_column_mirror; break;
2834  case 0x1004: s->waveform_slice = color_row_mirror; break;
2835  case 0x0104: s->waveform_slice = color_column; break;
2836  case 0x0004: s->waveform_slice = color_row; break;
2837  case 0x1114: s->waveform_slice = color16_column_mirror; break;
2838  case 0x1014: s->waveform_slice = color16_row_mirror; break;
2839  case 0x0114: s->waveform_slice = color16_column; break;
2840  case 0x0014: s->waveform_slice = color16_row; break;
2841  case 0x1105: s->waveform_slice = acolor_column_mirror; break;
2842  case 0x1005: s->waveform_slice = acolor_row_mirror; break;
2843  case 0x0105: s->waveform_slice = acolor_column; break;
2844  case 0x0005: s->waveform_slice = acolor_row; break;
2845  case 0x1115: s->waveform_slice = acolor16_column_mirror; break;
2846  case 0x1015: s->waveform_slice = acolor16_row_mirror; break;
2847  case 0x0115: s->waveform_slice = acolor16_column; break;
2848  case 0x0015: s->waveform_slice = acolor16_row; break;
2849  case 0x1106: s->waveform_slice = xflat_column_mirror; break;
2850  case 0x1006: s->waveform_slice = xflat_row_mirror; break;
2851  case 0x0106: s->waveform_slice = xflat_column; break;
2852  case 0x0006: s->waveform_slice = xflat_row; break;
2853  case 0x1116: s->waveform_slice = xflat16_column_mirror; break;
2854  case 0x1016: s->waveform_slice = xflat16_row_mirror; break;
2855  case 0x0116: s->waveform_slice = xflat16_column; break;
2856  case 0x0016: s->waveform_slice = xflat16_row; break;
2857  }
2858 
2859  s->grat_yuva_color[0] = 255;
2860  s->grat_yuva_color[2] = s->graticule == 2 ? 255 : 0;
2861  s->grat_yuva_color[3] = 255;
2862 
2863  switch (s->filter) {
2864  case LOWPASS:
2865  case COLOR:
2866  case ACOLOR:
2867  case CHROMA:
2868  case AFLAT:
2869  case XFLAT:
2870  case FLAT:
2871  if (s->graticule && s->mode == 1)
2873  else if (s->graticule && s->mode == 0)
2874  s->graticulef = s->bits > 8 ? graticule16_row : graticule_row;
2875  break;
2876  }
2877 
2878  switch (s->filter) {
2879  case COLOR:
2880  case ACOLOR:
2881  case LOWPASS:
2882  switch (s->scale) {
2883  case DIGITAL:
2884  switch (s->bits) {
2885  case 8: s->glines = (GraticuleLines *)digital8; s->nb_glines = FF_ARRAY_ELEMS(digital8); break;
2886  case 9: s->glines = (GraticuleLines *)digital9; s->nb_glines = FF_ARRAY_ELEMS(digital9); break;
2887  case 10: s->glines = (GraticuleLines *)digital10; s->nb_glines = FF_ARRAY_ELEMS(digital10); break;
2888  case 12: s->glines = (GraticuleLines *)digital12; s->nb_glines = FF_ARRAY_ELEMS(digital12); break;
2889  }
2890  break;
2891  case MILLIVOLTS:
2892  switch (s->bits) {
2893  case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
2894  case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
2895  case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
2896  case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
2897  }
2898  break;
2899  case IRE:
2900  switch (s->bits) {
2901  case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
2902  case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
2903  case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
2904  case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
2905  }
2906  break;
2907  }
2908  break;
2909  case CHROMA:
2910  switch (s->scale) {
2911  case DIGITAL:
2912  switch (s->bits) {
2913  case 8: s->glines = (GraticuleLines *)chroma_digital8; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital8); break;
2914  case 9: s->glines = (GraticuleLines *)chroma_digital9; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital9); break;
2915  case 10: s->glines = (GraticuleLines *)chroma_digital10; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital10); break;
2916  case 12: s->glines = (GraticuleLines *)chroma_digital12; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital12); break;
2917  }
2918  break;
2919  case MILLIVOLTS:
2920  switch (s->bits) {
2921  case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
2922  case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
2923  case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
2924  case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
2925  }
2926  break;
2927  case IRE:
2928  switch (s->bits) {
2929  case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
2930  case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
2931  case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
2932  case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
2933  }
2934  break;
2935  }
2936  break;
2937  case XFLAT:
2938  case AFLAT:
2939  switch (s->scale) {
2940  case DIGITAL:
2941  switch (s->bits) {
2942  case 8: s->glines = (GraticuleLines *)aflat_digital8; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital8); break;
2943  case 9: s->glines = (GraticuleLines *)aflat_digital9; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital9); break;
2944  case 10: s->glines = (GraticuleLines *)aflat_digital10; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital10); break;
2945  case 12: s->glines = (GraticuleLines *)aflat_digital12; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital12); break;
2946  }
2947  break;
2948  case MILLIVOLTS:
2949  switch (s->bits) {
2950  case 8: s->glines = (GraticuleLines *)aflat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts8); break;
2951  case 9: s->glines = (GraticuleLines *)aflat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts9); break;
2952  case 10: s->glines = (GraticuleLines *)aflat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts10); break;
2953  case 12: s->glines = (GraticuleLines *)aflat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts12); break;
2954  }
2955  break;
2956  case IRE:
2957  switch (s->bits) {
2958  case 8: s->glines = (GraticuleLines *)aflat_ire8; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire8); break;
2959  case 9: s->glines = (GraticuleLines *)aflat_ire9; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire9); break;
2960  case 10: s->glines = (GraticuleLines *)aflat_ire10; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire10); break;
2961  case 12: s->glines = (GraticuleLines *)aflat_ire12; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire12); break;
2962  }
2963  break;
2964  }
2965  break;
2966  case FLAT:
2967  switch (s->scale) {
2968  case DIGITAL:
2969  switch (s->bits) {
2970  case 8: s->glines = (GraticuleLines *)flat_digital8; s->nb_glines = FF_ARRAY_ELEMS(flat_digital8); break;
2971  case 9: s->glines = (GraticuleLines *)flat_digital9; s->nb_glines = FF_ARRAY_ELEMS(flat_digital9); break;
2972  case 10: s->glines = (GraticuleLines *)flat_digital10; s->nb_glines = FF_ARRAY_ELEMS(flat_digital10); break;
2973  case 12: s->glines = (GraticuleLines *)flat_digital12; s->nb_glines = FF_ARRAY_ELEMS(flat_digital12); break;
2974  }
2975  break;
2976  case MILLIVOLTS:
2977  switch (s->bits) {
2978  case 8: s->glines = (GraticuleLines *)flat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts8); break;
2979  case 9: s->glines = (GraticuleLines *)flat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts9); break;
2980  case 10: s->glines = (GraticuleLines *)flat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts10); break;
2981  case 12: s->glines = (GraticuleLines *)flat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts12); break;
2982  }
2983  break;
2984  case IRE:
2985  switch (s->bits) {
2986  case 8: s->glines = (GraticuleLines *)flat_ire8; s->nb_glines = FF_ARRAY_ELEMS(flat_ire8); break;
2987  case 9: s->glines = (GraticuleLines *)flat_ire9; s->nb_glines = FF_ARRAY_ELEMS(flat_ire9); break;
2988  case 10: s->glines = (GraticuleLines *)flat_ire10; s->nb_glines = FF_ARRAY_ELEMS(flat_ire10); break;
2989  case 12: s->glines = (GraticuleLines *)flat_ire12; s->nb_glines = FF_ARRAY_ELEMS(flat_ire12); break;
2990  }
2991  break;
2992  }
2993  break;
2994  }
2995 
2996  s->size = s->size << (s->bits - 8);
2997 
2998  switch (inlink->format) {
2999  case AV_PIX_FMT_GBRAP:
3000  case AV_PIX_FMT_GBRP:
3001  case AV_PIX_FMT_GBRP9:
3002  case AV_PIX_FMT_GBRP10:
3003  case AV_PIX_FMT_GBRP12:
3004  s->rgb = 1;
3005  memcpy(s->bg_color, black_gbrp_color, sizeof(s->bg_color));
3006  break;
3007  default:
3008  memcpy(s->bg_color, black_yuva_color, sizeof(s->bg_color));
3009  }
3010 
3011  s->bg_color[3] *= s->bgopacity;
3012 
3013  return 0;
3014 }
3015 
3016 static int config_output(AVFilterLink *outlink)
3017 {
3018  AVFilterContext *ctx = outlink->src;
3019  AVFilterLink *inlink = ctx->inputs[0];
3020  WaveformContext *s = ctx->priv;
3021  int comp = 0, i, j = 0, k, p, size;
3022 
3023  for (i = 0; i < s->ncomp; i++) {
3024  if ((1 << i) & s->pcomp)
3025  comp++;
3026  }
3027  s->acomp = comp;
3028  if (s->acomp == 0)
3029  return AVERROR(EINVAL);
3030 
3031  s->odesc = av_pix_fmt_desc_get(outlink->format);
3032  s->dcomp = s->odesc->nb_components;
3033 
3034  av_freep(&s->peak);
3035 
3036  if (s->mode) {
3037  outlink->h = s->size * FFMAX(comp * (s->display == STACK), 1);
3038  outlink->w = inlink->w * FFMAX(comp * (s->display == PARADE), 1);
3039  size = inlink->w;
3040  } else {
3041  outlink->w = s->size * FFMAX(comp * (s->display == STACK), 1);
3042  outlink->h = inlink->h * FFMAX(comp * (s->display == PARADE), 1);
3043  size = inlink->h;
3044  }
3045 
3046  s->peak = av_malloc_array(size, 32 * sizeof(*s->peak));
3047  if (!s->peak)
3048  return AVERROR(ENOMEM);
3049 
3050  for (p = 0; p < s->ncomp; p++) {
3051  const int plane = s->desc->comp[p].plane;
3052  int offset;
3053 
3054  if (!((1 << p) & s->pcomp))
3055  continue;
3056 
3057  for (k = 0; k < 4; k++) {
3058  s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0);
3059  s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16);
3060  }
3061 
3062  offset = j++ * s->size * (s->display == STACK);
3063  s->estart[plane] = offset;
3064  s->eend[plane] = (offset + s->size - 1);
3065  for (i = 0; i < size; i++) {
3066  for (k = 0; k < 4; k++) {
3067  s->emax[plane][k][i] = s->estart[plane];
3068  s->emin[plane][k][i] = s->eend[plane];
3069  }
3070  }
3071  }
3072 
3073  outlink->sample_aspect_ratio = (AVRational){1,1};
3074 
3075  return 0;
3076 }
3077 
3079 {
3080  AVFilterContext *ctx = inlink->dst;
3081  WaveformContext *s = ctx->priv;
3082  AVFilterLink *outlink = ctx->outputs[0];
3083  AVFrame *out;
3084  int i, j, k;
3085 
3086  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
3087  if (!out) {
3088  av_frame_free(&in);
3089  return AVERROR(ENOMEM);
3090  }
3091  out->pts = in->pts;
3093 
3094  for (k = 0; k < s->dcomp; k++) {
3095  if (s->bits <= 8) {
3096  for (i = 0; i < outlink->h ; i++)
3097  memset(out->data[s->odesc->comp[k].plane] +
3098  i * out->linesize[s->odesc->comp[k].plane],
3099  s->bg_color[k], outlink->w);
3100  } else {
3101  const int mult = s->max / 256;
3102  uint16_t *dst = (uint16_t *)out->data[s->odesc->comp[k].plane];
3103 
3104  for (i = 0; i < outlink->h ; i++) {
3105  for (j = 0; j < outlink->w; j++)
3106  dst[j] = s->bg_color[k] * mult;
3107  dst += out->linesize[s->odesc->comp[k].plane] / 2;
3108  }
3109  }
3110  }
3111 
3112  for (k = 0, i = 0; k < s->ncomp; k++) {
3113  if ((1 << k) & s->pcomp) {
3114  const int plane = s->desc->comp[k].plane;
3115  ThreadData td;
3116  int offset_y;
3117  int offset_x;
3118 
3119  if (s->display == PARADE) {
3120  offset_x = s->mode ? i++ * inlink->w : 0;
3121  offset_y = s->mode ? 0 : i++ * inlink->h;
3122  } else {
3123  offset_y = s->mode ? i++ * s->size * !!s->display : 0;
3124  offset_x = s->mode ? 0 : i++ * s->size * !!s->display;
3125  }
3126 
3127  td.in = in;
3128  td.out = out;
3129  td.component = k;
3130  td.offset_y = offset_y;
3131  td.offset_x = offset_x;
3132  ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx));
3133  switch (s->filter) {
3134  case ACOLOR:
3135  case CHROMA:
3136  case COLOR:
3137  case LOWPASS:
3138  if (s->bits <= 8)
3139  envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
3140  else
3141  envelope16(s, out, plane, plane, s->mode ? offset_x : offset_y);
3142  break;
3143  case FLAT:
3144  if (s->bits <= 8) {
3145  envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
3146  envelope(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
3147  } else {
3148  envelope16(s, out, plane, plane, s->mode ? offset_x : offset_y);
3149  envelope16(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
3150  }
3151  break;
3152  case AFLAT:
3153  case XFLAT:
3154  if (s->bits <= 8) {
3155  envelope(s, out, plane, (plane + 0) % s->ncomp, s->mode ? offset_x : offset_y);
3156  envelope(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
3157  envelope(s, out, plane, (plane + 2) % s->ncomp, s->mode ? offset_x : offset_y);
3158  } else {
3159  envelope16(s, out, plane, (plane + 0) % s->ncomp, s->mode ? offset_x : offset_y);
3160  envelope16(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
3161  envelope16(s, out, plane, (plane + 2) % s->ncomp, s->mode ? offset_x : offset_y);
3162  }
3163  break;
3164  }
3165  }
3166  }
3167  s->graticulef(s, out);
3168 
3169  av_frame_free(&in);
3170  return ff_filter_frame(outlink, out);
3171 }
3172 
3174 {
3175  WaveformContext *s = ctx->priv;
3176 
3177  av_freep(&s->peak);
3178 }
3179 
3180 static const AVFilterPad inputs[] = {
3181  {
3182  .name = "default",
3183  .type = AVMEDIA_TYPE_VIDEO,
3184  .filter_frame = filter_frame,
3185  .config_props = config_input,
3186  },
3187  { NULL }
3188 };
3189 
3190 static const AVFilterPad outputs[] = {
3191  {
3192  .name = "default",
3193  .type = AVMEDIA_TYPE_VIDEO,
3194  .config_props = config_output,
3195  },
3196  { NULL }
3197 };
3198 
3200  .name = "waveform",
3201  .description = NULL_IF_CONFIG_SMALL("Video waveform monitor."),
3202  .priv_size = sizeof(WaveformContext),
3203  .priv_class = &waveform_class,
3205  .uninit = uninit,
3206  .inputs = inputs,
3207  .outputs = outputs,
3209 };
int plane
Which of the 4 planes contains the component.
Definition: pixdesc.h:35
static const GraticuleLines aflat_digital10[]
Definition: vf_waveform.c:2162
#define NULL
Definition: coverity.c:32
AVFrame * out
Definition: af_adeclick.c:488
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:422
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:424
#define CHROMA_FUNC(name, column, mirror)
Definition: vf_waveform.c:1590
static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:596
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:407
static av_always_inline void acolor16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1880
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:425
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
Main libavfilter public API header.
static const GraticuleLines digital8[]
Definition: vf_waveform.c:2342
static const GraticuleLines aflat_ire9[]
Definition: vf_waveform.c:2216
#define CHROMA16_FUNC(name, column, mirror)
Definition: vf_waveform.c:1486
static int config_input(AVFilterLink *inlink)
Definition: vf_waveform.c:2774
#define FLAT16_FUNC(name, column, mirror)
Definition: vf_waveform.c:959
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:403
static const GraticuleLines flat_millivolts10[]
Definition: vf_waveform.c:2286
static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step)
Definition: vf_waveform.c:2473
static void update(uint8_t *target, int max, int intensity)
Definition: vf_waveform.c:626
static int config_output(AVFilterLink *outlink)
Definition: vf_waveform.c:3016
static enum AVPixelFormat in_color_pix_fmts[]
Definition: vf_waveform.c:189
static enum AVPixelFormat in_lowpass_pix_fmts[]
Definition: vf_waveform.c:171
static const GraticuleLines ire12[]
Definition: vf_waveform.c:2422
static const AVFilterPad inputs[]
Definition: vf_waveform.c:3180
static av_always_inline void acolor(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:2014
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:367
static const GraticuleLines flat_millivolts12[]
Definition: vf_waveform.c:2294
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:391
static const GraticuleLines aflat_millivolts9[]
Definition: vf_waveform.c:2182
static const GraticuleLines ire10[]
Definition: vf_waveform.c:2414
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
static const GraticuleLines flat_ire9[]
Definition: vf_waveform.c:2312
static const GraticuleLines chroma_digital8[]
Definition: vf_waveform.c:2430
static enum AVPixelFormat out_yuv9_lowpass_pix_fmts[]
Definition: vf_waveform.c:246
static enum AVPixelFormat in_flat_pix_fmts[]
Definition: vf_waveform.c:206
static void graticule16_row(WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:2649
#define ACOLOR_FUNC(name, column, mirror)
Definition: vf_waveform.c:2122
static const GraticuleLines flat_ire12[]
Definition: vf_waveform.c:2332
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static const GraticuleLines aflat_digital12[]
Definition: vf_waveform.c:2168
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:368
static enum AVPixelFormat out_gray9_lowpass_pix_fmts[]
Definition: vf_waveform.c:266
const char * name
Pad name.
Definition: internal.h:60
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:369
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define FLAGS
Definition: vf_waveform.c:115
FilterType
uint8_t grat_yuva_color[4]
Definition: vf_waveform.c:101
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:82
#define LOWPASS16_FUNC(name, column, mirror)
Definition: vf_waveform.c:712
void(* graticulef)(struct WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:109
AVOptions.
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
static int query_formats(AVFilterContext *ctx)
Definition: vf_waveform.c:288
static const uint8_t black_gbrp_color[4]
Definition: vf_waveform.c:2148
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
#define ACOLOR16_FUNC(name, column, mirror)
Definition: vf_waveform.c:1989
static const GraticuleLines aflat_millivolts10[]
Definition: vf_waveform.c:2190
int offset_y
Definition: vf_waveform.c:36
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:421
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:402
static void blend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step)
Definition: vf_waveform.c:2462
int height
Definition: vf_avgblur.c:61
static void graticule_row(WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:2608
static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
Definition: vf_waveform.c:2579
#define LOWPASS_FUNC(name, column, mirror)
Definition: vf_waveform.c:820
#define AFLAT(name, update_cr, column, mirror)
Definition: vf_waveform.c:1255
AVFilter ff_vf_waveform
Definition: vf_waveform.c:3199
AVFrame * dst
Definition: vf_blend.c:55
int plane
Definition: vf_blend.c:57
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range...
Definition: pixfmt.h:100
static void update16(uint16_t *target, int max, int intensity, int limit)
Definition: vf_waveform.c:618
static av_always_inline void lowpass(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:737
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:79
int linesize
Definition: vf_avgblur.c:64
ptrdiff_t size
Definition: opengl_enc.c:100
static const GraticuleLines chroma_digital10[]
Definition: vf_waveform.c:2446
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:392
static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step)
Definition: vf_waveform.c:2493
A filter pad used for either input or output.
Definition: internal.h:54
static enum AVPixelFormat out_gray8_lowpass_pix_fmts[]
Definition: vf_waveform.c:261
static const GraticuleLines flat_digital9[]
Definition: vf_waveform.c:2252
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int width
Definition: frame.h:353
#define td
Definition: regdef.h:70
int step
Definition: vf_remap.c:77
const uint8_t avpriv_cga_font[2048]
Definition: xga_font_data.c:29
static const GraticuleLines aflat_ire10[]
Definition: vf_waveform.c:2226
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
DisplayType
Definition: vf_waveform.c:51
static enum AVPixelFormat out_yuv12_lowpass_pix_fmts[]
Definition: vf_waveform.c:256
static void mirror(const float *modifier, float *vec)
Definition: vf_v360.c:1705
struct GraticuleLine line[4]
Definition: vf_waveform.c:71
AVFILTER_DEFINE_CLASS(waveform)
static av_always_inline void chroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1511
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:148
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
ScaleType
Definition: vf_waveform.c:58
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
static av_always_inline void flat16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:845
static const GraticuleLines flat_digital10[]
Definition: vf_waveform.c:2258
void * priv
private data for use by the filter
Definition: avfilter.h:353
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: frame.h:539
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:116
const char * arg
Definition: jacosubdec.c:66
Definition: graph2dot.c:48
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:408
simple assert() macros that are a bit more flexible than ISO C assert().
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:390
static enum AVPixelFormat in_pix_fmts[]
Definition: vf_ciescope.c:124
static void graticule_none(WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:2604
#define FFMAX(a, b)
Definition: common.h:94
static const GraticuleLines ire8[]
Definition: vf_waveform.c:2398
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:457
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:385
#define OFFSET(x)
Definition: vf_waveform.c:114
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
static const GraticuleLines millivolts12[]
Definition: vf_waveform.c:2390
static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step)
Definition: vf_waveform.c:2484
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:55
#define FFMIN(a, b)
Definition: common.h:96
static enum AVPixelFormat out_gray12_lowpass_pix_fmts[]
Definition: vf_waveform.c:276
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
Definition: vf_waveform.c:2502
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static enum AVPixelFormat flat_pix_fmts[]
Definition: vf_waveform.c:281
static av_always_inline void color16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1615
uint16_t pos
Definition: vf_waveform.c:67
AVFormatContext * ctx
Definition: movenc.c:48
int offset_x
Definition: vf_waveform.c:37
static const GraticuleLines flat_digital8[]
Definition: vf_waveform.c:2246
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
static const GraticuleLines aflat_digital9[]
Definition: vf_waveform.c:2156
unsigned nb_formats
number of formats
Definition: formats.h:65
static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:410
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:426
int * emax[4][4]
Definition: vf_waveform.c:92
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:386
#define FF_ARRAY_ELEMS(a)
the normal 2^n-1 "JPEG" YUV ranges
Definition: pixfmt.h:522
static enum AVPixelFormat out_yuv10_lowpass_pix_fmts[]
Definition: vf_waveform.c:251
if(ret)
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
const char * name
Definition: vf_waveform.c:66
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:83
static void update_cr(uint8_t *target, int unused, int intensity)
Definition: vf_waveform.c:634
static const AVOption waveform_options[]
Definition: vf_waveform.c:117
static const GraticuleLines aflat_digital8[]
Definition: vf_waveform.c:2150
static const GraticuleLines flat_ire8[]
Definition: vf_waveform.c:2302
Used for passing data between threads.
Definition: af_adeclick.c:487
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
static const GraticuleLines chroma_digital9[]
Definition: vf_waveform.c:2438
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
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:3190
static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
Definition: vf_waveform.c:2554
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_waveform.c:3173
static const GraticuleLines aflat_millivolts12[]
Definition: vf_waveform.c:2198
GraticuleLines * glines
Definition: vf_waveform.c:103
static av_always_inline void chroma16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1405
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:387
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
static enum AVPixelFormat out_yuv8_lowpass_pix_fmts[]
Definition: vf_waveform.c:241
static enum AVPixelFormat out_rgb9_lowpass_pix_fmts[]
Definition: vf_waveform.c:226
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
AVFrame * mask
static void update16_cr(uint16_t *target, int unused, int intensity, int limit)
Definition: vf_waveform.c:642
Rational number (pair of numerator and denominator).
Definition: rational.h:58
#define FLAT_FUNC(name, column, mirror)
Definition: vf_waveform.c:1096
static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:362
#define COLOR16_FUNC(name, column, mirror)
Definition: vf_waveform.c:1723
const char * name
Filter name.
Definition: avfilter.h:148
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:393
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:384
static const GraticuleLines flat_digital12[]
Definition: vf_waveform.c:2264
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
int * emin[4][4]
Definition: vf_waveform.c:93
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:404
static const GraticuleLines millivolts8[]
Definition: vf_waveform.c:2366
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:378
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:388
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:394
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
static const GraticuleLines digital12[]
Definition: vf_waveform.c:2360
uint8_t bg_color[4]
Definition: vf_waveform.c:81
int
static enum AVPixelFormat out_rgb12_lowpass_pix_fmts[]
Definition: vf_waveform.c:236
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
static av_always_inline void flat(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:984
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
static const GraticuleLines millivolts10[]
Definition: vf_waveform.c:2382
static const GraticuleLines aflat_ire12[]
Definition: vf_waveform.c:2236
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:423
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
static const GraticuleLines digital9[]
Definition: vf_waveform.c:2348
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
static enum AVPixelFormat out_pix_fmts[]
Definition: vf_ciescope.c:133
static av_always_inline void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:650
avfilter_execute_func * execute
Definition: internal.h:155
static const GraticuleLines digital10[]
Definition: vf_waveform.c:2354
static const GraticuleLines flat_ire10[]
Definition: vf_waveform.c:2322
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_waveform.c:3078
static void graticule_column(WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:2691
static const uint8_t black_yuva_color[4]
Definition: vf_waveform.c:2147
static void graticule16_column(WaveformContext *s, AVFrame *out)
Definition: vf_waveform.c:2732
const AVPixFmtDescriptor * odesc
Definition: vf_waveform.c:111
const AVPixFmtDescriptor * desc
Definition: vf_tonemap.c:196
int(* waveform_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_waveform.c:107
static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:527
A list of supported formats for one end of a filter link.
Definition: formats.h:64
#define AFLAT16(name, update_cr, column, mirror)
Definition: vf_waveform.c:1121
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
int component
Definition: vf_waveform.c:35
static const GraticuleLines flat_millivolts8[]
Definition: vf_waveform.c:2270
An instance of a filter.
Definition: avfilter.h:338
static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
Definition: vf_waveform.c:2528
int height
Definition: frame.h:353
#define av_freep(p)
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
void INT64 start
Definition: avisynth_c.h:766
#define av_always_inline
Definition: attributes.h:39
#define av_malloc_array(a, b)
AVFrame * in
Definition: af_afftdn.c:1082
static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
Definition: vf_waveform.c:607
static const GraticuleLines ire9[]
Definition: vf_waveform.c:2406
static const GraticuleLines chroma_digital12[]
Definition: vf_waveform.c:2454
static const GraticuleLines flat_millivolts9[]
Definition: vf_waveform.c:2278
AVFilterLink * inlink
Definition: vf_blend.c:56
internal API functions
static enum AVPixelFormat out_gray10_lowpass_pix_fmts[]
Definition: vf_waveform.c:271
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int depth
Number of bits in the component.
Definition: pixdesc.h:58
static const GraticuleLines aflat_ire8[]
Definition: vf_waveform.c:2206
static enum AVPixelFormat out_rgb8_lowpass_pix_fmts[]
Definition: vf_waveform.c:221
const AVPixFmtDescriptor * desc
Definition: vf_waveform.c:110
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int src_linesize
Definition: vf_bm3d.c:57
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
static const GraticuleLines millivolts9[]
Definition: vf_waveform.c:2374
for(j=16;j >0;--j)
#define COLOR_FUNC(name, column, mirror)
Definition: vf_waveform.c:1855
static const GraticuleLines aflat_millivolts8[]
Definition: vf_waveform.c:2174
CGA/EGA/VGA ROM font data.
static enum AVPixelFormat out_rgb10_lowpass_pix_fmts[]
Definition: vf_waveform.c:231
AVFrame * max
Definition: vf_threshold.c:75
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
const char * name
Definition: opengl_enc.c:102
int * formats
list of media formats
Definition: formats.h:66