FFmpeg
vf_colorchannelmixer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 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/opt.h"
22 #include "libavutil/pixdesc.h"
23 #include "avfilter.h"
24 #include "drawutils.h"
25 #include "formats.h"
26 #include "internal.h"
27 #include "video.h"
28 
29 #define R 0
30 #define G 1
31 #define B 2
32 #define A 3
33 
34 typedef struct ThreadData {
35  AVFrame *in, *out;
36 } ThreadData;
37 
38 typedef struct ColorChannelMixerContext {
39  const AVClass *class;
40  double rr, rg, rb, ra;
41  double gr, gg, gb, ga;
42  double br, bg, bb, ba;
43  double ar, ag, ab, aa;
44 
45  int *lut[4][4];
46 
47  int *buffer;
48 
49  uint8_t rgba_map[4];
50 
51  int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
53 
54 #define OFFSET(x) offsetof(ColorChannelMixerContext, x)
55 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
56 
58  { "rr", "set the red gain for the red channel", OFFSET(rr), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
59  { "rg", "set the green gain for the red channel", OFFSET(rg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
60  { "rb", "set the blue gain for the red channel", OFFSET(rb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
61  { "ra", "set the alpha gain for the red channel", OFFSET(ra), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
62  { "gr", "set the red gain for the green channel", OFFSET(gr), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
63  { "gg", "set the green gain for the green channel", OFFSET(gg), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
64  { "gb", "set the blue gain for the green channel", OFFSET(gb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
65  { "ga", "set the alpha gain for the green channel", OFFSET(ga), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
66  { "br", "set the red gain for the blue channel", OFFSET(br), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
67  { "bg", "set the green gain for the blue channel", OFFSET(bg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
68  { "bb", "set the blue gain for the blue channel", OFFSET(bb), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
69  { "ba", "set the alpha gain for the blue channel", OFFSET(ba), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
70  { "ar", "set the red gain for the alpha channel", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
71  { "ag", "set the green gain for the alpha channel", OFFSET(ag), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
72  { "ab", "set the blue gain for the alpha channel", OFFSET(ab), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
73  { "aa", "set the alpha gain for the alpha channel", OFFSET(aa), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
74  { NULL }
75 };
76 
77 AVFILTER_DEFINE_CLASS(colorchannelmixer);
78 
80 {
81  static const enum AVPixelFormat pix_fmts[] = {
96  };
97 
98  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
99  if (!fmts_list)
100  return AVERROR(ENOMEM);
101  return ff_set_common_formats(ctx, fmts_list);
102 }
103 
104 static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
105  int have_alpha)
106 {
108  ThreadData *td = arg;
109  AVFrame *in = td->in;
110  AVFrame *out = td->out;
111  const int slice_start = (out->height * jobnr) / nb_jobs;
112  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
113  const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0];
114  const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1];
115  const uint8_t *srcr = in->data[2] + slice_start * in->linesize[2];
116  const uint8_t *srca = in->data[3] + slice_start * in->linesize[3];
117  uint8_t *dstg = out->data[0] + slice_start * out->linesize[0];
118  uint8_t *dstb = out->data[1] + slice_start * out->linesize[1];
119  uint8_t *dstr = out->data[2] + slice_start * out->linesize[2];
120  uint8_t *dsta = out->data[3] + slice_start * out->linesize[3];
121  int i, j;
122 
123  for (i = slice_start; i < slice_end; i++) {
124  for (j = 0; j < out->width; j++) {
125  const uint8_t rin = srcr[j];
126  const uint8_t gin = srcg[j];
127  const uint8_t bin = srcb[j];
128  const uint8_t ain = have_alpha ? srca[j] : 0;
129 
130  dstr[j] = av_clip_uint8(s->lut[R][R][rin] +
131  s->lut[R][G][gin] +
132  s->lut[R][B][bin] +
133  (have_alpha == 1 ? s->lut[R][A][ain] : 0));
134  dstg[j] = av_clip_uint8(s->lut[G][R][rin] +
135  s->lut[G][G][gin] +
136  s->lut[G][B][bin] +
137  (have_alpha == 1 ? s->lut[G][A][ain] : 0));
138  dstb[j] = av_clip_uint8(s->lut[B][R][rin] +
139  s->lut[B][G][gin] +
140  s->lut[B][B][bin] +
141  (have_alpha == 1 ? s->lut[B][A][ain] : 0));
142  if (have_alpha == 1) {
143  dsta[j] = av_clip_uint8(s->lut[A][R][rin] +
144  s->lut[A][G][gin] +
145  s->lut[A][B][bin] +
146  s->lut[A][A][ain]);
147  }
148  }
149 
150  srcg += in->linesize[0];
151  srcb += in->linesize[1];
152  srcr += in->linesize[2];
153  srca += in->linesize[3];
154  dstg += out->linesize[0];
155  dstb += out->linesize[1];
156  dstr += out->linesize[2];
157  dsta += out->linesize[3];
158  }
159 
160  return 0;
161 }
162 
163 static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
164  int have_alpha, int depth)
165 {
167  ThreadData *td = arg;
168  AVFrame *in = td->in;
169  AVFrame *out = td->out;
170  const int slice_start = (out->height * jobnr) / nb_jobs;
171  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
172  const uint16_t *srcg = (const uint16_t *)(in->data[0] + slice_start * in->linesize[0]);
173  const uint16_t *srcb = (const uint16_t *)(in->data[1] + slice_start * in->linesize[1]);
174  const uint16_t *srcr = (const uint16_t *)(in->data[2] + slice_start * in->linesize[2]);
175  const uint16_t *srca = (const uint16_t *)(in->data[3] + slice_start * in->linesize[3]);
176  uint16_t *dstg = (uint16_t *)(out->data[0] + slice_start * out->linesize[0]);
177  uint16_t *dstb = (uint16_t *)(out->data[1] + slice_start * out->linesize[1]);
178  uint16_t *dstr = (uint16_t *)(out->data[2] + slice_start * out->linesize[2]);
179  uint16_t *dsta = (uint16_t *)(out->data[3] + slice_start * out->linesize[3]);
180  int i, j;
181 
182  for (i = slice_start; i < slice_end; i++) {
183  for (j = 0; j < out->width; j++) {
184  const uint16_t rin = srcr[j];
185  const uint16_t gin = srcg[j];
186  const uint16_t bin = srcb[j];
187  const uint16_t ain = have_alpha ? srca[j] : 0;
188 
189  dstr[j] = av_clip_uintp2(s->lut[R][R][rin] +
190  s->lut[R][G][gin] +
191  s->lut[R][B][bin] +
192  (have_alpha == 1 ? s->lut[R][A][ain] : 0), depth);
193  dstg[j] = av_clip_uintp2(s->lut[G][R][rin] +
194  s->lut[G][G][gin] +
195  s->lut[G][B][bin] +
196  (have_alpha == 1 ? s->lut[G][A][ain] : 0), depth);
197  dstb[j] = av_clip_uintp2(s->lut[B][R][rin] +
198  s->lut[B][G][gin] +
199  s->lut[B][B][bin] +
200  (have_alpha == 1 ? s->lut[B][A][ain] : 0), depth);
201  if (have_alpha == 1) {
202  dsta[j] = av_clip_uintp2(s->lut[A][R][rin] +
203  s->lut[A][G][gin] +
204  s->lut[A][B][bin] +
205  s->lut[A][A][ain], depth);
206  }
207  }
208 
209  srcg += in->linesize[0] / 2;
210  srcb += in->linesize[1] / 2;
211  srcr += in->linesize[2] / 2;
212  srca += in->linesize[3] / 2;
213  dstg += out->linesize[0] / 2;
214  dstb += out->linesize[1] / 2;
215  dstr += out->linesize[2] / 2;
216  dsta += out->linesize[3] / 2;
217  }
218 
219  return 0;
220 }
221 
222 static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
223 {
224  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0);
225 }
226 
227 static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
228 {
229  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1);
230 }
231 
232 static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
233 {
234  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9);
235 }
236 
237 static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
238 {
239  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10);
240 }
241 
242 static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
243 {
244  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10);
245 }
246 
247 static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
248 {
249  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12);
250 }
251 
252 static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
253 {
254  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12);
255 }
256 
257 static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
258 {
259  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14);
260 }
261 
262 static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
263 {
264  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16);
265 }
266 
267 static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
268 {
269  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16);
270 }
271 
272 static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
273  int have_alpha, int step)
274 {
276  ThreadData *td = arg;
277  AVFrame *in = td->in;
278  AVFrame *out = td->out;
279  const int slice_start = (out->height * jobnr) / nb_jobs;
280  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
281  const uint8_t roffset = s->rgba_map[R];
282  const uint8_t goffset = s->rgba_map[G];
283  const uint8_t boffset = s->rgba_map[B];
284  const uint8_t aoffset = s->rgba_map[A];
285  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
286  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
287  int i, j;
288 
289  for (i = slice_start; i < slice_end; i++) {
290  const uint8_t *src = srcrow;
291  uint8_t *dst = dstrow;
292 
293  for (j = 0; j < out->width * step; j += step) {
294  const uint8_t rin = src[j + roffset];
295  const uint8_t gin = src[j + goffset];
296  const uint8_t bin = src[j + boffset];
297  const uint8_t ain = src[j + aoffset];
298 
299  dst[j + roffset] = av_clip_uint8(s->lut[R][R][rin] +
300  s->lut[R][G][gin] +
301  s->lut[R][B][bin] +
302  (have_alpha == 1 ? s->lut[R][A][ain] : 0));
303  dst[j + goffset] = av_clip_uint8(s->lut[G][R][rin] +
304  s->lut[G][G][gin] +
305  s->lut[G][B][bin] +
306  (have_alpha == 1 ? s->lut[G][A][ain] : 0));
307  dst[j + boffset] = av_clip_uint8(s->lut[B][R][rin] +
308  s->lut[B][G][gin] +
309  s->lut[B][B][bin] +
310  (have_alpha == 1 ? s->lut[B][A][ain] : 0));
311  if (have_alpha == 1) {
312  dst[j + aoffset] = av_clip_uint8(s->lut[A][R][rin] +
313  s->lut[A][G][gin] +
314  s->lut[A][B][bin] +
315  s->lut[A][A][ain]);
316  } else if (have_alpha == -1 && in != out)
317  dst[j + aoffset] = 0;
318  }
319 
320  srcrow += in->linesize[0];
321  dstrow += out->linesize[0];
322  }
323 
324  return 0;
325 }
326 
327 static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
328  int have_alpha, int step)
329 {
331  ThreadData *td = arg;
332  AVFrame *in = td->in;
333  AVFrame *out = td->out;
334  const int slice_start = (out->height * jobnr) / nb_jobs;
335  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
336  const uint8_t roffset = s->rgba_map[R];
337  const uint8_t goffset = s->rgba_map[G];
338  const uint8_t boffset = s->rgba_map[B];
339  const uint8_t aoffset = s->rgba_map[A];
340  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
341  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
342  int i, j;
343 
344  for (i = slice_start; i < slice_end; i++) {
345  const uint16_t *src = (const uint16_t *)srcrow;
346  uint16_t *dst = (uint16_t *)dstrow;
347 
348  for (j = 0; j < out->width * step; j += step) {
349  const uint16_t rin = src[j + roffset];
350  const uint16_t gin = src[j + goffset];
351  const uint16_t bin = src[j + boffset];
352  const uint16_t ain = src[j + aoffset];
353 
354  dst[j + roffset] = av_clip_uint16(s->lut[R][R][rin] +
355  s->lut[R][G][gin] +
356  s->lut[R][B][bin] +
357  (have_alpha == 1 ? s->lut[R][A][ain] : 0));
358  dst[j + goffset] = av_clip_uint16(s->lut[G][R][rin] +
359  s->lut[G][G][gin] +
360  s->lut[G][B][bin] +
361  (have_alpha == 1 ? s->lut[G][A][ain] : 0));
362  dst[j + boffset] = av_clip_uint16(s->lut[B][R][rin] +
363  s->lut[B][G][gin] +
364  s->lut[B][B][bin] +
365  (have_alpha == 1 ? s->lut[B][A][ain] : 0));
366  if (have_alpha == 1) {
367  dst[j + aoffset] = av_clip_uint16(s->lut[A][R][rin] +
368  s->lut[A][G][gin] +
369  s->lut[A][B][bin] +
370  s->lut[A][A][ain]);
371  }
372  }
373 
374  srcrow += in->linesize[0];
375  dstrow += out->linesize[0];
376  }
377 
378  return 0;
379 }
380 
381 static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
382 {
383  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4);
384 }
385 
386 static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
387 {
388  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3);
389 }
390 
391 static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
392 {
393  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4);
394 }
395 
396 static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
397 {
398  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3);
399 }
400 
401 static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
402 {
403  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4);
404 }
405 
406 static int config_output(AVFilterLink *outlink)
407 {
408  AVFilterContext *ctx = outlink->src;
411  const int depth = desc->comp[0].depth;
412  int i, j, size, *buffer = s->buffer;
413 
414  ff_fill_rgba_map(s->rgba_map, outlink->format);
415 
416  size = 1 << depth;
417  if (!s->buffer) {
418  s->buffer = buffer = av_malloc(16 * size * sizeof(*s->buffer));
419  if (!s->buffer)
420  return AVERROR(ENOMEM);
421 
422  for (i = 0; i < 4; i++)
423  for (j = 0; j < 4; j++, buffer += size)
424  s->lut[i][j] = buffer;
425  }
426 
427  for (i = 0; i < size; i++) {
428  s->lut[R][R][i] = lrint(i * s->rr);
429  s->lut[R][G][i] = lrint(i * s->rg);
430  s->lut[R][B][i] = lrint(i * s->rb);
431  s->lut[R][A][i] = lrint(i * s->ra);
432 
433  s->lut[G][R][i] = lrint(i * s->gr);
434  s->lut[G][G][i] = lrint(i * s->gg);
435  s->lut[G][B][i] = lrint(i * s->gb);
436  s->lut[G][A][i] = lrint(i * s->ga);
437 
438  s->lut[B][R][i] = lrint(i * s->br);
439  s->lut[B][G][i] = lrint(i * s->bg);
440  s->lut[B][B][i] = lrint(i * s->bb);
441  s->lut[B][A][i] = lrint(i * s->ba);
442 
443  s->lut[A][R][i] = lrint(i * s->ar);
444  s->lut[A][G][i] = lrint(i * s->ag);
445  s->lut[A][B][i] = lrint(i * s->ab);
446  s->lut[A][A][i] = lrint(i * s->aa);
447  }
448 
449  switch (outlink->format) {
450  case AV_PIX_FMT_BGR24:
451  case AV_PIX_FMT_RGB24:
453  break;
454  case AV_PIX_FMT_0BGR:
455  case AV_PIX_FMT_0RGB:
456  case AV_PIX_FMT_BGR0:
457  case AV_PIX_FMT_RGB0:
459  break;
460  case AV_PIX_FMT_ABGR:
461  case AV_PIX_FMT_ARGB:
462  case AV_PIX_FMT_BGRA:
463  case AV_PIX_FMT_RGBA:
465  break;
466  case AV_PIX_FMT_BGR48:
467  case AV_PIX_FMT_RGB48:
469  break;
470  case AV_PIX_FMT_BGRA64:
471  case AV_PIX_FMT_RGBA64:
473  break;
474  case AV_PIX_FMT_GBRP:
476  break;
477  case AV_PIX_FMT_GBRAP:
479  break;
480  case AV_PIX_FMT_GBRP9:
482  break;
483  case AV_PIX_FMT_GBRP10:
485  break;
486  case AV_PIX_FMT_GBRAP10:
488  break;
489  case AV_PIX_FMT_GBRP12:
491  break;
492  case AV_PIX_FMT_GBRAP12:
494  break;
495  case AV_PIX_FMT_GBRP14:
497  break;
498  case AV_PIX_FMT_GBRP16:
500  break;
501  case AV_PIX_FMT_GBRAP16:
503  break;
504  }
505 
506  return 0;
507 }
508 
510 {
511  AVFilterContext *ctx = inlink->dst;
513  AVFilterLink *outlink = ctx->outputs[0];
514  ThreadData td;
515  AVFrame *out;
516 
517  if (av_frame_is_writable(in)) {
518  out = in;
519  } else {
520  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
521  if (!out) {
522  av_frame_free(&in);
523  return AVERROR(ENOMEM);
524  }
525  av_frame_copy_props(out, in);
526  }
527 
528  td.in = in;
529  td.out = out;
530  ctx->internal->execute(ctx, s->filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
531 
532  if (in != out)
533  av_frame_free(&in);
534  return ff_filter_frame(outlink, out);
535 }
536 
537 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
538  char *res, int res_len, int flags)
539 {
540  int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
541 
542  if (ret < 0)
543  return ret;
544 
545  return config_output(ctx->outputs[0]);
546 }
547 
549 {
551 
552  av_freep(&s->buffer);
553 }
554 
556  {
557  .name = "default",
558  .type = AVMEDIA_TYPE_VIDEO,
559  .filter_frame = filter_frame,
560  },
561  { NULL }
562 };
563 
565  {
566  .name = "default",
567  .type = AVMEDIA_TYPE_VIDEO,
568  .config_props = config_output,
569  },
570  { NULL }
571 };
572 
574  .name = "colorchannelmixer",
575  .description = NULL_IF_CONFIG_SMALL("Adjust colors by mixing color channels."),
576  .priv_size = sizeof(ColorChannelMixerContext),
577  .priv_class = &colorchannelmixer_class,
578  .uninit = uninit,
580  .inputs = colorchannelmixer_inputs,
581  .outputs = colorchannelmixer_outputs,
584 };
#define NULL
Definition: coverity.c:32
AVFILTER_DEFINE_CLASS(colorchannelmixer)
AVFrame * out
Definition: af_adeclick.c:488
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
static int query_formats(AVFilterContext *ctx)
AVOption.
Definition: opt.h:246
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:407
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:377
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:403
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:382
static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
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
static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step)
#define OFFSET(x)
static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
#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:125
static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const char * name
Pad name.
Definition: internal.h:60
static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1093
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
#define A
AVOptions.
static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVFilterPad colorchannelmixer_inputs[]
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:402
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
AVFrame * dst
Definition: vf_blend.c:55
static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:378
ptrdiff_t size
Definition: opengl_enc.c:100
static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define G
A filter pad used for either input or output.
Definition: internal.h:54
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int depth)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int width
Definition: frame.h:353
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:569
#define td
Definition: regdef.h:70
int step
Definition: vf_remap.c:77
static const AVOption colorchannelmixer_options[]
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
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:887
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:116
static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const char * arg
Definition: jacosubdec.c:66
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:408
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:373
static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:409
static av_cold void uninit(AVFilterContext *ctx)
const uint8_t * src
Definition: vf_bm3d.c:56
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
#define B
static const AVFilterPad colorchannelmixer_outputs[]
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:406
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define FFMIN(a, b)
Definition: common.h:96
AVFormatContext * ctx
Definition: movenc.c:48
static int config_output(AVFilterLink *outlink)
#define ra
Definition: regdef.h:57
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:405
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
misc drawing utilities
#define FLAGS
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:594
Used for passing data between threads.
Definition: dsddec.c:64
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
const char * name
Filter name.
Definition: avfilter.h:148
int(* filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:404
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:378
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
#define R
static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFilter ff_vf_colorchannelmixer
int
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
avfilter_execute_func * execute
Definition: internal.h:155
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2036
const AVPixFmtDescriptor * desc
Definition: vf_tonemap.c:196
A list of supported formats for one end of a filter link.
Definition: formats.h:64
#define lrint
Definition: tablegen.h:53
An instance of a filter.
Definition: avfilter.h:338
static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha)
int height
Definition: frame.h:353
#define av_freep(p)
#define av_always_inline
Definition: attributes.h:39
AVFrame * in
Definition: af_afftdn.c:1083
AVFilterLink * inlink
Definition: vf_blend.c:56
static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step)
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
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
GLuint buffer
Definition: opengl_enc.c:101