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