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/mem.h"
29 #include "libavutil/pixdesc.h"
30 #include "drawutils.h"
31 #include "formats.h"
32 
33 enum { RED = 0, GREEN, BLUE, ALPHA };
34 
36 {
37  switch (pix_fmt) {
38  case AV_PIX_FMT_0RGB:
39  case AV_PIX_FMT_ARGB: rgba_map[ALPHA] = 0; rgba_map[RED ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break;
40  case AV_PIX_FMT_0BGR:
41  case AV_PIX_FMT_ABGR: rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED ] = 3; break;
42  case AV_PIX_FMT_RGB48LE:
43  case AV_PIX_FMT_RGB48BE:
46  case AV_PIX_FMT_RGB0:
47  case AV_PIX_FMT_RGBA:
48  case AV_PIX_FMT_RGB24: rgba_map[RED ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break;
49  case AV_PIX_FMT_BGR48LE:
50  case AV_PIX_FMT_BGR48BE:
53  case AV_PIX_FMT_BGRA:
54  case AV_PIX_FMT_BGR0:
55  case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break;
56  case AV_PIX_FMT_GBRP9LE:
57  case AV_PIX_FMT_GBRP9BE:
66  case AV_PIX_FMT_GBRAP:
73  case AV_PIX_FMT_GBRP: rgba_map[GREEN] = 0; rgba_map[BLUE ] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break;
74  default: /* unsupported */
75  return AVERROR(EINVAL);
76  }
77  return 0;
78 }
79 
80 int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4],
81  enum AVPixelFormat pix_fmt, uint8_t rgba_color[4],
82  int *is_packed_rgba, uint8_t rgba_map_ptr[4])
83 {
84  uint8_t rgba_map[4] = {0};
85  int i;
87  int hsub;
88 
89  av_assert0(pix_desc);
90 
91  hsub = pix_desc->log2_chroma_w;
92 
93  *is_packed_rgba = ff_fill_rgba_map(rgba_map, pix_fmt) >= 0;
94 
95  if (*is_packed_rgba) {
96  pixel_step[0] = (av_get_bits_per_pixel(pix_desc))>>3;
97  for (i = 0; i < 4; i++)
98  dst_color[rgba_map[i]] = rgba_color[i];
99 
100  line[0] = av_malloc_array(w, pixel_step[0]);
101  if (!line[0])
102  return AVERROR(ENOMEM);
103  for (i = 0; i < w; i++)
104  memcpy(line[0] + i * pixel_step[0], dst_color, pixel_step[0]);
105  if (rgba_map_ptr)
106  memcpy(rgba_map_ptr, rgba_map, sizeof(rgba_map[0]) * 4);
107  } else {
108  int plane;
109 
110  dst_color[0] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]);
111  dst_color[1] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
112  dst_color[2] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
113  dst_color[3] = rgba_color[3];
114 
115  for (plane = 0; plane < 4; plane++) {
116  int line_size;
117  int hsub1 = (plane == 1 || plane == 2) ? hsub : 0;
118 
119  pixel_step[plane] = 1;
120  line_size = AV_CEIL_RSHIFT(w, hsub1) * pixel_step[plane];
121  line[plane] = av_malloc(line_size);
122  if (!line[plane]) {
123  while(plane && line[plane-1])
124  av_freep(&line[--plane]);
125  return AVERROR(ENOMEM);
126  }
127  memset(line[plane], dst_color[plane], line_size);
128  }
129  }
130 
131  return 0;
132 }
133 
134 void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4],
135  uint8_t *src[4], int pixelstep[4],
136  int hsub, int vsub, int x, int y, int w, int h)
137 {
138  int i, plane;
139  uint8_t *p;
140 
141  for (plane = 0; plane < 4 && dst[plane]; plane++) {
142  int hsub1 = plane == 1 || plane == 2 ? hsub : 0;
143  int vsub1 = plane == 1 || plane == 2 ? vsub : 0;
144  int width = AV_CEIL_RSHIFT(w, hsub1);
145  int height = AV_CEIL_RSHIFT(h, vsub1);
146 
147  p = dst[plane] + (y >> vsub1) * dst_linesize[plane];
148  for (i = 0; i < height; i++) {
149  memcpy(p + (x >> hsub1) * pixelstep[plane],
150  src[plane], width * pixelstep[plane]);
151  p += dst_linesize[plane];
152  }
153  }
154 }
155 
156 void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4],
157  uint8_t *src[4], int src_linesize[4], int pixelstep[4],
158  int hsub, int vsub, int x, int y, int y2, int w, int h)
159 {
160  int i, plane;
161  uint8_t *p;
162 
163  for (plane = 0; plane < 4 && dst[plane]; plane++) {
164  int hsub1 = plane == 1 || plane == 2 ? hsub : 0;
165  int vsub1 = plane == 1 || plane == 2 ? vsub : 0;
166  int width = AV_CEIL_RSHIFT(w, hsub1);
167  int height = AV_CEIL_RSHIFT(h, vsub1);
168 
169  p = dst[plane] + (y >> vsub1) * dst_linesize[plane];
170  for (i = 0; i < height; i++) {
171  memcpy(p + (x >> hsub1) * pixelstep[plane],
172  src[plane] + src_linesize[plane]*(i+(y2>>vsub1)), width * pixelstep[plane]);
173  p += dst_linesize[plane];
174  }
175  }
176 }
177 
179 {
181  const AVComponentDescriptor *c;
182  unsigned i, nb_planes = 0;
183  int pixelstep[MAX_PLANES] = { 0 };
184  int full_range = 0;
185 
186  if (!desc || !desc->name)
187  return AVERROR(EINVAL);
189  return AVERROR(ENOSYS);
191  return AVERROR(ENOSYS);
194  full_range = 1;
195  for (i = 0; i < desc->nb_components; i++) {
196  c = &desc->comp[i];
197  /* for now, only 8-16 bits formats */
198  if (c->depth < 8 || c->depth > 16)
199  return AVERROR(ENOSYS);
200  if (desc->flags & AV_PIX_FMT_FLAG_BE)
201  return AVERROR(ENOSYS);
202  if (c->plane >= MAX_PLANES)
203  return AVERROR(ENOSYS);
204  /* strange interleaving */
205  if (pixelstep[c->plane] != 0 &&
206  pixelstep[c->plane] != c->step)
207  return AVERROR(ENOSYS);
208  if (pixelstep[c->plane] == 6 &&
209  c->depth == 16)
210  return AVERROR(ENOSYS);
211  pixelstep[c->plane] = c->step;
212  if (pixelstep[c->plane] >= 8)
213  return AVERROR(ENOSYS);
214  nb_planes = FFMAX(nb_planes, c->plane + 1);
215  }
216  memset(draw, 0, sizeof(*draw));
217  draw->desc = desc;
218  draw->format = format;
219  draw->nb_planes = nb_planes;
220  draw->flags = flags;
221  draw->full_range = full_range;
222  memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
223  draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
224  draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
225  for (i = 0; i < (desc->nb_components - !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(flags & FF_DRAW_PROCESS_ALPHA))); i++)
226  draw->comp_mask[desc->comp[i].plane] |=
227  1 << desc->comp[i].offset;
228  return 0;
229 }
230 
232 {
233  unsigned i;
234  uint8_t rgba_map[4];
235 
236  if (rgba != color->rgba)
237  memcpy(color->rgba, rgba, sizeof(color->rgba));
238  if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) &&
239  ff_fill_rgba_map(rgba_map, draw->format) >= 0) {
240  if (draw->nb_planes == 1) {
241  for (i = 0; i < 4; i++) {
242  color->comp[0].u8[rgba_map[i]] = rgba[i];
243  if (draw->desc->comp[rgba_map[i]].depth > 8) {
244  color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8;
245  }
246  }
247  } else {
248  for (i = 0; i < 4; i++) {
249  color->comp[rgba_map[i]].u8[0] = rgba[i];
250  if (draw->desc->comp[rgba_map[i]].depth > 8)
251  color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8);
252  }
253  }
254  } else if (draw->nb_planes >= 2) {
255  /* assume YUV */
256  const AVPixFmtDescriptor *desc = draw->desc;
257  color->comp[desc->comp[0].plane].u8[desc->comp[0].offset] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
258  color->comp[desc->comp[1].plane].u8[desc->comp[1].offset] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
259  color->comp[desc->comp[2].plane].u8[desc->comp[2].offset] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
260  color->comp[3].u8[0] = rgba[3];
261 #define EXPAND(compn) \
262  if (desc->comp[compn].depth > 8) \
263  color->comp[desc->comp[compn].plane].u16[desc->comp[compn].offset] = \
264  color->comp[desc->comp[compn].plane].u8[desc->comp[compn].offset] << \
265  (draw->desc->comp[compn].depth + draw->desc->comp[compn].shift - 8)
266  EXPAND(3);
267  EXPAND(2);
268  EXPAND(1);
269  EXPAND(0);
270  } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A ||
271  draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE ||
272  draw->format == AV_PIX_FMT_GRAY9LE ||
273  draw->format == AV_PIX_FMT_GRAY10LE ||
274  draw->format == AV_PIX_FMT_GRAY12LE ||
275  draw->format == AV_PIX_FMT_GRAY14LE) {
276  const AVPixFmtDescriptor *desc = draw->desc;
277  color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
278  EXPAND(0);
279  color->comp[1].u8[0] = rgba[3];
280  EXPAND(1);
281  } else {
283  "Color conversion not implemented for %s\n", draw->desc->name);
284  memset(color, 128, sizeof(*color));
285  }
286 }
287 
288 static uint8_t *pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[],
289  int plane, int x, int y)
290 {
291  return data[plane] +
292  (y >> draw->vsub[plane]) * linesize[plane] +
293  (x >> draw->hsub[plane]) * draw->pixelstep[plane];
294 }
295 
297  uint8_t *dst[], int dst_linesize[],
298  uint8_t *src[], int src_linesize[],
299  int dst_x, int dst_y, int src_x, int src_y,
300  int w, int h)
301 {
302  int plane, y, wp, hp;
303  uint8_t *p, *q;
304 
305  for (plane = 0; plane < draw->nb_planes; plane++) {
306  p = pointer_at(draw, src, src_linesize, plane, src_x, src_y);
307  q = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
308  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]) * draw->pixelstep[plane];
309  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
310  for (y = 0; y < hp; y++) {
311  memcpy(q, p, wp);
312  p += src_linesize[plane];
313  q += dst_linesize[plane];
314  }
315  }
316 }
317 
319  uint8_t *dst[], int dst_linesize[],
320  int dst_x, int dst_y, int w, int h)
321 {
322  int plane, x, y, wp, hp;
323  uint8_t *p0, *p;
324  FFDrawColor color_tmp = *color;
325 
326  for (plane = 0; plane < draw->nb_planes; plane++) {
327  p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
328  wp = AV_CEIL_RSHIFT(w, draw->hsub[plane]);
329  hp = AV_CEIL_RSHIFT(h, draw->vsub[plane]);
330  if (!hp)
331  return;
332  p = p0;
333 
334  if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) {
335  for (x = 0; 2*x < draw->pixelstep[plane]; x++)
336  color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]);
337  }
338 
339  /* copy first line from color */
340  for (x = 0; x < wp; x++) {
341  memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]);
342  p += draw->pixelstep[plane];
343  }
344  wp *= draw->pixelstep[plane];
345  /* copy next lines from first line */
346  p = p0 + dst_linesize[plane];
347  for (y = 1; y < hp; y++) {
348  memcpy(p, p0, wp);
349  p += dst_linesize[plane];
350  }
351  }
352 }
353 
354 /**
355  * Clip interval [x; x+w[ within [0; wmax[.
356  * The resulting w may be negative if the final interval is empty.
357  * dx, if not null, return the difference between in and out value of x.
358  */
359 static void clip_interval(int wmax, int *x, int *w, int *dx)
360 {
361  if (dx)
362  *dx = 0;
363  if (*x < 0) {
364  if (dx)
365  *dx = -*x;
366  *w += *x;
367  *x = 0;
368  }
369  if (*x + *w > wmax)
370  *w = wmax - *x;
371 }
372 
373 /**
374  * Decompose w pixels starting at x
375  * into start + (w starting at x) + end
376  * with x and w aligned on multiples of 1<<sub.
377  */
378 static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end)
379 {
380  int mask = (1 << sub) - 1;
381 
382  *start = (-*x) & mask;
383  *x += *start;
384  *start = FFMIN(*start, *w);
385  *w -= *start;
386  *end = *w & mask;
387  *w >>= sub;
388 }
389 
390 static int component_used(FFDrawContext *draw, int plane, int comp)
391 {
392  return (draw->comp_mask[plane] >> comp) & 1;
393 }
394 
395 /* If alpha is in the [ 0 ; 0x1010101 ] range,
396  then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
397  and >> 24 gives a correct rounding. */
398 static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
399  int dx, int w, unsigned hsub, int left, int right)
400 {
401  unsigned asrc = alpha * src;
402  unsigned tau = 0x1010101 - alpha;
403  int x;
404 
405  if (left) {
406  unsigned suba = (left * alpha) >> hsub;
407  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
408  dst += dx;
409  }
410  for (x = 0; x < w; x++) {
411  *dst = (*dst * tau + asrc) >> 24;
412  dst += dx;
413  }
414  if (right) {
415  unsigned suba = (right * alpha) >> hsub;
416  *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
417  }
418 }
419 
420 static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
421  int dx, int w, unsigned hsub, int left, int right)
422 {
423  unsigned asrc = alpha * src;
424  unsigned tau = 0x10001 - alpha;
425  int x;
426 
427  if (left) {
428  unsigned suba = (left * alpha) >> hsub;
429  uint16_t value = AV_RL16(dst);
430  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
431  dst += dx;
432  }
433  for (x = 0; x < w; x++) {
434  uint16_t value = AV_RL16(dst);
435  AV_WL16(dst, (value * tau + asrc) >> 16);
436  dst += dx;
437  }
438  if (right) {
439  unsigned suba = (right * alpha) >> hsub;
440  uint16_t value = AV_RL16(dst);
441  AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
442  }
443 }
444 
446  uint8_t *dst[], int dst_linesize[],
447  int dst_w, int dst_h,
448  int x0, int y0, int w, int h)
449 {
450  unsigned alpha, nb_planes, nb_comp, plane, comp;
451  int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
452  uint8_t *p0, *p;
453 
454  /* TODO optimize if alpha = 0xFF */
455  clip_interval(dst_w, &x0, &w, NULL);
456  clip_interval(dst_h, &y0, &h, NULL);
457  if (w <= 0 || h <= 0 || !color->rgba[3])
458  return;
459  if (draw->desc->comp[0].depth <= 8) {
460  /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
461  alpha = 0x10203 * color->rgba[3] + 0x2;
462  } else {
463  /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
464  alpha = 0x101 * color->rgba[3] + 0x2;
465  }
466  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
467  nb_planes += !nb_planes;
468  for (plane = 0; plane < nb_planes; plane++) {
469  nb_comp = draw->pixelstep[plane];
470  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
471  w_sub = w;
472  h_sub = h;
473  x_sub = x0;
474  y_sub = y0;
475  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
476  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
477  for (comp = 0; comp < nb_comp; comp++) {
478  const int depth = draw->desc->comp[comp].depth;
479 
480  if (!component_used(draw, plane, comp))
481  continue;
482  p = p0 + comp;
483  if (top) {
484  if (depth <= 8) {
485  blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
486  draw->pixelstep[plane], w_sub,
487  draw->hsub[plane], left, right);
488  } else {
489  blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
490  draw->pixelstep[plane], w_sub,
491  draw->hsub[plane], left, right);
492  }
493  p += dst_linesize[plane];
494  }
495  if (depth <= 8) {
496  for (y = 0; y < h_sub; y++) {
497  blend_line(p, color->comp[plane].u8[comp], alpha,
498  draw->pixelstep[plane], w_sub,
499  draw->hsub[plane], left, right);
500  p += dst_linesize[plane];
501  }
502  } else {
503  for (y = 0; y < h_sub; y++) {
504  blend_line16(p, color->comp[plane].u16[comp], alpha,
505  draw->pixelstep[plane], w_sub,
506  draw->hsub[plane], left, right);
507  p += dst_linesize[plane];
508  }
509  }
510  if (bottom) {
511  if (depth <= 8) {
512  blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
513  draw->pixelstep[plane], w_sub,
514  draw->hsub[plane], left, right);
515  } else {
516  blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
517  draw->pixelstep[plane], w_sub,
518  draw->hsub[plane], left, right);
519  }
520  }
521  }
522  }
523 }
524 
525 static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
526  const uint8_t *mask, int mask_linesize, int l2depth,
527  unsigned w, unsigned h, unsigned shift, unsigned xm0)
528 {
529  unsigned xm, x, y, t = 0;
530  unsigned xmshf = 3 - l2depth;
531  unsigned xmmod = 7 >> l2depth;
532  unsigned mbits = (1 << (1 << l2depth)) - 1;
533  unsigned mmult = 255 / mbits;
534  uint16_t value = AV_RL16(dst);
535 
536  for (y = 0; y < h; y++) {
537  xm = xm0;
538  for (x = 0; x < w; x++) {
539  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
540  * mmult;
541  xm++;
542  }
543  mask += mask_linesize;
544  }
545  alpha = (t >> shift) * alpha;
546  AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
547 }
548 
549 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
550  const uint8_t *mask, int mask_linesize, int l2depth,
551  unsigned w, unsigned h, unsigned shift, unsigned xm0)
552 {
553  unsigned xm, x, y, t = 0;
554  unsigned xmshf = 3 - l2depth;
555  unsigned xmmod = 7 >> l2depth;
556  unsigned mbits = (1 << (1 << l2depth)) - 1;
557  unsigned mmult = 255 / mbits;
558 
559  for (y = 0; y < h; y++) {
560  xm = xm0;
561  for (x = 0; x < w; x++) {
562  t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
563  * mmult;
564  xm++;
565  }
566  mask += mask_linesize;
567  }
568  alpha = (t >> shift) * alpha;
569  *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
570 }
571 
572 static void blend_line_hv16(uint8_t *dst, int dst_delta,
573  unsigned src, unsigned alpha,
574  const uint8_t *mask, int mask_linesize, int l2depth, int w,
575  unsigned hsub, unsigned vsub,
576  int xm, int left, int right, int hband)
577 {
578  int x;
579 
580  if (left) {
581  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
582  left, hband, hsub + vsub, xm);
583  dst += dst_delta;
584  xm += left;
585  }
586  for (x = 0; x < w; x++) {
587  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
588  1 << hsub, hband, hsub + vsub, xm);
589  dst += dst_delta;
590  xm += 1 << hsub;
591  }
592  if (right)
593  blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
594  right, hband, hsub + vsub, xm);
595 }
596 
597 static void blend_line_hv(uint8_t *dst, int dst_delta,
598  unsigned src, unsigned alpha,
599  const uint8_t *mask, int mask_linesize, int l2depth, int w,
600  unsigned hsub, unsigned vsub,
601  int xm, int left, int right, int hband)
602 {
603  int x;
604 
605  if (left) {
606  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
607  left, hband, hsub + vsub, xm);
608  dst += dst_delta;
609  xm += left;
610  }
611  for (x = 0; x < w; x++) {
612  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
613  1 << hsub, hband, hsub + vsub, xm);
614  dst += dst_delta;
615  xm += 1 << hsub;
616  }
617  if (right)
618  blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
619  right, hband, hsub + vsub, xm);
620 }
621 
623  uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
624  const uint8_t *mask, int mask_linesize, int mask_w, int mask_h,
625  int l2depth, unsigned endianness, int x0, int y0)
626 {
627  unsigned alpha, nb_planes, nb_comp, plane, comp;
628  int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
629  uint8_t *p0, *p;
630  const uint8_t *m;
631 
632  clip_interval(dst_w, &x0, &mask_w, &xm0);
633  clip_interval(dst_h, &y0, &mask_h, &ym0);
634  mask += ym0 * mask_linesize;
635  if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
636  return;
637  if (draw->desc->comp[0].depth <= 8) {
638  /* alpha is in the [ 0 ; 0x10203 ] range,
639  alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
640  alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
641  } else {
642  alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
643  }
644  nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA));
645  nb_planes += !nb_planes;
646  for (plane = 0; plane < nb_planes; plane++) {
647  nb_comp = draw->pixelstep[plane];
648  p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
649  w_sub = mask_w;
650  h_sub = mask_h;
651  x_sub = x0;
652  y_sub = y0;
653  subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
654  subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
655  for (comp = 0; comp < nb_comp; comp++) {
656  const int depth = draw->desc->comp[comp].depth;
657 
658  if (!component_used(draw, plane, comp))
659  continue;
660  p = p0 + comp;
661  m = mask;
662  if (top) {
663  if (depth <= 8) {
664  blend_line_hv(p, draw->pixelstep[plane],
665  color->comp[plane].u8[comp], alpha,
666  m, mask_linesize, l2depth, w_sub,
667  draw->hsub[plane], draw->vsub[plane],
668  xm0, left, right, top);
669  } else {
670  blend_line_hv16(p, draw->pixelstep[plane],
671  color->comp[plane].u16[comp], alpha,
672  m, mask_linesize, l2depth, w_sub,
673  draw->hsub[plane], draw->vsub[plane],
674  xm0, left, right, top);
675  }
676  p += dst_linesize[plane];
677  m += top * mask_linesize;
678  }
679  if (depth <= 8) {
680  for (y = 0; y < h_sub; y++) {
681  blend_line_hv(p, draw->pixelstep[plane],
682  color->comp[plane].u8[comp], alpha,
683  m, mask_linesize, l2depth, w_sub,
684  draw->hsub[plane], draw->vsub[plane],
685  xm0, left, right, 1 << draw->vsub[plane]);
686  p += dst_linesize[plane];
687  m += mask_linesize << draw->vsub[plane];
688  }
689  } else {
690  for (y = 0; y < h_sub; y++) {
691  blend_line_hv16(p, draw->pixelstep[plane],
692  color->comp[plane].u16[comp], alpha,
693  m, mask_linesize, l2depth, w_sub,
694  draw->hsub[plane], draw->vsub[plane],
695  xm0, left, right, 1 << draw->vsub[plane]);
696  p += dst_linesize[plane];
697  m += mask_linesize << draw->vsub[plane];
698  }
699  }
700  if (bottom) {
701  if (depth <= 8) {
702  blend_line_hv(p, draw->pixelstep[plane],
703  color->comp[plane].u8[comp], alpha,
704  m, mask_linesize, l2depth, w_sub,
705  draw->hsub[plane], draw->vsub[plane],
706  xm0, left, right, bottom);
707  } else {
708  blend_line_hv16(p, draw->pixelstep[plane],
709  color->comp[plane].u16[comp], alpha,
710  m, mask_linesize, l2depth, w_sub,
711  draw->hsub[plane], draw->vsub[plane],
712  xm0, left, right, bottom);
713  }
714  }
715  }
716  }
717 }
718 
719 int ff_draw_round_to_sub(FFDrawContext *draw, int sub_dir, int round_dir,
720  int value)
721 {
722  unsigned shift = sub_dir ? draw->vsub_max : draw->hsub_max;
723 
724  if (!shift)
725  return value;
726  if (round_dir >= 0)
727  value += round_dir ? (1 << shift) - 1 : 1 << (shift - 1);
728  return (value >> shift) << shift;
729 }
730 
732 {
733  enum AVPixelFormat i;
734  FFDrawContext draw;
735  AVFilterFormats *fmts = NULL;
736  int ret;
737 
738  for (i = 0; av_pix_fmt_desc_get(i); i++)
739  if (ff_draw_init(&draw, i, flags) >= 0 &&
740  (ret = ff_add_format(&fmts, i)) < 0)
741  return NULL;
742  return fmts;
743 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
FFDrawColor
Definition: drawutils.h:62
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
AV_PIX_FMT_BGR48LE
@ AV_PIX_FMT_BGR48LE
packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as lit...
Definition: pixfmt.h:149
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
AV_PIX_FMT_BGRA64BE
@ AV_PIX_FMT_BGRA64BE
packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:207
color
Definition: vf_paletteuse.c:582
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:83
AV_PIX_FMT_GBRP16BE
@ AV_PIX_FMT_GBRP16BE
planar GBR 4:4:4 48bpp, big-endian
Definition: pixfmt.h:174
AV_PIX_FMT_GBRP10BE
@ AV_PIX_FMT_GBRP10BE
planar GBR 4:4:4 30bpp, big-endian
Definition: pixfmt.h:172
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2549
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:378
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
pixdesc.h
FFDrawContext::hsub_max
uint8_t hsub_max
Definition: drawutils.h:56
AV_PIX_FMT_RGBA64BE
@ AV_PIX_FMT_RGBA64BE
packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:205
FFDrawContext::desc
const struct AVPixFmtDescriptor * desc
Definition: drawutils.h:49
w
uint8_t w
Definition: llviddspenc.c:38
FFDrawColor::u16
uint16_t u16[8]
Definition: drawutils.h:66
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:58
AVPixFmtDescriptor::name
const char * name
Definition: pixdesc.h:82
data
const char data[16]
Definition: mxf.c:91
AV_PIX_FMT_P010BE
@ AV_PIX_FMT_P010BE
like NV12, with 10bpp per component, data in the high bits, zeros in the low bits,...
Definition: pixfmt.h:285
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:525
AV_PIX_FMT_GBRP14BE
@ AV_PIX_FMT_GBRP14BE
planar GBR 4:4:4 42bpp, big-endian
Definition: pixfmt.h:256
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
av_get_bits_per_pixel
int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel used by the pixel format described by pixdesc.
Definition: pixdesc.c:2501
FFDrawContext::nb_planes
unsigned nb_planes
Definition: drawutils.h:51
AV_PIX_FMT_GRAY10LE
@ AV_PIX_FMT_GRAY10LE
Y , 10bpp, little-endian.
Definition: pixfmt.h:298
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
FFDrawContext::pixelstep
int pixelstep[MAX_PLANES]
Definition: drawutils.h:52
hsub
static void hsub(htype *dst, const htype *src, int bins)
Definition: vf_median.c:75
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
formats.h
ff_copy_rectangle
void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4], uint8_t *src[4], int src_linesize[4], int pixelstep[4], int hsub, int vsub, int x, int y, int y2, int w, int h)
Definition: drawutils.c:156
AV_PIX_FMT_GBRAP12LE
@ AV_PIX_FMT_GBRAP12LE
planar GBR 4:4:4:4 48bpp, little-endian
Definition: pixfmt.h:288
FFDrawContext::vsub_max
uint8_t vsub_max
Definition: drawutils.h:57
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
AV_PIX_FMT_GRAY9LE
@ AV_PIX_FMT_GRAY9LE
Y , 9bpp, little-endian.
Definition: pixfmt.h:316
FFDrawColor::comp
union FFDrawColor::@204 comp[MAX_PLANES]
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:622
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:258
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
AV_PIX_FMT_GBRAP16BE
@ AV_PIX_FMT_GBRAP16BE
planar GBRA 4:4:4:4 64bpp, big-endian
Definition: pixfmt.h:216
full_range
bool full_range
Definition: hwcontext_videotoolbox.c:37
width
#define width
intreadwrite.h
MAX_PLANES
#define MAX_PLANES
Definition: ffv1.h:49
AV_PIX_FMT_GBRP16LE
@ AV_PIX_FMT_GBRP16LE
planar GBR 4:4:4 48bpp, little-endian
Definition: pixfmt.h:175
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
FFDrawContext::vsub
uint8_t vsub[MAX_PLANES]
Definition: drawutils.h:55
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
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:296
AV_PIX_FMT_P016BE
@ AV_PIX_FMT_P016BE
like NV12, with 16bpp per component, big-endian
Definition: pixfmt.h:301
FF_DRAW_PROCESS_ALPHA
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition: drawutils.h:74
GREEN
@ GREEN
Definition: drawutils.c:33
AV_PIX_FMT_GBRP12LE
@ AV_PIX_FMT_GBRP12LE
planar GBR 4:4:4 36bpp, little-endian
Definition: pixfmt.h:255
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:572
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:177
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:90
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:40
ff_draw_init
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:178
AVPixFmtDescriptor::log2_chroma_w
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
AV_PIX_FMT_GBRP10LE
@ AV_PIX_FMT_GBRP10LE
planar GBR 4:4:4 30bpp, little-endian
Definition: pixfmt.h:173
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_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
AV_PIX_FMT_GRAY8A
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:146
AV_PIX_FMT_GBRAP12BE
@ AV_PIX_FMT_GBRAP12BE
planar GBR 4:4:4:4 48bpp, big-endian
Definition: pixfmt.h:287
NULL
#define NULL
Definition: coverity.c:32
AVComponentDescriptor
Definition: pixdesc.h:31
AV_PIX_FMT_RGB48LE
@ AV_PIX_FMT_RGB48LE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as lit...
Definition: pixfmt.h:103
AV_PIX_FMT_YA16LE
@ AV_PIX_FMT_YA16LE
16 bits gray, 16 bits alpha (little-endian)
Definition: pixfmt.h:213
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
RGB_TO_V_CCIR
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
AV_PIX_FMT_RGBA64LE
@ AV_PIX_FMT_RGBA64LE
packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:206
src
#define src
Definition: vp8dsp.c:254
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:350
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
FFDrawColor::u8
uint8_t u8[16]
Definition: drawutils.h:67
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:359
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.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
ALPHA
@ ALPHA
Definition: drawutils.c:33
desc
const char * desc
Definition: nvenc.c:79
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
ff_fill_line_with_color
int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4], enum AVPixelFormat pix_fmt, uint8_t rgba_color[4], int *is_packed_rgba, uint8_t rgba_map_ptr[4])
Definition: drawutils.c:80
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:148
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:445
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
FFDrawContext::format
enum AVPixelFormat format
Definition: drawutils.h:50
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:296
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:318
AV_PIX_FMT_GBRP9BE
@ AV_PIX_FMT_GBRP9BE
planar GBR 4:4:4 27bpp, big-endian
Definition: pixfmt.h:170
FFDrawContext::comp_mask
uint8_t comp_mask[MAX_PLANES]
Definition: drawutils.h:53
component_used
static int component_used(FFDrawContext *draw, int plane, int comp)
Definition: drawutils.c:390
AV_PIX_FMT_GBRP9LE
@ AV_PIX_FMT_GBRP9LE
planar GBR 4:4:4 27bpp, little-endian
Definition: pixfmt.h:171
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
height
#define height
BLUE
@ BLUE
Definition: drawutils.c:33
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
AV_PIX_FMT_GBRAP10LE
@ AV_PIX_FMT_GBRAP10LE
planar GBR 4:4:4:4 40bpp, little-endian
Definition: pixfmt.h:291
av_bswap16
#define av_bswap16
Definition: bswap.h:31
line
Definition: graph2dot.c:48
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
ff_draw_rectangle
void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], uint8_t *src[4], int pixelstep[4], int hsub, int vsub, int x, int y, int w, int h)
Definition: drawutils.c:134
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
AV_PIX_FMT_BGRA64LE
@ AV_PIX_FMT_BGRA64LE
packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is st...
Definition: pixfmt.h:208
AV_PIX_FMT_RGB48BE
@ AV_PIX_FMT_RGB48BE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big...
Definition: pixfmt.h:102
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
ff_draw_supported_pixel_formats
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:731
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
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:719
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
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:128
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
uint8_t
uint8_t
Definition: audio_convert.c:194
RED
@ RED
Definition: drawutils.c:33
FFDrawContext
Definition: drawutils.h:48
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:231
AV_PIX_FMT_GBRAP16LE
@ AV_PIX_FMT_GBRAP16LE
planar GBRA 4:4:4:4 64bpp, little-endian
Definition: pixfmt.h:217
ret
ret
Definition: filter_design.txt:187
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
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:549
AV_PIX_FMT_P016LE
@ AV_PIX_FMT_P016LE
like NV12, with 16bpp per component, little-endian
Definition: pixfmt.h:300
FFDrawContext::hsub
uint8_t hsub[MAX_PLANES]
Definition: drawutils.h:54
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_GBRP12BE
@ AV_PIX_FMT_GBRP12BE
planar GBR 4:4:4 36bpp, big-endian
Definition: pixfmt.h:254
EXPAND
#define EXPAND(compn)
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:398
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
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:144
shift
static int shift(int a, int b)
Definition: sonic.c:82
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:98
avutil.h
mem.h
AV_PIX_FMT_P010LE
@ AV_PIX_FMT_P010LE
like NV12, with 10bpp per component, data in the high bits, zeros in the low bits,...
Definition: pixfmt.h:284
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
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:338
pointer_at
static uint8_t * pointer_at(FFDrawContext *draw, uint8_t *data[], int linesize[], int plane, int x, int y)
Definition: drawutils.c:288
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FFDrawContext::flags
unsigned flags
Definition: drawutils.h:59
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
AV_PIX_FMT_GBRP14LE
@ AV_PIX_FMT_GBRP14LE
planar GBR 4:4:4 42bpp, little-endian
Definition: pixfmt.h:257
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
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:597
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:420
FF_PSEUDOPAL
#define FF_PSEUDOPAL
Definition: internal.h:369
AV_PIX_FMT_GBRAP10BE
@ AV_PIX_FMT_GBRAP10BE
planar GBR 4:4:4:4 40bpp, big-endian
Definition: pixfmt.h:290
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
FFDrawContext::full_range
int full_range
Definition: drawutils.h:58
AV_PIX_FMT_BGR48BE
@ AV_PIX_FMT_BGR48BE
packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big...
Definition: pixfmt.h:148