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_ops(const char *report, const unsigned ranges[NB_PLANES],
115  const SwsOp *ops)
116 {
118  SwsCompiledOp comp_ref = {0}, comp_new = {0};
119  const SwsOpBackend *backend_new = NULL;
120  SwsOpList oplist = { .ops = (SwsOp *) ops };
121  const SwsOp *read_op, *write_op;
122  static const unsigned def_ranges[4] = {0};
123  if (!ranges)
124  ranges = def_ranges;
125 
126  declare_func(void, const SwsOpExec *, const void *, int bx, int y, int bx_end, int y_end);
127 
128  static DECLARE_ALIGNED_64(char, src0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
129  static DECLARE_ALIGNED_64(char, src1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
130  static DECLARE_ALIGNED_64(char, dst0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
131  static DECLARE_ALIGNED_64(char, dst1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
132 
133  if (!ctx)
134  return;
136 
137  read_op = &ops[0];
138  for (oplist.num_ops = 0; ops[oplist.num_ops].op; oplist.num_ops++)
139  write_op = &ops[oplist.num_ops];
140 
141  const int read_size = PIXELS * rw_pixel_bits(read_op) >> 3;
142  const int write_size = PIXELS * rw_pixel_bits(write_op) >> 3;
143 
144  for (int p = 0; p < NB_PLANES; p++) {
145  void *plane = src0[p];
146  switch (read_op->type) {
147  case U8:
148  fill8(plane, sizeof(src0[p]) / sizeof(uint8_t), ranges[p]);
149  set_range(&oplist.comps_src.max[p], ranges[p], UINT8_MAX);
150  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
151  break;
152  case U16:
153  fill16(plane, sizeof(src0[p]) / sizeof(uint16_t), ranges[p]);
154  set_range(&oplist.comps_src.max[p], ranges[p], UINT16_MAX);
155  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
156  break;
157  case U32:
158  fill32(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
159  set_range(&oplist.comps_src.max[p], ranges[p], UINT32_MAX);
160  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
161  break;
162  case F32:
163  fill32f(plane, sizeof(src0[p]) / sizeof(uint32_t), ranges[p]);
164  if (ranges[p] && ranges[p] <= INT_MAX) {
165  oplist.comps_src.max[p] = (AVRational) { ranges[p], 1 };
166  oplist.comps_src.min[p] = (AVRational) { 0, 1 };
167  }
168  break;
169  }
170  }
171 
172  memcpy(src1, src0, sizeof(src0));
173  memset(dst0, 0, sizeof(dst0));
174  memset(dst1, 0, sizeof(dst1));
175 
176  /* Compile `ops` using both the asm and c backends */
177  for (int n = 0; ff_sws_op_backends[n]; n++) {
178  const SwsOpBackend *backend = ff_sws_op_backends[n];
179  const bool is_ref = !strcmp(backend->name, "c");
180  if (is_ref || !comp_new.func) {
182  int ret = ff_sws_ops_compile_backend(ctx, backend, &oplist, &comp);
183  if (ret == AVERROR(ENOTSUP))
184  continue;
185  else if (ret < 0)
186  fail();
187  else if (PIXELS % comp.block_size != 0)
188  fail();
189 
190  if (is_ref)
191  comp_ref = comp;
192  if (!comp_new.func) {
193  comp_new = comp;
194  backend_new = backend;
195  }
196  }
197  }
198 
199  av_assert0(comp_ref.func && comp_new.func);
200 
201  SwsOpExec exec = {0};
202  exec.width = PIXELS;
203  exec.height = exec.slice_h = LINES;
204  for (int i = 0; i < NB_PLANES; i++) {
205  exec.in_stride[i] = sizeof(src0[i][0]);
206  exec.out_stride[i] = sizeof(dst0[i][0]);
207  exec.in_bump[i] = exec.in_stride[i] - read_size;
208  exec.out_bump[i] = exec.out_stride[i] - write_size;
209  }
210 
211  int32_t in_bump_y[LINES];
212  if (read_op->rw.filter == SWS_OP_FILTER_V) {
213  const int *offsets = read_op->rw.kernel->offsets;
214  for (int y = 0; y < LINES - 1; y++)
215  in_bump_y[y] = offsets[y + 1] - offsets[y] - 1;
216  in_bump_y[LINES - 1] = 0;
217  exec.in_bump_y = in_bump_y;
218  }
219 
220  int32_t in_offset_x[PIXELS];
221  if (read_op->rw.filter == SWS_OP_FILTER_H) {
222  const int *offsets = read_op->rw.kernel->offsets;
223  const int rw_bits = rw_pixel_bits(read_op);
224  for (int x = 0; x < PIXELS; x++)
225  in_offset_x[x] = offsets[x] * rw_bits >> 3;
226  exec.in_offset_x = in_offset_x;
227  }
228 
229  /**
230  * Don't use check_func() because the actual function pointer may be a
231  * wrapper shared by multiple implementations. Instead, take a hash of both
232  * the backend pointer and the active CPU flags.
233  */
234  uintptr_t id = (uintptr_t) backend_new;
235  id ^= (id << 6) + (id >> 2) + 0x9e3779b97f4a7c15 + comp_new.cpu_flags;
236 
237  if (check_key((void*) id, "%s", report)) {
238  exec.block_size_in = comp_ref.block_size * rw_pixel_bits(read_op) >> 3;
239  exec.block_size_out = comp_ref.block_size * rw_pixel_bits(write_op) >> 3;
240  for (int i = 0; i < NB_PLANES; i++) {
241  exec.in[i] = (void *) src0[i];
242  exec.out[i] = (void *) dst0[i];
243  }
244  checkasm_call(comp_ref.func, &exec, comp_ref.priv, 0, 0, PIXELS / comp_ref.block_size, LINES);
245 
246  exec.block_size_in = comp_new.block_size * rw_pixel_bits(read_op) >> 3;
247  exec.block_size_out = comp_new.block_size * rw_pixel_bits(write_op) >> 3;
248  for (int i = 0; i < NB_PLANES; i++) {
249  exec.in[i] = (void *) src1[i];
250  exec.out[i] = (void *) dst1[i];
251  }
252  checkasm_call_checked(comp_new.func, &exec, comp_new.priv, 0, 0, PIXELS / comp_new.block_size, LINES);
253 
254  for (int i = 0; i < NB_PLANES; i++) {
255  const char *name = FMT("%s[%d]", report, i);
256  const int stride = sizeof(dst0[i][0]);
257 
258  switch (write_op->type) {
259  case U8:
260  checkasm_check(uint8_t, (void *) dst0[i], stride,
261  (void *) dst1[i], stride,
262  write_size, LINES, name);
263  break;
264  case U16:
265  checkasm_check(uint16_t, (void *) dst0[i], stride,
266  (void *) dst1[i], stride,
267  write_size >> 1, LINES, name);
268  break;
269  case U32:
270  checkasm_check(uint32_t, (void *) dst0[i], stride,
271  (void *) dst1[i], stride,
272  write_size >> 2, LINES, name);
273  break;
274  case F32:
275  checkasm_check(float_ulp, (void *) dst0[i], stride,
276  (void *) dst1[i], stride,
277  write_size >> 2, LINES, name, 0);
278  break;
279  }
280 
281  if (write_op->rw.packed)
282  break;
283  }
284 
285  bench(comp_new.func, &exec, comp_new.priv, 0, 0, PIXELS / comp_new.block_size, LINES);
286  }
287 
288  if (comp_new.func != comp_ref.func)
289  ff_sws_compiled_op_unref(&comp_new);
290  ff_sws_compiled_op_unref(&comp_ref);
292 }
293 
294 #define CHECK_RANGES(NAME, RANGES, N_IN, N_OUT, IN, OUT, ...) \
295  do { \
296  check_ops(NAME, RANGES, (SwsOp[]) { \
297  { \
298  .op = SWS_OP_READ, \
299  .type = IN, \
300  .rw.elems = N_IN, \
301  }, \
302  __VA_ARGS__, \
303  { \
304  .op = SWS_OP_WRITE, \
305  .type = OUT, \
306  .rw.elems = N_OUT, \
307  }, {0} \
308  }); \
309  } while (0)
310 
311 #define MK_RANGES(R) ((const unsigned[]) { R, R, R, R })
312 #define CHECK_RANGE(NAME, RANGE, N_IN, N_OUT, IN, OUT, ...) \
313  CHECK_RANGES(NAME, MK_RANGES(RANGE), N_IN, N_OUT, IN, OUT, __VA_ARGS__)
314 
315 #define CHECK_COMMON_RANGE(NAME, RANGE, IN, OUT, ...) \
316  CHECK_RANGE(FMT("%s_p1000", NAME), RANGE, 1, 1, IN, OUT, __VA_ARGS__); \
317  CHECK_RANGE(FMT("%s_p1110", NAME), RANGE, 3, 3, IN, OUT, __VA_ARGS__); \
318  CHECK_RANGE(FMT("%s_p1111", NAME), RANGE, 4, 4, IN, OUT, __VA_ARGS__); \
319  CHECK_RANGE(FMT("%s_p1001", NAME), RANGE, 4, 2, IN, OUT, __VA_ARGS__, { \
320  .op = SWS_OP_SWIZZLE, \
321  .type = OUT, \
322  .swizzle = SWS_SWIZZLE(0, 3, 1, 2), \
323  })
324 
325 #define CHECK(NAME, N_IN, N_OUT, IN, OUT, ...) \
326  CHECK_RANGE(NAME, 0, N_IN, N_OUT, IN, OUT, __VA_ARGS__)
327 
328 #define CHECK_COMMON(NAME, IN, OUT, ...) \
329  CHECK_COMMON_RANGE(NAME, 0, IN, OUT, __VA_ARGS__)
330 
331 static void check_read_write(void)
332 {
333  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
334  const char *type = ff_sws_pixel_type_name(t);
335  for (int i = 1; i <= 4; i++) {
336  /* Test N->N planar read/write */
337  for (int o = 1; o <= i; o++) {
338  check_ops(FMT("rw_%d_%d_%s", i, o, type), NULL, (SwsOp[]) {
339  {
340  .op = SWS_OP_READ,
341  .type = t,
342  .rw.elems = i,
343  }, {
344  .op = SWS_OP_WRITE,
345  .type = t,
346  .rw.elems = o,
347  }, {0}
348  });
349  }
350 
351  /* Test packed read/write */
352  if (i == 1)
353  continue;
354 
355  check_ops(FMT("read_packed%d_%s", i, type), NULL, (SwsOp[]) {
356  {
357  .op = SWS_OP_READ,
358  .type = t,
359  .rw.elems = i,
360  .rw.packed = true,
361  }, {
362  .op = SWS_OP_WRITE,
363  .type = t,
364  .rw.elems = i,
365  }, {0}
366  });
367 
368  check_ops(FMT("write_packed%d_%s", i, type), NULL, (SwsOp[]) {
369  {
370  .op = SWS_OP_READ,
371  .type = t,
372  .rw.elems = i,
373  }, {
374  .op = SWS_OP_WRITE,
375  .type = t,
376  .rw.elems = i,
377  .rw.packed = true,
378  }, {0}
379  });
380  }
381  }
382 
383  /* Test fractional reads/writes */
384  for (int frac = 1; frac <= 3; frac++) {
385  const int bits = 8 >> frac;
386  const int range = (1 << bits) - 1;
387  if (bits == 2)
388  continue; /* no 2 bit packed formats currently exist */
389 
390  check_ops(FMT("read_frac%d", frac), NULL, (SwsOp[]) {
391  {
392  .op = SWS_OP_READ,
393  .type = U8,
394  .rw.elems = 1,
395  .rw.frac = frac,
396  }, {
397  .op = SWS_OP_WRITE,
398  .type = U8,
399  .rw.elems = 1,
400  }, {0}
401  });
402 
403  check_ops(FMT("write_frac%d", frac), MK_RANGES(range), (SwsOp[]) {
404  {
405  .op = SWS_OP_READ,
406  .type = U8,
407  .rw.elems = 1,
408  }, {
409  .op = SWS_OP_WRITE,
410  .type = U8,
411  .rw.elems = 1,
412  .rw.frac = frac,
413  }, {0}
414  });
415  }
416 }
417 
418 static void check_swap_bytes(void)
419 {
420  CHECK_COMMON("swap_bytes_16", U16, U16, {
421  .op = SWS_OP_SWAP_BYTES,
422  .type = U16,
423  });
424 
425  CHECK_COMMON("swap_bytes_32", U32, U32, {
426  .op = SWS_OP_SWAP_BYTES,
427  .type = U32,
428  });
429 }
430 
431 static void check_pack_unpack(void)
432 {
433  const struct {
435  SwsPackOp op;
436  } patterns[] = {
437  { U8, {{ 3, 3, 2 }}},
438  { U8, {{ 2, 3, 3 }}},
439  { U8, {{ 1, 2, 1 }}},
440  {U16, {{ 5, 6, 5 }}},
441  {U16, {{ 5, 5, 5 }}},
442  {U16, {{ 4, 4, 4 }}},
443  {U32, {{ 2, 10, 10, 10 }}},
444  {U32, {{10, 10, 10, 2 }}},
445  };
446 
447  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
448  const SwsPixelType type = patterns[i].type;
449  const SwsPackOp pack = patterns[i].op;
450  const int num = pack.pattern[3] ? 4 : 3;
451  const char *pat = FMT("%d%d%d%d", pack.pattern[0], pack.pattern[1],
452  pack.pattern[2], pack.pattern[3]);
453  const int total = pack.pattern[0] + pack.pattern[1] +
454  pack.pattern[2] + pack.pattern[3];
455  const unsigned ranges[4] = {
456  (1 << pack.pattern[0]) - 1,
457  (1 << pack.pattern[1]) - 1,
458  (1 << pack.pattern[2]) - 1,
459  (1 << pack.pattern[3]) - 1,
460  };
461 
462  CHECK_RANGES(FMT("pack_%s", pat), ranges, num, 1, type, type, {
463  .op = SWS_OP_PACK,
464  .type = type,
465  .pack = pack,
466  });
467 
468  CHECK_RANGE(FMT("unpack_%s", pat), UINT32_MAX >> (32 - total), 1, num, type, type, {
469  .op = SWS_OP_UNPACK,
470  .type = type,
471  .pack = pack,
472  });
473  }
474 }
475 
477 {
478  const unsigned num = rnd();
479  if (ff_sws_pixel_type_is_int(t)) {
480  const unsigned mask = UINT_MAX >> (32 - ff_sws_pixel_type_size(t) * 8);
481  return (AVRational) { num & mask, 1 };
482  } else {
483  const unsigned den = rnd();
484  return (AVRational) { num, den ? den : 1 };
485  }
486 }
487 
488 static void check_clear(void)
489 {
490  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
491  const char *type = ff_sws_pixel_type_name(t);
492  const int bits = ff_sws_pixel_type_size(t) * 8;
493 
494  /* TODO: AVRational can't fit 32 bit constants */
495  if (bits < 32) {
496  const AVRational chroma = (AVRational) { 1 << (bits - 1), 1};
497  const AVRational alpha = (AVRational) { (1 << bits) - 1, 1};
498  const AVRational zero = (AVRational) { 0, 1};
499  const AVRational none = {0};
500 
501  const SwsClearOp patterns[] = {
502  /* Zero only */
503  {{ none, none, none, zero }},
504  {{ zero, none, none, none }},
505  /* Alpha only */
506  {{ none, none, none, alpha }},
507  {{ alpha, none, none, none }},
508  /* Chroma only */
509  {{ chroma, chroma, none, none }},
510  {{ none, chroma, chroma, none }},
511  {{ none, none, chroma, chroma }},
512  {{ chroma, none, chroma, none }},
513  {{ none, chroma, none, chroma }},
514  /* Alpha+chroma */
515  {{ chroma, chroma, none, alpha }},
516  {{ none, chroma, chroma, alpha }},
517  {{ alpha, none, chroma, chroma }},
518  {{ chroma, none, chroma, alpha }},
519  {{ alpha, chroma, none, chroma }},
520  /* Random values */
521  {{ none, rndq(t), rndq(t), rndq(t) }},
522  {{ none, rndq(t), rndq(t), rndq(t) }},
523  {{ none, rndq(t), rndq(t), rndq(t) }},
524  {{ none, rndq(t), rndq(t), rndq(t) }},
525  };
526 
527  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
528  CHECK(FMT("clear_pattern_%s[%d]", type, i), 4, 4, t, t, {
529  .op = SWS_OP_CLEAR,
530  .type = t,
531  .clear = patterns[i],
532  });
533  }
534  } else if (!ff_sws_pixel_type_is_int(t)) {
535  /* Floating point YUV doesn't exist, only alpha needs to be cleared */
536  CHECK(FMT("clear_alpha_%s", type), 4, 4, t, t, {
537  .op = SWS_OP_CLEAR,
538  .type = t,
539  .clear.value[3] = { 0, 1 },
540  });
541  }
542  }
543 }
544 
545 static void check_shift(void)
546 {
547  for (SwsPixelType t = U16; t < SWS_PIXEL_TYPE_NB; t++) {
548  const char *type = ff_sws_pixel_type_name(t);
549  if (!ff_sws_pixel_type_is_int(t))
550  continue;
551 
552  for (int shift = 1; shift <= 8; shift++) {
553  CHECK_COMMON(FMT("lshift%d_%s", shift, type), t, t, {
554  .op = SWS_OP_LSHIFT,
555  .type = t,
556  .shift = { shift },
557  });
558 
559  CHECK_COMMON(FMT("rshift%d_%s", shift, type), t, t, {
560  .op = SWS_OP_RSHIFT,
561  .type = t,
562  .shift = { shift },
563  });
564  }
565  }
566 }
567 
568 static void check_swizzle(void)
569 {
570  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
571  const char *type = ff_sws_pixel_type_name(t);
572  static const int patterns[][4] = {
573  /* Pure swizzle */
574  {3, 0, 1, 2},
575  {3, 0, 2, 1},
576  {2, 1, 0, 3},
577  {3, 2, 1, 0},
578  {3, 1, 0, 2},
579  {3, 2, 0, 1},
580  {1, 2, 0, 3},
581  {1, 0, 2, 3},
582  {2, 0, 1, 3},
583  {2, 3, 1, 0},
584  {2, 1, 3, 0},
585  {1, 2, 3, 0},
586  {1, 3, 2, 0},
587  {0, 2, 1, 3},
588  {0, 2, 3, 1},
589  {0, 3, 1, 2},
590  {3, 1, 2, 0},
591  {0, 3, 2, 1},
592  /* Luma expansion */
593  {0, 0, 0, 3},
594  {3, 0, 0, 0},
595  {0, 0, 0, 1},
596  {1, 0, 0, 0},
597  };
598 
599  for (int i = 0; i < FF_ARRAY_ELEMS(patterns); i++) {
600  const int x = patterns[i][0], y = patterns[i][1],
601  z = patterns[i][2], w = patterns[i][3];
602  CHECK(FMT("swizzle_%d%d%d%d_%s", x, y, z, w, type), 4, 4, t, t, {
603  .op = SWS_OP_SWIZZLE,
604  .type = t,
605  .swizzle = SWS_SWIZZLE(x, y, z, w),
606  });
607  }
608  }
609 }
610 
611 static void check_convert(void)
612 {
613  for (SwsPixelType i = U8; i < SWS_PIXEL_TYPE_NB; i++) {
614  const char *itype = ff_sws_pixel_type_name(i);
615  const int isize = ff_sws_pixel_type_size(i);
616  for (SwsPixelType o = U8; o < SWS_PIXEL_TYPE_NB; o++) {
617  const char *otype = ff_sws_pixel_type_name(o);
618  const int osize = ff_sws_pixel_type_size(o);
619  const char *name = FMT("convert_%s_%s", itype, otype);
620  if (i == o)
621  continue;
622 
623  if (isize < osize || !ff_sws_pixel_type_is_int(o)) {
624  CHECK_COMMON(name, i, o, {
625  .op = SWS_OP_CONVERT,
626  .type = i,
627  .convert.to = o,
628  });
629  } else if (isize > osize || !ff_sws_pixel_type_is_int(i)) {
630  uint32_t range = UINT32_MAX >> (32 - osize * 8);
632  .op = SWS_OP_CONVERT,
633  .type = i,
634  .convert.to = o,
635  });
636  }
637  }
638  }
639 
640  /* Check expanding conversions */
641  CHECK_COMMON("expand16", U8, U16, {
642  .op = SWS_OP_CONVERT,
643  .type = U8,
644  .convert.to = U16,
645  .convert.expand = true,
646  });
647 
648  CHECK_COMMON("expand32", U8, U32, {
649  .op = SWS_OP_CONVERT,
650  .type = U8,
651  .convert.to = U32,
652  .convert.expand = true,
653  });
654 }
655 
656 static void check_dither(void)
657 {
658  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
659  const char *type = ff_sws_pixel_type_name(t);
661  continue;
662 
663  /* Test all sizes up to 256x256 */
664  for (int size_log2 = 0; size_log2 <= 8; size_log2++) {
665  const int size = 1 << size_log2;
666  const int mask = size - 1;
668  if (!matrix) {
669  fail();
670  return;
671  }
672 
673  if (size == 1) {
674  matrix[0] = (AVRational) { 1, 2 };
675  } else {
676  for (int i = 0; i < size * size; i++)
677  matrix[i] = rndq(t);
678  }
679 
680  CHECK_COMMON(FMT("dither_%dx%d_%s", size, size, type), t, t, {
681  .op = SWS_OP_DITHER,
682  .type = t,
683  .dither.size_log2 = size_log2,
684  .dither.matrix = matrix,
685  .dither.y_offset = {0, 3 & mask, 2 & mask, 5 & mask},
686  });
687 
689  }
690  }
691 }
692 
693 static void check_min_max(void)
694 {
695  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
696  const char *type = ff_sws_pixel_type_name(t);
697  CHECK_COMMON(FMT("min_%s", type), t, t, {
698  .op = SWS_OP_MIN,
699  .type = t,
700  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
701  });
702 
703  CHECK_COMMON(FMT("max_%s", type), t, t, {
704  .op = SWS_OP_MAX,
705  .type = t,
706  .clamp = {{ rndq(t), rndq(t), rndq(t), rndq(t) }},
707  });
708  }
709 }
710 
711 static void check_linear(void)
712 {
713  static const struct {
714  const char *name;
715  uint32_t mask;
716  } patterns[] = {
717  { "noop", 0 },
718  { "luma", SWS_MASK_LUMA },
719  { "alpha", SWS_MASK_ALPHA },
720  { "luma+alpha", SWS_MASK_LUMA | SWS_MASK_ALPHA },
721  { "dot3", 0x7 },
722  { "dot4", 0xF },
723  { "row0", SWS_MASK_ROW(0) },
724  { "row0+alpha", SWS_MASK_ROW(0) | SWS_MASK_ALPHA },
725  { "off3", SWS_MASK_OFF3 },
726  { "off3+alpha", SWS_MASK_OFF3 | SWS_MASK_ALPHA },
727  { "diag3", SWS_MASK_DIAG3 },
728  { "diag4", SWS_MASK_DIAG4 },
729  { "diag3+alpha", SWS_MASK_DIAG3 | SWS_MASK_ALPHA },
730  { "diag3+off3", SWS_MASK_DIAG3 | SWS_MASK_OFF3 },
731  { "diag3+off3+alpha", SWS_MASK_DIAG3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
732  { "diag4+off4", SWS_MASK_DIAG4 | SWS_MASK_OFF4 },
733  { "matrix3", SWS_MASK_MAT3 },
734  { "matrix3+off3", SWS_MASK_MAT3 | SWS_MASK_OFF3 },
735  { "matrix3+off3+alpha", SWS_MASK_MAT3 | SWS_MASK_OFF3 | SWS_MASK_ALPHA },
736  { "matrix4", SWS_MASK_MAT4 },
737  { "matrix4+off4", SWS_MASK_MAT4 | SWS_MASK_OFF4 },
738  };
739 
740  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
741  const char *type = ff_sws_pixel_type_name(t);
743  continue;
744 
745  for (int p = 0; p < FF_ARRAY_ELEMS(patterns); p++) {
746  const uint32_t mask = patterns[p].mask;
747  SwsLinearOp lin = { .mask = mask };
748 
749  for (int i = 0; i < 4; i++) {
750  for (int j = 0; j < 5; j++) {
751  if (mask & SWS_MASK(i, j)) {
752  lin.m[i][j] = rndq(t);
753  } else {
754  lin.m[i][j] = (AVRational) { i == j, 1 };
755  }
756  }
757  }
758 
759  CHECK(FMT("linear_%s_%s", patterns[p].name, type), 4, 4, t, t, {
760  .op = SWS_OP_LINEAR,
761  .type = t,
762  .lin = lin,
763  });
764  }
765  }
766 }
767 
768 static void check_scale(void)
769 {
770  for (SwsPixelType t = F32; t < SWS_PIXEL_TYPE_NB; t++) {
771  const char *type = ff_sws_pixel_type_name(t);
772  const int bits = ff_sws_pixel_type_size(t) * 8;
773  if (ff_sws_pixel_type_is_int(t)) {
774  /* Ensure the result won't exceed the value range */
775  const unsigned max = (1 << bits) - 1;
776  const unsigned scale = rnd() & max;
777  const unsigned range = max / (scale ? scale : 1);
778  CHECK_COMMON_RANGE(FMT("scale_%s", type), range, t, t, {
779  .op = SWS_OP_SCALE,
780  .type = t,
781  .scale = {{ scale, 1 }},
782  });
783  } else {
784  CHECK_COMMON(FMT("scale_%s", type), t, t, {
785  .op = SWS_OP_SCALE,
786  .type = t,
787  .scale = { rndq(t) },
788  });
789  }
790  }
791 }
792 
793 static void check_filter(void)
794 {
795  SwsFilterParams params = {
797  };
798 
800 
801  for (SwsPixelType t = U8; t < SWS_PIXEL_TYPE_NB; t++) {
802  const char *type = ff_sws_pixel_type_name(t);
803  for (SwsScaler scaler = SWS_SCALE_AUTO + 1; scaler < SWS_SCALE_NB; scaler++) {
804  params.scaler = scaler;
805  params.dst_size = LINES;
806  for (int h = 1; h <= LINES; h += h) {
807  params.src_size = h;
808  int ret = ff_sws_filter_generate(NULL, &params, &filter);
809  if (ret < 0) {
810  fail();
811  return;
812  }
813 
814  const char *name = filter->name;
815  for (int n = 1; n <= 4; n++) {
816  check_ops(FMT("%s_filter%d_v_%dx%d_%s", name, n, PIXELS, h, type), NULL, (SwsOp[]) {
817  {
818  .op = SWS_OP_READ,
819  .type = t,
820  .rw.elems = n,
821  .rw.filter = SWS_OP_FILTER_V,
822  .rw.kernel = filter,
823  }, {
824  .op = SWS_OP_WRITE,
825  .type = SWS_PIXEL_F32,
826  .rw.elems = n,
827  }, {0}
828  });
829  }
830 
832  }
833 
834  params.dst_size = PIXELS;
835  for (int w = 1; w <= PIXELS; w += w) {
836  params.src_size = w;
837  int ret = ff_sws_filter_generate(NULL, &params, &filter);
838  if (ret < 0) {
839  fail();
840  return;
841  }
842 
843  const char *name = filter->name;
844  for (int n = 1; n <= 4; n++) {
845  check_ops(FMT("%s_filter%d_h_%dx%d_%s", name, n, w, LINES, type), NULL, (SwsOp[]) {
846  {
847  .op = SWS_OP_READ,
848  .type = t,
849  .rw.elems = n,
850  .rw.filter = SWS_OP_FILTER_H,
851  .rw.kernel = filter,
852  }, {
853  .op = SWS_OP_WRITE,
854  .type = SWS_PIXEL_F32,
855  .rw.elems = n,
856  }, {0}
857  });
858  }
859 
861  }
862  }
863  }
864 }
865 
867 {
869  report("read_write");
871  report("swap_bytes");
873  report("pack_unpack");
874  check_clear();
875  report("clear");
876  check_shift();
877  report("shift");
878  check_swizzle();
879  report("swizzle");
880  check_convert();
881  report("convert");
882  check_dither();
883  report("dither");
884  check_min_max();
885  report("min_max");
886  check_linear();
887  report("linear");
888  check_scale();
889  report("scale");
890  check_filter();
891  report("filter");
892 }
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
SWS_SCALE_AUTO
@ SWS_SCALE_AUTO
Definition: swscale.h:97
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
U16
@ U16
Definition: sw_ops.c:40
mem_internal.h
U32
@ U32
Definition: sw_ops.c:41
SwsFilterParams::src_size
int src_size
The relative sizes of the input and output images.
Definition: filters.h:57
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:79
SwsOpList::comps_src
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
Definition: ops.h:282
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:328
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
check_min_max
static void check_min_max(void)
Definition: sw_ops.c:693
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:866
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:611
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:418
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:315
check_read_write
static void check_read_write(void)
Definition: sw_ops.c:331
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_OFF3
@ SWS_MASK_OFF3
Definition: ops.h:201
check_linear
static void check_linear(void)
Definition: sw_ops.c:711
SwsOpBackend::name
const char * name
Definition: ops_internal.h:56
check_filter
static void check_filter(void)
Definition: sw_ops.c:793
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:68
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
SWS_MASK_ALPHA
@ SWS_MASK_ALPHA
Definition: ops.h:198
check_clear
static void check_clear(void)
Definition: sw_ops.c:488
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:312
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:39
LINES
@ LINES
Definition: sw_ops.c:35
check_scale
static void check_scale(void)
Definition: sw_ops.c:768
fail
#define fail()
Definition: checkasm.h:223
SwsOpList::num_ops
int num_ops
Definition: ops.h:265
SwsFilterParams::dst_size
int dst_size
Definition: filters.h:58
PIXELS
@ PIXELS
Definition: sw_ops.c:34
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:83
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
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:206
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
float
float
Definition: af_crystalizer.c:122
U8
@ U8
Definition: sw_ops.c:39
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
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:311
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
F32
@ F32
Definition: sw_ops.c:42
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
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
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
SWS_OP_FILTER_V
@ SWS_OP_FILTER_V
Definition: ops.h:74
SWS_MASK_MAT3
@ SWS_MASK_MAT3
Definition: ops.h:202
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_MASK_DIAG4
@ SWS_MASK_DIAG4
Definition: ops.h:206
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
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
check_ops
static void check_ops(const char *report, const unsigned ranges[NB_PLANES], const SwsOp *ops)
Definition: sw_ops.c:114
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
NB_PLANES
@ NB_PLANES
Definition: sw_ops.c:33
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
report
#define report
Definition: checkasm.h:226
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:338
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:545
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:65
SwsCompiledOp
Definition: ops_dispatch.h:100
bench
#define bench(func,...)
Definition: checkasm.h:423
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:568
SWS_PIXEL_TYPE_NB
@ SWS_PIXEL_TYPE_NB
Definition: ops.h:39
SWS_MASK_LUMA
@ SWS_MASK_LUMA
Definition: ops.h:197
SWS_MASK_MAT4
@ SWS_MASK_MAT4
Definition: ops.h:208
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:53
SWS_SCALE_NB
@ SWS_SCALE_NB
not part of the ABI
Definition: swscale.h:106
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:476
check_key
#define check_key(key,...)
Definition: checkasm.h:214
w
uint8_t w
Definition: llvidencdsp.c:39
declare_func
#define declare_func(ret,...)
Definition: checkasm.h:218
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:2368
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:232
check_pack_unpack
static void check_pack_unpack(void)
Definition: sw_ops.c:431
h
h
Definition: vp9dsp_template.c:2070
stride
#define stride
Definition: h264pred_template.c:536
checkasm_check
#define checkasm_check(prefix,...)
Definition: checkasm.h:472
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:263
SWS_MASK_DIAG3
@ SWS_MASK_DIAG3
Definition: ops.h:200
SwsContext
Main external API structure.
Definition: swscale.h:206
CHECK
#define CHECK(NAME, N_IN, N_OUT, IN, OUT,...)
Definition: sw_ops.c:325
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:294
SwsOpExec::out_bump
ptrdiff_t out_bump[4]
Definition: ops_dispatch.h:52
check_dither
static void check_dither(void)
Definition: sw_ops.c:656
SWS_MASK_OFF4
@ SWS_MASK_OFF4
Definition: ops.h:207