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 <float.h>
22 
23 #include "libavutil/opt.h"
24 #include "libavutil/pixdesc.h"
25 #include "avfilter.h"
26 #include "drawutils.h"
27 #include "formats.h"
28 #include "internal.h"
29 #include "video.h"
30 
31 #define R 0
32 #define G 1
33 #define B 2
34 #define A 3
35 
36 typedef struct ThreadData {
37  AVFrame *in, *out;
38 } ThreadData;
39 
40 typedef struct ColorChannelMixerContext {
41  const AVClass *class;
42  double rr, rg, rb, ra;
43  double gr, gg, gb, ga;
44  double br, bg, bb, ba;
45  double ar, ag, ab, aa;
46  double sr, sg, sb;
48 
49  int *lut[4][4];
50 
51  int *buffer;
52 
54 
55  int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
57 
58 #define OFFSET(x) offsetof(ColorChannelMixerContext, x)
59 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
60 
62  { "rr", "set the red gain for the red channel", OFFSET(rr), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
63  { "rg", "set the green gain for the red channel", OFFSET(rg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
64  { "rb", "set the blue gain for the red channel", OFFSET(rb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
65  { "ra", "set the alpha gain for the red channel", OFFSET(ra), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
66  { "gr", "set the red gain for the green channel", OFFSET(gr), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
67  { "gg", "set the green gain for the green channel", OFFSET(gg), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
68  { "gb", "set the blue gain for the green channel", OFFSET(gb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
69  { "ga", "set the alpha gain for the green channel", OFFSET(ga), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
70  { "br", "set the red gain for the blue channel", OFFSET(br), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
71  { "bg", "set the green gain for the blue channel", OFFSET(bg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
72  { "bb", "set the blue gain for the blue channel", OFFSET(bb), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
73  { "ba", "set the alpha gain for the blue channel", OFFSET(ba), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
74  { "ar", "set the red gain for the alpha channel", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
75  { "ag", "set the green gain for the alpha channel", OFFSET(ag), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
76  { "ab", "set the blue gain for the alpha channel", OFFSET(ab), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
77  { "aa", "set the alpha gain for the alpha channel", OFFSET(aa), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
78  { "pl", "preserve lightness", OFFSET(preserve_lightness), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
79  { NULL }
80 };
81 
82 AVFILTER_DEFINE_CLASS(colorchannelmixer);
83 
85 {
86  static const enum AVPixelFormat pix_fmts[] = {
101  };
102 
104  if (!fmts_list)
105  return AVERROR(ENOMEM);
106  return ff_set_common_formats(ctx, fmts_list);
107 }
108 
109 static float lerpf(float v0, float v1, float f)
110 {
111  return v0 + (v1 - v0) * f;
112 }
113 
114 static void preservel(float *r, float *g, float *b, float lin, float lout)
115 {
116  *r *= lout / lin;
117  *g *= lout / lin;
118  *b *= lout / lin;
119 }
120 
121 static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
122  int have_alpha, int pl)
123 {
124  ColorChannelMixerContext *s = ctx->priv;
125  ThreadData *td = arg;
126  AVFrame *in = td->in;
127  AVFrame *out = td->out;
128  const float l = s->preserve_lightness;
129  const float sr = s->sr;
130  const float sg = s->sg;
131  const float sb = s->sb;
132  const int slice_start = (out->height * jobnr) / nb_jobs;
133  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
134  const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0];
135  const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1];
136  const uint8_t *srcr = in->data[2] + slice_start * in->linesize[2];
137  const uint8_t *srca = in->data[3] + slice_start * in->linesize[3];
138  uint8_t *dstg = out->data[0] + slice_start * out->linesize[0];
139  uint8_t *dstb = out->data[1] + slice_start * out->linesize[1];
140  uint8_t *dstr = out->data[2] + slice_start * out->linesize[2];
141  uint8_t *dsta = out->data[3] + slice_start * out->linesize[3];
142  int i, j;
143 
144  for (i = slice_start; i < slice_end; i++) {
145  for (j = 0; j < out->width; j++) {
146  const uint8_t rin = srcr[j];
147  const uint8_t gin = srcg[j];
148  const uint8_t bin = srcb[j];
149  const uint8_t ain = have_alpha ? srca[j] : 0;
150  int rout, gout, bout;
151  float lin;
152 
153  if (pl)
154  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
155 
156  rout = s->lut[R][R][rin] +
157  s->lut[R][G][gin] +
158  s->lut[R][B][bin] +
159  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
160  gout = s->lut[G][R][rin] +
161  s->lut[G][G][gin] +
162  s->lut[G][B][bin] +
163  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
164  bout = s->lut[B][R][rin] +
165  s->lut[B][G][gin] +
166  s->lut[B][B][bin] +
167  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
168 
169  if (pl) {
170  float frout = rout / sr;
171  float fgout = gout / sg;
172  float fbout = bout / sb;
173  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
174 
175  preservel(&frout, &fgout, &fbout, lin, lout);
176 
177  rout = lrintf(lerpf(rout, frout, l));
178  gout = lrintf(lerpf(gout, fgout, l));
179  bout = lrintf(lerpf(bout, fbout, l));
180  }
181 
182  dstr[j] = av_clip_uint8(rout);
183  dstg[j] = av_clip_uint8(gout);
184  dstb[j] = av_clip_uint8(bout);
185 
186  if (have_alpha == 1) {
187  dsta[j] = av_clip_uint8(s->lut[A][R][rin] +
188  s->lut[A][G][gin] +
189  s->lut[A][B][bin] +
190  s->lut[A][A][ain]);
191  }
192  }
193 
194  srcg += in->linesize[0];
195  srcb += in->linesize[1];
196  srcr += in->linesize[2];
197  srca += in->linesize[3];
198  dstg += out->linesize[0];
199  dstb += out->linesize[1];
200  dstr += out->linesize[2];
201  dsta += out->linesize[3];
202  }
203 
204  return 0;
205 }
206 
207 static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
208  int have_alpha, int depth, int pl)
209 {
210  ColorChannelMixerContext *s = ctx->priv;
211  ThreadData *td = arg;
212  AVFrame *in = td->in;
213  AVFrame *out = td->out;
214  const float l = s->preserve_lightness;
215  const float sr = s->sr;
216  const float sg = s->sg;
217  const float sb = s->sb;
218  const int slice_start = (out->height * jobnr) / nb_jobs;
219  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
220  const uint16_t *srcg = (const uint16_t *)(in->data[0] + slice_start * in->linesize[0]);
221  const uint16_t *srcb = (const uint16_t *)(in->data[1] + slice_start * in->linesize[1]);
222  const uint16_t *srcr = (const uint16_t *)(in->data[2] + slice_start * in->linesize[2]);
223  const uint16_t *srca = (const uint16_t *)(in->data[3] + slice_start * in->linesize[3]);
224  uint16_t *dstg = (uint16_t *)(out->data[0] + slice_start * out->linesize[0]);
225  uint16_t *dstb = (uint16_t *)(out->data[1] + slice_start * out->linesize[1]);
226  uint16_t *dstr = (uint16_t *)(out->data[2] + slice_start * out->linesize[2]);
227  uint16_t *dsta = (uint16_t *)(out->data[3] + slice_start * out->linesize[3]);
228  int i, j;
229 
230  for (i = slice_start; i < slice_end; i++) {
231  for (j = 0; j < out->width; j++) {
232  const uint16_t rin = srcr[j];
233  const uint16_t gin = srcg[j];
234  const uint16_t bin = srcb[j];
235  const uint16_t ain = have_alpha ? srca[j] : 0;
236  int rout, gout, bout;
237  float lin;
238 
239  if (pl)
240  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
241 
242  rout = s->lut[R][R][rin] +
243  s->lut[R][G][gin] +
244  s->lut[R][B][bin] +
245  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
246  gout = s->lut[G][R][rin] +
247  s->lut[G][G][gin] +
248  s->lut[G][B][bin] +
249  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
250  bout = s->lut[B][R][rin] +
251  s->lut[B][G][gin] +
252  s->lut[B][B][bin] +
253  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
254 
255  if (pl) {
256  float frout = rout / sr;
257  float fgout = gout / sg;
258  float fbout = bout / sb;
259  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
260 
261  preservel(&frout, &fgout, &fbout, lin, lout);
262 
263  rout = lrintf(lerpf(rout, frout, l));
264  gout = lrintf(lerpf(gout, fgout, l));
265  bout = lrintf(lerpf(bout, fbout, l));
266  }
267 
268  dstr[j] = av_clip_uintp2(rout, depth);
269  dstg[j] = av_clip_uintp2(gout, depth);
270  dstb[j] = av_clip_uintp2(bout, depth);
271 
272  if (have_alpha == 1) {
273  dsta[j] = av_clip_uintp2(s->lut[A][R][rin] +
274  s->lut[A][G][gin] +
275  s->lut[A][B][bin] +
276  s->lut[A][A][ain], depth);
277  }
278  }
279 
280  srcg += in->linesize[0] / 2;
281  srcb += in->linesize[1] / 2;
282  srcr += in->linesize[2] / 2;
283  srca += in->linesize[3] / 2;
284  dstg += out->linesize[0] / 2;
285  dstb += out->linesize[1] / 2;
286  dstr += out->linesize[2] / 2;
287  dsta += out->linesize[3] / 2;
288  }
289 
290  return 0;
291 }
292 
293 static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
294 {
295  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 0);
296 }
297 
298 static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
299 {
300  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 0);
301 }
302 
303 static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
304 {
305  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 1);
306 }
307 
308 static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
309 {
310  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 1);
311 }
312 
313 static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
314 {
315  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 0);
316 }
317 
318 static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
319 {
320  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 0);
321 }
322 
323 static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
324 {
325  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 0);
326 }
327 
328 static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
329 {
330  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 0);
331 }
332 
333 static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
334 {
335  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 0);
336 }
337 
338 static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
339 {
340  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 0);
341 }
342 
343 static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
344 {
345  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 0);
346 }
347 
348 static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
349 {
350  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 0);
351 }
352 
353 static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
354 {
355  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 1);
356 }
357 
358 static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
359 {
360  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 1);
361 }
362 
363 static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
364 {
365  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 1);
366 }
367 
368 static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
369 {
370  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 1);
371 }
372 
373 static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
374 {
375  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 1);
376 }
377 
378 static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
379 {
380  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 1);
381 }
382 
383 static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
384 {
385  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 1);
386 }
387 
388 static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
389 {
390  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 1);
391 }
392 
393 static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
394  int have_alpha, int step, int pl)
395 {
396  ColorChannelMixerContext *s = ctx->priv;
397  ThreadData *td = arg;
398  AVFrame *in = td->in;
399  AVFrame *out = td->out;
400  const float l = s->preserve_lightness;
401  const float sr = s->sr;
402  const float sg = s->sg;
403  const float sb = s->sb;
404  const int slice_start = (out->height * jobnr) / nb_jobs;
405  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
406  const uint8_t roffset = s->rgba_map[R];
407  const uint8_t goffset = s->rgba_map[G];
408  const uint8_t boffset = s->rgba_map[B];
409  const uint8_t aoffset = s->rgba_map[A];
410  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
411  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
412  int i, j;
413 
414  for (i = slice_start; i < slice_end; i++) {
415  const uint8_t *src = srcrow;
416  uint8_t *dst = dstrow;
417 
418  for (j = 0; j < out->width * step; j += step) {
419  const uint8_t rin = src[j + roffset];
420  const uint8_t gin = src[j + goffset];
421  const uint8_t bin = src[j + boffset];
422  const uint8_t ain = src[j + aoffset];
423  int rout, gout, bout;
424  float lin;
425 
426  if (pl)
427  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
428 
429  rout = s->lut[R][R][rin] +
430  s->lut[R][G][gin] +
431  s->lut[R][B][bin] +
432  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
433  gout = s->lut[G][R][rin] +
434  s->lut[G][G][gin] +
435  s->lut[G][B][bin] +
436  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
437  bout = s->lut[B][R][rin] +
438  s->lut[B][G][gin] +
439  s->lut[B][B][bin] +
440  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
441 
442  if (pl) {
443  float frout = rout / sr;
444  float fgout = gout / sg;
445  float fbout = bout / sb;
446  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
447 
448  preservel(&frout, &fgout, &fbout, lin, lout);
449 
450  rout = lrintf(lerpf(rout, frout, l));
451  gout = lrintf(lerpf(gout, fgout, l));
452  bout = lrintf(lerpf(bout, fbout, l));
453  }
454 
455  dst[j + roffset] = av_clip_uint8(rout);
456  dst[j + goffset] = av_clip_uint8(gout);
457  dst[j + boffset] = av_clip_uint8(bout);
458 
459  if (have_alpha == 1) {
460  dst[j + aoffset] = av_clip_uint8(s->lut[A][R][rin] +
461  s->lut[A][G][gin] +
462  s->lut[A][B][bin] +
463  s->lut[A][A][ain]);
464  } else if (have_alpha == -1 && in != out)
465  dst[j + aoffset] = 0;
466  }
467 
468  srcrow += in->linesize[0];
469  dstrow += out->linesize[0];
470  }
471 
472  return 0;
473 }
474 
475 static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
476  int have_alpha, int step, int pl)
477 {
478  ColorChannelMixerContext *s = ctx->priv;
479  ThreadData *td = arg;
480  AVFrame *in = td->in;
481  AVFrame *out = td->out;
482  const float l = s->preserve_lightness;
483  const float sr = s->sr;
484  const float sg = s->sg;
485  const float sb = s->sb;
486  const int slice_start = (out->height * jobnr) / nb_jobs;
487  const int slice_end = (out->height * (jobnr+1)) / nb_jobs;
488  const uint8_t roffset = s->rgba_map[R];
489  const uint8_t goffset = s->rgba_map[G];
490  const uint8_t boffset = s->rgba_map[B];
491  const uint8_t aoffset = s->rgba_map[A];
492  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
493  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
494  int i, j;
495 
496  for (i = slice_start; i < slice_end; i++) {
497  const uint16_t *src = (const uint16_t *)srcrow;
498  uint16_t *dst = (uint16_t *)dstrow;
499 
500  for (j = 0; j < out->width * step; j += step) {
501  const uint16_t rin = src[j + roffset];
502  const uint16_t gin = src[j + goffset];
503  const uint16_t bin = src[j + boffset];
504  const uint16_t ain = src[j + aoffset];
505  int rout, gout, bout;
506  float lin;
507 
508  if (pl)
509  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
510 
511  rout = s->lut[R][R][rin] +
512  s->lut[R][G][gin] +
513  s->lut[R][B][bin] +
514  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
515  gout = s->lut[G][R][rin] +
516  s->lut[G][G][gin] +
517  s->lut[G][B][bin] +
518  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
519  bout = s->lut[B][R][rin] +
520  s->lut[B][G][gin] +
521  s->lut[B][B][bin] +
522  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
523 
524  if (pl) {
525  float frout = rout / sr;
526  float fgout = gout / sg;
527  float fbout = bout / sb;
528  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
529 
530  preservel(&frout, &fgout, &fbout, lin, lout);
531 
532  rout = lrintf(lerpf(rout, frout, l));
533  gout = lrintf(lerpf(gout, fgout, l));
534  bout = lrintf(lerpf(bout, fbout, l));
535  }
536 
537  dst[j + roffset] = av_clip_uint16(rout);
538  dst[j + goffset] = av_clip_uint16(gout);
539  dst[j + boffset] = av_clip_uint16(bout);
540 
541  if (have_alpha == 1) {
542  dst[j + aoffset] = av_clip_uint16(s->lut[A][R][rin] +
543  s->lut[A][G][gin] +
544  s->lut[A][B][bin] +
545  s->lut[A][A][ain]);
546  }
547  }
548 
549  srcrow += in->linesize[0];
550  dstrow += out->linesize[0];
551  }
552 
553  return 0;
554 }
555 
556 static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
557 {
558  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0);
559 }
560 
561 static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
562 {
563  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0);
564 }
565 
566 static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
567 {
568  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1);
569 }
570 
571 static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
572 {
573  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1);
574 }
575 
576 static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
577 {
578  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0);
579 }
580 
581 static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
582 {
583  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0);
584 }
585 
586 static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
587 {
588  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 0);
589 }
590 
591 static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
592 {
593  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1);
594 }
595 
596 static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
597 {
598  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1);
599 }
600 
601 static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
602 {
603  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 1);
604 }
605 
606 static int config_output(AVFilterLink *outlink)
607 {
608  AVFilterContext *ctx = outlink->src;
609  ColorChannelMixerContext *s = ctx->priv;
611  const int depth = desc->comp[0].depth;
612  int i, j, size, *buffer = s->buffer;
613 
614  ff_fill_rgba_map(s->rgba_map, outlink->format);
615 
616  size = 1 << depth;
617  if (!s->buffer) {
618  s->buffer = buffer = av_malloc(16 * size * sizeof(*s->buffer));
619  if (!s->buffer)
620  return AVERROR(ENOMEM);
621 
622  for (i = 0; i < 4; i++)
623  for (j = 0; j < 4; j++, buffer += size)
624  s->lut[i][j] = buffer;
625  }
626 
627  s->sr = s->rr + s->rg + s->rb + s->ra;
628  s->sg = s->gr + s->gg + s->gb + s->ga;
629  s->sb = s->br + s->bg + s->bb + s->ba;
630 
631  if (fabs(s->sr) <= DBL_EPSILON)
632  s->sr = 1.;
633 
634  if (fabs(s->sg) <= DBL_EPSILON)
635  s->sg = 1.;
636 
637  if (fabs(s->sb) <= DBL_EPSILON)
638  s->sb = 1.;
639 
640  for (i = 0; i < size; i++) {
641  s->lut[R][R][i] = lrint(i * s->rr);
642  s->lut[R][G][i] = lrint(i * s->rg);
643  s->lut[R][B][i] = lrint(i * s->rb);
644  s->lut[R][A][i] = lrint(i * s->ra);
645 
646  s->lut[G][R][i] = lrint(i * s->gr);
647  s->lut[G][G][i] = lrint(i * s->gg);
648  s->lut[G][B][i] = lrint(i * s->gb);
649  s->lut[G][A][i] = lrint(i * s->ga);
650 
651  s->lut[B][R][i] = lrint(i * s->br);
652  s->lut[B][G][i] = lrint(i * s->bg);
653  s->lut[B][B][i] = lrint(i * s->bb);
654  s->lut[B][A][i] = lrint(i * s->ba);
655 
656  s->lut[A][R][i] = lrint(i * s->ar);
657  s->lut[A][G][i] = lrint(i * s->ag);
658  s->lut[A][B][i] = lrint(i * s->ab);
659  s->lut[A][A][i] = lrint(i * s->aa);
660  }
661 
662  switch (outlink->format) {
663  case AV_PIX_FMT_BGR24:
664  case AV_PIX_FMT_RGB24:
665  s->filter_slice[0] = filter_slice_rgb24;
666  s->filter_slice[1] = filter_slice_rgb24_pl;
667  break;
668  case AV_PIX_FMT_0BGR:
669  case AV_PIX_FMT_0RGB:
670  case AV_PIX_FMT_BGR0:
671  case AV_PIX_FMT_RGB0:
672  s->filter_slice[0] = filter_slice_rgb0;
673  s->filter_slice[1] = filter_slice_rgb0_pl;
674  break;
675  case AV_PIX_FMT_ABGR:
676  case AV_PIX_FMT_ARGB:
677  case AV_PIX_FMT_BGRA:
678  case AV_PIX_FMT_RGBA:
679  s->filter_slice[0] = filter_slice_rgba;
680  s->filter_slice[1] = filter_slice_rgba_pl;
681  break;
682  case AV_PIX_FMT_BGR48:
683  case AV_PIX_FMT_RGB48:
684  s->filter_slice[0] = filter_slice_rgb48;
685  s->filter_slice[1] = filter_slice_rgb48_pl;
686  break;
687  case AV_PIX_FMT_BGRA64:
688  case AV_PIX_FMT_RGBA64:
689  s->filter_slice[0] = filter_slice_rgba64;
690  s->filter_slice[1] = filter_slice_rgba64_pl;
691  break;
692  case AV_PIX_FMT_GBRP:
693  s->filter_slice[0] = filter_slice_gbrp;
694  s->filter_slice[1] = filter_slice_gbrp_pl;
695  break;
696  case AV_PIX_FMT_GBRAP:
697  s->filter_slice[0] = filter_slice_gbrap;
698  s->filter_slice[1] = filter_slice_gbrap_pl;
699  break;
700  case AV_PIX_FMT_GBRP9:
701  s->filter_slice[0] = filter_slice_gbrp9;
702  s->filter_slice[1] = filter_slice_gbrp9_pl;
703  break;
704  case AV_PIX_FMT_GBRP10:
705  s->filter_slice[0] = filter_slice_gbrp10;
706  s->filter_slice[1] = filter_slice_gbrp10_pl;
707  break;
708  case AV_PIX_FMT_GBRAP10:
709  s->filter_slice[0] = filter_slice_gbrap10;
710  s->filter_slice[1] = filter_slice_gbrap10_pl;
711  break;
712  case AV_PIX_FMT_GBRP12:
713  s->filter_slice[0] = filter_slice_gbrp12;
714  s->filter_slice[1] = filter_slice_gbrp12_pl;
715  break;
716  case AV_PIX_FMT_GBRAP12:
717  s->filter_slice[0] = filter_slice_gbrap12;
718  s->filter_slice[1] = filter_slice_gbrap12_pl;
719  break;
720  case AV_PIX_FMT_GBRP14:
721  s->filter_slice[0] = filter_slice_gbrp14;
722  s->filter_slice[1] = filter_slice_gbrp14_pl;
723  break;
724  case AV_PIX_FMT_GBRP16:
725  s->filter_slice[0] = filter_slice_gbrp16;
726  s->filter_slice[1] = filter_slice_gbrp16_pl;
727  break;
728  case AV_PIX_FMT_GBRAP16:
729  s->filter_slice[0] = filter_slice_gbrap16;
730  s->filter_slice[1] = filter_slice_gbrap16_pl;
731  break;
732  }
733 
734  return 0;
735 }
736 
738 {
739  AVFilterContext *ctx = inlink->dst;
740  ColorChannelMixerContext *s = ctx->priv;
741  AVFilterLink *outlink = ctx->outputs[0];
742  const int pl = s->preserve_lightness > 0.;
743  ThreadData td;
744  AVFrame *out;
745 
746  if (av_frame_is_writable(in)) {
747  out = in;
748  } else {
749  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
750  if (!out) {
751  av_frame_free(&in);
752  return AVERROR(ENOMEM);
753  }
755  }
756 
757  td.in = in;
758  td.out = out;
759  ctx->internal->execute(ctx, s->filter_slice[pl], &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
760 
761  if (in != out)
762  av_frame_free(&in);
763  return ff_filter_frame(outlink, out);
764 }
765 
766 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
767  char *res, int res_len, int flags)
768 {
769  int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
770 
771  if (ret < 0)
772  return ret;
773 
774  return config_output(ctx->outputs[0]);
775 }
776 
778 {
779  ColorChannelMixerContext *s = ctx->priv;
780 
781  av_freep(&s->buffer);
782 }
783 
785  {
786  .name = "default",
787  .type = AVMEDIA_TYPE_VIDEO,
788  .filter_frame = filter_frame,
789  },
790  { NULL }
791 };
792 
794  {
795  .name = "default",
796  .type = AVMEDIA_TYPE_VIDEO,
797  .config_props = config_output,
798  },
799  { NULL }
800 };
801 
803  .name = "colorchannelmixer",
804  .description = NULL_IF_CONFIG_SMALL("Adjust colors by mixing color channels."),
805  .priv_size = sizeof(ColorChannelMixerContext),
806  .priv_class = &colorchannelmixer_class,
807  .uninit = uninit,
813 };
ColorChannelMixerContext::gg
double gg
Definition: vf_colorchannelmixer.c:43
filter_slice_rgba64
static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:556
ff_get_video_buffer
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
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:421
filter_slice_rgba16_planar
static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int depth, int pl)
Definition: vf_colorchannelmixer.c:207
td
#define td
Definition: regdef.h:70
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
r
const char * r
Definition: vf_curves.c:116
AVERROR
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
ColorChannelMixerContext::rg
double rg
Definition: vf_colorchannelmixer.c:42
opt.h
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
ColorChannelMixerContext::bb
double bb
Definition: vf_colorchannelmixer.c:44
out
FILE * out
Definition: movenc.c:54
ff_vf_colorchannelmixer
AVFilter ff_vf_colorchannelmixer
Definition: vf_colorchannelmixer.c:802
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1094
filter_slice_rgba_planar
static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int pl)
Definition: vf_colorchannelmixer.c:121
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:146
filter_slice_gbrp10_pl
static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:358
inlink
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
Definition: filter_design.txt:212
ColorChannelMixerContext::sb
double sb
Definition: vf_colorchannelmixer.c:46
colorchannelmixer_options
static const AVOption colorchannelmixer_options[]
Definition: vf_colorchannelmixer.c:61
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:204
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:324
pixdesc.h
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
AVOption
AVOption.
Definition: opt.h:248
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_colorchannelmixer.c:84
b
#define b
Definition: input.c:41
filter_slice_gbrp14
static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:338
R
#define R
Definition: vf_colorchannelmixer.c:31
A
#define A
Definition: vf_colorchannelmixer.c:34
filter_slice_gbrp_pl
static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:303
float.h
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:149
filter_slice_rgb0
static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:586
G
#define G
Definition: vf_colorchannelmixer.c:32
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:502
ColorChannelMixerContext::ar
double ar
Definition: vf_colorchannelmixer.c:45
ColorChannelMixerContext::buffer
int * buffer
Definition: vf_colorchannelmixer.c:51
video.h
AVFormatContext::internal
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1698
filter_slice_gbrap
static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:298
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
ra
#define ra
Definition: regdef.h:57
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:65
formats.h
filter_slice_rgb0_pl
static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:601
ColorChannelMixerContext::gr
double gr
Definition: vf_colorchannelmixer.c:43
ColorChannelMixerContext::filter_slice
int(* filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:55
B
#define B
Definition: vf_colorchannelmixer.c:33
filter_slice_gbrap_pl
static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:308
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:417
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
v0
#define v0
Definition: regdef.h:26
filter_slice_rgba
static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:576
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
filter_slice_gbrap10_pl
static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:363
filter_slice_gbrap16
static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:348
FFMIN3
#define FFMIN3(a, b, c)
Definition: common.h:106
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
lerpf
static float lerpf(float v0, float v1, float f)
Definition: vf_colorchannelmixer.c:109
lrint
#define lrint
Definition: tablegen.h:53
av_cold
#define av_cold
Definition: attributes.h:90
inputs
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
Definition: filter_design.txt:243
ff_set_common_formats
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
ColorChannelMixerContext::rb
double rb
Definition: vf_colorchannelmixer.c:42
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
ColorChannelMixerContext::ba
double ba
Definition: vf_colorchannelmixer.c:44
FFMAX3
#define FFMAX3(a, b, c)
Definition: common.h:104
s
#define s(width, name)
Definition: cbs_vp9.c:257
filter_slice_gbrp14_pl
static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:378
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
FLAGS
#define FLAGS
Definition: vf_colorchannelmixer.c:59
g
const char * g
Definition: vf_curves.c:117
filter_slice_rgb48
static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:561
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:227
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2032
ColorChannelMixerContext::lut
int * lut[4][4]
Definition: vf_colorchannelmixer.c:49
ColorChannelMixerContext::ag
double ag
Definition: vf_colorchannelmixer.c:45
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:303
filter_slice_rgba_packed
static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step, int pl)
Definition: vf_colorchannelmixer.c:393
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ColorChannelMixerContext::bg
double bg
Definition: vf_colorchannelmixer.c:44
f
#define f(width, name)
Definition: cbs_vp9.c:255
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
ColorChannelMixerContext
Definition: vf_colorchannelmixer.c:40
arg
const char * arg
Definition: jacosubdec.c:66
preservel
static void preservel(float *r, float *g, float *b, float lin, float lout)
Definition: vf_colorchannelmixer.c:114
colorchannelmixer_outputs
static const AVFilterPad colorchannelmixer_outputs[]
Definition: vf_colorchannelmixer.c:793
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:418
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:389
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
AV_PIX_FMT_BGR48
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:390
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:659
filter_slice_gbrp
static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:293
filter_slice_gbrp9
static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:313
ColorChannelMixerContext::sr
double sr
Definition: vf_colorchannelmixer.c:46
filter_slice_gbrp10
static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:318
src
#define src
Definition: vp8dsp.c:255
ColorChannelMixerContext::preserve_lightness
double preserve_lightness
Definition: vf_colorchannelmixer.c:47
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
filter_slice_gbrap12_pl
static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:373
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(colorchannelmixer)
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
filter_slice_gbrap10
static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:323
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
filter_slice_gbrap16_pl
static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:388
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:385
size
int size
Definition: twinvq_data.h:10344
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:595
ff_filter_process_command
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
filter_slice_gbrp12_pl
static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:368
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#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
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
in
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
Definition: audio_convert.c:326
ColorChannelMixerContext::sg
double sg
Definition: vf_colorchannelmixer.c:46
AV_PIX_FMT_BGRA64
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:394
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_colorchannelmixer.c:737
i
int i
Definition: input.c:407
lrintf
#define lrintf(x)
Definition: libm_mips.h:72
filter_slice_rgba64_pl
static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:566
filter_slice_gbrp16_pl
static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:383
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
ThreadData
Used for passing data between threads.
Definition: dsddec.c:67
av_always_inline
#define av_always_inline
Definition: attributes.h:49
uint8_t
uint8_t
Definition: audio_convert.c:194
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
filter_slice_gbrp12
static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:328
AVFilter
Filter definition.
Definition: avfilter.h:145
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_colorchannelmixer.c:777
ret
ret
Definition: filter_design.txt:187
filter_slice_rgb24
static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:581
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
ColorChannelMixerContext::ab
double ab
Definition: vf_colorchannelmixer.c:45
ColorChannelMixerContext::rr
double rr
Definition: vf_colorchannelmixer.c:42
ColorChannelMixerContext::ga
double ga
Definition: vf_colorchannelmixer.c:43
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ColorChannelMixerContext::gb
double gb
Definition: vf_colorchannelmixer.c:43
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
avfilter.h
av_clip_uint8
#define av_clip_uint8
Definition: common.h:128
AVFilterContext
An instance of a filter.
Definition: avfilter.h:341
av_clip_uint16
#define av_clip_uint16
Definition: common.h:134
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_colorchannelmixer.c:606
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
filter_slice_gbrap12
static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:333
OFFSET
#define OFFSET(x)
Definition: vf_colorchannelmixer.c:58
ThreadData::in
AVFrame * in
Definition: af_adenorm.c:223
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
ColorChannelMixerContext::rgba_map
uint8_t rgba_map[4]
Definition: vf_colorchannelmixer.c:53
ColorChannelMixerContext::br
double br
Definition: vf_colorchannelmixer.c:44
filter_slice_rgb48_pl
static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:571
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
filter_slice_rgba_pl
static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:591
filter_slice_rgb24_pl
static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:596
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
ColorChannelMixerContext::ra
double ra
Definition: vf_colorchannelmixer.c:42
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
filter_slice_gbrp16
static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:343
filter_slice_rgba16_packed
static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step, int pl)
Definition: vf_colorchannelmixer.c:475
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_colorchannelmixer.c:766
drawutils.h
ColorChannelMixerContext::aa
double aa
Definition: vf_colorchannelmixer.c:45
colorchannelmixer_inputs
static const AVFilterPad colorchannelmixer_inputs[]
Definition: vf_colorchannelmixer.c:784
int
int
Definition: ffmpeg_filter.c:158
filter_slice_gbrp9_pl
static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorchannelmixer.c:353