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