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
91 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
95 if (
X) x[
i] = in0[elems *
i + 0];
96 if (
Y) y[
i] = in0[elems *
i + 1];
97 if (
Z) z[
i] = in0[elems *
i + 2];
98 if (
W)
w[
i] = in0[elems *
i + 3];
109 if (
X) out0[
i] = x[
i];
110 if (
Y) out1[
i] = y[
i];
111 if (
Z) out2[
i] = z[
i];
112 if (
W) out3[
i] =
w[
i];
123 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
127 if (
X) out0[elems *
i + 0] = x[
i];
128 if (
Y) out0[elems *
i + 1] = y[
i];
129 if (
Z) out0[elems *
i + 2] = z[
i];
130 if (
W) out0[elems *
i + 3] =
w[
i];
144 const pixel_t
val = ((
const pixel_t *) in0)[
i >> 3];
145 x[
i + 0] = (
val >> 7) & 1;
146 x[
i + 1] = (
val >> 6) & 1;
147 x[
i + 2] = (
val >> 5) & 1;
148 x[
i + 3] = (
val >> 4) & 1;
149 x[
i + 4] = (
val >> 3) & 1;
150 x[
i + 5] = (
val >> 2) & 1;
151 x[
i + 6] = (
val >> 1) & 1;
152 x[
i + 7] = (
val >> 0) & 1;
165 const pixel_t
val = in0[
i >> 1];
167 x[
i + 1] =
val & 0xF;
180 const pixel_t
index = in0[
i];
198 out0[
i >> 3] = x[
i + 0] << 7 |
217 out0[
i >> 1] = x[
i] << 4 | x[
i + 1];
254 static_assert(
sizeof(
out->priv.ptr) <=
sizeof(
int32_t[2]),
255 ">8 byte pointers not supported");
262 for (
int i = 0;
i <
filter->num_weights;
i++)
276 const float *restrict
weights = impl->priv.ptr;
277 const int filter_size = impl->priv.i32[2];
278 weights += filter_size * iter->y;
281 if (
X) memset(&
xs.f32, 0,
sizeof(
xs.f32));
282 if (
Y) memset(&ys.
f32, 0,
sizeof(ys.
f32));
283 if (
Z) memset(&zs.
f32, 0,
sizeof(zs.
f32));
284 if (
W) memset(&ws.
f32, 0,
sizeof(ws.
f32));
286 for (
int j = 0; j < filter_size; j++) {
324 if (padded_w ==
filter->dst_size) {
344 const int *restrict
weights = impl->priv.ptr;
345 const int filter_size = impl->priv.i32[2];
347 const int xpos = iter->x;
348 weights += filter_size * iter->x;
358 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
359 for (
int j = 0; j < filter_size; j++) {
361 if (
X) sx += (inter_t) (
weight * start0[j]);
362 if (
Y) sy += (inter_t) (
weight * start1[j]);
363 if (
Z) sz += (inter_t) (
weight * start2[j]);
364 if (
W) sw += (inter_t) (
weight * start3[j]);
388 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
389 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
394 pixel_t *ptr[5] = {
NULL, x, y, z,
w };
395 for (
int n = 0; n < num_moves; n++)
396 ptr[
dst[n] + 1] = ptr[
src[n] + 1];
408 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
409 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
416 memcpy(&
data[1].px, x, block_size);
417 memcpy(&
data[2].px, y, block_size);
418 memcpy(&
data[3].px, z, block_size);
419 memcpy(&
data[4].px,
w, block_size);
421 for (
int n = 0; n < num_moves; n++)
424 memcpy(x, &
data[1].px, block_size);
425 memcpy(y, &
data[2].px, block_size);
426 memcpy(z, &
data[3].px, block_size);
427 memcpy(
w, &
data[4].px, block_size);
441#define DECL_CAST(DST, dst) \
442 DECL_FUNC(to_##dst, const SwsCompMask mask) \
444 block_t xx, yy, zz, ww; \
447 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
448 if (X) xx.dst[i] = x[i]; \
449 if (Y) yy.dst[i] = y[i]; \
450 if (Z) zz.dst[i] = z[i]; \
451 if (W) ww.dst[i] = w[i]; \
454 CONTINUE(&xx, &yy, &zz, &ww); \
457 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
458 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
474 if (
X) x[
i] <<= amount;
475 if (
Y) y[
i] <<= amount;
476 if (
Z) z[
i] <<= amount;
477 if (
W)
w[
i] <<= amount;
487 if (
X) x[
i] >>= amount;
488 if (
Y) y[
i] >>= amount;
489 if (
Z) z[
i] >>= amount;
490 if (
W)
w[
i] >>= amount;
508 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
509 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
510 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
511 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
543 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
544 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
545 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
558 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
559 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
560 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
561 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
581 const uint8_t bx,
const uint8_t by,
582 const uint8_t bz,
const uint8_t bw)
584 const uint8_t sx = bw + bz + by;
585 const uint8_t sy = bw + bz;
586 const uint8_t sz = bw;
587 const uint8_t sw = 0;
589 const pixel_t
mx = (1 << bx) - 1;
590 const pixel_t
my = (1 << by) - 1;
591 const pixel_t
mz = (1 << bz) - 1;
592 const pixel_t mw = (1 << bw) - 1;
596 const pixel_t
val = x[
i];
597 if (
X) x[
i] = (
val >> sx) &
mx;
598 if (
Y) y[
i] = (
val >> sy) &
my;
599 if (
Z) z[
i] = (
val >> sz) &
mz;
600 if (
W)
w[
i] = (
val >> sw) & mw;
607 const uint8_t bx,
const uint8_t by,
608 const uint8_t bz,
const uint8_t bw)
610 const uint8_t sx = bw + bz + by;
611 const uint8_t sy = bw + bz;
612 const uint8_t sz = bw;
613 const uint8_t sw = 0;
618 if (
X)
val |= x[
i] << sx;
619 if (
Y)
val |= y[
i] << sy;
620 if (
Z)
val |= z[
i] << sz;
642 #define ONE(N) SWS_COMP_TEST(one, N)
643 #define ZERO(N) SWS_COMP_TEST(zero, N)
670 const pixel_t
scale = impl->priv.px[0];
687 if (
X) x[
i] += impl->priv.px[0];
688 if (
Y) y[
i] += impl->priv.px[1];
689 if (
Z) z[
i] += impl->priv.px[2];
690 if (
W)
w[
i] += impl->priv.px[3];
700 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
701 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
702 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
713 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
714 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
715 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
758 for (
int y = 0; y <
height; y++) {
760 for (
int x = 0; x <
size; x++)
763 row[x] = row[x %
size];
770 const uint8_t off0,
const uint8_t off1,
771 const uint8_t off2,
const uint8_t off3,
772 const uint8_t size_log2)
774 const int size = 1 << size_log2;
777 const pixel_t *
matrix = impl->priv.ptr;
788 if (
X) x[
i] += row0[
i];
789 if (
Y) y[
i] += row1[
i];
790 if (
Z) z[
i] += row2[
i];
791 if (
W)
w[
i] += row3[
i];
815 for (
int i = 0;
i < 4;
i++) {
816 for (
int j = 0; j < 4; j++)
834 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
838 const pixel_t xx = x[
i];
839 const pixel_t yy = y[
i];
840 const pixel_t zz = z[
i];
841 const pixel_t ww =
w[
i];
843#define LIN_VAL(I, J, val) \
844 ((one & SWS_MASK(I, J)) ? (val) : (pixel_t) ((uinter_t) c.m[I][J] * (val)))
846#define LIN_ROW(I, var) do { \
847 pixel_t tmp = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
848 if (!(zero & SWS_MASK(I, 0))) tmp += LIN_VAL(I, 0, xx); \
849 if (!(zero & SWS_MASK(I, 1))) tmp += LIN_VAL(I, 1, yy); \
850 if (!(zero & SWS_MASK(I, 2))) tmp += LIN_VAL(I, 2, zz); \
851 if (!(zero & SWS_MASK(I, 3))) tmp += LIN_VAL(I, 3, ww); \
882 return (vec3_t) { v.x, v.y, v.z };
885#define lerp(a, b, w) ((pixel_t) ((a) + (pixel_t) ((w) * (pixel_t) ((pixel_t) (b) - (a)))))
888pixel_t
fn(sum4)(pixel_t w0, pixel_t
a, pixel_t w1, pixel_t
b,
889 pixel_t w2, pixel_t
c, pixel_t w3, pixel_t d)
891 pixel_t sum = (pixel_t) (w0 *
a);
892 sum += (pixel_t) (w1 *
b);
893 sum += (pixel_t) (w2 *
c);
894 sum += (pixel_t) (w3 * d);
899vec3_t
fn(lerp3)(vec3_t
a, vec3_t
b, pixel_t
w)
909vec3_t
fn(lut3d_static)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
911 const int r_base = (int)
rgb.x;
912 const int g_base = (int)
rgb.y;
913 const int b_base = (int)
rgb.z;
918 pixel_t f0 =
rgb.x - r_base;
919 pixel_t f1 =
rgb.y - g_base;
920 pixel_t f2 =
rgb.z - b_base;
937 const pixel_t w0 = 1 - f0;
938 const pixel_t w1 = f0 - f1;
939 const pixel_t w2 = f1 - f2;
940 const pixel_t w3 = f2;
942 const v3u16_t *restrict
base = &lut3d->input[b_base][g_base][r_base];
943 const vec3_t v0 =
fn(vec3)(
base[0]);
944 const vec3_t v1 =
fn(vec3)(
base[off0]);
945 const vec3_t v2 =
fn(vec3)(
base[off0 + off1]);
946 const vec3_t v3 =
fn(vec3)(
base[off0 + off1 + off2]);
949 fn(sum4)(w0, v0.x, w1, v1.x, w2, v2.x, w3, v3.x),
950 fn(sum4)(w0, v0.y, w1, v1.y, w2, v2.y, w3, v3.y),
951 fn(sum4)(w0, v0.z, w1, v1.z, w2, v2.z, w3, v3.z),
956vec3_t
fn(lut3d_dynamic)(
const SwsLut3D *restrict lut3d, vec3_t
rgb)
961 const int Ix = (int)
rgb.x;
962 const pixel_t If =
rgb.x - Ix;
964 const v2u16_t a = lut3d->tone_map[Ix];
965 const v2u16_t b = lut3d->tone_map[Ix + 1];
967 const pixel_t k =
lerp(
a.y,
b.y, If);
968 const pixel_t
bias = (1 << 15) - k;
969 const pixel_t
scale = k / (pixel_t) (1 << 15);
981 const int lo0 = (int)
rgb.x;
982 const int lo1 = (int)
rgb.y;
983 const int lo2 = (int)
rgb.z;
989 const pixel_t w0 =
rgb.x - lo0;
990 const vec3_t c000 =
fn(vec3)(lut3d->output[lo2][lo1][lo0]);
991 const vec3_t c001 =
fn(vec3)(lut3d->output[lo2][lo1][hi0]);
992 const vec3_t c00 =
fn(lerp3)(c000, c001, w0);
993 const vec3_t c010 =
fn(vec3)(lut3d->output[lo2][hi1][lo0]);
994 const vec3_t c011 =
fn(vec3)(lut3d->output[lo2][hi1][hi0]);
995 const vec3_t c01 =
fn(lerp3)(c010, c011, w0);
996 const vec3_t c100 =
fn(vec3)(lut3d->output[hi2][lo1][lo0]);
997 const vec3_t c101 =
fn(vec3)(lut3d->output[hi2][lo1][hi0]);
998 const vec3_t c10 =
fn(lerp3)(c100, c101, w0);
999 const vec3_t c110 =
fn(vec3)(lut3d->output[hi2][hi1][lo0]);
1000 const vec3_t c111 =
fn(vec3)(lut3d->output[hi2][hi1][hi0]);
1001 const vec3_t c11 =
fn(lerp3)(c110, c111, w0);
1003 const pixel_t w1 =
rgb.y - lo1;
1004 const vec3_t c0 =
fn(lerp3)(c00, c01, w1);
1005 const vec3_t
c1 =
fn(lerp3)(c10, c11, w1);
1007 const pixel_t w2 =
rgb.z - lo2;
1008 return fn(lerp3)(c0,
c1, w2);
1013 const SwsLut3D *restrict lut3d = impl->priv.ptr;
1017 vec3_t
c = { x[
i], y[
i], z[
i] };
1018 c =
fn(lut3d_static)(lut3d,
c);
1020 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 av_always_inline void scale(vec_s32 res[4], vec_s16 res_packed[2], const int shift)
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
@ 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.
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)