38#if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
44#if ARCH_AARCH64 && HAVE_NEON
46#elif ARCH_X86_64 && HAVE_X86ASM
50#if HAVE_SPIRV_HEADERS_SPIRV_H || HAVE_SPIRV_UNIFIED1_SPIRV_H
103 for (
int i = 0;
i < 4;
i++) {
114 for (
int i = 0;
i < 4;
i++) {
115 const int src = swiz->
in[
i];
126 for (
int i = 0;
i < 4;
i++) {
136 switch (
op->rw.mode) {
170 for (
int i = 0;
i < 4;
i++)
178 for (
int i = 0;
i < 4;
i++)
186 for (
int i = 0;
i < 4;
i++) {
192 for (
int i = 0;
i < 4;
i++) {
201 for (
int i = 0;
i < 4;
i++) {
203 x[
i] =
op->clear.value[
i];
209 for (
int i = 0;
i < 4;
i++)
215 for (
int i = 0;
i < 4;
i++)
216 x[
i] = x[
i].den ?
Q((x[
i].num / x[
i].den) >>
op->shift.amount) : x[
i];
220 const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] };
221 for (
int i = 0;
i < 4;
i++)
222 x[
i] = orig[
op->swizzle.in[
i]];
228 for (
int i = 0;
i < 4;
i++) {
229 x[
i] = x[
i].
den ?
Q(x[
i].num / x[
i].den) : x[
i];
230 if (
op->convert.expand)
237 for (
int i = 0;
i < 4;
i++) {
238 if (
op->dither.y_offset[
i] >= 0 && x[
i].
den)
243 for (
int i = 0;
i < 4;
i++)
247 for (
int i = 0;
i < 4;
i++)
252 const AVRational64 orig[4] = { x[0], x[1], x[2], x[3] };
253 for (
int i = 0;
i < 4;
i++) {
255 for (
int j = 0; j < 4; j++)
262 for (
int i = 0;
i < 4;
i++)
272 for (
int i = 0;
i < 3;
i++)
292 return ((
a &
b) & flags_and) | ((
a |
b) & flags_or);
300 for (
int i = 0;
i < 4;
i++) {
322 for (
int n = 0; n < ops->
num_ops; n++) {
335 memcpy(
op->comps.min, prev.
min,
sizeof(prev.
min));
336 memcpy(
op->comps.max, prev.
max,
sizeof(prev.
max));
342 for (
int i = 0;
i < 4;
i++) {
347 #define FORWARD(I, J, EXPR) do { \
348 SwsCompFlags flags = prev.flags[J]; \
349 op->comps.flags[I] = merge_comp_flags(op->comps.flags[I], (EXPR)); \
350 op->comps.dep_in[I] |= prev.dep_in[J]; \
353 #define RESET(I) do { \
354 op->comps.flags[I] = SWS_COMP_GARBAGE; \
355 op->comps.min[I] = op->comps.max[I] = (AVRational64) {0}; \
356 op->comps.dep_in[I] = SWS_COMP_NONE; \
363 for (
int i = 0;
i <
op->rw.elems;
i++) {
365 switch (
op->rw.mode) {
388 if (
op->rw.filter.op) {
394 for (
int i = 0;
i < 4;
i++) {
396 op->comps.min[
i] = prev.
min[
i];
397 op->comps.max[
i] = prev.
max[
i];
401 for (
int i = 0;
i <
op->rw.elems;
i++)
403 for (
int i = 0;
i < 4;
i++)
408 for (
int i = 0;
i < 4;
i++)
414 for (
int i = 0;
i < 4;
i++) {
416 if (
op->clamp.limit[
i].den)
424 for (
int i = 0;
i < 4;
i++) {
426 op->comps.min[
i] = prev.
min[
i];
427 op->comps.max[
i] = prev.
max[
i];
428 if (
op->dither.y_offset[
i] < 0)
437 for (
int i = 0;
i < 4;
i++) {
438 const int pattern =
op->pack.pattern[
i];
442 op->comps.min[
i] =
Q(0);
443 op->comps.max[
i] =
Q((1ULL << pattern) - 1);
449 for (
int i = 0;
i < 4;
i++) {
450 if (
op->pack.pattern[
i])
457 for (
int i = 0;
i < 4;
i++) {
460 if (
op->clear.value[
i].num == 0)
462 if (
op->clear.value[
i].den == 1)
470 for (
int i = 0;
i < 4;
i++)
474 for (
int i = 0;
i < 4;
i++) {
483 for (
int i = 0;
i < 4;
i++) {
486 for (
int j = 0; j < 4; j++) {
503 if (
op->lin.m[
i][4].num) {
505 if (
op->lin.m[
i][4].den != 1)
515 for (
int i = 0;
i < 4;
i++) {
517 if (
op->scale.factor.den != 1)
519 if (
op->scale.factor.num < 0)
529 for (
int i = 0;
i < 3;
i++) {
532 for (
int j = 0; j < 3; j++)
535 op->comps.min[
i] =
Q(0);
536 op->comps.max[
i] =
Q(UINT16_MAX);
540 op->comps.min[3] = prev.
min[3];
541 op->comps.max[3] = prev.
max[3];
554 for (
int n = ops->
num_ops - 1; n >= 0; n--) {
558 for (
int i = 0;
i < 4;
i++) {
559 op->comps.dep_out[
i] = need_out[
i];
567 for (
int i = 0;
i <
op->rw.elems;
i++)
569 for (
int i =
op->rw.elems;
i < 4;
i++)
570 need_in[
i] = need_out[
i];
582 for (
int i = 0;
i < 4;
i++)
583 need_in[
i] = need_out[
i];
586 for (
int i = 0;
i < 4 &&
op->pack.pattern[
i];
i++)
587 need_in[0] |= need_out[
i];
590 for (
int i = 0;
i < 4 &&
op->pack.pattern[
i];
i++)
591 need_in[
i] = need_out[0];
594 for (
int i = 0;
i < 4;
i++) {
596 need_in[
i] = need_out[
i];
600 for (
int i = 0;
i < 4;
i++)
601 need_in[
op->swizzle.in[
i]] |= need_out[
i];
604 for (
int i = 0;
i < 4;
i++) {
605 for (
int j = 0; j < 4; j++) {
606 if (
op->lin.m[
i][j].num)
607 need_in[j] |= need_out[
i];
612 for (
int i = 0;
i < 3;
i++)
613 need_in[
i] = need_out[0] | need_out[1] | need_out[2];
614 need_in[3] = need_out[3];
618 memcpy(need_out, need_in,
sizeof(need_in));
652 for (
int i = 0;
i < 4;
i++)
690 for (
int i = 0;
i <
copy->num_ops;
i++) {
694 if (
op->rw.filter.kernel)
733 const int end = ops->
num_ops - count;
735 for (
int i = 0;
i < count;
i++)
783 for (
int i = 0;
i < num_planes;
i++) {
805 for (
int i = 0;
i < 4;
i++) {
806 for (
int j = 0; j < 5; j++) {
835 for (
int i = 0;
i < 4;
i++) {
847 }
else if (q.
den == 1) {
849 }
else if (q.
num > 1000 || q.
num < -1000 || q.
den > 1000 || q.
den < -1000) {
859 for (
int i = 0;
i < 4;
i++) {
892 if (!
op->rw.filter.op)
908 op->pack.pattern[0],
op->pack.pattern[1],
909 op->pack.pattern[2],
op->pack.pattern[3]);
917 op->swizzle.x,
op->swizzle.y,
op->swizzle.z,
op->swizzle.w);
923 op->convert.expand ?
" (expand)" :
"");
927 1 <<
op->dither.size_log2, 1 <<
op->dither.size_log2,
928 op->dither.y_offset[0],
op->dither.y_offset[1],
929 op->dither.y_offset[2],
op->dither.y_offset[3]);
942 for (
int i = 0;
i < 4;
i++) {
944 for (
int j = 0; j < 5; j++) {
954 if (
op->scale.factor.den != 1)
966 av_bprintf(bp,
"%-20s: %s",
name,
op->lut3d.dynamic ?
"dynamic" :
"static");
976 for (
int i = 0;
i < nb_planes;
i++)
977 inorder &= order[
i] ==
i;
982 for (
int i = 0;
i < nb_planes;
i++)
1023 if (range_mask &
mask) {
1030 av_log(log, lev_extra,
"%s\n", bp.str);
1033 bool has_deps =
false;
1034 for (
int i = 0;
i < 4;
i++)
1035 has_deps |=
op->comps.dep_in[
i] ||
op->comps.dep_out[
i];
1043 av_log(log, lev_extra,
"%s\n", bp.str);
1048 av_log(log,
lev,
" ('X' unused, 'z' byteswapped, '=' copied, '$' const, '+' integer, '0' zero)\n");
const SwsOpBackend backend_aarch64
static double val(void *priv, double ch)
static double bound(const double threshold, const double val)
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static uint32_t BS_FUNC read(BSCTX *bc, unsigned int n)
Return n bits from the buffer, n has to be in the 0-32 range.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
#define AV_BPRINT_SIZE_AUTOMATIC
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
static LevelCodes lev[4+3+3]
AVRational64 av_mul_q64(AVRational64 b, AVRational64 c)
Multiply two 64-bit rationals.
int av_cmp_q64(AVRational64 a, AVRational64 b)
Compare two 64-bit rationals.
AVRational64 av_add_q64(AVRational64 b, AVRational64 c)
Add two 64-bit rationals.
static double av_q2d_64(AVRational64 a)
Convert an AVRational64 to a double.
static AVRational64 av_make_q64(int64_t num, int64_t den)
Create an AVRational64.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
static const int weights[]
static void scale(int *out, const int *in, const int w, const int h, const int shift)
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
static int shift(int a, int b)
static int16_t mult(Float11 *f1, Float11 *f2)
Macro definitions for various function/variable attributes.
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
static const struct @257111027162314367033347246032313251342043035002 planes[]
static const uint16_t mask[17]
#define FFSWAP(type, a, b)
Memory handling functions.
int ff_sws_op_list_max_size(const SwsOpList *ops)
Returns the size of the largest pixel type used in ops.
void ff_sws_op_list_update_comps(SwsOpList *ops)
Infer + propagate known information about components.
void ff_sws_op_desc(AVBPrint *bp, const SwsOp *op)
Describe an operation in human-readable form.
const SwsOpBackend backend_c
Copyright (C) 2025 Niklas Haas.
uint32_t ff_sws_linear_mask(const SwsLinearOp *c)
static void print_q4(AVBPrint *bp, const AVRational64 q4[4], SwsCompMask mask)
static void desc_plane_order(AVBPrint *bp, int nb_planes, const uint8_t *order)
static void print_deps(AVBPrint *bp, const SwsCompMask *deps)
int ff_sws_op_list_insert_at(SwsOpList *ops, int index, SwsOp *op)
const SwsOpBackend backend_x86
static void op_uninit(SwsOp *op)
const SwsOp * ff_sws_op_list_input(const SwsOpList *ops)
Returns the input operation for a given op list, or NULL if there is none (e.g.
void ff_sws_op_list_free(SwsOpList **p_ops)
const SwsOpBackend *const ff_sws_op_backends[]
static AVRational64 av_min_q64(AVRational64 a, AVRational64 b)
const SwsOpBackend backend_murder
int ff_sws_op_list_append(SwsOpList *ops, SwsOp *op)
These will take over ownership of op and set it to {0}, even on failure.
void ff_sws_comp_mask_swizzle(SwsCompMask *mask, const SwsSwizzleOp *swiz)
SwsOpList * ff_sws_op_list_alloc(void)
#define FORWARD(I, J, EXPR)
const char * ff_sws_op_type_name(SwsOpType op)
static AVRational64 av_max_q64(AVRational64 a, AVRational64 b)
static char describe_comp_flags(SwsCompFlags flags)
SwsCompMask ff_sws_comp_mask_needed(const SwsOp *op)
const char * ff_sws_pixel_type_name(SwsPixelType type)
static SwsCompFlags merge_comp_flags(SwsCompFlags a, SwsCompFlags b)
SwsCompMask ff_sws_comp_mask_q4(const AVRational64 q[4])
int ff_sws_rw_op_planes(const SwsOp *op)
Return the number of planes involved in a read/write operation.
const SwsOp * ff_sws_op_list_output(const SwsOpList *ops)
Returns the output operation for a given op list, or NULL if there is none.
bool ff_sws_op_list_is_noop(const SwsOpList *ops)
Returns whether an op list represents a true no-op operation, i.e.
void ff_sws_op_list_print(void *log, int lev, int lev_extra, const SwsOpList *ops)
Print out the contents of an operation list.
static const char *const rw_mode_names[]
void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
Apply an operation to an AVRational64.
void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count)
SwsOpList * ff_sws_op_list_duplicate(const SwsOpList *ops)
Returns a duplicate of ops, or NULL on OOM.
static void apply_filter_weights(SwsComps *comps, const SwsComps *prev, const SwsFilterWeights *weights)
SwsOpType
Copyright (C) 2025 Niklas Haas.
@ SWS_RW_PLANAR
Note: 1-component reads are either SWS_RW_PLANAR or SWS_RW_PACKED, depending on the underlying interp...
#define SWS_OP_NEEDED(op, idx)
static AVRational64 ff_sws_pixel_expand(SwsPixelType from, SwsPixelType to)
static void ff_sws_pack_op_decode(const SwsOp *op, uint64_t mask[4], int shift[4])
Utilities for rational number calculation.
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
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.
64-bit Rational number (pair of numerator and denominator).
Represents a computed filter kernel.
int src_size
Copy of the parameters used to generate this filter, for reference.
char name[16]
Extra metadata about the filter, used to inform the optimizer / range tracker about the filter's beha...
int filter_size
The number of source texels to convolve over for each row.
Helper struct for representing a list of operations.
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
SwsReadWriteMode mode
Examples: rgba = 4x u8 packed yuv444p = 3x u8 rgb565 = 1x u16 <- use SWS_OP_UNPACK to unpack monow = ...
struct SwsReadWriteOp::@312356277033155231251141106170064356360153154105 filter
Filter kernel to apply to each plane while sampling.
#define ff_sws_comp_mask_str(mask)
#define SWS_COMP_TEST(mask, X)
static av_const bool ff_sws_pixel_type_is_int(SwsPixelType type)
uint8_t SwsCompMask
Bit-mask of components.
static av_const int ff_sws_pixel_type_size(SwsPixelType type)
static void copy(const float *p1, float *p2, const int length)