Go to the documentation of this file.
35 if ((ret = (x)) < 0) \
82 av_log(
ctx, msg_lev,
"Backend '%s' failed to compile operations: %s\n",
91 "block size = %d, over-read = {%d %d %d %d}, over-write = {%d %d %d %d}, "
92 "cpu flags = 0x%x\n", backend->
name,
out->block_size,
93 out->over_read[0],
out->over_read[1],
94 out->over_read[2],
out->over_read[3],
95 out->over_write[0],
out->over_write[1],
96 out->over_write[2],
out->over_write[3],
117 !(enabled & backend->
flags))
151 const uint8_t *in[4], uint8_t *
out[4])
154 const int y_src =
p->offsets_y ?
p->offsets_y[y_dst] : y_dst;
155 for (
int i = 0;
i <
p->planes_in;
i++)
157 for (
int i = 0;
i <
p->planes_out;
i++)
166 return h >>
base->in_sub_y[plane];
168 const int y0 =
p->offsets_y[y] >>
base->in_sub_y[plane];
169 const int y1 =
p->offsets_y[y +
h - 1] >>
base->in_sub_y[plane];
176 const uint64_t
bits = (uint64_t) pixels * pixel_bits;
183 return (
bits + 7) >> 3;
194 return FFMAX(safe_bytes, 0);
198 ptrdiff_t safe_offset,
201 size_t safe_blocks = num_blocks;
202 while (safe_blocks && offset_bytes[safe_blocks * block_size - 1] > safe_offset)
219 const unsigned block_size =
comp->block_size;
220 const size_t num_blocks = (
width + block_size - 1) / block_size;
221 const size_t aligned_w = num_blocks * block_size;
222 if (aligned_w <
width)
224 p->num_blocks = num_blocks;
225 p->memcpy_first =
false;
226 p->memcpy_last =
false;
227 p->memcpy_out =
false;
229 size_t safe_blocks = num_blocks;
230 for (
int i = 0;
i <
p->planes_in;
i++) {
231 const int idx =
p->idx_in[
i];
232 size_t input_bytes = in->
linesize[idx];
233 if (
p->filter_size_h && float_in) {
240 size_t safe_blocks_in;
242 size_t filter_size =
pixel_bytes(
p->filter_size_h,
p->pixel_bits_in,
245 safe_bytes - filter_size,
251 if (safe_blocks_in < num_blocks) {
252 p->memcpy_first |= in->
linesize[idx] < 0;
254 safe_blocks =
FFMIN(safe_blocks, safe_blocks_in);
263 for (
int i = 0;
i <
p->planes_out;
i++) {
264 const int idx =
p->idx_out[
i];
267 if (safe_blocks_out < num_blocks) {
268 p->memcpy_out =
true;
269 safe_blocks =
FFMIN(safe_blocks, safe_blocks_out);
278 if (
p->palette_idx >= 0) {
279 exec->
in[1] = in->
data[
p->palette_idx];
283 const bool memcpy_in =
p->memcpy_first ||
p->memcpy_last;
284 if (!memcpy_in && !
p->memcpy_out) {
292 size_t alloc_size = 0;
295 const size_t safe_width = safe_blocks * block_size;
296 const size_t tail_size =
width - safe_width;
299 p->tail_blocks = num_blocks - safe_blocks;
310 const size_t alloc_width = aligned_w - safe_width;
311 for (
int i = 0; memcpy_in &&
i <
p->planes_in;
i++) {
317 needed_size =
p->tail_size_in;
327 for (
int i = 0;
p->memcpy_out &&
i <
p->planes_out;
i++) {
340 alloc_size += aligned_w *
sizeof(*exec->
in_offset_x);
347 uint8_t *tail_buf =
p->tail_buf;
348 for (
int i = 0; memcpy_in &&
i <
p->planes_in;
i++) {
349 tail->
in[
i] = tail_buf;
353 for (
int i = 0;
p->memcpy_out &&
i <
p->planes_out;
i++) {
354 tail->
out[
i] = tail_buf;
360 for (
int i = safe_width;
i < aligned_w;
i++)
368 const uint8_t *
src,
const size_t src_stride,
369 const int h,
const size_t bytes)
371 for (
int y = 0; y <
h; y++) {
403 const bool memcpy_in =
p->memcpy_last && y +
h == pass->
lines ||
404 p->memcpy_first && y == 0;
405 const bool memcpy_out =
p->memcpy_out;
406 const size_t num_blocks =
p->num_blocks;
407 const size_t tail_blocks =
p->tail_blocks;
410 if (!memcpy_in && !memcpy_out) {
412 comp->func(&exec,
comp->priv, 0, y, num_blocks, y +
h);
418 if (num_blocks > tail_blocks) {
419 for (
int i = 0;
i < 4;
i++) {
423 exec.in_bump[
i] += exec.block_size_in[
i] * tail_blocks;
424 exec.out_bump[
i] += exec.block_size_out[
i] * tail_blocks;
427 comp->func(&exec,
comp->priv, 0, y, num_blocks - tail_blocks, y +
h);
434 for (
int i = 0;
i <
p->planes_in;
i++) {
436 if (!exec.in_offset_x || memcpy_in)
437 exec.in[
i] +=
p->tail_off_in;
438 tail.in[
i] += y * tail.in_stride[
i];
440 for (
int i = 0;
i <
p->planes_out;
i++) {
441 exec.out[
i] +=
p->tail_off_out;
442 tail.out[
i] += y * tail.out_stride[
i];
445 for (
int i = 0;
i <
p->planes_in;
i++) {
449 exec.in[
i], exec.in_stride[
i], lines,
p->tail_size_in);
452 const size_t loop_size = tail_blocks * exec.block_size_in[
i];
453 tail.in[
i] = exec.in[
i];
454 tail.in_stride[
i] = exec.in_stride[
i];
455 tail.in_bump[
i] = exec.in_stride[
i] - loop_size;
459 for (
int i = 0; !memcpy_out &&
i <
p->planes_out;
i++) {
461 const size_t loop_size = tail_blocks * exec.block_size_out[
i];
462 tail.out[
i] = exec.out[
i];
463 tail.out_stride[
i] = exec.out_stride[
i];
464 tail.out_bump[
i] = exec.out_stride[
i] - loop_size;
469 comp->func(&tail,
comp->priv, num_blocks - tail_blocks, y, num_blocks, y +
h);
471 for (
int i = 0; memcpy_out &&
i <
p->planes_out;
i++) {
472 const int lines =
h >> tail.out_sub_y[
i];
474 tail.out[
i], tail.out_stride[
i], lines,
p->tail_size_out);
491 switch (
op->rw.mode) {
497 const int bits = 8 >>
op->rw.frac;
505 if (!pass || pixel_bits <= 0)
510 for (
int i = 0;
i < 4;
i++) {
511 const int pad = (over_rw[
i] * 8 + pixel_bits - 1) / pixel_bits;
512 pad_max =
FFMAX(pad_max, pad);
546 if (
p->comp.opaque) {
550 input, 0,
c.slice_align,
c.func_opaque,
553 (*output)->backend =
comp->backend->flags;
567 .height =
dst->height,
580 if (block_bits_in & 0x7 || block_bits_out & 0x7) {
586 for (
int i = 0;
i < 4;
i++)
587 p->idx_in[
i] =
p->idx_out[
i] = -1;
589 for (
int i = 0;
i <
p->planes_in;
i++) {
591 const int chroma = idx == 1 || idx == 2;
594 p->exec_base.in_sub_x[
i] = sub_x;
595 p->exec_base.in_sub_y[
i] = sub_y;
596 p->exec_base.block_size_in[
i] = block_bits_in >> 3;
600 for (
int i = 0;
i <
p->planes_out;
i++) {
602 const int chroma = idx == 1 || idx == 2;
605 p->exec_base.out_sub_x[
i] = sub_x;
606 p->exec_base.out_sub_y[
i] = sub_y;
607 p->exec_base.block_size_out[
i] = block_bits_out >> 3;
623 for (
int y = 0; y <
filter->dst_size - 1; y++) {
624 int next =
filter->offsets[y + 1];
625 bump[y] = next -
line - 1;
628 bump[
filter->dst_size - 1] = 0;
629 p->exec_base.in_bump_y = bump;
638 p->exec_base.in_offset_x =
offset;
640 for (
int x = 0; x <
filter->dst_size; x++) {
645 if ((
bits & 0x7) || (
bits >> 3) > INT32_MAX) {
651 for (
int x =
filter->dst_size; x < pixels; x++)
653 for (
int i = 0;
i < 4;
i++)
654 p->exec_base.block_size_in[
i] = 0;
655 p->filter_size_h =
filter->filter_size;
664 (*output)->backend =
comp->backend->flags;
680 for (
int c = 0;
c < 4;
c++) {
721 for (
int idx = 1; idx < ops->
num_ops - 1; idx++) {
792 const int num_passes = graph->
num_passes - passes_orig;
static void copy_lines(uint8_t *dst, const size_t dst_stride, const uint8_t *src, const size_t src_stride, const int h, const size_t bytes)
@ AV_ROUND_UP
Round toward +infinity.
unsigned int tail_buf_size
int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt, int width, int height, SwsPass *input, int lines, int align, SwsPassFunc run, SwsPassSetup setup, void *priv, void(*free_cb)(void *priv), SwsPass **out_pass)
Allocate and add a new pass to the filter graph.
void ff_sws_op_list_free(SwsOpList **p_ops)
#define AV_LOG_WARNING
Something somehow does not look correct.
int ff_sws_rw_op_planes(const SwsOp *op)
Return the number of planes involved in a read/write operation.
Represents a single filter pass in the scaling graph.
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
void ff_sws_pass_link_output(SwsPass *dst, const SwsPass *src)
Link the output buffers to a different pass, rather than allocating new image buffers.
SwsOpList * ff_sws_op_list_duplicate(const SwsOpList *ops)
Returns a duplicate of ops, or NULL on OOM.
@ SWS_RW_PLANAR
Note: 1-component reads are either SWS_RW_PLANAR or SWS_RW_PACKED, depending on the underlying interp...
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
ptrdiff_t in_bump[4]
Pointer bump, difference between stride and processed line size.
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.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
static int compile_subpass(const CompileArgs *args, SwsOpList **pops, SwsPass *link, SwsPass *input, SwsPass **output)
Represents a computed filter kernel.
int32_t block_size_out[4]
@ AV_ROUND_ZERO
Round toward zero.
AVRounding
Rounding methods.
#define AV_LOG_VERBOSE
Detailed information.
void(* filter)(uint8_t *src, int stride, int qscale)
int width
Dimensions and format.
const SwsOpBackend * backend
int ff_sws_pixel_type_size(SwsPixelType type)
void ff_sws_op_list_print(void *log, int lev, int lev_extra, const SwsOpList *ops)
Print out the contents of an operation list.
const SwsOpBackend *const ff_sws_op_backends[]
static int rw_data_planes(const SwsOp *op)
enum AVPixelFormat hw_format
If NONE, backend only supports software frames.
static void get_row_data(const SwsOpPass *p, const int y_dst, const uint8_t *in[4], uint8_t *out[4])
static size_t safe_blocks_offset(size_t num_blocks, unsigned block_size, ptrdiff_t safe_offset, const int32_t *offset_bytes)
Represents a view into a single field of frame data.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static const struct @594 planes[]
enum AVPixelFormat format
#define AV_CEIL_RSHIFT(a, b)
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.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static AVFormatContext * ctx
uint8_t SwsCompMask
Bit-mask of components.
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
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.
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 link
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Copyright (C) 2026 Niklas Haas.
bool ff_sws_op_list_is_noop(const SwsOpList *ops)
Returns whether an op list represents a true no-op operation, i.e.
static void op_pass_free(void *ptr)
void ff_sws_compiled_op_unref(SwsCompiledOp *comp)
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
Allocate and clear a buffer, reusing the given one if large enough.
int ff_sws_op_list_split_at(SwsOpList *ops1, SwsOpList **ops2, int index)
Split an op list into two at the given index.
static int rw_pixel_bits(const SwsOp *op)
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
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(* compile)(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
Compile an operation list to an implementation chain.
@ AV_ROUND_DOWN
Round toward -infinity.
static void copy(const float *p1, float *p2, const int length)
@ SWS_OP_FLAG_SPLIT_MEMCPY
SwsBackend ff_sws_enabled_backends(const SwsContext *ctx)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define i(width, name, range_min, range_max)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
static int op_pass_setup(const SwsFrame *out, const SwsFrame *in, const SwsPass *pass)
void ff_sws_op_list_update_comps(SwsOpList *ops)
Infer + propagate known information about components.
static int compile_backend(SwsContext *ctx, const SwsOpBackend *backend, const SwsOpList *ops, SwsCompiledOp *out)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
const struct SwsOpBackend * backend
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
int ff_sws_op_list_split_planes(SwsOpList *ops1, SwsOpList **ops2, SwsCompMask planes)
Reduce an op list into a reduced subset that operates only on a given subset of planes.
SwsPassBuffer * output
Filter output buffer.
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 void align_pass(SwsPass *pass, int block_size, const int *over_rw, int pixel_bits)
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
static int get_lines_in(const SwsOpPass *p, const int y, const int h, const int plane)
int ff_sws_op_list_optimize(SwsOpList *ops)
Fuse compatible and eliminate redundant operations, as well as replacing some operations with more ef...
int32_t * in_offset_x
Pixel offset map; for horizontal scaling, in bytes.
@ AV_ROUND_INF
Round away from zero.
#define av_malloc_array(a, b)
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define DECLARE_ALIGNED_32(t, v)
static size_t pixel_bytes(size_t pixels, int pixel_bits, enum AVRounding rounding)
#define FFSWAP(type, a, b)
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static size_t safe_bytes_pad(int linesize, int plane_pad)
int ff_sws_compile_pass(SwsGraph *graph, const SwsOpBackend *backend, SwsOpList **pops, int flags, SwsPass *input, SwsPass **output)
Resolves an operation list to a graph pass.
Filter graph, which represents a 'baked' pixel format conversion.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
static void op_pass_run(const SwsFrame *out, const SwsFrame *in, const int y, const int h, const SwsPass *pass)
static SwsCompMask plane_mask_flags(const SwsOp *op, SwsCompFlags flags)
Represents an output buffer for a filter pass.
Helper struct for representing a list of operations.
static int compile_single(const CompileArgs *args, const SwsOpList *ops, SwsPass *link, SwsPass *input, SwsPass **output)
Main external API structure.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
#define RET(x)
Copyright (C) 2025 Niklas Haas.
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.
int ff_sws_ops_compile(SwsContext *ctx, const SwsOpBackend *backend, const SwsOpList *ops, SwsCompiledOp *out)
Attempt to compile a list of operations using a specific backend, or the best available backend if ba...
void ff_sws_graph_rollback(SwsGraph *graph, int since_idx)
Remove all passes added since the given index.
#define ff_sws_comp_mask_str(mask)