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