FFmpeg
sw_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 modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <string.h>
22 
23 #include "libavutil/avassert.h"
24 #include "libavutil/mem_internal.h"
25 #include "libavutil/refstruct.h"
26 
27 #include "libswscale/ops.h"
29 
30 #include "checkasm.h"
31 
32 enum {
33  NB_PLANES = 4,
34  PIXELS = 64,
35  LINES = 16,
36 };
37 
38 enum {
43 };
44 
45 #define FMT(fmt, ...) tprintf((char[256]) {0}, 256, fmt, __VA_ARGS__)
46 static const char *tprintf(char buf[], size_t size, const char *fmt, ...)
47 {
48  va_list ap;
49  va_start(ap, fmt);
50  vsnprintf(buf, size, fmt, ap);
51  va_end(ap);
52  return buf;
53 }
54 
55 static int rw_pixel_bits(const SwsOp *op)
56 {
57  const int elems = op->rw.packed ? op->rw.elems : 1;
58  const int size = ff_sws_pixel_type_size(op->type);
59  const int bits = 8 >> op->rw.frac;
60  av_assert1(bits >= 1);
61  return elems * size * bits;
62 }
63 
64 static float rndf(void)
65 {
66  union { uint32_t u; float f; } x;
67  do {
68  x.u = rnd();
69  } while (!isnormal(x.f));
70  return x.f;
71 }
72 
73 static void fill32f(float *line, int num, unsigned range)
74 {
75  const float scale = (float) range / UINT32_MAX;
76  for (int i = 0; i < num; i++)
77  line[i] = range ? scale * rnd() : rndf();
78 }
79 
80 static void fill32(uint32_t *line, int num, unsigned range)
81 {
82  for (int i = 0; i < num; i++)
83  line[i] = (range && range < UINT_MAX) ? rnd() % (range + 1) : rnd();
84 }
85 
86 static void fill16(uint16_t *line, int num, unsigned range)
87 {
88  if (!range) {
89  fill32((uint32_t *) line, AV_CEIL_RSHIFT(num, 1), 0);
90  } else {
91  for (int i = 0; i < num; i++)
92  line[i] = rnd() % (range + 1);
93  }
94 }
95 
96 static void fill8(uint8_t *line, int num, unsigned range)
97 {
98  if (!range) {
99  fill32((uint32_t *) line, AV_CEIL_RSHIFT(num, 2), 0);
100  } else {
101  for (int i = 0; i < num; i++)
102  line[i] = rnd() % (range + 1);
103  }
104 }
105 
106 static void set_range(AVRational *rangeq, unsigned range, unsigned range_def)
107 {
108  if (!range)
109  range = range_def;
110  if (range && range <= INT_MAX)
111  *rangeq = (AVRational) { range, 1 };
112 }
113 
114 static void check_compiled(const char *name,
115  const SwsOp *read_op, const SwsOp *write_op,
116  const int ranges[NB_PLANES],
117  const SwsCompiledOp *comp_ref,
118  const SwsCompiledOp *comp_new)
119 {
120  /**
121  * We can't use `check_func()` alone because the actual function pointer
122  * may be a wrapper or entry point shared by multiple implementations.
123  * Solve it by hashing in the active CPU flags as well.
124  */
125  uintptr_t id = (uintptr_t) comp_new->func;
126  id ^= (id << 6) + (id >> 2) + 0x9e3779b97f4a7c15 + comp_new->cpu_flags;
127  if (!check_key(id, "%s", name))
128  return;
129 
130  declare_func(void, const SwsOpExec *, const void *, int bx, int y, int bx_end, int y_end);
131 
132  static DECLARE_ALIGNED_64(char, src0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
133  static DECLARE_ALIGNED_64(char, src1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
134  static DECLARE_ALIGNED_64(char, dst0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
135  static DECLARE_ALIGNED_64(char, dst1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
136 
137  av_assert0(PIXELS % comp_new->block_size == 0);
138  for (int p = 0; p < NB_PLANES; p++) {
139  void *plane = src0[p];
140  switch (read_op->type) {
141  case U8:
142  fill8(plane, sizeof(src0[p]) / sizeof(uint8_t), ranges[p]);
143  break;
144  case U16:
145  fill16(plane, sizeof(src0[p]) / sizeof(uint16_t), ranges[p]);
146  break;
147  case U32:
148  fill32(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
149  break;
150  case F32:
151  fill32f(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
152  break;
153  }
154  }
155 
156  memcpy(src1, src0, sizeof(src0));
157  memset(dst0, 0, sizeof(dst0));
158  memset(dst1, 0, sizeof(dst1));
159 
160  const int read_size = PIXELS * rw_pixel_bits(read_op) >> 3;
161  const int write_size = PIXELS * rw_pixel_bits(write_op) >> 3;
162 
163  SwsOpExec exec = {0};
164  exec.width = PIXELS;
165  exec.height = exec.slice_h = LINES;
166  for (int i = 0; i < NB_PLANES; i++) {
167  exec.in_stride[i] = sizeof(src0[i][0]);
168  exec.out_stride[i] = sizeof(dst0[i][0]);
169  exec.in_bump[i] = exec.in_stride[i] - read_size;
170  exec.out_bump[i] = exec.out_stride[i] - write_size;
171  }
172 
173  int32_t in_bump_y[LINES];
174  if (read_op->rw.filter == SWS_OP_FILTER_V) {
175  const int *offsets = read_op->rw.kernel->offsets;
176  for (int y = 0; y < LINES - 1; y++)
177  in_bump_y[y] = offsets[y + 1] - offsets[y] - 1;
178  in_bump_y[LINES - 1] = 0;
179  exec.in_bump_y = in_bump_y;
180  }
181 
182  int32_t in_offset_x[PIXELS];
183  if (read_op->rw.filter == SWS_OP_FILTER_H) {
184  const int *offsets = read_op->rw.kernel->offsets;
185  const int rw_bits = rw_pixel_bits(read_op);
186  for (int x = 0; x < PIXELS; x++)
187  in_offset_x[x] = offsets[x] * rw_bits >> 3;
188  exec.in_offset_x = in_offset_x;
189  }
190 
191  exec.block_size_in = comp_ref->block_size * rw_pixel_bits(read_op) >> 3;
192  exec.block_size_out = comp_ref->block_size * rw_pixel_bits(write_op) >> 3;
193  for (int i = 0; i < NB_PLANES; i++) {
194  exec.in[i] = (void *) src0[i];
195  exec.out[i] = (void *) dst0[i];
196  }
197  checkasm_call(comp_ref->func, &exec, comp_ref->priv, 0, 0, PIXELS / comp_ref->block_size, LINES);
198 
199  exec.block_size_in = comp_new->block_size * rw_pixel_bits(read_op) >> 3;
200  exec.block_size_out = comp_new->block_size * rw_pixel_bits(write_op) >> 3;
201  for (int i = 0; i < NB_PLANES; i++) {
202  exec.in[i] = (void *) src1[i];
203  exec.out[i] = (void *) dst1[i];
204  }
205  checkasm_call_checked(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
206 
207  for (int i = 0; i < NB_PLANES; i++) {
208  const char *desc = FMT("%s[%d]", name, i);
209  const int stride = sizeof(dst0[i][0]);
210 
211  switch (write_op->type) {
212  case U8:
213  checkasm_check(uint8_t, (void *) dst0[i], stride,
214  (void *) dst1[i], stride,
215  write_size, LINES, desc);
216  break;
217  case U16:
218  checkasm_check(uint16_t, (void *) dst0[i], stride,
219  (void *) dst1[i], stride,
220  write_size >> 1, LINES, desc);
221  break;
222  case U32:
223  checkasm_check(uint32_t, (void *) dst0[i], stride,
224  (void *) dst1[i], stride,
225  write_size >> 2, LINES, desc);
226  break;
227  case F32:
228  checkasm_check(float_ulp, (void *) dst0[i], stride,
229  (void *) dst1[i], stride,
230  write_size >> 2, LINES, desc, 0);
231  break;
232  }
233 
234  if (write_op->rw.packed)
235  break;
236  }
237 
238  bench(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
239 }
240 
241 static void check_ops(const char *name, const unsigned ranges[NB_PLANES],
242  const SwsOp *ops)
243 {
245  if (!ctx)
246  return;
248 
249  static const unsigned def_ranges[4] = {0};
250  if (!ranges)
251  ranges = def_ranges;
252 
253  const SwsOp *read_op, *write_op;
254  SwsOpList oplist = {
255  .ops = (SwsOp *) ops,
256  .plane_src = {0, 1, 2, 3},
257  .plane_dst = {0, 1, 2, 3},
258  };
259 
260  read_op = &ops[0];
261  for (oplist.num_ops = 0; ops[oplist.num_ops].op; oplist.num_ops++)
262  write_op = &ops[oplist.num_ops];
263 
264  for (int p = 0; p < NB_PLANES; p++) {
265  switch (read_op->type) {
266  case U8:
267  set_range(&oplist.comps_src.max[p], ranges[p], UINT8_MAX);
268  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
269  break;
270  case U16:
271  set_range(&oplist.comps_src.max[p], ranges[p], UINT16_MAX);
272  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
273  break;
274  case U32:
275  set_range(&oplist.comps_src.max[p], ranges[p], UINT32_MAX);
276  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
277  break;
278  case F32:
279  if (ranges[p] && ranges[p] <= INT_MAX) {
280  oplist.comps_src.max[p] = (AVRational) { ranges[p], 1 };
281  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
282  }
283  break;
284  }
285  }
286 
287  static const SwsOpBackend *backend_ref;
288  if (!backend_ref) {
289  for (int n = 0; ff_sws_op_backends[n]; n++) {
290  if (!strcmp(ff_sws_op_backends[n]->name, "c")) {
291  backend_ref = ff_sws_op_backends[n];
292  break;
293  }
294  }
295  av_assert0(backend_ref);
296  }
297 
298  /* Always compile `ops` using the C backend as a reference */
299  SwsCompiledOp comp_ref = {0};
300  int ret = ff_sws_ops_compile(ctx, backend_ref, &oplist, &comp_ref);
301  if (ret < 0) {
302  av_assert0(ret != AVERROR(ENOTSUP));
303  fail();
304  goto done;
305  }
306 
307  /* Check with the C backend to establish a reference */
308  check_compiled(name, read_op, write_op, ranges, &comp_ref, &comp_ref);
309 
310  /* Iterate over every other backend, and test it against the C reference */
311  for (int n = 0; ff_sws_op_backends[n]; n++) {
312  const SwsOpBackend *backend = ff_sws_op_backends[n];
313  if (backend->hw_format != AV_PIX_FMT_NONE || backend == backend_ref)
314  continue;
315 
316  SwsCompiledOp comp_new = {0};
317  int ret = ff_sws_ops_compile(ctx, backend, &oplist, &comp_new);
318  if (ret == AVERROR(ENOTSUP)) {
319  continue;
320  } else if (ret < 0) {
321  fail();
322  goto done;
323  }
324 
325  /* Distinguish backends from each other even with same CPU flags */
327  check_compiled(name, read_op, write_op, ranges, &comp_ref, &comp_new);
328  ff_sws_compiled_op_unref(&comp_new);
329  }
330 
331 done:
332  ff_sws_compiled_op_unref(&comp_ref);
334 }
335 
336 #define CHECK_RANGES(NAME, RANGES, N_IN, N_OUT, IN, OUT, ...) \
337  do { \
338  check_ops(NAME, RANGES, (SwsOp[]) { \
339  { \
340  .op = SWS_OP_READ, \
341  .type = IN, \
342  .rw.elems = N_IN, \
343  }, \
344  __VA_ARGS__, \
345  { \
346  .op = SWS_OP_WRITE, \
347  .type = OUT, \
348  .rw.elems = N_OUT, \
349  }, {0} \
350  }); \
351  } while (0)
352 
353 #define MK_RANGES(R) ((const unsigned[]) { R, R, R, R })
354 #define CHECK_RANGE(NAME, RANGE, N_IN, N_OUT, IN, OUT, ...) \
355  CHECK_RANGES(NAME, MK_RANGES(RANGE), N_IN, N_OUT, IN, OUT, __VA_ARGS__)
356 
357 #define CHECK_COMMON_RANGE(NAME, RANGE, IN, OUT, ...) \
358  CHECK_RANGE(FMT("%s_p1000", NAME), RANGE, 4, 4, IN, OUT, __VA_ARGS__); \
359  CHECK_RANGE(FMT("%s_p1110", NAME), RANGE, 4, 4, IN, OUT, __VA_ARGS__); \
360  CHECK_RANGE(FMT("%s_p1111", NAME), RANGE, 4, 4, IN, OUT, __VA_ARGS__); \
361  CHECK_RANGE(FMT("%s_p1001", NAME), RANGE, 4, 4, IN, OUT, __VA_ARGS__, { \
362  .op = SWS_OP_SWIZZLE, \
363  .type = OUT, \
364  .swizzle = SWS_SWIZZLE(0, 3, 1, 2), \
365  })
366 
367 #define CHECK(NAME, N_IN, N_OUT, IN, OUT, ...) \
368  CHECK_RANGE(NAME, 0, N_IN, N_OUT, IN, OUT, __VA_ARGS__)
369 
370 #define CHECK_COMMON(NAME, IN, OUT, ...) \
371  CHECK_COMMON_RANGE(NAME, 0, IN, OUT, __VA_ARGS__)
372 
373 static void check_read_write(void)
374 {
375  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
376  const char *type = ff_sws_pixel_type_name(t);
377  for (int i = 1; i <= 4; i++) {
378  /* Test N->N planar read/write */
379  for (int o = 1; o <= i; o++) {
380  check_ops(FMT("rw_%d_%d_%s", i, o, type), NULL, (SwsOp[]) {
381  {
382  .op = SWS_OP_READ,
383  .type = t,
384  .rw.elems = i,
385  }, {
386  .op = SWS_OP_WRITE,
387  .type = t,
388  .rw.elems = o,
389  }, {0}
390  });
391  }
392 
393  /* Test packed read/write */
394  if (i == 1)
395  continue;
396 
397  check_ops(FMT("read_packed%d_%s", i, type), NULL, (SwsOp[]) {
398  {
399  .op = SWS_OP_READ,
400  .type = t,
401  .rw.elems = i,
402  .rw.packed = true,
403  }, {
404  .op = SWS_OP_WRITE,
405  .type = t,
406  .rw.elems = i,
407  }, {0}
408  });
409 
410  check_ops(FMT("write_packed%d_%s", i, type), NULL, (SwsOp[]) {
411  {
412  .op = SWS_OP_READ,
413  .type = t,
414  .rw.elems = i,
415  }, {
416  .op = SWS_OP_WRITE,
417  .type = t,
418  .rw.elems = i,
419  .rw.packed = true,
420  }, {0}
421  });
422  }
423  }
424 
425  /* Test fractional reads/writes */
426  for (int frac = 1; frac <= 3; frac++) {
427  const int bits = 8 >> frac;
428  const int range = (1 << bits) - 1;
429  if (bits == 2)
430  continue; /* no 2 bit packed formats currently exist */
431 
432  check_ops(FMT("read_frac%d", frac), NULL, (SwsOp[]) {
433  {
434  .op = SWS_OP_READ,
435  .type = U8,
436  .rw.elems = 1,
437  .rw.frac = frac,
438  }, {
439  .op = SWS_OP_WRITE,
440  .type = U8,
441  .rw.elems = 1,
442  }, {0}
443  });
444 
445  check_ops(FMT("write_frac%d", frac), MK_RANGES(range), (SwsOp[]) {
446  {
447  .op = SWS_OP_READ,
448  .type = U8,
449  .rw.elems = 1,
450  }, {
451  .op = SWS_OP_WRITE,
452  .type = U8,
453  .rw.elems = 1,
454  .rw.frac = frac,
455  }, {0}
456  });
457  }
458 }
459 
460 static void check_swap_bytes(void)
461 {
462  CHECK_COMMON("swap_bytes_16", U16, U16, {
463  .op = SWS_OP_SWAP_BYTES,
464  .type = U16,
465  });
466 
467  CHECK_COMMON("swap_bytes_32", U32, U32, {
468  .op = SWS_OP_SWAP_BYTES,
469  .type = U32,
470  });
471 }
472 
473 static void check_pack_unpack(void)
474 {
475  const struct {
477  SwsPackOp op;
478  } patterns[] = {
479  { U8, {{ 3, 3, 2 }}},
480  { U8, {{ 2, 3, 3 }}},
481  { U8, {{ 1, 2, 1 }}},
482  {U16, {{ 5, 6, 5 }}},
483  {U16, {{ 5, 5, 5 }}},
484  {U16, {{ 4, 4, 4 }}},
485  {U32, {{ 2, 10, 10, 10 }}},
486  {U32, {{10, 10, 10, 2 }}},
487  };
488 
489  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
490  const SwsPixelType type = patterns[i].type;
491  const SwsPackOp pack = patterns[i].op;
492  const int num = pack.pattern[3] ? 4 : 3;
493  const char *pat = FMT("%d%d%d%d", pack.pattern[0], pack.pattern[1],
494  pack.pattern[2], pack.pattern[3]);
495  const int total = pack.pattern[0] + pack.pattern[1] +
496  pack.pattern[2] + pack.pattern[3];
497  const unsigned ranges[4] = {
498  (1 << pack.pattern[0]) - 1,
499  (1 << pack.pattern[1]) - 1,
500  (1 << pack.pattern[2]) - 1,
501  (1 << pack.pattern[3]) - 1,
502  };
503 
504  CHECK_RANGES(FMT("pack_%s", pat), ranges, num, 1, type, type, {
505  .op = SWS_OP_PACK,
506  .type = type,
507  .pack = pack,
508  });
509 
510  CHECK_RANGE(FMT("unpack_%s", pat), UINT32_MAX >> (32 - total), 1, num, type, type, {
511  .op = SWS_OP_UNPACK,
512  .type = type,
513  .pack = pack,
514  });
515  }
516 }
517 
519 {
520  const unsigned num = rnd();
521  if (ff_sws_pixel_type_is_int(t)) {
522  const unsigned mask = UINT_MAX >> (32 - ff_sws_pixel_type_size(t) * 8);
523  return (AVRational) { num & mask, 1 };
524  } else {
525  const unsigned den = rnd();
526  return (AVRational) { num, den ? den : 1 };
527  }
528 }
529 
530 static void check_clear(void)
531 {
532  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
533  const char *type = ff_sws_pixel_type_name(t);
534  const int bits = ff_sws_pixel_type_size(t) * 8;
535 
536  /* TODO: AVRational can't fit 32 bit constants */
537  if (bits < 32) {
538  const AVRational chroma = (AVRational) { 1 << (bits - 1), 1};
539  const AVRational alpha = (AVRational) { (1 << bits) - 1, 1};
540  const AVRational zero = (AVRational) { 0, 1};
541  const AVRational none = {0};
542 
543  const AVRational patterns[][4] = {
544  /* Zero only */
545  { none, none, none, zero },
546  { zero, none, none, none },
547  /* Alpha only */
548  { none, none, none, alpha },
549  { alpha, none, none, none },
550  /* Chroma only */
551  { chroma, chroma, none, none },
552  { none, chroma, chroma, none },
553  { none, none, chroma, chroma },
554  { chroma, none, chroma, none },
555  { none, chroma, none, chroma },
556  /* Alpha+chroma */
557  { chroma, chroma, none, alpha },
558  { none, chroma, chroma, alpha },
559  { alpha, none, chroma, chroma },
560  { chroma, none, chroma, alpha },
561  { alpha, chroma, none, chroma },
562  };
563 
564  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
565  SwsClearOp clear = { .mask = ff_sws_comp_mask_q4(patterns[i]) };
566  memcpy(clear.value, patterns[i], sizeof(clear.value));
567  CHECK(FMT("clear_pattern_%s[%d]", type, i), 4, 4, t, t, {
568  .op = SWS_OP_CLEAR,
569  .type = t,
570  .clear = clear,
571  });
572  }
573  } else if (!ff_sws_pixel_type_is_int(t)) {
574  /* Floating point YUV doesn't exist, only alpha needs to be cleared */
575  CHECK(FMT("clear_alpha_%s", type), 4, 4, t, t, {
576  .op = SWS_OP_CLEAR,
577  .type = t,
578  .clear.value[3] = { 0, 1 },
579  .clear.mask = SWS_COMP(3),
580  });
581  }
582  }
583 }
584 
585 static void check_shift(void)
586 {
587  for (SwsPixelType t = U16; t < SWS_PIXEL_TYPE_NB; t++) {
588  const char *type = ff_sws_pixel_type_name(t);
589  if (!ff_sws_pixel_type_is_int(t))
590  continue;
591 
592  for (int shift = 1; shift <= 8; shift++) {
593  CHECK_COMMON(FMT("lshift%d_%s", shift, type), t, t, {
594  .op = SWS_OP_LSHIFT,
595  .type = t,
596  .shift = { shift },
597  });
598 
599  CHECK_COMMON(FMT("rshift%d_%s", shift, type), t, t, {
600  .op = SWS_OP_RSHIFT,
601  .type = t,
602  .shift = { shift },
603  });
604  }
605  }
606 }
607 
608 static void check_swizzle(void)
609 {
610  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
611  const char *type = ff_sws_pixel_type_name(t);
612  static const int patterns[][4] = {
613  /* Pure swizzle */
614  {3, 0, 1, 2},
615  {3, 0, 2, 1},
616  {2, 1, 0, 3},
617  {3, 2, 1, 0},
618  {3, 1, 0, 2},
619  {3, 2, 0, 1},
620  {1, 2, 0, 3},
621  {1, 0, 2, 3},
622  {2, 0, 1, 3},
623  {2, 3, 1, 0},
624  {2, 1, 3, 0},
625  {1, 2, 3, 0},
626  {1, 3, 2, 0},
627  {0, 2, 1, 3},
628  {0, 2, 3, 1},
629  {0, 3, 1, 2},
630  {3, 1, 2, 0},
631  {0, 3, 2, 1},
632  /* Luma expansion */
633  {0, 0, 0, 3},
634  {3, 0, 0, 0},
635  {0, 0, 0, 1},
636  {1, 0, 0, 0},
637  };
638 
639  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
640  const int x = patterns[i][0], y = patterns[i][1],
641  z = patterns[i][2], w = patterns[i][3];
642  CHECK(FMT("swizzle_%d%d%d%d_%s", x, y, z, w, type), 4, 4, t, t, {
643  .op = SWS_OP_SWIZZLE,
644  .type = t,
645  .swizzle = SWS_SWIZZLE(x, y, z, w),
646  });
647  }
648  }
649 }
650 
651 static void check_convert(void)
652 {
653  for (SwsPixelType i = U8; i < SWS_PIXEL_TYPE_NB; i++) {
654  const char *itype = ff_sws_pixel_type_name(i);
655  const int isize = ff_sws_pixel_type_size(i);
656  for (SwsPixelType o = U8; o < SWS_PIXEL_TYPE_NB; o++) {
657  const char *otype = ff_sws_pixel_type_name(o);
658  const int osize = ff_sws_pixel_type_size(o);
659  const char *name = FMT("convert_%s_%s", itype, otype);
660  if (i == o)
661  continue;
662 
663  if (isize < osize || !ff_sws_pixel_type_is_int(o)) {
664  CHECK_COMMON(name, i, o, {
665  .op = SWS_OP_CONVERT,
666  .type = i,
667  .convert.to = o,
668  });
669  } else if (isize > osize || !ff_sws_pixel_type_is_int(i)) {
670  uint32_t range = UINT32_MAX >> (32 - osize * 8);
672  .op = SWS_OP_CONVERT,
673  .type = i,
674  .convert.to = o,
675  });
676  }
677  }
678  }
679 
680  /* Check expanding conversions */
681  CHECK_COMMON("expand16", U8, U16, {
682  .op = SWS_OP_CONVERT,
683  .type = U8,
684  .convert.to = U16,
685  .convert.expand = true,
686  });
687 
688  CHECK_COMMON("expand32", U8, U32, {
689  .op = SWS_OP_CONVERT,
690  .type = U8,
691  .convert.to = U32,
692  .convert.expand = true,
693  });
694 }
695 
696 static void check_dither(void)
697 {
698  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
699  const char *type = ff_sws_pixel_type_name(t);
701  continue;
702 
703  /* Test all sizes up to 256x256 */
704  for (int size_log2 = 0; size_log2 <= 8; size_log2++) {
705  const int size = 1 << size_log2;
706  const int mask = size - 1;
708  if (!matrix) {
709  fail();
710  return;
711  }
712 
713  if (size == 1) {
714  matrix[0] = (AVRational) { 1, 2 };
715  } else {
716  for (int i = 0; i < size * size; i++)
717  matrix[i] = rndq(t);
718  }
719 
720  CHECK_COMMON(FMT("dither_%dx%d_%s", size, size, type), t, t, {
721  .op = SWS_OP_DITHER,
722  .type = t,
723  .dither.size_log2 = size_log2,
724  .dither.matrix = matrix,
725  .dither.y_offset = {0, 3 & mask, 2 & mask, 5 & mask},
726  });
727 
729  }
730  }
731 }
732 
733 static void check_min_max(void)
734 {
735  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
736  const char *type = ff_sws_pixel_type_name(t);
737  CHECK_COMMON(FMT("min_%s", type), t, t, {
738  .op = SWS_OP_MIN,
739  .type = t,
740  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
741  });
742 
743  CHECK_COMMON(FMT("max_%s", type), t, t, {
744  .op = SWS_OP_MAX,
745  .type = t,
746  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
747  });
748  }
749 }
750 
751 static void check_linear(void)
752 {
753  static const struct {
754  const char *name;
755  uint32_t mask;
756  } patterns[] = {
757  { "luma", SWS_MASK_LUMA },
758  { "alpha", SWS_MASK_ALPHA },
759  { "luma+alpha", SWS_MASK_LUMA | SWS_MASK_ALPHA },
760  { "dot3", 0x7 },
761  { "row0", SWS_MASK_ROW(0) ^ SWS_MASK(0, 3) },
762  { "diag3", SWS_MASK_DIAG3 },
763  { "diag4", SWS_MASK_DIAG4 },
764  { "diag3+alpha", SWS_MASK_DIAG3 | SWS_MASK_ALPHA },
765  { "diag3+off3", SWS_MASK_DIAG3 | SWS_MASK_OFF3 },
766  { "matrix3+off3", SWS_MASK_MAT3 | SWS_MASK_OFF3 },
767  { "matrix3+off3+alpha", SWS_MASK_MAT3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
768  };
769 
770  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
771  const char *type = ff_sws_pixel_type_name(t);
773  continue;
774 
775  for (int p = 0; p < FF_ARRAY_ELEMS(patterns); p++) {
776  const uint32_t mask = patterns[p].mask;
777  SwsLinearOp lin = { .mask = mask };
778 
779  for (int i = 0; i < 4; i++) {
780  for (int j = 0; j < 5; j++) {
781  if (mask & SWS_MASK(i, j)) {
782  lin.m[i][j] = rndq(t);
783  } else {
784  lin.m[i][j] = (AVRational) { i == j, 1 };
785  }
786  }
787  }
788 
789  CHECK(FMT("linear_%s_%s", patterns[p].name, type), 4, 4, t, t, {
790  .op = SWS_OP_LINEAR,
791  .type = t,
792  .lin = lin,
793  });
794  }
795  }
796 }
797 
798 static void check_scale(void)
799 {
800  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
801  const char *type = ff_sws_pixel_type_name(t);
802  const int bits = ff_sws_pixel_type_size(t) * 8;
803  if (ff_sws_pixel_type_is_int(t)) {
804  const unsigned max = UINT32_MAX >> (32 - bits);
805 
806  /* Test fixed fast path for expansion from bits to full range */
807  CHECK_COMMON_RANGE(FMT("scale_full_%s", type), 1, t, t, {
808  .op = SWS_OP_SCALE,
809  .type = t,
810  .scale = {{ max, 1 }},
811  });
812 
813  /* Ensure the result won't exceed the value range */
814  const unsigned scale = rnd() & (max >> 1);
815  const unsigned range = max / (scale ? scale : 1);
816  CHECK_COMMON_RANGE(FMT("scale_%s", type), range, t, t, {
817  .op = SWS_OP_SCALE,
818  .type = t,
819  .scale = {{ scale, 1 }},
820  });
821  } else {
822  CHECK_COMMON(FMT("scale_%s", type), t, t, {
823  .op = SWS_OP_SCALE,
824  .type = t,
825  .scale = { rndq(t) },
826  });
827  }
828  }
829 }
830 
831 static void check_filter(void)
832 {
833  SwsFilterParams params = {
835  };
836 
837  const SwsScaler scalers[] = {
840  };
841 
843 
844  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
845  const char *type = ff_sws_pixel_type_name(t);
846  for (int s = 0; s < FF_ARRAY_ELEMS(scalers); s++) {
847  params.scaler = scalers[s];
848  params.dst_size = LINES;
849  for (int h = 1; h <= LINES; h += h) {
850  params.src_size = h;
851  int ret = ff_sws_filter_generate(NULL, &params, &filter);
852  if (ret < 0) {
853  fail();
854  return;
855  }
856 
857  const char *name = filter->name;
858  for (int n = 1; n <= 4; n++) {
859  check_ops(FMT("%s_filter%d_v_%dx%d_%s", name, n, PIXELS, h, type), NULL, (SwsOp[]) {
860  {
861  .op = SWS_OP_READ,
862  .type = t,
863  .rw.elems = n,
864  .rw.filter = SWS_OP_FILTER_V,
865  .rw.kernel = filter,
866  }, {
867  .op = SWS_OP_WRITE,
868  .type = SWS_PIXEL_F32,
869  .rw.elems = n,
870  }, {0}
871  });
872  }
873 
875  }
876 
877  params.dst_size = PIXELS;
878  for (int w = 1; w <= PIXELS; w += w) {
879  params.src_size = w;
880  int ret = ff_sws_filter_generate(NULL, &params, &filter);
881  if (ret < 0) {
882  fail();
883  return;
884  }
885 
886  const char *name = filter->name;
887  for (int n = 1; n <= 4; n++) {
888  check_ops(FMT("%s_filter%d_h_%dx%d_%s", name, n, w, LINES, type), NULL, (SwsOp[]) {
889  {
890  .op = SWS_OP_READ,
891  .type = t,
892  .rw.elems = n,
893  .rw.filter = SWS_OP_FILTER_H,
894  .rw.kernel = filter,
895  }, {
896  .op = SWS_OP_WRITE,
897  .type = SWS_PIXEL_F32,
898  .rw.elems = n,
899  }, {0}
900  });
901  }
902 
904  }
905  }
906  }
907 }
908 
910 {
912  report("read_write");
914  report("swap_bytes");
916  report("pack_unpack");
917  check_clear();
918  report("clear");
919  check_shift();
920  report("shift");
921  check_swizzle();
922  report("swizzle");
923  check_convert();
924  report("convert");
925  check_dither();
926  report("dither");
927  check_min_max();
928  report("min_max");
929  check_linear();
930  report("linear");
931  check_scale();
932  report("scale");
933  check_filter();
934  report("filter");
935 }
SWS_OP_READ
@ SWS_OP_READ
Definition: ops.h:50
SWS_PIXEL_U16
@ SWS_PIXEL_U16
Definition: ops.h:36
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:53
PIXELS
@ PIXELS
Definition: sw_ops.c:34
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
SwsCompiledOp::func
SwsOpFunc func
Definition: ops_dispatch.h:103
SwsClearOp::value
AVRational value[4]
Definition: ops.h:170
SWS_OP_LSHIFT
@ SWS_OP_LSHIFT
Definition: ops.h:58
SWS_OP_UNPACK
@ SWS_OP_UNPACK
Definition: ops.h:56
SwsClearOp
Definition: ops.h:168
mem_internal.h
SwsFilterParams::src_size
int src_size
The relative sizes of the input and output images.
Definition: filters.h:57
SwsOpList::comps_src
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
Definition: ops.h:307
checkasm_get_cpu_suffix
static const char * checkasm_get_cpu_suffix(void)
Get the suffix for the current CPU flag, or "c" if none.
Definition: checkasm.h:326
SwsOpExec::in_bump
ptrdiff_t in_bump[4]
Pointer bump, difference between stride and processed line size.
Definition: ops_dispatch.h:51
SWS_OP_CLEAR
@ SWS_OP_CLEAR
Definition: ops.h:62
CHECK_COMMON
#define CHECK_COMMON(NAME, IN, OUT,...)
Definition: sw_ops.c:370
SwsOpExec::in
const uint8_t * in[4]
Definition: ops_dispatch.h:37
SwsOpExec::out_stride
ptrdiff_t out_stride[4]
Definition: ops_dispatch.h:42
checkasm_call_checked
#define checkasm_call_checked(func,...)
Definition: aarch64.h:93
SwsLinearOp::m
AVRational m[4][5]
Generalized 5x5 affine transformation: [ Out.x ] = [ A B C D E ] [ Out.y ] = [ F G H I J ] * [ x y z ...
Definition: ops.h:206
matrix
Definition: vc1dsp.c:43
src1
const pixel * src1
Definition: h264pred_template.c:420
mask
int mask
Definition: mediacodecdec_common.c:154
SwsOp::rw
SwsReadWriteOp rw
Definition: ops.h:243
check_min_max
static void check_min_max(void)
Definition: sw_ops.c:733
SWS_MASK_ALPHA
@ SWS_MASK_ALPHA
Definition: ops.h:218
ops.h
u
#define u(width, name, range_min, range_max)
Definition: cbs_apv.c:68
SWS_OP_DITHER
@ SWS_OP_DITHER
Definition: ops.h:70
SwsFilterWeights
Represents a computed filter kernel.
Definition: filters.h:64
checkasm_check_sw_ops
void checkasm_check_sw_ops(void)
Definition: sw_ops.c:909
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:180
SwsOpExec::block_size_in
int32_t block_size_in
Definition: ops_dispatch.h:57
check_convert
static void check_convert(void)
Definition: sw_ops.c:651
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:1639
SwsFilterWeights::offsets
int * offsets
The computed source pixel positions for each row of the filter.
Definition: filters.h:84
check_swap_bytes
static void check_swap_bytes(void)
Definition: sw_ops.c:460
SwsCompiledOp::cpu_flags
int cpu_flags
Definition: ops_dispatch.h:119
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
CHECK_COMMON_RANGE
#define CHECK_COMMON_RANGE(NAME, RANGE, IN, OUT,...)
Definition: sw_ops.c:357
check_read_write
static void check_read_write(void)
Definition: sw_ops.c:373
SwsFilterParams
Definition: filters.h:45
max
#define max(a, b)
Definition: cuda_runtime.h:33
SWS_PIXEL_U32
@ SWS_PIXEL_U32
Definition: ops.h:37
SwsOpExec::in_stride
ptrdiff_t in_stride[4]
Definition: ops_dispatch.h:41
SWS_MASK_MAT3
@ SWS_MASK_MAT3
Definition: ops.h:222
check_linear
static void check_linear(void)
Definition: sw_ops.c:751
SwsOpBackend::name
const char * name
Definition: ops_dispatch.h:134
check_filter
static void check_filter(void)
Definition: sw_ops.c:831
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:77
F32
@ F32
Definition: sw_ops.c:42
rndf
static float rndf(void)
Definition: sw_ops.c:64
ff_sws_filter_generate
int ff_sws_filter_generate(void *log, const SwsFilterParams *params, SwsFilterWeights **out)
Generate a filter kernel for the given parameters.
Definition: filters.c:187
SWS_MASK_ROW
#define SWS_MASK_ROW(I)
Definition: ops.h:212
DECLARE_ALIGNED_64
#define DECLARE_ALIGNED_64(t, v)
Definition: mem_internal.h:114
check_key
#define check_key
Definition: test.h:481
check_clear
static void check_clear(void)
Definition: sw_ops.c:530
SwsPixelType
SwsPixelType
Copyright (C) 2025 Niklas Haas.
Definition: ops.h:33
CHECK_RANGE
#define CHECK_RANGE(NAME, RANGE, N_IN, N_OUT, IN, OUT,...)
Definition: sw_ops.c:354
SwsComps::max
AVRational max[4]
Definition: ops.h:114
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: ops.h:38
SwsClearOp::mask
SwsCompMask mask
Definition: ops.h:169
ff_sws_op_backends
const SwsOpBackend *const ff_sws_op_backends[]
Definition: ops.c:45
check_scale
static void check_scale(void)
Definition: sw_ops.c:798
SwsOpList::num_ops
int num_ops
Definition: ops.h:290
SwsFilterParams::dst_size
int dst_size
Definition: filters.h:58
checkasm.h
SWS_PIXEL_U8
@ SWS_PIXEL_U8
Definition: ops.h:35
ff_sws_pixel_type_is_int
bool ff_sws_pixel_type_is_int(SwsPixelType type)
Definition: ops.c:92
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
SwsOpBackend::hw_format
enum AVPixelFormat hw_format
If NONE, backend only supports software frames.
Definition: ops_dispatch.h:150
refstruct.h
checkasm_call
#define checkasm_call(func,...)
Call a function with signal handling.
Definition: test.h:252
SwsLinearOp::mask
uint32_t mask
Definition: ops.h:207
av_refstruct_allocz
static void * av_refstruct_allocz(size_t size)
Equivalent to av_refstruct_alloc_ext(size, 0, NULL, NULL)
Definition: refstruct.h:105
SwsOp::op
SwsOpType op
Definition: ops.h:239
SWS_OP_SCALE
@ SWS_OP_SCALE
Definition: ops.h:66
avassert.h
checkasm_set_func_variant
CHECKASM_API CheckasmKey CHECKASM_API void checkasm_set_func_variant(const char *id,...) CHECKASM_PRINTF(1
Set a custom variant identifier for the next checkasm_check_func() call.
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
float
float
Definition: af_crystalizer.c:122
s
#define s(width, name)
Definition: cbs_vp9.c:198
offsets
static const int offsets[]
Definition: hevc_pel.c:34
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
SWS_SWIZZLE
#define SWS_SWIZZLE(X, Y, Z, W)
Definition: ops.h:161
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1465
SwsOpExec::in_bump_y
int32_t * in_bump_y
Line bump; determines how many additional lines to advance (after incrementing normally to the next l...
Definition: ops_dispatch.h:72
SwsComps::min
AVRational min[4]
Definition: ops.h:114
SWS_MASK_OFF3
@ SWS_MASK_OFF3
Definition: ops.h:221
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
declare_func
#define declare_func
Definition: test.h:488
bits
uint8_t bits
Definition: vp3data.h:128
SWS_MASK_LUMA
@ SWS_MASK_LUMA
Definition: ops.h:217
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:64
fill32
static void fill32(uint32_t *line, int num, unsigned range)
Definition: sw_ops.c:80
MK_RANGES
#define MK_RANGES(R)
Definition: sw_ops.c:353
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
bench
#define bench(...)
Definition: checkasm.h:142
FMT
#define FMT(fmt,...)
Definition: sw_ops.c:45
SWS_OP_LINEAR
@ SWS_OP_LINEAR
Definition: ops.h:69
SWS_OP_FILTER_H
@ SWS_OP_FILTER_H
Definition: ops.h:73
SwsOpBackend
Definition: ops_dispatch.h:133
if
if(ret)
Definition: filter_design.txt:179
SWS_OP_PACK
@ SWS_OP_PACK
Definition: ops.h:57
SwsOpExec::height
int32_t height
Definition: ops_dispatch.h:55
SwsOpExec
Copyright (C) 2026 Niklas Haas.
Definition: ops_dispatch.h:35
SwsReadWriteOp::kernel
SwsFilterWeights * kernel
Definition: ops.h:138
fill16
static void fill16(uint16_t *line, int num, unsigned range)
Definition: sw_ops.c:86
fail
#define fail
Definition: test.h:478
rw_pixel_bits
static int rw_pixel_bits(const SwsOp *op)
Definition: sw_ops.c:55
NULL
#define NULL
Definition: coverity.c:32
tprintf
static const char * tprintf(char buf[], size_t size, const char *fmt,...)
Definition: sw_ops.c:46
ff_sws_compiled_op_unref
void ff_sws_compiled_op_unref(SwsCompiledOp *comp)
Definition: ops_dispatch.c:117
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
SWS_OP_FILTER_V
@ SWS_OP_FILTER_V
Definition: ops.h:74
SwsScaler
SwsScaler
Definition: swscale.h:96
SwsOpExec::slice_h
int32_t slice_h
Definition: ops_dispatch.h:56
SWS_COMP
#define SWS_COMP(X)
Definition: ops.h:88
SWS_MASK
#define SWS_MASK(I, J)
Definition: ops.h:210
SWS_MASK_DIAG4
@ SWS_MASK_DIAG4
Definition: ops.h:226
NB_PLANES
@ NB_PLANES
Definition: sw_ops.c:33
SWS_SCALE_SINC
@ SWS_SCALE_SINC
unwindowed sinc
Definition: swscale.h:103
SWS_PARAM_DEFAULT
#define SWS_PARAM_DEFAULT
Definition: swscale.h:458
SwsPackOp::pattern
uint8_t pattern[4]
Packed bits are assumed to be LSB-aligned within the underlying integer type; i.e.
Definition: ops.h:146
f
f
Definition: af_crystalizer.c:122
SwsOpExec::block_size_out
int32_t block_size_out
Definition: ops_dispatch.h:58
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1043
shift
static int shift(int a, int b)
Definition: bonk.c:261
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
SwsOp::type
SwsPixelType type
Definition: ops.h:240
size
int size
Definition: twinvq_data.h:10344
SWS_OP_RSHIFT
@ SWS_OP_RSHIFT
Definition: ops.h:59
rnd
#define rnd
Definition: checkasm.h:140
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2594
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:51
line
Definition: graph2dot.c:48
U32
@ U32
Definition: sw_ops.c:41
SWS_MASK_DIAG3
@ SWS_MASK_DIAG3
Definition: ops.h:220
SwsLinearOp
Definition: ops.h:193
zero
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
Definition: interplayacm.c:121
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
fill32f
static void fill32f(float *line, int num, unsigned range)
Definition: sw_ops.c:73
SwsOpExec::out
uint8_t * out[4]
Definition: ops_dispatch.h:38
ff_sws_comp_mask_q4
SwsCompMask ff_sws_comp_mask_q4(const AVRational q[4])
Definition: ops.c:137
SWS_SCALE_POINT
@ SWS_SCALE_POINT
nearest neighbor (point sampling)
Definition: swscale.h:100
SwsOpExec::in_offset_x
int32_t * in_offset_x
Pixel offset map; for horizontal scaling, in bytes.
Definition: ops_dispatch.h:80
SwsOpList::ops
SwsOp * ops
Definition: ops.h:289
SwsPackOp
Definition: ops.h:141
vsnprintf
#define vsnprintf
Definition: snprintf.h:36
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:58
LINES
@ LINES
Definition: sw_ops.c:35
ops_internal.h
SwsFilterParams::scaler_params
double scaler_params[SWS_NUM_SCALER_PARAMS]
Definition: filters.h:50
SwsOp
Definition: ops.h:238
SwsOpExec::width
int32_t width
Definition: ops_dispatch.h:55
SwsCompiledOp::priv
void * priv
Definition: ops_dispatch.h:127
SwsCompiledOp::block_size
int block_size
Definition: ops_dispatch.h:122
ret
ret
Definition: filter_design.txt:187
check_shift
static void check_shift(void)
Definition: sw_ops.c:585
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:65
SwsCompiledOp
Definition: ops_dispatch.h:100
SwsReadWriteOp::filter
SwsOpType filter
Filter kernel to apply to each plane while sampling.
Definition: ops.h:137
check_swizzle
static void check_swizzle(void)
Definition: sw_ops.c:608
U16
@ U16
Definition: sw_ops.c:40
SWS_PIXEL_TYPE_NB
@ SWS_PIXEL_TYPE_NB
Definition: ops.h:39
check_compiled
static void check_compiled(const char *name, const SwsOp *read_op, const SwsOp *write_op, const int ranges[NB_PLANES], const SwsCompiledOp *comp_ref, const SwsCompiledOp *comp_new)
Definition: sw_ops.c:114
SwsReadWriteOp::packed
bool packed
Definition: ops.h:128
ff_sws_pixel_type_name
const char * ff_sws_pixel_type_name(SwsPixelType type)
Definition: ops.c:62
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
SWS_OP_SWAP_BYTES
@ SWS_OP_SWAP_BYTES
Definition: ops.h:52
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
src0
const pixel *const src0
Definition: h264pred_template.c:419
rndq
static AVRational rndq(SwsPixelType t)
Definition: sw_ops.c:518
desc
const char * desc
Definition: libsvtav1.c:83
report
#define report
Definition: test.h:479
w
uint8_t w
Definition: llvidencdsp.c:39
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:278
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
SWS_OP_CONVERT
@ SWS_OP_CONVERT
Definition: ops.h:63
fill8
static void fill8(uint8_t *line, int num, unsigned range)
Definition: sw_ops.c:96
sws_free_context
void sws_free_context(SwsContext **ctx)
Free the context and everything associated with it, and write NULL to the provided pointer.
Definition: utils.c:2381
set_range
static void set_range(AVRational *rangeq, unsigned range, unsigned range_def)
Definition: sw_ops.c:106
int32_t
int32_t
Definition: audioconvert.c:56
check_pack_unpack
static void check_pack_unpack(void)
Definition: sw_ops.c:473
h
h
Definition: vp9dsp_template.c:2070
check_ops
static void check_ops(const char *name, const unsigned ranges[NB_PLANES], const SwsOp *ops)
Definition: sw_ops.c:241
stride
#define stride
Definition: h264pred_template.c:536
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:288
SwsContext
Main external API structure.
Definition: swscale.h:229
CHECK
#define CHECK(NAME, N_IN, N_OUT, IN, OUT,...)
Definition: sw_ops.c:367
SwsFilterParams::scaler
SwsScaler scaler
The filter kernel and parameters to use.
Definition: filters.h:49
CHECK_RANGES
#define CHECK_RANGES(NAME, RANGES, N_IN, N_OUT, IN, OUT,...)
Definition: sw_ops.c:336
SwsOpExec::out_bump
ptrdiff_t out_bump[4]
Definition: ops_dispatch.h:52
check_dither
static void check_dither(void)
Definition: sw_ops.c:696
ff_sws_ops_compile
int ff_sws_ops_compile(SwsContext *ctx, const SwsOpBackend *backend, const SwsOpList *ops, SwsCompiledOp *out)
Attempt to compile a list of operations using a specific backend, or the best available backend if ba...
Definition: ops_dispatch.c:95
U8
@ U8
Definition: sw_ops.c:39