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++) {
321 const int *restrict
weights = impl->priv.ptr;
322 const int filter_size = impl->priv.i32[2];
324 const int xpos = iter->x;
325 weights += filter_size * iter->x;
335 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
336 for (
int j = 0; j < filter_size; j++) {
338 if (
X) sx +=
weight * start0[j];
339 if (
Y) sy +=
weight * start1[j];
340 if (
Z) sz +=
weight * start2[j];
341 if (
W) sw +=
weight * start3[j];
365 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
366 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
371 pixel_t *ptr[5] = {
NULL, x, y, z,
w };
372 for (
int n = 0; n < num_moves; n++)
373 ptr[
dst[n] + 1] = ptr[
src[n] + 1];
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)
393 memcpy(&
data[1].px, x, block_size);
394 memcpy(&
data[2].px, y, block_size);
395 memcpy(&
data[3].px, z, block_size);
396 memcpy(&
data[4].px,
w, block_size);
398 for (
int n = 0; n < num_moves; n++)
401 memcpy(x, &
data[1].px, block_size);
402 memcpy(y, &
data[2].px, block_size);
403 memcpy(z, &
data[3].px, block_size);
404 memcpy(
w, &
data[4].px, block_size);
418#define DECL_CAST(DST, dst) \
419 DECL_FUNC(to_##dst, const SwsCompMask mask) \
421 block_t xx, yy, zz, ww; \
424 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
425 if (X) xx.dst[i] = x[i]; \
426 if (Y) yy.dst[i] = y[i]; \
427 if (Z) zz.dst[i] = z[i]; \
428 if (W) ww.dst[i] = w[i]; \
431 CONTINUE(&xx, &yy, &zz, &ww); \
434 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
435 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
451 if (
X) x[
i] <<= amount;
452 if (
Y) y[
i] <<= amount;
453 if (
Z) z[
i] <<= amount;
454 if (
W)
w[
i] <<= amount;
464 if (
X) x[
i] >>= amount;
465 if (
Y) y[
i] >>= amount;
466 if (
Z) z[
i] >>= amount;
467 if (
W)
w[
i] >>= amount;
485 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
486 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
487 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
488 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
520 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
521 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
522 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
535 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
536 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
537 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
538 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
558 const uint8_t bx,
const uint8_t by,
559 const uint8_t bz,
const uint8_t bw)
561 const uint8_t sx = bw + bz + by;
562 const uint8_t sy = bw + bz;
563 const uint8_t sz = bw;
564 const uint8_t sw = 0;
566 const pixel_t
mx = (1 << bx) - 1;
567 const pixel_t
my = (1 << by) - 1;
568 const pixel_t
mz = (1 << bz) - 1;
569 const pixel_t mw = (1 << bw) - 1;
573 const pixel_t
val = x[
i];
574 if (
X) x[
i] = (
val >> sx) &
mx;
575 if (
Y) y[
i] = (
val >> sy) &
my;
576 if (
Z) z[
i] = (
val >> sz) &
mz;
577 if (
W)
w[
i] = (
val >> sw) & mw;
584 const uint8_t bx,
const uint8_t by,
585 const uint8_t bz,
const uint8_t bw)
587 const uint8_t sx = bw + bz + by;
588 const uint8_t sy = bw + bz;
589 const uint8_t sz = bw;
590 const uint8_t sw = 0;
595 if (
X)
val |= x[
i] << sx;
596 if (
Y)
val |= y[
i] << sy;
597 if (
Z)
val |= z[
i] << sz;
619 #define ONE(N) SWS_COMP_TEST(one, N)
620 #define ZERO(N) SWS_COMP_TEST(zero, N)
647 const pixel_t
scale = impl->priv.px[0];
664 if (
X) x[
i] += impl->priv.px[0];
665 if (
Y) y[
i] += impl->priv.px[1];
666 if (
Z) z[
i] += impl->priv.px[2];
667 if (
W)
w[
i] += impl->priv.px[3];
677 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
678 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
679 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
690 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
691 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
692 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
735 for (
int y = 0; y <
height; y++) {
737 for (
int x = 0; x <
size; x++)
740 row[x] = row[x %
size];
747 const uint8_t off0,
const uint8_t off1,
748 const uint8_t off2,
const uint8_t off3,
749 const uint8_t size_log2)
751 const int size = 1 << size_log2;
754 const pixel_t *
matrix = impl->priv.ptr;
765 if (
X) x[
i] += row0[
i];
766 if (
Y) y[
i] += row1[
i];
767 if (
Z) z[
i] += row2[
i];
768 if (
W)
w[
i] += row3[
i];
792 for (
int i = 0;
i < 4;
i++) {
793 for (
int j = 0; j < 4; j++)
811 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
815 const pixel_t xx = x[
i];
816 const pixel_t yy = y[
i];
817 const pixel_t zz = z[
i];
818 const pixel_t ww =
w[
i];
820#define LIN_VAL(I, J, val) \
821 ((one & SWS_MASK(I, J)) ? (val) : c.m[I][J] * (val))
823#define LIN_ROW(I, var) do { \
824 var[i] = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
825 if (!(zero & SWS_MASK(I, 0))) var[i] += LIN_VAL(I, 0, xx); \
826 if (!(zero & SWS_MASK(I, 1))) var[i] += LIN_VAL(I, 1, yy); \
827 if (!(zero & SWS_MASK(I, 2))) var[i] += LIN_VAL(I, 2, zz); \
828 if (!(zero & SWS_MASK(I, 3))) var[i] += LIN_VAL(I, 3, ww); \
858 return (vec3_t) { v.x, v.y, v.z };
861#define lerp(a, b, w) ((a) + (w) * ((pixel_t) (b) - (a)))
864vec3_t
fn(lerp3)(vec3_t
a, vec3_t
b, pixel_t
w)
874vec3_t
fn(lut3d_static)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
876 const int r_base = (int)
rgb.x;
877 const int g_base = (int)
rgb.y;
878 const int b_base = (int)
rgb.z;
883 pixel_t f0 =
rgb.x - r_base;
884 pixel_t f1 =
rgb.y - g_base;
885 pixel_t f2 =
rgb.z - b_base;
902 const pixel_t w0 = 1 - f0;
903 const pixel_t w1 = f0 - f1;
904 const pixel_t w2 = f1 - f2;
905 const pixel_t w3 = f2;
907 const v3u16_t *restrict
base = &lut3d->input[b_base][g_base][r_base];
908 const vec3_t v0 =
fn(vec3)(
base[0]);
909 const vec3_t v1 =
fn(vec3)(
base[off0]);
910 const vec3_t v2 =
fn(vec3)(
base[off0 + off1]);
911 const vec3_t v3 =
fn(vec3)(
base[off0 + off1 + off2]);
914 w0 * v0.x + w1 * v1.x + w2 * v2.x + w3 * v3.x,
915 w0 * v0.y + w1 * v1.y + w2 * v2.y + w3 * v3.y,
916 w0 * v0.z + w1 * v1.z + w2 * v2.z + w3 * v3.z,
921vec3_t
fn(lut3d_dynamic)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
926 const int Ix = (int)
rgb.x;
927 const pixel_t If =
rgb.x - Ix;
929 const v2u16_t a = lut3d->tone_map[Ix];
930 const v2u16_t b = lut3d->tone_map[Ix + 1];
932 const pixel_t k =
lerp(
a.y,
b.y, If);
933 const pixel_t
bias = (1 << 15) - k;
934 const pixel_t
scale = k / (pixel_t) (1 << 15);
946 const int lo0 = (int)
rgb.x;
947 const int lo1 = (int)
rgb.y;
948 const int lo2 = (int)
rgb.z;
954 const pixel_t w0 =
rgb.x - lo0;
955 const vec3_t c000 =
fn(vec3)(lut3d->output[lo2][lo1][lo0]);
956 const vec3_t c001 =
fn(vec3)(lut3d->output[lo2][lo1][hi0]);
957 const vec3_t c00 =
fn(lerp3)(c000, c001, w0);
958 const vec3_t c010 =
fn(vec3)(lut3d->output[lo2][hi1][lo0]);
959 const vec3_t c011 =
fn(vec3)(lut3d->output[lo2][hi1][hi0]);
960 const vec3_t c01 =
fn(lerp3)(c010, c011, w0);
961 const vec3_t c100 =
fn(vec3)(lut3d->output[hi2][lo1][lo0]);
962 const vec3_t c101 =
fn(vec3)(lut3d->output[hi2][lo1][hi0]);
963 const vec3_t c10 =
fn(lerp3)(c100, c101, w0);
964 const vec3_t c110 =
fn(vec3)(lut3d->output[hi2][hi1][lo0]);
965 const vec3_t c111 =
fn(vec3)(lut3d->output[hi2][hi1][hi0]);
966 const vec3_t c11 =
fn(lerp3)(c110, c111, w0);
968 const pixel_t w1 =
rgb.y - lo1;
969 const vec3_t c0 =
fn(lerp3)(c00, c01, w1);
970 const vec3_t
c1 =
fn(lerp3)(c10, c11, w1);
972 const pixel_t w2 =
rgb.z - lo2;
973 return fn(lerp3)(c0,
c1, w2);
978 const SwsLut3D *restrict lut3d = impl->priv.ptr;
982 vec3_t
c = { x[
i], y[
i], z[
i] };
983 c =
fn(lut3d_static)(lut3d,
c);
985 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)