Go to the documentation of this file.
29 #if IS_FLOAT && BIT_DEPTH == 32
30 # define PIXEL_TYPE SWS_PIXEL_F32
31 # define pixel_t float
32 # define inter_t float
36 # define PIXEL_MAX 0xFFFFFFFFu
37 # define PIXEL_SWAP av_bswap32
38 # define pixel_t uint32_t
39 # define inter_t int64_t
43 # define PIXEL_MAX 0xFFFFu
44 # define PIXEL_SWAP av_bswap16
45 # define pixel_t uint16_t
46 # define inter_t int64_t
50 # define PIXEL_MAX 0xFFu
51 # define pixel_t uint8_t
52 # define inter_t int32_t
56 # error Invalid BIT_DEPTH
83 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
87 if (
X) x[
i] = in0[elems *
i + 0];
88 if (
Y) y[
i] = in0[elems *
i + 1];
89 if (
Z) z[
i] = in0[elems *
i + 2];
90 if (
W)
w[
i] = in0[elems *
i + 3];
101 if (
X) out0[
i] = x[
i];
102 if (
Y) out1[
i] = y[
i];
103 if (
Z) out2[
i] = z[
i];
104 if (
W) out3[
i] =
w[
i];
115 const int elems =
W ? 4 :
Z ? 3 :
Y ? 2 : 1;
119 if (
X) out0[elems *
i + 0] = x[
i];
120 if (
Y) out0[elems *
i + 1] = y[
i];
121 if (
Z) out0[elems *
i + 2] = z[
i];
122 if (
W) out0[elems *
i + 3] =
w[
i];
137 x[
i + 0] = (
val >> 7) & 1;
138 x[
i + 1] = (
val >> 6) & 1;
139 x[
i + 2] = (
val >> 5) & 1;
140 x[
i + 3] = (
val >> 4) & 1;
141 x[
i + 4] = (
val >> 3) & 1;
142 x[
i + 5] = (
val >> 2) & 1;
143 x[
i + 6] = (
val >> 1) & 1;
144 x[
i + 7] = (
val >> 0) & 1;
159 x[
i + 1] =
val & 0xF;
172 out0[
i >> 3] = x[
i + 0] << 7 |
191 out0[
i >> 1] = x[
i] << 4 | x[
i + 1];
226 static_assert(
sizeof(
out->priv.ptr) <=
sizeof(
int32_t[2]),
227 ">8 byte pointers not supported");
234 for (
int i = 0;
i <
filter->num_weights;
i++)
248 const float *restrict
weights = impl->priv.ptr;
249 const int filter_size = impl->priv.i32[2];
250 weights += filter_size * iter->y;
253 if (
X) memset(&
xs.f32, 0,
sizeof(
xs.f32));
254 if (
Y) memset(&ys.
f32, 0,
sizeof(ys.
f32));
255 if (
Z) memset(&zs.
f32, 0,
sizeof(zs.
f32));
256 if (
W) memset(&ws.
f32, 0,
sizeof(ws.
f32));
258 for (
int j = 0; j < filter_size; j++) {
300 const int *restrict
weights = impl->priv.ptr;
301 const int filter_size = impl->priv.i32[2];
303 const int xpos = iter->x;
304 weights += filter_size * iter->x;
314 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
315 for (
int j = 0; j < filter_size; j++) {
317 if (
X) sx +=
weight * start0[j];
318 if (
Y) sy +=
weight * start1[j];
319 if (
Z) sz +=
weight * start2[j];
320 if (
W) sw +=
weight * start3[j];
344 #define DECL_PERMUTE(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3) \
345 static void NAME##_c(SwsOpIter *restrict iter, \
346 const SwsOpImpl *restrict impl, \
347 void *restrict in0, void *restrict in1, \
348 void *restrict in2, void *restrict in3) \
350 CONTINUE(in##IDX0, in##IDX1, in##IDX2, in##IDX3); \
353 #define DECL_COPY(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3) \
354 static void NAME##_c(SwsOpIter *restrict iter, \
355 const SwsOpImpl *restrict impl, \
356 void *restrict in0, void *restrict in1, \
357 void *restrict in2, void *restrict in3) \
359 const SwsCompMask mask = (MASK); \
360 block_t x, y, z, w; \
362 if (X) memcpy(&x.px, in##IDX0, SIZEOF_BLOCK); \
363 if (Y) memcpy(&y.px, in##IDX1, SIZEOF_BLOCK); \
364 if (Z) memcpy(&z.px, in##IDX2, SIZEOF_BLOCK); \
365 if (W) memcpy(&w.px, in##IDX3, SIZEOF_BLOCK); \
367 CONTINUE(X ? &x : in0, Y ? &y : in1, Z ? &z : in2, W ? &w : in3); \
379 #define DECL_CAST(DST, dst) \
380 DECL_FUNC(to_##dst, const SwsCompMask mask) \
382 block_t xx, yy, zz, ww; \
385 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
386 if (X) xx.dst[i] = x[i]; \
387 if (Y) yy.dst[i] = y[i]; \
388 if (Z) zz.dst[i] = z[i]; \
389 if (W) ww.dst[i] = w[i]; \
392 CONTINUE(&xx, &yy, &zz, &ww); \
395 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
396 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
412 if (
X) x[
i] <<= amount;
413 if (
Y) y[
i] <<= amount;
414 if (
Z) z[
i] <<= amount;
415 if (
W)
w[
i] <<= amount;
425 if (
X) x[
i] >>= amount;
426 if (
Y) y[
i] >>= amount;
427 if (
Z) z[
i] >>= amount;
428 if (
W)
w[
i] >>= amount;
446 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
447 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
448 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
449 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
481 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
482 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
483 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
496 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
497 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
498 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
499 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
519 const uint8_t bx,
const uint8_t by,
520 const uint8_t bz,
const uint8_t bw)
522 const uint8_t sx = bw + bz + by;
523 const uint8_t sy = bw + bz;
524 const uint8_t sz = bw;
525 const uint8_t sw = 0;
530 const pixel_t mw = (1 << bw) - 1;
535 if (
X) x[
i] = (
val >> sx) &
mx;
536 if (
Y) y[
i] = (
val >> sy) &
my;
537 if (
Z) z[
i] = (
val >> sz) &
mz;
538 if (
W)
w[
i] = (
val >> sw) & mw;
545 const uint8_t bx,
const uint8_t by,
546 const uint8_t bz,
const uint8_t bw)
548 const uint8_t sx = bw + bz + by;
549 const uint8_t sy = bw + bz;
550 const uint8_t sz = bw;
551 const uint8_t sw = 0;
556 if (
X)
val |= x[
i] << sx;
557 if (
Y)
val |= y[
i] << sy;
558 if (
Z)
val |= z[
i] << sz;
580 #define ONE(N) SWS_COMP_TEST(one, N)
581 #define ZERO(N) SWS_COMP_TEST(zero, N)
625 if (
X) x[
i] += impl->priv.px[0];
626 if (
Y) y[
i] += impl->priv.px[1];
627 if (
Z) z[
i] += impl->priv.px[2];
628 if (
W)
w[
i] += impl->priv.px[3];
638 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
639 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
640 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
651 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
652 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
653 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
696 for (
int y = 0; y <
height; y++) {
698 for (
int x = 0; x <
size; x++)
701 row[x] = row[x %
size];
708 const uint8_t off0,
const uint8_t off1,
709 const uint8_t off2,
const uint8_t off3,
710 const uint8_t size_log2)
712 const int size = 1 << size_log2;
726 if (
X) x[
i] += row0[
i];
727 if (
Y) y[
i] += row1[
i];
728 if (
Z) z[
i] += row2[
i];
729 if (
W)
w[
i] += row3[
i];
753 for (
int i = 0;
i < 4;
i++) {
754 for (
int j = 0; j < 4; j++)
772 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
781 #define LIN_VAL(I, J, val) \
782 ((one & SWS_MASK(I, J)) ? (val) : c.m[I][J] * (val))
784 #define LIN_ROW(I, var) do { \
785 var[i] = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
786 if (!(zero & SWS_MASK(I, 0))) var[i] += LIN_VAL(I, 0, xx); \
787 if (!(zero & SWS_MASK(I, 1))) var[i] += LIN_VAL(I, 1, yy); \
788 if (!(zero & SWS_MASK(I, 2))) var[i] += LIN_VAL(I, 2, zz); \
789 if (!(zero & SWS_MASK(I, 3))) var[i] += LIN_VAL(I, 3, ww); \
#define DECL_IMPL_WRITE(...)
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
float f32[SWS_BLOCK_SIZE]
#define DECL_ENTRY(SETUP, NAME,...)
Represents a computed filter kernel.
#define DECL_COPY(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3)
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
void(* filter)(uint8_t *src, int stride, int qscale)
static void ff_op_priv_unref(SwsOpPriv *priv)
static int setup_linear(const SwsImplParams *params, SwsImplResult *out)
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
static int setup_dither(const SwsImplParams *params, SwsImplResult *out)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
DECL_WRITE(write_planar, const SwsCompMask mask)
const h264_weight_func weight
static double val(void *priv, double ch)
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
#define SWS_COMP_ELEMS(N)
#define SWS_FOR(TYPE, UOP, MACRO,...)
#define SWS_FOR_STRUCT(TYPE, UOP, MACRO,...)
static const uint16_t dither[8][8]
uint8_t SwsCompMask
Bit-mask of components.
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
static unsigned int BS_FUNC() read_bit(BSCTX *bc)
Return one bit from the buffer.
Copyright (C) 2026 Niklas Haas.
#define xs(width, name, var, subs,...)
#define DECL_IMPL(FUNC, NAME, TYPE, UOP,...)
#define SWS_BLOCK_SIZE
Copyright (C) 2026 Niklas Haas.
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
#define i(width, name, range_min, range_max)
static double mz(int i, double w0, double r, double alpha)
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
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 offset
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
static int unpack(const uint8_t *src, const uint8_t *src_end, uint8_t *dst, int width, int height)
Unpack buffer.
int32_t * in_offset_x
Pixel offset map; for horizontal scaling, in bytes.
static const int weights[]
void * av_calloc(size_t nmemb, size_t size)
static void ff_op_priv_free(SwsOpPriv *priv)
#define bump_ptr(ptr, bump)
DECL_FUNC(lshift, const SwsCompMask mask, const uint8_t amount)
DECL_SETUP(setup_filter_v, params, out)
#define DECL_CAST(DST, dst)
uint32_t u32[SWS_BLOCK_SIZE]
int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
uint16_t u16[SWS_BLOCK_SIZE]
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static int setup_filter_v(const SwsImplParams *params, SwsImplResult *out)
#define DECL_PERMUTE(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3)
DECL_READ(read_planar, const SwsCompMask mask)
int ff_sws_dither_height(const SwsDitherUOp *dither)
Computes (1 << size_log2) + MAX(y_offset).
#define DECL_IMPL_READ(...)
static int setup_filter_h(const SwsImplParams *params, SwsImplResult *out)