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