FFmpeg
vf_paletteuse.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Stupeflix
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 /**
22  * @file
23  * Use a palette to downsample an input video stream.
24  */
25 
26 #include "libavutil/bprint.h"
27 #include "libavutil/file_open.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/qsort.h"
31 #include "avfilter.h"
32 #include "framesync.h"
33 #include "internal.h"
34 
43 };
44 
50 };
51 
52 enum diff_mode {
56 };
57 
58 struct color_node {
59  uint8_t val[4];
60  uint8_t palette_id;
61  int split;
63 };
64 
65 #define NBITS 5
66 #define CACHE_SIZE (1<<(4*NBITS))
67 
68 struct cached_color {
69  uint32_t color;
70  uint8_t pal_entry;
71 };
72 
73 struct cache_node {
76 };
77 
78 struct PaletteUseContext;
79 
81  int x_start, int y_start, int width, int height);
82 
83 typedef struct PaletteUseContext {
84  const AVClass *class;
86  struct cache_node cache[CACHE_SIZE]; /* lookup cache */
87  struct color_node map[AVPALETTE_COUNT]; /* 3D-Tree (KD-Tree with K=3) for reverse colormap */
89  int transparency_index; /* index in the palette of transparency. -1 if there is no transparency in the palette. */
91  int use_alpha;
93  int dither;
94  int new;
97  int ordered_dither[8*8];
98  int diff_mode;
101 
102  /* debug options */
106  uint64_t total_mean_err;
109 
110 #define OFFSET(x) offsetof(PaletteUseContext, x)
111 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
112 static const AVOption paletteuse_options[] = {
113  { "dither", "select dithering mode", OFFSET(dither), AV_OPT_TYPE_INT, {.i64=DITHERING_SIERRA2_4A}, 0, NB_DITHERING-1, FLAGS, "dithering_mode" },
114  { "bayer", "ordered 8x8 bayer dithering (deterministic)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_BAYER}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
115  { "heckbert", "dithering as defined by Paul Heckbert in 1982 (simple error diffusion)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_HECKBERT}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
116  { "floyd_steinberg", "Floyd and Steingberg dithering (error diffusion)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_FLOYD_STEINBERG}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
117  { "sierra2", "Frankie Sierra dithering v2 (error diffusion)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_SIERRA2}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
118  { "sierra2_4a", "Frankie Sierra dithering v2 \"Lite\" (error diffusion)", 0, AV_OPT_TYPE_CONST, {.i64=DITHERING_SIERRA2_4A}, INT_MIN, INT_MAX, FLAGS, "dithering_mode" },
119  { "bayer_scale", "set scale for bayer dithering", OFFSET(bayer_scale), AV_OPT_TYPE_INT, {.i64=2}, 0, 5, FLAGS },
120  { "diff_mode", "set frame difference mode", OFFSET(diff_mode), AV_OPT_TYPE_INT, {.i64=DIFF_MODE_NONE}, 0, NB_DIFF_MODE-1, FLAGS, "diff_mode" },
121  { "rectangle", "process smallest different rectangle", 0, AV_OPT_TYPE_CONST, {.i64=DIFF_MODE_RECTANGLE}, INT_MIN, INT_MAX, FLAGS, "diff_mode" },
122  { "new", "take new palette for each output frame", OFFSET(new), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
123  { "alpha_threshold", "set the alpha threshold for transparency", OFFSET(trans_thresh), AV_OPT_TYPE_INT, {.i64=128}, 0, 255, FLAGS },
124  { "use_alpha", "use alpha channel for mapping", OFFSET(use_alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
125 
126  /* following are the debug options, not part of the official API */
127  { "debug_kdtree", "save Graphviz graph of the kdtree in specified file", OFFSET(dot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
128  { "color_search", "set reverse colormap color search method", OFFSET(color_search_method), AV_OPT_TYPE_INT, {.i64=COLOR_SEARCH_NNS_ITERATIVE}, 0, NB_COLOR_SEARCHES-1, FLAGS, "search" },
129  { "nns_iterative", "iterative search", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_NNS_ITERATIVE}, INT_MIN, INT_MAX, FLAGS, "search" },
130  { "nns_recursive", "recursive search", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_NNS_RECURSIVE}, INT_MIN, INT_MAX, FLAGS, "search" },
131  { "bruteforce", "brute-force into the palette", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_BRUTEFORCE}, INT_MIN, INT_MAX, FLAGS, "search" },
132  { "mean_err", "compute and print mean error", OFFSET(calc_mean_err), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
133  { "debug_accuracy", "test color search accuracy", OFFSET(debug_accuracy), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
134  { NULL }
135 };
136 
137 AVFILTER_DEFINE_CLASS(paletteuse);
138 
139 static int load_apply_palette(FFFrameSync *fs);
140 
142 {
143  static const enum AVPixelFormat in_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE};
144  static const enum AVPixelFormat inpal_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE};
145  static const enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE};
146  int ret;
147  if ((ret = ff_formats_ref(ff_make_format_list(in_fmts),
148  &ctx->inputs[0]->outcfg.formats)) < 0 ||
149  (ret = ff_formats_ref(ff_make_format_list(inpal_fmts),
150  &ctx->inputs[1]->outcfg.formats)) < 0 ||
152  &ctx->outputs[0]->incfg.formats)) < 0)
153  return ret;
154  return 0;
155 }
156 
157 static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg,
158  int eb, int scale, int shift)
159 {
160  return px >> 24 << 24
161  | av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<<shift))) << 16
162  | av_clip_uint8((px >> 8 & 0xff) + ((eg * scale) / (1<<shift))) << 8
163  | av_clip_uint8((px & 0xff) + ((eb * scale) / (1<<shift)));
164 }
165 
166 static av_always_inline int diff(const uint8_t *c1, const uint8_t *c2, const PaletteUseContext *s)
167 {
168  // XXX: try L*a*b with CIE76 (dL*dL + da*da + db*db)
169  const int da = c1[0] - c2[0];
170  const int dr = c1[1] - c2[1];
171  const int dg = c1[2] - c2[2];
172  const int db = c1[3] - c2[3];
173 
174  if (s->use_alpha)
175  return da*da + dr*dr + dg*dg + db*db;
176 
177  if (c1[0] < s->trans_thresh && c2[0] < s->trans_thresh) {
178  return 0;
179  } else if (c1[0] >= s->trans_thresh && c2[0] >= s->trans_thresh) {
180  return dr*dr + dg*dg + db*db;
181  } else {
182  return 255*255 + 255*255 + 255*255;
183  }
184 }
185 
186 static av_always_inline uint8_t colormap_nearest_bruteforce(const PaletteUseContext *s, const uint8_t *argb)
187 {
188  int i, pal_id = -1, min_dist = INT_MAX;
189 
190  for (i = 0; i < AVPALETTE_COUNT; i++) {
191  const uint32_t c = s->palette[i];
192 
193  if (s->use_alpha || c >> 24 >= s->trans_thresh) { // ignore transparent entry
194  const uint8_t palargb[] = {
195  s->palette[i]>>24 & 0xff,
196  s->palette[i]>>16 & 0xff,
197  s->palette[i]>> 8 & 0xff,
198  s->palette[i] & 0xff,
199  };
200  const int d = diff(palargb, argb, s);
201  if (d < min_dist) {
202  pal_id = i;
203  min_dist = d;
204  }
205  }
206  }
207  return pal_id;
208 }
209 
210 /* Recursive form, simpler but a bit slower. Kept for reference. */
212  int node_pos;
213  int dist_sqd;
214 };
215 
217  const struct color_node *map,
218  const int node_pos,
219  const uint8_t *target,
220  struct nearest_color *nearest)
221 {
222  const struct color_node *kd = map + node_pos;
223  const int split = kd->split;
224  int dx, nearer_kd_id, further_kd_id;
225  const uint8_t *current = kd->val;
226  const int current_to_target = diff(target, current, s);
227 
228  if (current_to_target < nearest->dist_sqd) {
229  nearest->node_pos = node_pos;
230  nearest->dist_sqd = current_to_target;
231  }
232 
233  if (kd->left_id != -1 || kd->right_id != -1) {
234  dx = target[split] - current[split];
235 
236  if (dx <= 0) nearer_kd_id = kd->left_id, further_kd_id = kd->right_id;
237  else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id;
238 
239  if (nearer_kd_id != -1)
240  colormap_nearest_node(s, map, nearer_kd_id, target, nearest);
241 
242  if (further_kd_id != -1 && dx*dx < nearest->dist_sqd)
243  colormap_nearest_node(s, map, further_kd_id, target, nearest);
244  }
245 }
246 
247 static av_always_inline uint8_t colormap_nearest_recursive(const PaletteUseContext *s, const struct color_node *node, const uint8_t *rgb)
248 {
249  struct nearest_color res = {.dist_sqd = INT_MAX, .node_pos = -1};
250  colormap_nearest_node(s, node, 0, rgb, &res);
251  return node[res.node_pos].palette_id;
252 }
253 
254 struct stack_node {
255  int color_id;
256  int dx2;
257 };
258 
259 static av_always_inline uint8_t colormap_nearest_iterative(const PaletteUseContext *s, const struct color_node *root, const uint8_t *target)
260 {
261  int pos = 0, best_node_id = -1, best_dist = INT_MAX, cur_color_id = 0;
262  struct stack_node nodes[16];
263  struct stack_node *node = &nodes[0];
264 
265  for (;;) {
266 
267  const struct color_node *kd = &root[cur_color_id];
268  const uint8_t *current = kd->val;
269  const int current_to_target = diff(target, current, s);
270 
271  /* Compare current color node to the target and update our best node if
272  * it's actually better. */
273  if (current_to_target < best_dist) {
274  best_node_id = cur_color_id;
275  if (!current_to_target)
276  goto end; // exact match, we can return immediately
277  best_dist = current_to_target;
278  }
279 
280  /* Check if it's not a leaf */
281  if (kd->left_id != -1 || kd->right_id != -1) {
282  const int split = kd->split;
283  const int dx = target[split] - current[split];
284  int nearer_kd_id, further_kd_id;
285 
286  /* Define which side is the most interesting. */
287  if (dx <= 0) nearer_kd_id = kd->left_id, further_kd_id = kd->right_id;
288  else nearer_kd_id = kd->right_id, further_kd_id = kd->left_id;
289 
290  if (nearer_kd_id != -1) {
291  if (further_kd_id != -1) {
292  /* Here, both paths are defined, so we push a state for
293  * when we are going back. */
294  node->color_id = further_kd_id;
295  node->dx2 = dx*dx;
296  pos++;
297  node++;
298  }
299  /* We can now update current color with the most probable path
300  * (no need to create a state since there is nothing to save
301  * anymore). */
302  cur_color_id = nearer_kd_id;
303  continue;
304  } else if (dx*dx < best_dist) {
305  /* The nearest path isn't available, so there is only one path
306  * possible and it's the least probable. We enter it only if the
307  * distance from the current point to the hyper rectangle is
308  * less than our best distance. */
309  cur_color_id = further_kd_id;
310  continue;
311  }
312  }
313 
314  /* Unstack as much as we can, typically as long as the least probable
315  * branch aren't actually probable. */
316  do {
317  if (--pos < 0)
318  goto end;
319  node--;
320  } while (node->dx2 >= best_dist);
321 
322  /* We got a node where the least probable branch might actually contain
323  * a relevant color. */
324  cur_color_id = node->color_id;
325  }
326 
327 end:
328  return root[best_node_id].palette_id;
329 }
330 
331 #define COLORMAP_NEAREST(s, search, root, target) \
332  search == COLOR_SEARCH_NNS_ITERATIVE ? colormap_nearest_iterative(s, root, target) : \
333  search == COLOR_SEARCH_NNS_RECURSIVE ? colormap_nearest_recursive(s, root, target) : \
334  colormap_nearest_bruteforce(s, target)
335 
336 /**
337  * Check if the requested color is in the cache already. If not, find it in the
338  * color tree and cache it.
339  * Note: a, r, g, and b are the components of color, but are passed as well to avoid
340  * recomputing them (they are generally computed by the caller for other uses).
341  */
343  uint8_t a, uint8_t r, uint8_t g, uint8_t b,
344  const enum color_search_method search_method)
345 {
346  int i;
347  const uint8_t argb_elts[] = {a, r, g, b};
348  const uint8_t rhash = r & ((1<<NBITS)-1);
349  const uint8_t ghash = g & ((1<<NBITS)-1);
350  const uint8_t bhash = b & ((1<<NBITS)-1);
351  const unsigned hash = rhash<<(NBITS*2) | ghash<<NBITS | bhash;
352  struct cache_node *node = &s->cache[hash];
353  struct cached_color *e;
354 
355  // first, check for transparency
356  if (a < s->trans_thresh && s->transparency_index >= 0) {
357  return s->transparency_index;
358  }
359 
360  for (i = 0; i < node->nb_entries; i++) {
361  e = &node->entries[i];
362  if (e->color == color)
363  return e->pal_entry;
364  }
365 
366  e = av_dynarray2_add((void**)&node->entries, &node->nb_entries,
367  sizeof(*node->entries), NULL);
368  if (!e)
369  return AVERROR(ENOMEM);
370  e->color = color;
371  e->pal_entry = COLORMAP_NEAREST(s, search_method, s->map, argb_elts);
372 
373  return e->pal_entry;
374 }
375 
377  uint32_t c, int *ea, int *er, int *eg, int *eb,
378  const enum color_search_method search_method)
379 {
380  const uint8_t a = c >> 24 & 0xff;
381  const uint8_t r = c >> 16 & 0xff;
382  const uint8_t g = c >> 8 & 0xff;
383  const uint8_t b = c & 0xff;
384  uint32_t dstc;
385  const int dstx = color_get(s, c, a, r, g, b, search_method);
386  if (dstx < 0)
387  return dstx;
388  dstc = s->palette[dstx];
389  if (dstx == s->transparency_index) {
390  *ea =*er = *eg = *eb = 0;
391  } else {
392  *ea = (int)a - (int)(dstc >> 24 & 0xff);
393  *er = (int)r - (int)(dstc >> 16 & 0xff);
394  *eg = (int)g - (int)(dstc >> 8 & 0xff);
395  *eb = (int)b - (int)(dstc & 0xff);
396  }
397  return dstx;
398 }
399 
401  int x_start, int y_start, int w, int h,
402  enum dithering_mode dither,
403  const enum color_search_method search_method)
404 {
405  int x, y;
406  const int src_linesize = in ->linesize[0] >> 2;
407  const int dst_linesize = out->linesize[0];
408  uint32_t *src = ((uint32_t *)in ->data[0]) + y_start*src_linesize;
409  uint8_t *dst = out->data[0] + y_start*dst_linesize;
410 
411  w += x_start;
412  h += y_start;
413 
414  for (y = y_start; y < h; y++) {
415  for (x = x_start; x < w; x++) {
416  int ea, er, eg, eb;
417 
418  if (dither == DITHERING_BAYER) {
419  const int d = s->ordered_dither[(y & 7)<<3 | (x & 7)];
420  const uint8_t a8 = src[x] >> 24 & 0xff;
421  const uint8_t r8 = src[x] >> 16 & 0xff;
422  const uint8_t g8 = src[x] >> 8 & 0xff;
423  const uint8_t b8 = src[x] & 0xff;
424  const uint8_t r = av_clip_uint8(r8 + d);
425  const uint8_t g = av_clip_uint8(g8 + d);
426  const uint8_t b = av_clip_uint8(b8 + d);
427  const uint32_t color_new = (unsigned)(a8) << 24 | r << 16 | g << 8 | b;
428  const int color = color_get(s, color_new, a8, r, g, b, search_method);
429 
430  if (color < 0)
431  return color;
432  dst[x] = color;
433 
434  } else if (dither == DITHERING_HECKBERT) {
435  const int right = x < w - 1, down = y < h - 1;
436  const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method);
437 
438  if (color < 0)
439  return color;
440  dst[x] = color;
441 
442  if (right) src[ x + 1] = dither_color(src[ x + 1], er, eg, eb, 3, 3);
443  if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 3, 3);
444  if (right && down) src[src_linesize + x + 1] = dither_color(src[src_linesize + x + 1], er, eg, eb, 2, 3);
445 
446  } else if (dither == DITHERING_FLOYD_STEINBERG) {
447  const int right = x < w - 1, down = y < h - 1, left = x > x_start;
448  const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method);
449 
450  if (color < 0)
451  return color;
452  dst[x] = color;
453 
454  if (right) src[ x + 1] = dither_color(src[ x + 1], er, eg, eb, 7, 4);
455  if (left && down) src[src_linesize + x - 1] = dither_color(src[src_linesize + x - 1], er, eg, eb, 3, 4);
456  if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 5, 4);
457  if (right && down) src[src_linesize + x + 1] = dither_color(src[src_linesize + x + 1], er, eg, eb, 1, 4);
458 
459  } else if (dither == DITHERING_SIERRA2) {
460  const int right = x < w - 1, down = y < h - 1, left = x > x_start;
461  const int right2 = x < w - 2, left2 = x > x_start + 1;
462  const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method);
463 
464  if (color < 0)
465  return color;
466  dst[x] = color;
467 
468  if (right) src[ x + 1] = dither_color(src[ x + 1], er, eg, eb, 4, 4);
469  if (right2) src[ x + 2] = dither_color(src[ x + 2], er, eg, eb, 3, 4);
470 
471  if (down) {
472  if (left2) src[ src_linesize + x - 2] = dither_color(src[ src_linesize + x - 2], er, eg, eb, 1, 4);
473  if (left) src[ src_linesize + x - 1] = dither_color(src[ src_linesize + x - 1], er, eg, eb, 2, 4);
474  if (1) src[ src_linesize + x ] = dither_color(src[ src_linesize + x ], er, eg, eb, 3, 4);
475  if (right) src[ src_linesize + x + 1] = dither_color(src[ src_linesize + x + 1], er, eg, eb, 2, 4);
476  if (right2) src[ src_linesize + x + 2] = dither_color(src[ src_linesize + x + 2], er, eg, eb, 1, 4);
477  }
478 
479  } else if (dither == DITHERING_SIERRA2_4A) {
480  const int right = x < w - 1, down = y < h - 1, left = x > x_start;
481  const int color = get_dst_color_err(s, src[x], &ea, &er, &eg, &eb, search_method);
482 
483  if (color < 0)
484  return color;
485  dst[x] = color;
486 
487  if (right) src[ x + 1] = dither_color(src[ x + 1], er, eg, eb, 2, 2);
488  if (left && down) src[src_linesize + x - 1] = dither_color(src[src_linesize + x - 1], er, eg, eb, 1, 2);
489  if ( down) src[src_linesize + x ] = dither_color(src[src_linesize + x ], er, eg, eb, 1, 2);
490 
491  } else {
492  const uint8_t a = src[x] >> 24 & 0xff;
493  const uint8_t r = src[x] >> 16 & 0xff;
494  const uint8_t g = src[x] >> 8 & 0xff;
495  const uint8_t b = src[x] & 0xff;
496  const int color = color_get(s, src[x], a, r, g, b, search_method);
497 
498  if (color < 0)
499  return color;
500  dst[x] = color;
501  }
502  }
503  src += src_linesize;
504  dst += dst_linesize;
505  }
506  return 0;
507 }
508 
509 #define INDENT 4
510 static void disp_node(AVBPrint *buf,
511  const struct color_node *map,
512  int parent_id, int node_id,
513  int depth)
514 {
515  const struct color_node *node = &map[node_id];
516  const uint32_t fontcolor = node->val[1] > 0x50 &&
517  node->val[2] > 0x50 &&
518  node->val[3] > 0x50 ? 0 : 0xffffff;
519  const int rgb_comp = node->split - 1;
520  av_bprintf(buf, "%*cnode%d ["
521  "label=\"%c%02X%c%02X%c%02X%c\" "
522  "fillcolor=\"#%02x%02x%02x\" "
523  "fontcolor=\"#%06"PRIX32"\"]\n",
524  depth*INDENT, ' ', node->palette_id,
525  "[ "[rgb_comp], node->val[1],
526  "][ "[rgb_comp], node->val[2],
527  " ]["[rgb_comp], node->val[3],
528  " ]"[rgb_comp],
529  node->val[1], node->val[2], node->val[3],
530  fontcolor);
531  if (parent_id != -1)
532  av_bprintf(buf, "%*cnode%d -> node%d\n", depth*INDENT, ' ',
533  map[parent_id].palette_id, node->palette_id);
534  if (node->left_id != -1) disp_node(buf, map, node_id, node->left_id, depth + 1);
535  if (node->right_id != -1) disp_node(buf, map, node_id, node->right_id, depth + 1);
536 }
537 
538 // debug_kdtree=kdtree.dot -> dot -Tpng kdtree.dot > kdtree.png
539 static int disp_tree(const struct color_node *node, const char *fname)
540 {
541  AVBPrint buf;
542  FILE *f = avpriv_fopen_utf8(fname, "w");
543 
544  if (!f) {
545  int ret = AVERROR(errno);
546  av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s' for writing: %s\n",
547  fname, av_err2str(ret));
548  return ret;
549  }
550 
552 
553  av_bprintf(&buf, "digraph {\n");
554  av_bprintf(&buf, " node [style=filled fontsize=10 shape=box]\n");
555  disp_node(&buf, node, -1, 0, 0);
556  av_bprintf(&buf, "}\n");
557 
558  fwrite(buf.str, 1, buf.len, f);
559  fclose(f);
560  av_bprint_finalize(&buf, NULL);
561  return 0;
562 }
563 
565 {
566  int r, g, b, ret = 0;
567 
568  for (r = 0; r < 256; r++) {
569  for (g = 0; g < 256; g++) {
570  for (b = 0; b < 256; b++) {
571  const uint8_t argb[] = {0xff, r, g, b};
572  const int r1 = COLORMAP_NEAREST(s, s->color_search_method, s->map, argb);
573  const int r2 = colormap_nearest_bruteforce(s, argb);
574  if (r1 != r2) {
575  const uint32_t c1 = s->palette[r1];
576  const uint32_t c2 = s->palette[r2];
577  const uint8_t a1 = s->use_alpha ? c1>>24 & 0xff : 0xff;
578  const uint8_t a2 = s->use_alpha ? c2>>24 & 0xff : 0xff;
579  const uint8_t palargb1[] = { a1, c1>>16 & 0xff, c1>> 8 & 0xff, c1 & 0xff };
580  const uint8_t palargb2[] = { a2, c2>>16 & 0xff, c2>> 8 & 0xff, c2 & 0xff };
581  const int d1 = diff(palargb1, argb, s);
582  const int d2 = diff(palargb2, argb, s);
583  if (d1 != d2) {
584  if (s->use_alpha)
586  "/!\\ %02X%02X%02X: %d ! %d (%08"PRIX32" ! %08"PRIX32") / dist: %d ! %d\n",
587  r, g, b, r1, r2, c1, c2, d1, d2);
588  else
590  "/!\\ %02X%02X%02X: %d ! %d (%06"PRIX32" ! %06"PRIX32") / dist: %d ! %d\n",
591  r, g, b, r1, r2, c1 & 0xffffff, c2 & 0xffffff, d1, d2);
592  ret = 1;
593  }
594  }
595  }
596  }
597  }
598  return ret;
599 }
600 
601 struct color {
602  uint32_t value;
603  uint8_t pal_id;
604 };
605 
606 struct color_rect {
607  uint8_t min[4];
608  uint8_t max[4];
609 };
610 
611 typedef int (*cmp_func)(const void *, const void *);
612 
613 #define DECLARE_CMP_FUNC(name, pos) \
614 static int cmp_##name(const void *pa, const void *pb) \
615 { \
616  const struct color *a = pa; \
617  const struct color *b = pb; \
618  return (int)(a->value >> (8 * (3 - (pos))) & 0xff) \
619  - (int)(b->value >> (8 * (3 - (pos))) & 0xff); \
620 }
621 
626 
627 static const cmp_func cmp_funcs[] = {cmp_a, cmp_r, cmp_g, cmp_b};
628 
629 static int get_next_color(const uint8_t *color_used, const PaletteUseContext *s,
630  int *component, const struct color_rect *box)
631 {
632  int wa, wr, wg, wb;
633  int i, longest = 0;
634  unsigned nb_color = 0;
635  struct color_rect ranges;
636  struct color tmp_pal[256];
637  cmp_func cmpf;
638 
639  ranges.min[0] = ranges.min[1] = ranges.min[2] = ranges.min[3]= 0xff;
640  ranges.max[0] = ranges.max[1] = ranges.max[2] = ranges.max[3]= 0x00;
641 
642  for (i = 0; i < AVPALETTE_COUNT; i++) {
643  const uint32_t c = s->palette[i];
644  const uint8_t a = c >> 24 & 0xff;
645  const uint8_t r = c >> 16 & 0xff;
646  const uint8_t g = c >> 8 & 0xff;
647  const uint8_t b = c & 0xff;
648 
649  if (!s->use_alpha && a < s->trans_thresh) {
650  continue;
651  }
652 
653  if (color_used[i] || (a != 0xff && !s->use_alpha) ||
654  r < box->min[1] || g < box->min[2] || b < box->min[3] ||
655  r > box->max[1] || g > box->max[2] || b > box->max[3])
656  continue;
657 
658  if (s->use_alpha && (a < box->min[0] || a > box->max[0]))
659  continue;
660 
661  if (a < ranges.min[0]) ranges.min[0] = a;
662  if (r < ranges.min[1]) ranges.min[1] = r;
663  if (g < ranges.min[2]) ranges.min[2] = g;
664  if (b < ranges.min[3]) ranges.min[3] = b;
665 
666  if (a > ranges.max[0]) ranges.max[0] = a;
667  if (r > ranges.max[1]) ranges.max[1] = r;
668  if (g > ranges.max[2]) ranges.max[2] = g;
669  if (b > ranges.max[3]) ranges.max[3] = b;
670 
671  tmp_pal[nb_color].value = c;
672  tmp_pal[nb_color].pal_id = i;
673 
674  nb_color++;
675  }
676 
677  if (!nb_color)
678  return -1;
679 
680  /* define longest axis that will be the split component */
681  wa = ranges.max[0] - ranges.min[0];
682  wr = ranges.max[1] - ranges.min[1];
683  wg = ranges.max[2] - ranges.min[2];
684  wb = ranges.max[3] - ranges.min[3];
685 
686  if (s->use_alpha) {
687  if (wa >= wr && wa >= wb && wa >= wg) longest = 0;
688  if (wr >= wg && wr >= wb && wr >= wa) longest = 1;
689  if (wg >= wr && wg >= wb && wg >= wa) longest = 2;
690  if (wb >= wr && wb >= wg && wb >= wa) longest = 3;
691  } else {
692  if (wr >= wg && wr >= wb) longest = 1;
693  if (wg >= wr && wg >= wb) longest = 2;
694  if (wb >= wr && wb >= wg) longest = 3;
695  }
696 
697  cmpf = cmp_funcs[longest];
698  *component = longest;
699 
700  /* sort along this axis to get median */
701  AV_QSORT(tmp_pal, nb_color, struct color, cmpf);
702 
703  return tmp_pal[nb_color >> 1].pal_id;
704 }
705 
706 static int colormap_insert(struct color_node *map,
707  uint8_t *color_used,
708  int *nb_used,
709  const PaletteUseContext *s,
710  const struct color_rect *box)
711 {
712  uint32_t c;
713  int component, cur_id;
714  int node_left_id = -1, node_right_id = -1;
715  struct color_node *node;
716  struct color_rect box1, box2;
717  const int pal_id = get_next_color(color_used, s, &component, box);
718 
719  if (pal_id < 0)
720  return -1;
721 
722  /* create new node with that color */
723  cur_id = (*nb_used)++;
724  c = s->palette[pal_id];
725  node = &map[cur_id];
726  node->split = component;
727  node->palette_id = pal_id;
728  node->val[0] = c>>24 & 0xff;
729  node->val[1] = c>>16 & 0xff;
730  node->val[2] = c>> 8 & 0xff;
731  node->val[3] = c & 0xff;
732 
733  color_used[pal_id] = 1;
734 
735  /* get the two boxes this node creates */
736  box1 = box2 = *box;
737  box1.max[component] = node->val[component];
738  box2.min[component] = FFMIN(node->val[component] + 1, 255);
739 
740  node_left_id = colormap_insert(map, color_used, nb_used, s, &box1);
741 
742  if (box2.min[component] <= box2.max[component])
743  node_right_id = colormap_insert(map, color_used, nb_used, s, &box2);
744 
745  node->left_id = node_left_id;
746  node->right_id = node_right_id;
747 
748  return cur_id;
749 }
750 
751 static int cmp_pal_entry(const void *a, const void *b)
752 {
753  const int c1 = *(const uint32_t *)a & 0xffffff;
754  const int c2 = *(const uint32_t *)b & 0xffffff;
755  return c1 - c2;
756 }
757 
758 static int cmp_pal_entry_alpha(const void *a, const void *b)
759 {
760  const int c1 = *(const uint32_t *)a;
761  const int c2 = *(const uint32_t *)b;
762  return c1 - c2;
763 }
764 
766 {
767  int i, nb_used = 0;
768  uint8_t color_used[AVPALETTE_COUNT] = {0};
769  uint32_t last_color = 0;
770  struct color_rect box;
771 
772  if (!s->use_alpha && s->transparency_index >= 0) {
773  FFSWAP(uint32_t, s->palette[s->transparency_index], s->palette[255]);
774  }
775 
776  /* disable transparent colors and dups */
777  qsort(s->palette, AVPALETTE_COUNT-(s->transparency_index >= 0), sizeof(*s->palette),
778  s->use_alpha ? cmp_pal_entry_alpha : cmp_pal_entry);
779 
780  for (i = 0; i < AVPALETTE_COUNT; i++) {
781  const uint32_t c = s->palette[i];
782  if (i != 0 && c == last_color) {
783  color_used[i] = 1;
784  continue;
785  }
786  last_color = c;
787  if (!s->use_alpha && c >> 24 < s->trans_thresh) {
788  color_used[i] = 1; // ignore transparent color(s)
789  continue;
790  }
791  }
792 
793  box.min[0] = box.min[1] = box.min[2] = box.min[3] = 0x00;
794  box.max[0] = box.max[1] = box.max[2] = box.max[3] = 0xff;
795 
796  colormap_insert(s->map, color_used, &nb_used, s, &box);
797 
798  if (s->dot_filename)
799  disp_tree(s->map, s->dot_filename);
800 
801  if (s->debug_accuracy) {
802  if (!debug_accuracy(s))
803  av_log(NULL, AV_LOG_INFO, "Accuracy check passed\n");
804  }
805 }
806 
807 static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1,
808  const AVFrame *in2, int frame_count)
809 {
810  int x, y;
811  const uint32_t *palette = s->palette;
812  uint32_t *src1 = (uint32_t *)in1->data[0];
813  uint8_t *src2 = in2->data[0];
814  const int src1_linesize = in1->linesize[0] >> 2;
815  const int src2_linesize = in2->linesize[0];
816  const float div = in1->width * in1->height * (s->use_alpha ? 4 : 3);
817  unsigned mean_err = 0;
818 
819  for (y = 0; y < in1->height; y++) {
820  for (x = 0; x < in1->width; x++) {
821  const uint32_t c1 = src1[x];
822  const uint32_t c2 = palette[src2[x]];
823  const uint8_t a1 = s->use_alpha ? c1>>24 & 0xff : 0xff;
824  const uint8_t a2 = s->use_alpha ? c2>>24 & 0xff : 0xff;
825  const uint8_t argb1[] = {a1, c1 >> 16 & 0xff, c1 >> 8 & 0xff, c1 & 0xff};
826  const uint8_t argb2[] = {a2, c2 >> 16 & 0xff, c2 >> 8 & 0xff, c2 & 0xff};
827  mean_err += diff(argb1, argb2, s);
828  }
829  src1 += src1_linesize;
830  src2 += src2_linesize;
831  }
832 
833  s->total_mean_err += mean_err;
834 
835  av_log(NULL, AV_LOG_INFO, "MEP:%.3f TotalMEP:%.3f\n",
836  mean_err / div, s->total_mean_err / (div * frame_count));
837 }
838 
840  const AVFrame *prv_src, const AVFrame *cur_src,
841  const AVFrame *prv_dst, AVFrame *cur_dst,
842  int *xp, int *yp, int *wp, int *hp)
843 {
844  int x_start = 0, y_start = 0;
845  int width = cur_src->width;
846  int height = cur_src->height;
847 
848  if (prv_src->data[0] && diff_mode == DIFF_MODE_RECTANGLE) {
849  int y;
850  int x_end = cur_src->width - 1,
851  y_end = cur_src->height - 1;
852  const uint32_t *prv_srcp = (const uint32_t *)prv_src->data[0];
853  const uint32_t *cur_srcp = (const uint32_t *)cur_src->data[0];
854  const uint8_t *prv_dstp = prv_dst->data[0];
855  uint8_t *cur_dstp = cur_dst->data[0];
856 
857  const int prv_src_linesize = prv_src->linesize[0] >> 2;
858  const int cur_src_linesize = cur_src->linesize[0] >> 2;
859  const int prv_dst_linesize = prv_dst->linesize[0];
860  const int cur_dst_linesize = cur_dst->linesize[0];
861 
862  /* skip common lines */
863  while (y_start < y_end && !memcmp(prv_srcp + y_start*prv_src_linesize,
864  cur_srcp + y_start*cur_src_linesize,
865  cur_src->width * 4)) {
866  memcpy(cur_dstp + y_start*cur_dst_linesize,
867  prv_dstp + y_start*prv_dst_linesize,
868  cur_dst->width);
869  y_start++;
870  }
871  while (y_end > y_start && !memcmp(prv_srcp + y_end*prv_src_linesize,
872  cur_srcp + y_end*cur_src_linesize,
873  cur_src->width * 4)) {
874  memcpy(cur_dstp + y_end*cur_dst_linesize,
875  prv_dstp + y_end*prv_dst_linesize,
876  cur_dst->width);
877  y_end--;
878  }
879 
880  height = y_end + 1 - y_start;
881 
882  /* skip common columns */
883  while (x_start < x_end) {
884  int same_column = 1;
885  for (y = y_start; y <= y_end; y++) {
886  if (prv_srcp[y*prv_src_linesize + x_start] != cur_srcp[y*cur_src_linesize + x_start]) {
887  same_column = 0;
888  break;
889  }
890  }
891  if (!same_column)
892  break;
893  x_start++;
894  }
895  while (x_end > x_start) {
896  int same_column = 1;
897  for (y = y_start; y <= y_end; y++) {
898  if (prv_srcp[y*prv_src_linesize + x_end] != cur_srcp[y*cur_src_linesize + x_end]) {
899  same_column = 0;
900  break;
901  }
902  }
903  if (!same_column)
904  break;
905  x_end--;
906  }
907  width = x_end + 1 - x_start;
908 
909  if (x_start) {
910  for (y = y_start; y <= y_end; y++)
911  memcpy(cur_dstp + y*cur_dst_linesize,
912  prv_dstp + y*prv_dst_linesize, x_start);
913  }
914  if (x_end != cur_src->width - 1) {
915  const int copy_len = cur_src->width - 1 - x_end;
916  for (y = y_start; y <= y_end; y++)
917  memcpy(cur_dstp + y*cur_dst_linesize + x_end + 1,
918  prv_dstp + y*prv_dst_linesize + x_end + 1,
919  copy_len);
920  }
921  }
922  *xp = x_start;
923  *yp = y_start;
924  *wp = width;
925  *hp = height;
926 }
927 
929 {
930  int x, y, w, h, ret;
931  AVFilterContext *ctx = inlink->dst;
932  PaletteUseContext *s = ctx->priv;
933  AVFilterLink *outlink = inlink->dst->outputs[0];
934 
935  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
936  if (!out) {
937  *outf = NULL;
938  return AVERROR(ENOMEM);
939  }
941 
942  set_processing_window(s->diff_mode, s->last_in, in,
943  s->last_out, out, &x, &y, &w, &h);
944  av_frame_unref(s->last_in);
945  av_frame_unref(s->last_out);
946  if ((ret = av_frame_ref(s->last_in, in)) < 0 ||
947  (ret = av_frame_ref(s->last_out, out)) < 0 ||
948  (ret = av_frame_make_writable(s->last_in)) < 0) {
949  av_frame_free(&out);
950  *outf = NULL;
951  return ret;
952  }
953 
954  ff_dlog(ctx, "%dx%d rect: (%d;%d) -> (%d,%d) [area:%dx%d]\n",
955  w, h, x, y, x+w, y+h, in->width, in->height);
956 
957  ret = s->set_frame(s, out, in, x, y, w, h);
958  if (ret < 0) {
959  av_frame_free(&out);
960  *outf = NULL;
961  return ret;
962  }
963  memcpy(out->data[1], s->palette, AVPALETTE_SIZE);
964  if (s->calc_mean_err)
965  debug_mean_error(s, in, out, inlink->frame_count_out);
966  *outf = out;
967  return 0;
968 }
969 
970 static int config_output(AVFilterLink *outlink)
971 {
972  int ret;
973  AVFilterContext *ctx = outlink->src;
974  PaletteUseContext *s = ctx->priv;
975 
977  if (ret < 0)
978  return ret;
979  s->fs.opt_repeatlast = 1; // only 1 frame in the palette
980  s->fs.in[1].before = s->fs.in[1].after = EXT_INFINITY;
981  s->fs.on_event = load_apply_palette;
982 
983  outlink->w = ctx->inputs[0]->w;
984  outlink->h = ctx->inputs[0]->h;
985 
986  outlink->time_base = ctx->inputs[0]->time_base;
987  if ((ret = ff_framesync_configure(&s->fs)) < 0)
988  return ret;
989  return 0;
990 }
991 
993 {
994  AVFilterContext *ctx = inlink->dst;
995 
996  if (inlink->w * inlink->h != AVPALETTE_COUNT) {
998  "Palette input must contain exactly %d pixels. "
999  "Specified input has %dx%d=%d pixels\n",
1000  AVPALETTE_COUNT, inlink->w, inlink->h,
1001  inlink->w * inlink->h);
1002  return AVERROR(EINVAL);
1003  }
1004  return 0;
1005 }
1006 
1007 static void load_palette(PaletteUseContext *s, const AVFrame *palette_frame)
1008 {
1009  int i, x, y;
1010  const uint32_t *p = (const uint32_t *)palette_frame->data[0];
1011  const int p_linesize = palette_frame->linesize[0] >> 2;
1012 
1013  s->transparency_index = -1;
1014 
1015  if (s->new) {
1016  memset(s->palette, 0, sizeof(s->palette));
1017  memset(s->map, 0, sizeof(s->map));
1018  for (i = 0; i < CACHE_SIZE; i++)
1019  av_freep(&s->cache[i].entries);
1020  memset(s->cache, 0, sizeof(s->cache));
1021  }
1022 
1023  i = 0;
1024  for (y = 0; y < palette_frame->height; y++) {
1025  for (x = 0; x < palette_frame->width; x++) {
1026  s->palette[i] = p[x];
1027  if (!s->use_alpha && p[x]>>24 < s->trans_thresh) {
1028  s->transparency_index = i; // we are assuming at most one transparent color in palette
1029  }
1030  i++;
1031  }
1032  p += p_linesize;
1033  }
1034 
1035  load_colormap(s);
1036 
1037  if (!s->new)
1038  s->palette_loaded = 1;
1039 }
1040 
1042 {
1043  AVFilterContext *ctx = fs->parent;
1044  AVFilterLink *inlink = ctx->inputs[0];
1045  PaletteUseContext *s = ctx->priv;
1046  AVFrame *master, *second, *out = NULL;
1047  int ret;
1048 
1049  // writable for error diffusal dithering
1051  if (ret < 0)
1052  return ret;
1053  if (!master || !second) {
1055  return AVERROR_BUG;
1056  }
1057  if (!s->palette_loaded) {
1058  load_palette(s, second);
1059  }
1062  if (ret < 0)
1063  return ret;
1064  return ff_filter_frame(ctx->outputs[0], out);
1065 }
1066 
1067 #define DEFINE_SET_FRAME(color_search, name, value) \
1068 static int set_frame_##name(PaletteUseContext *s, AVFrame *out, AVFrame *in, \
1069  int x_start, int y_start, int w, int h) \
1070 { \
1071  return set_frame(s, out, in, x_start, y_start, w, h, value, color_search); \
1072 }
1073 
1074 #define DEFINE_SET_FRAME_COLOR_SEARCH(color_search, color_search_macro) \
1075  DEFINE_SET_FRAME(color_search_macro, color_search##_##none, DITHERING_NONE) \
1076  DEFINE_SET_FRAME(color_search_macro, color_search##_##bayer, DITHERING_BAYER) \
1077  DEFINE_SET_FRAME(color_search_macro, color_search##_##heckbert, DITHERING_HECKBERT) \
1078  DEFINE_SET_FRAME(color_search_macro, color_search##_##floyd_steinberg, DITHERING_FLOYD_STEINBERG) \
1079  DEFINE_SET_FRAME(color_search_macro, color_search##_##sierra2, DITHERING_SIERRA2) \
1080  DEFINE_SET_FRAME(color_search_macro, color_search##_##sierra2_4a, DITHERING_SIERRA2_4A) \
1081 
1085 
1086 #define DITHERING_ENTRIES(color_search) { \
1087  set_frame_##color_search##_none, \
1088  set_frame_##color_search##_bayer, \
1089  set_frame_##color_search##_heckbert, \
1090  set_frame_##color_search##_floyd_steinberg, \
1091  set_frame_##color_search##_sierra2, \
1092  set_frame_##color_search##_sierra2_4a, \
1093 }
1094 
1096  DITHERING_ENTRIES(nns_iterative),
1097  DITHERING_ENTRIES(nns_recursive),
1098  DITHERING_ENTRIES(bruteforce),
1099 };
1100 
1101 static int dither_value(int p)
1102 {
1103  const int q = p ^ (p >> 3);
1104  return (p & 4) >> 2 | (q & 4) >> 1 \
1105  | (p & 2) << 1 | (q & 2) << 2 \
1106  | (p & 1) << 4 | (q & 1) << 5;
1107 }
1108 
1110 {
1111  PaletteUseContext *s = ctx->priv;
1112 
1113  s->last_in = av_frame_alloc();
1114  s->last_out = av_frame_alloc();
1115  if (!s->last_in || !s->last_out)
1116  return AVERROR(ENOMEM);
1117 
1118  s->set_frame = set_frame_lut[s->color_search_method][s->dither];
1119 
1120  if (s->dither == DITHERING_BAYER) {
1121  int i;
1122  const int delta = 1 << (5 - s->bayer_scale); // to avoid too much luma
1123 
1124  for (i = 0; i < FF_ARRAY_ELEMS(s->ordered_dither); i++)
1125  s->ordered_dither[i] = (dither_value(i) >> s->bayer_scale) - delta;
1126  }
1127 
1128  return 0;
1129 }
1130 
1132 {
1133  PaletteUseContext *s = ctx->priv;
1134  return ff_framesync_activate(&s->fs);
1135 }
1136 
1138 {
1139  int i;
1140  PaletteUseContext *s = ctx->priv;
1141 
1142  ff_framesync_uninit(&s->fs);
1143  for (i = 0; i < CACHE_SIZE; i++)
1144  av_freep(&s->cache[i].entries);
1145  av_frame_free(&s->last_in);
1146  av_frame_free(&s->last_out);
1147 }
1148 
1149 static const AVFilterPad paletteuse_inputs[] = {
1150  {
1151  .name = "default",
1152  .type = AVMEDIA_TYPE_VIDEO,
1153  },{
1154  .name = "palette",
1155  .type = AVMEDIA_TYPE_VIDEO,
1156  .config_props = config_input_palette,
1157  },
1158 };
1159 
1161  {
1162  .name = "default",
1163  .type = AVMEDIA_TYPE_VIDEO,
1164  .config_props = config_output,
1165  },
1166 };
1167 
1169  .name = "paletteuse",
1170  .description = NULL_IF_CONFIG_SMALL("Use a palette to downsample an input video stream."),
1171  .priv_size = sizeof(PaletteUseContext),
1172  .init = init,
1173  .uninit = uninit,
1174  .activate = activate,
1178  .priv_class = &paletteuse_class,
1179 };
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:101
cached_color::color
uint32_t color
Definition: vf_paletteuse.c:69
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:134
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
config_input_palette
static int config_input_palette(AVFilterLink *inlink)
Definition: vf_paletteuse.c:992
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
PaletteUseContext::use_alpha
int use_alpha
Definition: vf_paletteuse.c:91
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_paletteuse.c:141
cmp_pal_entry_alpha
static int cmp_pal_entry_alpha(const void *a, const void *b)
Definition: vf_paletteuse.c:758
PaletteUseContext::dot_filename
char * dot_filename
Definition: vf_paletteuse.c:103
r
const char * r
Definition: vf_curves.c:126
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
opt.h
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:380
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:304
debug_mean_error
static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, const AVFrame *in2, int frame_count)
Definition: vf_paletteuse.c:807
out
FILE * out
Definition: movenc.c:54
color
Definition: vf_paletteuse.c:601
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1009
diff
static av_always_inline int diff(const uint8_t *c1, const uint8_t *c2, const PaletteUseContext *s)
Definition: vf_paletteuse.c:166
src1
const pixel * src1
Definition: h264pred_template.c:421
PaletteUseContext::last_out
AVFrame * last_out
Definition: vf_paletteuse.c:100
dither_color
static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift)
Definition: vf_paletteuse.c:157
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
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_paletteuse.c:1109
set_frame_func
int(* set_frame_func)(struct PaletteUseContext *s, AVFrame *out, AVFrame *in, int x_start, int y_start, int width, int height)
Definition: vf_paletteuse.c:80
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
av_frame_make_writable
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:550
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_paletteuse.c:1137
AVFrame::width
int width
Definition: frame.h:397
w
uint8_t w
Definition: llviddspenc.c:38
av_dynarray2_add
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
Definition: mem.c:351
AVOption
AVOption.
Definition: opt.h:251
b
#define b
Definition: input.c:41
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:167
stack_node::dx2
int dx2
Definition: vf_paletteuse.c:256
data
const char data[16]
Definition: mxf.c:146
PaletteUseContext::set_frame
set_frame_func set_frame
Definition: vf_paletteuse.c:95
disp_tree
static int disp_tree(const struct color_node *node, const char *fname)
Definition: vf_paletteuse.c:539
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:175
c1
static const uint64_t c1
Definition: murmur3.c:51
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
EXT_INFINITY
@ EXT_INFINITY
Extend the frame to infinity.
Definition: framesync.h:75
hash
uint8_t hash[HASH_SIZE]
Definition: movenc.c:57
PaletteUseContext::palette_loaded
int palette_loaded
Definition: vf_paletteuse.c:92
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:346
stack_node::color_id
int color_id
Definition: vf_paletteuse.c:255
DIFF_MODE_NONE
@ DIFF_MODE_NONE
Definition: vf_paletteuse.c:53
rgb
Definition: rpzaenc.c:59
NB_DITHERING
@ NB_DITHERING
Definition: vf_paletteuse.c:42
dither_value
static int dither_value(int p)
Definition: vf_paletteuse.c:1101
COLOR_SEARCH_BRUTEFORCE
@ COLOR_SEARCH_BRUTEFORCE
Definition: vf_paletteuse.c:48
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
apply_palette
static int apply_palette(AVFilterLink *inlink, AVFrame *in, AVFrame **outf)
Definition: vf_paletteuse.c:928
PaletteUseContext::cache
struct cache_node cache[CACHE_SIZE]
Definition: vf_paletteuse.c:86
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:104
a1
#define a1
Definition: regdef.h:47
colormap_nearest_bruteforce
static av_always_inline uint8_t colormap_nearest_bruteforce(const PaletteUseContext *s, const uint8_t *argb)
Definition: vf_paletteuse.c:186
PaletteUseContext::ordered_dither
int ordered_dither[8 *8]
Definition: vf_paletteuse.c:97
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
set_processing_window
static void set_processing_window(enum diff_mode diff_mode, const AVFrame *prv_src, const AVFrame *cur_src, const AVFrame *prv_dst, AVFrame *cur_dst, int *xp, int *yp, int *wp, int *hp)
Definition: vf_paletteuse.c:839
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
INDENT
#define INDENT
Definition: vf_paletteuse.c:509
color_rect
Definition: vf_paletteuse.c:606
DEFINE_SET_FRAME_COLOR_SEARCH
#define DEFINE_SET_FRAME_COLOR_SEARCH(color_search, color_search_macro)
Definition: vf_paletteuse.c:1074
PaletteUseContext::bayer_scale
int bayer_scale
Definition: vf_paletteuse.c:96
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:256
dithering_mode
dithering_mode
Definition: vf_paletteuse.c:35
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_paletteuse.c:970
g
const char * g
Definition: vf_curves.c:127
ff_formats_ref
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:596
color_node::right_id
int right_id
Definition: vf_paletteuse.c:62
DITHERING_HECKBERT
@ DITHERING_HECKBERT
Definition: vf_paletteuse.c:38
stack_node
Definition: vf_paletteuse.c:254
nearest_color::dist_sqd
int dist_sqd
Definition: vf_paletteuse.c:213
ctx
AVFormatContext * ctx
Definition: movenc.c:48
set_frame_lut
static const set_frame_func set_frame_lut[NB_COLOR_SEARCHES][NB_DITHERING]
Definition: vf_paletteuse.c:1095
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:190
file_open.h
debug_accuracy
static int debug_accuracy(const PaletteUseContext *s)
Definition: vf_paletteuse.c:564
if
if(ret)
Definition: filter_design.txt:179
color_node::palette_id
uint8_t palette_id
Definition: vf_paletteuse.c:60
load_apply_palette
static int load_apply_palette(FFFrameSync *fs)
Definition: vf_paletteuse.c:1041
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
ff_vf_paletteuse
const AVFilter ff_vf_paletteuse
Definition: vf_paletteuse.c:1168
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:603
PaletteUseContext::dither
int dither
Definition: vf_paletteuse.c:93
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:258
colormap_insert
static int colormap_insert(struct color_node *map, uint8_t *color_used, int *nb_used, const PaletteUseContext *s, const struct color_rect *box)
Definition: vf_paletteuse.c:706
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
DITHERING_ENTRIES
#define DITHERING_ENTRIES(color_search)
Definition: vf_paletteuse.c:1086
PaletteUseContext
Definition: vf_paletteuse.c:83
get_dst_color_err
static av_always_inline int get_dst_color_err(PaletteUseContext *s, uint32_t c, int *ea, int *er, int *eg, int *eb, const enum color_search_method search_method)
Definition: vf_paletteuse.c:376
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
cmp_funcs
static const cmp_func cmp_funcs[]
Definition: vf_paletteuse.c:627
AVPALETTE_COUNT
#define AVPALETTE_COUNT
Definition: pixfmt.h:33
get_next_color
static int get_next_color(const uint8_t *color_used, const PaletteUseContext *s, int *component, const struct color_rect *box)
Definition: vf_paletteuse.c:629
disp_node
static void disp_node(AVBPrint *buf, const struct color_node *map, int parent_id, int node_id, int depth)
Definition: vf_paletteuse.c:510
DITHERING_NONE
@ DITHERING_NONE
Definition: vf_paletteuse.c:36
paletteuse_options
static const AVOption paletteuse_options[]
Definition: vf_paletteuse.c:112
ff_dlog
#define ff_dlog(a,...)
Definition: tableprint_vlc.h:28
PaletteUseContext::trans_thresh
int trans_thresh
Definition: vf_paletteuse.c:90
qsort.h
f
f
Definition: af_crystalizer.c:122
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:115
ff_framesync_init_dualinput
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:372
master
const char * master
Definition: vf_curves.c:129
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:353
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
nearest_color
Definition: vf_paletteuse.c:211
shift
static int shift(int a, int b)
Definition: bonk.c:253
DITHERING_BAYER
@ DITHERING_BAYER
Definition: vf_paletteuse.c:37
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
DITHERING_FLOYD_STEINBERG
@ DITHERING_FLOYD_STEINBERG
Definition: vf_paletteuse.c:39
PaletteUseContext::palette
uint32_t palette[AVPALETTE_COUNT]
Definition: vf_paletteuse.c:88
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
DITHERING_SIERRA2
@ DITHERING_SIERRA2
Definition: vf_paletteuse.c:40
PaletteUseContext::fs
FFFrameSync fs
Definition: vf_paletteuse.c:85
split
static char * split(char *message, char delim)
Definition: af_channelmap.c:81
height
#define height
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:432
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
color_get
static av_always_inline int color_get(PaletteUseContext *s, uint32_t color, uint8_t a, uint8_t r, uint8_t g, uint8_t b, const enum color_search_method search_method)
Check if the requested color is in the cache already.
Definition: vf_paletteuse.c:342
DITHERING_SIERRA2_4A
@ DITHERING_SIERRA2_4A
Definition: vf_paletteuse.c:41
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
PaletteUseContext::transparency_index
int transparency_index
Definition: vf_paletteuse.c:89
internal.h
DECLARE_CMP_FUNC
#define DECLARE_CMP_FUNC(name, pos)
Definition: vf_paletteuse.c:613
activate
static int activate(AVFilterContext *ctx)
Definition: vf_paletteuse.c:1131
OFFSET
#define OFFSET(x)
Definition: vf_paletteuse.c:110
bprint.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
cache_node
Definition: vf_paletteuse.c:73
AV_QSORT
#define AV_QSORT(p, num, type, cmp)
Quicksort This sort is fast, and fully inplace but not stable and it is possible to construct input t...
Definition: qsort.h:33
internal.h
src2
const pixel * src2
Definition: h264pred_template.c:422
a2
#define a2
Definition: regdef.h:48
cmp_pal_entry
static int cmp_pal_entry(const void *a, const void *b)
Definition: vf_paletteuse.c:751
delta
float delta
Definition: vorbis_enc_data.h:430
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
cache_node::entries
struct cached_color * entries
Definition: vf_paletteuse.c:74
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:487
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
avpriv_fopen_utf8
FILE * avpriv_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
Definition: file_open.c:159
PaletteUseContext::diff_mode
int diff_mode
Definition: vf_paletteuse.c:98
color_node::split
int split
Definition: vf_paletteuse.c:61
cached_color::pal_entry
uint8_t pal_entry
Definition: vf_paletteuse.c:70
load_colormap
static void load_colormap(PaletteUseContext *s)
Definition: vf_paletteuse.c:765
PaletteUseContext::total_mean_err
uint64_t total_mean_err
Definition: vf_paletteuse.c:106
diff_mode
diff_mode
Definition: vf_paletteuse.c:52
FLAGS
#define FLAGS
Definition: vf_paletteuse.c:111
AVFilter
Filter definition.
Definition: avfilter.h:171
cache_node::nb_entries
int nb_entries
Definition: vf_paletteuse.c:75
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
ret
ret
Definition: filter_design.txt:187
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
PaletteUseContext::color_search_method
int color_search_method
Definition: vf_paletteuse.c:104
pos
unsigned int pos
Definition: spdifenc.c:412
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
set_frame
static av_always_inline int set_frame(PaletteUseContext *s, AVFrame *out, AVFrame *in, int x_start, int y_start, int w, int h, enum dithering_mode dither, const enum color_search_method search_method)
Definition: vf_paletteuse.c:400
colormap_nearest_iterative
static av_always_inline uint8_t colormap_nearest_iterative(const PaletteUseContext *s, const struct color_node *root, const uint8_t *target)
Definition: vf_paletteuse.c:259
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
NBITS
#define NBITS
Definition: vf_paletteuse.c:65
AVFrame::height
int height
Definition: frame.h:397
c2
static const uint64_t c2
Definition: murmur3.c:52
framesync.h
DIFF_MODE_RECTANGLE
@ DIFF_MODE_RECTANGLE
Definition: vf_paletteuse.c:54
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
COLOR_SEARCH_NNS_ITERATIVE
@ COLOR_SEARCH_NNS_ITERATIVE
Definition: vf_paletteuse.c:46
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
cmp_func
int(* cmp_func)(const void *, const void *)
Definition: vf_paletteuse.c:611
PaletteUseContext::map
struct color_node map[AVPALETTE_COUNT]
Definition: vf_paletteuse.c:87
COLOR_SEARCH_NNS_RECURSIVE
@ COLOR_SEARCH_NNS_RECURSIVE
Definition: vf_paletteuse.c:47
colormap_nearest_node
static void colormap_nearest_node(const PaletteUseContext *s, const struct color_node *map, const int node_pos, const uint8_t *target, struct nearest_color *nearest)
Definition: vf_paletteuse.c:216
PaletteUseContext::debug_accuracy
int debug_accuracy
Definition: vf_paletteuse.c:107
color_rect::min
uint8_t min[4]
Definition: vf_paletteuse.c:607
COLORMAP_NEAREST
#define COLORMAP_NEAREST(s, search, root, target)
Definition: vf_paletteuse.c:331
colormap_nearest_recursive
static av_always_inline uint8_t colormap_nearest_recursive(const PaletteUseContext *s, const struct color_node *node, const uint8_t *rgb)
Definition: vf_paletteuse.c:247
av_clip_uint8
#define av_clip_uint8
Definition: common.h:101
AVFilterContext
An instance of a filter.
Definition: avfilter.h:415
color_node::val
uint8_t val[4]
Definition: vf_paletteuse.c:59
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
CACHE_SIZE
#define CACHE_SIZE
Definition: vf_paletteuse.c:66
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
color::pal_id
uint8_t pal_id
Definition: vf_paletteuse.c:603
NB_COLOR_SEARCHES
@ NB_COLOR_SEARCHES
Definition: vf_paletteuse.c:49
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:191
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
color::value
uint32_t value
Definition: vf_paletteuse.c:602
d
d
Definition: ffmpeg_filter.c:156
paletteuse_outputs
static const AVFilterPad paletteuse_outputs[]
Definition: vf_paletteuse.c:1160
PaletteUseContext::calc_mean_err
int calc_mean_err
Definition: vf_paletteuse.c:105
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:370
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
ff_framesync_activate
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:355
color_node::left_id
int left_id
Definition: vf_paletteuse.c:62
color_node
Definition: vf_paletteuse.c:58
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(paletteuse)
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
ff_framesync_dualinput_get_writable
int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
Same as ff_framesync_dualinput_get(), but make sure that f0 is writable.
Definition: framesync.c:410
color_rect::max
uint8_t max[4]
Definition: vf_paletteuse.c:608
int
int
Definition: ffmpeg_filter.c:156
PaletteUseContext::last_in
AVFrame * last_in
Definition: vf_paletteuse.c:99
nearest_color::node_pos
int node_pos
Definition: vf_paletteuse.c:212
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
paletteuse_inputs
static const AVFilterPad paletteuse_inputs[]
Definition: vf_paletteuse.c:1149
load_palette
static void load_palette(PaletteUseContext *s, const AVFrame *palette_frame)
Definition: vf_paletteuse.c:1007
cached_color
Definition: vf_paletteuse.c:68
color_search_method
color_search_method
Definition: vf_paletteuse.c:45
min
float min
Definition: vorbis_enc_data.h:429
NB_DIFF_MODE
@ NB_DIFF_MODE
Definition: vf_paletteuse.c:55
dither
static const uint8_t dither[8][8]
Definition: vf_fspp.c:58