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