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, const SwsOpBackend *backend,
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  declare_func(void, const SwsOpExec *, const void *, int bx, int y, int bx_end, int y_end);
121 
122  static DECLARE_ALIGNED_64(char, src0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
123  static DECLARE_ALIGNED_64(char, src1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
124  static DECLARE_ALIGNED_64(char, dst0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
125  static DECLARE_ALIGNED_64(char, dst1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
126 
127  av_assert0(PIXELS % comp_new->block_size == 0);
128  for (int p = 0; p < NB_PLANES; p++) {
129  void *plane = src0[p];
130  switch (read_op->type) {
131  case U8:
132  fill8(plane, sizeof(src0[p]) / sizeof(uint8_t), ranges[p]);
133  break;
134  case U16:
135  fill16(plane, sizeof(src0[p]) / sizeof(uint16_t), ranges[p]);
136  break;
137  case U32:
138  fill32(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
139  break;
140  case F32:
141  fill32f(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
142  break;
143  }
144  }
145 
146  memcpy(src1, src0, sizeof(src0));
147  memset(dst0, 0, sizeof(dst0));
148  memset(dst1, 0, sizeof(dst1));
149 
150  const int read_size = PIXELS * rw_pixel_bits(read_op) >> 3;
151  const int write_size = PIXELS * rw_pixel_bits(write_op) >> 3;
152 
153  SwsOpExec exec = {0};
154  exec.width = PIXELS;
155  exec.height = exec.slice_h = LINES;
156  for (int i = 0; i < NB_PLANES; i++) {
157  exec.in_stride[i] = sizeof(src0[i][0]);
158  exec.out_stride[i] = sizeof(dst0[i][0]);
159  exec.in_bump[i] = exec.in_stride[i] - read_size;
160  exec.out_bump[i] = exec.out_stride[i] - write_size;
161  }
162 
163  int32_t in_bump_y[LINES];
164  if (read_op->rw.filter == SWS_OP_FILTER_V) {
165  const int *offsets = read_op->rw.kernel->offsets;
166  for (int y = 0; y < LINES - 1; y++)
167  in_bump_y[y] = offsets[y + 1] - offsets[y] - 1;
168  in_bump_y[LINES - 1] = 0;
169  exec.in_bump_y = in_bump_y;
170  }
171 
172  int32_t in_offset_x[PIXELS];
173  if (read_op->rw.filter == SWS_OP_FILTER_H) {
174  const int *offsets = read_op->rw.kernel->offsets;
175  const int rw_bits = rw_pixel_bits(read_op);
176  for (int x = 0; x < PIXELS; x++)
177  in_offset_x[x] = offsets[x] * rw_bits >> 3;
178  exec.in_offset_x = in_offset_x;
179  }
180 
181  /**
182  * We can't use `check_func()` alone because the actual function pointer
183  * may be a wrapper or entry point shared by multiple implementations.
184  * Solve it by hashing in the active CPU flags as well.
185  */
186  uintptr_t id = (uintptr_t) comp_new->func;
187  id ^= (id << 6) + (id >> 2) + 0x9e3779b97f4a7c15 + comp_new->cpu_flags;
188 
189  if (check_key((void*) id, "%s/%s", name, backend->name)) {
190  exec.block_size_in = comp_ref->block_size * rw_pixel_bits(read_op) >> 3;
191  exec.block_size_out = comp_ref->block_size * rw_pixel_bits(write_op) >> 3;
192  for (int i = 0; i < NB_PLANES; i++) {
193  exec.in[i] = (void *) src0[i];
194  exec.out[i] = (void *) dst0[i];
195  }
196  checkasm_call(comp_ref->func, &exec, comp_ref->priv, 0, 0, PIXELS / comp_ref->block_size, LINES);
197 
198  exec.block_size_in = comp_new->block_size * rw_pixel_bits(read_op) >> 3;
199  exec.block_size_out = comp_new->block_size * rw_pixel_bits(write_op) >> 3;
200  for (int i = 0; i < NB_PLANES; i++) {
201  exec.in[i] = (void *) src1[i];
202  exec.out[i] = (void *) dst1[i];
203  }
204  checkasm_call_checked(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
205 
206  for (int i = 0; i < NB_PLANES; i++) {
207  const char *desc = FMT("%s[%d]", name, i);
208  const int stride = sizeof(dst0[i][0]);
209 
210  switch (write_op->type) {
211  case U8:
212  checkasm_check(uint8_t, (void *) dst0[i], stride,
213  (void *) dst1[i], stride,
214  write_size, LINES, desc);
215  break;
216  case U16:
217  checkasm_check(uint16_t, (void *) dst0[i], stride,
218  (void *) dst1[i], stride,
219  write_size >> 1, LINES, desc);
220  break;
221  case U32:
222  checkasm_check(uint32_t, (void *) dst0[i], stride,
223  (void *) dst1[i], stride,
224  write_size >> 2, LINES, desc);
225  break;
226  case F32:
227  checkasm_check(float_ulp, (void *) dst0[i], stride,
228  (void *) dst1[i], stride,
229  write_size >> 2, LINES, desc, 0);
230  break;
231  }
232 
233  if (write_op->rw.packed)
234  break;
235  }
236 
237  bench(comp_new->func, &exec, comp_new->priv, 0, 0, PIXELS / comp_new->block_size, LINES);
238  }
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_backend(ctx, backend_ref, &oplist, &comp_ref);
301  if (ret < 0) {
302  av_assert0(ret != AVERROR(ENOTSUP));
303  fail();
304  goto done;
305  }
306 
307  /* Iterate over every other backend, and test it against the C reference */
308  for (int n = 0; ff_sws_op_backends[n]; n++) {
309  const SwsOpBackend *backend = ff_sws_op_backends[n];
310  if (backend->hw_format != AV_PIX_FMT_NONE || backend == backend_ref)
311  continue;
312 
313  if (!av_get_cpu_flags()) {
314  /* Also test once with the existing C reference to set the baseline */
315  check_compiled(name, backend, read_op, write_op, ranges, &comp_ref, &comp_ref);
316  }
317 
318  SwsCompiledOp comp_new = {0};
319  int ret = ff_sws_ops_compile_backend(ctx, backend, &oplist, &comp_new);
320  if (ret == AVERROR(ENOTSUP)) {
321  continue;
322  } else if (ret < 0) {
323  fail();
324  goto done;
325  }
326 
327  check_compiled(name, backend, 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 SwsClearOp patterns[] = {
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  CHECK(FMT("clear_pattern_%s[%d]", type, i), 4, 4, t, t, {
566  .op = SWS_OP_CLEAR,
567  .type = t,
568  .clear = patterns[i],
569  });
570  }
571  } else if (!ff_sws_pixel_type_is_int(t)) {
572  /* Floating point YUV doesn't exist, only alpha needs to be cleared */
573  CHECK(FMT("clear_alpha_%s", type), 4, 4, t, t, {
574  .op = SWS_OP_CLEAR,
575  .type = t,
576  .clear.value[3] = { 0, 1 },
577  });
578  }
579  }
580 }
581 
582 static void check_shift(void)
583 {
584  for (SwsPixelType t = U16; t < SWS_PIXEL_TYPE_NB; t++) {
585  const char *type = ff_sws_pixel_type_name(t);
586  if (!ff_sws_pixel_type_is_int(t))
587  continue;
588 
589  for (int shift = 1; shift <= 8; shift++) {
590  CHECK_COMMON(FMT("lshift%d_%s", shift, type), t, t, {
591  .op = SWS_OP_LSHIFT,
592  .type = t,
593  .shift = { shift },
594  });
595 
596  CHECK_COMMON(FMT("rshift%d_%s", shift, type), t, t, {
597  .op = SWS_OP_RSHIFT,
598  .type = t,
599  .shift = { shift },
600  });
601  }
602  }
603 }
604 
605 static void check_swizzle(void)
606 {
607  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
608  const char *type = ff_sws_pixel_type_name(t);
609  static const int patterns[][4] = {
610  /* Pure swizzle */
611  {3, 0, 1, 2},
612  {3, 0, 2, 1},
613  {2, 1, 0, 3},
614  {3, 2, 1, 0},
615  {3, 1, 0, 2},
616  {3, 2, 0, 1},
617  {1, 2, 0, 3},
618  {1, 0, 2, 3},
619  {2, 0, 1, 3},
620  {2, 3, 1, 0},
621  {2, 1, 3, 0},
622  {1, 2, 3, 0},
623  {1, 3, 2, 0},
624  {0, 2, 1, 3},
625  {0, 2, 3, 1},
626  {0, 3, 1, 2},
627  {3, 1, 2, 0},
628  {0, 3, 2, 1},
629  /* Luma expansion */
630  {0, 0, 0, 3},
631  {3, 0, 0, 0},
632  {0, 0, 0, 1},
633  {1, 0, 0, 0},
634  };
635 
636  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
637  const int x = patterns[i][0], y = patterns[i][1],
638  z = patterns[i][2], w = patterns[i][3];
639  CHECK(FMT("swizzle_%d%d%d%d_%s", x, y, z, w, type), 4, 4, t, t, {
640  .op = SWS_OP_SWIZZLE,
641  .type = t,
642  .swizzle = SWS_SWIZZLE(x, y, z, w),
643  });
644  }
645  }
646 }
647 
648 static void check_convert(void)
649 {
650  for (SwsPixelType i = U8; i < SWS_PIXEL_TYPE_NB; i++) {
651  const char *itype = ff_sws_pixel_type_name(i);
652  const int isize = ff_sws_pixel_type_size(i);
653  for (SwsPixelType o = U8; o < SWS_PIXEL_TYPE_NB; o++) {
654  const char *otype = ff_sws_pixel_type_name(o);
655  const int osize = ff_sws_pixel_type_size(o);
656  const char *name = FMT("convert_%s_%s", itype, otype);
657  if (i == o)
658  continue;
659 
660  if (isize < osize || !ff_sws_pixel_type_is_int(o)) {
661  CHECK_COMMON(name, i, o, {
662  .op = SWS_OP_CONVERT,
663  .type = i,
664  .convert.to = o,
665  });
666  } else if (isize > osize || !ff_sws_pixel_type_is_int(i)) {
667  uint32_t range = UINT32_MAX >> (32 - osize * 8);
669  .op = SWS_OP_CONVERT,
670  .type = i,
671  .convert.to = o,
672  });
673  }
674  }
675  }
676 
677  /* Check expanding conversions */
678  CHECK_COMMON("expand16", U8, U16, {
679  .op = SWS_OP_CONVERT,
680  .type = U8,
681  .convert.to = U16,
682  .convert.expand = true,
683  });
684 
685  CHECK_COMMON("expand32", U8, U32, {
686  .op = SWS_OP_CONVERT,
687  .type = U8,
688  .convert.to = U32,
689  .convert.expand = true,
690  });
691 }
692 
693 static void check_dither(void)
694 {
695  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
696  const char *type = ff_sws_pixel_type_name(t);
698  continue;
699 
700  /* Test all sizes up to 256x256 */
701  for (int size_log2 = 0; size_log2 <= 8; size_log2++) {
702  const int size = 1 << size_log2;
703  const int mask = size - 1;
705  if (!matrix) {
706  fail();
707  return;
708  }
709 
710  if (size == 1) {
711  matrix[0] = (AVRational) { 1, 2 };
712  } else {
713  for (int i = 0; i < size * size; i++)
714  matrix[i] = rndq(t);
715  }
716 
717  CHECK_COMMON(FMT("dither_%dx%d_%s", size, size, type), t, t, {
718  .op = SWS_OP_DITHER,
719  .type = t,
720  .dither.size_log2 = size_log2,
721  .dither.matrix = matrix,
722  .dither.y_offset = {0, 3 & mask, 2 & mask, 5 & mask},
723  });
724 
726  }
727  }
728 }
729 
730 static void check_min_max(void)
731 {
732  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
733  const char *type = ff_sws_pixel_type_name(t);
734  CHECK_COMMON(FMT("min_%s", type), t, t, {
735  .op = SWS_OP_MIN,
736  .type = t,
737  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
738  });
739 
740  CHECK_COMMON(FMT("max_%s", type), t, t, {
741  .op = SWS_OP_MAX,
742  .type = t,
743  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
744  });
745  }
746 }
747 
748 static void check_linear(void)
749 {
750  static const struct {
751  const char *name;
752  uint32_t mask;
753  } patterns[] = {
754  { "luma", SWS_MASK_LUMA },
755  { "alpha", SWS_MASK_ALPHA },
756  { "luma+alpha", SWS_MASK_LUMA | SWS_MASK_ALPHA },
757  { "dot3", 0x7 },
758  { "row0", SWS_MASK_ROW(0) ^ SWS_MASK(0, 3) },
759  { "diag3", SWS_MASK_DIAG3 },
760  { "diag4", SWS_MASK_DIAG4 },
761  { "diag3+alpha", SWS_MASK_DIAG3 | SWS_MASK_ALPHA },
762  { "diag3+off3", SWS_MASK_DIAG3 | SWS_MASK_OFF3 },
763  { "matrix3+off3", SWS_MASK_MAT3 | SWS_MASK_OFF3 },
764  { "matrix3+off3+alpha", SWS_MASK_MAT3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
765  };
766 
767  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
768  const char *type = ff_sws_pixel_type_name(t);
770  continue;
771 
772  for (int p = 0; p < FF_ARRAY_ELEMS(patterns); p++) {
773  const uint32_t mask = patterns[p].mask;
774  SwsLinearOp lin = { .mask = mask };
775 
776  for (int i = 0; i < 4; i++) {
777  for (int j = 0; j < 5; j++) {
778  if (mask & SWS_MASK(i, j)) {
779  lin.m[i][j] = rndq(t);
780  } else {
781  lin.m[i][j] = (AVRational) { i == j, 1 };
782  }
783  }
784  }
785 
786  CHECK(FMT("linear_%s_%s", patterns[p].name, type), 4, 4, t, t, {
787  .op = SWS_OP_LINEAR,
788  .type = t,
789  .lin = lin,
790  });
791  }
792  }
793 }
794 
795 static void check_scale(void)
796 {
797  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
798  const char *type = ff_sws_pixel_type_name(t);
799  const int bits = ff_sws_pixel_type_size(t) * 8;
800  if (ff_sws_pixel_type_is_int(t)) {
801  const unsigned max = (1 << bits) - 1;
802 
803  /* Test fixed fast path for expansion from bits to full range */
804  CHECK_COMMON_RANGE(FMT("scale_full_%s", type), 1, t, t, {
805  .op = SWS_OP_SCALE,
806  .type = t,
807  .scale = {{ max, 1 }},
808  });
809 
810  /* Ensure the result won't exceed the value range */
811  const unsigned scale = rnd() & (max >> 1);
812  const unsigned range = max / (scale ? scale : 1);
813  CHECK_COMMON_RANGE(FMT("scale_%s", type), range, t, t, {
814  .op = SWS_OP_SCALE,
815  .type = t,
816  .scale = {{ scale, 1 }},
817  });
818  } else {
819  CHECK_COMMON(FMT("scale_%s", type), t, t, {
820  .op = SWS_OP_SCALE,
821  .type = t,
822  .scale = { rndq(t) },
823  });
824  }
825  }
826 }
827 
828 static void check_filter(void)
829 {
830  SwsFilterParams params = {
832  };
833 
834  const SwsScaler scalers[] = {
837  };
838 
840 
841  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
842  const char *type = ff_sws_pixel_type_name(t);
843  for (int s = 0; s < FF_ARRAY_ELEMS(scalers); s++) {
844  params.scaler = scalers[s];
845  params.dst_size = LINES;
846  for (int h = 1; h <= LINES; h += h) {
847  params.src_size = h;
848  int ret = ff_sws_filter_generate(NULL, &params, &filter);
849  if (ret < 0) {
850  fail();
851  return;
852  }
853 
854  const char *name = filter->name;
855  for (int n = 1; n <= 4; n++) {
856  check_ops(FMT("%s_filter%d_v_%dx%d_%s", name, n, PIXELS, h, type), NULL, (SwsOp[]) {
857  {
858  .op = SWS_OP_READ,
859  .type = t,
860  .rw.elems = n,
861  .rw.filter = SWS_OP_FILTER_V,
862  .rw.kernel = filter,
863  }, {
864  .op = SWS_OP_WRITE,
865  .type = SWS_PIXEL_F32,
866  .rw.elems = n,
867  }, {0}
868  });
869  }
870 
872  }
873 
874  params.dst_size = PIXELS;
875  for (int w = 1; w <= PIXELS; w += w) {
876  params.src_size = w;
877  int ret = ff_sws_filter_generate(NULL, &params, &filter);
878  if (ret < 0) {
879  fail();
880  return;
881  }
882 
883  const char *name = filter->name;
884  for (int n = 1; n <= 4; n++) {
885  check_ops(FMT("%s_filter%d_h_%dx%d_%s", name, n, w, LINES, type), NULL, (SwsOp[]) {
886  {
887  .op = SWS_OP_READ,
888  .type = t,
889  .rw.elems = n,
890  .rw.filter = SWS_OP_FILTER_H,
891  .rw.kernel = filter,
892  }, {
893  .op = SWS_OP_WRITE,
894  .type = SWS_PIXEL_F32,
895  .rw.elems = n,
896  }, {0}
897  });
898  }
899 
901  }
902  }
903  }
904 }
905 
907 {
909  report("read_write");
911  report("swap_bytes");
913  report("pack_unpack");
914  check_clear();
915  report("clear");
916  check_shift();
917  report("shift");
918  check_swizzle();
919  report("swizzle");
920  check_convert();
921  report("convert");
922  check_dither();
923  report("dither");
924  check_min_max();
925  report("min_max");
926  check_linear();
927  report("linear");
928  check_scale();
929  report("scale");
930  check_filter();
931  report("filter");
932 }
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
check_compiled
static void check_compiled(const char *name, const SwsOpBackend *backend, 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
SWS_OP_SWIZZLE
@ SWS_OP_SWIZZLE
Definition: ops.h:53
SWS_MASK_OFF3
@ SWS_MASK_OFF3
Definition: ops.h:201
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
SWS_OP_LSHIFT
@ SWS_OP_LSHIFT
Definition: ops.h:58
SWS_OP_UNPACK
@ SWS_OP_UNPACK
Definition: ops.h:56
SwsClearOp
Definition: ops.h:149
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:282
SWS_MASK_ALPHA
@ SWS_MASK_ALPHA
Definition: ops.h:198
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
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:186
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:223
U32
@ U32
Definition: sw_ops.c:41
check_min_max
static void check_min_max(void)
Definition: sw_ops.c:730
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:906
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:157
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:648
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:116
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
SWS_MASK_DIAG3
@ SWS_MASK_DIAG3
Definition: ops.h:200
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
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:109
SwsOpExec::in_stride
ptrdiff_t in_stride[4]
Definition: ops_dispatch.h:41
check_linear
static void check_linear(void)
Definition: sw_ops.c:748
SWS_MASK_DIAG4
@ SWS_MASK_DIAG4
Definition: ops.h:206
SwsOpBackend::name
const char * name
Definition: ops_internal.h:56
check_filter
static void check_filter(void)
Definition: sw_ops.c:828
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:76
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:183
SWS_MASK_ROW
#define SWS_MASK_ROW(I)
Definition: ops.h:192
DECLARE_ALIGNED_64
#define DECLARE_ALIGNED_64(t, v)
Definition: mem_internal.h:114
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:96
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: ops.h:38
ff_sws_op_backends
const SwsOpBackend *const ff_sws_op_backends[]
Definition: ops.c:44
check_scale
static void check_scale(void)
Definition: sw_ops.c:795
fail
#define fail()
Definition: checkasm.h:224
SwsOpList::num_ops
int num_ops
Definition: ops.h:265
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:91
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
PIXELS
@ PIXELS
Definition: sw_ops.c:34
SwsOpBackend::hw_format
enum AVPixelFormat hw_format
If NONE, backend only supports software frames.
Definition: ops_internal.h:71
refstruct.h
SwsLinearOp::mask
uint32_t mask
Definition: ops.h:187
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:219
SWS_OP_SCALE
@ SWS_OP_SCALE
Definition: ops.h:66
avassert.h
rnd
#define rnd()
Definition: checkasm.h:207
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:143
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1414
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:96
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
bits
uint8_t bits
Definition: vp3data.h:128
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
NB_PLANES
@ NB_PLANES
Definition: sw_ops.c:33
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
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_internal.h:55
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:120
fill16
static void fill16(uint16_t *line, int num, unsigned range)
Definition: sw_ops.c:86
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:104
SWS_MASK_MAT3
@ SWS_MASK_MAT3
Definition: ops.h:202
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
U8
@ U8
Definition: sw_ops.c:39
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_MASK
#define SWS_MASK(I, J)
Definition: ops.h:190
SWS_SCALE_SINC
@ SWS_SCALE_SINC
unwindowed sinc
Definition: swscale.h:103
SWS_PARAM_DEFAULT
#define SWS_PARAM_DEFAULT
Definition: swscale.h:423
SwsPackOp::pattern
uint8_t pattern[4]
Packed bits are assumed to be LSB-aligned within the underlying integer type; i.e.
Definition: ops.h:128
f
f
Definition: af_crystalizer.c:122
SwsOpExec::block_size_out
int32_t block_size_out
Definition: ops_dispatch.h:58
U16
@ U16
Definition: sw_ops.c:40
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1031
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:220
size
int size
Definition: twinvq_data.h:10344
SWS_OP_RSHIFT
@ SWS_OP_RSHIFT
Definition: ops.h:59
range
enum AVColorRange range
Definition: mediacodec_wrapper.c:2594
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:51
LINES
@ LINES
Definition: sw_ops.c:35
line
Definition: graph2dot.c:48
SwsLinearOp
Definition: ops.h:173
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
SWS_SCALE_POINT
@ SWS_SCALE_POINT
nearest neighbor (point sampling)
Definition: swscale.h:100
report
#define report
Definition: checkasm.h:227
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:264
SwsPackOp
Definition: ops.h:123
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
ops_internal.h
SwsFilterParams::scaler_params
double scaler_params[SWS_NUM_SCALER_PARAMS]
Definition: filters.h:50
checkasm_call_checked
#define checkasm_call_checked(func,...)
Definition: checkasm.h:339
SwsOp
Definition: ops.h:218
SwsOpExec::width
int32_t width
Definition: ops_dispatch.h:55
SwsCompiledOp::priv
void * priv
Definition: ops_dispatch.h:124
SwsCompiledOp::block_size
int block_size
Definition: ops_dispatch.h:119
ret
ret
Definition: filter_design.txt:187
check_shift
static void check_shift(void)
Definition: sw_ops.c:582
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:65
SwsCompiledOp
Definition: ops_dispatch.h:100
bench
#define bench(func,...)
Definition: checkasm.h:424
id
enum AVCodecID id
Definition: dts2pts.c:549
SwsReadWriteOp::filter
SwsOpType filter
Filter kernel to apply to each plane while sampling.
Definition: ops.h:119
check_swizzle
static void check_swizzle(void)
Definition: sw_ops.c:605
SWS_PIXEL_TYPE_NB
@ SWS_PIXEL_TYPE_NB
Definition: ops.h:39
SWS_MASK_LUMA
@ SWS_MASK_LUMA
Definition: ops.h:197
SwsReadWriteOp::packed
bool packed
Definition: ops.h:110
ff_sws_pixel_type_name
const char * ff_sws_pixel_type_name(SwsPixelType type)
Definition: ops.c:61
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
ff_sws_ops_compile_backend
int ff_sws_ops_compile_backend(SwsContext *ctx, const SwsOpBackend *backend, const SwsOpList *ops, SwsCompiledOp *out)
Attempt to compile a list of operations using a specific backend.
Definition: ops_dispatch.c:55
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:82
check_key
#define check_key(key,...)
Definition: checkasm.h:215
w
uint8_t w
Definition: llvidencdsp.c:39
declare_func
#define declare_func(ret,...)
Definition: checkasm.h:219
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
F32
@ F32
Definition: sw_ops.c:42
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:2369
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
checkasm_call
#define checkasm_call(func,...)
Definition: checkasm.h:233
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
checkasm_check
#define checkasm_check(prefix,...)
Definition: checkasm.h:473
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:263
SwsContext
Main external API structure.
Definition: swscale.h:206
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:693