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