29#if IS_FLOAT && BIT_DEPTH == 32
30# define PIXEL_TYPE SWS_PIXEL_F32
33# define uinter_t float
34# define vec3_t v3f32_t
38# define PIXEL_MAX 0xFFFFFFFFu
39# define PIXEL_SWAP av_bswap32
40# define pixel_t uint32_t
41# define inter_t int64_t
42# define uinter_t uint64_t
46# define PIXEL_MAX 0xFFFFu
47# define PIXEL_SWAP av_bswap16
48# define pixel_t uint16_t
49# define inter_t int64_t
50# define uinter_t uint64_t
54# define PIXEL_MAX 0xFFu
55# define pixel_t uint8_t
56# define inter_t int32_t
57# define uinter_t uint32_t
61# error Invalid BIT_DEPTH
88 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
92 if (
X) x[
i] = in0[elems *
i + 0];
93 if (
Y) y[
i] = in0[elems *
i + 1];
94 if (
Z) z[
i] = in0[elems *
i + 2];
95 if (
W)
w[
i] = in0[elems *
i + 3];
106 if (
X) out0[
i] = x[
i];
107 if (
Y) out1[
i] = y[
i];
108 if (
Z) out2[
i] = z[
i];
109 if (
W) out3[
i] =
w[
i];
120 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
124 if (
X) out0[elems *
i + 0] = x[
i];
125 if (
Y) out0[elems *
i + 1] = y[
i];
126 if (
Z) out0[elems *
i + 2] = z[
i];
127 if (
W) out0[elems *
i + 3] =
w[
i];
141 const pixel_t
val = ((
const pixel_t *) in0)[
i >> 3];
142 x[
i + 0] = (
val >> 7) & 1;
143 x[
i + 1] = (
val >> 6) & 1;
144 x[
i + 2] = (
val >> 5) & 1;
145 x[
i + 3] = (
val >> 4) & 1;
146 x[
i + 4] = (
val >> 3) & 1;
147 x[
i + 5] = (
val >> 2) & 1;
148 x[
i + 6] = (
val >> 1) & 1;
149 x[
i + 7] = (
val >> 0) & 1;
162 const pixel_t
val = in0[
i >> 1];
164 x[
i + 1] =
val & 0xF;
177 const pixel_t
index = in0[
i];
195 out0[
i >> 3] = x[
i + 0] << 7 |
214 out0[
i >> 1] = x[
i] << 4 | x[
i + 1];
251 static_assert(
sizeof(
out->priv.ptr) <=
sizeof(
int32_t[2]),
252 ">8 byte pointers not supported");
259 for (
int i = 0;
i <
filter->num_weights;
i++)
273 const float *restrict
weights = impl->priv.ptr;
274 const int filter_size = impl->priv.i32[2];
275 weights += filter_size * iter->y;
278 if (
X) memset(&
xs.f32, 0,
sizeof(
xs.f32));
279 if (
Y) memset(&ys.
f32, 0,
sizeof(ys.
f32));
280 if (
Z) memset(&zs.
f32, 0,
sizeof(zs.
f32));
281 if (
W) memset(&ws.
f32, 0,
sizeof(ws.
f32));
283 for (
int j = 0; j < filter_size; j++) {
321 if (padded_w ==
filter->dst_size) {
341 const int *restrict
weights = impl->priv.ptr;
342 const int filter_size = impl->priv.i32[2];
344 const int xpos = iter->x;
345 weights += filter_size * iter->x;
355 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
356 for (
int j = 0; j < filter_size; j++) {
358 if (
X) sx +=
weight * start0[j];
359 if (
Y) sy +=
weight * start1[j];
360 if (
Z) sz +=
weight * start2[j];
361 if (
W) sw +=
weight * start3[j];
385 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
386 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
391 pixel_t *ptr[5] = {
NULL, x, y, z,
w };
392 for (
int n = 0; n < num_moves; n++)
393 ptr[
dst[n] + 1] = ptr[
src[n] + 1];
405 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
406 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
413 memcpy(&
data[1].px, x, block_size);
414 memcpy(&
data[2].px, y, block_size);
415 memcpy(&
data[3].px, z, block_size);
416 memcpy(&
data[4].px,
w, block_size);
418 for (
int n = 0; n < num_moves; n++)
421 memcpy(x, &
data[1].px, block_size);
422 memcpy(y, &
data[2].px, block_size);
423 memcpy(z, &
data[3].px, block_size);
424 memcpy(
w, &
data[4].px, block_size);
438#define DECL_CAST(DST, dst) \
439 DECL_FUNC(to_##dst, const SwsCompMask mask) \
441 block_t xx, yy, zz, ww; \
444 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
445 if (X) xx.dst[i] = x[i]; \
446 if (Y) yy.dst[i] = y[i]; \
447 if (Z) zz.dst[i] = z[i]; \
448 if (W) ww.dst[i] = w[i]; \
451 CONTINUE(&xx, &yy, &zz, &ww); \
454 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
455 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
471 if (
X) x[
i] <<= amount;
472 if (
Y) y[
i] <<= amount;
473 if (
Z) z[
i] <<= amount;
474 if (
W)
w[
i] <<= amount;
484 if (
X) x[
i] >>= amount;
485 if (
Y) y[
i] >>= amount;
486 if (
Z) z[
i] >>= amount;
487 if (
W)
w[
i] >>= amount;
505 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
506 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
507 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
508 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
540 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
541 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
542 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
555 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
556 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
557 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
558 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
578 const uint8_t bx,
const uint8_t by,
579 const uint8_t bz,
const uint8_t bw)
581 const uint8_t sx = bw + bz + by;
582 const uint8_t sy = bw + bz;
583 const uint8_t sz = bw;
584 const uint8_t sw = 0;
586 const pixel_t
mx = (1 << bx) - 1;
587 const pixel_t
my = (1 << by) - 1;
588 const pixel_t
mz = (1 << bz) - 1;
589 const pixel_t mw = (1 << bw) - 1;
593 const pixel_t
val = x[
i];
594 if (
X) x[
i] = (
val >> sx) &
mx;
595 if (
Y) y[
i] = (
val >> sy) &
my;
596 if (
Z) z[
i] = (
val >> sz) &
mz;
597 if (
W)
w[
i] = (
val >> sw) & mw;
604 const uint8_t bx,
const uint8_t by,
605 const uint8_t bz,
const uint8_t bw)
607 const uint8_t sx = bw + bz + by;
608 const uint8_t sy = bw + bz;
609 const uint8_t sz = bw;
610 const uint8_t sw = 0;
615 if (
X)
val |= x[
i] << sx;
616 if (
Y)
val |= y[
i] << sy;
617 if (
Z)
val |= z[
i] << sz;
639 #define ONE(N) SWS_COMP_TEST(one, N)
640 #define ZERO(N) SWS_COMP_TEST(zero, N)
667 const pixel_t
scale = impl->priv.px[0];
684 if (
X) x[
i] += impl->priv.px[0];
685 if (
Y) y[
i] += impl->priv.px[1];
686 if (
Z) z[
i] += impl->priv.px[2];
687 if (
W)
w[
i] += impl->priv.px[3];
697 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
698 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
699 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
710 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
711 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
712 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
755 for (
int y = 0; y <
height; y++) {
757 for (
int x = 0; x <
size; x++)
760 row[x] = row[x %
size];
767 const uint8_t off0,
const uint8_t off1,
768 const uint8_t off2,
const uint8_t off3,
769 const uint8_t size_log2)
771 const int size = 1 << size_log2;
774 const pixel_t *
matrix = impl->priv.ptr;
785 if (
X) x[
i] += row0[
i];
786 if (
Y) y[
i] += row1[
i];
787 if (
Z) z[
i] += row2[
i];
788 if (
W)
w[
i] += row3[
i];
812 for (
int i = 0;
i < 4;
i++) {
813 for (
int j = 0; j < 4; j++)
831 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
835 const pixel_t xx = x[
i];
836 const pixel_t yy = y[
i];
837 const pixel_t zz = z[
i];
838 const pixel_t ww =
w[
i];
840#define LIN_VAL(I, J, val) \
841 ((one & SWS_MASK(I, J)) ? (val) : (uinter_t) c.m[I][J] * (val))
843#define LIN_ROW(I, var) do { \
844 pixel_t tmp = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
845 if (!(zero & SWS_MASK(I, 0))) tmp += LIN_VAL(I, 0, xx); \
846 if (!(zero & SWS_MASK(I, 1))) tmp += LIN_VAL(I, 1, yy); \
847 if (!(zero & SWS_MASK(I, 2))) tmp += LIN_VAL(I, 2, zz); \
848 if (!(zero & SWS_MASK(I, 3))) tmp += LIN_VAL(I, 3, ww); \
879 return (vec3_t) { v.x, v.y, v.z };
882#define lerp(a, b, w) ((a) + (w) * ((pixel_t) (b) - (a)))
885vec3_t
fn(lerp3)(vec3_t
a, vec3_t
b, pixel_t
w)
895vec3_t
fn(lut3d_static)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
897 const int r_base = (int)
rgb.x;
898 const int g_base = (int)
rgb.y;
899 const int b_base = (int)
rgb.z;
904 pixel_t f0 =
rgb.x - r_base;
905 pixel_t f1 =
rgb.y - g_base;
906 pixel_t f2 =
rgb.z - b_base;
923 const pixel_t w0 = 1 - f0;
924 const pixel_t w1 = f0 - f1;
925 const pixel_t w2 = f1 - f2;
926 const pixel_t w3 = f2;
928 const v3u16_t *restrict
base = &lut3d->input[b_base][g_base][r_base];
929 const vec3_t v0 =
fn(vec3)(
base[0]);
930 const vec3_t v1 =
fn(vec3)(
base[off0]);
931 const vec3_t v2 =
fn(vec3)(
base[off0 + off1]);
932 const vec3_t v3 =
fn(vec3)(
base[off0 + off1 + off2]);
935 w0 * v0.x + w1 * v1.x + w2 * v2.x + w3 * v3.x,
936 w0 * v0.y + w1 * v1.y + w2 * v2.y + w3 * v3.y,
937 w0 * v0.z + w1 * v1.z + w2 * v2.z + w3 * v3.z,
942vec3_t
fn(lut3d_dynamic)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
947 const int Ix = (int)
rgb.x;
948 const pixel_t If =
rgb.x - Ix;
950 const v2u16_t a = lut3d->tone_map[Ix];
951 const v2u16_t b = lut3d->tone_map[Ix + 1];
953 const pixel_t k =
lerp(
a.y,
b.y, If);
954 const pixel_t
bias = (1 << 15) - k;
955 const pixel_t
scale = k / (pixel_t) (1 << 15);
967 const int lo0 = (int)
rgb.x;
968 const int lo1 = (int)
rgb.y;
969 const int lo2 = (int)
rgb.z;
975 const pixel_t w0 =
rgb.x - lo0;
976 const vec3_t c000 =
fn(vec3)(lut3d->output[lo2][lo1][lo0]);
977 const vec3_t c001 =
fn(vec3)(lut3d->output[lo2][lo1][hi0]);
978 const vec3_t c00 =
fn(lerp3)(c000, c001, w0);
979 const vec3_t c010 =
fn(vec3)(lut3d->output[lo2][hi1][lo0]);
980 const vec3_t c011 =
fn(vec3)(lut3d->output[lo2][hi1][hi0]);
981 const vec3_t c01 =
fn(lerp3)(c010, c011, w0);
982 const vec3_t c100 =
fn(vec3)(lut3d->output[hi2][lo1][lo0]);
983 const vec3_t c101 =
fn(vec3)(lut3d->output[hi2][lo1][hi0]);
984 const vec3_t c10 =
fn(lerp3)(c100, c101, w0);
985 const vec3_t c110 =
fn(vec3)(lut3d->output[hi2][hi1][lo0]);
986 const vec3_t c111 =
fn(vec3)(lut3d->output[hi2][hi1][hi0]);
987 const vec3_t c11 =
fn(lerp3)(c110, c111, w0);
989 const pixel_t w1 =
rgb.y - lo1;
990 const vec3_t c0 =
fn(lerp3)(c00, c01, w1);
991 const vec3_t
c1 =
fn(lerp3)(c10, c11, w1);
993 const pixel_t w2 =
rgb.z - lo2;
994 return fn(lerp3)(c0,
c1, w2);
999 const SwsLut3D *restrict lut3d = impl->priv.ptr;
1003 vec3_t
c = { x[
i], y[
i], z[
i] };
1004 c =
fn(lut3d_static)(lut3d,
c);
1006 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)