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