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