FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_waveform.c
Date: 2026-09-24 20:08:24
Exec Total Coverage
Lines: 298 1659 18.0%
Functions: 13 110 11.8%
Branches: 168 1715 9.8%

Line Branch Exec Source
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"
25 #include "libavutil/xga_font_data.h"
26 #include "avfilter.h"
27 #include "filters.h"
28 #include "formats.h"
29 #include "video.h"
30
31 typedef struct ThreadData {
32 AVFrame *in;
33 AVFrame *out;
34 int component;
35 int offset_y;
36 int offset_x;
37 } ThreadData;
38
39 enum FitMode {
40 FM_NONE,
41 FM_SIZE,
42 NB_FITMODES
43 };
44
45 enum FilterType {
46 LOWPASS,
47 FLAT,
48 AFLAT,
49 CHROMA,
50 COLOR,
51 ACOLOR,
52 XFLAT,
53 YFLAT,
54 NB_FILTERS
55 };
56
57 enum DisplayType {
58 OVERLAY,
59 STACK,
60 PARADE,
61 NB_DISPLAYS
62 };
63
64 enum ScaleType {
65 DIGITAL,
66 MILLIVOLTS,
67 IRE,
68 NB_SCALES
69 };
70
71 enum GraticuleType {
72 GRAT_NONE,
73 GRAT_GREEN,
74 GRAT_ORANGE,
75 GRAT_INVERT,
76 NB_GRATICULES
77 };
78
79 typedef struct GraticuleLine {
80 char name[6];
81 uint16_t pos;
82 } GraticuleLine;
83
84 typedef struct GraticuleLines {
85 struct GraticuleLine line[4];
86 } GraticuleLines;
87
88 typedef struct WaveformContext {
89 const AVClass *class;
90 int mode;
91 int acomp;
92 int dcomp;
93 int ncomp;
94 int pcomp;
95 uint8_t bg_color[4];
96 float fintensity;
97 int intensity;
98 int mirror;
99 int display;
100 int envelope;
101 int graticule;
102 float opacity;
103 float bgopacity;
104 int estart[4];
105 int eend[4];
106 int *emax[4][4];
107 int *emin[4][4];
108 int *peak;
109 int filter;
110 int flags;
111 int bits;
112 int max;
113 int size;
114 int scale;
115 uint8_t grat_yuva_color[4];
116 int shift_w[4], shift_h[4];
117 const GraticuleLines *glines;
118 int nb_glines;
119 int rgb;
120 float ftint[2];
121 int tint[2];
122 int fitmode;
123 int input;
124
125 int (*waveform_slice)(AVFilterContext *ctx, void *arg,
126 int jobnr, int nb_jobs);
127 void (*graticulef)(struct WaveformContext *s, AVFrame *out);
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]);
133 const AVPixFmtDescriptor *desc;
134 const AVPixFmtDescriptor *odesc;
135 } WaveformContext;
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
141 static 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
206 AVFILTER_DEFINE_CLASS(waveform);
207
208 static const enum AVPixelFormat in_lowpass_pix_fmts[] = {
209 AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
210 AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
211 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
212 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
213 AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
214 AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
215 AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
216 AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
217 AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12,
218 AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
219 AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
220 AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
221 AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
222 AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
223 AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12,
224 AV_PIX_FMT_NONE
225 };
226
227 static const enum AVPixelFormat in_color_pix_fmts[] = {
228 AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
229 AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
230 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
231 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
232 AV_PIX_FMT_YUV411P,
233 AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
234 AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
235 AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
236 AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
237 AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
238 AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
239 AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
240 AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
241 AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12,
242 AV_PIX_FMT_NONE
243 };
244
245 static const enum AVPixelFormat in_flat_pix_fmts[] = {
246 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
247 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
248 AV_PIX_FMT_YUV411P,
249 AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
250 AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
251 AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
252 AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
253 AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
254 AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
255 AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
256 AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
257 AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12,
258 AV_PIX_FMT_NONE
259 };
260
261 static const enum AVPixelFormat out_rgb8_lowpass_pix_fmts[] = {
262 AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
263 AV_PIX_FMT_NONE
264 };
265
266 static const enum AVPixelFormat out_rgb9_lowpass_pix_fmts[] = {
267 AV_PIX_FMT_GBRP9,
268 AV_PIX_FMT_NONE
269 };
270
271 static const enum AVPixelFormat out_rgb10_lowpass_pix_fmts[] = {
272 AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
273 AV_PIX_FMT_NONE
274 };
275
276 static const enum AVPixelFormat out_rgb12_lowpass_pix_fmts[] = {
277 AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
278 AV_PIX_FMT_NONE
279 };
280
281 static const enum AVPixelFormat out_yuv8_lowpass_pix_fmts[] = {
282 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P,
283 AV_PIX_FMT_NONE
284 };
285
286 static const enum AVPixelFormat out_yuv9_lowpass_pix_fmts[] = {
287 AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9,
288 AV_PIX_FMT_NONE
289 };
290
291 static const enum AVPixelFormat out_yuv10_lowpass_pix_fmts[] = {
292 AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10,
293 AV_PIX_FMT_NONE
294 };
295
296 static const enum AVPixelFormat out_yuv12_lowpass_pix_fmts[] = {
297 AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUVA444P12,
298 AV_PIX_FMT_NONE
299 };
300
301 static const enum AVPixelFormat out_gray8_lowpass_pix_fmts[] = {
302 AV_PIX_FMT_GRAY8,
303 AV_PIX_FMT_NONE
304 };
305
306 static const enum AVPixelFormat out_gray9_lowpass_pix_fmts[] = {
307 AV_PIX_FMT_GRAY9,
308 AV_PIX_FMT_NONE
309 };
310
311 static const enum AVPixelFormat out_gray10_lowpass_pix_fmts[] = {
312 AV_PIX_FMT_GRAY10,
313 AV_PIX_FMT_NONE
314 };
315
316 static const enum AVPixelFormat out_gray12_lowpass_pix_fmts[] = {
317 AV_PIX_FMT_GRAY12,
318 AV_PIX_FMT_NONE
319 };
320
321 8 static int query_formats(AVFilterContext *ctx)
322 {
323 8 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
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (!ctx->inputs[0]->incfg.formats ||
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 !ctx->inputs[0]->incfg.formats->nb_formats) {
332 4 return AVERROR(EAGAIN);
333 }
334
335
1/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 switch (s->filter) {
336 4 case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break;
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
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!ctx->inputs[0]->outcfg.formats) {
348
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 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 4 avff = ctx->inputs[0]->incfg.formats;
353 4 avff2 = ctx->inputs[0]->outcfg.formats;
354 4 desc = av_pix_fmt_desc_get(avff->formats[0]);
355 4 desc2 = av_pix_fmt_desc_get(avff2->formats[0]);
356 4 ncomp = desc->nb_components;
357 4 ncomp2 = desc2->nb_components;
358 4 rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
359 4 depth = desc->comp[0].depth;
360 4 depth2 = desc2->comp[0].depth;
361
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (ncomp != ncomp2 || depth != depth2)
362 ✗ return AVERROR(EAGAIN);
363
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 for (i = 1; i < avff->nb_formats && !s->input; i++) {
364 ✗ desc = av_pix_fmt_desc_get(avff->formats[i]);
365 ✗ if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) ||
366 ✗ depth != desc->comp[0].depth)
367 ✗ return AVERROR(EAGAIN);
368 }
369
370
2/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 if (s->filter == LOWPASS && ncomp == 1 && depth == 8)
371 ✗ out_pix_fmts = out_gray8_lowpass_pix_fmts;
372
2/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (s->filter == LOWPASS && ncomp == 1 && depth == 9)
373 ✗ out_pix_fmts = out_gray9_lowpass_pix_fmts;
374
2/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (s->filter == LOWPASS && ncomp == 1 && depth == 10)
375 ✗ out_pix_fmts = out_gray10_lowpass_pix_fmts;
376
2/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (s->filter == LOWPASS && ncomp == 1 && depth == 12)
377 ✗ out_pix_fmts = out_gray12_lowpass_pix_fmts;
378
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (rgb && depth == 8 && ncomp > 2)
379 ✗ out_pix_fmts = out_rgb8_lowpass_pix_fmts;
380
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (rgb && depth == 9 && ncomp > 2)
381 ✗ out_pix_fmts = out_rgb9_lowpass_pix_fmts;
382
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (rgb && depth == 10 && ncomp > 2)
383 ✗ out_pix_fmts = out_rgb10_lowpass_pix_fmts;
384
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 else if (rgb && depth == 12 && ncomp > 2)
385 ✗ out_pix_fmts = out_rgb12_lowpass_pix_fmts;
386
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 else if (depth == 8 && ncomp > 2)
387 4 out_pix_fmts = out_yuv8_lowpass_pix_fmts;
388 ✗ else if (depth == 9 && ncomp > 2)
389 ✗ out_pix_fmts = out_yuv9_lowpass_pix_fmts;
390 ✗ else if (depth == 10 && ncomp > 2)
391 ✗ out_pix_fmts = out_yuv10_lowpass_pix_fmts;
392 ✗ else if (depth == 12 && ncomp > 2)
393 ✗ out_pix_fmts = out_yuv12_lowpass_pix_fmts;
394 else
395 ✗ return AVERROR(EAGAIN);
396
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if ((ret = ff_formats_ref(ff_make_pixel_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats)) < 0)
397 ✗ return ret;
398
399 4 return 0;
400 }
401
402 ✗ static 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
450 50 static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
451 {
452 50 const int dst_linesize = out->linesize[component];
453 50 const uint8_t bg = s->bg_color[component];
454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
456 50 const int start = s->estart[plane];
457 50 const int end = s->eend[plane];
458 uint8_t *dst;
459 int x, y;
460
461
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (s->mode) {
462
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 50 times.
17650 for (x = offset; x < offset + dst_w; x++) {
463
1/2
✓ Branch 0 taken 375540 times.
✗ Branch 1 not taken.
375540 for (y = start; y < end; y++) {
464 375540 dst = out->data[component] + y * dst_linesize + x;
465
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 357940 times.
375540 if (dst[0] != bg) {
466 17600 dst[0] = 255;
467 17600 break;
468 }
469 }
470
1/2
✓ Branch 0 taken 385656 times.
✗ Branch 1 not taken.
385656 for (y = end - 1; y >= start; y--) {
471 385656 dst = out->data[component] + y * dst_linesize + x;
472
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 368056 times.
385656 if (dst[0] != bg) {
473 17600 dst[0] = 255;
474 17600 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 50 }
496
497 ✗ static 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
567 50 static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
568 {
569 50 const int dst_linesize = out->linesize[component];
570 50 const int bg = s->bg_color[component];
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
573 50 const int start = s->estart[plane];
574 50 const int end = s->eend[plane];
575 50 int *emax = s->emax[plane][component];
576 50 int *emin = s->emin[plane][component];
577 uint8_t *dst;
578 int x, y;
579
580
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (s->mode) {
581
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 50 times.
17650 for (x = offset; x < offset + dst_w; x++) {
582
3/4
✓ Branch 0 taken 152559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 136288 times.
✓ Branch 3 taken 16271 times.
152559 for (y = start; y < end && y < emin[x - offset]; y++) {
583 136288 dst = out->data[component] + y * dst_linesize + x;
584
2/2
✓ Branch 0 taken 1329 times.
✓ Branch 1 taken 134959 times.
136288 if (dst[0] != bg) {
585 1329 emin[x - offset] = y;
586 1329 break;
587 }
588 }
589
3/4
✓ Branch 0 taken 159188 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144269 times.
✓ Branch 3 taken 14919 times.
159188 for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
590 144269 dst = out->data[component] + y * dst_linesize + x;
591
2/2
✓ Branch 0 taken 2681 times.
✓ Branch 1 taken 141588 times.
144269 if (dst[0] != bg) {
592 2681 emax[x - offset] = y;
593 2681 break;
594 }
595 }
596 }
597
598
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (s->envelope == 3)
599 50 envelope_instant(s, out, plane, component, offset);
600
601
2/2
✓ Branch 0 taken 17600 times.
✓ Branch 1 taken 50 times.
17650 for (x = offset; x < offset + dst_w; x++) {
602 17600 dst = out->data[component] + emin[x - offset] * dst_linesize + x;
603 17600 dst[0] = 255;
604 17600 dst = out->data[component] + emax[x - offset] * dst_linesize + x;
605 17600 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 50 }
635
636 ✗ static 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
647 250 static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
648 {
649
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 50 times.
250 if (s->envelope == 0) {
650 200 return;
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 } else if (s->envelope == 1) {
652 ✗ envelope_instant(s, out, plane, component, offset);
653 } else {
654 50 envelope_peak(s, out, plane, component, offset);
655 }
656 }
657
658 ✗ static 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
666 20275200 static void update(uint8_t *target, int max, int intensity)
667 {
668
1/2
✓ Branch 0 taken 20275200 times.
✗ Branch 1 not taken.
20275200 if (*target <= max)
669 20275200 *target += intensity;
670 else
671 ✗ *target = 255;
672 20275200 }
673
674 ✗ static 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
682 ✗ static 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
690 ✗ static av_always_inline void lowpass16(WaveformContext *s,
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) \
804 static 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
823 ✗ LOWPASS16_FUNC(column_mirror, 1, 1)
824 ✗ LOWPASS16_FUNC(column, 1, 0)
825 ✗ LOWPASS16_FUNC(row_mirror, 0, 1)
826 ✗ LOWPASS16_FUNC(row, 0, 0)
827
828 2250 static av_always_inline void lowpass(WaveformContext *s,
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 2250 const int plane = s->desc->comp[component].plane;
836
2/4
✓ Branch 0 taken 2250 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2250 times.
2250 const int dplane = (s->rgb || s->display == OVERLAY) ? plane : 0;
837 2250 const int shift_w = s->shift_w[component];
838 2250 const int shift_h = s->shift_h[component];
839 2250 const int src_linesize = in->linesize[plane];
840 2250 const int dst_linesize = out->linesize[dplane];
841
1/2
✓ Branch 0 taken 2250 times.
✗ Branch 1 not taken.
2250 const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
842 2250 const int max = 255 - intensity;
843 2250 const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
844 2250 const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
845
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 1800 times.
2250 const int sliceh_start = !column ? ff_slice_pos(src_h, jobnr, nb_jobs) : 0;
846
2/2
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 1800 times.
2250 const int sliceh_end = !column ? ff_slice_pos(src_h, jobnr + 1, nb_jobs) : src_h;
847
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 450 times.
2250 const int slicew_start = column ? ff_slice_pos(src_w, jobnr, nb_jobs) : 0;
848
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 450 times.
2250 const int slicew_end = column ? ff_slice_pos(src_w, jobnr + 1, nb_jobs) : src_w;
849
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 450 times.
2250 const int step = column ? 1 << shift_w : 1 << shift_h;
850 2250 const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize;
851 2250 uint8_t *dst_data = out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
852 2250 uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
853
1/2
✓ Branch 0 taken 2250 times.
✗ Branch 1 not taken.
2250 uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
854 const uint8_t *p;
855 int y;
856
857
3/4
✓ Branch 0 taken 450 times.
✓ Branch 1 taken 1800 times.
✓ Branch 2 taken 450 times.
✗ Branch 3 not taken.
2250 if (!column && mirror)
858 450 dst_data += s->size;
859
860
2/2
✓ Branch 0 taken 403200 times.
✓ Branch 1 taken 2250 times.
405450 for (y = sliceh_start; y < sliceh_end; y++) {
861 403200 const uint8_t *src_data_end = src_data + slicew_end;
862 403200 uint8_t *dst = dst_line + slicew_start * step;
863
864
2/2
✓ Branch 0 taken 17740800 times.
✓ Branch 1 taken 403200 times.
18144000 for (p = src_data + slicew_start; p < src_data_end; p++) {
865 uint8_t *target;
866 17740800 int i = 0;
867
868
2/2
✓ Branch 0 taken 12672000 times.
✓ Branch 1 taken 5068800 times.
17740800 if (column) {
869 do {
870 15206400 target = dst++ + dst_signed_linesize * *p;
871 15206400 update(target, max, intensity);
872
2/2
✓ Branch 0 taken 2534400 times.
✓ Branch 1 taken 12672000 times.
15206400 } while (++i < step);
873 } else {
874 5068800 uint8_t *row = dst_data;
875 do {
876
1/2
✓ Branch 0 taken 5068800 times.
✗ Branch 1 not taken.
5068800 if (mirror)
877 5068800 target = row - *p - 1;
878 else
879 ✗ target = row + *p;
880 5068800 update(target, max, intensity);
881 5068800 row += dst_linesize;
882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5068800 times.
5068800 } while (++i < step);
883 }
884 }
885 403200 src_data += src_linesize;
886 403200 dst_data += dst_linesize * step;
887 }
888
889
6/10
✓ Branch 0 taken 2250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1800 times.
✓ Branch 3 taken 450 times.
✓ Branch 4 taken 1800 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1800 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1800 times.
✗ Branch 9 not taken.
4050 if (s->display != OVERLAY && column && !s->rgb && out->data[1] && out->data[2]) {
890 1800 const int bg = s->bg_color[0];
891 1800 const int dst_h = 256;
892 1800 const int t0 = s->tint[0];
893 1800 const int t1 = s->tint[1];
894 uint8_t *dst0, *dst1;
895 const uint8_t *src;
896 int x;
897
898 1800 src = out->data[0] + offset_y * dst_linesize + offset_x;
899 1800 dst0 = out->data[1] + offset_y * dst_linesize + offset_x;
900 1800 dst1 = out->data[2] + offset_y * dst_linesize + offset_x;
901
2/2
✓ Branch 0 taken 460800 times.
✓ Branch 1 taken 1800 times.
462600 for (y = 0; y < dst_h; y++) {
902
2/2
✓ Branch 0 taken 18022400 times.
✓ Branch 1 taken 460800 times.
18483200 for (x = slicew_start * step; x < slicew_end * step; x++) {
903
2/2
✓ Branch 0 taken 8505880 times.
✓ Branch 1 taken 9516520 times.
18022400 if (src[x] != bg) {
904 8505880 dst0[x] = t0;
905 8505880 dst1[x] = t1;
906 }
907 }
908
909 460800 src += dst_linesize;
910 460800 dst0 += dst_linesize;
911 460800 dst1 += dst_linesize;
912 }
913
4/8
✓ Branch 0 taken 450 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 450 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 450 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 450 times.
✗ Branch 7 not taken.
450 } else if (s->display != OVERLAY && !s->rgb && out->data[1] && out->data[2]) {
914 450 const int bg = s->bg_color[0];
915 450 const int dst_w = 256;
916 450 const int t0 = s->tint[0];
917 450 const int t1 = s->tint[1];
918 uint8_t *dst0, *dst1;
919 const uint8_t *src;
920 int x;
921
922 450 src = out->data[0] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
923 450 dst0 = out->data[1] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
924 450 dst1 = out->data[2] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
925
2/2
✓ Branch 0 taken 14400 times.
✓ Branch 1 taken 450 times.
14850 for (y = sliceh_start * step; y < sliceh_end * step; y++) {
926
2/2
✓ Branch 0 taken 3686400 times.
✓ Branch 1 taken 14400 times.
3700800 for (x = 0; x < dst_w; x++) {
927
2/2
✓ Branch 0 taken 1616988 times.
✓ Branch 1 taken 2069412 times.
3686400 if (src[x] != bg) {
928 1616988 dst0[x] = t0;
929 1616988 dst1[x] = t1;
930 }
931 }
932
933 14400 src += dst_linesize;
934 14400 dst0 += dst_linesize;
935 14400 dst1 += dst_linesize;
936 }
937 }
938 2250 }
939
940 #define LOWPASS_FUNC(name, column, mirror) \
941 static 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
960 1800 LOWPASS_FUNC(column_mirror, 1, 1)
961 ✗ LOWPASS_FUNC(column, 1, 0)
962 450 LOWPASS_FUNC(row_mirror, 0, 1)
963 ✗ LOWPASS_FUNC(row, 0, 0)
964
965 ✗ static av_always_inline void flat16(WaveformContext *s,
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) \
1080 static 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
1099 ✗ FLAT16_FUNC(column_mirror, 1, 1)
1100 ✗ FLAT16_FUNC(column, 1, 0)
1101 ✗ FLAT16_FUNC(row_mirror, 0, 1)
1102 ✗ FLAT16_FUNC(row, 0, 0)
1103
1104 ✗ static av_always_inline void flat(WaveformContext *s,
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) \
1217 static 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
1236 ✗ FLAT_FUNC(column_mirror, 1, 1)
1237 ✗ FLAT_FUNC(column, 1, 0)
1238 ✗ FLAT_FUNC(row_mirror, 0, 1)
1239 ✗ FLAT_FUNC(row, 0, 0)
1240
1241 #define AFLAT16(name, update_cb, update_cr, column, mirror) \
1242 static 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) \
1376 static 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
1507 ✗ AFLAT16(aflat16_row, update16, update16, 0, 0)
1508 ✗ AFLAT16(aflat16_row_mirror, update16, update16, 0, 1)
1509 ✗ AFLAT16(aflat16_column, update16, update16, 1, 0)
1510 ✗ AFLAT16(aflat16_column_mirror, update16, update16, 1, 1)
1511 ✗ AFLAT16(xflat16_row, update16, update16_cr, 0, 0)
1512 ✗ AFLAT16(xflat16_row_mirror, update16, update16_cr, 0, 1)
1513 ✗ AFLAT16(xflat16_column, update16, update16_cr, 1, 0)
1514 ✗ AFLAT16(xflat16_column_mirror, update16, update16_cr, 1, 1)
1515 ✗ AFLAT16(yflat16_row, update16_cr, update16_cr, 0, 0)
1516 ✗ AFLAT16(yflat16_row_mirror, update16_cr, update16_cr, 0, 1)
1517 ✗ AFLAT16(yflat16_column, update16_cr, update16_cr, 1, 0)
1518 ✗ AFLAT16(yflat16_column_mirror, update16_cr, update16_cr, 1, 1)
1519
1520 ✗ AFLAT(aflat_row, update, update, 0, 0)
1521 ✗ AFLAT(aflat_row_mirror, update, update, 0, 1)
1522 ✗ AFLAT(aflat_column, update, update, 1, 0)
1523 ✗ AFLAT(aflat_column_mirror, update, update, 1, 1)
1524 ✗ AFLAT(xflat_row, update, update_cr, 0, 0)
1525 ✗ AFLAT(xflat_row_mirror, update, update_cr, 0, 1)
1526 ✗ AFLAT(xflat_column, update, update_cr, 1, 0)
1527 ✗ AFLAT(xflat_column_mirror, update, update_cr, 1, 1)
1528 ✗ AFLAT(yflat_row, update_cr, update_cr, 0, 0)
1529 ✗ AFLAT(yflat_row_mirror, update_cr, update_cr, 0, 1)
1530 ✗ AFLAT(yflat_column, update_cr, update_cr, 1, 0)
1531 ✗ AFLAT(yflat_column_mirror, update_cr, update_cr, 1, 1)
1532
1533 ✗ static av_always_inline void chroma16(WaveformContext *s,
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) \
1615 static 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
1634 ✗ CHROMA16_FUNC(column_mirror, 1, 1)
1635 ✗ CHROMA16_FUNC(column, 1, 0)
1636 ✗ CHROMA16_FUNC(row_mirror, 0, 1)
1637 ✗ CHROMA16_FUNC(row, 0, 0)
1638
1639 ✗ static av_always_inline void chroma(WaveformContext *s,
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) \
1719 static 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
1738 ✗ CHROMA_FUNC(column_mirror, 1, 1)
1739 ✗ CHROMA_FUNC(column, 1, 0)
1740 ✗ CHROMA_FUNC(row_mirror, 0, 1)
1741 ✗ CHROMA_FUNC(row, 0, 0)
1742
1743 ✗ static av_always_inline void color16(WaveformContext *s,
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) \
1852 static 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
1871 ✗ COLOR16_FUNC(column_mirror, 1, 1)
1872 ✗ COLOR16_FUNC(column, 1, 0)
1873 ✗ COLOR16_FUNC(row_mirror, 0, 1)
1874 ✗ COLOR16_FUNC(row, 0, 0)
1875
1876 ✗ static av_always_inline void color(WaveformContext *s,
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) \
1984 static 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
2003 ✗ COLOR_FUNC(column_mirror, 1, 1)
2004 ✗ COLOR_FUNC(column, 1, 0)
2005 ✗ COLOR_FUNC(row_mirror, 0, 1)
2006 ✗ COLOR_FUNC(row, 0, 0)
2007
2008 ✗ static av_always_inline void acolor16(WaveformContext *s,
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) \
2118 static 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
2137 ✗ ACOLOR16_FUNC(column_mirror, 1, 1)
2138 ✗ ACOLOR16_FUNC(column, 1, 0)
2139 ✗ ACOLOR16_FUNC(row_mirror, 0, 1)
2140 ✗ ACOLOR16_FUNC(row, 0, 0)
2141
2142 ✗ static av_always_inline void acolor(WaveformContext *s,
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) \
2251 static 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
2270 ✗ ACOLOR_FUNC(column_mirror, 1, 1)
2271 ✗ ACOLOR_FUNC(column, 1, 0)
2272 ✗ ACOLOR_FUNC(row_mirror, 0, 1)
2273 ✗ ACOLOR_FUNC(row, 0, 0)
2274
2275 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
2276 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
2277
2278 static const GraticuleLines aflat_digital8[] = {
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
2284 static const GraticuleLines aflat_digital9[] = {
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
2290 static const GraticuleLines aflat_digital10[] = {
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
2296 static const GraticuleLines aflat_digital12[] = {
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
2302 static const GraticuleLines aflat_millivolts8[] = {
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
2310 static const GraticuleLines aflat_millivolts9[] = {
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
2318 static const GraticuleLines aflat_millivolts10[] = {
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
2326 static const GraticuleLines aflat_millivolts12[] = {
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
2334 static 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
2344 static 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
2354 static 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
2364 static 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
2374 static const GraticuleLines flat_digital8[] = {
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
2380 static const GraticuleLines flat_digital9[] = {
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
2386 static const GraticuleLines flat_digital10[] = {
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
2392 static const GraticuleLines flat_digital12[] = {
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
2398 static const GraticuleLines flat_millivolts8[] = {
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
2406 static const GraticuleLines flat_millivolts9[] = {
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
2414 static const GraticuleLines flat_millivolts10[] = {
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
2422 static const GraticuleLines flat_millivolts12[] = {
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
2430 static 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
2440 static 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
2450 static 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
2460 static 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
2470 static 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
2476 static 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
2482 static 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
2488 static 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
2494 static 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
2502 static 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
2510 static const GraticuleLines millivolts10[] = {
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
2518 static const GraticuleLines millivolts12[] = {
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
2526 static 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
2534 static 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
2542 static 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
2550 static 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
2558 static const GraticuleLines chroma_digital8[] = {
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
2566 static const GraticuleLines chroma_digital9[] = {
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
2574 static const GraticuleLines chroma_digital10[] = {
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
2582 static const GraticuleLines chroma_digital12[] = {
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
2590 ✗ static 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
2601 ✗ static 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
2613 ✗ static 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
2622 ✗ static 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
2632 ✗ static 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
2658 ✗ static 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
2684 ✗ static 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
2709 ✗ static 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
2734 ✗ static 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
2745 ✗ static 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
2757 ✗ static 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
2766 ✗ static 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
2776 ✗ static 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
2802 ✗ static 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
2828 ✗ static 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
2853 ✗ static 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
2878 200 static void graticule_none(WaveformContext *s, AVFrame *out)
2879 {
2880 200 }
2881
2882 ✗ static void graticule_row(WaveformContext *s, AVFrame *out)
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
2923 ✗ static void graticule16_row(WaveformContext *s, AVFrame *out)
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
2965 ✗ static void graticule_column(WaveformContext *s, AVFrame *out)
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
3006 ✗ static void graticule16_column(WaveformContext *s, AVFrame *out)
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
3048 4 static int config_input(AVFilterLink *inlink)
3049 {
3050 4 AVFilterContext *ctx = inlink->dst;
3051 4 WaveformContext *s = ctx->priv;
3052
3053 4 s->desc = av_pix_fmt_desc_get(inlink->format);
3054 4 s->ncomp = s->desc->nb_components;
3055 4 s->bits = s->desc->comp[0].depth;
3056 4 s->max = 1 << s->bits;
3057
3058 4 s->shift_w[0] = s->shift_w[3] = 0;
3059 4 s->shift_h[0] = s->shift_h[3] = 0;
3060 4 s->shift_w[1] = s->shift_w[2] = s->desc->log2_chroma_w;
3061 4 s->shift_h[1] = s->shift_h[2] = s->desc->log2_chroma_h;
3062
3063 4 s->graticulef = graticule_none;
3064
3065
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 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 4 default: s->size = 256; break;
3071 }
3072
3073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 switch (s->filter | ((s->bits > 8) << 4) |
3074
2/65
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
4 (s->mode << 8) | (s->mirror << 12)) {
3075 3 case 0x1100: s->waveform_slice = lowpass_column_mirror; break;
3076 1 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 4 s->grat_yuva_color[0] = 255;
3142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 s->grat_yuva_color[1] = s->graticule == GRAT_INVERT ? 255 : 0;
3143
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 s->grat_yuva_color[2] = s->graticule == GRAT_ORANGE || s->graticule == GRAT_INVERT ? 255 : 0;
3144 4 s->grat_yuva_color[3] = 255;
3145
3146
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
4 if (s->mode == 0 && s->graticule != GRAT_INVERT) {
3147
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 s->blend_line = s->bits <= 8 ? blend_vline : blend_vline16;
3148
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 s->draw_text = s->bits <= 8 ? draw_vtext : draw_vtext16;
3149
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 } else if (s->graticule != GRAT_INVERT) {
3150
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 s->blend_line = s->bits <= 8 ? blend_hline : blend_hline16;
3151
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 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
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 switch (s->filter) {
3161 4 case LOWPASS:
3162 case COLOR:
3163 case ACOLOR:
3164 case CHROMA:
3165 case AFLAT:
3166 case XFLAT:
3167 case YFLAT:
3168 case FLAT:
3169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 if (s->graticule > GRAT_NONE && s->mode == 1)
3170 ✗ s->graticulef = s->bits > 8 ? graticule16_column : graticule_column;
3171
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 else if (s->graticule > GRAT_NONE && s->mode == 0)
3172 ✗ s->graticulef = s->bits > 8 ? graticule16_row : graticule_row;
3173 4 break;
3174 }
3175
3176
1/5
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 switch (s->filter) {
3177 4 case COLOR:
3178 case ACOLOR:
3179 case LOWPASS:
3180
1/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 switch (s->scale) {
3181 4 case DIGITAL:
3182
1/5
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4 switch (s->bits) {
3183 4 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 4 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 4 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 4 s->size = s->size << (s->bits - 8);
3296
3297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 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 4 default:
3307 4 memcpy(s->bg_color, black_yuva_color, sizeof(s->bg_color));
3308 }
3309
3310 4 return 0;
3311 }
3312
3313 4 static int config_output(AVFilterLink *outlink)
3314 {
3315 4 AVFilterContext *ctx = outlink->src;
3316 4 AVFilterLink *inlink = ctx->inputs[0];
3317 4 WaveformContext *s = ctx->priv;
3318 4 int comp = 0, i, j = 0, k, p, size;
3319
3320
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (i = 0; i < s->ncomp; i++) {
3321
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
12 if ((1 << i) & s->pcomp)
3322 5 comp++;
3323 }
3324 4 s->acomp = comp;
3325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->acomp == 0)
3326 ✗ return AVERROR(EINVAL);
3327
3328 4 s->odesc = av_pix_fmt_desc_get(outlink->format);
3329 4 s->dcomp = s->odesc->nb_components;
3330
3331 4 av_freep(&s->peak);
3332
3333
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (s->mode) {
3334 3 outlink->h = s->size * FFMAX(comp * (s->display == STACK), 1);
3335 3 outlink->w = inlink->w * FFMAX(comp * (s->display == PARADE), 1);
3336 3 size = inlink->w;
3337 } else {
3338 1 outlink->w = s->size * FFMAX(comp * (s->display == STACK), 1);
3339 1 outlink->h = inlink->h * FFMAX(comp * (s->display == PARADE), 1);
3340 1 size = inlink->h;
3341 }
3342
3343 4 s->peak = av_malloc_array(size, 32 * sizeof(*s->peak));
3344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!s->peak)
3345 ✗ return AVERROR(ENOMEM);
3346
3347
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (p = 0; p < s->ncomp; p++) {
3348 12 const int plane = s->desc->comp[p].plane;
3349 int offset;
3350
3351
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 if (!((1 << p) & s->pcomp))
3352 7 continue;
3353
3354
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5 times.
25 for (k = 0; k < 4; k++) {
3355 20 s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0);
3356 20 s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16);
3357 }
3358
3359 5 offset = j++ * s->size * (s->display == STACK);
3360 5 s->estart[plane] = offset;
3361 5 s->eend[plane] = (offset + s->size - 1);
3362
2/2
✓ Branch 0 taken 1696 times.
✓ Branch 1 taken 5 times.
1701 for (i = 0; i < size; i++) {
3363
2/2
✓ Branch 0 taken 6784 times.
✓ Branch 1 taken 1696 times.
8480 for (k = 0; k < 4; k++) {
3364 6784 s->emax[plane][k][i] = s->estart[plane];
3365 6784 s->emin[plane][k][i] = s->eend[plane];
3366 }
3367 }
3368 }
3369
3370
1/3
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
4 switch (s->fitmode) {
3371 4 case FM_NONE:
3372 4 outlink->sample_aspect_ratio = (AVRational){ 1, 1 };
3373 4 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
3382 4 av_reduce(&outlink->sample_aspect_ratio.num, &outlink->sample_aspect_ratio.den,
3383 4 outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den, INT_MAX);
3384
3385 4 return 0;
3386 }
3387
3388 200 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
3389 {
3390 200 AVFilterContext *ctx = inlink->dst;
3391 200 WaveformContext *s = ctx->priv;
3392 200 AVFilterLink *outlink = ctx->outputs[0];
3393 AVFrame *out;
3394 int i, j, k;
3395
3396 200 s->intensity = s->fintensity * (s->max - 1);
3397 200 s->bg_color[3] = s->bgopacity * (s->max - 1);
3398 200 s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1);
3399 200 s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1);
3400
3401 200 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
3402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (!out) {
3403 ✗ av_frame_free(&in);
3404 ✗ return AVERROR(ENOMEM);
3405 }
3406
3407
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 200 times.
800 for (k = 0; k < s->dcomp; k++) {
3408
1/2
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
600 if (s->bits <= 8) {
3409
2/2
✓ Branch 0 taken 196800 times.
✓ Branch 1 taken 600 times.
197400 for (i = 0; i < outlink->h ; i++)
3410 196800 memset(out->data[s->odesc->comp[k].plane] +
3411 196800 i * out->linesize[s->odesc->comp[k].plane],
3412 196800 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
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 200 times.
800 for (k = 0, i = 0; k < s->ncomp; k++) {
3426
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 350 times.
600 if ((1 << k) & s->pcomp) {
3427 250 const int plane = s->desc->comp[k].plane;
3428 ThreadData td;
3429 int offset_y;
3430 int offset_x;
3431
3432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250 times.
250 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
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 50 times.
250 offset_y = s->mode ? i++ * s->size * !!s->display : 0;
3437
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 200 times.
250 offset_x = s->mode ? 0 : i++ * s->size * !!s->display;
3438 }
3439
3440 250 td.in = in;
3441 250 td.out = out;
3442 250 td.component = k;
3443 250 td.offset_y = offset_y;
3444 250 td.offset_x = offset_x;
3445 250 ff_filter_execute(ctx, s->waveform_slice, &td, NULL,
3446 ff_filter_get_nb_threads(ctx));
3447
1/5
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
250 switch (s->filter) {
3448 250 case LOWPASS:
3449
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 if (s->bits <= 8)
3450
4/6
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 250 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 250 times.
250 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 250 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 200 s->graticulef(s, out);
3488
3489 200 av_frame_copy_props(out, in);
3490 200 out->color_range = AVCOL_RANGE_JPEG;
3491 200 av_frame_free(&in);
3492 200 out->sample_aspect_ratio = outlink->sample_aspect_ratio;
3493 200 return ff_filter_frame(outlink, out);
3494 }
3495
3496 8 static av_cold void uninit(AVFilterContext *ctx)
3497 {
3498 8 WaveformContext *s = ctx->priv;
3499
3500 8 av_freep(&s->peak);
3501 8 }
3502
3503 static 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
3512 static const AVFilterPad outputs[] = {
3513 {
3514 .name = "default",
3515 .type = AVMEDIA_TYPE_VIDEO,
3516 .config_props = config_output,
3517 },
3518 };
3519
3520 const FFFilter ff_vf_waveform = {
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,
3527 FILTER_INPUTS(inputs),
3528 FILTER_OUTPUTS(outputs),
3529 FILTER_QUERY_FUNC(query_formats),
3530 .process_command = ff_filter_process_command,
3531 };
3532