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