FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_waveform.c
Date: 2024-04-18 20:30:25
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 "formats.h"
28 #include "internal.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 const char *name;
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 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_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_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 ? (src_h * jobnr) / nb_jobs : 0;
709 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
710 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
711 const int slicew_end = column ? (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 ? (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 ? (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 ? (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 ? (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 ? (src_h * jobnr) / nb_jobs : 0;
990 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
991 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
992 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
1127 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1128 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1129 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0; \
1273 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
1274 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
1275 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0; \
1390 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
1391 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
1392 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
1554 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1555 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1556 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
1650 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1651 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1652 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
1755 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1756 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1757 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
1887 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
1888 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
1889 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
2021 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
2022 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
2023 const int slicew_end = column ? (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 ? (src_h * jobnr) / nb_jobs : 0;
2153 const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
2154 const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
2155 const int slicew_end = column ? (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, 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, 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, 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, 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, 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, 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, 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, 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 = (GraticuleLines *)digital8; s->nb_glines = FF_ARRAY_ELEMS(digital8); break;
3184 case 9: s->glines = (GraticuleLines *)digital9; s->nb_glines = FF_ARRAY_ELEMS(digital9); break;
3185 case 10: s->glines = (GraticuleLines *)digital10; s->nb_glines = FF_ARRAY_ELEMS(digital10); break;
3186 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
3192 case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
3193 case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
3194 case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
3195 }
3196 break;
3197 case IRE:
3198 switch (s->bits) {
3199 case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
3200 case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
3201 case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
3202 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)chroma_digital8; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital8); break;
3212 case 9: s->glines = (GraticuleLines *)chroma_digital9; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital9); break;
3213 case 10: s->glines = (GraticuleLines *)chroma_digital10; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital10); break;
3214 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
3220 case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
3221 case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
3222 case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
3223 }
3224 break;
3225 case IRE:
3226 switch (s->bits) {
3227 case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
3228 case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
3229 case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
3230 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)aflat_digital8; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital8); break;
3242 case 9: s->glines = (GraticuleLines *)aflat_digital9; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital9); break;
3243 case 10: s->glines = (GraticuleLines *)aflat_digital10; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital10); break;
3244 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)aflat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts8); break;
3250 case 9: s->glines = (GraticuleLines *)aflat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts9); break;
3251 case 10: s->glines = (GraticuleLines *)aflat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts10); break;
3252 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)aflat_ire8; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire8); break;
3258 case 9: s->glines = (GraticuleLines *)aflat_ire9; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire9); break;
3259 case 10: s->glines = (GraticuleLines *)aflat_ire10; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire10); break;
3260 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)flat_digital8; s->nb_glines = FF_ARRAY_ELEMS(flat_digital8); break;
3270 case 9: s->glines = (GraticuleLines *)flat_digital9; s->nb_glines = FF_ARRAY_ELEMS(flat_digital9); break;
3271 case 10: s->glines = (GraticuleLines *)flat_digital10; s->nb_glines = FF_ARRAY_ELEMS(flat_digital10); break;
3272 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)flat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts8); break;
3278 case 9: s->glines = (GraticuleLines *)flat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts9); break;
3279 case 10: s->glines = (GraticuleLines *)flat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts10); break;
3280 case 12: s->glines = (GraticuleLines *)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 = (GraticuleLines *)flat_ire8; s->nb_glines = FF_ARRAY_ELEMS(flat_ire8); break;
3286 case 9: s->glines = (GraticuleLines *)flat_ire9; s->nb_glines = FF_ARRAY_ELEMS(flat_ire9); break;
3287 case 10: s->glines = (GraticuleLines *)flat_ire10; s->nb_glines = FF_ARRAY_ELEMS(flat_ire10); break;
3288 case 12: s->glines = (GraticuleLines *)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 AVFilter ff_vf_waveform = {
3521 .name = "waveform",
3522 .description = NULL_IF_CONFIG_SMALL("Video waveform monitor."),
3523 .priv_size = sizeof(WaveformContext),
3524 .priv_class = &waveform_class,
3525 .uninit = uninit,
3526 FILTER_INPUTS(inputs),
3527 FILTER_OUTPUTS(outputs),
3528 FILTER_QUERY_FUNC(query_formats),
3529 .flags = AVFILTER_FLAG_SLICE_THREADS,
3530 .process_command = ff_filter_process_command,
3531 };
3532