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;
190 out0[
i >> 3] = x[
i + 0] << 7 |
209 out0[
i >> 1] = x[
i] << 4 | x[
i + 1];
246 static_assert(
sizeof(
out->priv.ptr) <=
sizeof(
int32_t[2]),
247 ">8 byte pointers not supported");
254 for (
int i = 0;
i <
filter->num_weights;
i++)
268 const float *restrict
weights = impl->priv.ptr;
269 const int filter_size = impl->priv.i32[2];
270 weights += filter_size * iter->y;
273 if (
X) memset(&
xs.f32, 0,
sizeof(
xs.f32));
274 if (
Y) memset(&ys.
f32, 0,
sizeof(ys.
f32));
275 if (
Z) memset(&zs.
f32, 0,
sizeof(zs.
f32));
276 if (
W) memset(&ws.
f32, 0,
sizeof(ws.
f32));
278 for (
int j = 0; j < filter_size; j++) {
320 const int *restrict
weights = impl->priv.ptr;
321 const int filter_size = impl->priv.i32[2];
323 const int xpos = iter->x;
324 weights += filter_size * iter->x;
334 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
335 for (
int j = 0; j < filter_size; j++) {
337 if (
X) sx +=
weight * start0[j];
338 if (
Y) sy +=
weight * start1[j];
339 if (
Z) sz +=
weight * start2[j];
340 if (
W) sw +=
weight * start3[j];
364 #define DECL_PERMUTE(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3) \
365 static void NAME##_c(SwsOpIter *restrict iter, \
366 const SwsOpImpl *restrict impl, \
367 void *restrict in0, void *restrict in1, \
368 void *restrict in2, void *restrict in3) \
370 CONTINUE(in##IDX0, in##IDX1, in##IDX2, in##IDX3); \
373 #define DECL_COPY(DUMMY, NAME, TYPE, UOP, MASK, IDX0, IDX1, IDX2, IDX3) \
374 static void NAME##_c(SwsOpIter *restrict iter, \
375 const SwsOpImpl *restrict impl, \
376 void *restrict in0, void *restrict in1, \
377 void *restrict in2, void *restrict in3) \
379 const SwsCompMask mask = (MASK); \
380 block_t x, y, z, w; \
382 if (X) memcpy(&x.px, in##IDX0, SIZEOF_BLOCK); \
383 if (Y) memcpy(&y.px, in##IDX1, SIZEOF_BLOCK); \
384 if (Z) memcpy(&z.px, in##IDX2, SIZEOF_BLOCK); \
385 if (W) memcpy(&w.px, in##IDX3, SIZEOF_BLOCK); \
387 CONTINUE(X ? &x : in0, Y ? &y : in1, Z ? &z : in2, W ? &w : in3); \
399 #define DECL_CAST(DST, dst) \
400 DECL_FUNC(to_##dst, const SwsCompMask mask) \
402 block_t xx, yy, zz, ww; \
405 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
406 if (X) xx.dst[i] = x[i]; \
407 if (Y) yy.dst[i] = y[i]; \
408 if (Z) zz.dst[i] = z[i]; \
409 if (W) ww.dst[i] = w[i]; \
412 CONTINUE(&xx, &yy, &zz, &ww); \
415 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
416 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
432 if (
X) x[
i] <<= amount;
433 if (
Y) y[
i] <<= amount;
434 if (
Z) z[
i] <<= amount;
435 if (
W)
w[
i] <<= amount;
445 if (
X) x[
i] >>= amount;
446 if (
Y) y[
i] >>= amount;
447 if (
Z) z[
i] >>= amount;
448 if (
W)
w[
i] >>= amount;
466 if (
X) x[
i] = PIXEL_SWAP(x[
i]);
467 if (
Y) y[
i] = PIXEL_SWAP(y[
i]);
468 if (
Z) z[
i] = PIXEL_SWAP(z[
i]);
469 if (
W)
w[
i] = PIXEL_SWAP(
w[
i]);
501 if (
X) x16.
u16[
i] = x[
i] << 8 | x[
i];
502 if (
Y) y16.
u16[
i] = y[
i] << 8 | y[
i];
503 if (
Z) z16.
u16[
i] = z[
i] << 8 | z[
i];
516 if (
X) x32.
u32[
i] = (uint32_t) x[
i] << 24 | x[
i] << 16 | x[
i] << 8 | x[
i];
517 if (
Y) y32.
u32[
i] = (uint32_t) y[
i] << 24 | y[
i] << 16 | y[
i] << 8 | y[
i];
518 if (
Z) z32.
u32[
i] = (uint32_t) z[
i] << 24 | z[
i] << 16 | z[
i] << 8 | z[
i];
519 if (
W) w32.
u32[
i] = (uint32_t)
w[
i] << 24 |
w[
i] << 16 |
w[
i] << 8 |
w[
i];
539 const uint8_t bx,
const uint8_t by,
540 const uint8_t bz,
const uint8_t bw)
542 const uint8_t sx = bw + bz + by;
543 const uint8_t sy = bw + bz;
544 const uint8_t sz = bw;
545 const uint8_t sw = 0;
550 const pixel_t mw = (1 << bw) - 1;
555 if (
X) x[
i] = (
val >> sx) &
mx;
556 if (
Y) y[
i] = (
val >> sy) &
my;
557 if (
Z) z[
i] = (
val >> sz) &
mz;
558 if (
W)
w[
i] = (
val >> sw) & mw;
565 const uint8_t bx,
const uint8_t by,
566 const uint8_t bz,
const uint8_t bw)
568 const uint8_t sx = bw + bz + by;
569 const uint8_t sy = bw + bz;
570 const uint8_t sz = bw;
571 const uint8_t sw = 0;
576 if (
X)
val |= x[
i] << sx;
577 if (
Y)
val |= y[
i] << sy;
578 if (
Z)
val |= z[
i] << sz;
600 #define ONE(N) SWS_COMP_TEST(one, N)
601 #define ZERO(N) SWS_COMP_TEST(zero, N)
645 if (
X) x[
i] += impl->priv.px[0];
646 if (
Y) y[
i] += impl->priv.px[1];
647 if (
Z) z[
i] += impl->priv.px[2];
648 if (
W)
w[
i] += impl->priv.px[3];
658 if (
X) x[
i] =
FFMIN(x[
i], impl->priv.px[0]);
659 if (
Y) y[
i] =
FFMIN(y[
i], impl->priv.px[1]);
660 if (
Z) z[
i] =
FFMIN(z[
i], impl->priv.px[2]);
671 if (
X) x[
i] =
FFMAX(x[
i], impl->priv.px[0]);
672 if (
Y) y[
i] =
FFMAX(y[
i], impl->priv.px[1]);
673 if (
Z) z[
i] =
FFMAX(z[
i], impl->priv.px[2]);
716 for (
int y = 0; y <
height; y++) {
718 for (
int x = 0; x <
size; x++)
721 row[x] = row[x %
size];
728 const uint8_t off0,
const uint8_t off1,
729 const uint8_t off2,
const uint8_t off3,
730 const uint8_t size_log2)
732 const int size = 1 << size_log2;
746 if (
X) x[
i] += row0[
i];
747 if (
Y) y[
i] += row1[
i];
748 if (
Z) z[
i] += row2[
i];
749 if (
W)
w[
i] += row3[
i];
773 for (
int i = 0;
i < 4;
i++) {
774 for (
int j = 0; j < 4; j++)
792 const fn(LinCoeffs)
c = *(
const fn(LinCoeffs) *) impl->priv.ptr;
801 #define LIN_VAL(I, J, val) \
802 ((one & SWS_MASK(I, J)) ? (val) : c.m[I][J] * (val))
804 #define LIN_ROW(I, var) do { \
805 var[i] = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
806 if (!(zero & SWS_MASK(I, 0))) var[i] += LIN_VAL(I, 0, xx); \
807 if (!(zero & SWS_MASK(I, 1))) var[i] += LIN_VAL(I, 1, yy); \
808 if (!(zero & SWS_MASK(I, 2))) var[i] += LIN_VAL(I, 2, zz); \
809 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
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
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[]
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 default value
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)
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)