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