FFmpeg
ops.c
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2025 Niklas Haas
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/avstring.h"
23 #include "libavutil/bswap.h"
24 #include "libavutil/mem.h"
25 #include "libavutil/rational.h"
26 #include "libavutil/refstruct.h"
27 
28 #include "ops.h"
29 #include "ops_internal.h"
30 
31 extern const SwsOpBackend backend_c;
32 extern const SwsOpBackend backend_murder;
33 extern const SwsOpBackend backend_x86;
34 extern const SwsOpBackend backend_vulkan;
35 
36 const SwsOpBackend * const ff_sws_op_backends[] = {
38 #if ARCH_X86_64 && HAVE_X86ASM
39  &backend_x86,
40 #endif
41  &backend_c,
42 #if CONFIG_VULKAN
44 #endif
45  NULL
46 };
47 
49 {
50  switch (type) {
51  case SWS_PIXEL_U8: return "u8";
52  case SWS_PIXEL_U16: return "u16";
53  case SWS_PIXEL_U32: return "u32";
54  case SWS_PIXEL_F32: return "f32";
55  case SWS_PIXEL_NONE: return "none";
56  case SWS_PIXEL_TYPE_NB: break;
57  }
58 
59  av_unreachable("Invalid pixel type!");
60  return "ERR";
61 }
62 
64 {
65  switch (type) {
66  case SWS_PIXEL_U8: return sizeof(uint8_t);
67  case SWS_PIXEL_U16: return sizeof(uint16_t);
68  case SWS_PIXEL_U32: return sizeof(uint32_t);
69  case SWS_PIXEL_F32: return sizeof(float);
70  case SWS_PIXEL_NONE: break;
71  case SWS_PIXEL_TYPE_NB: break;
72  }
73 
74  av_unreachable("Invalid pixel type!");
75  return 0;
76 }
77 
79 {
80  switch (type) {
81  case SWS_PIXEL_U8:
82  case SWS_PIXEL_U16:
83  case SWS_PIXEL_U32:
84  return true;
85  case SWS_PIXEL_F32:
86  return false;
87  case SWS_PIXEL_NONE:
88  case SWS_PIXEL_TYPE_NB: break;
89  }
90 
91  av_unreachable("Invalid pixel type!");
92  return false;
93 }
94 
96 {
97  switch (op) {
98  case SWS_OP_READ: return "SWS_OP_READ";
99  case SWS_OP_WRITE: return "SWS_OP_WRITE";
100  case SWS_OP_SWAP_BYTES: return "SWS_OP_SWAP_BYTES";
101  case SWS_OP_SWIZZLE: return "SWS_OP_SWIZZLE";
102  case SWS_OP_UNPACK: return "SWS_OP_UNPACK";
103  case SWS_OP_PACK: return "SWS_OP_PACK";
104  case SWS_OP_LSHIFT: return "SWS_OP_LSHIFT";
105  case SWS_OP_RSHIFT: return "SWS_OP_RSHIFT";
106  case SWS_OP_CLEAR: return "SWS_OP_CLEAR";
107  case SWS_OP_CONVERT: return "SWS_OP_CONVERT";
108  case SWS_OP_MIN: return "SWS_OP_MIN";
109  case SWS_OP_MAX: return "SWS_OP_MAX";
110  case SWS_OP_SCALE: return "SWS_OP_SCALE";
111  case SWS_OP_LINEAR: return "SWS_OP_LINEAR";
112  case SWS_OP_DITHER: return "SWS_OP_DITHER";
113  case SWS_OP_INVALID: return "SWS_OP_INVALID";
114  case SWS_OP_TYPE_NB: break;
115  }
116 
117  av_unreachable("Invalid operation type!");
118  return "ERR";
119 }
120 
121 /* biased towards `a` */
123 {
124  return av_cmp_q(a, b) == 1 ? b : a;
125 }
126 
128 {
129  return av_cmp_q(a, b) == -1 ? b : a;
130 }
131 
133 {
134  uint64_t mask[4];
135  int shift[4];
136 
137  switch (op->op) {
138  case SWS_OP_READ:
139  case SWS_OP_WRITE:
140  return;
141  case SWS_OP_UNPACK: {
144  unsigned val = x[0].num;
145  for (int i = 0; i < 4; i++)
146  x[i] = Q((val >> shift[i]) & mask[i]);
147  return;
148  }
149  case SWS_OP_PACK: {
152  unsigned val = 0;
153  for (int i = 0; i < 4; i++)
154  val |= (x[i].num & mask[i]) << shift[i];
155  x[0] = Q(val);
156  return;
157  }
158  case SWS_OP_SWAP_BYTES:
160  switch (ff_sws_pixel_type_size(op->type)) {
161  case 2:
162  for (int i = 0; i < 4; i++)
163  x[i].num = av_bswap16(x[i].num);
164  break;
165  case 4:
166  for (int i = 0; i < 4; i++)
167  x[i].num = av_bswap32(x[i].num);
168  break;
169  }
170  return;
171  case SWS_OP_CLEAR:
172  for (int i = 0; i < 4; i++) {
173  if (op->c.q4[i].den)
174  x[i] = op->c.q4[i];
175  }
176  return;
177  case SWS_OP_LSHIFT: {
179  AVRational mult = Q(1 << op->c.u);
180  for (int i = 0; i < 4; i++)
181  x[i] = x[i].den ? av_mul_q(x[i], mult) : x[i];
182  return;
183  }
184  case SWS_OP_RSHIFT: {
186  for (int i = 0; i < 4; i++)
187  x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->c.u) : x[i];
188  return;
189  }
190  case SWS_OP_SWIZZLE: {
191  const AVRational orig[4] = { x[0], x[1], x[2], x[3] };
192  for (int i = 0; i < 4; i++)
193  x[i] = orig[op->swizzle.in[i]];
194  return;
195  }
196  case SWS_OP_CONVERT:
197  if (ff_sws_pixel_type_is_int(op->convert.to)) {
198  const AVRational scale = ff_sws_pixel_expand(op->type, op->convert.to);
199  for (int i = 0; i < 4; i++) {
200  x[i] = x[i].den ? Q(x[i].num / x[i].den) : x[i];
201  if (op->convert.expand)
202  x[i] = av_mul_q(x[i], scale);
203  }
204  }
205  return;
206  case SWS_OP_DITHER:
208  for (int i = 0; i < 4; i++) {
209  if (op->dither.y_offset[i] >= 0 && x[i].den)
210  x[i] = av_add_q(x[i], av_make_q(1, 2));
211  }
212  return;
213  case SWS_OP_MIN:
214  for (int i = 0; i < 4; i++)
215  x[i] = av_min_q(x[i], op->c.q4[i]);
216  return;
217  case SWS_OP_MAX:
218  for (int i = 0; i < 4; i++)
219  x[i] = av_max_q(x[i], op->c.q4[i]);
220  return;
221  case SWS_OP_LINEAR: {
223  const AVRational orig[4] = { x[0], x[1], x[2], x[3] };
224  for (int i = 0; i < 4; i++) {
225  AVRational sum = op->lin.m[i][4];
226  for (int j = 0; j < 4; j++)
227  sum = av_add_q(sum, av_mul_q(orig[j], op->lin.m[i][j]));
228  x[i] = sum;
229  }
230  return;
231  }
232  case SWS_OP_SCALE:
233  for (int i = 0; i < 4; i++)
234  x[i] = x[i].den ? av_mul_q(x[i], op->c.q) : x[i];
235  return;
236  }
237 
238  av_unreachable("Invalid operation type!");
239 }
240 
241 /* merge_comp_flags() forms a monoid with flags_identity as the null element */
244 {
245  const SwsCompFlags flags_or = SWS_COMP_GARBAGE;
246  const SwsCompFlags flags_and = SWS_COMP_ZERO | SWS_COMP_EXACT;
247  return ((a & b) & flags_and) | ((a | b) & flags_or);
248 }
249 
250 /* Linearly propagate flags per component */
251 static void propagate_flags(SwsOp *op, const SwsComps *prev)
252 {
253  for (int i = 0; i < 4; i++)
254  op->comps.flags[i] = prev->flags[i];
255 }
256 
257 /* Clear undefined values in dst with src */
259 {
260  for (int i = 0; i < 4; i++) {
261  if (dst[i].den == 0)
262  dst[i] = src[i];
263  }
264 }
265 
266 /* Infer + propagate known information about components */
268 {
269  SwsComps next = { .unused = {true, true, true, true} };
270  SwsComps prev = { .flags = {
272  }};
273 
274  /* Forwards pass, propagates knowledge about the incoming pixel values */
275  for (int n = 0; n < ops->num_ops; n++) {
276  SwsOp *op = &ops->ops[n];
277 
278  switch (op->op) {
279  case SWS_OP_READ:
280  case SWS_OP_LINEAR:
281  case SWS_OP_SWAP_BYTES:
282  case SWS_OP_UNPACK:
283  break; /* special cases, handled below */
284  default:
285  memcpy(op->comps.min, prev.min, sizeof(prev.min));
286  memcpy(op->comps.max, prev.max, sizeof(prev.max));
287  ff_sws_apply_op_q(op, op->comps.min);
288  ff_sws_apply_op_q(op, op->comps.max);
289  break;
290  }
291 
292  switch (op->op) {
293  case SWS_OP_READ:
294  /* Active components are taken from the user-provided values,
295  * other components are explicitly stripped */
296  for (int i = 0; i < op->rw.elems; i++) {
297  const int idx = op->rw.packed ? i : ops->order_src.in[i];
298  op->comps.flags[i] = ops->comps_src.flags[idx];
299  op->comps.min[i] = ops->comps_src.min[idx];
300  op->comps.max[i] = ops->comps_src.max[idx];
301  }
302  for (int i = op->rw.elems; i < 4; i++) {
303  op->comps.flags[i] = prev.flags[i];
304  op->comps.min[i] = prev.min[i];
305  op->comps.max[i] = prev.max[i];
306  }
307  break;
308  case SWS_OP_SWAP_BYTES:
309  for (int i = 0; i < 4; i++) {
310  op->comps.flags[i] = prev.flags[i] ^ SWS_COMP_SWAPPED;
311  op->comps.min[i] = prev.min[i];
312  op->comps.max[i] = prev.max[i];
313  }
314  break;
315  case SWS_OP_WRITE:
316  for (int i = 0; i < op->rw.elems; i++)
317  av_assert1(!(prev.flags[i] & SWS_COMP_GARBAGE));
318  /* fall through */
319  case SWS_OP_LSHIFT:
320  case SWS_OP_RSHIFT:
321  propagate_flags(op, &prev);
322  break;
323  case SWS_OP_MIN:
324  propagate_flags(op, &prev);
325  clear_undefined_values(op->comps.max, op->c.q4);
326  break;
327  case SWS_OP_MAX:
328  propagate_flags(op, &prev);
329  clear_undefined_values(op->comps.min, op->c.q4);
330  break;
331  case SWS_OP_DITHER:
332  /* Strip zero flag because of the nonzero dithering offset */
333  for (int i = 0; i < 4; i++)
334  op->comps.flags[i] = prev.flags[i] & ~SWS_COMP_ZERO;
335  break;
336  case SWS_OP_UNPACK:
337  for (int i = 0; i < 4; i++) {
338  const int pattern = op->pack.pattern[i];
339  if (pattern) {
340  av_assert1(pattern < 32);
341  op->comps.flags[i] = prev.flags[0];
342  op->comps.min[i] = Q(0);
343  op->comps.max[i] = Q((1ULL << pattern) - 1);
344  } else
345  op->comps.flags[i] = SWS_COMP_GARBAGE;
346  }
347  break;
348  case SWS_OP_PACK: {
350  for (int i = 0; i < 4; i++) {
351  if (op->pack.pattern[i])
352  flags = merge_comp_flags(flags, prev.flags[i]);
353  if (i > 0) /* clear remaining comps for sanity */
354  op->comps.flags[i] = SWS_COMP_GARBAGE;
355  }
356  op->comps.flags[0] = flags;
357  break;
358  }
359  case SWS_OP_CLEAR:
360  for (int i = 0; i < 4; i++) {
361  if (op->c.q4[i].den) {
362  op->comps.flags[i] = 0;
363  if (op->c.q4[i].num == 0)
364  op->comps.flags[i] |= SWS_COMP_ZERO;
365  if (op->c.q4[i].den == 1)
366  op->comps.flags[i] |= SWS_COMP_EXACT;
367  } else {
368  op->comps.flags[i] = prev.flags[i];
369  }
370  }
371  break;
372  case SWS_OP_SWIZZLE:
373  for (int i = 0; i < 4; i++)
374  op->comps.flags[i] = prev.flags[op->swizzle.in[i]];
375  break;
376  case SWS_OP_CONVERT:
377  for (int i = 0; i < 4; i++) {
378  op->comps.flags[i] = prev.flags[i];
379  if (ff_sws_pixel_type_is_int(op->convert.to))
380  op->comps.flags[i] |= SWS_COMP_EXACT;
381  }
382  break;
383  case SWS_OP_LINEAR:
384  for (int i = 0; i < 4; i++) {
386  AVRational min = Q(0), max = Q(0);
387  for (int j = 0; j < 4; j++) {
388  const AVRational k = op->lin.m[i][j];
389  AVRational mink = av_mul_q(prev.min[j], k);
390  AVRational maxk = av_mul_q(prev.max[j], k);
391  if (k.num) {
392  flags = merge_comp_flags(flags, prev.flags[j]);
393  if (k.den != 1) /* fractional coefficient */
394  flags &= ~SWS_COMP_EXACT;
395  if (k.num < 0)
396  FFSWAP(AVRational, mink, maxk);
397  min = av_add_q(min, mink);
398  max = av_add_q(max, maxk);
399  }
400  }
401  if (op->lin.m[i][4].num) { /* nonzero offset */
402  flags &= ~SWS_COMP_ZERO;
403  if (op->lin.m[i][4].den != 1) /* fractional offset */
404  flags &= ~SWS_COMP_EXACT;
405  min = av_add_q(min, op->lin.m[i][4]);
406  max = av_add_q(max, op->lin.m[i][4]);
407  }
408  op->comps.flags[i] = flags;
409  op->comps.min[i] = min;
410  op->comps.max[i] = max;
411  }
412  break;
413  case SWS_OP_SCALE:
414  for (int i = 0; i < 4; i++) {
415  op->comps.flags[i] = prev.flags[i];
416  if (op->c.q.den != 1) /* fractional scale */
417  op->comps.flags[i] &= ~SWS_COMP_EXACT;
418  if (op->c.q.num < 0)
419  FFSWAP(AVRational, op->comps.min[i], op->comps.max[i]);
420  }
421  break;
422 
423  case SWS_OP_INVALID:
424  case SWS_OP_TYPE_NB:
425  av_unreachable("Invalid operation type!");
426  }
427 
428  prev = op->comps;
429  }
430 
431  /* Backwards pass, solves for component dependencies */
432  for (int n = ops->num_ops - 1; n >= 0; n--) {
433  SwsOp *op = &ops->ops[n];
434 
435  switch (op->op) {
436  case SWS_OP_READ:
437  case SWS_OP_WRITE:
438  for (int i = 0; i < op->rw.elems; i++)
439  op->comps.unused[i] = op->op == SWS_OP_READ;
440  for (int i = op->rw.elems; i < 4; i++)
441  op->comps.unused[i] = next.unused[i];
442  break;
443  case SWS_OP_SWAP_BYTES:
444  case SWS_OP_LSHIFT:
445  case SWS_OP_RSHIFT:
446  case SWS_OP_CONVERT:
447  case SWS_OP_DITHER:
448  case SWS_OP_MIN:
449  case SWS_OP_MAX:
450  case SWS_OP_SCALE:
451  for (int i = 0; i < 4; i++)
452  op->comps.unused[i] = next.unused[i];
453  break;
454  case SWS_OP_UNPACK: {
455  bool unused = true;
456  for (int i = 0; i < 4; i++) {
457  if (op->pack.pattern[i])
458  unused &= next.unused[i];
459  op->comps.unused[i] = i > 0;
460  }
461  op->comps.unused[0] = unused;
462  break;
463  }
464  case SWS_OP_PACK:
465  for (int i = 0; i < 4; i++) {
466  if (op->pack.pattern[i])
467  op->comps.unused[i] = next.unused[0];
468  else
469  op->comps.unused[i] = true;
470  }
471  break;
472  case SWS_OP_CLEAR:
473  for (int i = 0; i < 4; i++) {
474  if (op->c.q4[i].den)
475  op->comps.unused[i] = true;
476  else
477  op->comps.unused[i] = next.unused[i];
478  }
479  break;
480  case SWS_OP_SWIZZLE: {
481  bool unused[4] = { true, true, true, true };
482  for (int i = 0; i < 4; i++)
483  unused[op->swizzle.in[i]] &= next.unused[i];
484  for (int i = 0; i < 4; i++)
485  op->comps.unused[i] = unused[i];
486  break;
487  }
488  case SWS_OP_LINEAR:
489  for (int j = 0; j < 4; j++) {
490  bool unused = true;
491  for (int i = 0; i < 4; i++) {
492  if (op->lin.m[i][j].num)
493  unused &= next.unused[i];
494  }
495  op->comps.unused[j] = unused;
496  }
497  break;
498  }
499 
500  next = op->comps;
501  }
502 }
503 
504 static void op_uninit(SwsOp *op)
505 {
506  switch (op->op) {
507  case SWS_OP_DITHER:
508  av_refstruct_unref(&op->dither.matrix);
509  break;
510  }
511 
512  *op = (SwsOp) {0};
513 }
514 
516 {
517  SwsOpList *ops = av_mallocz(sizeof(SwsOpList));
518  if (!ops)
519  return NULL;
520 
521  ops->order_src = ops->order_dst = SWS_SWIZZLE(0, 1, 2, 3);
522  ff_fmt_clear(&ops->src);
523  ff_fmt_clear(&ops->dst);
524  return ops;
525 }
526 
528 {
529  SwsOpList *ops = *p_ops;
530  if (!ops)
531  return;
532 
533  for (int i = 0; i < ops->num_ops; i++)
534  op_uninit(&ops->ops[i]);
535 
536  av_freep(&ops->ops);
537  av_free(ops);
538  *p_ops = NULL;
539 }
540 
542 {
543  SwsOpList *copy = av_malloc(sizeof(*copy));
544  if (!copy)
545  return NULL;
546 
547  int num = ops->num_ops;
548  if (num)
549  num = 1 << av_ceil_log2(num);
550 
551  *copy = *ops;
552  copy->ops = av_memdup(ops->ops, num * sizeof(ops->ops[0]));
553  if (!copy->ops) {
554  av_free(copy);
555  return NULL;
556  }
557 
558  for (int i = 0; i < ops->num_ops; i++) {
559  const SwsOp *op = &ops->ops[i];
560  switch (op->op) {
561  case SWS_OP_DITHER:
562  av_refstruct_ref(copy->ops[i].dither.matrix);
563  break;
564  }
565  }
566 
567  return copy;
568 }
569 
571 {
572  if (!ops->num_ops)
573  return NULL;
574 
575  const SwsOp *read = &ops->ops[0];
576  return read->op == SWS_OP_READ ? read : NULL;
577 }
578 
580 {
581  if (!ops->num_ops)
582  return NULL;
583 
584  const SwsOp *write = &ops->ops[ops->num_ops - 1];
585  return write->op == SWS_OP_WRITE ? write : NULL;
586 }
587 
588 void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
589 {
590  const int end = ops->num_ops - count;
591  av_assert2(index >= 0 && count >= 0 && index + count <= ops->num_ops);
592  op_uninit(&ops->ops[index]);
593  for (int i = index; i < end; i++)
594  ops->ops[i] = ops->ops[i + count];
595  ops->num_ops = end;
596 }
597 
599 {
600  void *ret = av_dynarray2_add((void **) &ops->ops, &ops->num_ops, sizeof(*op), NULL);
601  if (!ret) {
602  op_uninit(op);
603  return AVERROR(ENOMEM);
604  }
605 
606  for (int i = ops->num_ops - 1; i > index; i--)
607  ops->ops[i] = ops->ops[i - 1];
608  ops->ops[index] = *op;
609  return 0;
610 }
611 
613 {
614  return ff_sws_op_list_insert_at(ops, ops->num_ops, op);
615 }
616 
618 {
619  if (!ops->num_ops)
620  return true;
621 
622  const SwsOp *read = ff_sws_op_list_input(ops);
623  const SwsOp *write = ff_sws_op_list_output(ops);
624  if (!read || !write || ops->num_ops > 2 ||
625  read->type != write->type ||
626  read->rw.packed != write->rw.packed ||
627  read->rw.elems != write->rw.elems ||
628  read->rw.frac != write->rw.frac)
629  return false;
630 
631  /**
632  * Note that this check is unlikely to ever be hit in practice, since it
633  * would imply the existence of planar formats with different plane orders
634  * between them, e.g. rgbap <-> gbrap, which doesn't currently exist.
635  * However, the check is cheap and lets me sleep at night.
636  */
637  const int num_planes = read->rw.packed ? 1 : read->rw.elems;
638  for (int i = 0; i < num_planes; i++) {
639  if (ops->order_src.in[i] != ops->order_dst.in[i])
640  return false;
641  }
642 
643  return true;
644 }
645 
647 {
648  int max_size = 0;
649  for (int i = 0; i < ops->num_ops; i++) {
650  const int size = ff_sws_pixel_type_size(ops->ops[i].type);
651  max_size = FFMAX(max_size, size);
652  }
653 
654  return max_size;
655 }
656 
658 {
659  uint32_t mask = 0;
660  for (int i = 0; i < 4; i++) {
661  for (int j = 0; j < 5; j++) {
662  if (av_cmp_q(c.m[i][j], Q(i == j)))
663  mask |= SWS_MASK(i, j);
664  }
665  }
666  return mask;
667 }
668 
669 static const char *describe_lin_mask(uint32_t mask)
670 {
671  /* Try to be fairly descriptive without assuming too much */
672  static const struct {
673  char name[24];
674  uint32_t mask;
675  } patterns[] = {
676  { "noop", 0 },
677  { "luma", SWS_MASK_LUMA },
678  { "alpha", SWS_MASK_ALPHA },
679  { "luma+alpha", SWS_MASK_LUMA | SWS_MASK_ALPHA },
680  { "dot3", 0x7 },
681  { "dot4", 0xF },
682  { "row0", SWS_MASK_ROW(0) },
683  { "row0+alpha", SWS_MASK_ROW(0) | SWS_MASK_ALPHA },
684  { "col0", SWS_MASK_COL(0) },
685  { "col0+off3", SWS_MASK_COL(0) | SWS_MASK_OFF3 },
686  { "off3", SWS_MASK_OFF3 },
687  { "off3+alpha", SWS_MASK_OFF3 | SWS_MASK_ALPHA },
688  { "diag3", SWS_MASK_DIAG3 },
689  { "diag4", SWS_MASK_DIAG4 },
690  { "diag3+alpha", SWS_MASK_DIAG3 | SWS_MASK_ALPHA },
691  { "diag3+off3", SWS_MASK_DIAG3 | SWS_MASK_OFF3 },
692  { "diag3+off3+alpha", SWS_MASK_DIAG3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
693  { "diag4+off4", SWS_MASK_DIAG4 | SWS_MASK_OFF4 },
694  { "matrix3", SWS_MASK_MAT3 },
695  { "matrix3+off3", SWS_MASK_MAT3 | SWS_MASK_OFF3 },
696  { "matrix3+off3+alpha", SWS_MASK_MAT3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
697  { "matrix4", SWS_MASK_MAT4 },
698  { "matrix4+off4", SWS_MASK_MAT4 | SWS_MASK_OFF4 },
699  };
700 
701  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
702  if (!(mask & ~patterns[i].mask))
703  return patterns[i].name;
704  }
705 
706  av_unreachable("Invalid linear mask!");
707  return "ERR";
708 }
709 
711 {
712  if (flags & SWS_COMP_GARBAGE)
713  return 'X';
714  else if (flags & SWS_COMP_ZERO)
715  return '0';
716  else if (flags & SWS_COMP_SWAPPED)
717  return 'z';
718  else if (flags & SWS_COMP_EXACT)
719  return '+';
720  else
721  return '.';
722 }
723 
724 static const char *describe_order(SwsSwizzleOp order, int planes, char buf[32])
725 {
726  if (order.mask == SWS_SWIZZLE(0, 1, 2, 3).mask)
727  return "";
728 
729  av_strlcpy(buf, ", via {", 32);
730  for (int i = 0; i < planes; i++)
731  av_strlcatf(buf, 32, "%s%d", i ? ", " : "", order.in[i]);
732  av_strlcat(buf, "}", 32);
733  return buf;
734 }
735 
736 static const char *print_q(const AVRational q, char buf[], int buf_len)
737 {
738  if (!q.den) {
739  return q.num > 0 ? "inf" : q.num < 0 ? "-inf" : "nan";
740  } else if (q.den == 1) {
741  snprintf(buf, buf_len, "%d", q.num);
742  return buf;
743  } else if (abs(q.num) > 1000 || abs(q.den) > 1000) {
744  snprintf(buf, buf_len, "%f", av_q2d(q));
745  return buf;
746  } else {
747  snprintf(buf, buf_len, "%d/%d", q.num, q.den);
748  return buf;
749  }
750 }
751 
752 #define PRINTQ(q) print_q(q, (char[32]){0}, sizeof(char[32]))
753 
754 void ff_sws_op_list_print(void *log, int lev, int lev_extra,
755  const SwsOpList *ops)
756 {
757  if (!ops->num_ops) {
758  av_log(log, lev, " (empty)\n");
759  return;
760  }
761 
762  for (int i = 0; i < ops->num_ops; i++) {
763  const SwsOp *op = &ops->ops[i];
764  const SwsOp *next = i + 1 < ops->num_ops ? &ops->ops[i + 1] : op;
765  const char *name = ff_sws_op_type_name(op->op);
766  char buf[32];
767 
768  av_log(log, lev, " [%3s %c%c%c%c -> %c%c%c%c] ",
769  ff_sws_pixel_type_name(op->type),
770  op->comps.unused[0] ? 'X' : '.',
771  op->comps.unused[1] ? 'X' : '.',
772  op->comps.unused[2] ? 'X' : '.',
773  op->comps.unused[3] ? 'X' : '.',
774  next->comps.unused[0] ? 'X' : describe_comp_flags(op->comps.flags[0]),
775  next->comps.unused[1] ? 'X' : describe_comp_flags(op->comps.flags[1]),
776  next->comps.unused[2] ? 'X' : describe_comp_flags(op->comps.flags[2]),
777  next->comps.unused[3] ? 'X' : describe_comp_flags(op->comps.flags[3]));
778 
779  switch (op->op) {
780  case SWS_OP_INVALID:
781  case SWS_OP_SWAP_BYTES:
782  av_log(log, lev, "%s\n", name);
783  break;
784  case SWS_OP_READ:
785  case SWS_OP_WRITE:
786  av_log(log, lev, "%-20s: %d elem(s) %s >> %d%s\n", name,
787  op->rw.elems, op->rw.packed ? "packed" : "planar",
788  op->rw.frac,
789  describe_order(op->op == SWS_OP_READ ? ops->order_src
790  : ops->order_dst,
791  op->rw.packed ? 1 : op->rw.elems, buf));
792  break;
793  case SWS_OP_LSHIFT:
794  av_log(log, lev, "%-20s: << %u\n", name, op->c.u);
795  break;
796  case SWS_OP_RSHIFT:
797  av_log(log, lev, "%-20s: >> %u\n", name, op->c.u);
798  break;
799  case SWS_OP_PACK:
800  case SWS_OP_UNPACK:
801  av_log(log, lev, "%-20s: {%d %d %d %d}\n", name,
802  op->pack.pattern[0], op->pack.pattern[1],
803  op->pack.pattern[2], op->pack.pattern[3]);
804  break;
805  case SWS_OP_CLEAR:
806  av_log(log, lev, "%-20s: {%s %s %s %s}\n", name,
807  op->c.q4[0].den ? PRINTQ(op->c.q4[0]) : "_",
808  op->c.q4[1].den ? PRINTQ(op->c.q4[1]) : "_",
809  op->c.q4[2].den ? PRINTQ(op->c.q4[2]) : "_",
810  op->c.q4[3].den ? PRINTQ(op->c.q4[3]) : "_");
811  break;
812  case SWS_OP_SWIZZLE:
813  av_log(log, lev, "%-20s: %d%d%d%d\n", name,
814  op->swizzle.x, op->swizzle.y, op->swizzle.z, op->swizzle.w);
815  break;
816  case SWS_OP_CONVERT:
817  av_log(log, lev, "%-20s: %s -> %s%s\n", name,
818  ff_sws_pixel_type_name(op->type),
819  ff_sws_pixel_type_name(op->convert.to),
820  op->convert.expand ? " (expand)" : "");
821  break;
822  case SWS_OP_DITHER:
823  av_log(log, lev, "%-20s: %dx%d matrix + {%d %d %d %d}\n", name,
824  1 << op->dither.size_log2, 1 << op->dither.size_log2,
825  op->dither.y_offset[0], op->dither.y_offset[1],
826  op->dither.y_offset[2], op->dither.y_offset[3]);
827  break;
828  case SWS_OP_MIN:
829  av_log(log, lev, "%-20s: x <= {%s %s %s %s}\n", name,
830  op->c.q4[0].den ? PRINTQ(op->c.q4[0]) : "_",
831  op->c.q4[1].den ? PRINTQ(op->c.q4[1]) : "_",
832  op->c.q4[2].den ? PRINTQ(op->c.q4[2]) : "_",
833  op->c.q4[3].den ? PRINTQ(op->c.q4[3]) : "_");
834  break;
835  case SWS_OP_MAX:
836  av_log(log, lev, "%-20s: {%s %s %s %s} <= x\n", name,
837  op->c.q4[0].den ? PRINTQ(op->c.q4[0]) : "_",
838  op->c.q4[1].den ? PRINTQ(op->c.q4[1]) : "_",
839  op->c.q4[2].den ? PRINTQ(op->c.q4[2]) : "_",
840  op->c.q4[3].den ? PRINTQ(op->c.q4[3]) : "_");
841  break;
842  case SWS_OP_LINEAR:
843  av_log(log, lev, "%-20s: %s [[%s %s %s %s %s] "
844  "[%s %s %s %s %s] "
845  "[%s %s %s %s %s] "
846  "[%s %s %s %s %s]]\n",
847  name, describe_lin_mask(op->lin.mask),
848  PRINTQ(op->lin.m[0][0]), PRINTQ(op->lin.m[0][1]), PRINTQ(op->lin.m[0][2]), PRINTQ(op->lin.m[0][3]), PRINTQ(op->lin.m[0][4]),
849  PRINTQ(op->lin.m[1][0]), PRINTQ(op->lin.m[1][1]), PRINTQ(op->lin.m[1][2]), PRINTQ(op->lin.m[1][3]), PRINTQ(op->lin.m[1][4]),
850  PRINTQ(op->lin.m[2][0]), PRINTQ(op->lin.m[2][1]), PRINTQ(op->lin.m[2][2]), PRINTQ(op->lin.m[2][3]), PRINTQ(op->lin.m[2][4]),
851  PRINTQ(op->lin.m[3][0]), PRINTQ(op->lin.m[3][1]), PRINTQ(op->lin.m[3][2]), PRINTQ(op->lin.m[3][3]), PRINTQ(op->lin.m[3][4]));
852  break;
853  case SWS_OP_SCALE:
854  av_log(log, lev, "%-20s: * %s\n", name, PRINTQ(op->c.q));
855  break;
856  case SWS_OP_TYPE_NB:
857  break;
858  }
859 
860  if (op->comps.min[0].den || op->comps.min[1].den ||
861  op->comps.min[2].den || op->comps.min[3].den ||
862  op->comps.max[0].den || op->comps.max[1].den ||
863  op->comps.max[2].den || op->comps.max[3].den)
864  {
865  av_log(log, lev_extra, " min: {%s, %s, %s, %s}, max: {%s, %s, %s, %s}\n",
866  next->comps.unused[0] ? "_" : PRINTQ(op->comps.min[0]),
867  next->comps.unused[1] ? "_" : PRINTQ(op->comps.min[1]),
868  next->comps.unused[2] ? "_" : PRINTQ(op->comps.min[2]),
869  next->comps.unused[3] ? "_" : PRINTQ(op->comps.min[3]),
870  next->comps.unused[0] ? "_" : PRINTQ(op->comps.max[0]),
871  next->comps.unused[1] ? "_" : PRINTQ(op->comps.max[1]),
872  next->comps.unused[2] ? "_" : PRINTQ(op->comps.max[2]),
873  next->comps.unused[3] ? "_" : PRINTQ(op->comps.max[3]));
874  }
875 
876  }
877 
878  av_log(log, lev, " (X = unused, z = byteswapped, + = exact, 0 = zero)\n");
879 }
SWS_OP_READ
@ SWS_OP_READ
Definition: ops.h:47
SWS_MASK_LUMA
@ SWS_MASK_LUMA
Definition: ops.h:171
flags
const SwsFlags flags[]
Definition: swscale.c:61
SWS_PIXEL_U16
@ SWS_PIXEL_U16
Definition: ops.h:33
ff_sws_op_list_free
void ff_sws_op_list_free(SwsOpList **p_ops)
Definition: ops.c:527
name
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 minimum maximum flags name is the option name
Definition: writing_filters.txt:88
SWS_OP_SWIZZLE
@ SWS_OP_SWIZZLE
Definition: ops.h:50
ff_sws_op_list_alloc
SwsOpList * ff_sws_op_list_alloc(void)
Definition: ops.c:515
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
SWS_OP_LSHIFT
@ SWS_OP_LSHIFT
Definition: ops.h:55
SWS_OP_UNPACK
@ SWS_OP_UNPACK
Definition: ops.h:53
ff_sws_op_list_duplicate
SwsOpList * ff_sws_op_list_duplicate(const SwsOpList *ops)
Returns a duplicate of ops, or NULL on OOM.
Definition: ops.c:541
SwsSwizzleOp::mask
uint32_t mask
Definition: ops.h:128
av_min_q
static AVRational av_min_q(AVRational a, AVRational b)
Definition: ops.c:122
SwsOpList::comps_src
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
Definition: ops.h:243
merge_comp_flags
static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
Definition: ops.c:243
ff_sws_op_list_input
const SwsOp * ff_sws_op_list_input(const SwsOpList *ops)
Returns the input operation for a given op list, or NULL if there is none (e.g.
Definition: ops.c:570
SWS_COMP_ZERO
@ SWS_COMP_ZERO
Definition: ops.h:77
SWS_OP_CLEAR
@ SWS_OP_CLEAR
Definition: ops.h:59
ff_sws_linear_mask
uint32_t ff_sws_linear_mask(const SwsLinearOp c)
Definition: ops.c:657
ff_sws_op_list_max_size
int ff_sws_op_list_max_size(const SwsOpList *ops)
Returns the size of the largest pixel type used in ops.
Definition: ops.c:646
backend_x86
const SwsOpBackend backend_x86
Definition: ops.c:765
SwsComps::unused
bool unused[4]
Definition: ops.h:93
rational.h
ff_sws_op_list_append
int ff_sws_op_list_append(SwsOpList *ops, SwsOp *op)
These will take over ownership of op and set it to {0}, even on failure.
Definition: ops.c:612
normalize.log
log
Definition: normalize.py:21
mask
int mask
Definition: mediacodecdec_common.c:154
SwsOp::rw
SwsReadWriteOp rw
Definition: ops.h:193
backend_vulkan
const SwsOpBackend backend_vulkan
Definition: ops.c:339
ops.h
SWS_OP_DITHER
@ SWS_OP_DITHER
Definition: ops.h:67
describe_comp_flags
static char describe_comp_flags(SwsCompFlags flags)
Definition: ops.c:710
av_dynarray2_add
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
Definition: mem.c:343
b
#define b
Definition: input.c:42
max
#define max(a, b)
Definition: cuda_runtime.h:33
SWS_PIXEL_U32
@ SWS_PIXEL_U32
Definition: ops.h:34
SWS_OP_TYPE_NB
@ SWS_OP_TYPE_NB
Definition: ops.h:69
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:103
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:63
clear_undefined_values
static void clear_undefined_values(AVRational dst[4], const AVRational src[4])
Definition: ops.c:258
SWS_MASK_ROW
#define SWS_MASK_ROW(I)
Definition: ops.h:166
av_memdup
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:304
SwsPixelType
SwsPixelType
Copyright (C) 2025 Niklas Haas.
Definition: ops.h:30
SwsComps::max
AVRational max[4]
Definition: ops.h:97
ff_sws_op_list_print
void ff_sws_op_list_print(void *log, int lev, int lev_extra, const SwsOpList *ops)
Print out the contents of an operation list.
Definition: ops.c:754
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: ops.h:35
ff_sws_op_backends
const SwsOpBackend *const ff_sws_op_backends[]
Definition: ops.c:36
av_ceil_log2
#define av_ceil_log2
Definition: common.h:97
SwsOpList::num_ops
int num_ops
Definition: ops.h:226
SwsCompFlags
SwsCompFlags
Definition: ops.h:74
SWS_MASK_COL
#define SWS_MASK_COL(J)
Definition: ops.h:167
SWS_PIXEL_U8
@ SWS_PIXEL_U8
Definition: ops.h:32
SwsSwizzleOp
Definition: ops.h:122
ff_sws_pixel_type_is_int
bool ff_sws_pixel_type_is_int(SwsPixelType type)
Definition: ops.c:78
val
static double val(void *priv, double ch)
Definition: aeval.c:77
flags_identity
static const SwsCompFlags flags_identity
Definition: ops.c:242
type
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 type
Definition: writing_filters.txt:86
AVRational::num
int num
Numerator.
Definition: rational.h:59
refstruct.h
SwsOp::op
SwsOpType op
Definition: ops.h:189
Q
#define Q(q)
mult
static int16_t mult(Float11 *f1, Float11 *f2)
Definition: g726.c:60
SWS_OP_SCALE
@ SWS_OP_SCALE
Definition: ops.h:63
avassert.h
SWS_MASK_MAT3
@ SWS_MASK_MAT3
Definition: ops.h:176
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
float
float
Definition: af_crystalizer.c:122
SWS_SWIZZLE
#define SWS_SWIZZLE(X, Y, Z, W)
Definition: ops.h:134
SwsComps::min
AVRational min[4]
Definition: ops.h:97
op
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:76
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
backend_c
const SwsOpBackend backend_c
Copyright (C) 2025 Niklas Haas.
Definition: ops_backend.c:104
SWS_OP_MIN
@ SWS_OP_MIN
Definition: ops.h:61
ff_sws_pixel_expand
static AVRational ff_sws_pixel_expand(SwsPixelType from, SwsPixelType to)
Definition: ops_internal.h:31
SWS_OP_LINEAR
@ SWS_OP_LINEAR
Definition: ops.h:66
ff_sws_op_list_output
const SwsOp * ff_sws_op_list_output(const SwsOpList *ops)
Returns the output operation for a given op list, or NULL if there is none.
Definition: ops.c:579
PRINTQ
#define PRINTQ(q)
Definition: ops.c:752
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
describe_order
static const char * describe_order(SwsSwizzleOp order, int planes, char buf[32])
Definition: ops.c:724
SwsOpBackend
Definition: ops_internal.h:55
SWS_OP_PACK
@ SWS_OP_PACK
Definition: ops.h:54
ff_sws_op_list_is_noop
bool ff_sws_op_list_is_noop(const SwsOpList *ops)
Returns whether an op list represents a true no-op operation, i.e.
Definition: ops.c:617
NULL
#define NULL
Definition: coverity.c:32
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_unreachable
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition: avassert.h:116
SwsReadWriteOp::frac
uint8_t frac
Definition: ops.h:102
SWS_COMP_GARBAGE
@ SWS_COMP_GARBAGE
Definition: ops.h:75
planes
static const struct @562 planes[]
SwsOpType
SwsOpType
Definition: ops.h:43
abs
#define abs(x)
Definition: cuda_runtime.h:35
ff_sws_op_list_remove_at
void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
Definition: ops.c:588
print_q
static const char * print_q(const AVRational q, char buf[], int buf_len)
Definition: ops.c:736
SWS_MASK
#define SWS_MASK(I, J)
Definition: ops.h:164
SWS_PIXEL_NONE
@ SWS_PIXEL_NONE
Definition: ops.h:31
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ff_sws_apply_op_q
void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
Apply an operation to an AVRational.
Definition: ops.c:132
SwsOpList::order_dst
SwsSwizzleOp order_dst
Definition: ops.h:232
copy
static void copy(const float *p1, float *p2, const int length)
Definition: vf_vaguedenoiser.c:186
shift
static int shift(int a, int b)
Definition: bonk.c:261
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
av_bswap32
#define av_bswap32
Definition: bswap.h:47
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
SwsOp::type
SwsPixelType type
Definition: ops.h:190
ff_sws_op_list_insert_at
int ff_sws_op_list_insert_at(SwsOpList *ops, int index, SwsOp *op)
Definition: ops.c:598
size
int size
Definition: twinvq_data.h:10344
SWS_MASK_DIAG4
@ SWS_MASK_DIAG4
Definition: ops.h:180
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
SWS_OP_RSHIFT
@ SWS_OP_RSHIFT
Definition: ops.h:56
SwsOpList::src
SwsFormat src
Definition: ops.h:229
SWS_OP_INVALID
@ SWS_OP_INVALID
Definition: ops.h:44
ff_sws_op_list_update_comps
void ff_sws_op_list_update_comps(SwsOpList *ops)
Infer + propagate known information about components.
Definition: ops.c:267
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:48
av_refstruct_ref
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition: refstruct.c:140
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
op_uninit
static void op_uninit(SwsOp *op)
Definition: ops.c:504
SwsOp::comps
SwsComps comps
Metadata about the operation's input/output components.
Definition: ops.h:208
SwsLinearOp
Definition: ops.h:147
av_refstruct_unref
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
av_max_q
static AVRational av_max_q(AVRational a, AVRational b)
Definition: ops.c:127
SwsOpList::ops
SwsOp * ops
Definition: ops.h:225
SwsOpList::order_src
SwsSwizzleOp order_src
Definition: ops.h:232
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:58
ops_internal.h
lev
static LevelCodes lev[4+3+3]
Definition: clearvideo.c:80
SwsOp
Definition: ops.h:188
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
SwsComps::flags
SwsCompFlags flags[4]
Definition: ops.h:92
ret
ret
Definition: filter_design.txt:187
bswap.h
backend_murder
const SwsOpBackend backend_murder
Definition: ops_memcpy.c:130
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
av_strlcat
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition: avstring.c:95
av_malloc
void * av_malloc(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:98
SwsOpList::dst
SwsFormat dst
Definition: ops.h:229
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:62
SWS_MASK_OFF3
@ SWS_MASK_OFF3
Definition: ops.h:175
SWS_PIXEL_TYPE_NB
@ SWS_PIXEL_TYPE_NB
Definition: ops.h:36
SwsComps
Definition: ops.h:91
AVRational::den
int den
Denominator.
Definition: rational.h:60
SWS_COMP_SWAPPED
@ SWS_COMP_SWAPPED
Definition: ops.h:78
SwsReadWriteOp::packed
bool packed
Definition: ops.h:103
ff_sws_pixel_type_name
const char * ff_sws_pixel_type_name(SwsPixelType type)
Definition: ops.c:48
SWS_OP_SWAP_BYTES
@ SWS_OP_SWAP_BYTES
Definition: ops.h:49
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
SWS_COMP_EXACT
@ SWS_COMP_EXACT
Definition: ops.h:76
describe_lin_mask
static const char * describe_lin_mask(uint32_t mask)
Definition: ops.c:669
SwsReadWriteOp::elems
uint8_t elems
Definition: ops.h:101
mem.h
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:278
av_add_q
AVRational av_add_q(AVRational b, AVRational c)
Add two rationals.
Definition: rational.c:93
ff_sws_pack_op_decode
static void ff_sws_pack_op_decode(const SwsOp *op, uint64_t mask[4], int shift[4])
Definition: ops_internal.h:43
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
SwsSwizzleOp::in
uint8_t in[4]
Definition: ops.h:129
SWS_OP_CONVERT
@ SWS_OP_CONVERT
Definition: ops.h:60
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
propagate_flags
static void propagate_flags(SwsOp *op, const SwsComps *prev)
Definition: ops.c:251
SWS_MASK_MAT4
@ SWS_MASK_MAT4
Definition: ops.h:182
SWS_MASK_OFF4
@ SWS_MASK_OFF4
Definition: ops.h:181
avstring.h
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:224
av_bswap16
#define av_bswap16
Definition: bswap.h:28
ff_sws_op_type_name
const char * ff_sws_op_type_name(SwsOpType op)
Definition: ops.c:95
snprintf
#define snprintf
Definition: snprintf.h:34
src
#define src
Definition: vp8dsp.c:248
SWS_MASK_DIAG3
@ SWS_MASK_DIAG3
Definition: ops.h:174
read
static uint32_t BS_FUNC() read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
Definition: bitstream_template.h:239
SWS_MASK_ALPHA
@ SWS_MASK_ALPHA
Definition: ops.h:172
ff_fmt_clear
static void ff_fmt_clear(SwsFormat *fmt)
Definition: format.h:89
min
float min
Definition: vorbis_enc_data.h:429