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/bprint.h"
24 #include "libavutil/bswap.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/rational.h"
27 #include "libavutil/refstruct.h"
28 
29 #include "format.h"
30 #include "ops.h"
31 #include "ops_internal.h"
32 
33 extern const SwsOpBackend backend_c;
34 extern const SwsOpBackend backend_murder;
35 extern const SwsOpBackend backend_x86;
36 extern const SwsOpBackend backend_vulkan;
37 
38 const SwsOpBackend * const ff_sws_op_backends[] = {
40 #if ARCH_X86_64 && HAVE_X86ASM
41  &backend_x86,
42 #endif
43  &backend_c,
44 #if CONFIG_VULKAN
46 #endif
47  NULL
48 };
49 
51 {
52  switch (type) {
53  case SWS_PIXEL_U8: return "u8";
54  case SWS_PIXEL_U16: return "u16";
55  case SWS_PIXEL_U32: return "u32";
56  case SWS_PIXEL_F32: return "f32";
57  case SWS_PIXEL_NONE: return "none";
58  case SWS_PIXEL_TYPE_NB: break;
59  }
60 
61  av_unreachable("Invalid pixel type!");
62  return "ERR";
63 }
64 
66 {
67  switch (type) {
68  case SWS_PIXEL_U8: return sizeof(uint8_t);
69  case SWS_PIXEL_U16: return sizeof(uint16_t);
70  case SWS_PIXEL_U32: return sizeof(uint32_t);
71  case SWS_PIXEL_F32: return sizeof(float);
72  case SWS_PIXEL_NONE: break;
73  case SWS_PIXEL_TYPE_NB: break;
74  }
75 
76  av_unreachable("Invalid pixel type!");
77  return 0;
78 }
79 
81 {
82  switch (type) {
83  case SWS_PIXEL_U8:
84  case SWS_PIXEL_U16:
85  case SWS_PIXEL_U32:
86  return true;
87  case SWS_PIXEL_F32:
88  return false;
89  case SWS_PIXEL_NONE:
90  case SWS_PIXEL_TYPE_NB: break;
91  }
92 
93  av_unreachable("Invalid pixel type!");
94  return false;
95 }
96 
98 {
99  switch (op) {
100  case SWS_OP_READ: return "SWS_OP_READ";
101  case SWS_OP_WRITE: return "SWS_OP_WRITE";
102  case SWS_OP_SWAP_BYTES: return "SWS_OP_SWAP_BYTES";
103  case SWS_OP_SWIZZLE: return "SWS_OP_SWIZZLE";
104  case SWS_OP_UNPACK: return "SWS_OP_UNPACK";
105  case SWS_OP_PACK: return "SWS_OP_PACK";
106  case SWS_OP_LSHIFT: return "SWS_OP_LSHIFT";
107  case SWS_OP_RSHIFT: return "SWS_OP_RSHIFT";
108  case SWS_OP_CLEAR: return "SWS_OP_CLEAR";
109  case SWS_OP_CONVERT: return "SWS_OP_CONVERT";
110  case SWS_OP_MIN: return "SWS_OP_MIN";
111  case SWS_OP_MAX: return "SWS_OP_MAX";
112  case SWS_OP_SCALE: return "SWS_OP_SCALE";
113  case SWS_OP_LINEAR: return "SWS_OP_LINEAR";
114  case SWS_OP_DITHER: return "SWS_OP_DITHER";
115  case SWS_OP_INVALID: return "SWS_OP_INVALID";
116  case SWS_OP_TYPE_NB: break;
117  }
118 
119  av_unreachable("Invalid operation type!");
120  return "ERR";
121 }
122 
123 /* biased towards `a` */
125 {
126  return av_cmp_q(a, b) == 1 ? b : a;
127 }
128 
130 {
131  return av_cmp_q(a, b) == -1 ? b : a;
132 }
133 
135 {
136  uint64_t mask[4];
137  int shift[4];
138 
139  switch (op->op) {
140  case SWS_OP_READ:
141  case SWS_OP_WRITE:
142  return;
143  case SWS_OP_UNPACK: {
146  unsigned val = x[0].num;
147  for (int i = 0; i < 4; i++)
148  x[i] = Q((val >> shift[i]) & mask[i]);
149  return;
150  }
151  case SWS_OP_PACK: {
154  unsigned val = 0;
155  for (int i = 0; i < 4; i++)
156  val |= (x[i].num & mask[i]) << shift[i];
157  x[0] = Q(val);
158  return;
159  }
160  case SWS_OP_SWAP_BYTES:
162  switch (ff_sws_pixel_type_size(op->type)) {
163  case 2:
164  for (int i = 0; i < 4; i++)
165  x[i].num = av_bswap16(x[i].num);
166  break;
167  case 4:
168  for (int i = 0; i < 4; i++)
169  x[i].num = av_bswap32(x[i].num);
170  break;
171  }
172  return;
173  case SWS_OP_CLEAR:
174  for (int i = 0; i < 4; i++) {
175  if (op->c.q4[i].den)
176  x[i] = op->c.q4[i];
177  }
178  return;
179  case SWS_OP_LSHIFT: {
181  AVRational mult = Q(1 << op->c.u);
182  for (int i = 0; i < 4; i++)
183  x[i] = x[i].den ? av_mul_q(x[i], mult) : x[i];
184  return;
185  }
186  case SWS_OP_RSHIFT: {
188  for (int i = 0; i < 4; i++)
189  x[i] = x[i].den ? Q((x[i].num / x[i].den) >> op->c.u) : x[i];
190  return;
191  }
192  case SWS_OP_SWIZZLE: {
193  const AVRational orig[4] = { x[0], x[1], x[2], x[3] };
194  for (int i = 0; i < 4; i++)
195  x[i] = orig[op->swizzle.in[i]];
196  return;
197  }
198  case SWS_OP_CONVERT:
199  if (ff_sws_pixel_type_is_int(op->convert.to)) {
200  const AVRational scale = ff_sws_pixel_expand(op->type, op->convert.to);
201  for (int i = 0; i < 4; i++) {
202  x[i] = x[i].den ? Q(x[i].num / x[i].den) : x[i];
203  if (op->convert.expand)
204  x[i] = av_mul_q(x[i], scale);
205  }
206  }
207  return;
208  case SWS_OP_DITHER:
210  for (int i = 0; i < 4; i++) {
211  if (op->dither.y_offset[i] >= 0 && x[i].den)
212  x[i] = av_add_q(x[i], av_make_q(1, 2));
213  }
214  return;
215  case SWS_OP_MIN:
216  for (int i = 0; i < 4; i++)
217  x[i] = av_min_q(x[i], op->c.q4[i]);
218  return;
219  case SWS_OP_MAX:
220  for (int i = 0; i < 4; i++)
221  x[i] = av_max_q(x[i], op->c.q4[i]);
222  return;
223  case SWS_OP_LINEAR: {
225  const AVRational orig[4] = { x[0], x[1], x[2], x[3] };
226  for (int i = 0; i < 4; i++) {
227  AVRational sum = op->lin.m[i][4];
228  for (int j = 0; j < 4; j++)
229  sum = av_add_q(sum, av_mul_q(orig[j], op->lin.m[i][j]));
230  x[i] = sum;
231  }
232  return;
233  }
234  case SWS_OP_SCALE:
235  for (int i = 0; i < 4; i++)
236  x[i] = x[i].den ? av_mul_q(x[i], op->c.q) : x[i];
237  return;
238  }
239 
240  av_unreachable("Invalid operation type!");
241 }
242 
243 /* merge_comp_flags() forms a monoid with flags_identity as the null element */
246 {
247  const SwsCompFlags flags_or = SWS_COMP_GARBAGE;
248  const SwsCompFlags flags_and = SWS_COMP_ZERO | SWS_COMP_EXACT;
249  return ((a & b) & flags_and) | ((a | b) & flags_or);
250 }
251 
252 /* Linearly propagate flags per component */
253 static void propagate_flags(SwsOp *op, const SwsComps *prev)
254 {
255  for (int i = 0; i < 4; i++)
256  op->comps.flags[i] = prev->flags[i];
257 }
258 
259 /* Clear undefined values in dst with src */
261 {
262  for (int i = 0; i < 4; i++) {
263  if (dst[i].den == 0)
264  dst[i] = src[i];
265  }
266 }
267 
268 /* Infer + propagate known information about components */
270 {
271  SwsComps next = { .unused = {true, true, true, true} };
272  SwsComps prev = { .flags = {
274  }};
275 
276  /* Forwards pass, propagates knowledge about the incoming pixel values */
277  for (int n = 0; n < ops->num_ops; n++) {
278  SwsOp *op = &ops->ops[n];
279 
280  switch (op->op) {
281  case SWS_OP_READ:
282  case SWS_OP_LINEAR:
283  case SWS_OP_SWAP_BYTES:
284  case SWS_OP_UNPACK:
285  break; /* special cases, handled below */
286  default:
287  memcpy(op->comps.min, prev.min, sizeof(prev.min));
288  memcpy(op->comps.max, prev.max, sizeof(prev.max));
289  ff_sws_apply_op_q(op, op->comps.min);
290  ff_sws_apply_op_q(op, op->comps.max);
291  break;
292  }
293 
294  switch (op->op) {
295  case SWS_OP_READ:
296  /* Active components are taken from the user-provided values,
297  * other components are explicitly stripped */
298  for (int i = 0; i < op->rw.elems; i++) {
299  const int idx = op->rw.packed ? i : ops->order_src.in[i];
300  op->comps.flags[i] = ops->comps_src.flags[idx];
301  op->comps.min[i] = ops->comps_src.min[idx];
302  op->comps.max[i] = ops->comps_src.max[idx];
303  }
304  for (int i = op->rw.elems; i < 4; i++) {
305  op->comps.flags[i] = prev.flags[i];
306  op->comps.min[i] = prev.min[i];
307  op->comps.max[i] = prev.max[i];
308  }
309  break;
310  case SWS_OP_SWAP_BYTES:
311  for (int i = 0; i < 4; i++) {
312  op->comps.flags[i] = prev.flags[i] ^ SWS_COMP_SWAPPED;
313  op->comps.min[i] = prev.min[i];
314  op->comps.max[i] = prev.max[i];
315  }
316  break;
317  case SWS_OP_WRITE:
318  for (int i = 0; i < op->rw.elems; i++)
319  av_assert1(!(prev.flags[i] & SWS_COMP_GARBAGE));
320  /* fall through */
321  case SWS_OP_LSHIFT:
322  case SWS_OP_RSHIFT:
323  propagate_flags(op, &prev);
324  break;
325  case SWS_OP_MIN:
326  propagate_flags(op, &prev);
327  clear_undefined_values(op->comps.max, op->c.q4);
328  break;
329  case SWS_OP_MAX:
330  propagate_flags(op, &prev);
331  clear_undefined_values(op->comps.min, op->c.q4);
332  break;
333  case SWS_OP_DITHER:
334  /* Strip zero flag because of the nonzero dithering offset */
335  for (int i = 0; i < 4; i++)
336  op->comps.flags[i] = prev.flags[i] & ~SWS_COMP_ZERO;
337  break;
338  case SWS_OP_UNPACK:
339  for (int i = 0; i < 4; i++) {
340  const int pattern = op->pack.pattern[i];
341  if (pattern) {
342  av_assert1(pattern < 32);
343  op->comps.flags[i] = prev.flags[0];
344  op->comps.min[i] = Q(0);
345  op->comps.max[i] = Q((1ULL << pattern) - 1);
346  } else
347  op->comps.flags[i] = SWS_COMP_GARBAGE;
348  }
349  break;
350  case SWS_OP_PACK: {
352  for (int i = 0; i < 4; i++) {
353  if (op->pack.pattern[i])
354  flags = merge_comp_flags(flags, prev.flags[i]);
355  if (i > 0) /* clear remaining comps for sanity */
356  op->comps.flags[i] = SWS_COMP_GARBAGE;
357  }
358  op->comps.flags[0] = flags;
359  break;
360  }
361  case SWS_OP_CLEAR:
362  for (int i = 0; i < 4; i++) {
363  if (op->c.q4[i].den) {
364  op->comps.flags[i] = 0;
365  if (op->c.q4[i].num == 0)
366  op->comps.flags[i] |= SWS_COMP_ZERO;
367  if (op->c.q4[i].den == 1)
368  op->comps.flags[i] |= SWS_COMP_EXACT;
369  } else {
370  op->comps.flags[i] = prev.flags[i];
371  }
372  }
373  break;
374  case SWS_OP_SWIZZLE:
375  for (int i = 0; i < 4; i++)
376  op->comps.flags[i] = prev.flags[op->swizzle.in[i]];
377  break;
378  case SWS_OP_CONVERT:
379  for (int i = 0; i < 4; i++) {
380  op->comps.flags[i] = prev.flags[i];
381  if (ff_sws_pixel_type_is_int(op->convert.to))
382  op->comps.flags[i] |= SWS_COMP_EXACT;
383  }
384  break;
385  case SWS_OP_LINEAR:
386  for (int i = 0; i < 4; i++) {
388  AVRational min = Q(0), max = Q(0);
389  for (int j = 0; j < 4; j++) {
390  const AVRational k = op->lin.m[i][j];
391  AVRational mink = av_mul_q(prev.min[j], k);
392  AVRational maxk = av_mul_q(prev.max[j], k);
393  if (k.num) {
394  flags = merge_comp_flags(flags, prev.flags[j]);
395  if (k.den != 1) /* fractional coefficient */
396  flags &= ~SWS_COMP_EXACT;
397  if (k.num < 0)
398  FFSWAP(AVRational, mink, maxk);
399  min = av_add_q(min, mink);
400  max = av_add_q(max, maxk);
401  }
402  }
403  if (op->lin.m[i][4].num) { /* nonzero offset */
404  flags &= ~SWS_COMP_ZERO;
405  if (op->lin.m[i][4].den != 1) /* fractional offset */
406  flags &= ~SWS_COMP_EXACT;
407  min = av_add_q(min, op->lin.m[i][4]);
408  max = av_add_q(max, op->lin.m[i][4]);
409  }
410  op->comps.flags[i] = flags;
411  op->comps.min[i] = min;
412  op->comps.max[i] = max;
413  }
414  break;
415  case SWS_OP_SCALE:
416  for (int i = 0; i < 4; i++) {
417  op->comps.flags[i] = prev.flags[i];
418  if (op->c.q.den != 1) /* fractional scale */
419  op->comps.flags[i] &= ~SWS_COMP_EXACT;
420  if (op->c.q.num < 0)
421  FFSWAP(AVRational, op->comps.min[i], op->comps.max[i]);
422  }
423  break;
424 
425  case SWS_OP_INVALID:
426  case SWS_OP_TYPE_NB:
427  av_unreachable("Invalid operation type!");
428  }
429 
430  prev = op->comps;
431  }
432 
433  /* Backwards pass, solves for component dependencies */
434  for (int n = ops->num_ops - 1; n >= 0; n--) {
435  SwsOp *op = &ops->ops[n];
436 
437  switch (op->op) {
438  case SWS_OP_READ:
439  case SWS_OP_WRITE:
440  for (int i = 0; i < op->rw.elems; i++)
441  op->comps.unused[i] = op->op == SWS_OP_READ;
442  for (int i = op->rw.elems; i < 4; i++)
443  op->comps.unused[i] = next.unused[i];
444  break;
445  case SWS_OP_SWAP_BYTES:
446  case SWS_OP_LSHIFT:
447  case SWS_OP_RSHIFT:
448  case SWS_OP_CONVERT:
449  case SWS_OP_DITHER:
450  case SWS_OP_MIN:
451  case SWS_OP_MAX:
452  case SWS_OP_SCALE:
453  for (int i = 0; i < 4; i++)
454  op->comps.unused[i] = next.unused[i];
455  break;
456  case SWS_OP_UNPACK: {
457  bool unused = true;
458  for (int i = 0; i < 4; i++) {
459  if (op->pack.pattern[i])
460  unused &= next.unused[i];
461  op->comps.unused[i] = i > 0;
462  }
463  op->comps.unused[0] = unused;
464  break;
465  }
466  case SWS_OP_PACK:
467  for (int i = 0; i < 4; i++) {
468  if (op->pack.pattern[i])
469  op->comps.unused[i] = next.unused[0];
470  else
471  op->comps.unused[i] = true;
472  }
473  break;
474  case SWS_OP_CLEAR:
475  for (int i = 0; i < 4; i++) {
476  if (op->c.q4[i].den)
477  op->comps.unused[i] = true;
478  else
479  op->comps.unused[i] = next.unused[i];
480  }
481  break;
482  case SWS_OP_SWIZZLE: {
483  bool unused[4] = { true, true, true, true };
484  for (int i = 0; i < 4; i++)
485  unused[op->swizzle.in[i]] &= next.unused[i];
486  for (int i = 0; i < 4; i++)
487  op->comps.unused[i] = unused[i];
488  break;
489  }
490  case SWS_OP_LINEAR:
491  for (int j = 0; j < 4; j++) {
492  bool unused = true;
493  for (int i = 0; i < 4; i++) {
494  if (op->lin.m[i][j].num)
495  unused &= next.unused[i];
496  }
497  op->comps.unused[j] = unused;
498  }
499  break;
500  }
501 
502  next = op->comps;
503  }
504 }
505 
506 static void op_uninit(SwsOp *op)
507 {
508  switch (op->op) {
509  case SWS_OP_DITHER:
510  av_refstruct_unref(&op->dither.matrix);
511  break;
512  }
513 
514  *op = (SwsOp) {0};
515 }
516 
518 {
519  SwsOpList *ops = av_mallocz(sizeof(SwsOpList));
520  if (!ops)
521  return NULL;
522 
523  ops->order_src = ops->order_dst = SWS_SWIZZLE(0, 1, 2, 3);
524  ff_fmt_clear(&ops->src);
525  ff_fmt_clear(&ops->dst);
526  return ops;
527 }
528 
530 {
531  SwsOpList *ops = *p_ops;
532  if (!ops)
533  return;
534 
535  for (int i = 0; i < ops->num_ops; i++)
536  op_uninit(&ops->ops[i]);
537 
538  av_freep(&ops->ops);
539  av_free(ops);
540  *p_ops = NULL;
541 }
542 
544 {
545  SwsOpList *copy = av_malloc(sizeof(*copy));
546  if (!copy)
547  return NULL;
548 
549  int num = ops->num_ops;
550  if (num)
551  num = 1 << av_ceil_log2(num);
552 
553  *copy = *ops;
554  copy->ops = av_memdup(ops->ops, num * sizeof(ops->ops[0]));
555  if (!copy->ops) {
556  av_free(copy);
557  return NULL;
558  }
559 
560  for (int i = 0; i < copy->num_ops; i++) {
561  const SwsOp *op = &copy->ops[i];
562  switch (op->op) {
563  case SWS_OP_DITHER:
564  av_refstruct_ref(op->dither.matrix);
565  break;
566  }
567  }
568 
569  return copy;
570 }
571 
573 {
574  if (!ops->num_ops)
575  return NULL;
576 
577  const SwsOp *read = &ops->ops[0];
578  return read->op == SWS_OP_READ ? read : NULL;
579 }
580 
582 {
583  if (!ops->num_ops)
584  return NULL;
585 
586  const SwsOp *write = &ops->ops[ops->num_ops - 1];
587  return write->op == SWS_OP_WRITE ? write : NULL;
588 }
589 
590 void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
591 {
592  const int end = ops->num_ops - count;
593  av_assert2(index >= 0 && count >= 0 && index + count <= ops->num_ops);
594  for (int i = 0; i < count; i++)
595  op_uninit(&ops->ops[index + i]);
596  for (int i = index; i < end; i++)
597  ops->ops[i] = ops->ops[i + count];
598  ops->num_ops = end;
599 }
600 
602 {
603  void *ret = av_dynarray2_add((void **) &ops->ops, &ops->num_ops, sizeof(*op), NULL);
604  if (!ret) {
605  op_uninit(op);
606  return AVERROR(ENOMEM);
607  }
608 
609  for (int i = ops->num_ops - 1; i > index; i--)
610  ops->ops[i] = ops->ops[i - 1];
611  ops->ops[index] = *op;
612  return 0;
613 }
614 
616 {
617  return ff_sws_op_list_insert_at(ops, ops->num_ops, op);
618 }
619 
621 {
622  if (!ops->num_ops)
623  return true;
624 
625  const SwsOp *read = ff_sws_op_list_input(ops);
626  const SwsOp *write = ff_sws_op_list_output(ops);
627  if (!read || !write || ops->num_ops > 2 ||
628  read->type != write->type ||
629  read->rw.packed != write->rw.packed ||
630  read->rw.elems != write->rw.elems ||
631  read->rw.frac != write->rw.frac)
632  return false;
633 
634  /**
635  * Note that this check is unlikely to ever be hit in practice, since it
636  * would imply the existence of planar formats with different plane orders
637  * between them, e.g. rgbap <-> gbrap, which doesn't currently exist.
638  * However, the check is cheap and lets me sleep at night.
639  */
640  const int num_planes = read->rw.packed ? 1 : read->rw.elems;
641  for (int i = 0; i < num_planes; i++) {
642  if (ops->order_src.in[i] != ops->order_dst.in[i])
643  return false;
644  }
645 
646  return true;
647 }
648 
650 {
651  int max_size = 0;
652  for (int i = 0; i < ops->num_ops; i++) {
653  const int size = ff_sws_pixel_type_size(ops->ops[i].type);
654  max_size = FFMAX(max_size, size);
655  }
656 
657  return max_size;
658 }
659 
661 {
662  uint32_t mask = 0;
663  for (int i = 0; i < 4; i++) {
664  for (int j = 0; j < 5; j++) {
665  if (av_cmp_q(c.m[i][j], Q(i == j)))
666  mask |= SWS_MASK(i, j);
667  }
668  }
669  return mask;
670 }
671 
672 static const char *describe_lin_mask(uint32_t mask)
673 {
674  /* Try to be fairly descriptive without assuming too much */
675  static const struct {
676  char name[24];
677  uint32_t mask;
678  } patterns[] = {
679  { "noop", 0 },
680  { "luma", SWS_MASK_LUMA },
681  { "alpha", SWS_MASK_ALPHA },
682  { "luma+alpha", SWS_MASK_LUMA | SWS_MASK_ALPHA },
683  { "dot3", 0x7 },
684  { "dot4", 0xF },
685  { "row0", SWS_MASK_ROW(0) },
686  { "row0+alpha", SWS_MASK_ROW(0) | SWS_MASK_ALPHA },
687  { "col0", SWS_MASK_COL(0) },
688  { "col0+off3", SWS_MASK_COL(0) | SWS_MASK_OFF3 },
689  { "off3", SWS_MASK_OFF3 },
690  { "off3+alpha", SWS_MASK_OFF3 | SWS_MASK_ALPHA },
691  { "diag3", SWS_MASK_DIAG3 },
692  { "diag4", SWS_MASK_DIAG4 },
693  { "diag3+alpha", SWS_MASK_DIAG3 | SWS_MASK_ALPHA },
694  { "diag3+off3", SWS_MASK_DIAG3 | SWS_MASK_OFF3 },
695  { "diag3+off3+alpha", SWS_MASK_DIAG3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
696  { "diag4+off4", SWS_MASK_DIAG4 | SWS_MASK_OFF4 },
697  { "matrix3", SWS_MASK_MAT3 },
698  { "matrix3+off3", SWS_MASK_MAT3 | SWS_MASK_OFF3 },
699  { "matrix3+off3+alpha", SWS_MASK_MAT3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
700  { "matrix4", SWS_MASK_MAT4 },
701  { "matrix4+off4", SWS_MASK_MAT4 | SWS_MASK_OFF4 },
702  };
703 
704  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
705  if (!(mask & ~patterns[i].mask))
706  return patterns[i].name;
707  }
708 
709  av_unreachable("Invalid linear mask!");
710  return "ERR";
711 }
712 
714 {
715  if (flags & SWS_COMP_GARBAGE)
716  return 'X';
717  else if (flags & SWS_COMP_ZERO)
718  return '0';
719  else if (flags & SWS_COMP_SWAPPED)
720  return 'z';
721  else if (flags & SWS_COMP_EXACT)
722  return '+';
723  else
724  return '.';
725 }
726 
727 static void print_q(AVBPrint *bp, const AVRational q, bool ignore_den0)
728 {
729  if (!q.den && ignore_den0) {
730  av_bprintf(bp, "_");
731  } else if (!q.den) {
732  av_bprintf(bp, "%s", q.num > 0 ? "inf" : q.num < 0 ? "-inf" : "nan");
733  } else if (q.den == 1) {
734  av_bprintf(bp, "%d", q.num);
735  } else if (abs(q.num) > 1000 || abs(q.den) > 1000) {
736  av_bprintf(bp, "%f", av_q2d(q));
737  } else {
738  av_bprintf(bp, "%d/%d", q.num, q.den);
739  }
740 }
741 
742 static void print_q4(AVBPrint *bp, const AVRational q4[4], bool ignore_den0,
743  const bool unused[4])
744 {
745  av_bprintf(bp, "{");
746  for (int i = 0; i < 4; i++) {
747  if (i)
748  av_bprintf(bp, " ");
749  if (unused && unused[i]) {
750  av_bprintf(bp, "_");
751  } else {
752  print_q(bp, q4[i], ignore_den0);
753  }
754  }
755  av_bprintf(bp, "}");
756 }
757 
758 void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op, const bool unused[4])
759 {
760  const char *name = ff_sws_op_type_name(op->op);
761 
762  switch (op->op) {
763  case SWS_OP_INVALID:
764  case SWS_OP_SWAP_BYTES:
765  av_bprintf(bp, "%s", name);
766  break;
767  case SWS_OP_READ:
768  case SWS_OP_WRITE:
769  av_bprintf(bp, "%-20s: %d elem(s) %s >> %d", name,
770  op->rw.elems, op->rw.packed ? "packed" : "planar",
771  op->rw.frac);
772  break;
773  case SWS_OP_LSHIFT:
774  av_bprintf(bp, "%-20s: << %u", name, op->c.u);
775  break;
776  case SWS_OP_RSHIFT:
777  av_bprintf(bp, "%-20s: >> %u", name, op->c.u);
778  break;
779  case SWS_OP_PACK:
780  case SWS_OP_UNPACK:
781  av_bprintf(bp, "%-20s: {%d %d %d %d}", name,
782  op->pack.pattern[0], op->pack.pattern[1],
783  op->pack.pattern[2], op->pack.pattern[3]);
784  break;
785  case SWS_OP_CLEAR:
786  av_bprintf(bp, "%-20s: ", name);
787  print_q4(bp, op->c.q4, true, unused);
788  break;
789  case SWS_OP_SWIZZLE:
790  av_bprintf(bp, "%-20s: %d%d%d%d", name,
791  op->swizzle.x, op->swizzle.y, op->swizzle.z, op->swizzle.w);
792  break;
793  case SWS_OP_CONVERT:
794  av_bprintf(bp, "%-20s: %s -> %s%s", name,
795  ff_sws_pixel_type_name(op->type),
796  ff_sws_pixel_type_name(op->convert.to),
797  op->convert.expand ? " (expand)" : "");
798  break;
799  case SWS_OP_DITHER:
800  av_bprintf(bp, "%-20s: %dx%d matrix + {%d %d %d %d}", name,
801  1 << op->dither.size_log2, 1 << op->dither.size_log2,
802  op->dither.y_offset[0], op->dither.y_offset[1],
803  op->dither.y_offset[2], op->dither.y_offset[3]);
804  break;
805  case SWS_OP_MIN:
806  av_bprintf(bp, "%-20s: x <= ", name);
807  print_q4(bp, op->c.q4, true, unused);
808  break;
809  case SWS_OP_MAX:
810  av_bprintf(bp, "%-20s: ", name);
811  print_q4(bp, op->c.q4, true, unused);
812  av_bprintf(bp, " <= x");
813  break;
814  case SWS_OP_LINEAR:
815  av_bprintf(bp, "%-20s: %s [", name, describe_lin_mask(op->lin.mask));
816  for (int i = 0; i < 4; i++) {
817  av_bprintf(bp, "%s[", i ? " " : "");
818  for (int j = 0; j < 5; j++) {
819  av_bprintf(bp, j ? " " : "");
820  print_q(bp, op->lin.m[i][j], false);
821  }
822  av_bprintf(bp, "]");
823  }
824  av_bprintf(bp, "]");
825  break;
826  case SWS_OP_SCALE:
827  av_bprintf(bp, "%-20s: * %d/%d", name, op->c.q.num, op->c.q.den);
828  break;
829  case SWS_OP_TYPE_NB:
830  break;
831  }
832 }
833 
834 void ff_sws_op_list_print(void *log, int lev, int lev_extra,
835  const SwsOpList *ops)
836 {
837  AVBPrint bp;
838  if (!ops->num_ops) {
839  av_log(log, lev, " (empty)\n");
840  return;
841  }
842 
844 
845  for (int i = 0; i < ops->num_ops; i++) {
846  const SwsOp *op = &ops->ops[i];
847  const SwsOp *next = i + 1 < ops->num_ops ? &ops->ops[i + 1] : op;
848  av_bprint_clear(&bp);
849  av_bprintf(&bp, " [%3s %c%c%c%c -> %c%c%c%c] ",
850  ff_sws_pixel_type_name(op->type),
851  op->comps.unused[0] ? 'X' : '.',
852  op->comps.unused[1] ? 'X' : '.',
853  op->comps.unused[2] ? 'X' : '.',
854  op->comps.unused[3] ? 'X' : '.',
855  next->comps.unused[0] ? 'X' : describe_comp_flags(op->comps.flags[0]),
856  next->comps.unused[1] ? 'X' : describe_comp_flags(op->comps.flags[1]),
857  next->comps.unused[2] ? 'X' : describe_comp_flags(op->comps.flags[2]),
858  next->comps.unused[3] ? 'X' : describe_comp_flags(op->comps.flags[3]));
859 
860  ff_sws_op_desc(&bp, op, next->comps.unused);
861 
862  if (op->op == SWS_OP_READ || op->op == SWS_OP_WRITE) {
863  SwsSwizzleOp order = op->op == SWS_OP_READ ? ops->order_src : ops->order_dst;
864  if (order.mask != SWS_SWIZZLE(0, 1, 2, 3).mask) {
865  const int planes = op->rw.packed ? 1 : op->rw.elems;
866  av_bprintf(&bp, ", via {");
867  for (int i = 0; i < planes; i++)
868  av_bprintf(&bp, "%s%d", i ? ", " : "", order.in[i]);
869  av_bprintf(&bp, "}");
870  }
871  }
872 
874  av_log(log, lev, "%s\n", bp.str);
875 
876  if (op->comps.min[0].den || op->comps.min[1].den ||
877  op->comps.min[2].den || op->comps.min[3].den ||
878  op->comps.max[0].den || op->comps.max[1].den ||
879  op->comps.max[2].den || op->comps.max[3].den)
880  {
881  av_bprint_clear(&bp);
882  av_bprintf(&bp, " min: ");
883  print_q4(&bp, op->comps.min, false, next->comps.unused);
884  av_bprintf(&bp, ", max: ");
885  print_q4(&bp, op->comps.max, false, next->comps.unused);
887  av_log(log, lev_extra, "%s\n", bp.str);
888  }
889 
890  }
891 
892  av_log(log, lev, " (X = unused, z = byteswapped, + = exact, 0 = zero)\n");
893 }
894 
895 static int enum_ops_fmt(SwsContext *ctx, void *opaque,
896  enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
897  int (*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
898 {
899  int ret;
902  if (!ops)
903  return AVERROR(ENOMEM);
904 
905  ff_fmt_from_pixfmt(src_fmt, &ops->src);
906  ff_fmt_from_pixfmt(dst_fmt, &ops->dst);
907  ops->src.width = ops->dst.width = 16;
908  ops->src.height = ops->dst.height = 16;
909 
910  bool incomplete = ff_infer_colors(&ops->src.color, &ops->dst.color);
911  if (ff_sws_decode_pixfmt(ops, src_fmt) < 0 ||
912  ff_sws_decode_colors(ctx, type, ops, &ops->src, &incomplete) < 0 ||
913  ff_sws_encode_colors(ctx, type, ops, &ops->src, &ops->dst, &incomplete) < 0 ||
914  ff_sws_encode_pixfmt(ops, dst_fmt) < 0)
915  {
916  ret = 0; /* silently skip unsupported formats */
917  goto fail;
918  }
919 
921  if (ret < 0)
922  goto fail;
923 
924  ret = cb(ctx, opaque, ops);
925  if (ret < 0)
926  goto fail;
927 
928 fail:
929  ff_sws_op_list_free(&ops);
930  return ret;
931 }
932 
934  enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
935  int (*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
936 {
937  const AVPixFmtDescriptor *src_start = av_pix_fmt_desc_next(NULL);
938  const AVPixFmtDescriptor *dst_start = src_start;
939  if (src_fmt != AV_PIX_FMT_NONE)
940  src_start = av_pix_fmt_desc_get(src_fmt);
941  if (dst_fmt != AV_PIX_FMT_NONE)
942  dst_start = av_pix_fmt_desc_get(dst_fmt);
943 
944  const AVPixFmtDescriptor *src, *dst;
945  for (src = src_start; src; src = av_pix_fmt_desc_next(src)) {
946  const enum AVPixelFormat src_f = av_pix_fmt_desc_get_id(src);
947  for (dst = dst_start; dst; dst = av_pix_fmt_desc_next(dst)) {
948  const enum AVPixelFormat dst_f = av_pix_fmt_desc_get_id(dst);
949  int ret = enum_ops_fmt(ctx, opaque, src_f, dst_f, cb);
950  if (ret < 0)
951  return ret;
952  if (dst_fmt != AV_PIX_FMT_NONE)
953  break;
954  }
955  if (src_fmt != AV_PIX_FMT_NONE)
956  break;
957  }
958 
959  return 0;
960 }
961 
962 struct EnumOpaque {
963  void *opaque;
964  int (*cb)(SwsContext *ctx, void *opaque, SwsOp *op);
965 };
966 
967 static int enum_ops(SwsContext *ctx, void *opaque, SwsOpList *ops)
968 {
969  struct EnumOpaque *priv = opaque;
970  for (int i = 0; i < ops->num_ops; i++) {
971  int ret = priv->cb(ctx, priv->opaque, &ops->ops[i]);
972  if (ret < 0)
973  return ret;
974  }
975  return 0;
976 }
977 
979  enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
980  int (*cb)(SwsContext *ctx, void *opaque, SwsOp *op))
981 {
982  struct EnumOpaque priv = { opaque, cb };
983  return ff_sws_enum_op_lists(ctx, &priv, src_fmt, dst_fmt, enum_ops);
984 }
SWS_OP_READ
@ SWS_OP_READ
Definition: ops.h:49
flags
const SwsFlags flags[]
Definition: swscale.c:71
ff_sws_enum_ops
int ff_sws_enum_ops(SwsContext *ctx, void *opaque, enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int(*cb)(SwsContext *ctx, void *opaque, SwsOp *op))
Helper function to enumerate over all possible operations, under the current set of options in ctx,...
Definition: ops.c:978
print_q
static void print_q(AVBPrint *bp, const AVRational q, bool ignore_den0)
Definition: ops.c:727
SWS_PIXEL_U16
@ SWS_PIXEL_U16
Definition: ops.h:35
ff_sws_op_list_free
void ff_sws_op_list_free(SwsOpList **p_ops)
Definition: ops.c:529
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
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:52
ff_sws_op_list_alloc
SwsOpList * ff_sws_op_list_alloc(void)
Definition: ops.c:517
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:218
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:57
SWS_OP_UNPACK
@ SWS_OP_UNPACK
Definition: ops.h:55
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:543
SwsSwizzleOp::mask
uint32_t mask
Definition: ops.h:130
SWS_MASK_OFF4
@ SWS_MASK_OFF4
Definition: ops.h:183
ff_sws_op_desc
void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op, const bool unused[4])
Describe an operation in human-readable form.
Definition: ops.c:758
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:247
av_min_q
static AVRational av_min_q(AVRational a, AVRational b)
Definition: ops.c:124
SwsOpList::comps_src
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
Definition: ops.h:250
merge_comp_flags
static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
Definition: ops.c:245
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:572
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
SWS_COMP_ZERO
@ SWS_COMP_ZERO
Definition: ops.h:79
SWS_OP_CLEAR
@ SWS_OP_CLEAR
Definition: ops.h:61
ff_sws_linear_mask
uint32_t ff_sws_linear_mask(const SwsLinearOp c)
Definition: ops.c:660
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:649
backend_x86
const SwsOpBackend backend_x86
Definition: ops.c:780
SwsComps::unused
bool unused[4]
Definition: ops.h:95
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:615
normalize.log
log
Definition: normalize.py:21
mask
int mask
Definition: mediacodecdec_common.c:154
SwsOp::rw
SwsReadWriteOp rw
Definition: ops.h:195
ff_sws_decode_colors
int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops, const SwsFormat *fmt, bool *incomplete)
Append a set of operations for transforming decoded pixel values to/from normalized RGB in the specif...
backend_vulkan
const SwsOpBackend backend_vulkan
Definition: ops.c:423
ops.h
SWS_OP_DITHER
@ SWS_OP_DITHER
Definition: ops.h:69
describe_comp_flags
static char describe_comp_flags(SwsCompFlags flags)
Definition: ops.c:713
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
av_pix_fmt_desc_next
const AVPixFmtDescriptor * av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev)
Iterate over all pixel format descriptors known to libavutil.
Definition: pixdesc.c:3463
enum_ops_fmt
static int enum_ops_fmt(SwsContext *ctx, void *opaque, enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int(*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
Definition: ops.c:895
max
#define max(a, b)
Definition: cuda_runtime.h:33
SWS_PIXEL_U32
@ SWS_PIXEL_U32
Definition: ops.h:36
SWS_OP_TYPE_NB
@ SWS_OP_TYPE_NB
Definition: ops.h:71
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
format.h
enum_ops
static int enum_ops(SwsContext *ctx, void *opaque, SwsOpList *ops)
Definition: ops.c:967
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:65
clear_undefined_values
static void clear_undefined_values(AVRational dst[4], const AVRational src[4])
Definition: ops.c:260
SWS_MASK_ROW
#define SWS_MASK_ROW(I)
Definition: ops.h:168
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:32
SwsComps::max
AVRational max[4]
Definition: ops.h:99
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:834
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: ops.h:37
ff_sws_op_backends
const SwsOpBackend *const ff_sws_op_backends[]
Definition: ops.c:38
SWS_MASK_LUMA
@ SWS_MASK_LUMA
Definition: ops.h:173
av_ceil_log2
#define av_ceil_log2
Definition: common.h:97
fail
#define fail()
Definition: checkasm.h:222
SwsOpList::num_ops
int num_ops
Definition: ops.h:233
SwsCompFlags
SwsCompFlags
Definition: ops.h:76
SWS_MASK_COL
#define SWS_MASK_COL(J)
Definition: ops.h:169
SWS_PIXEL_U8
@ SWS_PIXEL_U8
Definition: ops.h:34
SwsSwizzleOp
Definition: ops.h:124
AV_BPRINT_SIZE_AUTOMATIC
#define AV_BPRINT_SIZE_AUTOMATIC
ff_sws_pixel_type_is_int
bool ff_sws_pixel_type_is_int(SwsPixelType type)
Definition: ops.c:80
val
static double val(void *priv, double ch)
Definition: aeval.c:77
flags_identity
static const SwsCompFlags flags_identity
Definition: ops.c:244
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
SWS_MASK_MAT4
@ SWS_MASK_MAT4
Definition: ops.h:184
refstruct.h
SwsOp::op
SwsOpType op
Definition: ops.h:191
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:65
avassert.h
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
SwsFormat::height
int height
Definition: format.h:78
SWS_MASK_OFF3
@ SWS_MASK_OFF3
Definition: ops.h:177
float
float
Definition: af_crystalizer.c:122
SWS_SWIZZLE
#define SWS_SWIZZLE(X, Y, Z, W)
Definition: ops.h:136
SwsComps::min
AVRational min[4]
Definition: ops.h:99
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:106
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
SWS_OP_MIN
@ SWS_OP_MIN
Definition: ops.h:63
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
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:68
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:581
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
SwsOpBackend
Definition: ops_internal.h:55
SWS_OP_PACK
@ SWS_OP_PACK
Definition: ops.h:56
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:620
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:104
ff_infer_colors
bool ff_infer_colors(SwsColor *src, SwsColor *dst)
Definition: format.c:539
SWS_COMP_GARBAGE
@ SWS_COMP_GARBAGE
Definition: ops.h:77
print_q4
static void print_q4(AVBPrint *bp, const AVRational q4[4], bool ignore_den0, const bool unused[4])
Definition: ops.c:742
SwsOpType
SwsOpType
Definition: ops.h:45
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:590
SWS_MASK
#define SWS_MASK(I, J)
Definition: ops.h:166
SWS_PIXEL_NONE
@ SWS_PIXEL_NONE
Definition: ops.h:33
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:134
SWS_MASK_MAT3
@ SWS_MASK_MAT3
Definition: ops.h:178
SwsOpList::order_dst
SwsSwizzleOp order_dst
Definition: ops.h:239
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:192
ff_sws_op_list_insert_at
int ff_sws_op_list_insert_at(SwsOpList *ops, int index, SwsOp *op)
Definition: ops.c:601
size
int size
Definition: twinvq_data.h:10344
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:58
SwsOpList::src
SwsFormat src
Definition: ops.h:236
SWS_OP_INVALID
@ SWS_OP_INVALID
Definition: ops.h:46
ff_sws_op_list_update_comps
void ff_sws_op_list_update_comps(SwsOpList *ops)
Infer + propagate known information about components.
Definition: ops.c:269
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:50
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:506
SwsOp::comps
SwsComps comps
Metadata about the operation's input/output components.
Definition: ops.h:210
av_pix_fmt_desc_get_id
enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc)
Definition: pixdesc.c:3475
SwsLinearOp
Definition: ops.h:149
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
EnumOpaque::opaque
void * opaque
Definition: ops.c:963
ff_sws_op_list_optimize
int ff_sws_op_list_optimize(SwsOpList *ops)
Fuse compatible and eliminate redundant operations, as well as replacing some operations with more ef...
Definition: ops_optimizer.c:283
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
ff_fmt_from_pixfmt
void ff_fmt_from_pixfmt(enum AVPixelFormat pixfmt, SwsFormat *fmt)
Subset of ff_fmt_from_frame() that sets default metadata for the format.
Definition: format.c:482
bprint.h
SWS_MASK_DIAG4
@ SWS_MASK_DIAG4
Definition: ops.h:182
av_max_q
static AVRational av_max_q(AVRational a, AVRational b)
Definition: ops.c:129
SwsOpList::ops
SwsOp * ops
Definition: ops.h:232
SwsOpList::order_src
SwsSwizzleOp order_src
Definition: ops.h:239
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:58
ff_sws_encode_colors
int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops, const SwsFormat *src, const SwsFormat *dst, bool *incomplete)
ops_internal.h
SWS_MASK_ALPHA
@ SWS_MASK_ALPHA
Definition: ops.h:174
SwsFormat::width
int width
Definition: format.h:78
ff_sws_enum_op_lists
int ff_sws_enum_op_lists(SwsContext *ctx, void *opaque, enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, int(*cb)(SwsContext *ctx, void *opaque, SwsOpList *ops))
Helper function to enumerate over all possible (optimized) operation lists, under the current set of ...
Definition: ops.c:933
lev
static LevelCodes lev[4+3+3]
Definition: clearvideo.c:80
SwsOp
Definition: ops.h:190
ff_sws_decode_pixfmt
int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
Append a set of operations for decoding/encoding raw pixels.
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:94
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_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:236
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:64
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
SWS_PIXEL_TYPE_NB
@ SWS_PIXEL_TYPE_NB
Definition: ops.h:38
SwsComps
Definition: ops.h:93
EnumOpaque::cb
int(* cb)(SwsContext *ctx, void *opaque, SwsOp *op)
Definition: ops.c:964
AVRational::den
int den
Denominator.
Definition: rational.h:60
SWS_COMP_SWAPPED
@ SWS_COMP_SWAPPED
Definition: ops.h:80
SwsReadWriteOp::packed
bool packed
Definition: ops.h:105
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
ff_sws_pixel_type_name
const char * ff_sws_pixel_type_name(SwsPixelType type)
Definition: ops.c:50
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
SWS_OP_SWAP_BYTES
@ SWS_OP_SWAP_BYTES
Definition: ops.h:51
SwsFormat::color
SwsColor color
Definition: format.h:86
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:78
describe_lin_mask
static const char * describe_lin_mask(uint32_t mask)
Definition: ops.c:672
SwsReadWriteOp::elems
uint8_t elems
Definition: ops.h:103
mem.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
planes
static const struct @570 planes[]
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
EnumOpaque
Definition: ops.c:962
SwsSwizzleOp::in
uint8_t in[4]
Definition: ops.h:131
SWS_OP_CONVERT
@ SWS_OP_CONVERT
Definition: ops.h:62
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:253
avstring.h
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:231
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:97
SWS_MASK_DIAG3
@ SWS_MASK_DIAG3
Definition: ops.h:176
unused
static const bool unused[4]
Definition: sws_ops.c:53
SwsContext
Main external API structure.
Definition: swscale.h:206
src
#define src
Definition: vp8dsp.c:248
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
ff_sws_encode_pixfmt
int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
ff_fmt_clear
static void ff_fmt_clear(SwsFormat *fmt)
Definition: format.h:89
min
float min
Definition: vorbis_enc_data.h:429