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  depthb = db;
65  }
66 
67  if (desc->nb_components == 3)
68  rgba_map[ALPHA] = had0 ? 3 : 0;
69  }
70 
71  av_assert0(rgba_map[RED] != rgba_map[GREEN]);
72  av_assert0(rgba_map[GREEN] != rgba_map[BLUE]);
73  av_assert0(rgba_map[BLUE] != rgba_map[RED]);
74  av_assert0(rgba_map[RED] != rgba_map[ALPHA]);
75  av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]);
76  av_assert0(rgba_map[BLUE] != rgba_map[ALPHA]);
77 
78  return 0;
79 }
80 
82  enum AVColorRange range, unsigned flags)
83 {
85  const AVLumaCoefficients *luma = NULL;
86  const AVComponentDescriptor *c;
87  unsigned i, nb_planes = 0;
88  int pixelstep[MAX_PLANES] = { 0 };
89  int depthb = 0;
90 
91  if (!desc || !desc->name)
92  return AVERROR(EINVAL);
93  if (desc->flags & AV_PIX_FMT_FLAG_BE)
94  return AVERROR(ENOSYS);
96  return AVERROR(ENOSYS);
97  if (csp == AVCOL_SPC_UNSPECIFIED)
99  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp)))
100  return AVERROR(EINVAL);
107  return AVERROR(EINVAL);
108  for (i = 0; i < desc->nb_components; i++) {
109  int db;
110  c = &desc->comp[i];
111  /* for now, only 8-16 bits formats */
112  if (c->depth < 8 || c->depth > 16)
113  return AVERROR(ENOSYS);
114  if (c->plane >= MAX_PLANES)
115  return AVERROR(ENOSYS);
116  /* data must either be in the high or low bits, never middle */
117  if (c->shift && ((c->shift + c->depth) & 0x7))
118  return AVERROR(ENOSYS);
119  /* mixed >8 and <=8 depth */
120  db = (c->depth + 7) / 8;
121  if (depthb && (depthb != db))
122  return AVERROR(ENOSYS);
123  depthb = db;
124  if (db * (c->offset + 1) > 16)
125  return AVERROR(ENOSYS);
126  if (c->offset % db)
127  return AVERROR(ENOSYS);
128  /* strange interleaving */
129  if (pixelstep[c->plane] != 0 &&
130  pixelstep[c->plane] != c->step)
131  return AVERROR(ENOSYS);
132  pixelstep[c->plane] = c->step;
133  if (pixelstep[c->plane] >= 8)
134  return AVERROR(ENOSYS);
135  nb_planes = FFMAX(nb_planes, c->plane + 1);
136  }
137  memset(draw, 0, sizeof(*draw));
138  draw->desc = desc;
139  draw->format = format;
140  draw->nb_planes = nb_planes;
141  draw->range = range;
142  draw->csp = csp;
143  draw->flags = flags;
144  if (luma)
145  ff_fill_rgb2yuv_table(luma, draw->rgb2yuv);
146  memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
147  draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
148  draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
149  return 0;
150 }
151 
153 {
155 }
156 
157 void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
158 {
159  unsigned i;
160  double yuvad[4];
161  double rgbad[4];
162  const AVPixFmtDescriptor *desc = draw->desc;
163 
164  if (rgba != color->rgba)
165  memcpy(color->rgba, rgba, sizeof(color->rgba));
166 
167  memset(color->comp, 0, sizeof(color->comp));
168 
169  for (int i = 0; i < 4; i++)
170  rgbad[i] = color->rgba[i] / 255.;
171 
172  if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB)
173  memcpy(yuvad, rgbad, sizeof(double) * 3);
174  else
175  ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv);
176 
177  yuvad[3] = rgbad[3];
178 
179  for (int i = 0; i < 3; i++) {
180  int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0);
181  if (draw->range == AVCOL_RANGE_MPEG) {
182  yuvad[i] *= (chroma ? 224. : 219.) / 255.;
183  yuvad[i] += (chroma ? 128. : 16.) / 255.;
184  } else if (chroma) {
185  yuvad[i] += 0.5;
186  }
187  }
188 
189  // Ensure we place the alpha appropriately for gray formats
190  if (desc->nb_components <= 2)
191  yuvad[1] = yuvad[3];
192 
193  for (i = 0; i < desc->nb_components; i++) {
194  unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5;
195  if (desc->comp[i].depth > 8)
196  color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val;
197  else
198  color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val;
199  }
200 }
201 
202 static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[],
203  int plane, int x, int y)
204 {
205  return data[plane] +
206  (y >> draw->vsub[plane]) * linesize[plane] +
207  (x >> draw->hsub[plane]) * draw->pixelstep[plane];
208 }
209 
211  uint8_t *dst[], int dst_linesize[],
212  uint8_t *src[], int src_linesize[],
213  int dst_x, int dst_y, int src_x, int src_y,
214  int w, int h)
215 {
216  int plane, y, wp, hp;
217  uint8_t *p, *q;
218 
219  for (plane = 0; plane < draw->nb_planes; plane++) {
220  p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
221  q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
222  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane];
223  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
224  for (y = 0; y < hp; y++) {
225  memcpy(q, p, wp);
226  p += src_linesize[plane];
227  q += dst_linesize[plane];
228  }
229  }
230 }
231 
233  uint8_t *dst[], int dst_linesize[],
234  int dst_x, int dst_y, int w, int h)
235 {
236  int plane, x, y, wp, hp;
237  uint8_t *p0, *p;
238  FFDrawColor color_tmp = *color;
239 
240  for (plane = 0; plane < draw->nb_planes; plane++) {
241  p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
242  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]);
243  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
244  if (!hp)
245  return;
246  p = p0;
247 
248  if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) {
249  for (x = 0; 2*x < draw->pixelstep[plane]; x++)
250  color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]);
251  }
252 
253  /* copy first line from color */
254  for (x = 0; x < wp; x++) {
255  memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]);
256  p += draw->pixelstep[plane];
257  }
258  wp *= draw->pixelstep[plane];
259  /* copy next lines from first line */
260  p = p0 + dst_linesize[plane];
261  for (y = 1; y < hp; y++) {
262  memcpy(p, p0, wp);
263  p += dst_linesize[plane];
264  }
265  }
266 }
267 
268 /**
269  * Clip interval [x; x+w[ within [0; wmax[.
270  * The resulting w may be negative if the final interval is empty.
271  * dx, if not null, return the difference between in and out value of x.
272  */
273 static void clip_interval(int wmax, int *x, int *w, int *dx)
274 {
275  if (dx)
276  *dx = 0;
277  if (*x < 0) {
278  if (dx)
279  *dx = -*x;
280  *w += *x;
281  *x = 0;
282  }
283  if (*x + *w > wmax)
284  *w = wmax - *x;
285 }
286 
287 /**
288  * Decompose w pixels starting at x
289  * into start + (w starting at x) + end
290  * with x and w aligned on multiples of 1<<sub.
291  */
292 static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
293 {
294  int mask = (1 << sub) - 1;
295 
296  *start = (-*x) & mask;
297  *x += *start;
298  *start = FFMIN(*start, *w);
299  *w -= *start;
300  *end = *w & mask;
301  *w >>= sub;
302 }
303 
304 /* If alpha is in the [ 0 ; 0x1010101 ] range,
305  then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
306  and >> 24 gives a correct rounding. */
307 static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
308  int dx, int w, unsigned hsub, int left, int right)
309 {
310  unsigned asrc = alpha * src;
311  unsigned tau = 0x1010101 - alpha;
312  int x;
313 
314  if (left) {
315  unsigned suba = (left * alpha) >> hsub;
316  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
317  dst += dx;
318  }
319  for (x = 0; x < w; x++) {
320  *dst = (*dst * tau + asrc) >> 24;
321  dst += dx;
322  }
323  if (right) {
324  unsigned suba = (right * alpha) >> hsub;
325  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
326  }
327 }
328 
329 static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
330  int dx, int w, unsigned hsub, int left, int right)
331 {
332  unsigned asrc = alpha * src;
333  unsigned tau = 0x10001 - alpha;
334  int x;
335 
336  if (left) {
337  unsigned suba = (left * alpha) >> hsub;
338  uint16_t value = AV_RL16(dst);
339  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
340  dst += dx;
341  }
342  for (x = 0; x < w; x++) {
343  uint16_t value = AV_RL16(dst);
344  AV_WL16(dst, (value * tau + asrc) >> 16);
345  dst += dx;
346  }
347  if (right) {
348  unsigned suba = (right * alpha) >> hsub;
349  uint16_t value = AV_RL16(dst);
350  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
351  }
352 }
353 
355  uint8_t *dst[], int dst_linesize[],
356  int dst_w, int dst_h,
357  int x0, int y0, int w, int h)
358 {
359  unsigned alpha, nb_planes, nb_comp, plane, comp;
360  int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
361  uint8_t *p0, *p;
362 
363  nb_comp = draw->desc->nb_components -
364  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
365 
366  /* TODO optimize if alpha = 0xFF */
367  clip_interval(dst_w, &x0, &w, NULL);
368  clip_interval(dst_h, &y0, &h, NULL);
369  if (w <= 0 || h <= 0 || !color->rgba[3])
370  return;
371  if (draw->desc->comp[0].depth <= 8) {
372  /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
373  alpha = 0x10203 * color->rgba[3] + 0x2;
374  } else {
375  /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
376  alpha = 0x101 * color->rgba[3] + 0x2;
377  }
378  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
379  nb_planes += !nb_planes;
380  for (plane = 0; plane < nb_planes; plane++) {
381  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
382  w_sub = w;
383  h_sub = h;
384  x_sub = x0;
385  y_sub = y0;
386  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
387  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
388  for (comp = 0; comp < nb_comp; comp++) {
389  const int depth = draw->desc->comp[comp].depth;
390  const int offset = draw->desc->comp[comp].offset;
391  const int index = offset / ((depth + 7) / 8);
392 
393  if (draw->desc->comp[comp].plane != plane)
394  continue;
395  p = p0 + offset;
396  if (top) {
397  if (depth <= 8) {
398  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
399  draw->pixelstep[plane], w_sub,
400  draw->hsub[plane], left, right);
401  } else {
402  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
403  draw->pixelstep[plane], w_sub,
404  draw->hsub[plane], left, right);
405  }
406  p += dst_linesize[plane];
407  }
408  if (depth <= 8) {
409  for (y = 0; y < h_sub; y++) {
410  blend_line(p, color->comp[plane].u8[index], alpha,
411  draw->pixelstep[plane], w_sub,
412  draw->hsub[plane], left, right);
413  p += dst_linesize[plane];
414  }
415  } else {
416  for (y = 0; y < h_sub; y++) {
417  blend_line16(p, color->comp[plane].u16[index], alpha,
418  draw->pixelstep[plane], w_sub,
419  draw->hsub[plane], left, right);
420  p += dst_linesize[plane];
421  }
422  }
423  if (bottom) {
424  if (depth <= 8) {
425  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
426  draw->pixelstep[plane], w_sub,
427  draw->hsub[plane], left, right);
428  } else {
429  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
430  draw->pixelstep[plane], w_sub,
431  draw->hsub[plane], left, right);
432  }
433  }
434  }
435  }
436 }
437 
438 static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
439  const uint8_t *mask, int mask_linesize, int l2depth,
440  unsigned w, unsigned h, unsigned shift, unsigned xm0)
441 {
442  unsigned xm, x, y, t = 0;
443  unsigned xmshf = 3 - l2depth;
444  unsigned xmmod = 7 >> l2depth;
445  unsigned mbits = (1 << (1 << l2depth)) - 1;
446  unsigned mmult = 255 / mbits;
447  uint16_t value = AV_RL16(dst);
448 
449  for (y = 0; y < h; y++) {
450  xm = xm0;
451  for (x = 0; x < w; x++) {
452  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
453  * mmult;
454  xm++;
455  }
456  mask += mask_linesize;
457  }
458  alpha = (t >> shift) * alpha;
459  AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
460 }
461 
462 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
463  const uint8_t *mask, int mask_linesize, int l2depth,
464  unsigned w, unsigned h, unsigned shift, unsigned xm0)
465 {
466  unsigned xm, x, y, t = 0;
467  unsigned xmshf = 3 - l2depth;
468  unsigned xmmod = 7 >> l2depth;
469  unsigned mbits = (1 << (1 << l2depth)) - 1;
470  unsigned mmult = 255 / mbits;
471 
472  for (y = 0; y < h; y++) {
473  xm = xm0;
474  for (x = 0; x < w; x++) {
475  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
476  * mmult;
477  xm++;
478  }
479  mask += mask_linesize;
480  }
481  alpha = (t >> shift) * alpha;
482  *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
483 }
484 
485 static void blend_line_hv16(uint8_t *dst, int dst_delta,
486  unsigned src, unsigned alpha,
487  const uint8_t *mask, int mask_linesize, int l2depth, int w,
488  unsigned hsub, unsigned vsub,
489  int xm, int left, int right, int hband)
490 {
491  int x;
492 
493  if (left) {
494  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
495  left, hband, hsub + vsub, xm);
496  dst += dst_delta;
497  xm += left;
498  }
499  for (x = 0; x < w; x++) {
500  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
501  1 << hsub, hband, hsub + vsub, xm);
502  dst += dst_delta;
503  xm += 1 << hsub;
504  }
505  if (right)
506  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
507  right, hband, hsub + vsub, xm);
508 }
509 
510 static void blend_line_hv(uint8_t *dst, int dst_delta,
511  unsigned src, unsigned alpha,
512  const uint8_t *mask, int mask_linesize, int l2depth, int w,
513  unsigned hsub, unsigned vsub,
514  int xm, int left, int right, int hband)
515 {
516  int x;
517 
518  if (left) {
519  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
520  left, hband, hsub + vsub, xm);
521  dst += dst_delta;
522  xm += left;
523  }
524  for (x = 0; x < w; x++) {
525  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
526  1 << hsub, hband, hsub + vsub, xm);
527  dst += dst_delta;
528  xm += 1 << hsub;
529  }
530  if (right)
531  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
532  right, hband, hsub + vsub, xm);
533 }
534 
536  uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
537  const uint8_t *mask, int mask_linesize, int mask_w, int mask_h,
538  int l2depth, unsigned endianness, int x0, int y0)
539 {
540  unsigned alpha, nb_planes, nb_comp, plane, comp;
541  int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
542  uint8_t *p0, *p;
543  const uint8_t *m;
544 
545  nb_comp = draw->desc->nb_components -
546  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
547 
548  clip_interval(dst_w, &x0, &mask_w, &xm0);
549  clip_interval(dst_h, &y0, &mask_h, &ym0);
550  mask += ym0 * mask_linesize;
551  if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
552  return;
553  if (draw->desc->comp[0].depth <= 8) {
554  /* alpha is in the [ 0 ; 0x10203 ] range,
555  alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
556  alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
557  } else {
558  alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
559  }
560  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
561  nb_planes += !nb_planes;
562  for (plane = 0; plane < nb_planes; plane++) {
563  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
564  w_sub = mask_w;
565  h_sub = mask_h;
566  x_sub = x0;
567  y_sub = y0;
568  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
569  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
570  for (comp = 0; comp < nb_comp; comp++) {
571  const int depth = draw->desc->comp[comp].depth;
572  const int offset = draw->desc->comp[comp].offset;
573  const int index = offset / ((depth + 7) / 8);
574 
575  if (draw->desc->comp[comp].plane != plane)
576  continue;
577  p = p0 + offset;
578  m = mask;
579  if (top) {
580  if (depth <= 8) {
581  blend_line_hv(p, draw->pixelstep[plane],
582  color->comp[plane].u8[index], alpha,
583  m, mask_linesize, l2depth, w_sub,
584  draw->hsub[plane], draw->vsub[plane],
585  xm0, left, right, top);
586  } else {
587  blend_line_hv16(p, draw->pixelstep[plane],
588  color->comp[plane].u16[index], alpha,
589  m, mask_linesize, l2depth, w_sub,
590  draw->hsub[plane], draw->vsub[plane],
591  xm0, left, right, top);
592  }
593  p += dst_linesize[plane];
594  m += top * mask_linesize;
595  }
596  if (depth <= 8) {
597  for (y = 0; y < h_sub; y++) {
598  blend_line_hv(p, draw->pixelstep[plane],
599  color->comp[plane].u8[index], alpha,
600  m, mask_linesize, l2depth, w_sub,
601  draw->hsub[plane], draw->vsub[plane],
602  xm0, left, right, 1 << draw->vsub[plane]);
603  p += dst_linesize[plane];
604  m += mask_linesize << draw->vsub[plane];
605  }
606  } else {
607  for (y = 0; y < h_sub; y++) {
608  blend_line_hv16(p, draw->pixelstep[plane],
609  color->comp[plane].u16[index], alpha,
610  m, mask_linesize, l2depth, w_sub,
611  draw->hsub[plane], draw->vsub[plane],
612  xm0, left, right, 1 << draw->vsub[plane]);
613  p += dst_linesize[plane];
614  m += mask_linesize << draw->vsub[plane];
615  }
616  }
617  if (bottom) {
618  if (depth <= 8) {
619  blend_line_hv(p, draw->pixelstep[plane],
620  color->comp[plane].u8[index], alpha,
621  m, mask_linesize, l2depth, w_sub,
622  draw->hsub[plane], draw->vsub[plane],
623  xm0, left, right, bottom);
624  } else {
625  blend_line_hv16(p, draw->pixelstep[plane],
626  color->comp[plane].u16[index], alpha,
627  m, mask_linesize, l2depth, w_sub,
628  draw->hsub[plane], draw->vsub[plane],
629  xm0, left, right, bottom);
630  }
631  }
632  }
633  }
634 }
635 
636 int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir,
637  int value)
638 {
639  unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max;
640 
641  if (!shift)
642  return value;
643  if (round_dir >= 0)
644  value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1);
645  return (value >> shift) << shift;
646 }
647 
649 {
650  enum AVPixelFormat i;
652  AVFilterFormats *fmts = NULL;
653  int ret;
654 
655  for (i = 0; av_pix_fmt_desc_get(i); i++)
656  if (ff_draw_init(&draw, i, flags) >= 0 &&
657  (ret = ff_add_format(&fmts, i)) < 0)
658  return NULL;
659  return fmts;
660 }
FFDrawColor
Definition: drawutils.h:50
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
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:511
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:81
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
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:292
pixdesc.h
ALPHA
@ ALPHA
Definition: drawutils.c:33
w
uint8_t w
Definition: llviddspenc.c:38
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:686
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:58
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:1639
data
const char data[16]
Definition: mxf.c:148
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:438
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:610
AVLumaCoefficients
Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar calculations.
Definition: csp.h:48
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
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:535
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:283
GREEN
@ GREEN
Definition: drawutils.c:33
avassert.h
RED
@ RED
Definition: drawutils.c:33
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:86
intreadwrite.h
MAX_PLANES
#define MAX_PLANES
Definition: ffv1.h:43
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
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:616
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
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:210
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:485
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
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
ff_draw_init
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Definition: drawutils.c:152
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:87
if
if(ret)
Definition: filter_design.txt:179
BLUE
@ BLUE
Definition: drawutils.c:33
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:85
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:504
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:273
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:652
index
int index
Definition: gxfenc.c:90
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:261
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:354
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:81
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:232
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
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2464
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
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
draw
static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: avf_showcwt.c:449
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:256
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:648
AVColorSpace
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:609
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:636
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
FFDrawColor::comp
union FFDrawColor::@304 comp[MAX_PLANES]
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:107
FFDrawContext
Definition: drawutils.h:35
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:612
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:669
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:157
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:462
pos
unsigned int pos
Definition: spdifenc.c:414
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:307
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:79
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:202
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:482
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:510
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:329
h
h
Definition: vp9dsp_template.c:2070
drawutils.h
av_bswap16
#define av_bswap16
Definition: bswap.h:28
AVColorRange
AVColorRange
Visual content value range.
Definition: pixfmt.h:651