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