29#if IS_FLOAT && BIT_DEPTH == 32
30# define PIXEL_TYPE SWS_PIXEL_F32
33# define vec3_t v3f32_t
37# define PIXEL_MAX 0xFFFFFFFFu
38# define PIXEL_SWAP av_bswap32
39# define pixel_t uint32_t
40# define inter_t int64_t
44# define PIXEL_MAX 0xFFFFu
45# define PIXEL_SWAP av_bswap16
46# define pixel_t uint16_t
47# define inter_t int64_t
51# define PIXEL_MAX 0xFFu
52# define pixel_t uint8_t
53# define inter_t int32_t
57# error Invalid BIT_DEPTH
84 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
88 if (
X) x[
i] = in0[elems *
i + 0];
89 if (
Y) y[
i] = in0[elems *
i + 1];
90 if (
Z) z[
i] = in0[elems *
i + 2];
91 if (
W)
w[
i] = in0[elems *
i + 3];
102 if (
X) out0[
i] = x[
i];
103 if (
Y) out1[
i] = y[
i];
104 if (
Z) out2[
i] = z[
i];
105 if (
W) out3[
i] =
w[
i];
116 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
120 if (
X) out0[elems *
i + 0] = x[
i];
121 if (
Y) out0[elems *
i + 1] = y[
i];
122 if (
Z) out0[elems *
i + 2] = z[
i];
123 if (
W) out0[elems *
i + 3] =
w[
i];
137 const pixel_t
val = ((
const pixel_t *) in0)[
i >> 3];
138 x[
i + 0] = (
val >> 7) & 1;
139 x[
i + 1] = (
val >> 6) & 1;
140 x[
i + 2] = (
val >> 5) & 1;
141 x[
i + 3] = (
val >> 4) & 1;
142 x[
i + 4] = (
val >> 3) & 1;
143 x[
i + 5] = (
val >> 2) & 1;
144 x[
i + 6] = (
val >> 1) & 1;
145 x[
i + 7] = (
val >> 0) & 1;
158 const pixel_t
val = in0[
i >> 1];
160 x[
i + 1] =
val & 0xF;
173 const pixel_t
index = in0[
i];
191 out0[
i >> 3] = x[
i + 0] << 7 |
210 out0[
i >> 1] = x[
i] << 4 | x[
i + 1];
247 static_assert(
sizeof(
out->priv.ptr) <=
sizeof(
int32_t[2]),
248 ">8 byte pointers not supported");
255 for (
int i = 0;
i <
filter->num_weights;
i++)
269 const float *restrict
weights = impl->priv.ptr;
270 const int filter_size = impl->priv.i32[2];
271 weights += filter_size * iter->y;
274 if (
X) memset(&
xs.f32, 0,
sizeof(
xs.f32));
275 if (
Y) memset(&ys.
f32, 0,
sizeof(ys.
f32));
276 if (
Z) memset(&zs.
f32, 0,
sizeof(zs.
f32));
277 if (
W) memset(&ws.
f32, 0,
sizeof(ws.
f32));
279 for (
int j = 0; j < filter_size; j++) {
317 if (padded_w ==
filter->dst_size) {
337 const int *restrict
weights = impl->priv.ptr;
338 const int filter_size = impl->priv.i32[2];
340 const int xpos = iter->x;
341 weights += filter_size * iter->x;
351 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
352 for (
int j = 0; j < filter_size; j++) {
354 if (
X) sx +=
weight * start0[j];
355 if (
Y) sy +=
weight * start1[j];
356 if (
Z) sz +=
weight * start2[j];
357 if (
W) sw +=
weight * start3[j];
381 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
382 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
387 pixel_t *ptr[5] = {
NULL, x, y, z,
w };
388 for (
int n = 0; n < num_moves; n++)
389 ptr[
dst[n] + 1] = ptr[
src[n] + 1];
401 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
402 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
409 memcpy(&
data[1].px, x, block_size);
410 memcpy(&
data[2].px, y, block_size);
411 memcpy(&
data[3].px, z, block_size);
412 memcpy(&
data[4].px,
w, block_size);
414 for (
int n = 0; n < num_moves; n++)
417 memcpy(x, &
data[1].px, block_size);
418 memcpy(y, &
data[2].px, block_size);
419 memcpy(z, &
data[3].px, block_size);
420 memcpy(
w, &
data[4].px, block_size);
434#define DECL_CAST(DST, dst) \
435 DECL_FUNC(to_##dst, const SwsCompMask mask) \
437 block_t xx, yy, zz, ww; \
440 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
441 if (X) xx.dst[i] = x[i]; \
442 if (Y) yy.dst[i] = y[i]; \
443 if (Z) zz.dst[i] = z[i]; \
444 if (W) ww.dst[i] = w[i]; \
447 CONTINUE(&xx, &yy, &zz, &ww); \
450 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
451 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
467 if (
X) x[
i] <<= amount;
468 if (
Y) y[
i] <<= amount;
469 if (
Z) z[
i] <<= amount;
470 if (
W)
w[
i] <<= amount;
480 if (
X) x[
i] >>= amount;
481 if (
Y) y[
i] >>= amount;
482 if (
Z) z[
i] >>= amount;
483 if (
W)
w[
i] >>= amount;
501 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
502 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
503 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
504 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
536 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
537 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
538 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
551 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
552 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
553 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
554 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
574 const uint8_t bx,
const uint8_t by,
575 const uint8_t bz,
const uint8_t bw)
577 const uint8_t sx = bw + bz + by;
578 const uint8_t sy = bw + bz;
579 const uint8_t sz = bw;
580 const uint8_t sw = 0;
582 const pixel_t
mx = (1 << bx) - 1;
583 const pixel_t
my = (1 << by) - 1;
584 const pixel_t
mz = (1 << bz) - 1;
585 const pixel_t mw = (1 << bw) - 1;
589 const pixel_t
val = x[
i];
590 if (
X) x[
i] = (
val >> sx) &
mx;
591 if (
Y) y[
i] = (
val >> sy) &
my;
592 if (
Z) z[
i] = (
val >> sz) &
mz;
593 if (
W)
w[
i] = (
val >> sw) & mw;
600 const uint8_t bx,
const uint8_t by,
601 const uint8_t bz,
const uint8_t bw)
603 const uint8_t sx = bw + bz + by;
604 const uint8_t sy = bw + bz;
605 const uint8_t sz = bw;
606 const uint8_t sw = 0;
611 if (
X)
val |= x[
i] << sx;
612 if (
Y)
val |= y[
i] << sy;
613 if (
Z)
val |= z[
i] << sz;
635 #define ONE(N) SWS_COMP_TEST(one, N)
636 #define ZERO(N) SWS_COMP_TEST(zero, N)
663 const pixel_t
scale = impl->priv.px[0];
680 if (
X) x[
i] += impl->priv.px[0];
681 if (
Y) y[
i] += impl->priv.px[1];
682 if (
Z) z[
i] += impl->priv.px[2];
683 if (
W)
w[
i] += impl->priv.px[3];
693 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
694 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
695 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
706 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
707 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
708 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
751 for (
int y = 0; y <
height; y++) {
753 for (
int x = 0; x <
size; x++)
756 row[x] = row[x %
size];
763 const uint8_t off0,
const uint8_t off1,
764 const uint8_t off2,
const uint8_t off3,
765 const uint8_t size_log2)
767 const int size = 1 << size_log2;
770 const pixel_t *
matrix = impl->priv.ptr;
781 if (
X) x[
i] += row0[
i];
782 if (
Y) y[
i] += row1[
i];
783 if (
Z) z[
i] += row2[
i];
784 if (
W)
w[
i] += row3[
i];
808 for (
int i = 0;
i < 4;
i++) {
809 for (
int j = 0; j < 4; j++)
827 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
831 const pixel_t xx = x[
i];
832 const pixel_t yy = y[
i];
833 const pixel_t zz = z[
i];
834 const pixel_t ww =
w[
i];
836#define LIN_VAL(I, J, val) \
837 ((one & SWS_MASK(I, J)) ? (val) : c.m[I][J] * (val))
839#define LIN_ROW(I, var) do { \
840 var[i] = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
841 if (!(zero & SWS_MASK(I, 0))) var[i] += LIN_VAL(I, 0, xx); \
842 if (!(zero & SWS_MASK(I, 1))) var[i] += LIN_VAL(I, 1, yy); \
843 if (!(zero & SWS_MASK(I, 2))) var[i] += LIN_VAL(I, 2, zz); \
844 if (!(zero & SWS_MASK(I, 3))) var[i] += LIN_VAL(I, 3, ww); \
874 return (vec3_t) { v.x, v.y, v.z };
877#define lerp(a, b, w) ((a) + (w) * ((pixel_t) (b) - (a)))
880vec3_t
fn(lerp3)(vec3_t
a, vec3_t
b, pixel_t
w)
890vec3_t
fn(lut3d_static)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
892 const int r_base = (int)
rgb.x;
893 const int g_base = (int)
rgb.y;
894 const int b_base = (int)
rgb.z;
899 pixel_t f0 =
rgb.x - r_base;
900 pixel_t f1 =
rgb.y - g_base;
901 pixel_t f2 =
rgb.z - b_base;
918 const pixel_t w0 = 1 - f0;
919 const pixel_t w1 = f0 - f1;
920 const pixel_t w2 = f1 - f2;
921 const pixel_t w3 = f2;
923 const v3u16_t *restrict
base = &lut3d->input[b_base][g_base][r_base];
924 const vec3_t v0 =
fn(vec3)(
base[0]);
925 const vec3_t v1 =
fn(vec3)(
base[off0]);
926 const vec3_t v2 =
fn(vec3)(
base[off0 + off1]);
927 const vec3_t v3 =
fn(vec3)(
base[off0 + off1 + off2]);
930 w0 * v0.x + w1 * v1.x + w2 * v2.x + w3 * v3.x,
931 w0 * v0.y + w1 * v1.y + w2 * v2.y + w3 * v3.y,
932 w0 * v0.z + w1 * v1.z + w2 * v2.z + w3 * v3.z,
937vec3_t
fn(lut3d_dynamic)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
942 const int Ix = (int)
rgb.x;
943 const pixel_t If =
rgb.x - Ix;
945 const v2u16_t a = lut3d->tone_map[Ix];
946 const v2u16_t b = lut3d->tone_map[Ix + 1];
948 const pixel_t k =
lerp(
a.y,
b.y, If);
949 const pixel_t
bias = (1 << 15) - k;
950 const pixel_t
scale = k / (pixel_t) (1 << 15);
962 const int lo0 = (int)
rgb.x;
963 const int lo1 = (int)
rgb.y;
964 const int lo2 = (int)
rgb.z;
970 const pixel_t w0 =
rgb.x - lo0;
971 const vec3_t c000 =
fn(vec3)(lut3d->output[lo2][lo1][lo0]);
972 const vec3_t c001 =
fn(vec3)(lut3d->output[lo2][lo1][hi0]);
973 const vec3_t c00 =
fn(lerp3)(c000, c001, w0);
974 const vec3_t c010 =
fn(vec3)(lut3d->output[lo2][hi1][lo0]);
975 const vec3_t c011 =
fn(vec3)(lut3d->output[lo2][hi1][hi0]);
976 const vec3_t c01 =
fn(lerp3)(c010, c011, w0);
977 const vec3_t c100 =
fn(vec3)(lut3d->output[hi2][lo1][lo0]);
978 const vec3_t c101 =
fn(vec3)(lut3d->output[hi2][lo1][hi0]);
979 const vec3_t c10 =
fn(lerp3)(c100, c101, w0);
980 const vec3_t c110 =
fn(vec3)(lut3d->output[hi2][hi1][lo0]);
981 const vec3_t c111 =
fn(vec3)(lut3d->output[hi2][hi1][hi0]);
982 const vec3_t c11 =
fn(lerp3)(c110, c111, w0);
984 const pixel_t w1 =
rgb.y - lo1;
985 const vec3_t c0 =
fn(lerp3)(c00, c01, w1);
986 const vec3_t
c1 =
fn(lerp3)(c10, c11, w1);
988 const pixel_t w2 =
rgb.z - lo2;
989 return fn(lerp3)(c0,
c1, w2);
994 const SwsLut3D *restrict lut3d = impl->priv.ptr;
998 vec3_t
c = { x[
i], y[
i], z[
i] };
999 c =
fn(lut3d_static)(lut3d,
c);
1001 c =
fn(lut3d_dynamic)(lut3d,
c);
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
SwsAArch64OpImplParams params
static double val(void *priv, double ch)
static double mz(int i, double w0, double r, double alpha)
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
static unsigned int BS_FUNC read_bit(BSCTX *bc)
Return one bit from the buffer.
#define i(width, name, range_min, range_max)
#define xs(width, name, var, subs,...)
static void permute(int16_t dst[64], const int16_t src[64], enum idct_permutation_type perm_type)
static int unpack(const uint8_t *src, const uint8_t *src_end, uint8_t *dst, int width, int height)
Unpack buffer.
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
static const int weights[]
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
static void scale(int *out, const int *in, const int w, const int h, const int shift)
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
static const uint16_t mask[17]
#define FFSWAP(type, a, b)
void * av_calloc(size_t nmemb, size_t size)
int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
static void ff_op_priv_unref(SwsOpPriv *priv)
static void ff_op_priv_free(SwsOpPriv *priv)
static double lerp(double a, double b, double x)
const void * av_refstruct_ref_c(const void *obj)
Analog of av_refstruct_ref(), but for constant objects.
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
const h264_weight_func weight
Represents a computed filter kernel.
Append a set of operations for applying a gamut/tone mapping 3D LUT to the pixels.
Copyright (C) 2026 Niklas Haas.
int32_t * in_offset_x
Pixel offset map; for horizontal scaling, in bytes.
union SwsUOp::@242237116251216327057105100216205033300341206345 data
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
uint32_t u32[SWS_BLOCK_SIZE]
float f32[SWS_BLOCK_SIZE]
uint16_t u16[SWS_BLOCK_SIZE]
int ff_sws_dither_height(const SwsDitherUOp *dither)
Computes (1 << size_log2) + MAX(y_offset).
#define SWS_COMP_ELEMS(N)
uint8_t SwsCompMask
Bit-mask of components.
#define SWS_FOR(TYPE, UOP, MACRO,...)
#define SWS_FOR_STRUCT(TYPE, UOP, MACRO,...)
#define DECL_CAST(DST, dst)
#define DECL_IMPL_WRITE(...)
#define DECL_WRITE(NAME,...)
#define DECL_IMPL_READ(...)
#define DECL_FUNC(NAME,...)
#define bump_ptr(ptr, bump)
#define DECL_IMPL(FUNC, NAME, TYPE, UOP,...)
#define SWS_BLOCK_SIZE
Copyright (C) 2026 Niklas Haas.
#define DECL_READ(NAME,...)
#define DECL_ENTRY(SETUP, NAME,...)
#define DECL_SETUP(NAME, PARAMS, OUT)
static const uint16_t dither[8][8]
static void copy(const float *p1, float *p2, const int length)
static int bias(int x, int c)
static int setup_linear(const SwsImplParams *params, SwsImplResult *out)
static int setup_filter_v(const SwsImplParams *params, SwsImplResult *out)
static int setup_dither(const SwsImplParams *params, SwsImplResult *out)
static int setup_filter_h(const SwsImplParams *params, SwsImplResult *out)