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