blob: 70995eebeee3bedef1669928fb425828c41a5e31
1 | /* |
2 | * Copyright (c) 2012-2016 Paul B Mahol |
3 | * Copyright (c) 2013 Marton Balint |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "libavutil/avassert.h" |
23 | #include "libavutil/opt.h" |
24 | #include "libavutil/parseutils.h" |
25 | #include "libavutil/pixdesc.h" |
26 | #include "libavutil/xga_font_data.h" |
27 | #include "avfilter.h" |
28 | #include "formats.h" |
29 | #include "internal.h" |
30 | #include "video.h" |
31 | |
32 | enum FilterType { |
33 | LOWPASS, |
34 | FLAT, |
35 | AFLAT, |
36 | CHROMA, |
37 | COLOR, |
38 | ACOLOR, |
39 | NB_FILTERS |
40 | }; |
41 | |
42 | enum DisplayType { |
43 | OVERLAY, |
44 | STACK, |
45 | PARADE, |
46 | NB_DISPLAYS |
47 | }; |
48 | |
49 | enum ScaleType { |
50 | DIGITAL, |
51 | MILLIVOLTS, |
52 | IRE, |
53 | NB_SCALES |
54 | }; |
55 | |
56 | typedef struct GraticuleLine { |
57 | const char *name; |
58 | uint16_t pos; |
59 | } GraticuleLine; |
60 | |
61 | typedef struct GraticuleLines { |
62 | struct GraticuleLine line[4]; |
63 | } GraticuleLines; |
64 | |
65 | typedef struct WaveformContext { |
66 | const AVClass *class; |
67 | int mode; |
68 | int acomp; |
69 | int dcomp; |
70 | int ncomp; |
71 | int pcomp; |
72 | uint8_t bg_color[4]; |
73 | float fintensity; |
74 | int intensity; |
75 | int mirror; |
76 | int display; |
77 | int envelope; |
78 | int graticule; |
79 | float opacity; |
80 | float bgopacity; |
81 | int estart[4]; |
82 | int eend[4]; |
83 | int *emax[4][4]; |
84 | int *emin[4][4]; |
85 | int *peak; |
86 | int filter; |
87 | int flags; |
88 | int bits; |
89 | int max; |
90 | int size; |
91 | int scale; |
92 | int shift_w[4], shift_h[4]; |
93 | GraticuleLines *glines; |
94 | int nb_glines; |
95 | void (*waveform)(struct WaveformContext *s, |
96 | AVFrame *in, AVFrame *out, |
97 | int component, int intensity, |
98 | int offset_y, int offset_x, |
99 | int column, int mirror); |
100 | void (*graticulef)(struct WaveformContext *s, AVFrame *out); |
101 | const AVPixFmtDescriptor *desc; |
102 | const AVPixFmtDescriptor *odesc; |
103 | } WaveformContext; |
104 | |
105 | #define OFFSET(x) offsetof(WaveformContext, x) |
106 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
107 | |
108 | static const AVOption waveform_options[] = { |
109 | { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" }, |
110 | { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" }, |
111 | { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, |
112 | { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, |
113 | { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS }, |
114 | { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS }, |
115 | { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, |
116 | { "r", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, |
117 | { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" }, |
118 | { "d", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" }, |
119 | { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY}, 0, 0, FLAGS, "display" }, |
120 | { "stack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=STACK}, 0, 0, FLAGS, "display" }, |
121 | { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PARADE}, 0, 0, FLAGS, "display" }, |
122 | { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS }, |
123 | { "c", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS }, |
124 | { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" }, |
125 | { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" }, |
126 | { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" }, |
127 | { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" }, |
128 | { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" }, |
129 | { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" }, |
130 | { "filter", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" }, |
131 | { "f", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" }, |
132 | { "lowpass", NULL, 0, AV_OPT_TYPE_CONST, {.i64=LOWPASS}, 0, 0, FLAGS, "filter" }, |
133 | { "flat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "filter" }, |
134 | { "aflat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=AFLAT}, 0, 0, FLAGS, "filter" }, |
135 | { "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA}, 0, 0, FLAGS, "filter" }, |
136 | { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" }, |
137 | { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" }, |
138 | { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, |
139 | { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" }, |
140 | { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, |
141 | { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, |
142 | { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, |
143 | { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, |
144 | { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" }, |
145 | { "fl", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" }, |
146 | { "numbers", "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" }, |
147 | { "dots", "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" }, |
148 | { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" }, |
149 | { "s", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" }, |
150 | { "digital", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DIGITAL}, 0, 0, FLAGS, "scale" }, |
151 | { "millivolts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MILLIVOLTS}, 0, 0, FLAGS, "scale" }, |
152 | { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" }, |
153 | { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, |
154 | { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, |
155 | { NULL } |
156 | }; |
157 | |
158 | AVFILTER_DEFINE_CLASS(waveform); |
159 | |
160 | static const enum AVPixelFormat in_lowpass_pix_fmts[] = { |
161 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
162 | AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, |
163 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, |
164 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, |
165 | AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, |
166 | AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, |
167 | AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, |
168 | AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, |
169 | AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, |
170 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, |
171 | AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9, |
172 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, |
173 | AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, |
174 | AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, |
175 | AV_PIX_FMT_NONE |
176 | }; |
177 | |
178 | static const enum AVPixelFormat in_color_pix_fmts[] = { |
179 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
180 | AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, |
181 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, |
182 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, |
183 | AV_PIX_FMT_YUV411P, |
184 | AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, |
185 | AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, |
186 | AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, |
187 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, |
188 | AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9, |
189 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, |
190 | AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, |
191 | AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, |
192 | AV_PIX_FMT_NONE |
193 | }; |
194 | |
195 | static const enum AVPixelFormat in_flat_pix_fmts[] = { |
196 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, |
197 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, |
198 | AV_PIX_FMT_YUV411P, |
199 | AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, |
200 | AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, |
201 | AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, |
202 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, |
203 | AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9, |
204 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, |
205 | AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, |
206 | AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, |
207 | AV_PIX_FMT_NONE |
208 | }; |
209 | |
210 | static const enum AVPixelFormat out_rgb8_lowpass_pix_fmts[] = { |
211 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, |
212 | AV_PIX_FMT_NONE |
213 | }; |
214 | |
215 | static const enum AVPixelFormat out_rgb9_lowpass_pix_fmts[] = { |
216 | AV_PIX_FMT_GBRP9, |
217 | AV_PIX_FMT_NONE |
218 | }; |
219 | |
220 | static const enum AVPixelFormat out_rgb10_lowpass_pix_fmts[] = { |
221 | AV_PIX_FMT_GBRP10, |
222 | AV_PIX_FMT_NONE |
223 | }; |
224 | |
225 | static const enum AVPixelFormat out_rgb12_lowpass_pix_fmts[] = { |
226 | AV_PIX_FMT_GBRP12, |
227 | AV_PIX_FMT_NONE |
228 | }; |
229 | |
230 | static const enum AVPixelFormat out_yuv8_lowpass_pix_fmts[] = { |
231 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P, |
232 | AV_PIX_FMT_NONE |
233 | }; |
234 | |
235 | static const enum AVPixelFormat out_yuv9_lowpass_pix_fmts[] = { |
236 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9, |
237 | AV_PIX_FMT_NONE |
238 | }; |
239 | |
240 | static const enum AVPixelFormat out_yuv10_lowpass_pix_fmts[] = { |
241 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, |
242 | AV_PIX_FMT_NONE |
243 | }; |
244 | |
245 | static const enum AVPixelFormat out_yuv12_lowpass_pix_fmts[] = { |
246 | AV_PIX_FMT_YUV444P12, |
247 | AV_PIX_FMT_NONE |
248 | }; |
249 | |
250 | static const enum AVPixelFormat out_gray8_lowpass_pix_fmts[] = { |
251 | AV_PIX_FMT_GRAY8, |
252 | AV_PIX_FMT_NONE |
253 | }; |
254 | |
255 | static const enum AVPixelFormat out_gray10_lowpass_pix_fmts[] = { |
256 | AV_PIX_FMT_GRAY10, |
257 | AV_PIX_FMT_NONE |
258 | }; |
259 | |
260 | static const enum AVPixelFormat out_gray12_lowpass_pix_fmts[] = { |
261 | AV_PIX_FMT_GRAY12, |
262 | AV_PIX_FMT_NONE |
263 | }; |
264 | |
265 | static const enum AVPixelFormat flat_pix_fmts[] = { |
266 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, |
267 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, |
268 | AV_PIX_FMT_YUV444P12, |
269 | AV_PIX_FMT_NONE |
270 | }; |
271 | |
272 | static int query_formats(AVFilterContext *ctx) |
273 | { |
274 | WaveformContext *s = ctx->priv; |
275 | const enum AVPixelFormat *out_pix_fmts; |
276 | const enum AVPixelFormat *in_pix_fmts; |
277 | const AVPixFmtDescriptor *desc; |
278 | AVFilterFormats *avff; |
279 | int depth, rgb, i, ret, ncomp; |
280 | |
281 | if (!ctx->inputs[0]->in_formats || |
282 | !ctx->inputs[0]->in_formats->nb_formats) { |
283 | return AVERROR(EAGAIN); |
284 | } |
285 | |
286 | switch (s->filter) { |
287 | case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break; |
288 | case CHROMA: |
289 | case AFLAT: |
290 | case FLAT: in_pix_fmts = in_flat_pix_fmts; break; |
291 | case ACOLOR: |
292 | case COLOR: in_pix_fmts = in_color_pix_fmts; break; |
293 | } |
294 | |
295 | if (!ctx->inputs[0]->out_formats) { |
296 | if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0) |
297 | return ret; |
298 | } |
299 | |
300 | avff = ctx->inputs[0]->in_formats; |
301 | desc = av_pix_fmt_desc_get(avff->formats[0]); |
302 | ncomp = desc->nb_components; |
303 | rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; |
304 | depth = desc->comp[0].depth; |
305 | for (i = 1; i < avff->nb_formats; i++) { |
306 | desc = av_pix_fmt_desc_get(avff->formats[i]); |
307 | if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) || |
308 | depth != desc->comp[0].depth) |
309 | return AVERROR(EAGAIN); |
310 | } |
311 | |
312 | if (s->filter == LOWPASS && ncomp == 1 && depth == 8) |
313 | out_pix_fmts = out_gray8_lowpass_pix_fmts; |
314 | else if (s->filter == LOWPASS && ncomp == 1 && depth == 10) |
315 | out_pix_fmts = out_gray10_lowpass_pix_fmts; |
316 | else if (s->filter == LOWPASS && ncomp == 1 && depth == 12) |
317 | out_pix_fmts = out_gray12_lowpass_pix_fmts; |
318 | else if (rgb && depth == 8 && ncomp > 2) |
319 | out_pix_fmts = out_rgb8_lowpass_pix_fmts; |
320 | else if (rgb && depth == 9 && ncomp > 2) |
321 | out_pix_fmts = out_rgb9_lowpass_pix_fmts; |
322 | else if (rgb && depth == 10 && ncomp > 2) |
323 | out_pix_fmts = out_rgb10_lowpass_pix_fmts; |
324 | else if (rgb && depth == 12 && ncomp > 2) |
325 | out_pix_fmts = out_rgb12_lowpass_pix_fmts; |
326 | else if (depth == 8 && ncomp > 2) |
327 | out_pix_fmts = out_yuv8_lowpass_pix_fmts; |
328 | else if (depth == 9 && ncomp > 2) |
329 | out_pix_fmts = out_yuv9_lowpass_pix_fmts; |
330 | else if (depth == 10 && ncomp > 2) |
331 | out_pix_fmts = out_yuv10_lowpass_pix_fmts; |
332 | else if (depth == 12 && ncomp > 2) |
333 | out_pix_fmts = out_yuv12_lowpass_pix_fmts; |
334 | else |
335 | return AVERROR(EAGAIN); |
336 | if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0) |
337 | return ret; |
338 | |
339 | return 0; |
340 | } |
341 | |
342 | static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
343 | { |
344 | const int dst_linesize = out->linesize[component] / 2; |
345 | const int bg = s->bg_color[component] * (s->max / 256); |
346 | const int limit = s->max - 1; |
347 | const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height; |
348 | const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width; |
349 | const int start = s->estart[plane]; |
350 | const int end = s->eend[plane]; |
351 | uint16_t *dst; |
352 | int x, y; |
353 | |
354 | if (s->mode) { |
355 | for (x = offset; x < offset + dst_w; x++) { |
356 | for (y = start; y < end; y++) { |
357 | dst = (uint16_t *)out->data[component] + y * dst_linesize + x; |
358 | if (dst[0] != bg) { |
359 | dst[0] = limit; |
360 | break; |
361 | } |
362 | } |
363 | for (y = end - 1; y >= start; y--) { |
364 | dst = (uint16_t *)out->data[component] + y * dst_linesize + x; |
365 | if (dst[0] != bg) { |
366 | dst[0] = limit; |
367 | break; |
368 | } |
369 | } |
370 | } |
371 | } else { |
372 | for (y = offset; y < offset + dst_h; y++) { |
373 | dst = (uint16_t *)out->data[component] + y * dst_linesize; |
374 | for (x = start; x < end; x++) { |
375 | if (dst[x] != bg) { |
376 | dst[x] = limit; |
377 | break; |
378 | } |
379 | } |
380 | for (x = end - 1; x >= start; x--) { |
381 | if (dst[x] != bg) { |
382 | dst[x] = limit; |
383 | break; |
384 | } |
385 | } |
386 | } |
387 | } |
388 | } |
389 | |
390 | static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
391 | { |
392 | const int dst_linesize = out->linesize[component]; |
393 | const uint8_t bg = s->bg_color[component]; |
394 | const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height; |
395 | const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width; |
396 | const int start = s->estart[plane]; |
397 | const int end = s->eend[plane]; |
398 | uint8_t *dst; |
399 | int x, y; |
400 | |
401 | if (s->mode) { |
402 | for (x = offset; x < offset + dst_w; x++) { |
403 | for (y = start; y < end; y++) { |
404 | dst = out->data[component] + y * dst_linesize + x; |
405 | if (dst[0] != bg) { |
406 | dst[0] = 255; |
407 | break; |
408 | } |
409 | } |
410 | for (y = end - 1; y >= start; y--) { |
411 | dst = out->data[component] + y * dst_linesize + x; |
412 | if (dst[0] != bg) { |
413 | dst[0] = 255; |
414 | break; |
415 | } |
416 | } |
417 | } |
418 | } else { |
419 | for (y = offset; y < offset + dst_h; y++) { |
420 | dst = out->data[component] + y * dst_linesize; |
421 | for (x = start; x < end; x++) { |
422 | if (dst[x] != bg) { |
423 | dst[x] = 255; |
424 | break; |
425 | } |
426 | } |
427 | for (x = end - 1; x >= start; x--) { |
428 | if (dst[x] != bg) { |
429 | dst[x] = 255; |
430 | break; |
431 | } |
432 | } |
433 | } |
434 | } |
435 | } |
436 | |
437 | static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
438 | { |
439 | const int dst_linesize = out->linesize[component] / 2; |
440 | const int bg = s->bg_color[component] * (s->max / 256); |
441 | const int limit = s->max - 1; |
442 | const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height; |
443 | const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width; |
444 | const int start = s->estart[plane]; |
445 | const int end = s->eend[plane]; |
446 | int *emax = s->emax[plane][component]; |
447 | int *emin = s->emin[plane][component]; |
448 | uint16_t *dst; |
449 | int x, y; |
450 | |
451 | if (s->mode) { |
452 | for (x = offset; x < offset + dst_w; x++) { |
453 | for (y = start; y < end && y < emin[x - offset]; y++) { |
454 | dst = (uint16_t *)out->data[component] + y * dst_linesize + x; |
455 | if (dst[0] != bg) { |
456 | emin[x - offset] = y; |
457 | break; |
458 | } |
459 | } |
460 | for (y = end - 1; y >= start && y >= emax[x - offset]; y--) { |
461 | dst = (uint16_t *)out->data[component] + y * dst_linesize + x; |
462 | if (dst[0] != bg) { |
463 | emax[x - offset] = y; |
464 | break; |
465 | } |
466 | } |
467 | } |
468 | |
469 | if (s->envelope == 3) |
470 | envelope_instant16(s, out, plane, component, offset); |
471 | |
472 | for (x = offset; x < offset + dst_w; x++) { |
473 | dst = (uint16_t *)out->data[component] + emin[x - offset] * dst_linesize + x; |
474 | dst[0] = limit; |
475 | dst = (uint16_t *)out->data[component] + emax[x - offset] * dst_linesize + x; |
476 | dst[0] = limit; |
477 | } |
478 | } else { |
479 | for (y = offset; y < offset + dst_h; y++) { |
480 | dst = (uint16_t *)out->data[component] + y * dst_linesize; |
481 | for (x = start; x < end && x < emin[y - offset]; x++) { |
482 | if (dst[x] != bg) { |
483 | emin[y - offset] = x; |
484 | break; |
485 | } |
486 | } |
487 | for (x = end - 1; x >= start && x >= emax[y - offset]; x--) { |
488 | if (dst[x] != bg) { |
489 | emax[y - offset] = x; |
490 | break; |
491 | } |
492 | } |
493 | } |
494 | |
495 | if (s->envelope == 3) |
496 | envelope_instant16(s, out, plane, component, offset); |
497 | |
498 | for (y = offset; y < offset + dst_h; y++) { |
499 | dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y - offset]; |
500 | dst[0] = limit; |
501 | dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y - offset]; |
502 | dst[0] = limit; |
503 | } |
504 | } |
505 | } |
506 | |
507 | static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
508 | { |
509 | const int dst_linesize = out->linesize[component]; |
510 | const int bg = s->bg_color[component]; |
511 | const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height; |
512 | const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width; |
513 | const int start = s->estart[plane]; |
514 | const int end = s->eend[plane]; |
515 | int *emax = s->emax[plane][component]; |
516 | int *emin = s->emin[plane][component]; |
517 | uint8_t *dst; |
518 | int x, y; |
519 | |
520 | if (s->mode) { |
521 | for (x = offset; x < offset + dst_w; x++) { |
522 | for (y = start; y < end && y < emin[x - offset]; y++) { |
523 | dst = out->data[component] + y * dst_linesize + x; |
524 | if (dst[0] != bg) { |
525 | emin[x - offset] = y; |
526 | break; |
527 | } |
528 | } |
529 | for (y = end - 1; y >= start && y >= emax[x - offset]; y--) { |
530 | dst = out->data[component] + y * dst_linesize + x; |
531 | if (dst[0] != bg) { |
532 | emax[x - offset] = y; |
533 | break; |
534 | } |
535 | } |
536 | } |
537 | |
538 | if (s->envelope == 3) |
539 | envelope_instant(s, out, plane, component, offset); |
540 | |
541 | for (x = offset; x < offset + dst_w; x++) { |
542 | dst = out->data[component] + emin[x - offset] * dst_linesize + x; |
543 | dst[0] = 255; |
544 | dst = out->data[component] + emax[x - offset] * dst_linesize + x; |
545 | dst[0] = 255; |
546 | } |
547 | } else { |
548 | for (y = offset; y < offset + dst_h; y++) { |
549 | dst = out->data[component] + y * dst_linesize; |
550 | for (x = start; x < end && x < emin[y - offset]; x++) { |
551 | if (dst[x] != bg) { |
552 | emin[y - offset] = x; |
553 | break; |
554 | } |
555 | } |
556 | for (x = end - 1; x >= start && x >= emax[y - offset]; x--) { |
557 | if (dst[x] != bg) { |
558 | emax[y - offset] = x; |
559 | break; |
560 | } |
561 | } |
562 | } |
563 | |
564 | if (s->envelope == 3) |
565 | envelope_instant(s, out, plane, component, offset); |
566 | |
567 | for (y = offset; y < offset + dst_h; y++) { |
568 | dst = out->data[component] + y * dst_linesize + emin[y - offset]; |
569 | dst[0] = 255; |
570 | dst = out->data[component] + y * dst_linesize + emax[y - offset]; |
571 | dst[0] = 255; |
572 | } |
573 | } |
574 | } |
575 | |
576 | static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
577 | { |
578 | if (s->envelope == 0) { |
579 | return; |
580 | } else if (s->envelope == 1) { |
581 | envelope_instant16(s, out, plane, component, offset); |
582 | } else { |
583 | envelope_peak16(s, out, plane, component, offset); |
584 | } |
585 | } |
586 | |
587 | static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset) |
588 | { |
589 | if (s->envelope == 0) { |
590 | return; |
591 | } else if (s->envelope == 1) { |
592 | envelope_instant(s, out, plane, component, offset); |
593 | } else { |
594 | envelope_peak(s, out, plane, component, offset); |
595 | } |
596 | } |
597 | |
598 | static void update16(uint16_t *target, int max, int intensity, int limit) |
599 | { |
600 | if (*target <= max) |
601 | *target += intensity; |
602 | else |
603 | *target = limit; |
604 | } |
605 | |
606 | static void update(uint8_t *target, int max, int intensity) |
607 | { |
608 | if (*target <= max) |
609 | *target += intensity; |
610 | else |
611 | *target = 255; |
612 | } |
613 | |
614 | static av_always_inline void lowpass16(WaveformContext *s, |
615 | AVFrame *in, AVFrame *out, |
616 | int component, int intensity, |
617 | int offset_y, int offset_x, |
618 | int column, int mirror) |
619 | { |
620 | const int plane = s->desc->comp[component].plane; |
621 | const int shift_w = s->shift_w[component]; |
622 | const int shift_h = s->shift_h[component]; |
623 | const int src_linesize = in->linesize[plane] / 2; |
624 | const int dst_linesize = out->linesize[plane] / 2; |
625 | const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); |
626 | const int limit = s->max - 1; |
627 | const int max = limit - intensity; |
628 | const int src_h = AV_CEIL_RSHIFT(in->height, shift_h); |
629 | const int src_w = AV_CEIL_RSHIFT(in->width, shift_w); |
630 | const uint16_t *src_data = (const uint16_t *)in->data[plane]; |
631 | uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x; |
632 | uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); |
633 | uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data); |
634 | const int step = column ? 1 << shift_w : 1 << shift_h; |
635 | const uint16_t *p; |
636 | int y; |
637 | |
638 | if (!column && mirror) |
639 | dst_data += s->size; |
640 | |
641 | for (y = 0; y < src_h; y++) { |
642 | const uint16_t *src_data_end = src_data + src_w; |
643 | uint16_t *dst = dst_line; |
644 | |
645 | for (p = src_data; p < src_data_end; p++) { |
646 | uint16_t *target; |
647 | int i = 0, v = FFMIN(*p, limit); |
648 | |
649 | if (column) { |
650 | do { |
651 | target = dst++ + dst_signed_linesize * v; |
652 | update16(target, max, intensity, limit); |
653 | } while (++i < step); |
654 | } else { |
655 | uint16_t *row = dst_data; |
656 | do { |
657 | if (mirror) |
658 | target = row - v - 1; |
659 | else |
660 | target = row + v; |
661 | update16(target, max, intensity, limit); |
662 | row += dst_linesize; |
663 | } while (++i < step); |
664 | } |
665 | } |
666 | src_data += src_linesize; |
667 | dst_data += dst_linesize * step; |
668 | } |
669 | |
670 | envelope16(s, out, plane, plane, column ? offset_x : offset_y); |
671 | } |
672 | |
673 | #define LOWPASS16_FUNC(name, column, mirror) \ |
674 | static void lowpass16_##name(WaveformContext *s, \ |
675 | AVFrame *in, AVFrame *out, \ |
676 | int component, int intensity, \ |
677 | int offset_y, int offset_x, \ |
678 | int unused1, int unused2) \ |
679 | { \ |
680 | lowpass16(s, in, out, component, intensity, \ |
681 | offset_y, offset_x, column, mirror); \ |
682 | } |
683 | |
684 | LOWPASS16_FUNC(column_mirror, 1, 1) |
685 | LOWPASS16_FUNC(column, 1, 0) |
686 | LOWPASS16_FUNC(row_mirror, 0, 1) |
687 | LOWPASS16_FUNC(row, 0, 0) |
688 | |
689 | static av_always_inline void lowpass(WaveformContext *s, |
690 | AVFrame *in, AVFrame *out, |
691 | int component, int intensity, |
692 | int offset_y, int offset_x, |
693 | int column, int mirror) |
694 | { |
695 | const int plane = s->desc->comp[component].plane; |
696 | const int shift_w = s->shift_w[component]; |
697 | const int shift_h = s->shift_h[component]; |
698 | const int src_linesize = in->linesize[plane]; |
699 | const int dst_linesize = out->linesize[plane]; |
700 | const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); |
701 | const int max = 255 - intensity; |
702 | const int src_h = AV_CEIL_RSHIFT(in->height, shift_h); |
703 | const int src_w = AV_CEIL_RSHIFT(in->width, shift_w); |
704 | const uint8_t *src_data = in->data[plane]; |
705 | uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x; |
706 | uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); |
707 | uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data); |
708 | const int step = column ? 1 << shift_w : 1 << shift_h; |
709 | const uint8_t *p; |
710 | int y; |
711 | |
712 | if (!column && mirror) |
713 | dst_data += s->size; |
714 | |
715 | for (y = 0; y < src_h; y++) { |
716 | const uint8_t *src_data_end = src_data + src_w; |
717 | uint8_t *dst = dst_line; |
718 | |
719 | for (p = src_data; p < src_data_end; p++) { |
720 | uint8_t *target; |
721 | if (column) { |
722 | target = dst + dst_signed_linesize * *p; |
723 | dst += step; |
724 | update(target, max, intensity); |
725 | } else { |
726 | uint8_t *row = dst_data; |
727 | if (mirror) |
728 | target = row - *p - 1; |
729 | else |
730 | target = row + *p; |
731 | update(target, max, intensity); |
732 | row += dst_linesize; |
733 | } |
734 | } |
735 | src_data += src_linesize; |
736 | dst_data += dst_linesize * step; |
737 | } |
738 | |
739 | if (column && step > 1) { |
740 | const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width; |
741 | const int dst_h = 256; |
742 | uint8_t *dst; |
743 | int x, z; |
744 | |
745 | dst = out->data[plane] + offset_y * dst_linesize + offset_x; |
746 | for (y = 0; y < dst_h; y++) { |
747 | for (x = 0; x < dst_w; x+=step) { |
748 | for (z = 1; z < step; z++) { |
749 | dst[x + z] = dst[x]; |
750 | } |
751 | } |
752 | dst += dst_linesize; |
753 | } |
754 | } else if (step > 1) { |
755 | const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height; |
756 | const int dst_w = 256; |
757 | uint8_t *dst; |
758 | int z; |
759 | |
760 | dst = out->data[plane] + offset_y * dst_linesize + offset_x; |
761 | for (y = 0; y < dst_h; y+=step) { |
762 | for (z = 1; z < step; z++) |
763 | memcpy(dst + dst_linesize * z, dst, dst_w); |
764 | dst += dst_linesize * step; |
765 | } |
766 | } |
767 | |
768 | envelope(s, out, plane, plane, column ? offset_x : offset_y); |
769 | } |
770 | |
771 | #define LOWPASS_FUNC(name, column, mirror) \ |
772 | static void lowpass_##name(WaveformContext *s, \ |
773 | AVFrame *in, AVFrame *out, \ |
774 | int component, int intensity, \ |
775 | int offset_y, int offset_x, \ |
776 | int unused1, int unused2) \ |
777 | { \ |
778 | lowpass(s, in, out, component, intensity, \ |
779 | offset_y, offset_x, column, mirror); \ |
780 | } |
781 | |
782 | LOWPASS_FUNC(column_mirror, 1, 1) |
783 | LOWPASS_FUNC(column, 1, 0) |
784 | LOWPASS_FUNC(row_mirror, 0, 1) |
785 | LOWPASS_FUNC(row, 0, 0) |
786 | |
787 | static av_always_inline void flat16(WaveformContext *s, |
788 | AVFrame *in, AVFrame *out, |
789 | int component, int intensity, |
790 | int offset_y, int offset_x, |
791 | int column, int mirror) |
792 | { |
793 | const int plane = s->desc->comp[component].plane; |
794 | const int c0_linesize = in->linesize[ plane + 0 ] / 2; |
795 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; |
796 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; |
797 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
798 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
799 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
800 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
801 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
802 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
803 | const int d0_linesize = out->linesize[ plane + 0 ] / 2; |
804 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; |
805 | const int limit = s->max - 1; |
806 | const int max = limit - intensity; |
807 | const int mid = s->max / 2; |
808 | const int src_h = in->height; |
809 | const int src_w = in->width; |
810 | int x, y; |
811 | |
812 | if (column) { |
813 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
814 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
815 | |
816 | for (x = 0; x < src_w; x++) { |
817 | const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; |
818 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
819 | const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
820 | uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x; |
821 | uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x; |
822 | uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
823 | uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
824 | uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
825 | uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
826 | |
827 | for (y = 0; y < src_h; y++) { |
828 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max; |
829 | const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit); |
830 | uint16_t *target; |
831 | |
832 | target = d0 + x + d0_signed_linesize * c0; |
833 | update16(target, max, intensity, limit); |
834 | target = d1 + x + d1_signed_linesize * (c0 - c1); |
835 | update16(target, max, intensity, limit); |
836 | target = d1 + x + d1_signed_linesize * (c0 + c1); |
837 | update16(target, max, intensity, limit); |
838 | |
839 | if (!c0_shift_h || (y & c0_shift_h)) |
840 | c0_data += c0_linesize; |
841 | if (!c1_shift_h || (y & c1_shift_h)) |
842 | c1_data += c1_linesize; |
843 | if (!c2_shift_h || (y & c2_shift_h)) |
844 | c2_data += c2_linesize; |
845 | d0_data += d0_linesize; |
846 | d1_data += d1_linesize; |
847 | } |
848 | } |
849 | } else { |
850 | const uint16_t *c0_data = (uint16_t *)in->data[plane]; |
851 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
852 | const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
853 | uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x; |
854 | uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x; |
855 | |
856 | if (mirror) { |
857 | d0_data += s->size - 1; |
858 | d1_data += s->size - 1; |
859 | } |
860 | |
861 | for (y = 0; y < src_h; y++) { |
862 | for (x = 0; x < src_w; x++) { |
863 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max; |
864 | const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit); |
865 | uint16_t *target; |
866 | |
867 | if (mirror) { |
868 | target = d0_data - c0; |
869 | update16(target, max, intensity, limit); |
870 | target = d1_data - (c0 - c1); |
871 | update16(target, max, intensity, limit); |
872 | target = d1_data - (c0 + c1); |
873 | update16(target, max, intensity, limit); |
874 | } else { |
875 | target = d0_data + c0; |
876 | update16(target, max, intensity, limit); |
877 | target = d1_data + (c0 - c1); |
878 | update16(target, max, intensity, limit); |
879 | target = d1_data + (c0 + c1); |
880 | update16(target, max, intensity, limit); |
881 | } |
882 | } |
883 | |
884 | if (!c0_shift_h || (y & c0_shift_h)) |
885 | c0_data += c0_linesize; |
886 | if (!c1_shift_h || (y & c1_shift_h)) |
887 | c1_data += c1_linesize; |
888 | if (!c2_shift_h || (y & c2_shift_h)) |
889 | c2_data += c2_linesize; |
890 | d0_data += d0_linesize; |
891 | d1_data += d1_linesize; |
892 | } |
893 | } |
894 | |
895 | envelope16(s, out, plane, plane, column ? offset_x : offset_y); |
896 | envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); |
897 | } |
898 | |
899 | static av_always_inline void flat(WaveformContext *s, |
900 | AVFrame *in, AVFrame *out, |
901 | int component, int intensity, |
902 | int offset_y, int offset_x, |
903 | int column, int mirror) |
904 | { |
905 | const int plane = s->desc->comp[component].plane; |
906 | const int c0_linesize = in->linesize[ plane + 0 ]; |
907 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; |
908 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; |
909 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
910 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
911 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
912 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
913 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
914 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
915 | const int d0_linesize = out->linesize[ plane + 0 ]; |
916 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; |
917 | const int max = 255 - intensity; |
918 | const int src_h = in->height; |
919 | const int src_w = in->width; |
920 | int x, y; |
921 | |
922 | if (column) { |
923 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
924 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
925 | |
926 | for (x = 0; x < src_w; x++) { |
927 | const uint8_t *c0_data = in->data[plane + 0]; |
928 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
929 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
930 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
931 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
932 | uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
933 | uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
934 | uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
935 | uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
936 | |
937 | for (y = 0; y < src_h; y++) { |
938 | const int c0 = c0_data[x >> c0_shift_w] + 256; |
939 | const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128); |
940 | uint8_t *target; |
941 | |
942 | target = d0 + x + d0_signed_linesize * c0; |
943 | update(target, max, intensity); |
944 | target = d1 + x + d1_signed_linesize * (c0 - c1); |
945 | update(target, max, intensity); |
946 | target = d1 + x + d1_signed_linesize * (c0 + c1); |
947 | update(target, max, intensity); |
948 | |
949 | if (!c0_shift_h || (y & c0_shift_h)) |
950 | c0_data += c0_linesize; |
951 | if (!c1_shift_h || (y & c1_shift_h)) |
952 | c1_data += c1_linesize; |
953 | if (!c2_shift_h || (y & c2_shift_h)) |
954 | c2_data += c2_linesize; |
955 | d0_data += d0_linesize; |
956 | d1_data += d1_linesize; |
957 | } |
958 | } |
959 | } else { |
960 | const uint8_t *c0_data = in->data[plane]; |
961 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
962 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
963 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
964 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
965 | |
966 | if (mirror) { |
967 | d0_data += s->size - 1; |
968 | d1_data += s->size - 1; |
969 | } |
970 | |
971 | for (y = 0; y < src_h; y++) { |
972 | for (x = 0; x < src_w; x++) { |
973 | int c0 = c0_data[x >> c0_shift_w] + 256; |
974 | const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128); |
975 | uint8_t *target; |
976 | |
977 | if (mirror) { |
978 | target = d0_data - c0; |
979 | update(target, max, intensity); |
980 | target = d1_data - (c0 - c1); |
981 | update(target, max, intensity); |
982 | target = d1_data - (c0 + c1); |
983 | update(target, max, intensity); |
984 | } else { |
985 | target = d0_data + c0; |
986 | update(target, max, intensity); |
987 | target = d1_data + (c0 - c1); |
988 | update(target, max, intensity); |
989 | target = d1_data + (c0 + c1); |
990 | update(target, max, intensity); |
991 | } |
992 | } |
993 | |
994 | if (!c0_shift_h || (y & c0_shift_h)) |
995 | c0_data += c0_linesize; |
996 | if (!c1_shift_h || (y & c1_shift_h)) |
997 | c1_data += c1_linesize; |
998 | if (!c2_shift_h || (y & c2_shift_h)) |
999 | c2_data += c2_linesize; |
1000 | d0_data += d0_linesize; |
1001 | d1_data += d1_linesize; |
1002 | } |
1003 | } |
1004 | |
1005 | envelope(s, out, plane, plane, column ? offset_x : offset_y); |
1006 | envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); |
1007 | } |
1008 | |
1009 | static av_always_inline void aflat16(WaveformContext *s, |
1010 | AVFrame *in, AVFrame *out, |
1011 | int component, int intensity, |
1012 | int offset_y, int offset_x, |
1013 | int column, int mirror) |
1014 | { |
1015 | const int plane = s->desc->comp[component].plane; |
1016 | const int c0_linesize = in->linesize[ plane + 0 ] / 2; |
1017 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; |
1018 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; |
1019 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1020 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1021 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1022 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1023 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1024 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1025 | const int d0_linesize = out->linesize[ plane + 0 ] / 2; |
1026 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; |
1027 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; |
1028 | const int limit = s->max - 1; |
1029 | const int max = limit - intensity; |
1030 | const int mid = s->max / 2; |
1031 | const int src_h = in->height; |
1032 | const int src_w = in->width; |
1033 | int x, y; |
1034 | |
1035 | if (column) { |
1036 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1037 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1038 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1039 | |
1040 | for (x = 0; x < src_w; x++) { |
1041 | const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; |
1042 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1043 | const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1044 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1045 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1046 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1047 | uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1048 | uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1049 | uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1050 | uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1051 | uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1052 | uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1053 | |
1054 | for (y = 0; y < src_h; y++) { |
1055 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; |
1056 | const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; |
1057 | const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; |
1058 | uint16_t *target; |
1059 | |
1060 | target = d0 + x + d0_signed_linesize * c0; |
1061 | update16(target, max, intensity, limit); |
1062 | |
1063 | target = d1 + x + d1_signed_linesize * (c0 + c1); |
1064 | update16(target, max, intensity, limit); |
1065 | |
1066 | target = d2 + x + d2_signed_linesize * (c0 + c2); |
1067 | update16(target, max, intensity, limit); |
1068 | |
1069 | if (!c0_shift_h || (y & c0_shift_h)) |
1070 | c0_data += c0_linesize; |
1071 | if (!c1_shift_h || (y & c1_shift_h)) |
1072 | c1_data += c1_linesize; |
1073 | if (!c2_shift_h || (y & c2_shift_h)) |
1074 | c2_data += c2_linesize; |
1075 | d0_data += d0_linesize; |
1076 | d1_data += d1_linesize; |
1077 | d2_data += d2_linesize; |
1078 | } |
1079 | } |
1080 | } else { |
1081 | const uint16_t *c0_data = (uint16_t *)in->data[plane]; |
1082 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1083 | const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1084 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1085 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1086 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1087 | |
1088 | if (mirror) { |
1089 | d0_data += s->size - 1; |
1090 | d1_data += s->size - 1; |
1091 | d2_data += s->size - 1; |
1092 | } |
1093 | |
1094 | for (y = 0; y < src_h; y++) { |
1095 | for (x = 0; x < src_w; x++) { |
1096 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; |
1097 | const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; |
1098 | const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; |
1099 | uint16_t *target; |
1100 | |
1101 | if (mirror) { |
1102 | target = d0_data - c0; |
1103 | update16(target, max, intensity, limit); |
1104 | target = d1_data - (c0 + c1); |
1105 | update16(target, max, intensity, limit); |
1106 | target = d2_data - (c0 + c2); |
1107 | update16(target, max, intensity, limit); |
1108 | } else { |
1109 | target = d0_data + c0; |
1110 | update16(target, max, intensity, limit); |
1111 | target = d1_data + (c0 + c1); |
1112 | update16(target, max, intensity, limit); |
1113 | target = d2_data + (c0 + c2); |
1114 | update16(target, max, intensity, limit); |
1115 | } |
1116 | } |
1117 | |
1118 | if (!c0_shift_h || (y & c0_shift_h)) |
1119 | c0_data += c0_linesize; |
1120 | if (!c1_shift_h || (y & c1_shift_h)) |
1121 | c1_data += c1_linesize; |
1122 | if (!c2_shift_h || (y & c2_shift_h)) |
1123 | c2_data += c2_linesize; |
1124 | d0_data += d0_linesize; |
1125 | d1_data += d1_linesize; |
1126 | d2_data += d2_linesize; |
1127 | } |
1128 | } |
1129 | |
1130 | envelope16(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); |
1131 | envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); |
1132 | envelope16(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); |
1133 | } |
1134 | |
1135 | static av_always_inline void aflat(WaveformContext *s, |
1136 | AVFrame *in, AVFrame *out, |
1137 | int component, int intensity, |
1138 | int offset_y, int offset_x, |
1139 | int column, int mirror) |
1140 | { |
1141 | const int plane = s->desc->comp[component].plane; |
1142 | const int c0_linesize = in->linesize[ plane + 0 ]; |
1143 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; |
1144 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; |
1145 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1146 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1147 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1148 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1149 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1150 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1151 | const int d0_linesize = out->linesize[ plane + 0 ]; |
1152 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; |
1153 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; |
1154 | const int max = 255 - intensity; |
1155 | const int src_h = in->height; |
1156 | const int src_w = in->width; |
1157 | int x, y; |
1158 | |
1159 | if (column) { |
1160 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1161 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1162 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1163 | |
1164 | for (x = 0; x < src_w; x++) { |
1165 | const uint8_t *c0_data = in->data[plane + 0]; |
1166 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
1167 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
1168 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1169 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1170 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1171 | uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1172 | uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1173 | uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1174 | uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1175 | uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1176 | uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1177 | |
1178 | for (y = 0; y < src_h; y++) { |
1179 | const int c0 = c0_data[x >> c0_shift_w] + 128; |
1180 | const int c1 = c1_data[x >> c1_shift_w] - 128; |
1181 | const int c2 = c2_data[x >> c2_shift_w] - 128; |
1182 | uint8_t *target; |
1183 | |
1184 | target = d0 + x + d0_signed_linesize * c0; |
1185 | update(target, max, intensity); |
1186 | |
1187 | target = d1 + x + d1_signed_linesize * (c0 + c1); |
1188 | update(target, max, intensity); |
1189 | |
1190 | target = d2 + x + d2_signed_linesize * (c0 + c2); |
1191 | update(target, max, intensity); |
1192 | |
1193 | if (!c0_shift_h || (y & c0_shift_h)) |
1194 | c0_data += c0_linesize; |
1195 | if (!c1_shift_h || (y & c1_shift_h)) |
1196 | c1_data += c1_linesize; |
1197 | if (!c1_shift_h || (y & c1_shift_h)) |
1198 | c2_data += c1_linesize; |
1199 | d0_data += d0_linesize; |
1200 | d1_data += d1_linesize; |
1201 | d2_data += d2_linesize; |
1202 | } |
1203 | } |
1204 | } else { |
1205 | const uint8_t *c0_data = in->data[plane]; |
1206 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
1207 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
1208 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1209 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1210 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1211 | |
1212 | if (mirror) { |
1213 | d0_data += s->size - 1; |
1214 | d1_data += s->size - 1; |
1215 | d2_data += s->size - 1; |
1216 | } |
1217 | |
1218 | for (y = 0; y < src_h; y++) { |
1219 | for (x = 0; x < src_w; x++) { |
1220 | const int c0 = c0_data[x >> c0_shift_w] + 128; |
1221 | const int c1 = c1_data[x >> c1_shift_w] - 128; |
1222 | const int c2 = c2_data[x >> c2_shift_w] - 128; |
1223 | uint8_t *target; |
1224 | |
1225 | if (mirror) { |
1226 | target = d0_data - c0; |
1227 | update(target, max, intensity); |
1228 | target = d1_data - (c0 + c1); |
1229 | update(target, max, intensity); |
1230 | target = d2_data - (c0 + c2); |
1231 | update(target, max, intensity); |
1232 | } else { |
1233 | target = d0_data + c0; |
1234 | update(target, max, intensity); |
1235 | target = d1_data + (c0 + c1); |
1236 | update(target, max, intensity); |
1237 | target = d2_data + (c0 + c2); |
1238 | update(target, max, intensity); |
1239 | } |
1240 | } |
1241 | |
1242 | if (!c0_shift_h || (y & c0_shift_h)) |
1243 | c0_data += c0_linesize; |
1244 | if (!c1_shift_h || (y & c1_shift_h)) |
1245 | c1_data += c1_linesize; |
1246 | if (!c2_shift_h || (y & c2_shift_h)) |
1247 | c2_data += c2_linesize; |
1248 | d0_data += d0_linesize; |
1249 | d1_data += d1_linesize; |
1250 | d2_data += d2_linesize; |
1251 | } |
1252 | } |
1253 | |
1254 | envelope(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y); |
1255 | envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y); |
1256 | envelope(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y); |
1257 | } |
1258 | |
1259 | static av_always_inline void chroma16(WaveformContext *s, |
1260 | AVFrame *in, AVFrame *out, |
1261 | int component, int intensity, |
1262 | int offset_y, int offset_x, |
1263 | int column, int mirror) |
1264 | { |
1265 | const int plane = s->desc->comp[component].plane; |
1266 | const int c0_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; |
1267 | const int c1_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; |
1268 | const int dst_linesize = out->linesize[plane] / 2; |
1269 | const int limit = s->max - 1; |
1270 | const int max = limit - intensity; |
1271 | const int mid = s->max / 2; |
1272 | const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1273 | const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1274 | const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1275 | const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1276 | const int src_h = in->height; |
1277 | const int src_w = in->width; |
1278 | int x, y; |
1279 | |
1280 | if (column) { |
1281 | const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); |
1282 | |
1283 | for (x = 0; x < src_w; x++) { |
1284 | const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1285 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1286 | uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x; |
1287 | uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); |
1288 | uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data); |
1289 | uint16_t *dst = dst_line; |
1290 | |
1291 | for (y = 0; y < src_h; y++) { |
1292 | const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit); |
1293 | uint16_t *target; |
1294 | |
1295 | target = dst + x + dst_signed_linesize * sum; |
1296 | update16(target, max, intensity, limit); |
1297 | |
1298 | if (!c0_shift_h || (y & c0_shift_h)) |
1299 | c0_data += c0_linesize; |
1300 | if (!c1_shift_h || (y & c1_shift_h)) |
1301 | c1_data += c1_linesize; |
1302 | dst_data += dst_linesize; |
1303 | } |
1304 | } |
1305 | } else { |
1306 | const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1307 | const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1308 | uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x; |
1309 | |
1310 | if (mirror) |
1311 | dst_data += s->size - 1; |
1312 | for (y = 0; y < src_h; y++) { |
1313 | for (x = 0; x < src_w; x++) { |
1314 | const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit); |
1315 | uint16_t *target; |
1316 | |
1317 | if (mirror) { |
1318 | target = dst_data - sum; |
1319 | update16(target, max, intensity, limit); |
1320 | } else { |
1321 | target = dst_data + sum; |
1322 | update16(target, max, intensity, limit); |
1323 | } |
1324 | } |
1325 | |
1326 | if (!c0_shift_h || (y & c0_shift_h)) |
1327 | c0_data += c0_linesize; |
1328 | if (!c1_shift_h || (y & c1_shift_h)) |
1329 | c1_data += c1_linesize; |
1330 | dst_data += dst_linesize; |
1331 | } |
1332 | } |
1333 | |
1334 | envelope16(s, out, plane, plane, column ? offset_x : offset_y); |
1335 | } |
1336 | |
1337 | static av_always_inline void chroma(WaveformContext *s, |
1338 | AVFrame *in, AVFrame *out, |
1339 | int component, int intensity, |
1340 | int offset_y, int offset_x, |
1341 | int column, int mirror) |
1342 | { |
1343 | const int plane = s->desc->comp[component].plane; |
1344 | const int c0_linesize = in->linesize[(plane + 1) % s->ncomp]; |
1345 | const int c1_linesize = in->linesize[(plane + 2) % s->ncomp]; |
1346 | const int dst_linesize = out->linesize[plane]; |
1347 | const int max = 255 - intensity; |
1348 | const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1349 | const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1350 | const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1351 | const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1352 | const int src_h = in->height; |
1353 | const int src_w = in->width; |
1354 | int x, y; |
1355 | |
1356 | if (column) { |
1357 | const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); |
1358 | |
1359 | for (x = 0; x < src_w; x++) { |
1360 | const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp]; |
1361 | const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp]; |
1362 | uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x; |
1363 | uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); |
1364 | uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data); |
1365 | uint8_t *dst = dst_line; |
1366 | |
1367 | for (y = 0; y < src_h; y++) { |
1368 | const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127); |
1369 | uint8_t *target; |
1370 | |
1371 | target = dst + x + dst_signed_linesize * sum; |
1372 | update(target, max, intensity); |
1373 | |
1374 | if (!c0_shift_h || (y & c0_shift_h)) |
1375 | c0_data += c0_linesize; |
1376 | if (!c1_shift_h || (y & c1_shift_h)) |
1377 | c1_data += c1_linesize; |
1378 | dst_data += dst_linesize; |
1379 | } |
1380 | } |
1381 | } else { |
1382 | const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp]; |
1383 | const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp]; |
1384 | uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x; |
1385 | |
1386 | if (mirror) |
1387 | dst_data += s->size - 1; |
1388 | for (y = 0; y < src_h; y++) { |
1389 | for (x = 0; x < src_w; x++) { |
1390 | const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127); |
1391 | uint8_t *target; |
1392 | |
1393 | if (mirror) { |
1394 | target = dst_data - sum; |
1395 | update(target, max, intensity); |
1396 | } else { |
1397 | target = dst_data + sum; |
1398 | update(target, max, intensity); |
1399 | } |
1400 | } |
1401 | |
1402 | if (!c0_shift_h || (y & c0_shift_h)) |
1403 | c0_data += c0_linesize; |
1404 | if (!c1_shift_h || (y & c1_shift_h)) |
1405 | c1_data += c1_linesize; |
1406 | dst_data += dst_linesize; |
1407 | } |
1408 | } |
1409 | |
1410 | envelope(s, out, plane, plane, column ? offset_x : offset_y); |
1411 | } |
1412 | |
1413 | static av_always_inline void color16(WaveformContext *s, |
1414 | AVFrame *in, AVFrame *out, |
1415 | int component, int intensity, |
1416 | int offset_y, int offset_x, |
1417 | int column, int mirror) |
1418 | { |
1419 | const int plane = s->desc->comp[component].plane; |
1420 | const int limit = s->max - 1; |
1421 | const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0]; |
1422 | const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1423 | const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1424 | const int c0_linesize = in->linesize[ plane + 0 ] / 2; |
1425 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; |
1426 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; |
1427 | const int d0_linesize = out->linesize[ plane + 0 ] / 2; |
1428 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; |
1429 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; |
1430 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1431 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1432 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1433 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1434 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1435 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1436 | const int src_h = in->height; |
1437 | const int src_w = in->width; |
1438 | int x, y; |
1439 | |
1440 | if (column) { |
1441 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1442 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1443 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1444 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1445 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1446 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1447 | uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1448 | uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1449 | uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1450 | uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1451 | uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1452 | uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1453 | |
1454 | for (y = 0; y < src_h; y++) { |
1455 | for (x = 0; x < src_w; x++) { |
1456 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit); |
1457 | const int c1 = c1_data[x >> c1_shift_w]; |
1458 | const int c2 = c2_data[x >> c2_shift_w]; |
1459 | |
1460 | *(d0 + d0_signed_linesize * c0 + x) = c0; |
1461 | *(d1 + d1_signed_linesize * c0 + x) = c1; |
1462 | *(d2 + d2_signed_linesize * c0 + x) = c2; |
1463 | } |
1464 | |
1465 | if (!c0_shift_h || (y & c0_shift_h)) |
1466 | c0_data += c0_linesize; |
1467 | if (!c1_shift_h || (y & c1_shift_h)) |
1468 | c1_data += c1_linesize; |
1469 | if (!c2_shift_h || (y & c2_shift_h)) |
1470 | c2_data += c2_linesize; |
1471 | d0_data += d0_linesize; |
1472 | d1_data += d1_linesize; |
1473 | d2_data += d2_linesize; |
1474 | } |
1475 | } else { |
1476 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1477 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1478 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1479 | |
1480 | if (mirror) { |
1481 | d0_data += s->size - 1; |
1482 | d1_data += s->size - 1; |
1483 | d2_data += s->size - 1; |
1484 | } |
1485 | |
1486 | for (y = 0; y < src_h; y++) { |
1487 | for (x = 0; x < src_w; x++) { |
1488 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit); |
1489 | const int c1 = c1_data[x >> c1_shift_w]; |
1490 | const int c2 = c2_data[x >> c2_shift_w]; |
1491 | |
1492 | if (mirror) { |
1493 | *(d0_data - c0) = c0; |
1494 | *(d1_data - c0) = c1; |
1495 | *(d2_data - c0) = c2; |
1496 | } else { |
1497 | *(d0_data + c0) = c0; |
1498 | *(d1_data + c0) = c1; |
1499 | *(d2_data + c0) = c2; |
1500 | } |
1501 | } |
1502 | |
1503 | if (!c0_shift_h || (y & c0_shift_h)) |
1504 | c0_data += c0_linesize; |
1505 | if (!c1_shift_h || (y & c1_shift_h)) |
1506 | c1_data += c1_linesize; |
1507 | if (!c2_shift_h || (y & c2_shift_h)) |
1508 | c2_data += c2_linesize; |
1509 | d0_data += d0_linesize; |
1510 | d1_data += d1_linesize; |
1511 | d2_data += d2_linesize; |
1512 | } |
1513 | } |
1514 | |
1515 | envelope16(s, out, plane, plane, column ? offset_x : offset_y); |
1516 | } |
1517 | |
1518 | static av_always_inline void color(WaveformContext *s, |
1519 | AVFrame *in, AVFrame *out, |
1520 | int component, int intensity, |
1521 | int offset_y, int offset_x, |
1522 | int column, int mirror) |
1523 | { |
1524 | const int plane = s->desc->comp[component].plane; |
1525 | const uint8_t *c0_data = in->data[plane + 0]; |
1526 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
1527 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
1528 | const int c0_linesize = in->linesize[ plane + 0 ]; |
1529 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; |
1530 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; |
1531 | const int d0_linesize = out->linesize[ plane + 0 ]; |
1532 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; |
1533 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; |
1534 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1535 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1536 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1537 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1538 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1539 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1540 | const int src_h = in->height; |
1541 | const int src_w = in->width; |
1542 | int x, y; |
1543 | |
1544 | if (s->mode) { |
1545 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1546 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1547 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1548 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1549 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1550 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1551 | uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1552 | uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1553 | uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1554 | uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1555 | uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1556 | uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1557 | |
1558 | for (y = 0; y < src_h; y++) { |
1559 | for (x = 0; x < src_w; x++) { |
1560 | const int c0 = c0_data[x >> c0_shift_w]; |
1561 | const int c1 = c1_data[x >> c1_shift_w]; |
1562 | const int c2 = c2_data[x >> c2_shift_w]; |
1563 | |
1564 | *(d0 + d0_signed_linesize * c0 + x) = c0; |
1565 | *(d1 + d1_signed_linesize * c0 + x) = c1; |
1566 | *(d2 + d2_signed_linesize * c0 + x) = c2; |
1567 | } |
1568 | |
1569 | if (!c0_shift_h || (y & c0_shift_h)) |
1570 | c0_data += c0_linesize; |
1571 | if (!c1_shift_h || (y & c1_shift_h)) |
1572 | c1_data += c1_linesize; |
1573 | if (!c2_shift_h || (y & c2_shift_h)) |
1574 | c2_data += c2_linesize; |
1575 | d0_data += d0_linesize; |
1576 | d1_data += d1_linesize; |
1577 | d2_data += d2_linesize; |
1578 | } |
1579 | } else { |
1580 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1581 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1582 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1583 | |
1584 | if (mirror) { |
1585 | d0_data += s->size - 1; |
1586 | d1_data += s->size - 1; |
1587 | d2_data += s->size - 1; |
1588 | } |
1589 | |
1590 | for (y = 0; y < src_h; y++) { |
1591 | for (x = 0; x < src_w; x++) { |
1592 | const int c0 = c0_data[x >> c0_shift_w]; |
1593 | const int c1 = c1_data[x >> c1_shift_w]; |
1594 | const int c2 = c2_data[x >> c2_shift_w]; |
1595 | |
1596 | if (mirror) { |
1597 | *(d0_data - c0) = c0; |
1598 | *(d1_data - c0) = c1; |
1599 | *(d2_data - c0) = c2; |
1600 | } else { |
1601 | *(d0_data + c0) = c0; |
1602 | *(d1_data + c0) = c1; |
1603 | *(d2_data + c0) = c2; |
1604 | } |
1605 | } |
1606 | |
1607 | if (!c0_shift_h || (y & c0_shift_h)) |
1608 | c0_data += c0_linesize; |
1609 | if (!c1_shift_h || (y & c1_shift_h)) |
1610 | c1_data += c1_linesize; |
1611 | if (!c2_shift_h || (y & c2_shift_h)) |
1612 | c2_data += c2_linesize; |
1613 | d0_data += d0_linesize; |
1614 | d1_data += d1_linesize; |
1615 | d2_data += d2_linesize; |
1616 | } |
1617 | } |
1618 | |
1619 | envelope(s, out, plane, plane, column ? offset_x : offset_y); |
1620 | } |
1621 | |
1622 | static av_always_inline void acolor16(WaveformContext *s, |
1623 | AVFrame *in, AVFrame *out, |
1624 | int component, int intensity, |
1625 | int offset_y, int offset_x, |
1626 | int column, int mirror) |
1627 | { |
1628 | const int plane = s->desc->comp[component].plane; |
1629 | const int limit = s->max - 1; |
1630 | const int max = limit - intensity; |
1631 | const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0]; |
1632 | const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp]; |
1633 | const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp]; |
1634 | const int c0_linesize = in->linesize[ plane + 0 ] / 2; |
1635 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; |
1636 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; |
1637 | const int d0_linesize = out->linesize[ plane + 0 ] / 2; |
1638 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; |
1639 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; |
1640 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1641 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1642 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1643 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1644 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1645 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1646 | const int src_h = in->height; |
1647 | const int src_w = in->width; |
1648 | int x, y; |
1649 | |
1650 | if (s->mode) { |
1651 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1652 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1653 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1654 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1655 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1656 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1657 | uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1658 | uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1659 | uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1660 | uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1661 | uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1662 | uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1663 | |
1664 | for (y = 0; y < src_h; y++) { |
1665 | for (x = 0; x < src_w; x++) { |
1666 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit); |
1667 | const int c1 = c1_data[x >> c1_shift_w]; |
1668 | const int c2 = c2_data[x >> c2_shift_w]; |
1669 | |
1670 | update16(d0 + d0_signed_linesize * c0 + x, max, intensity, limit); |
1671 | *(d1 + d1_signed_linesize * c0 + x) = c1; |
1672 | *(d2 + d2_signed_linesize * c0 + x) = c2; |
1673 | } |
1674 | |
1675 | if (!c0_shift_h || (y & c0_shift_h)) |
1676 | c0_data += c0_linesize; |
1677 | if (!c1_shift_h || (y & c1_shift_h)) |
1678 | c1_data += c1_linesize; |
1679 | if (!c2_shift_h || (y & c2_shift_h)) |
1680 | c2_data += c2_linesize; |
1681 | d0_data += d0_linesize; |
1682 | d1_data += d1_linesize; |
1683 | d2_data += d2_linesize; |
1684 | } |
1685 | } else { |
1686 | uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; |
1687 | uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1688 | uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1689 | |
1690 | if (mirror) { |
1691 | d0_data += s->size - 1; |
1692 | d1_data += s->size - 1; |
1693 | d2_data += s->size - 1; |
1694 | } |
1695 | |
1696 | for (y = 0; y < src_h; y++) { |
1697 | for (x = 0; x < src_w; x++) { |
1698 | const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit); |
1699 | const int c1 = c1_data[x >> c1_shift_w]; |
1700 | const int c2 = c2_data[x >> c2_shift_w]; |
1701 | |
1702 | if (mirror) { |
1703 | update16(d0_data - c0, max, intensity, limit); |
1704 | *(d1_data - c0) = c1; |
1705 | *(d2_data - c0) = c2; |
1706 | } else { |
1707 | update16(d0_data + c0, max, intensity, limit); |
1708 | *(d1_data + c0) = c1; |
1709 | *(d2_data + c0) = c2; |
1710 | } |
1711 | } |
1712 | |
1713 | if (!c0_shift_h || (y & c0_shift_h)) |
1714 | c0_data += c0_linesize; |
1715 | if (!c1_shift_h || (y & c1_shift_h)) |
1716 | c1_data += c1_linesize; |
1717 | if (!c2_shift_h || (y & c2_shift_h)) |
1718 | c2_data += c2_linesize; |
1719 | d0_data += d0_linesize; |
1720 | d1_data += d1_linesize; |
1721 | d2_data += d2_linesize; |
1722 | } |
1723 | } |
1724 | |
1725 | envelope16(s, out, plane, plane, column ? offset_x : offset_y); |
1726 | } |
1727 | |
1728 | static av_always_inline void acolor(WaveformContext *s, |
1729 | AVFrame *in, AVFrame *out, |
1730 | int component, int intensity, |
1731 | int offset_y, int offset_x, |
1732 | int column, int mirror) |
1733 | { |
1734 | const int plane = s->desc->comp[component].plane; |
1735 | const uint8_t *c0_data = in->data[plane + 0]; |
1736 | const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; |
1737 | const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; |
1738 | const int c0_linesize = in->linesize[ plane + 0 ]; |
1739 | const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; |
1740 | const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; |
1741 | const int d0_linesize = out->linesize[ plane + 0 ]; |
1742 | const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; |
1743 | const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; |
1744 | const int c0_shift_w = s->shift_w[ component + 0 ]; |
1745 | const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; |
1746 | const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; |
1747 | const int c0_shift_h = s->shift_h[ component + 0 ]; |
1748 | const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; |
1749 | const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; |
1750 | const int max = 255 - intensity; |
1751 | const int src_h = in->height; |
1752 | const int src_w = in->width; |
1753 | int x, y; |
1754 | |
1755 | if (s->mode) { |
1756 | const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); |
1757 | const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); |
1758 | const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); |
1759 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1760 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1761 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1762 | uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); |
1763 | uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); |
1764 | uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); |
1765 | uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); |
1766 | uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); |
1767 | uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); |
1768 | |
1769 | for (y = 0; y < src_h; y++) { |
1770 | for (x = 0; x < src_w; x++) { |
1771 | const int c0 = c0_data[x >> c0_shift_w]; |
1772 | const int c1 = c1_data[x >> c1_shift_w]; |
1773 | const int c2 = c2_data[x >> c2_shift_w]; |
1774 | |
1775 | update(d0 + d0_signed_linesize * c0 + x, max, intensity); |
1776 | *(d1 + d1_signed_linesize * c0 + x) = c1; |
1777 | *(d2 + d2_signed_linesize * c0 + x) = c2; |
1778 | } |
1779 | |
1780 | if (!c0_shift_h || (y & c0_shift_h)) |
1781 | c0_data += c0_linesize; |
1782 | if (!c1_shift_h || (y & c1_shift_h)) |
1783 | c1_data += c1_linesize; |
1784 | if (!c2_shift_h || (y & c2_shift_h)) |
1785 | c2_data += c2_linesize; |
1786 | d0_data += d0_linesize; |
1787 | d1_data += d1_linesize; |
1788 | d2_data += d2_linesize; |
1789 | } |
1790 | } else { |
1791 | uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; |
1792 | uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; |
1793 | uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; |
1794 | |
1795 | if (mirror) { |
1796 | d0_data += s->size - 1; |
1797 | d1_data += s->size - 1; |
1798 | d2_data += s->size - 1; |
1799 | } |
1800 | |
1801 | for (y = 0; y < src_h; y++) { |
1802 | for (x = 0; x < src_w; x++) { |
1803 | const int c0 = c0_data[x >> c0_shift_w]; |
1804 | const int c1 = c1_data[x >> c1_shift_w]; |
1805 | const int c2 = c2_data[x >> c2_shift_w]; |
1806 | |
1807 | if (mirror) { |
1808 | update(d0_data - c0, max, intensity); |
1809 | *(d1_data - c0) = c1; |
1810 | *(d2_data - c0) = c2; |
1811 | } else { |
1812 | update(d0_data + c0, max, intensity); |
1813 | *(d1_data + c0) = c1; |
1814 | *(d2_data + c0) = c2; |
1815 | } |
1816 | } |
1817 | |
1818 | if (!c0_shift_h || (y & c0_shift_h)) |
1819 | c0_data += c0_linesize; |
1820 | if (!c1_shift_h || (y & c1_shift_h)) |
1821 | c1_data += c1_linesize; |
1822 | if (!c2_shift_h || (y & c2_shift_h)) |
1823 | c2_data += c2_linesize; |
1824 | d0_data += d0_linesize; |
1825 | d1_data += d1_linesize; |
1826 | d2_data += d2_linesize; |
1827 | } |
1828 | } |
1829 | |
1830 | envelope(s, out, plane, plane, column ? offset_x : offset_y); |
1831 | } |
1832 | |
1833 | static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 }; |
1834 | static const uint8_t green_yuva_color[4] = { 255, 0, 0, 255 }; |
1835 | static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 }; |
1836 | |
1837 | static const GraticuleLines aflat_digital8[] = { |
1838 | { { { "16", 16+128 }, { "16", 16+128 }, { "16", 16+128 }, { "0", 0+128 } } }, |
1839 | { { { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 } } }, |
1840 | { { { "235", 235+128 }, { "240", 240+128 }, { "240", 240+128 }, { "255", 255+128 } } }, |
1841 | }; |
1842 | |
1843 | static const GraticuleLines aflat_digital9[] = { |
1844 | { { { "32", 32+256 }, { "32", 32+256 }, { "32", 32+256 }, { "0", 0+256 } } }, |
1845 | { { { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 } } }, |
1846 | { { { "470", 470+256 }, { "480", 480+256 }, { "480", 480+256 }, { "511", 511+256 } } }, |
1847 | }; |
1848 | |
1849 | static const GraticuleLines aflat_digital10[] = { |
1850 | { { { "64", 64+512 }, { "64", 64+512 }, { "64", 64+512 }, { "0", 0+512 } } }, |
1851 | { { { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 } } }, |
1852 | { { { "940", 940+512 }, { "960", 960+512 }, { "960", 960+512 }, { "1023", 1023+512 } } }, |
1853 | }; |
1854 | |
1855 | static const GraticuleLines aflat_digital12[] = { |
1856 | { { { "256", 256+2048 }, { "256", 256+2048 }, { "256", 256+2048 }, { "0", 0+2048 } } }, |
1857 | { { { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 } } }, |
1858 | { { { "3760", 3760+2048 }, { "3840", 3840+2048 }, { "3840", 3840+2048 }, { "4095", 4095+2048 } } }, |
1859 | }; |
1860 | |
1861 | static const GraticuleLines aflat_millivolts8[] = { |
1862 | { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } }, |
1863 | { { { "175", 71+128 }, { "175", 72+128 }, { "175", 72+128 }, { "175", 64+128 } } }, |
1864 | { { { "350", 126+128 }, { "350", 128+128 }, { "350", 128+128 }, { "350", 128+128 } } }, |
1865 | { { { "525", 180+128 }, { "525", 184+128 }, { "525", 184+128 }, { "525", 192+128 } } }, |
1866 | { { { "700", 235+128 }, { "700", 240+128 }, { "700", 240+128 }, { "700", 255+128 } } }, |
1867 | }; |
1868 | |
1869 | static const GraticuleLines aflat_millivolts9[] = { |
1870 | { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } }, |
1871 | { { { "175", 142+256 }, { "175", 144+256 }, { "175", 144+256 }, { "175", 128+256 } } }, |
1872 | { { { "350", 251+256 }, { "350", 256+256 }, { "350", 256+256 }, { "350", 256+256 } } }, |
1873 | { { { "525", 361+256 }, { "525", 368+256 }, { "525", 368+256 }, { "525", 384+256 } } }, |
1874 | { { { "700", 470+256 }, { "700", 480+256 }, { "700", 480+256 }, { "700", 511+256 } } }, |
1875 | }; |
1876 | |
1877 | static const GraticuleLines aflat_millivolts10[] = { |
1878 | { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } }, |
1879 | { { { "175", 283+512 }, { "175", 288+512 }, { "175", 288+512 }, { "175", 256+512 } } }, |
1880 | { { { "350", 502+512 }, { "350", 512+512 }, { "350", 512+512 }, { "350", 512+512 } } }, |
1881 | { { { "525", 721+512 }, { "525", 736+512 }, { "525", 736+512 }, { "525", 768+512 } } }, |
1882 | { { { "700", 940+512 }, { "700", 960+512 }, { "700", 960+512 }, { "700", 1023+512 } } }, |
1883 | }; |
1884 | |
1885 | static const GraticuleLines aflat_millivolts12[] = { |
1886 | { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } }, |
1887 | { { { "175", 1132+2048 }, { "175", 1152+2048 }, { "175", 1152+2048 }, { "175", 1024+2048 } } }, |
1888 | { { { "350", 2008+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 } } }, |
1889 | { { { "525", 2884+2048 }, { "525", 2944+2048 }, { "525", 2944+2048 }, { "525", 3072+2048 } } }, |
1890 | { { { "700", 3760+2048 }, { "700", 3840+2048 }, { "700", 3840+2048 }, { "700", 4095+2048 } } }, |
1891 | }; |
1892 | |
1893 | static const GraticuleLines aflat_ire8[] = { |
1894 | { { { "-25", -39+128 }, { "-25", -40+128 }, { "-25", -40+128 }, { "-25", -64+128 } } }, |
1895 | { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } }, |
1896 | { { { "25", 71+128 }, { "25", 72+128 }, { "25", 72+128 }, { "25", 64+128 } } }, |
1897 | { { { "50", 126+128 }, { "50", 128+128 }, { "50", 128+128 }, { "50", 128+128 } } }, |
1898 | { { { "75", 180+128 }, { "75", 184+128 }, { "75", 184+128 }, { "75", 192+128 } } }, |
1899 | { { { "100", 235+128 }, { "100", 240+128 }, { "100", 240+128 }, { "100", 256+128 } } }, |
1900 | { { { "125", 290+128 }, { "125", 296+128 }, { "125", 296+128 }, { "125", 320+128 } } }, |
1901 | }; |
1902 | |
1903 | static const GraticuleLines aflat_ire9[] = { |
1904 | { { { "-25", -78+256 }, { "-25", -80+256 }, { "-25", -80+256 }, { "-25",-128+256 } } }, |
1905 | { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } }, |
1906 | { { { "25", 142+256 }, { "25", 144+256 }, { "25", 144+256 }, { "25", 128+256 } } }, |
1907 | { { { "50", 251+256 }, { "50", 256+256 }, { "50", 256+256 }, { "50", 256+256 } } }, |
1908 | { { { "75", 361+256 }, { "75", 368+256 }, { "75", 368+256 }, { "75", 384+256 } } }, |
1909 | { { { "100", 470+256 }, { "100", 480+256 }, { "100", 480+256 }, { "100", 512+256 } } }, |
1910 | { { { "125", 580+256 }, { "125", 592+256 }, { "125", 592+256 }, { "125", 640+256 } } }, |
1911 | }; |
1912 | |
1913 | static const GraticuleLines aflat_ire10[] = { |
1914 | { { { "-25",-156+512 }, { "-25",-160+512 }, { "-25",-160+512 }, { "-25", -256+512 } } }, |
1915 | { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } }, |
1916 | { { { "25", 283+512 }, { "25", 288+512 }, { "25", 288+512 }, { "25", 256+512 } } }, |
1917 | { { { "50", 502+512 }, { "50", 512+512 }, { "50", 512+512 }, { "50", 512+512 } } }, |
1918 | { { { "75", 721+512 }, { "75", 736+512 }, { "75", 736+512 }, { "75", 768+512 } } }, |
1919 | { { { "100", 940+512 }, { "100", 960+512 }, { "100", 960+512 }, { "100", 1024+512 } } }, |
1920 | { { { "125",1160+512 }, { "125",1184+512 }, { "125",1184+512 }, { "125", 1280+512 } } }, |
1921 | }; |
1922 | |
1923 | static const GraticuleLines aflat_ire12[] = { |
1924 | { { { "-25", -624+2048 }, { "-25", -640+2048 }, { "-25", -640+2048 }, { "-25",-1024+2048 } } }, |
1925 | { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } }, |
1926 | { { { "25", 1132+2048 }, { "25", 1152+2048 }, { "25", 1152+2048 }, { "25", 1024+2048 } } }, |
1927 | { { { "50", 2008+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 } } }, |
1928 | { { { "75", 2884+2048 }, { "75", 2944+2048 }, { "75", 2944+2048 }, { "75", 3072+2048 } } }, |
1929 | { { { "100", 3760+2048 }, { "100", 3840+2048 }, { "100", 3840+2048 }, { "100", 4096+2048 } } }, |
1930 | { { { "125", 4640+2048 }, { "125", 4736+2048 }, { "125", 4736+2048 }, { "125", 5120+2048 } } }, |
1931 | }; |
1932 | |
1933 | static const GraticuleLines flat_digital8[] = { |
1934 | { { { "16", 16+256 }, { "16", 16+256 }, { "16", 16+256 }, { "0", 0+256 } } }, |
1935 | { { { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 } } }, |
1936 | { { { "235", 235+256 }, { "240", 240+256 }, { "240", 240+256 }, { "255", 255+256 } } }, |
1937 | }; |
1938 | |
1939 | static const GraticuleLines flat_digital9[] = { |
1940 | { { { "32", 32+512 }, { "32", 32+512 }, { "32", 32+512 }, { "0", 0+512 } } }, |
1941 | { { { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 } } }, |
1942 | { { { "470", 470+512 }, { "480", 480+512 }, { "480", 480+512 }, { "511", 511+512 } } }, |
1943 | }; |
1944 | |
1945 | static const GraticuleLines flat_digital10[] = { |
1946 | { { { "64", 64+1024 }, { "64", 64+1024 }, { "64", 64+1024 }, { "0", 0+1024 } } }, |
1947 | { { { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 } } }, |
1948 | { { { "940", 940+1024 }, { "960", 960+1024 }, { "960", 960+1024 }, { "1023", 1023+1024 } } }, |
1949 | }; |
1950 | |
1951 | static const GraticuleLines flat_digital12[] = { |
1952 | { { { "256", 256+4096 }, { "256", 256+4096 }, { "256", 256+4096 }, { "0", 0+4096 } } }, |
1953 | { { { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 } } }, |
1954 | { { { "3760", 3760+4096 }, { "3840", 3840+4096 }, { "3840", 3840+4096 }, { "4095", 4095+4096 } } }, |
1955 | }; |
1956 | |
1957 | static const GraticuleLines flat_millivolts8[] = { |
1958 | { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } }, |
1959 | { { { "175", 71+256 }, { "175", 72+256 }, { "175", 72+256 }, { "175", 64+256 } } }, |
1960 | { { { "350", 126+256 }, { "350", 128+256 }, { "350", 128+256 }, { "350", 128+256 } } }, |
1961 | { { { "525", 180+256 }, { "525", 184+256 }, { "525", 184+256 }, { "525", 192+256 } } }, |
1962 | { { { "700", 235+256 }, { "700", 240+256 }, { "700", 240+256 }, { "700", 255+256 } } }, |
1963 | }; |
1964 | |
1965 | static const GraticuleLines flat_millivolts9[] = { |
1966 | { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } }, |
1967 | { { { "175", 142+512 }, { "175", 144+512 }, { "175", 144+512 }, { "175", 128+512 } } }, |
1968 | { { { "350", 251+512 }, { "350", 256+512 }, { "350", 256+512 }, { "350", 256+512 } } }, |
1969 | { { { "525", 361+512 }, { "525", 368+512 }, { "525", 368+512 }, { "525", 384+512 } } }, |
1970 | { { { "700", 470+512 }, { "700", 480+512 }, { "700", 480+512 }, { "700", 511+512 } } }, |
1971 | }; |
1972 | |
1973 | static const GraticuleLines flat_millivolts10[] = { |
1974 | { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } }, |
1975 | { { { "175", 283+1024 }, { "175", 288+1024 }, { "175", 288+1024 }, { "175", 256+1024 } } }, |
1976 | { { { "350", 502+1024 }, { "350", 512+1024 }, { "350", 512+1024 }, { "350", 512+1024 } } }, |
1977 | { { { "525", 721+1024 }, { "525", 736+1024 }, { "525", 736+1024 }, { "525", 768+1024 } } }, |
1978 | { { { "700", 940+1024 }, { "700", 960+1024 }, { "700", 960+1024 }, { "700", 1023+1024 } } }, |
1979 | }; |
1980 | |
1981 | static const GraticuleLines flat_millivolts12[] = { |
1982 | { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } }, |
1983 | { { { "175", 1132+4096 }, { "175", 1152+4096 }, { "175", 1152+4096 }, { "175", 1024+4096 } } }, |
1984 | { { { "350", 2008+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 } } }, |
1985 | { { { "525", 2884+4096 }, { "525", 2944+4096 }, { "525", 2944+4096 }, { "525", 3072+4096 } } }, |
1986 | { { { "700", 3760+4096 }, { "700", 3840+4096 }, { "700", 3840+4096 }, { "700", 4095+4096 } } }, |
1987 | }; |
1988 | |
1989 | static const GraticuleLines flat_ire8[] = { |
1990 | { { { "-25", -39+256 }, { "-25", -40+256 }, { "-25", -40+256 }, { "-25", -64+256 } } }, |
1991 | { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } }, |
1992 | { { { "25", 71+256 }, { "25", 72+256 }, { "25", 72+256 }, { "25", 64+256 } } }, |
1993 | { { { "50", 126+256 }, { "50", 128+256 }, { "50", 128+256 }, { "50", 128+256 } } }, |
1994 | { { { "75", 180+256 }, { "75", 184+256 }, { "75", 184+256 }, { "75", 192+256 } } }, |
1995 | { { { "100", 235+256 }, { "100", 240+256 }, { "100", 240+256 }, { "100", 256+256 } } }, |
1996 | { { { "125", 290+256 }, { "125", 296+256 }, { "125", 296+256 }, { "125", 320+256 } } }, |
1997 | }; |
1998 | |
1999 | static const GraticuleLines flat_ire9[] = { |
2000 | { { { "-25", -78+512 }, { "-25", -80+512 }, { "-25", -80+512 }, { "-25",-128+512 } } }, |
2001 | { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } }, |
2002 | { { { "25", 142+512 }, { "25", 144+512 }, { "25", 144+512 }, { "25", 128+512 } } }, |
2003 | { { { "50", 251+512 }, { "50", 256+512 }, { "50", 256+512 }, { "50", 256+512 } } }, |
2004 | { { { "75", 361+512 }, { "75", 368+512 }, { "75", 368+512 }, { "75", 384+512 } } }, |
2005 | { { { "100", 470+512 }, { "100", 480+512 }, { "100", 480+512 }, { "100", 512+512 } } }, |
2006 | { { { "125", 580+512 }, { "125", 592+512 }, { "125", 592+512 }, { "125", 640+512 } } }, |
2007 | }; |
2008 | |
2009 | static const GraticuleLines flat_ire10[] = { |
2010 | { { { "-25",-156+1024 }, { "-25",-160+1024 }, { "-25",-160+1024 }, { "-25", -256+1024 } } }, |
2011 | { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } }, |
2012 | { { { "25", 283+1024 }, { "25", 288+1024 }, { "25", 288+1024 }, { "25", 256+1024 } } }, |
2013 | { { { "50", 502+1024 }, { "50", 512+1024 }, { "50", 512+1024 }, { "50", 512+1024 } } }, |
2014 | { { { "75", 721+1024 }, { "75", 736+1024 }, { "75", 736+1024 }, { "75", 768+1024 } } }, |
2015 | { { { "100", 940+1024 }, { "100", 960+1024 }, { "100", 960+1024 }, { "100", 1024+1024 } } }, |
2016 | { { { "125",1160+1024 }, { "125",1184+1024 }, { "125",1184+1024 }, { "125", 1280+1024 } } }, |
2017 | }; |
2018 | |
2019 | static const GraticuleLines flat_ire12[] = { |
2020 | { { { "-25", -624+4096 }, { "-25", -640+4096 }, { "-25", -640+4096 }, { "-25",-1024+4096 } } }, |
2021 | { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } }, |
2022 | { { { "25", 1132+4096 }, { "25", 1152+4096 }, { "25", 1152+4096 }, { "25", 1024+4096 } } }, |
2023 | { { { "50", 2008+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 } } }, |
2024 | { { { "75", 2884+4096 }, { "75", 2944+4096 }, { "75", 2944+4096 }, { "75", 3072+4096 } } }, |
2025 | { { { "100", 3760+4096 }, { "100", 3840+4096 }, { "100", 3840+4096 }, { "100", 4096+4096 } } }, |
2026 | { { { "125", 4640+4096 }, { "125", 4736+4096 }, { "125", 4736+4096 }, { "125", 5120+4096 } } }, |
2027 | }; |
2028 | |
2029 | static const GraticuleLines digital8[] = { |
2030 | { { { "16", 16 }, { "16", 16 }, { "16", 16 }, { "0", 0 } } }, |
2031 | { { { "128", 128 }, { "128", 128 }, { "128", 128 }, { "128", 128 } } }, |
2032 | { { { "235", 235 }, { "240", 240 }, { "240", 240 }, { "255", 255 } } }, |
2033 | }; |
2034 | |
2035 | static const GraticuleLines digital9[] = { |
2036 | { { { "32", 32 }, { "32", 32 }, { "32", 32 }, { "0", 0 } } }, |
2037 | { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "256", 256 } } }, |
2038 | { { { "470", 470 }, { "480", 480 }, { "480", 480 }, { "511", 511 } } }, |
2039 | }; |
2040 | |
2041 | static const GraticuleLines digital10[] = { |
2042 | { { { "64", 64 }, { "64", 64 }, { "64", 64 }, { "0", 0 } } }, |
2043 | { { { "512", 512 }, { "512", 512 }, { "512", 512 }, { "512", 512 } } }, |
2044 | { { { "940", 940 }, { "960", 960 }, { "960", 960 }, { "1023", 1023 } } }, |
2045 | }; |
2046 | |
2047 | static const GraticuleLines digital12[] = { |
2048 | { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "0", 0 } } }, |
2049 | { { { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 } } }, |
2050 | { { { "3760", 3760 }, { "3840", 3840 }, { "3840", 3840 }, { "4095", 4095 } } }, |
2051 | }; |
2052 | |
2053 | static const GraticuleLines millivolts8[] = { |
2054 | { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } }, |
2055 | { { { "175", 71 }, { "175", 72 }, { "175", 72 }, { "175", 64 } } }, |
2056 | { { { "350", 126 }, { "350", 128 }, { "350", 128 }, { "350", 128 } } }, |
2057 | { { { "525", 180 }, { "525", 184 }, { "525", 184 }, { "525", 192 } } }, |
2058 | { { { "700", 235 }, { "700", 240 }, { "700", 240 }, { "700", 255 } } }, |
2059 | }; |
2060 | |
2061 | static const GraticuleLines millivolts9[] = { |
2062 | { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } }, |
2063 | { { { "175", 142 }, { "175", 144 }, { "175", 144 }, { "175", 128 } } }, |
2064 | { { { "350", 251 }, { "350", 256 }, { "350", 256 }, { "350", 256 } } }, |
2065 | { { { "525", 361 }, { "525", 368 }, { "525", 368 }, { "525", 384 } } }, |
2066 | { { { "700", 470 }, { "700", 480 }, { "700", 480 }, { "700", 511 } } }, |
2067 | }; |
2068 | |
2069 | static const GraticuleLines millivolts10[] = { |
2070 | { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } }, |
2071 | { { { "175", 283 }, { "175", 288 }, { "175", 288 }, { "175", 256 } } }, |
2072 | { { { "350", 502 }, { "350", 512 }, { "350", 512 }, { "350", 512 } } }, |
2073 | { { { "525", 721 }, { "525", 736 }, { "525", 736 }, { "525", 768 } } }, |
2074 | { { { "700", 940 }, { "700", 960 }, { "700", 960 }, { "700", 1023 } } }, |
2075 | }; |
2076 | |
2077 | static const GraticuleLines millivolts12[] = { |
2078 | { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } }, |
2079 | { { { "175", 1132 }, { "175", 1152 }, { "175", 1152 }, { "175", 1024 } } }, |
2080 | { { { "350", 2008 }, { "350", 2048 }, { "350", 2048 }, { "350", 2048 } } }, |
2081 | { { { "525", 2884 }, { "525", 2944 }, { "525", 2944 }, { "525", 3072 } } }, |
2082 | { { { "700", 3760 }, { "700", 3840 }, { "700", 3840 }, { "700", 4095 } } }, |
2083 | }; |
2084 | |
2085 | static const GraticuleLines ire8[] = { |
2086 | { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } }, |
2087 | { { { "25", 71 }, { "25", 72 }, { "25", 72 }, { "25", 64 } } }, |
2088 | { { { "50", 126 }, { "50", 128 }, { "50", 128 }, { "50", 128 } } }, |
2089 | { { { "75", 180 }, { "75", 184 }, { "75", 184 }, { "75", 192 } } }, |
2090 | { { { "100", 235 }, { "100", 240 }, { "100", 240 }, { "100", 255 } } }, |
2091 | }; |
2092 | |
2093 | static const GraticuleLines ire9[] = { |
2094 | { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } }, |
2095 | { { { "25", 142 }, { "25", 144 }, { "25", 144 }, { "25", 128 } } }, |
2096 | { { { "50", 251 }, { "50", 256 }, { "50", 256 }, { "50", 256 } } }, |
2097 | { { { "75", 361 }, { "75", 368 }, { "75", 368 }, { "75", 384 } } }, |
2098 | { { { "100", 470 }, { "100", 480 }, { "100", 480 }, { "100", 511 } } }, |
2099 | }; |
2100 | |
2101 | static const GraticuleLines ire10[] = { |
2102 | { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } }, |
2103 | { { { "25", 283 }, { "25", 288 }, { "25", 288 }, { "25", 256 } } }, |
2104 | { { { "50", 502 }, { "50", 512 }, { "50", 512 }, { "50", 512 } } }, |
2105 | { { { "75", 721 }, { "75", 736 }, { "75", 736 }, { "75", 768 } } }, |
2106 | { { { "100", 940 }, { "100", 960 }, { "100", 960 }, { "100", 1023 } } }, |
2107 | }; |
2108 | |
2109 | static const GraticuleLines ire12[] = { |
2110 | { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } }, |
2111 | { { { "25", 1132 }, { "25", 1152 }, { "25", 1152 }, { "25", 1024 } } }, |
2112 | { { { "50", 2008 }, { "50", 2048 }, { "50", 2048 }, { "50", 2048 } } }, |
2113 | { { { "75", 2884 }, { "75", 2944 }, { "75", 2944 }, { "75", 3072 } } }, |
2114 | { { { "100", 3760 }, { "100", 3840 }, { "100", 3840 }, { "100", 4095 } } }, |
2115 | }; |
2116 | |
2117 | static const GraticuleLines chroma_digital8[] = { |
2118 | { { { "50", 50 }, { "50", 50 }, { "50", 50 }, { "50", 50 } } }, |
2119 | { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } }, |
2120 | { { { "150", 150 }, { "150", 150 }, { "150", 150 }, { "150", 150 } } }, |
2121 | { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } }, |
2122 | { { { "255", 255 }, { "255", 255 }, { "255", 255 }, { "255", 255 } } }, |
2123 | }; |
2124 | |
2125 | static const GraticuleLines chroma_digital9[] = { |
2126 | { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } }, |
2127 | { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } }, |
2128 | { { { "300", 300 }, { "300", 300 }, { "300", 300 }, { "300", 300 } } }, |
2129 | { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } }, |
2130 | { { { "500", 500 }, { "500", 500 }, { "500", 500 }, { "500", 500 } } }, |
2131 | }; |
2132 | |
2133 | static const GraticuleLines chroma_digital10[] = { |
2134 | { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } }, |
2135 | { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } }, |
2136 | { { { "600", 600 }, { "600", 600 }, { "600", 600 }, { "600", 600 } } }, |
2137 | { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } }, |
2138 | { { {"1000",1000 }, {"1000",1000 }, {"1000",1000 }, {"1000",1000 } } }, |
2139 | }; |
2140 | |
2141 | static const GraticuleLines chroma_digital12[] = { |
2142 | { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } }, |
2143 | { { { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 } } }, |
2144 | { { { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 } } }, |
2145 | { { { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 } } }, |
2146 | { { { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 } } }, |
2147 | }; |
2148 | |
2149 | static void blend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step) |
2150 | { |
2151 | int y; |
2152 | |
2153 | for (y = 0; y < height; y += step) { |
2154 | dst[0] = v * o1 + dst[0] * o2; |
2155 | |
2156 | dst += linesize * step; |
2157 | } |
2158 | } |
2159 | |
2160 | static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step) |
2161 | { |
2162 | int y; |
2163 | |
2164 | for (y = 0; y < height; y += step) { |
2165 | dst[0] = v * o1 + dst[0] * o2; |
2166 | |
2167 | dst += (linesize / 2) * step; |
2168 | } |
2169 | } |
2170 | |
2171 | static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step) |
2172 | { |
2173 | int x; |
2174 | |
2175 | for (x = 0; x < width; x += step) { |
2176 | dst[x] = v * o1 + dst[x] * o2; |
2177 | } |
2178 | } |
2179 | |
2180 | static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step) |
2181 | { |
2182 | int x; |
2183 | |
2184 | for (x = 0; x < width; x += step) { |
2185 | dst[x] = v * o1 + dst[x] * o2; |
2186 | } |
2187 | } |
2188 | |
2189 | static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) |
2190 | { |
2191 | const uint8_t *font; |
2192 | int font_height; |
2193 | int i, plane; |
2194 | |
2195 | font = avpriv_cga_font, font_height = 8; |
2196 | |
2197 | for (plane = 0; plane < 4 && out->data[plane]; plane++) { |
2198 | for (i = 0; txt[i]; i++) { |
2199 | int char_y, mask; |
2200 | int v = color[plane]; |
2201 | |
2202 | uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8); |
2203 | for (char_y = 0; char_y < font_height; char_y++) { |
2204 | for (mask = 0x80; mask; mask >>= 1) { |
2205 | if (font[txt[i] * font_height + char_y] & mask) |
2206 | p[0] = p[0] * o2 + v * o1; |
2207 | p++; |
2208 | } |
2209 | p += out->linesize[plane] - 8; |
2210 | } |
2211 | } |
2212 | } |
2213 | } |
2214 | |
2215 | static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) |
2216 | { |
2217 | const uint8_t *font; |
2218 | int font_height; |
2219 | int i, plane; |
2220 | |
2221 | font = avpriv_cga_font, font_height = 8; |
2222 | |
2223 | for (plane = 0; plane < 4 && out->data[plane]; plane++) { |
2224 | for (i = 0; txt[i]; i++) { |
2225 | int char_y, mask; |
2226 | int v = color[plane] * mult; |
2227 | |
2228 | uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8); |
2229 | for (char_y = 0; char_y < font_height; char_y++) { |
2230 | for (mask = 0x80; mask; mask >>= 1) { |
2231 | if (font[txt[i] * font_height + char_y] & mask) |
2232 | p[0] = p[0] * o2 + v * o1; |
2233 | p++; |
2234 | } |
2235 | p += out->linesize[plane] / 2 - 8; |
2236 | } |
2237 | } |
2238 | } |
2239 | } |
2240 | |
2241 | static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) |
2242 | { |
2243 | const uint8_t *font; |
2244 | int font_height; |
2245 | int i, plane; |
2246 | |
2247 | font = avpriv_cga_font, font_height = 8; |
2248 | |
2249 | for (plane = 0; plane < 4 && out->data[plane]; plane++) { |
2250 | for (i = 0; txt[i]; i++) { |
2251 | int char_y, mask; |
2252 | int v = color[plane]; |
2253 | |
2254 | for (char_y = font_height - 1; char_y >= 0; char_y--) { |
2255 | uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x; |
2256 | for (mask = 0x80; mask; mask >>= 1) { |
2257 | if (font[txt[i] * font_height + font_height - 1 - char_y] & mask) |
2258 | p[char_y] = p[char_y] * o2 + v * o1; |
2259 | p += out->linesize[plane]; |
2260 | } |
2261 | } |
2262 | } |
2263 | } |
2264 | } |
2265 | |
2266 | static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) |
2267 | { |
2268 | const uint8_t *font; |
2269 | int font_height; |
2270 | int i, plane; |
2271 | |
2272 | font = avpriv_cga_font, font_height = 8; |
2273 | |
2274 | for (plane = 0; plane < 4 && out->data[plane]; plane++) { |
2275 | for (i = 0; txt[i]; i++) { |
2276 | int char_y, mask; |
2277 | int v = color[plane] * mult; |
2278 | |
2279 | for (char_y = 0; char_y < font_height; char_y++) { |
2280 | uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x; |
2281 | for (mask = 0x80; mask; mask >>= 1) { |
2282 | if (font[txt[i] * font_height + font_height - 1 - char_y] & mask) |
2283 | p[char_y] = p[char_y] * o2 + v * o1; |
2284 | p += out->linesize[plane] / 2; |
2285 | } |
2286 | } |
2287 | } |
2288 | } |
2289 | } |
2290 | |
2291 | static void graticule_none(WaveformContext *s, AVFrame *out) |
2292 | { |
2293 | } |
2294 | |
2295 | static void graticule_green_row(WaveformContext *s, AVFrame *out) |
2296 | { |
2297 | const int step = (s->flags & 2) + 1; |
2298 | const float o1 = s->opacity; |
2299 | const float o2 = 1. - o1; |
2300 | const int height = s->display == PARADE ? out->height / s->acomp : out->height; |
2301 | int k = 0, c, p, l, offset_x = 0, offset_y = 0; |
2302 | |
2303 | for (c = 0; c < s->ncomp; c++) { |
2304 | if (!((1 << c) & s->pcomp) || (!s->display && k > 0)) |
2305 | continue; |
2306 | |
2307 | k++; |
2308 | for (p = 0; p < s->ncomp; p++) { |
2309 | const int v = green_yuva_color[p]; |
2310 | for (l = 0; l < s->nb_glines; l++) { |
2311 | const uint16_t pos = s->glines[l].line[c].pos; |
2312 | int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); |
2313 | uint8_t *dst = out->data[p] + offset_y * out->linesize[p] + x; |
2314 | |
2315 | blend_vline(dst, height, out->linesize[p], o1, o2, v, step); |
2316 | } |
2317 | } |
2318 | |
2319 | for (l = 0; l < s->nb_glines && (s->flags & 1); l++) { |
2320 | const char *name = s->glines[l].line[c].name; |
2321 | const uint16_t pos = s->glines[l].line[c].pos; |
2322 | int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10; |
2323 | |
2324 | if (x < 0) |
2325 | x = 4; |
2326 | |
2327 | draw_vtext(out, x, offset_y + 2, o1, o2, name, green_yuva_color); |
2328 | } |
2329 | |
2330 | offset_x += s->size * (s->display == STACK); |
2331 | offset_y += height * (s->display == PARADE); |
2332 | } |
2333 | } |
2334 | |
2335 | static void graticule16_green_row(WaveformContext *s, AVFrame *out) |
2336 | { |
2337 | const int step = (s->flags & 2) + 1; |
2338 | const float o1 = s->opacity; |
2339 | const float o2 = 1. - o1; |
2340 | const int mult = s->size / 256; |
2341 | const int height = s->display == PARADE ? out->height / s->acomp : out->height; |
2342 | int k = 0, c, p, l, offset_x = 0, offset_y = 0; |
2343 | |
2344 | for (c = 0; c < s->ncomp; c++) { |
2345 | if (!((1 << c) & s->pcomp) || (!s->display && k > 0)) |
2346 | continue; |
2347 | |
2348 | k++; |
2349 | for (p = 0; p < s->ncomp; p++) { |
2350 | const int v = green_yuva_color[p] * mult; |
2351 | for (l = 0; l < s->nb_glines ; l++) { |
2352 | const uint16_t pos = s->glines[l].line[c].pos; |
2353 | int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); |
2354 | uint16_t *dst = (uint16_t *)(out->data[p] + offset_y * out->linesize[p]) + x; |
2355 | |
2356 | blend_vline16(dst, height, out->linesize[p], o1, o2, v, step); |
2357 | } |
2358 | } |
2359 | |
2360 | for (l = 0; l < s->nb_glines && (s->flags & 1); l++) { |
2361 | const char *name = s->glines[l].line[c].name; |
2362 | const uint16_t pos = s->glines[l].line[c].pos; |
2363 | int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10; |
2364 | |
2365 | if (x < 0) |
2366 | x = 4; |
2367 | |
2368 | draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, green_yuva_color); |
2369 | } |
2370 | |
2371 | offset_x += s->size * (s->display == STACK); |
2372 | offset_y += height * (s->display == PARADE); |
2373 | } |
2374 | } |
2375 | |
2376 | static void graticule_green_column(WaveformContext *s, AVFrame *out) |
2377 | { |
2378 | const int step = (s->flags & 2) + 1; |
2379 | const float o1 = s->opacity; |
2380 | const float o2 = 1. - o1; |
2381 | const int width = s->display == PARADE ? out->width / s->acomp : out->width; |
2382 | int k = 0, c, p, l, offset_y = 0, offset_x = 0; |
2383 | |
2384 | for (c = 0; c < s->ncomp; c++) { |
2385 | if ((!((1 << c) & s->pcomp) || (!s->display && k > 0))) |
2386 | continue; |
2387 | |
2388 | k++; |
2389 | for (p = 0; p < s->ncomp; p++) { |
2390 | const int v = green_yuva_color[p]; |
2391 | for (l = 0; l < s->nb_glines ; l++) { |
2392 | const uint16_t pos = s->glines[l].line[c].pos; |
2393 | int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); |
2394 | uint8_t *dst = out->data[p] + y * out->linesize[p] + offset_x; |
2395 | |
2396 | blend_hline(dst, width, o1, o2, v, step); |
2397 | } |
2398 | } |
2399 | |
2400 | for (l = 0; l < s->nb_glines && (s->flags & 1); l++) { |
2401 | const char *name = s->glines[l].line[c].name; |
2402 | const uint16_t pos = s->glines[l].line[c].pos; |
2403 | int y = offset_y + (s->mirror ? s->size - 1 - pos : pos) - 10; |
2404 | |
2405 | if (y < 0) |
2406 | y = 4; |
2407 | |
2408 | draw_htext(out, 2 + offset_x, y, o1, o2, name, green_yuva_color); |
2409 | } |
2410 | |
2411 | offset_y += s->size * (s->display == STACK); |
2412 | offset_x += width * (s->display == PARADE); |
2413 | } |
2414 | } |
2415 | |
2416 | static void graticule16_green_column(WaveformContext *s, AVFrame *out) |
2417 | { |
2418 | const int step = (s->flags & 2) + 1; |
2419 | const float o1 = s->opacity; |
2420 | const float o2 = 1. - o1; |
2421 | const int mult = s->size / 256; |
2422 | const int width = s->display == PARADE ? out->width / s->acomp : out->width; |
2423 | int k = 0, c, p, l, offset_x = 0, offset_y = 0; |
2424 | |
2425 | for (c = 0; c < s->ncomp; c++) { |
2426 | if ((!((1 << c) & s->pcomp) || (!s->display && k > 0))) |
2427 | continue; |
2428 | |
2429 | k++; |
2430 | for (p = 0; p < s->ncomp; p++) { |
2431 | const int v = green_yuva_color[p] * mult; |
2432 | for (l = 0; l < s->nb_glines ; l++) { |
2433 | const uint16_t pos = s->glines[l].line[c].pos; |
2434 | int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); |
2435 | uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]) + offset_x; |
2436 | |
2437 | blend_hline16(dst, width, o1, o2, v, step); |
2438 | } |
2439 | } |
2440 | |
2441 | for (l = 0; l < s->nb_glines && (s->flags & 1); l++) { |
2442 | const char *name = s->glines[l].line[c].name; |
2443 | const uint16_t pos = s->glines[l].line[c].pos; |
2444 | int y = offset_y + (s->mirror ? s->size - 1 - pos: pos) - 10; |
2445 | |
2446 | if (y < 0) |
2447 | y = 4; |
2448 | |
2449 | draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, green_yuva_color); |
2450 | } |
2451 | |
2452 | offset_y += s->size * (s->display == STACK); |
2453 | offset_x += width * (s->display == PARADE); |
2454 | } |
2455 | } |
2456 | |
2457 | static int config_input(AVFilterLink *inlink) |
2458 | { |
2459 | AVFilterContext *ctx = inlink->dst; |
2460 | WaveformContext *s = ctx->priv; |
2461 | |
2462 | s->desc = av_pix_fmt_desc_get(inlink->format); |
2463 | s->ncomp = s->desc->nb_components; |
2464 | s->bits = s->desc->comp[0].depth; |
2465 | s->max = 1 << s->bits; |
2466 | s->intensity = s->fintensity * (s->max - 1); |
2467 | |
2468 | s->shift_w[0] = s->shift_w[3] = 0; |
2469 | s->shift_h[0] = s->shift_h[3] = 0; |
2470 | s->shift_w[1] = s->shift_w[2] = s->desc->log2_chroma_w; |
2471 | s->shift_h[1] = s->shift_h[2] = s->desc->log2_chroma_h; |
2472 | |
2473 | s->graticulef = graticule_none; |
2474 | |
2475 | switch (s->filter) { |
2476 | case AFLAT: s->size = 256 * 2; break; |
2477 | case FLAT: s->size = 256 * 3; break; |
2478 | default: s->size = 256; break; |
2479 | } |
2480 | |
2481 | switch (s->filter | ((s->bits > 8) << 4) | |
2482 | (s->mode << 8) | (s->mirror << 12)) { |
2483 | case 0x1100: s->waveform = lowpass_column_mirror; break; |
2484 | case 0x1000: s->waveform = lowpass_row_mirror; break; |
2485 | case 0x0100: s->waveform = lowpass_column; break; |
2486 | case 0x0000: s->waveform = lowpass_row; break; |
2487 | case 0x1110: s->waveform = lowpass16_column_mirror; break; |
2488 | case 0x1010: s->waveform = lowpass16_row_mirror; break; |
2489 | case 0x0110: s->waveform = lowpass16_column; break; |
2490 | case 0x0010: s->waveform = lowpass16_row; break; |
2491 | case 0x1101: |
2492 | case 0x1001: |
2493 | case 0x0101: |
2494 | case 0x0001: s->waveform = flat; break; |
2495 | case 0x1111: |
2496 | case 0x1011: |
2497 | case 0x0111: |
2498 | case 0x0011: s->waveform = flat16; break; |
2499 | case 0x1102: |
2500 | case 0x1002: |
2501 | case 0x0102: |
2502 | case 0x0002: s->waveform = aflat; break; |
2503 | case 0x1112: |
2504 | case 0x1012: |
2505 | case 0x0112: |
2506 | case 0x0012: s->waveform = aflat16; break; |
2507 | case 0x1103: |
2508 | case 0x1003: |
2509 | case 0x0103: |
2510 | case 0x0003: s->waveform = chroma; break; |
2511 | case 0x1113: |
2512 | case 0x1013: |
2513 | case 0x0113: |
2514 | case 0x0013: s->waveform = chroma16; break; |
2515 | case 0x1104: |
2516 | case 0x1004: |
2517 | case 0x0104: |
2518 | case 0x0004: s->waveform = color; break; |
2519 | case 0x1114: |
2520 | case 0x1014: |
2521 | case 0x0114: |
2522 | case 0x0014: s->waveform = color16; break; |
2523 | case 0x1105: |
2524 | case 0x1005: |
2525 | case 0x0105: |
2526 | case 0x0005: s->waveform = acolor; break; |
2527 | case 0x1115: |
2528 | case 0x1015: |
2529 | case 0x0115: |
2530 | case 0x0015: s->waveform = acolor16; break; |
2531 | } |
2532 | |
2533 | switch (s->filter) { |
2534 | case LOWPASS: |
2535 | case COLOR: |
2536 | case ACOLOR: |
2537 | case CHROMA: |
2538 | case AFLAT: |
2539 | case FLAT: |
2540 | if (s->graticule && s->mode == 1) |
2541 | s->graticulef = s->bits > 8 ? graticule16_green_column : graticule_green_column; |
2542 | else if (s->graticule && s->mode == 0) |
2543 | s->graticulef = s->bits > 8 ? graticule16_green_row : graticule_green_row; |
2544 | break; |
2545 | } |
2546 | |
2547 | switch (s->filter) { |
2548 | case COLOR: |
2549 | case ACOLOR: |
2550 | case LOWPASS: |
2551 | switch (s->scale) { |
2552 | case DIGITAL: |
2553 | switch (s->bits) { |
2554 | case 8: s->glines = (GraticuleLines *)digital8; s->nb_glines = FF_ARRAY_ELEMS(digital8); break; |
2555 | case 9: s->glines = (GraticuleLines *)digital9; s->nb_glines = FF_ARRAY_ELEMS(digital9); break; |
2556 | case 10: s->glines = (GraticuleLines *)digital10; s->nb_glines = FF_ARRAY_ELEMS(digital10); break; |
2557 | case 12: s->glines = (GraticuleLines *)digital12; s->nb_glines = FF_ARRAY_ELEMS(digital12); break; |
2558 | } |
2559 | break; |
2560 | case MILLIVOLTS: |
2561 | switch (s->bits) { |
2562 | case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break; |
2563 | case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break; |
2564 | case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break; |
2565 | case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break; |
2566 | } |
2567 | break; |
2568 | case IRE: |
2569 | switch (s->bits) { |
2570 | case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break; |
2571 | case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break; |
2572 | case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break; |
2573 | case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break; |
2574 | } |
2575 | break; |
2576 | } |
2577 | break; |
2578 | case CHROMA: |
2579 | switch (s->scale) { |
2580 | case DIGITAL: |
2581 | switch (s->bits) { |
2582 | case 8: s->glines = (GraticuleLines *)chroma_digital8; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital8); break; |
2583 | case 9: s->glines = (GraticuleLines *)chroma_digital9; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital9); break; |
2584 | case 10: s->glines = (GraticuleLines *)chroma_digital10; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital10); break; |
2585 | case 12: s->glines = (GraticuleLines *)chroma_digital12; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital12); break; |
2586 | } |
2587 | break; |
2588 | case MILLIVOLTS: |
2589 | switch (s->bits) { |
2590 | case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break; |
2591 | case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break; |
2592 | case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break; |
2593 | case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break; |
2594 | } |
2595 | break; |
2596 | case IRE: |
2597 | switch (s->bits) { |
2598 | case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break; |
2599 | case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break; |
2600 | case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break; |
2601 | case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break; |
2602 | } |
2603 | break; |
2604 | } |
2605 | break; |
2606 | case AFLAT: |
2607 | switch (s->scale) { |
2608 | case DIGITAL: |
2609 | switch (s->bits) { |
2610 | case 8: s->glines = (GraticuleLines *)aflat_digital8; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital8); break; |
2611 | case 9: s->glines = (GraticuleLines *)aflat_digital9; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital9); break; |
2612 | case 10: s->glines = (GraticuleLines *)aflat_digital10; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital10); break; |
2613 | case 12: s->glines = (GraticuleLines *)aflat_digital12; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital12); break; |
2614 | } |
2615 | break; |
2616 | case MILLIVOLTS: |
2617 | switch (s->bits) { |
2618 | case 8: s->glines = (GraticuleLines *)aflat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts8); break; |
2619 | case 9: s->glines = (GraticuleLines *)aflat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts9); break; |
2620 | case 10: s->glines = (GraticuleLines *)aflat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts10); break; |
2621 | case 12: s->glines = (GraticuleLines *)aflat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts12); break; |
2622 | } |
2623 | break; |
2624 | case IRE: |
2625 | switch (s->bits) { |
2626 | case 8: s->glines = (GraticuleLines *)aflat_ire8; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire8); break; |
2627 | case 9: s->glines = (GraticuleLines *)aflat_ire9; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire9); break; |
2628 | case 10: s->glines = (GraticuleLines *)aflat_ire10; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire10); break; |
2629 | case 12: s->glines = (GraticuleLines *)aflat_ire12; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire12); break; |
2630 | } |
2631 | break; |
2632 | } |
2633 | break; |
2634 | case FLAT: |
2635 | switch (s->scale) { |
2636 | case DIGITAL: |
2637 | switch (s->bits) { |
2638 | case 8: s->glines = (GraticuleLines *)flat_digital8; s->nb_glines = FF_ARRAY_ELEMS(flat_digital8); break; |
2639 | case 9: s->glines = (GraticuleLines *)flat_digital9; s->nb_glines = FF_ARRAY_ELEMS(flat_digital9); break; |
2640 | case 10: s->glines = (GraticuleLines *)flat_digital10; s->nb_glines = FF_ARRAY_ELEMS(flat_digital10); break; |
2641 | case 12: s->glines = (GraticuleLines *)flat_digital12; s->nb_glines = FF_ARRAY_ELEMS(flat_digital12); break; |
2642 | } |
2643 | break; |
2644 | case MILLIVOLTS: |
2645 | switch (s->bits) { |
2646 | case 8: s->glines = (GraticuleLines *)flat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts8); break; |
2647 | case 9: s->glines = (GraticuleLines *)flat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts9); break; |
2648 | case 10: s->glines = (GraticuleLines *)flat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts10); break; |
2649 | case 12: s->glines = (GraticuleLines *)flat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts12); break; |
2650 | } |
2651 | break; |
2652 | case IRE: |
2653 | switch (s->bits) { |
2654 | case 8: s->glines = (GraticuleLines *)flat_ire8; s->nb_glines = FF_ARRAY_ELEMS(flat_ire8); break; |
2655 | case 9: s->glines = (GraticuleLines *)flat_ire9; s->nb_glines = FF_ARRAY_ELEMS(flat_ire9); break; |
2656 | case 10: s->glines = (GraticuleLines *)flat_ire10; s->nb_glines = FF_ARRAY_ELEMS(flat_ire10); break; |
2657 | case 12: s->glines = (GraticuleLines *)flat_ire12; s->nb_glines = FF_ARRAY_ELEMS(flat_ire12); break; |
2658 | } |
2659 | break; |
2660 | } |
2661 | break; |
2662 | } |
2663 | |
2664 | s->size = s->size << (s->bits - 8); |
2665 | |
2666 | switch (inlink->format) { |
2667 | case AV_PIX_FMT_GBRAP: |
2668 | case AV_PIX_FMT_GBRP: |
2669 | case AV_PIX_FMT_GBRP9: |
2670 | case AV_PIX_FMT_GBRP10: |
2671 | case AV_PIX_FMT_GBRP12: |
2672 | memcpy(s->bg_color, black_gbrp_color, sizeof(s->bg_color)); |
2673 | s->graticulef = graticule_none; |
2674 | break; |
2675 | default: |
2676 | memcpy(s->bg_color, black_yuva_color, sizeof(s->bg_color)); |
2677 | } |
2678 | |
2679 | s->bg_color[3] *= s->bgopacity; |
2680 | |
2681 | return 0; |
2682 | } |
2683 | |
2684 | static int config_output(AVFilterLink *outlink) |
2685 | { |
2686 | AVFilterContext *ctx = outlink->src; |
2687 | AVFilterLink *inlink = ctx->inputs[0]; |
2688 | WaveformContext *s = ctx->priv; |
2689 | int comp = 0, i, j = 0, k, p, size; |
2690 | |
2691 | for (i = 0; i < s->ncomp; i++) { |
2692 | if ((1 << i) & s->pcomp) |
2693 | comp++; |
2694 | } |
2695 | s->acomp = comp; |
2696 | s->odesc = av_pix_fmt_desc_get(outlink->format); |
2697 | s->dcomp = s->odesc->nb_components; |
2698 | |
2699 | av_freep(&s->peak); |
2700 | |
2701 | if (s->mode) { |
2702 | outlink->h = s->size * FFMAX(comp * (s->display == STACK), 1); |
2703 | outlink->w = inlink->w * FFMAX(comp * (s->display == PARADE), 1); |
2704 | size = inlink->w; |
2705 | } else { |
2706 | outlink->w = s->size * FFMAX(comp * (s->display == STACK), 1); |
2707 | outlink->h = inlink->h * FFMAX(comp * (s->display == PARADE), 1); |
2708 | size = inlink->h; |
2709 | } |
2710 | |
2711 | s->peak = av_malloc_array(size, 32 * sizeof(*s->peak)); |
2712 | if (!s->peak) |
2713 | return AVERROR(ENOMEM); |
2714 | |
2715 | for (p = 0; p < s->ncomp; p++) { |
2716 | const int plane = s->desc->comp[p].plane; |
2717 | int offset; |
2718 | |
2719 | if (!((1 << p) & s->pcomp)) |
2720 | continue; |
2721 | |
2722 | for (k = 0; k < 4; k++) { |
2723 | s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0); |
2724 | s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16); |
2725 | } |
2726 | |
2727 | offset = j++ * s->size * (s->display == STACK); |
2728 | s->estart[plane] = offset; |
2729 | s->eend[plane] = (offset + s->size - 1); |
2730 | for (i = 0; i < size; i++) { |
2731 | for (k = 0; k < 4; k++) { |
2732 | s->emax[plane][k][i] = s->estart[plane]; |
2733 | s->emin[plane][k][i] = s->eend[plane]; |
2734 | } |
2735 | } |
2736 | } |
2737 | |
2738 | outlink->sample_aspect_ratio = (AVRational){1,1}; |
2739 | |
2740 | return 0; |
2741 | } |
2742 | |
2743 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
2744 | { |
2745 | AVFilterContext *ctx = inlink->dst; |
2746 | WaveformContext *s = ctx->priv; |
2747 | AVFilterLink *outlink = ctx->outputs[0]; |
2748 | AVFrame *out; |
2749 | int i, j, k; |
2750 | |
2751 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
2752 | if (!out) { |
2753 | av_frame_free(&in); |
2754 | return AVERROR(ENOMEM); |
2755 | } |
2756 | out->pts = in->pts; |
2757 | av_frame_set_color_range(out, AVCOL_RANGE_JPEG); |
2758 | |
2759 | for (k = 0; k < s->dcomp; k++) { |
2760 | if (s->bits <= 8) { |
2761 | for (i = 0; i < outlink->h ; i++) |
2762 | memset(out->data[s->odesc->comp[k].plane] + |
2763 | i * out->linesize[s->odesc->comp[k].plane], |
2764 | s->bg_color[k], outlink->w); |
2765 | } else { |
2766 | const int mult = s->max / 256; |
2767 | uint16_t *dst = (uint16_t *)out->data[s->odesc->comp[k].plane]; |
2768 | |
2769 | for (i = 0; i < outlink->h ; i++) { |
2770 | for (j = 0; j < outlink->w; j++) |
2771 | dst[j] = s->bg_color[k] * mult; |
2772 | dst += out->linesize[s->odesc->comp[k].plane] / 2; |
2773 | } |
2774 | } |
2775 | } |
2776 | |
2777 | for (k = 0, i = 0; k < s->ncomp; k++) { |
2778 | if ((1 << k) & s->pcomp) { |
2779 | int offset_y; |
2780 | int offset_x; |
2781 | |
2782 | if (s->display == PARADE) { |
2783 | offset_x = s->mode ? i++ * inlink->w : 0; |
2784 | offset_y = s->mode ? 0 : i++ * inlink->h; |
2785 | } else { |
2786 | offset_y = s->mode ? i++ * s->size * !!s->display : 0; |
2787 | offset_x = s->mode ? 0 : i++ * s->size * !!s->display; |
2788 | } |
2789 | s->waveform(s, in, out, k, s->intensity, offset_y, offset_x, s->mode, s->mirror); |
2790 | } |
2791 | } |
2792 | s->graticulef(s, out); |
2793 | |
2794 | av_frame_free(&in); |
2795 | return ff_filter_frame(outlink, out); |
2796 | } |
2797 | |
2798 | static av_cold void uninit(AVFilterContext *ctx) |
2799 | { |
2800 | WaveformContext *s = ctx->priv; |
2801 | |
2802 | av_freep(&s->peak); |
2803 | } |
2804 | |
2805 | static const AVFilterPad inputs[] = { |
2806 | { |
2807 | .name = "default", |
2808 | .type = AVMEDIA_TYPE_VIDEO, |
2809 | .filter_frame = filter_frame, |
2810 | .config_props = config_input, |
2811 | }, |
2812 | { NULL } |
2813 | }; |
2814 | |
2815 | static const AVFilterPad outputs[] = { |
2816 | { |
2817 | .name = "default", |
2818 | .type = AVMEDIA_TYPE_VIDEO, |
2819 | .config_props = config_output, |
2820 | }, |
2821 | { NULL } |
2822 | }; |
2823 | |
2824 | AVFilter ff_vf_waveform = { |
2825 | .name = "waveform", |
2826 | .description = NULL_IF_CONFIG_SMALL("Video waveform monitor."), |
2827 | .priv_size = sizeof(WaveformContext), |
2828 | .priv_class = &waveform_class, |
2829 | .query_formats = query_formats, |
2830 | .uninit = uninit, |
2831 | .inputs = inputs, |
2832 | .outputs = outputs, |
2833 | }; |
2834 |