FFmpeg
drawutils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2011 Stefano Sabatini <stefano.sabatini-lala poste it>
3  * Copyright 2012 Nicolas George <nicolas.george normalesup org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <string.h>
23 
24 #include "libavutil/avassert.h"
25 #include "libavutil/avutil.h"
26 #include "libavutil/csp.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/pixdesc.h"
29 #include "colorspace.h"
30 #include "drawutils.h"
31 #include "formats.h"
32 
33 enum { RED = 0, GREEN, BLUE, ALPHA };
34 
35 int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
36 {
38  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
39  return AVERROR(EINVAL);
40  if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
41  return AVERROR(EINVAL);
42  av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA));
43  if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
44  rgba_map[RED] = desc->comp[0].plane;
45  rgba_map[GREEN] = desc->comp[1].plane;
46  rgba_map[BLUE] = desc->comp[2].plane;
47  rgba_map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3;
48  } else {
49  int had0 = 0;
50  unsigned depthb = 0;
51  unsigned i;
52  for (i = 0; i < desc->nb_components; i++) {
53  /* all components must have same depth in bytes */
54  unsigned db = (desc->comp[i].depth + 7) / 8;
55  unsigned pos = desc->comp[i].offset / db;
56  if (depthb && (depthb != db))
57  return AVERROR(ENOSYS);
58 
59  if (desc->comp[i].offset % db)
60  return AVERROR(ENOSYS);
61 
62  had0 |= pos == 0;
63  rgba_map[i] = pos;
64  }
65 
66  if (desc->nb_components == 3)
67  rgba_map[ALPHA] = had0 ? 3 : 0;
68  }
69 
70  av_assert0(rgba_map[RED] != rgba_map[GREEN]);
71  av_assert0(rgba_map[GREEN] != rgba_map[BLUE]);
72  av_assert0(rgba_map[BLUE] != rgba_map[RED]);
73  av_assert0(rgba_map[RED] != rgba_map[ALPHA]);
74  av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]);
75  av_assert0(rgba_map[BLUE] != rgba_map[ALPHA]);
76 
77  return 0;
78 }
79 
81  enum AVColorRange range, unsigned flags)
82 {
84  const AVLumaCoefficients *luma = NULL;
85  const AVComponentDescriptor *c;
86  unsigned i, nb_planes = 0;
87  int pixelstep[MAX_PLANES] = { 0 };
88  int depthb = 0;
89 
90  if (!desc || !desc->name)
91  return AVERROR(EINVAL);
92  if (desc->flags & AV_PIX_FMT_FLAG_BE)
93  return AVERROR(ENOSYS);
95  return AVERROR(ENOSYS);
96  if (csp == AVCOL_SPC_UNSPECIFIED)
98  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp)))
99  return AVERROR(EINVAL);
100  if (range == AVCOL_RANGE_UNSPECIFIED)
105  if (range != AVCOL_RANGE_JPEG && range != AVCOL_RANGE_MPEG)
106  return AVERROR(EINVAL);
107  for (i = 0; i < desc->nb_components; i++) {
108  int db;
109  c = &desc->comp[i];
110  /* for now, only 8-16 bits formats */
111  if (c->depth < 8 || c->depth > 16)
112  return AVERROR(ENOSYS);
113  if (c->plane >= MAX_PLANES)
114  return AVERROR(ENOSYS);
115  /* data must either be in the high or low bits, never middle */
116  if (c->shift && ((c->shift + c->depth) & 0x7))
117  return AVERROR(ENOSYS);
118  /* mixed >8 and <=8 depth */
119  db = (c->depth + 7) / 8;
120  if (depthb && (depthb != db))
121  return AVERROR(ENOSYS);
122  depthb = db;
123  if (db * (c->offset + 1) > 16)
124  return AVERROR(ENOSYS);
125  if (c->offset % db)
126  return AVERROR(ENOSYS);
127  /* strange interleaving */
128  if (pixelstep[c->plane] != 0 &&
129  pixelstep[c->plane] != c->step)
130  return AVERROR(ENOSYS);
131  pixelstep[c->plane] = c->step;
132  if (pixelstep[c->plane] >= 8)
133  return AVERROR(ENOSYS);
134  nb_planes = FFMAX(nb_planes, c->plane + 1);
135  }
136  memset(draw, 0, sizeof(*draw));
137  draw->desc = desc;
138  draw->format = format;
139  draw->nb_planes = nb_planes;
140  draw->range = range;
141  draw->csp = csp;
142  draw->flags = flags;
143  if (luma)
144  ff_fill_rgb2yuv_table(luma, draw->rgb2yuv);
145  memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
146  draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
147  draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
148  return 0;
149 }
150 
152 {
154 }
155 
156 void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
157 {
158  unsigned i;
159  double yuvad[4];
160  double rgbad[4];
161  const AVPixFmtDescriptor *desc = draw->desc;
162 
163  if (rgba != color->rgba)
164  memcpy(color->rgba, rgba, sizeof(color->rgba));
165 
166  memset(color->comp, 0, sizeof(color->comp));
167 
168  for (int i = 0; i < 4; i++)
169  rgbad[i] = color->rgba[i] / 255.;
170 
171  if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB)
172  memcpy(yuvad, rgbad, sizeof(double) * 3);
173  else
174  ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv);
175 
176  yuvad[3] = rgbad[3];
177 
178  for (int i = 0; i < 3; i++) {
179  int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0);
180  if (draw->range == AVCOL_RANGE_MPEG) {
181  yuvad[i] *= (chroma ? 224. : 219.) / 255.;
182  yuvad[i] += (chroma ? 128. : 16.) / 255.;
183  } else if (chroma) {
184  yuvad[i] += 0.5;
185  }
186  }
187 
188  // Ensure we place the alpha appropriately for gray formats
189  if (desc->nb_components <= 2)
190  yuvad[1] = yuvad[3];
191 
192  for (i = 0; i < desc->nb_components; i++) {
193  unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5;
194  if (desc->comp[i].depth > 8)
195  color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val;
196  else
197  color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val;
198  }
199 }
200 
201 static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[],
202  int plane, int x, int y)
203 {
204  return data[plane] +
205  (y >> draw->vsub[plane]) * linesize[plane] +
206  (x >> draw->hsub[plane]) * draw->pixelstep[plane];
207 }
208 
210  uint8_t *dst[], int dst_linesize[],
211  uint8_t *src[], int src_linesize[],
212  int dst_x, int dst_y, int src_x, int src_y,
213  int w, int h)
214 {
215  int plane, y, wp, hp;
216  uint8_t *p, *q;
217 
218  for (plane = 0; plane < draw->nb_planes; plane++) {
219  p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
220  q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
221  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane];
222  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
223  for (y = 0; y < hp; y++) {
224  memcpy(q, p, wp);
225  p += src_linesize[plane];
226  q += dst_linesize[plane];
227  }
228  }
229 }
230 
232  uint8_t *dst[], int dst_linesize[],
233  int dst_x, int dst_y, int w, int h)
234 {
235  int plane, x, y, wp, hp;
236  uint8_t *p0, *p;
237  FFDrawColor color_tmp = *color;
238 
239  for (plane = 0; plane < draw->nb_planes; plane++) {
240  p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
241  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]);
242  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
243  if (!hp)
244  return;
245  p = p0;
246 
247  if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) {
248  for (x = 0; 2*x < draw->pixelstep[plane]; x++)
249  color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]);
250  }
251 
252  /* copy first line from color */
253  for (x = 0; x < wp; x++) {
254  memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]);
255  p += draw->pixelstep[plane];
256  }
257  wp *= draw->pixelstep[plane];
258  /* copy next lines from first line */
259  p = p0 + dst_linesize[plane];
260  for (y = 1; y < hp; y++) {
261  memcpy(p, p0, wp);
262  p += dst_linesize[plane];
263  }
264  }
265 }
266 
267 /**
268  * Clip interval [x; x+w[ within [0; wmax[.
269  * The resulting w may be negative if the final interval is empty.
270  * dx, if not null, return the difference between in and out value of x.
271  */
272 static void clip_interval(int wmax, int *x, int *w, int *dx)
273 {
274  if (dx)
275  *dx = 0;
276  if (*x < 0) {
277  if (dx)
278  *dx = -*x;
279  *w += *x;
280  *x = 0;
281  }
282  if (*x + *w > wmax)
283  *w = wmax - *x;
284 }
285 
286 /**
287  * Decompose w pixels starting at x
288  * into start + (w starting at x) + end
289  * with x and w aligned on multiples of 1<<sub.
290  */
291 static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
292 {
293  int mask = (1 << sub) - 1;
294 
295  *start = (-*x) & mask;
296  *x += *start;
297  *start = FFMIN(*start, *w);
298  *w -= *start;
299  *end = *w & mask;
300  *w >>= sub;
301 }
302 
303 /* If alpha is in the [ 0 ; 0x1010101 ] range,
304  then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
305  and >> 24 gives a correct rounding. */
306 static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
307  int dx, int w, unsigned hsub, int left, int right)
308 {
309  unsigned asrc = alpha * src;
310  unsigned tau = 0x1010101 - alpha;
311  int x;
312 
313  if (left) {
314  unsigned suba = (left * alpha) >> hsub;
315  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
316  dst += dx;
317  }
318  for (x = 0; x < w; x++) {
319  *dst = (*dst * tau + asrc) >> 24;
320  dst += dx;
321  }
322  if (right) {
323  unsigned suba = (right * alpha) >> hsub;
324  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
325  }
326 }
327 
328 static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
329  int dx, int w, unsigned hsub, int left, int right)
330 {
331  unsigned asrc = alpha * src;
332  unsigned tau = 0x10001 - alpha;
333  int x;
334 
335  if (left) {
336  unsigned suba = (left * alpha) >> hsub;
337  uint16_t value = AV_RL16(dst);
338  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
339  dst += dx;
340  }
341  for (x = 0; x < w; x++) {
342  uint16_t value = AV_RL16(dst);
343  AV_WL16(dst, (value * tau + asrc) >> 16);
344  dst += dx;
345  }
346  if (right) {
347  unsigned suba = (right * alpha) >> hsub;
348  uint16_t value = AV_RL16(dst);
349  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
350  }
351 }
352 
354  uint8_t *dst[], int dst_linesize[],
355  int dst_w, int dst_h,
356  int x0, int y0, int w, int h)
357 {
358  unsigned alpha, nb_planes, nb_comp, plane, comp;
359  int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
360  uint8_t *p0, *p;
361 
362  nb_comp = draw->desc->nb_components -
363  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
364 
365  /* TODO optimize if alpha = 0xFF */
366  clip_interval(dst_w, &x0, &w, NULL);
367  clip_interval(dst_h, &y0, &h, NULL);
368  if (w <= 0 || h <= 0 || !color->rgba[3])
369  return;
370  if (draw->desc->comp[0].depth <= 8) {
371  /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
372  alpha = 0x10203 * color->rgba[3] + 0x2;
373  } else {
374  /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
375  alpha = 0x101 * color->rgba[3] + 0x2;
376  }
377  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
378  nb_planes += !nb_planes;
379  for (plane = 0; plane < nb_planes; plane++) {
380  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
381  w_sub = w;
382  h_sub = h;
383  x_sub = x0;
384  y_sub = y0;
385  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
386  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
387  for (comp = 0; comp < nb_comp; comp++) {
388  const int depth = draw->desc->comp[comp].depth;
389  const int offset = draw->desc->comp[comp].offset;
390  const int index = offset / ((depth + 7) / 8);
391 
392  if (draw->desc->comp[comp].plane != plane)
393  continue;
394  p = p0 + offset;
395  if (top) {
396  if (depth <= 8) {
397  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
398  draw->pixelstep[plane], w_sub,
399  draw->hsub[plane], left, right);
400  } else {
401  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
402  draw->pixelstep[plane], w_sub,
403  draw->hsub[plane], left, right);
404  }
405  p += dst_linesize[plane];
406  }
407  if (depth <= 8) {
408  for (y = 0; y < h_sub; y++) {
409  blend_line(p, color->comp[plane].u8[index], alpha,
410  draw->pixelstep[plane], w_sub,
411  draw->hsub[plane], left, right);
412  p += dst_linesize[plane];
413  }
414  } else {
415  for (y = 0; y < h_sub; y++) {
416  blend_line16(p, color->comp[plane].u16[index], alpha,
417  draw->pixelstep[plane], w_sub,
418  draw->hsub[plane], left, right);
419  p += dst_linesize[plane];
420  }
421  }
422  if (bottom) {
423  if (depth <= 8) {
424  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
425  draw->pixelstep[plane], w_sub,
426  draw->hsub[plane], left, right);
427  } else {
428  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
429  draw->pixelstep[plane], w_sub,
430  draw->hsub[plane], left, right);
431  }
432  }
433  }
434  }
435 }
436 
437 static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
438  const uint8_t *mask, int mask_linesize, int l2depth,
439  unsigned w, unsigned h, unsigned shift, unsigned xm0)
440 {
441  unsigned xm, x, y, t = 0;
442  unsigned xmshf = 3 - l2depth;
443  unsigned xmmod = 7 >> l2depth;
444  unsigned mbits = (1 << (1 << l2depth)) - 1;
445  unsigned mmult = 255 / mbits;
446  uint16_t value = AV_RL16(dst);
447 
448  for (y = 0; y < h; y++) {
449  xm = xm0;
450  for (x = 0; x < w; x++) {
451  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
452  * mmult;
453  xm++;
454  }
455  mask += mask_linesize;
456  }
457  alpha = (t >> shift) * alpha;
458  AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
459 }
460 
461 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
462  const uint8_t *mask, int mask_linesize, int l2depth,
463  unsigned w, unsigned h, unsigned shift, unsigned xm0)
464 {
465  unsigned xm, x, y, t = 0;
466  unsigned xmshf = 3 - l2depth;
467  unsigned xmmod = 7 >> l2depth;
468  unsigned mbits = (1 << (1 << l2depth)) - 1;
469  unsigned mmult = 255 / mbits;
470 
471  for (y = 0; y < h; y++) {
472  xm = xm0;
473  for (x = 0; x < w; x++) {
474  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
475  * mmult;
476  xm++;
477  }
478  mask += mask_linesize;
479  }
480  alpha = (t >> shift) * alpha;
481  *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
482 }
483 
484 static void blend_line_hv16(uint8_t *dst, int dst_delta,
485  unsigned src, unsigned alpha,
486  const uint8_t *mask, int mask_linesize, int l2depth, int w,
487  unsigned hsub, unsigned vsub,
488  int xm, int left, int right, int hband)
489 {
490  int x;
491 
492  if (left) {
493  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
494  left, hband, hsub + vsub, xm);
495  dst += dst_delta;
496  xm += left;
497  }
498  for (x = 0; x < w; x++) {
499  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
500  1 << hsub, hband, hsub + vsub, xm);
501  dst += dst_delta;
502  xm += 1 << hsub;
503  }
504  if (right)
505  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
506  right, hband, hsub + vsub, xm);
507 }
508 
509 static void blend_line_hv(uint8_t *dst, int dst_delta,
510  unsigned src, unsigned alpha,
511  const uint8_t *mask, int mask_linesize, int l2depth, int w,
512  unsigned hsub, unsigned vsub,
513  int xm, int left, int right, int hband)
514 {
515  int x;
516 
517  if (left) {
518  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
519  left, hband, hsub + vsub, xm);
520  dst += dst_delta;
521  xm += left;
522  }
523  for (x = 0; x < w; x++) {
524  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
525  1 << hsub, hband, hsub + vsub, xm);
526  dst += dst_delta;
527  xm += 1 << hsub;
528  }
529  if (right)
530  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
531  right, hband, hsub + vsub, xm);
532 }
533 
535  uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
536  const uint8_t *mask, int mask_linesize, int mask_w, int mask_h,
537  int l2depth, unsigned endianness, int x0, int y0)
538 {
539  unsigned alpha, nb_planes, nb_comp, plane, comp;
540  int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
541  uint8_t *p0, *p;
542  const uint8_t *m;
543 
544  nb_comp = draw->desc->nb_components -
545  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
546 
547  clip_interval(dst_w, &x0, &mask_w, &xm0);
548  clip_interval(dst_h, &y0, &mask_h, &ym0);
549  mask += ym0 * mask_linesize;
550  if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
551  return;
552  if (draw->desc->comp[0].depth <= 8) {
553  /* alpha is in the [ 0 ; 0x10203 ] range,
554  alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
555  alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
556  } else {
557  alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
558  }
559  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
560  nb_planes += !nb_planes;
561  for (plane = 0; plane < nb_planes; plane++) {
562  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
563  w_sub = mask_w;
564  h_sub = mask_h;
565  x_sub = x0;
566  y_sub = y0;
567  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
568  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
569  for (comp = 0; comp < nb_comp; comp++) {
570  const int depth = draw->desc->comp[comp].depth;
571  const int offset = draw->desc->comp[comp].offset;
572  const int index = offset / ((depth + 7) / 8);
573 
574  if (draw->desc->comp[comp].plane != plane)
575  continue;
576  p = p0 + offset;
577  m = mask;
578  if (top) {
579  if (depth <= 8) {
580  blend_line_hv(p, draw->pixelstep[plane],
581  color->comp[plane].u8[index], alpha,
582  m, mask_linesize, l2depth, w_sub,
583  draw->hsub[plane], draw->vsub[plane],
584  xm0, left, right, top);
585  } else {
586  blend_line_hv16(p, draw->pixelstep[plane],
587  color->comp[plane].u16[index], alpha,
588  m, mask_linesize, l2depth, w_sub,
589  draw->hsub[plane], draw->vsub[plane],
590  xm0, left, right, top);
591  }
592  p += dst_linesize[plane];
593  m += top * mask_linesize;
594  }
595  if (depth <= 8) {
596  for (y = 0; y < h_sub; y++) {
597  blend_line_hv(p, draw->pixelstep[plane],
598  color->comp[plane].u8[index], alpha,
599  m, mask_linesize, l2depth, w_sub,
600  draw->hsub[plane], draw->vsub[plane],
601  xm0, left, right, 1 << draw->vsub[plane]);
602  p += dst_linesize[plane];
603  m += mask_linesize << draw->vsub[plane];
604  }
605  } else {
606  for (y = 0; y < h_sub; y++) {
607  blend_line_hv16(p, draw->pixelstep[plane],
608  color->comp[plane].u16[index], alpha,
609  m, mask_linesize, l2depth, w_sub,
610  draw->hsub[plane], draw->vsub[plane],
611  xm0, left, right, 1 << draw->vsub[plane]);
612  p += dst_linesize[plane];
613  m += mask_linesize << draw->vsub[plane];
614  }
615  }
616  if (bottom) {
617  if (depth <= 8) {
618  blend_line_hv(p, draw->pixelstep[plane],
619  color->comp[plane].u8[index], alpha,
620  m, mask_linesize, l2depth, w_sub,
621  draw->hsub[plane], draw->vsub[plane],
622  xm0, left, right, bottom);
623  } else {
624  blend_line_hv16(p, draw->pixelstep[plane],
625  color->comp[plane].u16[index], alpha,
626  m, mask_linesize, l2depth, w_sub,
627  draw->hsub[plane], draw->vsub[plane],
628  xm0, left, right, bottom);
629  }
630  }
631  }
632  }
633 }
634 
635 int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir,
636  int value)
637 {
638  unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max;
639 
640  if (!shift)
641  return value;
642  if (round_dir >= 0)
643  value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1);
644  return (value >> shift) << shift;
645 }
646 
648 {
649  enum AVPixelFormat i;
651  AVFilterFormats *fmts = NULL;
652  int ret;
653 
654  for (i = 0; av_pix_fmt_desc_get(i); i++)
655  if (ff_draw_init(&draw, i, flags) >= 0 &&
656  (ret = ff_add_format(&fmts, i)) < 0)
657  return NULL;
658  return fmts;
659 }
FFDrawColor
Definition: drawutils.h:50
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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
color
Definition: vf_paletteuse.c:509
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:80
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:31
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2888
subsampling_bounds
static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
Decompose w pixels starting at x into start + (w starting at x) + end with x and w aligned on multipl...
Definition: drawutils.c:291
pixdesc.h
BLUE
@ BLUE
Definition: drawutils.c:33
w
uint8_t w
Definition: llviddspenc.c:38
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:661
FFDrawColor::u16
uint16_t u16[8]
Definition: drawutils.h:54
av_csp_luma_coeffs_from_avcsp
const struct AVLumaCoefficients * av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp)
Retrieves the Luma coefficients necessary to construct a conversion matrix from an enum constant desc...
Definition: csp.c:53
chroma
static av_always_inline void chroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1635
data
const char data[16]
Definition: mxf.c:146
blend_pixel16
static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha, const uint8_t *mask, int mask_linesize, int l2depth, unsigned w, unsigned h, unsigned shift, unsigned xm0)
Definition: drawutils.c:437
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:588
AVLumaCoefficients
Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar calculations.
Definition: csp.h:44
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
hsub
static void hsub(htype *dst, const htype *src, int bins)
Definition: vf_median.c:74
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
RED
@ RED
Definition: drawutils.c:33
formats.h
colorspace.h
val
static double val(void *priv, double ch)
Definition: aeval.c:77
ff_blend_mask
void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, int l2depth, unsigned endianness, int x0, int y0)
Blend an alpha mask with an uniform color.
Definition: drawutils.c:534
AV_PIX_FMT_YUVJ411P
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:276
avassert.h
mask
static const uint16_t mask[17]
Definition: lzw.c:38
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
intreadwrite.h
MAX_PLANES
#define MAX_PLANES
Definition: ffv1.h:44
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:50
format
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 format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
AVCOL_SPC_SMPTE170M
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition: pixfmt.h:594
ff_copy_rectangle2
void ff_copy_rectangle2(FFDrawContext *draw, uint8_t *dst[], int dst_linesize[], uint8_t *src[], int src_linesize[], int dst_x, int dst_y, int src_x, int src_y, int w, int h)
Copy a rectangle from an image to another.
Definition: drawutils.c:209
FF_DRAW_PROCESS_ALPHA
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition: drawutils.h:62
blend_line_hv16
static void blend_line_hv16(uint8_t *dst, int dst_delta, unsigned src, unsigned alpha, const uint8_t *mask, int mask_linesize, int l2depth, int w, unsigned hsub, unsigned vsub, int xm, int left, int right, int hband)
Definition: drawutils.c:484
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
GREEN
@ GREEN
Definition: drawutils.c:33
AV_PIX_FMT_FLAG_ALPHA
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:147
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
ff_draw_init
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Definition: drawutils.c:151
ff_matrix_mul_3x3_vec
void ff_matrix_mul_3x3_vec(double dst[3], const double vec[3], const double mat[3][3])
Definition: colorspace.c:66
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
if
if(ret)
Definition: filter_design.txt:179
NULL
#define NULL
Definition: coverity.c:32
AVComponentDescriptor
Definition: pixdesc.h:30
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
ff_add_format
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition: formats.c:449
FFDrawColor::u8
uint8_t u8[16]
Definition: drawutils.h:55
clip_interval
static void clip_interval(int wmax, int *x, int *w, int *dx)
Clip interval [x; x+w[ within [0; wmax[.
Definition: drawutils.c:272
ALPHA
@ ALPHA
Definition: drawutils.c:33
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:627
index
int index
Definition: gxfenc.c:89
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
AV_PIX_FMT_FLAG_RGB
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:136
shift
static int shift(int a, int b)
Definition: bonk.c:257
ff_blend_rectangle
void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, int x0, int y0, int w, int h)
Blend a rectangle with an uniform color.
Definition: drawutils.c:353
FFDrawColor::comp
union FFDrawColor::@222 comp[MAX_PLANES]
ff_draw_init2
int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, enum AVColorRange range, unsigned flags)
Init a draw context.
Definition: drawutils.c:80
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
ff_fill_rectangle
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition: drawutils.c:231
AV_PIX_FMT_FLAG_BITSTREAM
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition: pixdesc.h:124
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
csp.h
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
av_bswap16
#define av_bswap16
Definition: bswap.h:31
draw
static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showcwt.c:297
ff_fill_rgb2yuv_table
void ff_fill_rgb2yuv_table(const AVLumaCoefficients *coeffs, double rgb2yuv[3][3])
Definition: colorspace.c:125
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
ff_draw_supported_pixel_formats
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:647
AVColorSpace
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:587
ff_draw_round_to_sub
int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir, int value)
Round a dimension according to subsampling.
Definition: drawutils.c:635
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:116
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
FFDrawContext
Definition: drawutils.h:35
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:590
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:644
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:156
ret
ret
Definition: filter_design.txt:187
blend_pixel
static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha, const uint8_t *mask, int mask_linesize, int l2depth, unsigned w, unsigned h, unsigned shift, unsigned xm0)
Definition: drawutils.c:461
pos
unsigned int pos
Definition: spdifenc.c:412
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
blend_line
static void blend_line(uint8_t *dst, unsigned src, unsigned alpha, int dx, int w, unsigned hsub, int left, int right)
Definition: drawutils.c:306
AV_PIX_FMT_FLAG_PLANAR
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:132
desc
const char * desc
Definition: libsvtav1.c:83
avutil.h
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
pointer_at
static uint8_t * pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], int plane, int x, int y)
Definition: drawutils.c:201
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
blend_line_hv
static void blend_line_hv(uint8_t *dst, int dst_delta, unsigned src, unsigned alpha, const uint8_t *mask, int mask_linesize, int l2depth, int w, unsigned hsub, unsigned vsub, int xm, int left, int right, int hband)
Definition: drawutils.c:509
blend_line16
static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha, int dx, int w, unsigned hsub, int left, int right)
Definition: drawutils.c:328
h
h
Definition: vp9dsp_template.c:2038
drawutils.h
AVColorRange
AVColorRange
Visual content value range.
Definition: pixfmt.h:626