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/colorspace.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/pixdesc.h"
29 #include "drawutils.h"
30 #include "formats.h"
31 
32 enum { RED = 0, GREEN, BLUE, ALPHA };
33 
34 int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
35 {
37  if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
38  return AVERROR(EINVAL);
39  if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
40  return AVERROR(EINVAL);
41  av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA));
42  if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
43  rgba_map[RED] = desc->comp[0].plane;
44  rgba_map[GREEN] = desc->comp[1].plane;
45  rgba_map[BLUE] = desc->comp[2].plane;
46  rgba_map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3;
47  } else {
48  int had0 = 0;
49  unsigned depthb = 0;
50  unsigned i;
51  for (i = 0; i < desc->nb_components; i++) {
52  /* all components must have same depth in bytes */
53  unsigned db = (desc->comp[i].depth + 7) / 8;
54  unsigned pos = desc->comp[i].offset / db;
55  if (depthb && (depthb != db))
56  return AVERROR(ENOSYS);
57 
58  if (desc->comp[i].offset % db)
59  return AVERROR(ENOSYS);
60 
61  had0 |= pos == 0;
62  rgba_map[i] = pos;
63  }
64 
65  if (desc->nb_components == 3)
66  rgba_map[ALPHA] = had0 ? 3 : 0;
67  }
68 
69  av_assert0(rgba_map[RED] != rgba_map[GREEN]);
70  av_assert0(rgba_map[GREEN] != rgba_map[BLUE]);
71  av_assert0(rgba_map[BLUE] != rgba_map[RED]);
72  av_assert0(rgba_map[RED] != rgba_map[ALPHA]);
73  av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]);
74  av_assert0(rgba_map[BLUE] != rgba_map[ALPHA]);
75 
76  return 0;
77 }
78 
80 {
82  const AVComponentDescriptor *c;
83  unsigned i, nb_planes = 0;
84  int pixelstep[MAX_PLANES] = { 0 };
85  int full_range = 0;
86  int depthb = 0;
87 
88  if (!desc || !desc->name)
89  return AVERROR(EINVAL);
90  if (desc->flags & AV_PIX_FMT_FLAG_BE)
91  return AVERROR(ENOSYS);
93  return AVERROR(ENOSYS);
96  full_range = 1;
97  for (i = 0; i < desc->nb_components; i++) {
98  int db;
99  c = &desc->comp[i];
100  /* for now, only 8-16 bits formats */
101  if (c->depth < 8 || c->depth > 16)
102  return AVERROR(ENOSYS);
103  if (c->plane >= MAX_PLANES)
104  return AVERROR(ENOSYS);
105  /* data must either be in the high or low bits, never middle */
106  if (c->shift && ((c->shift + c->depth) & 0x7))
107  return AVERROR(ENOSYS);
108  /* mixed >8 and <=8 depth */
109  db = (c->depth + 7) / 8;
110  if (depthb && (depthb != db))
111  return AVERROR(ENOSYS);
112  depthb = db;
113  if (db * (c->offset + 1) > 16)
114  return AVERROR(ENOSYS);
115  if (c->offset % db)
116  return AVERROR(ENOSYS);
117  /* strange interleaving */
118  if (pixelstep[c->plane] != 0 &&
119  pixelstep[c->plane] != c->step)
120  return AVERROR(ENOSYS);
121  if (pixelstep[c->plane] == 6 &&
122  c->depth == 16)
123  return AVERROR(ENOSYS);
124  pixelstep[c->plane] = c->step;
125  if (pixelstep[c->plane] >= 8)
126  return AVERROR(ENOSYS);
127  nb_planes = FFMAX(nb_planes, c->plane + 1);
128  }
129  memset(draw, 0, sizeof(*draw));
130  draw->desc = desc;
131  draw->format = format;
132  draw->nb_planes = nb_planes;
133  draw->flags = flags;
134  draw->full_range = full_range;
135  memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
136  draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
137  draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
138  return 0;
139 }
140 
141 void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
142 {
143  unsigned i;
144  uint8_t tmp8[4];
145  const AVPixFmtDescriptor *desc = draw->desc;
146 
147  if (rgba != color->rgba)
148  memcpy(color->rgba, rgba, sizeof(color->rgba));
149 
150  memset(color->comp, 0, sizeof(color->comp));
151 
152  if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) {
153  memcpy(tmp8, rgba, sizeof(tmp8));
154  } else if (draw->nb_planes >= 2) {
155  /* assume YUV */
156  tmp8[0] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
157  tmp8[1] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
158  tmp8[2] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
159  tmp8[3] = rgba[3];
160  } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A ||
161  draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE ||
162  draw->format == AV_PIX_FMT_GRAY9LE ||
163  draw->format == AV_PIX_FMT_GRAY10LE ||
164  draw->format == AV_PIX_FMT_GRAY12LE ||
165  draw->format == AV_PIX_FMT_GRAY14LE) {
166  tmp8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
167  tmp8[1] = rgba[3];
168  } else {
170  "Color conversion not implemented for %s\n", draw->desc->name);
171  memset(color, 128, sizeof(*color));
172  return;
173  }
174 
175  for (i = 0; i < desc->nb_components; i++) {
176  if (desc->comp[i].depth > 8)
177  color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = tmp8[i] <<
178  (draw->desc->comp[i].depth + draw->desc->comp[i].shift - 8);
179  else
180  color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = tmp8[i];
181  }
182 }
183 
184 static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[],
185  int plane, int x, int y)
186 {
187  return data[plane] +
188  (y >> draw->vsub[plane]) * linesize[plane] +
189  (x >> draw->hsub[plane]) * draw->pixelstep[plane];
190 }
191 
193  uint8_t *dst[], int dst_linesize[],
194  uint8_t *src[], int src_linesize[],
195  int dst_x, int dst_y, int src_x, int src_y,
196  int w, int h)
197 {
198  int plane, y, wp, hp;
199  uint8_t *p, *q;
200 
201  for (plane = 0; plane < draw->nb_planes; plane++) {
202  p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
203  q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
204  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane];
205  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
206  for (y = 0; y < hp; y++) {
207  memcpy(q, p, wp);
208  p += src_linesize[plane];
209  q += dst_linesize[plane];
210  }
211  }
212 }
213 
215  uint8_t *dst[], int dst_linesize[],
216  int dst_x, int dst_y, int w, int h)
217 {
218  int plane, x, y, wp, hp;
219  uint8_t *p0, *p;
220  FFDrawColor color_tmp = *color;
221 
222  for (plane = 0; plane < draw->nb_planes; plane++) {
223  p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
224  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]);
225  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
226  if (!hp)
227  return;
228  p = p0;
229 
230  if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) {
231  for (x = 0; 2*x < draw->pixelstep[plane]; x++)
232  color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]);
233  }
234 
235  /* copy first line from color */
236  for (x = 0; x < wp; x++) {
237  memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]);
238  p += draw->pixelstep[plane];
239  }
240  wp *= draw->pixelstep[plane];
241  /* copy next lines from first line */
242  p = p0 + dst_linesize[plane];
243  for (y = 1; y < hp; y++) {
244  memcpy(p, p0, wp);
245  p += dst_linesize[plane];
246  }
247  }
248 }
249 
250 /**
251  * Clip interval [x; x+w[ within [0; wmax[.
252  * The resulting w may be negative if the final interval is empty.
253  * dx, if not null, return the difference between in and out value of x.
254  */
255 static void clip_interval(int wmax, int *x, int *w, int *dx)
256 {
257  if (dx)
258  *dx = 0;
259  if (*x < 0) {
260  if (dx)
261  *dx = -*x;
262  *w += *x;
263  *x = 0;
264  }
265  if (*x + *w > wmax)
266  *w = wmax - *x;
267 }
268 
269 /**
270  * Decompose w pixels starting at x
271  * into start + (w starting at x) + end
272  * with x and w aligned on multiples of 1<<sub.
273  */
274 static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
275 {
276  int mask = (1 << sub) - 1;
277 
278  *start = (-*x) & mask;
279  *x += *start;
280  *start = FFMIN(*start, *w);
281  *w -= *start;
282  *end = *w & mask;
283  *w >>= sub;
284 }
285 
286 /* If alpha is in the [ 0 ; 0x1010101 ] range,
287  then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
288  and >> 24 gives a correct rounding. */
289 static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
290  int dx, int w, unsigned hsub, int left, int right)
291 {
292  unsigned asrc = alpha * src;
293  unsigned tau = 0x1010101 - alpha;
294  int x;
295 
296  if (left) {
297  unsigned suba = (left * alpha) >> hsub;
298  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
299  dst += dx;
300  }
301  for (x = 0; x < w; x++) {
302  *dst = (*dst * tau + asrc) >> 24;
303  dst += dx;
304  }
305  if (right) {
306  unsigned suba = (right * alpha) >> hsub;
307  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
308  }
309 }
310 
311 static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
312  int dx, int w, unsigned hsub, int left, int right)
313 {
314  unsigned asrc = alpha * src;
315  unsigned tau = 0x10001 - alpha;
316  int x;
317 
318  if (left) {
319  unsigned suba = (left * alpha) >> hsub;
320  uint16_t value = AV_RL16(dst);
321  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
322  dst += dx;
323  }
324  for (x = 0; x < w; x++) {
325  uint16_t value = AV_RL16(dst);
326  AV_WL16(dst, (value * tau + asrc) >> 16);
327  dst += dx;
328  }
329  if (right) {
330  unsigned suba = (right * alpha) >> hsub;
331  uint16_t value = AV_RL16(dst);
332  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
333  }
334 }
335 
337  uint8_t *dst[], int dst_linesize[],
338  int dst_w, int dst_h,
339  int x0, int y0, int w, int h)
340 {
341  unsigned alpha, nb_planes, nb_comp, plane, comp;
342  int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
343  uint8_t *p0, *p;
344 
345  nb_comp = draw->desc->nb_components -
346  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
347 
348  /* TODO optimize if alpha = 0xFF */
349  clip_interval(dst_w, &x0, &w, NULL);
350  clip_interval(dst_h, &y0, &h, NULL);
351  if (w <= 0 || h <= 0 || !color->rgba[3])
352  return;
353  if (draw->desc->comp[0].depth <= 8) {
354  /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
355  alpha = 0x10203 * color->rgba[3] + 0x2;
356  } else {
357  /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
358  alpha = 0x101 * color->rgba[3] + 0x2;
359  }
360  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
361  nb_planes += !nb_planes;
362  for (plane = 0; plane < nb_planes; plane++) {
363  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
364  w_sub = w;
365  h_sub = h;
366  x_sub = x0;
367  y_sub = y0;
368  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
369  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
370  for (comp = 0; comp < nb_comp; comp++) {
371  const int depth = draw->desc->comp[comp].depth;
372  const int offset = draw->desc->comp[comp].offset;
373  const int index = offset / ((depth + 7) / 8);
374 
375  if (draw->desc->comp[comp].plane != plane)
376  continue;
377  p = p0 + offset;
378  if (top) {
379  if (depth <= 8) {
380  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
381  draw->pixelstep[plane], w_sub,
382  draw->hsub[plane], left, right);
383  } else {
384  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
385  draw->pixelstep[plane], w_sub,
386  draw->hsub[plane], left, right);
387  }
388  p += dst_linesize[plane];
389  }
390  if (depth <= 8) {
391  for (y = 0; y < h_sub; y++) {
392  blend_line(p, color->comp[plane].u8[index], alpha,
393  draw->pixelstep[plane], w_sub,
394  draw->hsub[plane], left, right);
395  p += dst_linesize[plane];
396  }
397  } else {
398  for (y = 0; y < h_sub; y++) {
399  blend_line16(p, color->comp[plane].u16[index], alpha,
400  draw->pixelstep[plane], w_sub,
401  draw->hsub[plane], left, right);
402  p += dst_linesize[plane];
403  }
404  }
405  if (bottom) {
406  if (depth <= 8) {
407  blend_line(p, color->comp[plane].u8[index], alpha >> 1,
408  draw->pixelstep[plane], w_sub,
409  draw->hsub[plane], left, right);
410  } else {
411  blend_line16(p, color->comp[plane].u16[index], alpha >> 1,
412  draw->pixelstep[plane], w_sub,
413  draw->hsub[plane], left, right);
414  }
415  }
416  }
417  }
418 }
419 
420 static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
421  const uint8_t *mask, int mask_linesize, int l2depth,
422  unsigned w, unsigned h, unsigned shift, unsigned xm0)
423 {
424  unsigned xm, x, y, t = 0;
425  unsigned xmshf = 3 - l2depth;
426  unsigned xmmod = 7 >> l2depth;
427  unsigned mbits = (1 << (1 << l2depth)) - 1;
428  unsigned mmult = 255 / mbits;
429  uint16_t value = AV_RL16(dst);
430 
431  for (y = 0; y < h; y++) {
432  xm = xm0;
433  for (x = 0; x < w; x++) {
434  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
435  * mmult;
436  xm++;
437  }
438  mask += mask_linesize;
439  }
440  alpha = (t >> shift) * alpha;
441  AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
442 }
443 
444 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
445  const uint8_t *mask, int mask_linesize, int l2depth,
446  unsigned w, unsigned h, unsigned shift, unsigned xm0)
447 {
448  unsigned xm, x, y, t = 0;
449  unsigned xmshf = 3 - l2depth;
450  unsigned xmmod = 7 >> l2depth;
451  unsigned mbits = (1 << (1 << l2depth)) - 1;
452  unsigned mmult = 255 / mbits;
453 
454  for (y = 0; y < h; y++) {
455  xm = xm0;
456  for (x = 0; x < w; x++) {
457  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
458  * mmult;
459  xm++;
460  }
461  mask += mask_linesize;
462  }
463  alpha = (t >> shift) * alpha;
464  *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
465 }
466 
467 static void blend_line_hv16(uint8_t *dst, int dst_delta,
468  unsigned src, unsigned alpha,
469  const uint8_t *mask, int mask_linesize, int l2depth, int w,
470  unsigned hsub, unsigned vsub,
471  int xm, int left, int right, int hband)
472 {
473  int x;
474 
475  if (left) {
476  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
477  left, hband, hsub + vsub, xm);
478  dst += dst_delta;
479  xm += left;
480  }
481  for (x = 0; x < w; x++) {
482  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
483  1 << hsub, hband, hsub + vsub, xm);
484  dst += dst_delta;
485  xm += 1 << hsub;
486  }
487  if (right)
488  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
489  right, hband, hsub + vsub, xm);
490 }
491 
492 static void blend_line_hv(uint8_t *dst, int dst_delta,
493  unsigned src, unsigned alpha,
494  const uint8_t *mask, int mask_linesize, int l2depth, int w,
495  unsigned hsub, unsigned vsub,
496  int xm, int left, int right, int hband)
497 {
498  int x;
499 
500  if (left) {
501  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
502  left, hband, hsub + vsub, xm);
503  dst += dst_delta;
504  xm += left;
505  }
506  for (x = 0; x < w; x++) {
507  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
508  1 << hsub, hband, hsub + vsub, xm);
509  dst += dst_delta;
510  xm += 1 << hsub;
511  }
512  if (right)
513  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
514  right, hband, hsub + vsub, xm);
515 }
516 
518  uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
519  const uint8_t *mask, int mask_linesize, int mask_w, int mask_h,
520  int l2depth, unsigned endianness, int x0, int y0)
521 {
522  unsigned alpha, nb_planes, nb_comp, plane, comp;
523  int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
524  uint8_t *p0, *p;
525  const uint8_t *m;
526 
527  nb_comp = draw->desc->nb_components -
528  !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
529 
530  clip_interval(dst_w, &x0, &mask_w, &xm0);
531  clip_interval(dst_h, &y0, &mask_h, &ym0);
532  mask += ym0 * mask_linesize;
533  if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
534  return;
535  if (draw->desc->comp[0].depth <= 8) {
536  /* alpha is in the [ 0 ; 0x10203 ] range,
537  alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
538  alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
539  } else {
540  alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
541  }
542  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
543  nb_planes += !nb_planes;
544  for (plane = 0; plane < nb_planes; plane++) {
545  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
546  w_sub = mask_w;
547  h_sub = mask_h;
548  x_sub = x0;
549  y_sub = y0;
550  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
551  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
552  for (comp = 0; comp < nb_comp; comp++) {
553  const int depth = draw->desc->comp[comp].depth;
554  const int offset = draw->desc->comp[comp].offset;
555  const int index = offset / ((depth + 7) / 8);
556 
557  if (draw->desc->comp[comp].plane != plane)
558  continue;
559  p = p0 + offset;
560  m = mask;
561  if (top) {
562  if (depth <= 8) {
563  blend_line_hv(p, draw->pixelstep[plane],
564  color->comp[plane].u8[index], alpha,
565  m, mask_linesize, l2depth, w_sub,
566  draw->hsub[plane], draw->vsub[plane],
567  xm0, left, right, top);
568  } else {
569  blend_line_hv16(p, draw->pixelstep[plane],
570  color->comp[plane].u16[index], alpha,
571  m, mask_linesize, l2depth, w_sub,
572  draw->hsub[plane], draw->vsub[plane],
573  xm0, left, right, top);
574  }
575  p += dst_linesize[plane];
576  m += top * mask_linesize;
577  }
578  if (depth <= 8) {
579  for (y = 0; y < h_sub; y++) {
580  blend_line_hv(p, draw->pixelstep[plane],
581  color->comp[plane].u8[index], alpha,
582  m, mask_linesize, l2depth, w_sub,
583  draw->hsub[plane], draw->vsub[plane],
584  xm0, left, right, 1 << draw->vsub[plane]);
585  p += dst_linesize[plane];
586  m += mask_linesize << draw->vsub[plane];
587  }
588  } else {
589  for (y = 0; y < h_sub; y++) {
590  blend_line_hv16(p, draw->pixelstep[plane],
591  color->comp[plane].u16[index], alpha,
592  m, mask_linesize, l2depth, w_sub,
593  draw->hsub[plane], draw->vsub[plane],
594  xm0, left, right, 1 << draw->vsub[plane]);
595  p += dst_linesize[plane];
596  m += mask_linesize << draw->vsub[plane];
597  }
598  }
599  if (bottom) {
600  if (depth <= 8) {
601  blend_line_hv(p, draw->pixelstep[plane],
602  color->comp[plane].u8[index], alpha,
603  m, mask_linesize, l2depth, w_sub,
604  draw->hsub[plane], draw->vsub[plane],
605  xm0, left, right, bottom);
606  } else {
607  blend_line_hv16(p, draw->pixelstep[plane],
608  color->comp[plane].u16[index], alpha,
609  m, mask_linesize, l2depth, w_sub,
610  draw->hsub[plane], draw->vsub[plane],
611  xm0, left, right, bottom);
612  }
613  }
614  }
615  }
616 }
617 
618 int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir,
619  int value)
620 {
621  unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max;
622 
623  if (!shift)
624  return value;
625  if (round_dir >= 0)
626  value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1);
627  return (value >> shift) << shift;
628 }
629 
631 {
632  enum AVPixelFormat i;
633  FFDrawContext draw;
634  AVFilterFormats *fmts = NULL;
635  int ret;
636 
637  for (i = 0; av_pix_fmt_desc_get(i); i++)
638  if (ff_draw_init(&draw, i, flags) >= 0 &&
639  (ret = ff_add_format(&fmts, i)) < 0)
640  return NULL;
641  return fmts;
642 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
FFDrawColor
Definition: drawutils.h:48
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
RED
@ RED
Definition: drawutils.c:32
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
RGB_TO_U_JPEG
#define RGB_TO_U_JPEG(r1, g1, b1)
Definition: colorspace.h:114
color
Definition: vf_paletteuse.c:599
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:85
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:31
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2660
RGB_TO_U_CCIR
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
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:274
pixdesc.h
FFDrawContext::hsub_max
uint8_t hsub_max
Definition: drawutils.h:42
index
fg index
Definition: ffmpeg_filter.c:167
FFDrawContext::desc
const struct AVPixFmtDescriptor * desc
Definition: drawutils.h:36
w
uint8_t w
Definition: llviddspenc.c:38
FFDrawColor::u16
uint16_t u16[8]
Definition: drawutils.h:52
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:57
AVPixFmtDescriptor::name
const char * name
Definition: pixdesc.h:70
data
const char data[16]
Definition: mxf.c:143
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:420
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FFDrawContext::nb_planes
unsigned nb_planes
Definition: drawutils.h:38
AV_PIX_FMT_GRAY10LE
@ AV_PIX_FMT_GRAY10LE
Y , 10bpp, little-endian.
Definition: pixfmt.h:288
FFDrawContext::pixelstep
int pixelstep[MAX_PLANES]
Definition: drawutils.h:39
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
FFDrawContext::vsub_max
uint8_t vsub_max
Definition: drawutils.h:43
AV_PIX_FMT_GRAY9LE
@ AV_PIX_FMT_GRAY9LE
Y , 9bpp, little-endian.
Definition: pixfmt.h:306
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:517
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:248
avassert.h
colorspace.h
RGB_TO_V_JPEG
#define RGB_TO_V_JPEG(r1, g1, b1)
Definition: colorspace.h:118
mask
static const uint16_t mask[17]
Definition: lzw.c:38
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
full_range
bool full_range
Definition: hwcontext_videotoolbox.c:42
intreadwrite.h
MAX_PLANES
#define MAX_PLANES
Definition: ffv1.h:48
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:51
FFDrawContext::vsub
uint8_t vsub[MAX_PLANES]
Definition: drawutils.h:41
RGB_TO_Y_CCIR
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
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:192
FF_DRAW_PROCESS_ALPHA
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition: drawutils.h:60
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:467
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AV_PIX_FMT_FLAG_ALPHA
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:147
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
ff_draw_init
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:79
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
AV_PIX_FMT_GRAY8A
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:136
NULL
#define NULL
Definition: coverity.c:32
AVComponentDescriptor
Definition: pixdesc.h:30
AVPixFmtDescriptor::nb_components
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:71
AV_PIX_FMT_YA16LE
@ AV_PIX_FMT_YA16LE
16 bits gray, 16 bits alpha (little-endian)
Definition: pixfmt.h:203
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
AVComponentDescriptor::plane
int plane
Which of the 4 planes contains the component.
Definition: pixdesc.h:34
RGB_TO_V_CCIR
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
src
#define src
Definition: vp8dsp.c:255
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:420
FFDrawColor::u8
uint8_t u8[16]
Definition: drawutils.h:53
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
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:255
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:94
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
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:336
FFDrawContext::format
enum AVPixelFormat format
Definition: drawutils.h:37
GREEN
@ GREEN
Definition: drawutils.c:32
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
AV_PIX_FMT_GRAY12LE
@ AV_PIX_FMT_GRAY12LE
Y , 12bpp, little-endian.
Definition: pixfmt.h:286
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:214
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
format
ofilter format
Definition: ffmpeg_filter.c:172
BLUE
@ BLUE
Definition: drawutils.c:32
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
av_bswap16
#define av_bswap16
Definition: bswap.h:31
AVComponentDescriptor::shift
int shift
Number of least significant bits that must be shifted away to get the value.
Definition: pixdesc.h:52
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
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:630
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:618
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:116
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
FFDrawContext
Definition: drawutils.h:35
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:141
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:444
ALPHA
@ ALPHA
Definition: drawutils.c:32
pos
unsigned int pos
Definition: spdifenc.c:412
FFDrawContext::hsub
uint8_t hsub[MAX_PLANES]
Definition: drawutils.h:40
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:289
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
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
shift
static int shift(int a, int b)
Definition: sonic.c:83
desc
const char * desc
Definition: libsvtav1.c:79
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:98
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
AV_PIX_FMT_GRAY14LE
@ AV_PIX_FMT_GRAY14LE
Y , 14bpp, little-endian.
Definition: pixfmt.h:328
pointer_at
static uint8_t * pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], int plane, int x, int y)
Definition: drawutils.c:184
FFDrawContext::flags
unsigned flags
Definition: drawutils.h:45
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:34
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
blend_line_hv
static void blend_line_hv(uint8_t *dst, int dst_delta, unsigned src, unsigned alpha, const uint8_t *mask, int mask_linesize, int l2depth, int w, unsigned hsub, unsigned vsub, int xm, int left, int right, int hband)
Definition: drawutils.c:492
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
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:311
h
h
Definition: vp9dsp_template.c:2038
drawutils.h
RGB_TO_Y_JPEG
#define RGB_TO_Y_JPEG(r, g, b)
Definition: colorspace.h:110
FFDrawColor::comp
union FFDrawColor::@202 comp[MAX_PLANES]
FFDrawContext::full_range
int full_range
Definition: drawutils.h:44
AVComponentDescriptor::offset
int offset
Number of elements before the component of the first pixel.
Definition: pixdesc.h:46