FFmpeg
vf_vectorscope.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/parseutils.h"
25 #include "libavutil/pixdesc.h"
27 #include "avfilter.h"
28 #include "formats.h"
29 #include "internal.h"
30 #include "video.h"
31 
38 };
39 
48 };
49 
50 typedef struct VectorscopeContext {
51  const AVClass *class;
52  int mode;
53  int intensity;
54  float fintensity;
55  uint16_t bg_color[4];
56  float ftint[2];
57  int planewidth[4];
58  int planeheight[4];
59  int hsub, vsub;
60  int x, y, pd;
61  int is_yuv;
62  int size;
63  int depth;
64  int mult;
65  int envelope;
66  int graticule;
67  float opacity;
68  float bgopacity;
69  float lthreshold;
70  float hthreshold;
71  int tint[2];
72  int tmin;
73  int tmax;
74  int flags;
76  int cs;
79 
81  AVFrame *in, AVFrame *out, int pd);
83  int X, int Y, int D, int P);
85 
86 #define OFFSET(x) offsetof(VectorscopeContext, x)
87 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
88 
89 static const AVOption vectorscope_options[] = {
90  { "mode", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"},
91  { "m", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"},
92  { "gray", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" },
93  { "tint", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" },
94  { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "mode" },
95  { "color2", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR2}, 0, 0, FLAGS, "mode" },
96  { "color3", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR3}, 0, 0, FLAGS, "mode" },
97  { "color4", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR4}, 0, 0, FLAGS, "mode" },
98  { "color5", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR5}, 0, 0, FLAGS, "mode" },
99  { "x", "set color component on X axis", OFFSET(x), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS},
100  { "y", "set color component on Y axis", OFFSET(y), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS},
101  { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, FLAGS},
102  { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, FLAGS},
103  { "envelope", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope"},
104  { "e", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope"},
105  { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" },
106  { "instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" },
107  { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" },
108  { "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" },
109  { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"},
110  { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"},
111  { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_NONE}, 0, 0, FLAGS, "graticule" },
112  { "green", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_GREEN}, 0, 0, FLAGS, "graticule" },
113  { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_COLOR}, 0, 0, FLAGS, "graticule" },
114  { "invert", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_INVERT},0, 0, FLAGS, "graticule" },
115  { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS},
116  { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS},
117  { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"},
118  { "f", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"},
119  { "white", "draw white point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
120  { "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
121  { "name", "draw point name", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "flags" },
122  { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
123  { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
124  { "lthreshold", "set low threshold", OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
125  { "l", "set low threshold", OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
126  { "hthreshold", "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
127  { "h", "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
128  { "colorspace", "set colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "colorspace"},
129  { "c", "set colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "colorspace"},
130  { "auto", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colorspace" },
131  { "601", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colorspace" },
132  { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colorspace" },
133  { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
134  { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
135  { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
136  { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS},
137  { NULL }
138 };
139 
141 
142 static const enum AVPixelFormat out_yuv8_pix_fmts[] = {
145 };
146 
147 static const enum AVPixelFormat out_yuv9_pix_fmts[] = {
150 };
151 
152 static const enum AVPixelFormat out_yuv10_pix_fmts[] = {
155 };
156 
157 static const enum AVPixelFormat out_yuv12_pix_fmts[] = {
160 };
161 
162 static const enum AVPixelFormat out_rgb8_pix_fmts[] = {
165 };
166 
167 static const enum AVPixelFormat out_rgb9_pix_fmts[] = {
170 };
171 
172 static const enum AVPixelFormat out_rgb10_pix_fmts[] = {
175 };
176 
177 static const enum AVPixelFormat out_rgb12_pix_fmts[] = {
180 };
181 
182 static const enum AVPixelFormat in1_pix_fmts[] = {
191 };
192 
193 static const enum AVPixelFormat in2_pix_fmts[] = {
209 };
210 
212 {
213  VectorscopeContext *s = ctx->priv;
214  const enum AVPixelFormat *out_pix_fmts;
215  const AVPixFmtDescriptor *desc;
216  AVFilterFormats *avff;
217  int depth, rgb, i, ret;
218 
219  if (!ctx->inputs[0]->in_formats ||
220  !ctx->inputs[0]->in_formats->nb_formats) {
221  return AVERROR(EAGAIN);
222  }
223 
224  if (!ctx->inputs[0]->out_formats) {
225  const enum AVPixelFormat *in_pix_fmts;
226 
227  if ((s->x == 1 && s->y == 2) || (s->x == 2 && s->y == 1))
228  in_pix_fmts = in2_pix_fmts;
229  else
230  in_pix_fmts = in1_pix_fmts;
231  if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0)
232  return ret;
233  }
234 
235  avff = ctx->inputs[0]->in_formats;
236  desc = av_pix_fmt_desc_get(avff->formats[0]);
237  rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
238  depth = desc->comp[0].depth;
239  for (i = 1; i < avff->nb_formats; i++) {
240  desc = av_pix_fmt_desc_get(avff->formats[i]);
241  if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) ||
242  depth != desc->comp[0].depth)
243  return AVERROR(EAGAIN);
244  }
245 
246  if (rgb && depth == 8)
247  out_pix_fmts = out_rgb8_pix_fmts;
248  else if (rgb && depth == 9)
249  out_pix_fmts = out_rgb9_pix_fmts;
250  else if (rgb && depth == 10)
251  out_pix_fmts = out_rgb10_pix_fmts;
252  else if (rgb && depth == 12)
253  out_pix_fmts = out_rgb12_pix_fmts;
254  else if (depth == 8)
255  out_pix_fmts = out_yuv8_pix_fmts;
256  else if (depth == 9)
257  out_pix_fmts = out_yuv9_pix_fmts;
258  else if (depth == 10)
259  out_pix_fmts = out_yuv10_pix_fmts;
260  else if (depth == 12)
261  out_pix_fmts = out_yuv12_pix_fmts;
262  else
263  return AVERROR(EAGAIN);
264  if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
265  return ret;
266 
267  return 0;
268 }
269 
270 static int config_output(AVFilterLink *outlink)
271 {
272  VectorscopeContext *s = outlink->src->priv;
273  int i;
274 
275  s->intensity = s->fintensity * (s->size - 1);
276  outlink->h = outlink->w = s->size;
277  outlink->sample_aspect_ratio = (AVRational){1,1};
278 
279  s->peak_memory = av_calloc(s->size, s->size);
280  if (!s->peak_memory)
281  return AVERROR(ENOMEM);
282 
283  s->peak = av_calloc(s->size, sizeof(*s->peak));
284  if (!s->peak)
285  return AVERROR(ENOMEM);
286 
287  for (i = 0; i < s->size; i++)
288  s->peak[i] = s->peak_memory + s->size * i;
289 
290  return 0;
291 }
292 
294 {
295  const int dlinesize = out->linesize[0] / 2;
296  uint16_t *dpd = s->mode == COLOR || !s->is_yuv ? (uint16_t *)out->data[s->pd] : (uint16_t *)out->data[0];
297  const int max = s->size - 1;
298  int i, j;
299 
300  for (i = 0; i < out->height; i++) {
301  for (j = 0; j < out->width; j++) {
302  const int pos = i * dlinesize + j;
303  const int poa = (i - 1) * dlinesize + j;
304  const int pob = (i + 1) * dlinesize + j;
305 
306  if (dpd[pos] && (((!j || !dpd[pos - 1]) || ((j == (out->width - 1)) || !dpd[pos + 1]))
307  || ((!i || !dpd[poa]) || ((i == (out->height - 1)) || !dpd[pob])))) {
308  dpd[pos] = max;
309  }
310  }
311  }
312 }
313 
315 {
316  const int dlinesize = out->linesize[0] / 2;
317  uint16_t *dpd = s->mode == COLOR || !s->is_yuv ? (uint16_t *)out->data[s->pd] : (uint16_t *)out->data[0];
318  const int max = s->size - 1;
319  int i, j;
320 
321  for (i = 0; i < out->height; i++) {
322  for (j = 0; j < out->width; j++) {
323  const int pos = i * dlinesize + j;
324 
325  if (dpd[pos])
326  s->peak[i][j] = 1;
327  }
328  }
329 
330  if (s->envelope == 3)
331  envelope_instant16(s, out);
332 
333  for (i = 0; i < out->height; i++) {
334  for (j = 0; j < out->width; j++) {
335  const int pos = i * dlinesize + j;
336 
337  if (s->peak[i][j] && (((!j || !s->peak[i][j-1]) || ((j == (out->width - 1)) || !s->peak[i][j + 1]))
338  || ((!i || !s->peak[i-1][j]) || ((i == (out->height - 1)) || !s->peak[i + 1][j])))) {
339  dpd[pos] = max;
340  }
341  }
342  }
343 }
344 
346 {
347  const int dlinesize = out->linesize[0];
348  uint8_t *dpd = s->mode == COLOR || !s->is_yuv ? out->data[s->pd] : out->data[0];
349  int i, j;
350 
351  for (i = 0; i < out->height; i++) {
352  for (j = 0; j < out->width; j++) {
353  const int pos = i * dlinesize + j;
354  const int poa = (i - 1) * dlinesize + j;
355  const int pob = (i + 1) * dlinesize + j;
356 
357  if (dpd[pos] && (((!j || !dpd[pos - 1]) || ((j == (out->width - 1)) || !dpd[pos + 1]))
358  || ((!i || !dpd[poa]) || ((i == (out->height - 1)) || !dpd[pob])))) {
359  dpd[pos] = 255;
360  }
361  }
362  }
363 }
364 
366 {
367  const int dlinesize = out->linesize[0];
368  uint8_t *dpd = s->mode == COLOR || !s->is_yuv ? out->data[s->pd] : out->data[0];
369  int i, j;
370 
371  for (i = 0; i < out->height; i++) {
372  for (j = 0; j < out->width; j++) {
373  const int pos = i * dlinesize + j;
374 
375  if (dpd[pos])
376  s->peak[i][j] = 1;
377  }
378  }
379 
380  if (s->envelope == 3)
381  envelope_instant(s, out);
382 
383  for (i = 0; i < out->height; i++) {
384  for (j = 0; j < out->width; j++) {
385  const int pos = i * dlinesize + j;
386 
387  if (s->peak[i][j] && (((!j || !s->peak[i][j-1]) || ((j == (out->width - 1)) || !s->peak[i][j + 1]))
388  || ((!i || !s->peak[i-1][j]) || ((i == (out->height - 1)) || !s->peak[i + 1][j])))) {
389  dpd[pos] = 255;
390  }
391  }
392  }
393 }
394 
396 {
397  if (!s->envelope) {
398  return;
399  } else if (s->envelope == 1) {
400  envelope_instant16(s, out);
401  } else {
402  envelope_peak16(s, out);
403  }
404 }
405 
407 {
408  if (!s->envelope) {
409  return;
410  } else if (s->envelope == 1) {
411  envelope_instant(s, out);
412  } else {
413  envelope_peak(s, out);
414  }
415 }
416 
418 {
419  const uint16_t * const *src = (const uint16_t * const *)in->data;
420  const int slinesizex = in->linesize[s->x] / 2;
421  const int slinesizey = in->linesize[s->y] / 2;
422  const int slinesized = in->linesize[pd] / 2;
423  const int dlinesize = out->linesize[0] / 2;
424  const int intensity = s->intensity;
425  const int px = s->x, py = s->y;
426  const int h = s->planeheight[py];
427  const int w = s->planewidth[px];
428  const uint16_t *spx = src[px];
429  const uint16_t *spy = src[py];
430  const uint16_t *spd = src[pd];
431  const int hsub = s->hsub;
432  const int vsub = s->vsub;
433  uint16_t **dst = (uint16_t **)out->data;
434  uint16_t *dpx = dst[px];
435  uint16_t *dpy = dst[py];
436  uint16_t *dpd = dst[pd];
437  uint16_t *dp1 = dst[1];
438  uint16_t *dp2 = dst[2];
439  const int max = s->size - 1;
440  const int mid = s->size / 2;
441  const int tmin = s->tmin;
442  const int tmax = s->tmax;
443  int i, j, k;
444 
445  for (k = 0; k < 4 && dst[k]; k++) {
446  for (i = 0; i < out->height ; i++)
447  for (j = 0; j < out->width; j++)
448  AV_WN16(out->data[k] + i * out->linesize[k] + j * 2,
449  (s->mode == COLOR || s->mode == COLOR5) && k == s->pd ? 0 : s->bg_color[k]);
450  }
451 
452  switch (s->mode) {
453  case COLOR:
454  case COLOR5:
455  case TINT:
456  for (i = 0; i < h; i++) {
457  const int iwx = i * slinesizex;
458  const int iwy = i * slinesizey;
459  const int iwd = i * slinesized;
460  for (j = 0; j < w; j++) {
461  const int x = FFMIN(spx[iwx + j], max);
462  const int y = FFMIN(spy[iwy + j], max);
463  const int z = spd[iwd + j];
464  const int pos = y * dlinesize + x;
465 
466  if (z < tmin || z > tmax)
467  continue;
468 
469  dpd[pos] = FFMIN(dpd[pos] + intensity, max);
470  }
471  }
472  break;
473  case COLOR2:
474  if (s->is_yuv) {
475  for (i = 0; i < h; i++) {
476  const int iw1 = i * slinesizex;
477  const int iw2 = i * slinesizey;
478  const int iwd = i * slinesized;
479  for (j = 0; j < w; j++) {
480  const int x = FFMIN(spx[iw1 + j], max);
481  const int y = FFMIN(spy[iw2 + j], max);
482  const int z = spd[iwd + j];
483  const int pos = y * dlinesize + x;
484 
485  if (z < tmin || z > tmax)
486  continue;
487 
488  if (!dpd[pos])
489  dpd[pos] = FFABS(mid - x) + FFABS(mid - y);
490  dpx[pos] = x;
491  dpy[pos] = y;
492  }
493  }
494  } else {
495  for (i = 0; i < h; i++) {
496  const int iw1 = i * slinesizex;
497  const int iw2 = i * slinesizey;
498  const int iwd = i * slinesized;
499  for (j = 0; j < w; j++) {
500  const int x = FFMIN(spx[iw1 + j], max);
501  const int y = FFMIN(spy[iw2 + j], max);
502  const int z = spd[iwd + j];
503  const int pos = y * dlinesize + x;
504 
505  if (z < tmin || z > tmax)
506  continue;
507 
508  if (!dpd[pos])
509  dpd[pos] = FFMIN(x + y, max);
510  dpx[pos] = x;
511  dpy[pos] = y;
512  }
513  }
514  }
515  break;
516  case COLOR3:
517  for (i = 0; i < h; i++) {
518  const int iw1 = i * slinesizex;
519  const int iw2 = i * slinesizey;
520  const int iwd = i * slinesized;
521  for (j = 0; j < w; j++) {
522  const int x = FFMIN(spx[iw1 + j], max);
523  const int y = FFMIN(spy[iw2 + j], max);
524  const int z = spd[iwd + j];
525  const int pos = y * dlinesize + x;
526 
527  if (z < tmin || z > tmax)
528  continue;
529 
530  dpd[pos] = FFMIN(max, dpd[pos] + intensity);
531  dpx[pos] = x;
532  dpy[pos] = y;
533  }
534  }
535  break;
536  case COLOR4:
537  for (i = 0; i < in->height; i++) {
538  const int iwx = (i >> vsub) * slinesizex;
539  const int iwy = (i >> vsub) * slinesizey;
540  const int iwd = i * slinesized;
541  for (j = 0; j < in->width; j++) {
542  const int x = FFMIN(spx[iwx + (j >> hsub)], max);
543  const int y = FFMIN(spy[iwy + (j >> hsub)], max);
544  const int z = spd[iwd + j];
545  const int pos = y * dlinesize + x;
546 
547  if (z < tmin || z > tmax)
548  continue;
549 
550  dpd[pos] = FFMAX(z, dpd[pos]);
551  dpx[pos] = x;
552  dpy[pos] = y;
553  }
554  }
555  break;
556  default:
557  av_assert0(0);
558  }
559 
560  envelope16(s, out);
561 
562  if (dst[3]) {
563  for (i = 0; i < out->height; i++) {
564  for (j = 0; j < out->width; j++) {
565  int pos = i * dlinesize + j;
566 
567  if (dpd[pos])
568  dst[3][pos] = max;
569  }
570  }
571  }
572 
573  if (s->mode == TINT && s->is_yuv &&
574  (s->tint[0] != mid || s->tint[1] != mid)) {
575  for (i = 0; i < out->height; i++) {
576  for (j = 0; j < out->width; j++) {
577  const int pos = i * dlinesize + j;
578  if (dpd[pos]) {
579  dp1[pos] = s->tint[0];
580  dp2[pos] = s->tint[1];
581  }
582  }
583  }
584  } else if (s->mode == TINT && !s->is_yuv) {
585  for (i = 0; i < out->height; i++) {
586  for (j = 0; j < out->width; j++) {
587  const int pos = i * dlinesize + j;
588  if (dpd[pos]) {
589  dpx[pos] = av_clip(dpd[pos] + dpd[pos] * s->ftint[0], 0, max);
590  dpy[pos] = av_clip(dpd[pos] + dpd[pos] * s->ftint[1], 0, max);
591  }
592  }
593  }
594  } else if (s->mode == COLOR) {
595  for (i = 0; i < out->height; i++) {
596  for (j = 0; j < out->width; j++) {
597  if (!dpd[i * dlinesize + j]) {
598  dpx[i * dlinesize + j] = j;
599  dpy[i * dlinesize + j] = i;
600  dpd[i * dlinesize + j] = mid;
601  }
602  }
603  }
604  } else if (s->mode == COLOR5) {
605  for (i = 0; i < out->height; i++) {
606  for (j = 0; j < out->width; j++) {
607  if (!dpd[i * dlinesize + j]) {
608  dpx[i * dlinesize + j] = j;
609  dpy[i * dlinesize + j] = i;
610  dpd[i * dlinesize + j] = mid * M_SQRT2 - hypot(i - mid, j - mid);
611  }
612  }
613  }
614  }
615 }
616 
618 {
619  const uint8_t * const *src = (const uint8_t * const *)in->data;
620  const int slinesizex = in->linesize[s->x];
621  const int slinesizey = in->linesize[s->y];
622  const int slinesized = in->linesize[pd];
623  const int dlinesize = out->linesize[0];
624  const int intensity = s->intensity;
625  const int px = s->x, py = s->y;
626  const int h = s->planeheight[py];
627  const int w = s->planewidth[px];
628  const uint8_t *spx = src[px];
629  const uint8_t *spy = src[py];
630  const uint8_t *spd = src[pd];
631  const int hsub = s->hsub;
632  const int vsub = s->vsub;
633  uint8_t **dst = out->data;
634  uint8_t *dpx = dst[px];
635  uint8_t *dpy = dst[py];
636  uint8_t *dpd = dst[pd];
637  uint8_t *dp1 = dst[1];
638  uint8_t *dp2 = dst[2];
639  const int tmin = s->tmin;
640  const int tmax = s->tmax;
641  int i, j, k;
642 
643  for (k = 0; k < 4 && dst[k]; k++)
644  for (i = 0; i < out->height ; i++)
645  memset(dst[k] + i * out->linesize[k],
646  (s->mode == COLOR || s->mode == COLOR5) && k == s->pd ? 0 : s->bg_color[k], out->width);
647 
648  switch (s->mode) {
649  case COLOR5:
650  case COLOR:
651  case TINT:
652  for (i = 0; i < h; i++) {
653  const int iwx = i * slinesizex;
654  const int iwy = i * slinesizey;
655  const int iwd = i * slinesized;
656  for (j = 0; j < w; j++) {
657  const int x = spx[iwx + j];
658  const int y = spy[iwy + j];
659  const int z = spd[iwd + j];
660  const int pos = y * dlinesize + x;
661 
662  if (z < tmin || z > tmax)
663  continue;
664 
665  dpd[pos] = FFMIN(dpd[pos] + intensity, 255);
666  }
667  }
668  break;
669  case COLOR2:
670  if (s->is_yuv) {
671  for (i = 0; i < h; i++) {
672  const int iw1 = i * slinesizex;
673  const int iw2 = i * slinesizey;
674  const int iwd = i * slinesized;
675  for (j = 0; j < w; j++) {
676  const int x = spx[iw1 + j];
677  const int y = spy[iw2 + j];
678  const int z = spd[iwd + j];
679  const int pos = y * dlinesize + x;
680 
681  if (z < tmin || z > tmax)
682  continue;
683 
684  if (!dpd[pos])
685  dpd[pos] = FFABS(128 - x) + FFABS(128 - y);
686  dpx[pos] = x;
687  dpy[pos] = y;
688  }
689  }
690  } else {
691  for (i = 0; i < h; i++) {
692  const int iw1 = i * slinesizex;
693  const int iw2 = i * slinesizey;
694  const int iwd = i * slinesized;
695  for (j = 0; j < w; j++) {
696  const int x = spx[iw1 + j];
697  const int y = spy[iw2 + j];
698  const int z = spd[iwd + j];
699  const int pos = y * dlinesize + x;
700 
701  if (z < tmin || z > tmax)
702  continue;
703 
704  if (!dpd[pos])
705  dpd[pos] = FFMIN(x + y, 255);
706  dpx[pos] = x;
707  dpy[pos] = y;
708  }
709  }
710  }
711  break;
712  case COLOR3:
713  for (i = 0; i < h; i++) {
714  const int iw1 = i * slinesizex;
715  const int iw2 = i * slinesizey;
716  const int iwd = i * slinesized;
717  for (j = 0; j < w; j++) {
718  const int x = spx[iw1 + j];
719  const int y = spy[iw2 + j];
720  const int z = spd[iwd + j];
721  const int pos = y * dlinesize + x;
722 
723  if (z < tmin || z > tmax)
724  continue;
725 
726  dpd[pos] = FFMIN(255, dpd[pos] + intensity);
727  dpx[pos] = x;
728  dpy[pos] = y;
729  }
730  }
731  break;
732  case COLOR4:
733  for (i = 0; i < in->height; i++) {
734  const int iwx = (i >> vsub) * slinesizex;
735  const int iwy = (i >> vsub) * slinesizey;
736  const int iwd = i * slinesized;
737  for (j = 0; j < in->width; j++) {
738  const int x = spx[iwx + (j >> hsub)];
739  const int y = spy[iwy + (j >> hsub)];
740  const int z = spd[iwd + j];
741  const int pos = y * dlinesize + x;
742 
743  if (z < tmin || z > tmax)
744  continue;
745 
746  dpd[pos] = FFMAX(z, dpd[pos]);
747  dpx[pos] = x;
748  dpy[pos] = y;
749  }
750  }
751  break;
752  default:
753  av_assert0(0);
754  }
755 
756  envelope(s, out);
757 
758  if (dst[3]) {
759  for (i = 0; i < out->height; i++) {
760  for (j = 0; j < out->width; j++) {
761  int pos = i * dlinesize + j;
762 
763  if (dpd[pos])
764  dst[3][pos] = 255;
765  }
766  }
767  }
768 
769  if (s->mode == TINT && s->is_yuv &&
770  (s->tint[0] != 128 || s->tint[1] != 128)) {
771  for (i = 0; i < out->height; i++) {
772  for (j = 0; j < out->width; j++) {
773  const int pos = i * dlinesize + j;
774  if (dpd[pos]) {
775  dp1[pos] = s->tint[0];
776  dp2[pos] = s->tint[1];
777  }
778  }
779  }
780  } else if (s->mode == TINT && !s->is_yuv) {
781  for (i = 0; i < out->height; i++) {
782  for (j = 0; j < out->width; j++) {
783  const int pos = i * dlinesize + j;
784  if (dpd[pos]) {
785  dpx[pos] = av_clip_uint8(dpd[pos] + dpd[pos] * s->ftint[0]);
786  dpy[pos] = av_clip_uint8(dpd[pos] + dpd[pos] * s->ftint[1]);
787  }
788  }
789  }
790  } else if (s->mode == COLOR) {
791  for (i = 0; i < out->height; i++) {
792  for (j = 0; j < out->width; j++) {
793  if (!dpd[i * out->linesize[pd] + j]) {
794  dpx[i * out->linesize[px] + j] = j;
795  dpy[i * out->linesize[py] + j] = i;
796  dpd[i * out->linesize[pd] + j] = 128;
797  }
798  }
799  }
800  } else if (s->mode == COLOR5) {
801  for (i = 0; i < out->height; i++) {
802  for (j = 0; j < out->width; j++) {
803  if (!dpd[i * out->linesize[pd] + j]) {
804  dpx[i * out->linesize[px] + j] = j;
805  dpy[i * out->linesize[py] + j] = i;
806  dpd[i * out->linesize[pd] + j] = 128 * M_SQRT2 - hypot(i - 128, j - 128);
807  }
808  }
809  }
810  }
811 }
812 
813 const static char *positions_name[] = {
814  "R", "B", "Cy", "Yl", "G", "Mg",
815 };
816 
817 const static uint16_t positions[][14][3] = {
818  {
819  { 81, 90, 240 }, { 41, 240, 110 }, { 170, 166, 16 },
820  { 210, 16, 146 }, { 145, 54, 34 }, { 106, 202, 222 },
821  { 162, 44, 142 }, { 131, 156, 44 }, { 112, 72, 58 },
822  { 84, 184, 198 }, { 65, 100, 212 }, { 35, 212, 114 },
823  { 235, 128, 128 }, { 16, 128, 128 } },
824  { { 63, 102, 240 }, { 32, 240, 118 }, { 188, 154, 16 },
825  { 219, 16, 138 }, { 173, 42, 26 }, { 78, 214, 230 },
826  { 28, 212, 120 }, { 51, 109, 212 }, { 63, 193, 204 },
827  { 133, 63, 52 }, { 145, 147, 44 }, { 168, 44, 136 },
828  { 235, 128, 128 }, { 16, 128, 128 } },
829  { { 81*2, 90*2, 240*2 }, { 41*2, 240*2, 110*2 }, { 170*2, 166*2, 16*2 },
830  { 210*2, 16*2, 146*2 }, { 145*2, 54*2, 34*2 }, { 106*2, 202*2, 222*2 },
831  { 162*2, 44*2, 142*2 }, { 131*2, 156*2, 44*2 }, { 112*2, 72*2, 58*2 },
832  { 84*2, 184*2, 198*2 }, { 65*2, 100*2, 212*2 }, { 35*2, 212*2, 114*2 },
833  { 470, 256, 256 }, { 32, 256, 256 } },
834  { { 63*2, 102*2, 240*2 }, { 32*2, 240*2, 118*2 }, { 188*2, 154*2, 16*2 },
835  { 219*2, 16*2, 138*2 }, { 173*2, 42*2, 26*2 }, { 78*2, 214*2, 230*2 },
836  { 28*2, 212*2, 120*2 }, { 51*2, 109*2, 212*2 }, { 63*2, 193*2, 204*2 },
837  { 133*2, 63*2, 52*2 }, { 145*2, 147*2, 44*2 }, { 168*2, 44*2, 136*2 },
838  { 470, 256, 256 }, { 32, 256, 256 } },
839  { { 81*4, 90*4, 240*4 }, { 41*4, 240*4, 110*4 }, { 170*4, 166*4, 16*4 },
840  { 210*4, 16*4, 146*4 }, { 145*4, 54*4, 34*4 }, { 106*4, 202*4, 222*4 },
841  { 162*4, 44*4, 142*4 }, { 131*4, 156*4, 44*4 }, { 112*4, 72*4, 58*4 },
842  { 84*4, 184*4, 198*4 }, { 65*4, 100*4, 212*4 }, { 35*4, 212*4, 114*4 },
843  { 940, 512, 512 }, { 64, 512, 512 } },
844  { { 63*4, 102*4, 240*4 }, { 32*4, 240*4, 118*4 }, { 188*4, 154*4, 16*4 },
845  { 219*4, 16*4, 138*4 }, { 173*4, 42*4, 26*4 }, { 78*4, 214*4, 230*4 },
846  { 28*4, 212*4, 120*4 }, { 51*4, 109*4, 212*4 }, { 63*4, 193*4, 204*4 },
847  { 133*4, 63*4, 52*4 }, { 145*4, 147*4, 44*4 }, { 168*4, 44*4, 136*4 },
848  { 940, 512, 512 }, { 64, 512, 512 } },
849  { { 81*8, 90*4, 240*8 }, { 41*8, 240*8, 110*8 }, { 170*8, 166*8, 16*8 },
850  { 210*8, 16*4, 146*8 }, { 145*8, 54*8, 34*8 }, { 106*8, 202*8, 222*8 },
851  { 162*8, 44*4, 142*8 }, { 131*8, 156*8, 44*8 }, { 112*8, 72*8, 58*8 },
852  { 84*8, 184*4, 198*8 }, { 65*8, 100*8, 212*8 }, { 35*8, 212*8, 114*8 },
853  { 1880, 1024, 1024 }, { 128, 1024, 1024 } },
854  { { 63*8, 102*8, 240*8 }, { 32*8, 240*8, 118*8 }, { 188*8, 154*8, 16*8 },
855  { 219*8, 16*8, 138*8 }, { 173*8, 42*8, 26*8 }, { 78*8, 214*8, 230*8 },
856  { 28*8, 212*8, 120*8 }, { 51*8, 109*8, 212*8 }, { 63*8, 193*8, 204*8 },
857  { 133*8, 63*8, 52*8 }, { 145*8, 147*8, 44*8 }, { 168*8, 44*8, 136*8 },
858  { 1880, 1024, 1024 }, { 128, 1024, 1024 } },
859  { { 81*16, 90*16, 240*16 }, { 41*16, 240*16, 110*16 }, { 170*16, 166*16, 16*16 },
860  { 210*16, 16*16, 146*16 }, { 145*16, 54*16, 34*16 }, { 106*16, 202*16, 222*16 },
861  { 162*16, 44*16, 142*16 }, { 131*16, 156*16, 44*16 }, { 112*16, 72*16, 58*16 },
862  { 84*16, 184*16, 198*16 }, { 65*16, 100*16, 212*16 }, { 35*16, 212*16, 114*16 },
863  { 3760, 2048, 2048 }, { 256, 2048, 2048 } },
864  { { 63*16, 102*16, 240*16 }, { 32*16, 240*16, 118*16 }, { 188*16, 154*16, 16*16 },
865  { 219*16, 16*16, 138*16 }, { 173*16, 42*16, 26*16 }, { 78*16, 214*16, 230*16 },
866  { 28*16, 212*16, 120*16 }, { 51*16, 109*16, 212*16 }, { 63*16, 193*16, 204*16 },
867  { 133*16, 63*16, 52*16 }, { 145*16, 147*16, 44*16 }, { 168*16, 44*16, 136*16 },
868  { 3760, 2048, 2048 }, { 256, 2048, 2048 } },
869 };
870 
871 static void draw_dots(uint8_t *dst, int L, int v, float o)
872 {
873  const float f = 1. - o;
874  const float V = o * v;
875  int l = L * 2;
876 
877  dst[ l - 3] = dst[ l - 3] * f + V;
878  dst[ l + 3] = dst[ l + 3] * f + V;
879  dst[-l - 3] = dst[-l - 3] * f + V;
880  dst[-l + 3] = dst[-l + 3] * f + V;
881 
882  l += L;
883 
884  dst[ l - 3] = dst[ l - 3] * f + V;
885  dst[ l + 3] = dst[ l + 3] * f + V;
886  dst[ l - 2] = dst[ l - 2] * f + V;
887  dst[ l + 2] = dst[ l + 2] * f + V;
888  dst[-l - 3] = dst[-l - 3] * f + V;
889  dst[-l + 3] = dst[-l + 3] * f + V;
890  dst[-l - 2] = dst[-l - 2] * f + V;
891  dst[-l + 2] = dst[-l + 2] * f + V;
892 }
893 
894 static void draw_idots(uint8_t *dst, int L, float o)
895 {
896  const float f = 1. - o;
897  int l = L * 2;
898 
899  dst[ l - 3] = dst[ l - 3] * f + (255 - dst[ l - 3]) * o;
900  dst[ l + 3] = dst[ l + 3] * f + (255 - dst[ l + 3]) * o;
901  dst[-l - 3] = dst[-l - 3] * f + (255 - dst[-l - 3]) * o;
902  dst[-l + 3] = dst[-l + 3] * f + (255 - dst[-l + 3]) * o;
903 
904  l += L;
905 
906  dst[ l - 3] = dst[ l - 3] * f + (255 - dst[ l - 3]) * o;
907  dst[ l + 3] = dst[ l + 3] * f + (255 - dst[ l + 3]) * o;
908  dst[ l - 2] = dst[ l - 2] * f + (255 - dst[ l - 2]) * o;
909  dst[ l + 2] = dst[ l + 2] * f + (255 - dst[ l + 2]) * o;
910  dst[-l - 3] = dst[-l - 3] * f + (255 - dst[-l - 3]) * o;
911  dst[-l + 3] = dst[-l + 3] * f + (255 - dst[-l + 3]) * o;
912  dst[-l - 2] = dst[-l - 2] * f + (255 - dst[-l - 2]) * o;
913  dst[-l + 2] = dst[-l + 2] * f + (255 - dst[-l + 2]) * o;
914 }
915 
916 static void draw_dots16(uint16_t *dst, int L, int v, float o)
917 {
918  const float f = 1. - o;
919  const float V = o * v;
920  int l = L * 2;
921 
922  dst[ l - 3] = dst[ l - 3] * f + V;
923  dst[ l + 3] = dst[ l + 3] * f + V;
924  dst[-l - 3] = dst[-l - 3] * f + V;
925  dst[-l + 3] = dst[-l + 3] * f + V;
926 
927  l += L;
928 
929  dst[ l - 3] = dst[ l - 3] * f + V;
930  dst[ l + 3] = dst[ l + 3] * f + V;
931  dst[ l - 2] = dst[ l - 2] * f + V;
932  dst[ l + 2] = dst[ l + 2] * f + V;
933  dst[-l - 3] = dst[-l - 3] * f + V;
934  dst[-l + 3] = dst[-l + 3] * f + V;
935  dst[-l - 2] = dst[-l - 2] * f + V;
936  dst[-l + 2] = dst[-l + 2] * f + V;
937 }
938 
939 static void draw_idots16(uint16_t *dst, int L, int v, float o)
940 {
941  const float f = 1. - o;
942  int l = L * 2;
943 
944  dst[ l - 3] = dst[ l - 3] * f + (v - dst[ l - 3]) * o;
945  dst[ l + 3] = dst[ l + 3] * f + (v - dst[ l + 3]) * o;
946  dst[-l - 3] = dst[-l - 3] * f + (v - dst[-l - 3]) * o;
947  dst[-l + 3] = dst[-l + 3] * f + (v - dst[-l + 3]) * o;
948 
949  l += L;
950 
951  dst[ l - 3] = dst[ l - 3] * f + (v - dst[ l - 3]) * o;
952  dst[ l + 3] = dst[ l + 3] * f + (v - dst[ l + 3]) * o;
953  dst[ l - 2] = dst[ l - 2] * f + (v - dst[ l - 2]) * o;
954  dst[ l + 2] = dst[ l + 2] * f + (v - dst[ l + 2]) * o;
955  dst[-l - 3] = dst[-l - 3] * f + (v - dst[-l - 3]) * o;
956  dst[-l + 3] = dst[-l + 3] * f + (v - dst[-l + 3]) * o;
957  dst[-l - 2] = dst[-l - 2] * f + (v - dst[-l - 2]) * o;
958  dst[-l + 2] = dst[-l + 2] * f + (v - dst[-l + 2]) * o;
959 }
960 
961 static void none_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
962 {
963 }
964 
965 static void draw_ihtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
966 {
967  const uint8_t *font;
968  int font_height;
969  int i, plane;
970 
971  font = avpriv_cga_font, font_height = 8;
972 
973  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
974  for (i = 0; txt[i]; i++) {
975  int char_y, mask;
976 
977  uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
978  for (char_y = font_height - 1; char_y >= 0; char_y--) {
979  for (mask = 0x80; mask; mask >>= 1) {
980  if (font[txt[i] * font_height + char_y] & mask)
981  p[0] = p[0] * o2 + (255 - p[0]) * o1;
982  p++;
983  }
984  p += out->linesize[plane] - 8;
985  }
986  }
987  }
988 }
989 
990 static void draw_ihtext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4])
991 {
992  const uint8_t *font;
993  int font_height;
994  int i, plane;
995 
996  font = avpriv_cga_font, font_height = 8;
997 
998  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
999  for (i = 0; txt[i]; i++) {
1000  int char_y, mask;
1001  int v = color[plane];
1002 
1003  uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
1004  for (char_y = font_height - 1; char_y >= 0; char_y--) {
1005  for (mask = 0x80; mask; mask >>= 1) {
1006  if (font[txt[i] * font_height + char_y] & mask)
1007  p[0] = p[0] * o2 + (v - p[0]) * o1;
1008  p++;
1009  }
1010  p += out->linesize[plane] / 2 - 8;
1011  }
1012  }
1013  }
1014 }
1015 
1016 static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
1017 {
1018  const uint8_t *font;
1019  int font_height;
1020  int i, plane;
1021 
1022  font = avpriv_cga_font, font_height = 8;
1023 
1024  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1025  for (i = 0; txt[i]; i++) {
1026  int char_y, mask;
1027  int v = color[plane];
1028 
1029  uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
1030  for (char_y = font_height - 1; char_y >= 0; char_y--) {
1031  for (mask = 0x80; mask; mask >>= 1) {
1032  if (font[txt[i] * font_height + char_y] & mask)
1033  p[0] = p[0] * o2 + v * o1;
1034  p++;
1035  }
1036  p += out->linesize[plane] - 8;
1037  }
1038  }
1039  }
1040 }
1041 
1042 static void draw_htext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4])
1043 {
1044  const uint8_t *font;
1045  int font_height;
1046  int i, plane;
1047 
1048  font = avpriv_cga_font, font_height = 8;
1049 
1050  for (plane = 0; plane < 4 && out->data[plane]; plane++) {
1051  for (i = 0; txt[i]; i++) {
1052  int char_y, mask;
1053  int v = color[plane];
1054 
1055  uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
1056  for (char_y = font_height - 1; char_y >= 0; char_y--) {
1057  for (mask = 0x80; mask; mask >>= 1) {
1058  if (font[txt[i] * font_height + char_y] & mask)
1059  p[0] = p[0] * o2 + v * o1;
1060  p++;
1061  }
1062  p += out->linesize[plane] / 2 - 8;
1063  }
1064  }
1065  }
1066 }
1067 
1068 static void color_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1069 {
1070  const int max = s->size - 1;
1071  const float o = s->opacity;
1072  int i;
1073 
1074  for (i = 0; i < 12; i++) {
1075  int x = positions[P][i][X];
1076  int y = positions[P][i][Y];
1077  int d = positions[P][i][D];
1078 
1079  draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
1080  draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
1081  draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
1082  if (out->data[3])
1083  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1084  }
1085 
1086  if (s->flags & 1) {
1087  int x = positions[P][12][X];
1088  int y = positions[P][12][Y];
1089  int d = positions[P][12][D];
1090 
1091  draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
1092  draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
1093  draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
1094  if (out->data[3])
1095  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1096  }
1097 
1098  if (s->flags & 2) {
1099  int x = positions[P][13][X];
1100  int y = positions[P][13][Y];
1101  int d = positions[P][13][D];
1102 
1103  draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
1104  draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
1105  draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
1106  if (out->data[3])
1107  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1108  }
1109 
1110  for (i = 0; i < 6 && s->flags & 4; i++) {
1111  uint16_t color[4] = { 0, 0, 0, 0 };
1112  int x = positions[P][i][X];
1113  int y = positions[P][i][Y];
1114  int d = positions[P][i][D];
1115 
1116  color[D] = d;
1117  color[X] = x;
1118  color[Y] = y;
1119  color[3] = max;
1120 
1121  if (x > max / 2)
1122  x += 8;
1123  else
1124  x -= 14;
1125  if (y > max / 2)
1126  y += 8;
1127  else
1128  y -= 14;
1129 
1130  x = av_clip(x, 0, out->width - 9);
1131  y = av_clip(y, 0, out->height - 9);
1132  draw_htext16(out, x, y, o, 1. - o, positions_name[i], color);
1133  }
1134 }
1135 
1136 static void color_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1137 {
1138  const float o = s->opacity;
1139  int i;
1140 
1141  for (i = 0; i < 12; i++) {
1142  int x = positions[P][i][X];
1143  int y = positions[P][i][Y];
1144  int d = positions[P][i][D];
1145 
1146  draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
1147  draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
1148  draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
1149  if (out->data[3])
1150  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1151  }
1152 
1153  if (s->flags & 1) {
1154  int x = positions[P][12][X];
1155  int y = positions[P][12][Y];
1156  int d = positions[P][12][D];
1157 
1158  draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
1159  draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
1160  draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
1161  if (out->data[3])
1162  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1163  }
1164 
1165  if (s->flags & 2) {
1166  int x = positions[P][13][X];
1167  int y = positions[P][13][Y];
1168  int d = positions[P][12][D];
1169 
1170  draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
1171  draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
1172  draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
1173  if (out->data[3])
1174  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1175  }
1176 
1177  for (i = 0; i < 6 && s->flags & 4; i++) {
1178  uint8_t color[4] = { 0, 0, 0, 255 };
1179  int x = positions[P][i][X];
1180  int y = positions[P][i][Y];
1181  int d = positions[P][i][D];
1182 
1183  color[D] = d;
1184  color[X] = x;
1185  color[Y] = y;
1186 
1187  if (x > 128)
1188  x += 8;
1189  else
1190  x -= 14;
1191  if (y > 128)
1192  y += 8;
1193  else
1194  y -= 14;
1195 
1196  x = av_clip(x, 0, out->width - 9);
1197  y = av_clip(y, 0, out->height - 9);
1198  draw_htext(out, x, y, o, 1. - o, positions_name[i], color);
1199  }
1200 }
1201 
1202 static void green_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1203 {
1204  const int max = s->size - 1;
1205  const float o = s->opacity;
1206  const int m = s->mult;
1207  int i;
1208 
1209  for (i = 0; i < 12; i++) {
1210  int x = positions[P][i][X];
1211  int y = positions[P][i][Y];
1212 
1213  draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
1214  draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
1215  draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
1216  if (out->data[3])
1217  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1218  }
1219 
1220  if (s->flags & 1) {
1221  int x = positions[P][12][X];
1222  int y = positions[P][12][Y];
1223 
1224  draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
1225  draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
1226  draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
1227  if (out->data[3])
1228  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1229  }
1230 
1231  if (s->flags & 2) {
1232  int x = positions[P][13][X];
1233  int y = positions[P][13][Y];
1234 
1235  draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
1236  draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
1237  draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
1238  if (out->data[3])
1239  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1240  }
1241 
1242  for (i = 0; i < 6 && s->flags & 4; i++) {
1243  const uint16_t color[4] = { 128 * m, 0, 0, max };
1244  int x = positions[P][i][X];
1245  int y = positions[P][i][Y];
1246 
1247  if (x > max / 2)
1248  x += 8;
1249  else
1250  x -= 14;
1251  if (y > max / 2)
1252  y += 8;
1253  else
1254  y -= 14;
1255 
1256  x = av_clip(x, 0, out->width - 9);
1257  y = av_clip(y, 0, out->height - 9);
1258  draw_htext16(out, x, y, o, 1. - o, positions_name[i], color);
1259  }
1260 }
1261 
1262 static void green_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1263 {
1264  const float o = s->opacity;
1265  int i;
1266 
1267  for (i = 0; i < 12; i++) {
1268  int x = positions[P][i][X];
1269  int y = positions[P][i][Y];
1270 
1271  draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
1272  draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
1273  draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
1274  if (out->data[3])
1275  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1276  }
1277 
1278  if (s->flags & 1) {
1279  int x = positions[P][12][X];
1280  int y = positions[P][12][Y];
1281 
1282  draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
1283  draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
1284  draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
1285  if (out->data[3])
1286  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1287  }
1288 
1289  if (s->flags & 2) {
1290  int x = positions[P][13][X];
1291  int y = positions[P][13][Y];
1292 
1293  draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
1294  draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
1295  draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
1296  if (out->data[3])
1297  draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
1298  }
1299 
1300  for (i = 0; i < 6 && s->flags & 4; i++) {
1301  const uint8_t color[4] = { 128, 0, 0, 255 };
1302  int x = positions[P][i][X];
1303  int y = positions[P][i][Y];
1304 
1305  if (x > 128)
1306  x += 8;
1307  else
1308  x -= 14;
1309  if (y > 128)
1310  y += 8;
1311  else
1312  y -= 14;
1313 
1314  x = av_clip(x, 0, out->width - 9);
1315  y = av_clip(y, 0, out->height - 9);
1316  draw_htext(out, x, y, o, 1. - o, positions_name[i], color);
1317  }
1318 }
1319 
1320 static void invert_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1321 {
1322  const int max = s->size - 1;
1323  const float o = s->opacity;
1324  int i;
1325 
1326  for (i = 0; i < 12; i++) {
1327  int x = positions[P][i][X];
1328  int y = positions[P][i][Y];
1329 
1330  draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o);
1331  draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o);
1332  draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o);
1333  if (out->data[3])
1334  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1335  }
1336 
1337  if (s->flags & 1) {
1338  int x = positions[P][12][X];
1339  int y = positions[P][12][Y];
1340 
1341  draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o);
1342  draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o);
1343  draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o);
1344  if (out->data[3])
1345  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1346  }
1347 
1348  if (s->flags & 2) {
1349  int x = positions[P][13][X];
1350  int y = positions[P][13][Y];
1351 
1352  draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o);
1353  draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o);
1354  draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o);
1355  if (out->data[3])
1356  draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
1357  }
1358 
1359  for (i = 0; i < 6 && s->flags & 4; i++) {
1360  uint16_t color[4] = { max, max, max, max };
1361  int x = positions[P][i][X];
1362  int y = positions[P][i][Y];
1363 
1364  if (x > max / 2)
1365  x += 8;
1366  else
1367  x -= 14;
1368  if (y > max / 2)
1369  y += 8;
1370  else
1371  y -= 14;
1372 
1373  x = av_clip(x, 0, out->width - 9);
1374  y = av_clip(y, 0, out->height - 9);
1375  draw_ihtext16(out, x, y, o, 1. - o, positions_name[i], color);
1376  }
1377 }
1378 
1379 static void invert_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
1380 {
1381  const float o = s->opacity;
1382  int i;
1383 
1384  for (i = 0; i < 12; i++) {
1385  int x = positions[P][i][X];
1386  int y = positions[P][i][Y];
1387 
1388  draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o);
1389  draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o);
1390  draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o);
1391  if (out->data[3])
1392  draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o);
1393  }
1394 
1395  if (s->flags & 1) {
1396  int x = positions[P][12][X];
1397  int y = positions[P][12][Y];
1398 
1399  draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o);
1400  draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o);
1401  draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o);
1402  if (out->data[3])
1403  draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o);
1404  }
1405 
1406  if (s->flags & 2) {
1407  int x = positions[P][13][X];
1408  int y = positions[P][13][Y];
1409 
1410  draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o);
1411  draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o);
1412  draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o);
1413  if (out->data[3])
1414  draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o);
1415  }
1416 
1417  for (i = 0; i < 6 && s->flags & 4; i++) {
1418  uint8_t color[4] = { 255, 255, 255, 255 };
1419  int x = positions[P][i][X];
1420  int y = positions[P][i][Y];
1421 
1422  if (x > 128)
1423  x += 8;
1424  else
1425  x -= 14;
1426  if (y > 128)
1427  y += 8;
1428  else
1429  y -= 14;
1430 
1431  x = av_clip(x, 0, out->width - 9);
1432  y = av_clip(y, 0, out->height - 9);
1433  draw_ihtext(out, x, y, o, 1. - o, positions_name[i], color);
1434  }
1435 }
1436 
1438 {
1439  AVFilterContext *ctx = inlink->dst;
1440  VectorscopeContext *s = ctx->priv;
1441  AVFilterLink *outlink = ctx->outputs[0];
1442  AVFrame *out;
1443  int plane;
1444 
1445  if (s->colorspace) {
1446  s->cs = (s->depth - 8) * 2 + s->colorspace - 1;
1447  } else {
1448  switch (in->colorspace) {
1449  case AVCOL_SPC_SMPTE170M:
1450  case AVCOL_SPC_BT470BG:
1451  s->cs = (s->depth - 8) * 2 + 0;
1452  break;
1453  case AVCOL_SPC_BT709:
1454  default:
1455  s->cs = (s->depth - 8) * 2 + 1;
1456  }
1457  }
1458 
1459  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1460  if (!out) {
1461  av_frame_free(&in);
1462  return AVERROR(ENOMEM);
1463  }
1464  av_frame_copy_props(out, in);
1465 
1466  s->vectorscope(s, in, out, s->pd);
1467  s->graticulef(s, out, s->x, s->y, s->pd, s->cs);
1468 
1469  for (plane = 0; plane < 4; plane++) {
1470  if (out->data[plane]) {
1471  out->data[plane] += (s->size - 1) * out->linesize[plane];
1472  out->linesize[plane] = -out->linesize[plane];
1473  }
1474  }
1475 
1476  av_frame_free(&in);
1477  return ff_filter_frame(outlink, out);
1478 }
1479 
1481 {
1483  AVFilterContext *ctx = inlink->dst;
1484  VectorscopeContext *s = ctx->priv;
1485 
1486  s->is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB);
1487  s->size = 1 << desc->comp[0].depth;
1488  s->mult = s->size / 256;
1489  s->depth = desc->comp[0].depth;
1490  s->tmin = s->lthreshold * (s->size - 1);
1491  s->tmax = s->hthreshold * (s->size - 1);
1492 
1493  if (s->tmin > s->tmax) {
1494  av_log(ctx, AV_LOG_ERROR, "low threshold should be less than high threshold\n");
1495  return AVERROR(EINVAL);
1496  }
1497 
1498  if (s->mode == TINT && s->is_yuv) {
1499  s->pd = 0;
1500  } else {
1501  if ((s->x == 1 && s->y == 2) || (s->x == 2 && s->y == 1))
1502  s->pd = 0;
1503  else if ((s->x == 0 && s->y == 2) || (s->x == 2 && s->y == 0))
1504  s->pd = 1;
1505  else if ((s->x == 0 && s->y == 1) || (s->x == 1 && s->y == 0))
1506  s->pd = 2;
1507  }
1508 
1509  if (s->size == 256)
1511  else
1513 
1515 
1516  if (s->is_yuv && s->size == 256) {
1517  if (s->graticule == GRAT_GREEN)
1519  else if (s->graticule == GRAT_COLOR)
1521  else if (s->graticule == GRAT_INVERT)
1523  } else if (s->is_yuv) {
1524  if (s->graticule == GRAT_GREEN)
1526  else if (s->graticule == GRAT_COLOR)
1528  else if (s->graticule == GRAT_INVERT)
1530  }
1531 
1532  s->bg_color[3] = s->bgopacity * (s->size - 1);
1533 
1534  s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1);
1535  s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1);
1536 
1537  switch (inlink->format) {
1538  case AV_PIX_FMT_GBRP12:
1539  case AV_PIX_FMT_GBRP10:
1540  case AV_PIX_FMT_GBRP9:
1541  case AV_PIX_FMT_GBRAP:
1542  case AV_PIX_FMT_GBRP:
1543  s->bg_color[0] = 0;
1544  s->bg_color[1] = 0;
1545  s->bg_color[2] = 0;
1546  break;
1547  default:
1548  s->bg_color[0] = 0;
1549  s->bg_color[1] = s->size / 2;
1550  s->bg_color[2] = s->size / 2;
1551  }
1552 
1553  s->hsub = desc->log2_chroma_w;
1554  s->vsub = desc->log2_chroma_h;
1555  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
1556  s->planeheight[0] = s->planeheight[3] = inlink->h;
1557  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
1558  s->planewidth[0] = s->planewidth[3] = inlink->w;
1559 
1560  return 0;
1561 }
1562 
1564 {
1565  VectorscopeContext *s = ctx->priv;
1566 
1567  av_freep(&s->peak);
1568  av_freep(&s->peak_memory);
1569 }
1570 
1571 static const AVFilterPad inputs[] = {
1572  {
1573  .name = "default",
1574  .type = AVMEDIA_TYPE_VIDEO,
1575  .filter_frame = filter_frame,
1576  .config_props = config_input,
1577  },
1578  { NULL }
1579 };
1580 
1581 static const AVFilterPad outputs[] = {
1582  {
1583  .name = "default",
1584  .type = AVMEDIA_TYPE_VIDEO,
1585  .config_props = config_output,
1586  },
1587  { NULL }
1588 };
1589 
1591  .name = "vectorscope",
1592  .description = NULL_IF_CONFIG_SMALL("Video vectorscope."),
1593  .priv_size = sizeof(VectorscopeContext),
1594  .priv_class = &vectorscope_class,
1596  .uninit = uninit,
1597  .inputs = inputs,
1598  .outputs = outputs,
1599 };
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
Definition: pixfmt.h:514
static int config_input(AVFilterLink *inlink)
#define NULL
Definition: coverity.c:32
#define P
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:434
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
AVFILTER_DEFINE_CLASS(vectorscope)
AVOption.
Definition: opt.h:248
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:436
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:437
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
Main libavfilter public API header.
const char * desc
Definition: nvenc.c:87
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 ...
Definition: pixfmt.h:518
static void envelope_peak(VectorscopeContext *s, AVFrame *out)
static void draw_ihtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
static void draw_idots16(uint16_t *dst, int L, int v, float o)
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
Definition: pixfmt.h:519
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:403
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
static void envelope_instant16(VectorscopeContext *s, AVFrame *out)
static enum AVPixelFormat out_yuv8_pix_fmts[]
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
static enum AVPixelFormat out_rgb12_pix_fmts[]
#define OFFSET(x)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
void(* vectorscope)(struct VectorscopeContext *s, AVFrame *in, AVFrame *out, int pd)
Definition: vf_addroi.c:26
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1091
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
VectorscopeMode
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:88
static enum AVPixelFormat in2_pix_fmts[]
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:433
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
#define max(a, b)
Definition: cuda_runtime.h:33
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:404
#define av_log(a,...)
static void invert_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
A filter pad used for either input or output.
Definition: internal.h:54
static const AVOption vectorscope_options[]
#define src
Definition: vp8dsp.c:254
static enum AVPixelFormat out_rgb8_pix_fmts[]
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
int width
Definition: frame.h:366
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
const uint8_t avpriv_cga_font[2048]
Definition: xga_font_data.c:29
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
static const uint16_t mask[17]
Definition: lzw.c:38
static const uint16_t positions[][14][3]
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:148
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
void * priv
private data for use by the filter
Definition: avfilter.h:353
unsigned int pos
Definition: spdifenc.c:410
static const AVFilterPad inputs[]
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:563
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
simple assert() macros that are a bit more flexible than ISO C assert().
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:402
static void draw_dots16(uint16_t *dst, int L, int v, float o)
static enum AVPixelFormat in_pix_fmts[]
Definition: vf_ciescope.c:124
static void draw_idots(uint8_t *dst, int L, float o)
#define FFMAX(a, b)
Definition: common.h:94
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
AVFilter ff_vf_vectorscope
static enum AVPixelFormat out_yuv10_pix_fmts[]
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
static enum AVPixelFormat out_rgb9_pix_fmts[]
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:397
uint16_t bg_color[4]
static av_const double hypot(double x, double y)
Definition: libm.h:366
static enum AVPixelFormat in1_pix_fmts[]
#define Y
Definition: boxblur.h:38
static void none_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
static enum AVPixelFormat out_rgb10_pix_fmts[]
#define FFMIN(a, b)
Definition: common.h:96
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:440
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:470
uint8_t w
Definition: llviddspenc.c:38
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static void green_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
AVFormatContext * ctx
Definition: movenc.c:48
static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int pd)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
static void draw_dots(uint8_t *dst, int L, int v, float o)
unsigned nb_formats
number of formats
Definition: formats.h:65
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:438
#define L(x)
Definition: vp56_arith.h:36
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:398
static void color_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
static enum AVPixelFormat out_yuv12_pix_fmts[]
static void envelope_peak16(VectorscopeContext *s, AVFrame *out)
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:339
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
static const AVFilterPad outputs[]
static int config_output(AVFilterLink *outlink)
#define FLAGS
static av_cold void uninit(AVFilterContext *ctx)
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:399
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
Describe the class of an AVClass context structure.
Definition: log.h:67
static int query_formats(AVFilterContext *ctx)
static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
Filter definition.
Definition: avfilter.h:144
Rational number (pair of numerator and denominator).
Definition: rational.h:58
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
const char * name
Filter name.
Definition: avfilter.h:148
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:405
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:396
GraticuleType
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
static void envelope_instant(VectorscopeContext *s, AVFrame *out)
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:400
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:406
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
#define M_SQRT2
Definition: mathematics.h:61
void(* graticulef)(struct VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
static const char * positions_name[]
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
D(D(float, sse)
Definition: rematrix_init.c:28
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:435
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
static enum AVPixelFormat out_pix_fmts[]
Definition: vf_ciescope.c:133
static enum AVPixelFormat out_yuv9_pix_fmts[]
static void envelope16(VectorscopeContext *s, AVFrame *out)
A list of supported formats for one end of a filter link.
Definition: formats.h:64
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
An instance of a filter.
Definition: avfilter.h:338
int height
Definition: frame.h:366
FILE * out
Definition: movenc.c:54
#define av_freep(p)
static void green_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
#define AV_WN16(p, v)
Definition: intreadwrite.h:372
static void draw_ihtext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4])
static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int pd)
static void draw_htext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4])
internal API functions
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int depth
Number of bits in the component.
Definition: pixdesc.h:58
static void invert_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
for(j=16;j >0;--j)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:659
int i
Definition: input.c:406
CGA/EGA/VGA ROM font data.
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:439
#define V
Definition: avdct.c:30
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
static void color_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
int * formats
list of media formats
Definition: formats.h:66