FFmpeg  4.4.8
vf_datascope.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 "filters.h"
29 #include "drawutils.h"
30 #include "formats.h"
31 #include "internal.h"
32 #include "video.h"
33 
34 typedef struct DatascopeContext {
35  const AVClass *class;
36  int ow, oh;
37  int x, y;
38  int mode;
39  int dformat;
40  int axis;
42  float opacity;
43 
44  int nb_planes;
45  int nb_comps;
46  int chars;
52 
55  int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
57 
58 #define OFFSET(x) offsetof(DatascopeContext, x)
59 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
60 #define FLAGSR AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
61 
62 static const AVOption datascope_options[] = {
63  { "size", "set output size", OFFSET(ow), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
64  { "s", "set output size", OFFSET(ow), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
65  { "x", "set x offset", OFFSET(x), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGSR },
66  { "y", "set y offset", OFFSET(y), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGSR },
67  { "mode", "set scope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGSR, "mode" },
68  { "mono", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGSR, "mode" },
69  { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGSR, "mode" },
70  { "color2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGSR, "mode" },
71  { "axis", "draw column/row numbers", OFFSET(axis), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGSR },
72  { "opacity", "set background opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGSR },
73  { "format", "set display number format", OFFSET(dformat), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGSR, "format" },
74  { "hex", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGSR, "format" },
75  { "dec", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGSR, "format" },
76  { "components", "set components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=15}, 1, 15, FLAGSR },
77  { NULL }
78 };
79 
81 
83 {
85 }
86 
88  int x0, int y0, const uint8_t *text, int vertical)
89 {
90  int x = x0;
91 
92  for (; *text; text++) {
93  if (*text == '\n') {
94  x = x0;
95  y0 += 8;
96  continue;
97  }
100  avpriv_cga_font + *text * 8, 1, 8, 8, 0, 0, x, y0);
101  if (vertical) {
102  x = x0;
103  y0 += 8;
104  } else {
105  x += 8;
106  }
107  }
108 }
109 
110 static void pick_color8(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
111 {
112  int p, i;
113 
114  color->rgba[3] = 255;
115  for (p = 0; p < draw->nb_planes; p++) {
116  if (draw->nb_planes == 1) {
117  for (i = 0; i < 4; i++) {
118  value[i] = in->data[0][y * in->linesize[0] + x * draw->pixelstep[0] + i];
119  color->comp[0].u8[i] = value[i];
120  }
121  } else {
122  value[p] = in->data[p][(y >> draw->vsub[p]) * in->linesize[p] + (x >> draw->hsub[p])];
123  color->comp[p].u8[0] = value[p];
124  }
125  }
126 }
127 
128 static void pick_color16(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
129 {
130  int p, i;
131 
132  color->rgba[3] = 255;
133  for (p = 0; p < draw->nb_planes; p++) {
134  if (draw->nb_planes == 1) {
135  for (i = 0; i < 4; i++) {
136  value[i] = AV_RL16(in->data[0] + y * in->linesize[0] + x * draw->pixelstep[0] + i * 2);
137  color->comp[0].u16[i] = value[i];
138  }
139  } else {
140  value[p] = AV_RL16(in->data[p] + (y >> draw->vsub[p]) * in->linesize[p] + (x >> draw->hsub[p]) * 2);
141  color->comp[p].u16[0] = value[p];
142  }
143  }
144 }
145 
147 {
148  int p;
149 
150  reverse->rgba[3] = 255;
151  for (p = 0; p < draw->nb_planes; p++) {
152  reverse->comp[p].u8[0] = color->comp[p].u8[0] > 127 ? 0 : 255;
153  reverse->comp[p].u8[1] = color->comp[p].u8[1] > 127 ? 0 : 255;
154  reverse->comp[p].u8[2] = color->comp[p].u8[2] > 127 ? 0 : 255;
155  }
156 }
157 
159 {
160  int p;
161 
162  reverse->rgba[3] = 255;
163  for (p = 0; p < draw->nb_planes; p++) {
164  const unsigned max = (1 << draw->desc->comp[p].depth) - 1;
165  const unsigned mid = (max + 1) / 2;
166 
167  reverse->comp[p].u16[0] = color->comp[p].u16[0] > mid ? 0 : max;
168  reverse->comp[p].u16[1] = color->comp[p].u16[1] > mid ? 0 : max;
169  reverse->comp[p].u16[2] = color->comp[p].u16[2] > mid ? 0 : max;
170  }
171 }
172 
173 typedef struct ThreadData {
174  AVFrame *in, *out;
175  int xoff, yoff, PP;
176 } ThreadData;
177 
178 static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
179 {
180  DatascopeContext *s = ctx->priv;
181  AVFilterLink *outlink = ctx->outputs[0];
182  AVFilterLink *inlink = ctx->inputs[0];
183  ThreadData *td = arg;
184  AVFrame *in = td->in;
185  AVFrame *out = td->out;
186  const int PP = td->PP;
187  const int xoff = td->xoff;
188  const int yoff = td->yoff;
189  const int P = FFMAX(s->nb_planes, s->nb_comps);
190  const int C = s->chars;
191  const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
192  const int W = (outlink->w - xoff) / (C * 10);
193  const int H = (outlink->h - yoff) / (PP * 12);
194  const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
195  const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
196  const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
197  int x, y, p;
198 
199  for (y = 0; y < H && (y + s->y < inlink->h); y++) {
200  for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
201  FFDrawColor color = { { 0 } };
202  FFDrawColor reverse = { { 0 } };
203  int value[4] = { 0 }, pp = 0;
204 
205  s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
206  s->reverse_color(&s->draw, &color, &reverse);
207  ff_fill_rectangle(&s->draw, &color, out->data, out->linesize,
208  xoff + x * C * 10, yoff + y * PP * 12, C * 10, PP * 12);
209 
210  for (p = 0; p < P; p++) {
211  char text[256];
212 
213  if (!(s->components & (1 << p)))
214  continue;
215  snprintf(text, sizeof(text), format[D], value[p]);
216  draw_text(&s->draw, out, &reverse, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
217  pp++;
218  }
219  }
220  }
221 
222  return 0;
223 }
224 
225 static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
226 {
227  DatascopeContext *s = ctx->priv;
228  AVFilterLink *outlink = ctx->outputs[0];
229  AVFilterLink *inlink = ctx->inputs[0];
230  ThreadData *td = arg;
231  AVFrame *in = td->in;
232  AVFrame *out = td->out;
233  const int PP = td->PP;
234  const int xoff = td->xoff;
235  const int yoff = td->yoff;
236  const int P = FFMAX(s->nb_planes, s->nb_comps);
237  const int C = s->chars;
238  const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
239  const int W = (outlink->w - xoff) / (C * 10);
240  const int H = (outlink->h - yoff) / (PP * 12);
241  const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
242  const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
243  const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
244  int x, y, p;
245 
246  for (y = 0; y < H && (y + s->y < inlink->h); y++) {
247  for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
248  FFDrawColor color = { { 0 } };
249  int value[4] = { 0 }, pp = 0;
250 
251  s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
252 
253  for (p = 0; p < P; p++) {
254  char text[256];
255 
256  if (!(s->components & (1 << p)))
257  continue;
258  snprintf(text, sizeof(text), format[D], value[p]);
259  draw_text(&s->draw, out, &color, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
260  pp++;
261  }
262  }
263  }
264 
265  return 0;
266 }
267 
268 static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
269 {
270  DatascopeContext *s = ctx->priv;
271  AVFilterLink *outlink = ctx->outputs[0];
272  AVFilterLink *inlink = ctx->inputs[0];
273  ThreadData *td = arg;
274  AVFrame *in = td->in;
275  AVFrame *out = td->out;
276  const int PP = td->PP;
277  const int xoff = td->xoff;
278  const int yoff = td->yoff;
279  const int P = FFMAX(s->nb_planes, s->nb_comps);
280  const int C = s->chars;
281  const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2;
282  const int W = (outlink->w - xoff) / (C * 10);
283  const int H = (outlink->h - yoff) / (PP * 12);
284  const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"};
285  const int slice_start = ff_slice_pos(W, jobnr, nb_jobs);
286  const int slice_end = ff_slice_pos(W, jobnr + 1, nb_jobs);
287  int x, y, p;
288 
289  for (y = 0; y < H && (y + s->y < inlink->h); y++) {
290  for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
291  FFDrawColor color = { { 0 } };
292  int value[4] = { 0 }, pp = 0;
293 
294  s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
295  for (p = 0; p < P; p++) {
296  char text[256];
297 
298  if (!(s->components & (1 << p)))
299  continue;
300  snprintf(text, sizeof(text), format[D], value[p]);
301  draw_text(&s->draw, out, &s->white, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0);
302  pp++;
303  }
304  }
305  }
306 
307  return 0;
308 }
309 
310 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
311 {
312  AVFilterContext *ctx = inlink->dst;
313  DatascopeContext *s = ctx->priv;
314  AVFilterLink *outlink = ctx->outputs[0];
315  const int P = FFMAX(s->nb_planes, s->nb_comps);
316  ThreadData td = { 0 };
317  int ymaxlen = 0;
318  int xmaxlen = 0;
319  int PP = 0;
320  AVFrame *out;
321 
322  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
323  if (!out) {
324  av_frame_free(&in);
325  return AVERROR(ENOMEM);
326  }
327  out->pts = in->pts;
328 
329  ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize,
330  0, 0, outlink->w, outlink->h);
331 
332  for (int p = 0; p < P; p++) {
333  if (s->components & (1 << p))
334  PP++;
335  }
336  PP = FFMAX(PP, 1);
337 
338  if (s->axis) {
339  const int C = s->chars;
340  int Y = outlink->h / (PP * 12);
341  int X = outlink->w / (C * 10);
342  char text[256] = { 0 };
343  int x, y;
344 
345  snprintf(text, sizeof(text), "%d", s->y + Y);
346  ymaxlen = strlen(text);
347  ymaxlen *= 10;
348  snprintf(text, sizeof(text), "%d", s->x + X);
349  xmaxlen = strlen(text);
350  xmaxlen *= 10;
351 
352  Y = (outlink->h - xmaxlen) / (PP * 12);
353  X = (outlink->w - ymaxlen) / (C * 10);
354 
355  for (y = 0; y < Y; y++) {
356  snprintf(text, sizeof(text), "%d", s->y + y);
357 
358  ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
359  0, xmaxlen + y * PP * 12 + (PP + 1) * PP - 2, ymaxlen, 10);
360 
361  draw_text(&s->draw, out, &s->yellow, 2, xmaxlen + y * PP * 12 + (PP + 1) * PP, text, 0);
362  }
363 
364  for (x = 0; x < X; x++) {
365  snprintf(text, sizeof(text), "%d", s->x + x);
366 
367  ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
368  ymaxlen + x * C * 10 + 2 * C - 2, 0, 10, xmaxlen);
369 
370  draw_text(&s->draw, out, &s->yellow, ymaxlen + x * C * 10 + 2 * C, 2, text, 1);
371  }
372  }
373 
374  td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen, td.PP = PP;
375  ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(ff_filter_get_nb_threads(ctx), FFMAX(outlink->w / 20, 1)));
376 
377  av_frame_free(&in);
378  return ff_filter_frame(outlink, out);
379 }
380 
381 static int config_input(AVFilterLink *inlink)
382 {
383  DatascopeContext *s = inlink->dst->priv;
384  uint8_t alpha = s->opacity * 255;
385 
386  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
387  ff_draw_init(&s->draw, inlink->format, 0);
388  ff_draw_color(&s->draw, &s->white, (uint8_t[]){ 255, 255, 255, 255} );
389  ff_draw_color(&s->draw, &s->black, (uint8_t[]){ 0, 0, 0, alpha} );
390  ff_draw_color(&s->draw, &s->yellow, (uint8_t[]){ 255, 255, 0, 255} );
391  ff_draw_color(&s->draw, &s->gray, (uint8_t[]){ 77, 77, 77, 255} );
392  s->chars = (s->draw.desc->comp[0].depth + 7) / 8 * 2 + s->dformat;
393  s->nb_comps = s->draw.desc->nb_components;
394 
395  switch (s->mode) {
396  case 0: s->filter = filter_mono; break;
397  case 1: s->filter = filter_color; break;
398  case 2: s->filter = filter_color2; break;
399  }
400 
401  if (s->draw.desc->comp[0].depth <= 8) {
402  s->pick_color = pick_color8;
403  s->reverse_color = reverse_color8;
404  } else {
405  s->pick_color = pick_color16;
406  s->reverse_color = reverse_color16;
407  }
408 
409  return 0;
410 }
411 
412 static int config_output(AVFilterLink *outlink)
413 {
414  DatascopeContext *s = outlink->src->priv;
415 
416  outlink->h = s->oh;
417  outlink->w = s->ow;
418  outlink->sample_aspect_ratio = (AVRational){1,1};
419 
420  return 0;
421 }
422 
423 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
424  char *res, int res_len, int flags)
425 {
426  int ret;
427 
428  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
429  if (ret < 0)
430  return ret;
431 
432  return config_input(ctx->inputs[0]);
433 }
434 
435 static const AVFilterPad inputs[] = {
436  {
437  .name = "default",
438  .type = AVMEDIA_TYPE_VIDEO,
439  .filter_frame = filter_frame,
440  .config_props = config_input,
441  },
442  { NULL }
443 };
444 
445 static const AVFilterPad outputs[] = {
446  {
447  .name = "default",
448  .type = AVMEDIA_TYPE_VIDEO,
449  .config_props = config_output,
450  },
451  { NULL }
452 };
453 
455  .name = "datascope",
456  .description = NULL_IF_CONFIG_SMALL("Video data analysis."),
457  .priv_size = sizeof(DatascopeContext),
458  .priv_class = &datascope_class,
460  .inputs = inputs,
461  .outputs = outputs,
464 };
465 
466 typedef struct PixscopeContext {
467  const AVClass *class;
468 
469  float xpos, ypos;
470  float wx, wy;
471  int w, h;
472  float o;
473 
474  int x, y;
475  int ww, wh;
476 
478  int nb_comps;
479  int is_rgb;
489 
490  uint16_t values[4][80][80];
491 
494 
495 #define POFFSET(x) offsetof(PixscopeContext, x)
496 
497 static const AVOption pixscope_options[] = {
498  { "x", "set scope x offset", POFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
499  { "y", "set scope y offset", POFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
500  { "w", "set scope width", POFFSET(w), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGSR },
501  { "h", "set scope height", POFFSET(h), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGSR },
502  { "o", "set window opacity", POFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
503  { "wx", "set window x offset", POFFSET(wx), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGSR },
504  { "wy", "set window y offset", POFFSET(wy), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGSR },
505  { NULL }
506 };
507 
509 
511 {
512  PixscopeContext *s = inlink->dst->priv;
513 
514  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
515  ff_draw_init(&s->draw, inlink->format, 0);
516  ff_draw_color(&s->draw, &s->dark, (uint8_t[]){ 0, 0, 0, s->o * 255} );
517  ff_draw_color(&s->draw, &s->black, (uint8_t[]){ 0, 0, 0, 255} );
518  ff_draw_color(&s->draw, &s->white, (uint8_t[]){ 255, 255, 255, 255} );
519  ff_draw_color(&s->draw, &s->green, (uint8_t[]){ 0, 255, 0, 255} );
520  ff_draw_color(&s->draw, &s->blue, (uint8_t[]){ 0, 0, 255, 255} );
521  ff_draw_color(&s->draw, &s->red, (uint8_t[]){ 255, 0, 0, 255} );
522  s->nb_comps = s->draw.desc->nb_components;
523  s->is_rgb = s->draw.desc->flags & AV_PIX_FMT_FLAG_RGB;
524 
525  if (s->is_rgb) {
526  s->colors[0] = &s->red;
527  s->colors[1] = &s->green;
528  s->colors[2] = &s->blue;
529  s->colors[3] = &s->white;
530  ff_fill_rgba_map(s->rgba_map, inlink->format);
531  } else {
532  s->colors[0] = &s->white;
533  s->colors[1] = &s->blue;
534  s->colors[2] = &s->red;
535  s->colors[3] = &s->white;
536  s->rgba_map[0] = 0;
537  s->rgba_map[1] = 1;
538  s->rgba_map[2] = 2;
539  s->rgba_map[3] = 3;
540  }
541 
542  if (s->draw.desc->comp[0].depth <= 8) {
543  s->pick_color = pick_color8;
544  } else {
545  s->pick_color = pick_color16;
546  }
547 
548  if (inlink->w < 640 || inlink->h < 480) {
549  av_log(inlink->dst, AV_LOG_ERROR, "min supported resolution is 640x480\n");
550  return AVERROR(EINVAL);
551  }
552 
553  s->ww = 300;
554  s->wh = 300 * 1.6;
555  s->x = s->xpos * (inlink->w - 1);
556  s->y = s->ypos * (inlink->h - 1);
557  if (s->x + s->w >= inlink->w || s->y + s->h >= inlink->h) {
558  av_log(inlink->dst, AV_LOG_WARNING, "scope position is out of range, clipping\n");
559  s->x = FFMIN(s->x, inlink->w - s->w);
560  s->y = FFMIN(s->y, inlink->h - s->h);
561  }
562 
563  return 0;
564 }
565 
566 #define SQR(x) ((x)*(x))
567 
569 {
570  AVFilterContext *ctx = inlink->dst;
571  PixscopeContext *s = ctx->priv;
572  AVFilterLink *outlink = ctx->outputs[0];
573  AVFrame *out = ff_get_video_buffer(outlink, in->width, in->height);
574  int max[4] = { 0 }, min[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
575  float average[4] = { 0 };
576  double std[4] = { 0 }, rms[4] = { 0 };
577  const char rgba[4] = { 'R', 'G', 'B', 'A' };
578  const char yuva[4] = { 'Y', 'U', 'V', 'A' };
579  int x, y, X, Y, i, w, h;
580  char text[128];
581 
582  if (!out) {
583  av_frame_free(&in);
584  return AVERROR(ENOMEM);
585  }
587  av_frame_copy(out, in);
588 
589  w = s->ww / s->w;
590  h = s->ww / s->h;
591 
592  if (s->wx >= 0) {
593  X = (in->width - s->ww) * s->wx;
594  } else {
595  X = (in->width - s->ww) * -s->wx;
596  }
597  if (s->wy >= 0) {
598  Y = (in->height - s->wh) * s->wy;
599  } else {
600  Y = (in->height - s->wh) * -s->wy;
601  }
602 
603  if (s->wx < 0) {
604  if (s->x + s->w >= X && (s->x + s->w <= X + s->ww) &&
605  s->y + s->h >= Y && (s->y + s->h <= Y + s->wh)) {
606  X = (in->width - s->ww) * (1 + s->wx);
607  }
608  }
609 
610  if (s->wy < 0) {
611  if (s->x + s->w >= X && (s->x + s->w <= X + s->ww) &&
612  s->y + s->h >= Y && (s->y + s->h <= Y + s->wh)) {
613  Y = (in->height - s->wh) * (1 + s->wy);
614  }
615  }
616 
617  ff_blend_rectangle(&s->draw, &s->dark, out->data, out->linesize,
618  out->width, out->height,
619  X,
620  Y,
621  s->ww,
622  s->wh);
623 
624  for (y = 0; y < s->h; y++) {
625  for (x = 0; x < s->w; x++) {
626  FFDrawColor color = { { 0 } };
627  int value[4] = { 0 };
628 
629  s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
630  ff_fill_rectangle(&s->draw, &color, out->data, out->linesize,
631  x * w + (s->ww - 4 - (s->w * w)) / 2 + X, y * h + 2 + Y, w, h);
632  for (i = 0; i < 4; i++) {
633  s->values[i][x][y] = value[i];
634  rms[i] += (double)value[i] * (double)value[i];
635  average[i] += value[i];
636  min[i] = FFMIN(min[i], value[i]);
637  max[i] = FFMAX(max[i], value[i]);
638  }
639  }
640  }
641 
642  ff_blend_rectangle(&s->draw, &s->black, out->data, out->linesize,
643  out->width, out->height,
644  s->x - 2, s->y - 2, s->w + 4, 1);
645 
646  ff_blend_rectangle(&s->draw, &s->white, out->data, out->linesize,
647  out->width, out->height,
648  s->x - 1, s->y - 1, s->w + 2, 1);
649 
650  ff_blend_rectangle(&s->draw, &s->white, out->data, out->linesize,
651  out->width, out->height,
652  s->x - 1, s->y - 1, 1, s->h + 2);
653 
654  ff_blend_rectangle(&s->draw, &s->black, out->data, out->linesize,
655  out->width, out->height,
656  s->x - 2, s->y - 2, 1, s->h + 4);
657 
658  ff_blend_rectangle(&s->draw, &s->white, out->data, out->linesize,
659  out->width, out->height,
660  s->x - 1, s->y + 1 + s->h, s->w + 3, 1);
661 
662  ff_blend_rectangle(&s->draw, &s->black, out->data, out->linesize,
663  out->width, out->height,
664  s->x - 2, s->y + 2 + s->h, s->w + 4, 1);
665 
666  ff_blend_rectangle(&s->draw, &s->white, out->data, out->linesize,
667  out->width, out->height,
668  s->x + 1 + s->w, s->y - 1, 1, s->h + 2);
669 
670  ff_blend_rectangle(&s->draw, &s->black, out->data, out->linesize,
671  out->width, out->height,
672  s->x + 2 + s->w, s->y - 2, 1, s->h + 5);
673 
674  for (i = 0; i < 4; i++) {
675  rms[i] /= s->w * s->h;
676  rms[i] = sqrt(rms[i]);
677  average[i] /= s->w * s->h;
678  }
679 
680  for (y = 0; y < s->h; y++) {
681  for (x = 0; x < s->w; x++) {
682  for (i = 0; i < 4; i++)
683  std[i] += SQR(s->values[i][x][y] - average[i]);
684  }
685  }
686 
687  for (i = 0; i < 4; i++) {
688  std[i] /= s->w * s->h;
689  std[i] = sqrt(std[i]);
690  }
691 
692  snprintf(text, sizeof(text), "CH AVG MIN MAX RMS\n");
693  draw_text(&s->draw, out, &s->white, X + 28, Y + s->ww + 5, text, 0);
694  for (i = 0; i < s->nb_comps; i++) {
695  int c = s->rgba_map[i];
696 
697  snprintf(text, sizeof(text), "%c %07.1f %05d %05d %07.1f\n", s->is_rgb ? rgba[i] : yuva[i], average[c], min[c], max[c], rms[c]);
698  draw_text(&s->draw, out, s->colors[i], X + 28, Y + s->ww + 15 * (i + 1), text, 0);
699  }
700  snprintf(text, sizeof(text), "CH STD\n");
701  draw_text(&s->draw, out, &s->white, X + 28, Y + s->ww + 15 * (0 + 5), text, 0);
702  for (i = 0; i < s->nb_comps; i++) {
703  int c = s->rgba_map[i];
704 
705  snprintf(text, sizeof(text), "%c %07.2f\n", s->is_rgb ? rgba[i] : yuva[i], std[c]);
706  draw_text(&s->draw, out, s->colors[i], X + 28, Y + s->ww + 15 * (i + 6), text, 0);
707  }
708 
709  av_frame_free(&in);
710  return ff_filter_frame(outlink, out);
711 }
712 
713 static int pixscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args,
714  char *res, int res_len, int flags)
715 {
716  int ret;
717 
718  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
719  if (ret < 0)
720  return ret;
721 
722  return pixscope_config_input(ctx->inputs[0]);
723 }
724 
725 static const AVFilterPad pixscope_inputs[] = {
726  {
727  .name = "default",
728  .type = AVMEDIA_TYPE_VIDEO,
729  .filter_frame = pixscope_filter_frame,
730  .config_props = pixscope_config_input,
731  },
732  { NULL }
733 };
734 
735 static const AVFilterPad pixscope_outputs[] = {
736  {
737  .name = "default",
738  .type = AVMEDIA_TYPE_VIDEO,
739  },
740  { NULL }
741 };
742 
744  .name = "pixscope",
745  .description = NULL_IF_CONFIG_SMALL("Pixel data analysis."),
746  .priv_size = sizeof(PixscopeContext),
747  .priv_class = &pixscope_class,
753 };
754 
755 typedef struct PixelValues {
756  uint16_t p[4];
757 } PixelValues;
758 
759 typedef struct OscilloscopeContext {
760  const AVClass *class;
761 
762  float xpos, ypos;
763  float tx, ty;
764  float size;
765  float tilt;
766  float theight, twidth;
767  float o;
769  int grid;
771  int scope;
772 
773  int x1, y1, x2, y2;
774  int ox, oy;
775  int height, width;
776 
777  int max;
779  int nb_comps;
780  int is_rgb;
793 
796 
800 
801 #define OOFFSET(x) offsetof(OscilloscopeContext, x)
802 
803 static const AVOption oscilloscope_options[] = {
804  { "x", "set scope x position", OOFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
805  { "y", "set scope y position", OOFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
806  { "s", "set scope size", OOFFSET(size), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGSR },
807  { "t", "set scope tilt", OOFFSET(tilt), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
808  { "o", "set trace opacity", OOFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGSR },
809  { "tx", "set trace x position", OOFFSET(tx), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR },
810  { "ty", "set trace y position", OOFFSET(ty), AV_OPT_TYPE_FLOAT, {.dbl=0.9}, 0, 1, FLAGSR },
811  { "tw", "set trace width", OOFFSET(twidth), AV_OPT_TYPE_FLOAT, {.dbl=0.8},.1, 1, FLAGSR },
812  { "th", "set trace height", OOFFSET(theight), AV_OPT_TYPE_FLOAT, {.dbl=0.3},.1, 1, FLAGSR },
813  { "c", "set components to trace", OOFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGSR },
814  { "g", "draw trace grid", OOFFSET(grid), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR },
815  { "st", "draw statistics", OOFFSET(statistics), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR },
816  { "sc", "draw scope", OOFFSET(scope), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR },
817  { NULL }
818 };
819 
820 AVFILTER_DEFINE_CLASS(oscilloscope);
821 
823 {
824  OscilloscopeContext *s = ctx->priv;
825 
826  av_freep(&s->values);
827 }
828 
829 static void draw_line(FFDrawContext *draw, int x0, int y0, int x1, int y1,
831 {
832  int dx = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
833  int dy = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
834  int err = (dx > dy ? dx : -dy) / 2, e2;
835  int p, i;
836 
837  for (;;) {
838  if (x0 >= 0 && y0 >= 0 && x0 < out->width && y0 < out->height) {
839  for (p = 0; p < draw->nb_planes; p++) {
840  if (draw->desc->comp[p].depth == 8) {
841  if (draw->nb_planes == 1) {
842  for (i = 0; i < draw->desc->nb_components; i++) {
843  out->data[0][y0 * out->linesize[0] + x0 * draw->pixelstep[0] + i] = color->comp[0].u8[i];
844  }
845  } else {
846  out->data[p][out->linesize[p] * (y0 >> draw->vsub[p]) + (x0 >> draw->hsub[p])] = color->comp[p].u8[0];
847  }
848  } else {
849  if (draw->nb_planes == 1) {
850  for (i = 0; i < draw->desc->nb_components; i++) {
851  AV_WN16(out->data[0] + y0 * out->linesize[0] + (x0 * draw->pixelstep[0] + i), color->comp[0].u16[i]);
852  }
853  } else {
854  AV_WN16(out->data[p] + out->linesize[p] * (y0 >> draw->vsub[p]) + (x0 >> draw->hsub[p]) * 2, color->comp[p].u16[0]);
855  }
856  }
857  }
858  }
859 
860  if (x0 == x1 && y0 == y1)
861  break;
862 
863  e2 = err;
864 
865  if (e2 >-dx) {
866  err -= dy;
867  x0 += sx;
868  }
869 
870  if (e2 < dy) {
871  err += dx;
872  y0 += sy;
873  }
874  }
875 }
876 
878 {
879  int i, c;
880 
881  for (i = 1; i < s->nb_values; i++) {
882  for (c = 0; c < s->nb_comps; c++) {
883  if ((1 << c) & s->components) {
884  int x = i * s->width / s->nb_values;
885  int px = (i - 1) * s->width / s->nb_values;
886  int py = s->height - s->values[i-1].p[s->rgba_map[c]] * s->height / 256;
887  int y = s->height - s->values[i].p[s->rgba_map[c]] * s->height / 256;
888 
889  draw_line(&s->draw, s->ox + x, s->oy + y, s->ox + px, s->oy + py, frame, s->colors[c]);
890  }
891  }
892  }
893 }
894 
895 
897 {
898  int i, c;
899 
900  for (i = 1; i < s->nb_values; i++) {
901  for (c = 0; c < s->nb_comps; c++) {
902  if ((1 << c) & s->components) {
903  int x = i * s->width / s->nb_values;
904  int px = (i - 1) * s->width / s->nb_values;
905  int py = s->height - s->values[i-1].p[s->rgba_map[c]] * s->height / s->max;
906  int y = s->height - s->values[i].p[s->rgba_map[c]] * s->height / s->max;
907 
908  draw_line(&s->draw, s->ox + x, s->oy + y, s->ox + px, s->oy + py, frame, s->colors[c]);
909  }
910  }
911  }
912 }
913 
915 {
916  OscilloscopeContext *s = ctx->priv;
917  AVFilterLink *inlink = ctx->inputs[0];
918  int cx, cy, size;
919  double tilt;
920 
921  ff_draw_color(&s->draw, &s->dark, (uint8_t[]){ 0, 0, 0, s->o * 255} );
922  s->height = s->theight * inlink->h;
923  s->width = s->twidth * inlink->w;
924  size = hypot(inlink->w, inlink->h);
925  size *= s->size;
926  tilt = (s->tilt - 0.5) * M_PI;
927  cx = s->xpos * (inlink->w - 1);
928  cy = s->ypos * (inlink->h - 1);
929  s->x1 = cx - size / 2.0 * cos(tilt);
930  s->x2 = cx + size / 2.0 * cos(tilt);
931  s->y1 = cy - size / 2.0 * sin(tilt);
932  s->y2 = cy + size / 2.0 * sin(tilt);
933  s->ox = (inlink->w - s->width) * s->tx;
934  s->oy = (inlink->h - s->height) * s->ty;
935 }
936 
938 {
939  OscilloscopeContext *s = inlink->dst->priv;
940  int size;
941 
942  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
943  ff_draw_init(&s->draw, inlink->format, 0);
944  ff_draw_color(&s->draw, &s->black, (uint8_t[]){ 0, 0, 0, 255} );
945  ff_draw_color(&s->draw, &s->white, (uint8_t[]){ 255, 255, 255, 255} );
946  ff_draw_color(&s->draw, &s->green, (uint8_t[]){ 0, 255, 0, 255} );
947  ff_draw_color(&s->draw, &s->blue, (uint8_t[]){ 0, 0, 255, 255} );
948  ff_draw_color(&s->draw, &s->red, (uint8_t[]){ 255, 0, 0, 255} );
949  ff_draw_color(&s->draw, &s->cyan, (uint8_t[]){ 0, 255, 255, 255} );
950  ff_draw_color(&s->draw, &s->magenta, (uint8_t[]){ 255, 0, 255, 255} );
951  ff_draw_color(&s->draw, &s->gray, (uint8_t[]){ 128, 128, 128, 255} );
952  s->nb_comps = s->draw.desc->nb_components;
953  s->is_rgb = s->draw.desc->flags & AV_PIX_FMT_FLAG_RGB;
954 
955  if (s->is_rgb) {
956  s->colors[0] = &s->red;
957  s->colors[1] = &s->green;
958  s->colors[2] = &s->blue;
959  s->colors[3] = &s->white;
960  ff_fill_rgba_map(s->rgba_map, inlink->format);
961  } else {
962  s->colors[0] = &s->white;
963  s->colors[1] = &s->cyan;
964  s->colors[2] = &s->magenta;
965  s->colors[3] = &s->white;
966  s->rgba_map[0] = 0;
967  s->rgba_map[1] = 1;
968  s->rgba_map[2] = 2;
969  s->rgba_map[3] = 3;
970  }
971 
972  if (s->draw.desc->comp[0].depth <= 8) {
973  s->pick_color = pick_color8;
974  s->draw_trace = draw_trace8;
975  } else {
976  s->pick_color = pick_color16;
977  s->draw_trace = draw_trace16;
978  }
979 
980  s->max = (1 << s->draw.desc->comp[0].depth);
981  size = hypot(inlink->w, inlink->h);
982 
983  s->values = av_calloc(size, sizeof(*s->values));
984  if (!s->values)
985  return AVERROR(ENOMEM);
986 
987  update_oscilloscope(inlink->dst);
988 
989  return 0;
990 }
991 
992 static void draw_scope(OscilloscopeContext *s, int x0, int y0, int x1, int y1,
993  AVFrame *out, PixelValues *p, int state)
994 {
995  int dx = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
996  int dy = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
997  int err = (dx > dy ? dx : -dy) / 2, e2;
998 
999  for (;;) {
1000  if (x0 >= 0 && y0 >= 0 && x0 < out->width && y0 < out->height) {
1001  FFDrawColor color = { { 0 } };
1002  int value[4] = { 0 };
1003 
1004  s->pick_color(&s->draw, &color, out, x0, y0, value);
1005  s->values[s->nb_values].p[0] = value[0];
1006  s->values[s->nb_values].p[1] = value[1];
1007  s->values[s->nb_values].p[2] = value[2];
1008  s->values[s->nb_values].p[3] = value[3];
1009  s->nb_values++;
1010 
1011  if (s->scope) {
1012  if (s->draw.desc->comp[0].depth == 8) {
1013  if (s->draw.nb_planes == 1) {
1014  int i;
1015 
1016  for (i = 0; i < s->nb_comps; i++)
1017  out->data[0][out->linesize[0] * y0 + x0 * s->draw.pixelstep[0] + i] = 255 * ((s->nb_values + state) & 1);
1018  } else {
1019  out->data[0][out->linesize[0] * y0 + x0] = 255 * ((s->nb_values + state) & 1);
1020  }
1021  } else {
1022  if (s->draw.nb_planes == 1) {
1023  int i;
1024 
1025  for (i = 0; i < s->nb_comps; i++)
1026  AV_WN16(out->data[0] + out->linesize[0] * y0 + x0 * s->draw.pixelstep[0] + i, (s->max - 1) * ((s->nb_values + state) & 1));
1027  } else {
1028  AV_WN16(out->data[0] + out->linesize[0] * y0 + 2 * x0, (s->max - 1) * ((s->nb_values + state) & 1));
1029  }
1030  }
1031  }
1032  }
1033 
1034  if (x0 == x1 && y0 == y1)
1035  break;
1036 
1037  e2 = err;
1038 
1039  if (e2 >-dx) {
1040  err -= dy;
1041  x0 += sx;
1042  }
1043 
1044  if (e2 < dy) {
1045  err += dx;
1046  y0 += sy;
1047  }
1048  }
1049 }
1050 
1052 {
1053  AVFilterContext *ctx = inlink->dst;
1054  OscilloscopeContext *s = ctx->priv;
1055  AVFilterLink *outlink = ctx->outputs[0];
1056  float average[4] = { 0 };
1057  int max[4] = { 0 };
1058  int min[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
1059  int i, c;
1060 
1061  s->nb_values = 0;
1062  draw_scope(s, s->x1, s->y1, s->x2, s->y2, frame, s->values, inlink->frame_count_in & 1);
1063  ff_blend_rectangle(&s->draw, &s->dark, frame->data, frame->linesize,
1064  frame->width, frame->height,
1065  s->ox, s->oy, s->width, s->height + 20 * s->statistics);
1066 
1067  if (s->grid && outlink->h >= 10) {
1068  ff_fill_rectangle(&s->draw, &s->gray, frame->data, frame->linesize,
1069  s->ox, s->oy, s->width - 1, 1);
1070 
1071  for (i = 1; i < 5; i++) {
1072  ff_fill_rectangle(&s->draw, &s->gray, frame->data, frame->linesize,
1073  s->ox, s->oy + i * (s->height - 1) / 4, s->width, 1);
1074  }
1075 
1076  for (i = 0; i < 10; i++) {
1077  ff_fill_rectangle(&s->draw, &s->gray, frame->data, frame->linesize,
1078  s->ox + i * (s->width - 1) / 10, s->oy, 1, s->height);
1079  }
1080 
1081  ff_fill_rectangle(&s->draw, &s->gray, frame->data, frame->linesize,
1082  s->ox + s->width - 1, s->oy, 1, s->height);
1083  }
1084 
1085  s->draw_trace(s, frame);
1086 
1087  for (i = 0; i < s->nb_values; i++) {
1088  for (c = 0; c < s->nb_comps; c++) {
1089  if ((1 << c) & s->components) {
1090  max[c] = FFMAX(max[c], s->values[i].p[s->rgba_map[c]]);
1091  min[c] = FFMIN(min[c], s->values[i].p[s->rgba_map[c]]);
1092  average[c] += s->values[i].p[s->rgba_map[c]];
1093  }
1094  }
1095  }
1096  for (c = 0; c < s->nb_comps; c++) {
1097  average[c] /= s->nb_values;
1098  }
1099 
1100  if (s->statistics && s->height > 10 && s->width > 280 * av_popcount(s->components)) {
1101  for (c = 0, i = 0; c < s->nb_comps; c++) {
1102  if ((1 << c) & s->components) {
1103  const char rgba[4] = { 'R', 'G', 'B', 'A' };
1104  const char yuva[4] = { 'Y', 'U', 'V', 'A' };
1105  char text[128];
1106 
1107  snprintf(text, sizeof(text), "%c avg:%.1f min:%d max:%d\n", s->is_rgb ? rgba[c] : yuva[c], average[c], min[c], max[c]);
1108  draw_text(&s->draw, frame, &s->white, s->ox + 2 + 280 * i++, s->oy + s->height + 4, text, 0);
1109  }
1110  }
1111  }
1112 
1113  return ff_filter_frame(outlink, frame);
1114 }
1115 
1116 static int oscilloscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args,
1117  char *res, int res_len, int flags)
1118 {
1119  int ret;
1120 
1121  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
1122  if (ret < 0)
1123  return ret;
1124 
1126 
1127  return 0;
1128 }
1129 
1131  {
1132  .name = "default",
1133  .type = AVMEDIA_TYPE_VIDEO,
1134  .filter_frame = oscilloscope_filter_frame,
1135  .config_props = oscilloscope_config_input,
1136  .needs_writable = 1,
1137  },
1138  { NULL }
1139 };
1140 
1142  {
1143  .name = "default",
1144  .type = AVMEDIA_TYPE_VIDEO,
1145  },
1146  { NULL }
1147 };
1148 
1150  .name = "oscilloscope",
1151  .description = NULL_IF_CONFIG_SMALL("2D Video Oscilloscope."),
1152  .priv_size = sizeof(OscilloscopeContext),
1153  .priv_class = &oscilloscope_class,
1160 };
static const char *const format[]
Definition: af_aiir.c:456
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
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:882
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
Main libavfilter public API header.
#define AV_RL16
Definition: intreadwrite.h:42
#define Y
Definition: boxblur.h:38
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define s(width, name)
Definition: cbs_vp9.c:257
static struct @321 state
#define FFMIN(a, b)
Definition: common.h:105
#define av_popcount
Definition: common.h:176
#define FFMAX(a, b)
Definition: common.h:103
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define NULL
Definition: coverity.c:32
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:279
#define max(a, b)
Definition: cuda_runtime.h:33
static AVFrame * frame
void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, int x0, int y0, int w, int h)
Blend a rectangle with an uniform color.
Definition: drawutils.c:351
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:84
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:137
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition: drawutils.c:224
void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, int l2depth, unsigned endianness, int x0, int y0)
Blend an alpha mask with an uniform color.
Definition: drawutils.c:528
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:637
misc drawing utilities
mode
Use these values in ebur128_init (or'ed).
Definition: ebur128.h:83
double value
Definition: eval.c:100
int
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
Definition: filters.h:271
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:587
@ AV_OPT_TYPE_IMAGE_SIZE
offset must point to two consecutive integers
Definition: opt.h:235
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
@ AV_OPT_TYPE_INT
Definition: opt.h:225
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:228
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:126
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:799
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
static const int16_t alpha[]
Definition: ilbcdata.h:55
int i
Definition: input.c:407
#define AV_WN16(p, v)
Definition: intreadwrite.h:372
#define C
const char * arg
Definition: jacosubdec.c:66
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static av_const double hypot(double x, double y)
Definition: libm.h:366
uint8_t w
Definition: llviddspenc.c:39
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
#define M_PI
Definition: mathematics.h:52
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
#define P
AVOptions.
misc parsing utilities
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2613
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:148
#define td
Definition: regdef.h:70
D(D(float, sse)
Definition: rematrix_init.c:28
typedef void(RENAME(mix_any_func_type))
#define snprintf
Definition: snprintf.h:34
static uint32_t reverse(uint32_t num, int bits)
Definition: speedhqenc.c:51
Describe the class of an AVClass context structure.
Definition: log.h:67
int depth
Number of bits in the component.
Definition: pixdesc.h:58
An instance of a filter.
Definition: avfilter.h:341
void * priv
private data for use by the filter
Definition: avfilter.h:356
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1699
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:332
int width
Definition: frame.h:376
int height
Definition: frame.h:376
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:349
AVOption.
Definition: opt.h:248
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
Rational number (pair of numerator and denominator).
Definition: rational.h:58
void(* pick_color)(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
Definition: vf_datascope.c:53
FFDrawColor yellow
Definition: vf_datascope.c:48
void(* reverse_color)(FFDrawContext *draw, FFDrawColor *color, FFDrawColor *reverse)
Definition: vf_datascope.c:54
FFDrawContext draw
Definition: vf_datascope.c:47
FFDrawColor white
Definition: vf_datascope.c:49
FFDrawColor black
Definition: vf_datascope.c:50
int(* filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_datascope.c:55
FFDrawColor gray
Definition: vf_datascope.c:51
unsigned nb_planes
Definition: drawutils.h:38
const struct AVPixFmtDescriptor * desc
Definition: drawutils.h:36
uint8_t vsub[MAX_PLANES]
Definition: drawutils.h:42
uint8_t hsub[MAX_PLANES]
Definition: drawutils.h:41
int pixelstep[MAX_PLANES]
Definition: drawutils.h:39
FFDrawColor * colors[4]
Definition: vf_datascope.c:792
void(* pick_color)(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
Definition: vf_datascope.c:797
PixelValues * values
Definition: vf_datascope.c:795
FFDrawColor magenta
Definition: vf_datascope.c:790
void(* draw_trace)(struct OscilloscopeContext *s, AVFrame *frame)
Definition: vf_datascope.c:798
FFDrawContext draw
Definition: vf_datascope.c:782
uint16_t p[4]
Definition: vf_datascope.c:756
FFDrawColor black
Definition: vf_datascope.c:483
uint16_t values[4][80][80]
Definition: vf_datascope.c:490
uint8_t rgba_map[4]
Definition: vf_datascope.c:480
FFDrawColor green
Definition: vf_datascope.c:485
FFDrawColor dark
Definition: vf_datascope.c:482
FFDrawColor * colors[4]
Definition: vf_datascope.c:488
FFDrawColor white
Definition: vf_datascope.c:484
void(* pick_color)(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
Definition: vf_datascope.c:492
FFDrawColor blue
Definition: vf_datascope.c:486
FFDrawColor red
Definition: vf_datascope.c:487
FFDrawContext draw
Definition: vf_datascope.c:481
Used for passing data between threads.
Definition: dsddec.c:67
AVFrame * out
Definition: af_adeclick.c:502
AVFrame * in
Definition: af_adenorm.c:223
#define av_freep(p)
#define av_log(a,...)
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
#define height
#define width
int size
@ H
Definition: vf_addroi.c:26
@ X
Definition: vf_addroi.c:26
@ W
Definition: vf_addroi.c:26
static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_datascope.c:268
static const AVOption datascope_options[]
Definition: vf_datascope.c:62
static const AVFilterPad oscilloscope_outputs[]
#define FLAGSR
Definition: vf_datascope.c:60
static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_datascope.c:225
static void draw_trace8(OscilloscopeContext *s, AVFrame *frame)
Definition: vf_datascope.c:877
static void draw_trace16(OscilloscopeContext *s, AVFrame *frame)
Definition: vf_datascope.c:896
static void draw_text(FFDrawContext *draw, AVFrame *frame, FFDrawColor *color, int x0, int y0, const uint8_t *text, int vertical)
Definition: vf_datascope.c:87
static const AVOption oscilloscope_options[]
Definition: vf_datascope.c:803
static int pixscope_filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_datascope.c:568
static void oscilloscope_uninit(AVFilterContext *ctx)
Definition: vf_datascope.c:822
AVFILTER_DEFINE_CLASS(datascope)
static int query_formats(AVFilterContext *ctx)
Definition: vf_datascope.c:82
static int config_input(AVFilterLink *inlink)
Definition: vf_datascope.c:381
#define FLAGS
Definition: vf_datascope.c:59
static const AVFilterPad inputs[]
Definition: vf_datascope.c:435
static const AVOption pixscope_options[]
Definition: vf_datascope.c:497
static void draw_scope(OscilloscopeContext *s, int x0, int y0, int x1, int y1, AVFrame *out, PixelValues *p, int state)
Definition: vf_datascope.c:992
static const AVFilterPad outputs[]
Definition: vf_datascope.c:445
static int oscilloscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static void pick_color16(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
Definition: vf_datascope.c:128
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_datascope.c:310
#define POFFSET(x)
Definition: vf_datascope.c:495
static int pixscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_datascope.c:713
#define SQR(x)
Definition: vf_datascope.c:566
#define OOFFSET(x)
Definition: vf_datascope.c:801
static int oscilloscope_filter_frame(AVFilterLink *inlink, AVFrame *frame)
static void reverse_color8(FFDrawContext *draw, FFDrawColor *color, FFDrawColor *reverse)
Definition: vf_datascope.c:146
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_datascope.c:423
static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_datascope.c:178
static const AVFilterPad oscilloscope_inputs[]
static void reverse_color16(FFDrawContext *draw, FFDrawColor *color, FFDrawColor *reverse)
Definition: vf_datascope.c:158
static int pixscope_config_input(AVFilterLink *inlink)
Definition: vf_datascope.c:510
AVFilter ff_vf_datascope
Definition: vf_datascope.c:454
static const AVFilterPad pixscope_outputs[]
Definition: vf_datascope.c:735
#define OFFSET(x)
Definition: vf_datascope.c:58
static int config_output(AVFilterLink *outlink)
Definition: vf_datascope.c:412
static void draw_line(FFDrawContext *draw, int x0, int y0, int x1, int y1, AVFrame *out, FFDrawColor *color)
Definition: vf_datascope.c:829
AVFilter ff_vf_oscilloscope
AVFilter ff_vf_pixscope
Definition: vf_datascope.c:743
static void update_oscilloscope(AVFilterContext *ctx)
Definition: vf_datascope.c:914
static const AVFilterPad pixscope_inputs[]
Definition: vf_datascope.c:725
static int oscilloscope_config_input(AVFilterLink *inlink)
Definition: vf_datascope.c:937
static void pick_color8(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
Definition: vf_datascope.c:110
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:104
float min
static double c[64]
const uint8_t avpriv_cga_font[2048]
Definition: xga_font_data.c:29
CGA/EGA/VGA ROM font data.