Go to the documentation of this file.
72 av_log(
ctx, msg_lev,
"Backend '%s' failed to compile operations: %s\n",
93 "block size = %d, over-read = %d, over-write = %d, cpu flags = 0x%x\n",
94 backend->
name,
out->block_size,
out->over_read,
out->over_write,
127 const uint8_t *in[4], uint8_t *
out[4])
130 const int y_src =
p->offsets_y ?
p->offsets_y[y_dst] : y_dst;
131 for (
int i = 0;
i <
p->planes_in;
i++)
133 for (
int i = 0;
i <
p->planes_out;
i++)
148 const int block_size =
comp->block_size;
149 const int num_blocks = (pass->
width + block_size - 1) / block_size;
150 const int aligned_w = num_blocks * block_size;
151 p->num_blocks = num_blocks;
152 p->memcpy_first =
false;
153 p->memcpy_last =
false;
154 p->memcpy_out =
false;
156 for (
int i = 0;
i <
p->planes_in;
i++) {
157 const int idx =
p->idx_in[
i];
158 const int chroma = idx == 1 || idx == 2;
163 const int plane_size = plane_w *
p->pixel_bits_in >> 3;
164 const int total_size = plane_size + plane_pad;
167 p->memcpy_last |= total_size > in->
linesize[idx];
169 p->memcpy_first |= total_size > -in->
linesize[idx];
178 for (
int i = 0;
i <
p->planes_out;
i++) {
179 const int idx =
p->idx_out[
i];
180 const int chroma = idx == 1 || idx == 2;
185 const int plane_size = plane_w *
p->pixel_bits_out >> 3;
187 p->memcpy_out |= plane_size + plane_pad >
FFABS(
out->linesize[idx]);
195 const bool memcpy_in =
p->memcpy_first ||
p->memcpy_last;
196 if (!memcpy_in && !
p->memcpy_out)
202 size_t alloc_size = 0;
205 const int safe_width = (num_blocks - 1) * block_size;
206 const int tail_size = pass->
width - safe_width;
207 p->tail_off_out = safe_width *
p->pixel_bits_out >> 3;
208 p->tail_size_out = (tail_size *
p->pixel_bits_out + 7) >> 3;
213 p->tail_size_in += (
p->filter_size *
p->pixel_bits_in + 7) >> 3;
215 p->tail_off_in = safe_width *
p->pixel_bits_in >> 3;
216 p->tail_size_in = (tail_size *
p->pixel_bits_in + 7) >> 3;
219 for (
int i = 0; memcpy_in &&
i <
p->planes_in;
i++) {
220 size_t block_size = (
comp->block_size *
p->pixel_bits_in + 7) >> 3;
221 block_size +=
comp->over_read;
222 block_size =
FFMAX(block_size,
p->tail_size_in);
228 for (
int i = 0;
p->memcpy_out &&
i <
p->planes_out;
i++) {
229 size_t block_size = (
comp->block_size *
p->pixel_bits_out + 7) >> 3;
230 block_size +=
comp->over_write;
231 block_size =
FFMAX(block_size,
p->tail_size_out);
242 alloc_size += aligned_w *
sizeof(*exec->
in_offset_x);
248 p->tail_buf = tail_buf;
250 for (
int i = 0; memcpy_in &&
i <
p->planes_in;
i++) {
251 tail->
in[
i] = tail_buf;
255 for (
int i = 0;
p->memcpy_out &&
i <
p->planes_out;
i++) {
256 tail->
out[
i] = tail_buf;
262 for (
int i = safe_width;
i < aligned_w;
i++)
270 const uint8_t *
src,
const size_t src_stride,
271 const int h,
const size_t bytes)
273 for (
int y = 0; y <
h; y++) {
305 const bool memcpy_in =
p->memcpy_last && y +
h == pass->
height ||
306 p->memcpy_first && y == 0;
307 const bool memcpy_out =
p->memcpy_out;
308 const int num_blocks =
p->num_blocks;
311 if (!memcpy_in && !memcpy_out) {
313 comp->func(&exec,
comp->priv, 0, y, num_blocks, y +
h);
319 for (
int i = 0;
i < 4;
i++) {
323 exec.in_bump[
i] += exec.block_size_in;
324 exec.out_bump[
i] += exec.block_size_out;
327 comp->func(&exec,
comp->priv, 0, y, num_blocks - 1, y +
h);
333 for (
int i = 0;
i <
p->planes_in;
i++) {
335 if (!exec.in_offset_x || memcpy_in)
336 exec.in[
i] +=
p->tail_off_in;
337 tail.in[
i] += y * tail.in_stride[
i];
339 for (
int i = 0;
i <
p->planes_out;
i++) {
340 exec.out[
i] +=
p->tail_off_out;
341 tail.out[
i] += y * tail.out_stride[
i];
344 for (
int i = 0;
i <
p->planes_in;
i++) {
347 exec.in[
i], exec.in_stride[
i],
h,
p->tail_size_in);
350 tail.in[
i] = exec.in[
i];
351 tail.in_stride[
i] = exec.in_stride[
i];
352 tail.in_bump[
i] = exec.in_stride[
i] - exec.block_size_in;
356 for (
int i = 0; !memcpy_out &&
i <
p->planes_out;
i++) {
358 tail.out[
i] = exec.out[
i];
359 tail.out_stride[
i] = exec.out_stride[
i];
360 tail.out_bump[
i] = exec.out_stride[
i] - exec.block_size_out;
364 comp->func(&tail,
comp->priv, num_blocks - 1, y, num_blocks, y +
h);
366 for (
int i = 0; memcpy_out &&
i <
p->planes_out;
i++) {
368 tail.out[
i], tail.out_stride[
i],
h,
p->tail_size_out);
374 return op->rw.packed ? 1 :
op->rw.elems;
379 const int elems =
op->rw.packed ?
op->rw.elems : 1;
381 const int bits = 8 >>
op->rw.frac;
399 if (
p->comp.opaque) {
403 input,
c.slice_align,
c.func_opaque,
415 .height =
dst->height,
416 .block_size_in =
p->comp.block_size *
p->pixel_bits_in >> 3,
417 .block_size_out =
p->comp.block_size *
p->pixel_bits_out >> 3,
420 for (
int i = 0;
i < 4;
i++) {
437 for (
int y = 0; y <
filter->dst_size - 1; y++) {
438 int next =
filter->offsets[y + 1];
439 bump[y] = next -
line - 1;
442 bump[
filter->dst_size - 1] = 0;
443 p->exec_base.in_bump_y = bump;
453 for (
int x = 0; x <
filter->dst_size; x++)
455 for (
int x =
filter->dst_size; x < pixels; x++)
457 p->exec_base.in_offset_x =
offset;
458 p->exec_base.block_size_in = 0;
459 p->filter_size =
filter->filter_size;
487 if (!
read || !write) {
489 "and write, respectively.\n");
514 if (prev ==
input && !rest) {
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)
unsigned int tail_buf_size
static int rw_planes(const SwsOp *op)
void ff_sws_op_list_free(SwsOpList **p_ops)
#define AV_LOG_WARNING
Something somehow does not look correct.
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
SwsOpList * ff_sws_op_list_duplicate(const SwsOpList *ops)
Returns a duplicate of ops, or NULL on OOM.
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)
int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
Compile a list of operations using the best available backend.
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
Represents a computed filter kernel.
#define AV_LOG_VERBOSE
Detailed information.
void(* filter)(uint8_t *src, int stride, int qscale)
static int compile(SwsGraph *graph, const SwsOpList *ops, SwsPass *input, SwsPass **output)
int ff_sws_pixel_type_size(SwsPixelType type)
int ff_sws_op_list_subpass(SwsOpList *ops, SwsOpList **out_rest)
Eliminate SWS_OP_FILTER_* operations by merging them with prior SWS_OP_READ operations.
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[]
int(* compile)(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
Compile an operation list to an implementation chain.
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])
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList **pops, int flags, SwsPass *input, SwsPass **output)
Resolves an operation list to a graph pass.
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.
enum AVPixelFormat format
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
#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_LOG_DEBUG
Stuff which is only useful for libav* developers.
static AVFormatContext * ctx
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.
#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)
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
static int rw_pixel_bits(const SwsOp *op)
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
static void copy(const float *p1, float *p2, const int length)
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 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.
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
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...
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.
#define av_malloc_array(a, b)
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define DECLARE_ALIGNED_32(t, v)
Copyright (C) 2025 Niklas Haas.
int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt, int width, int height, SwsPass *input, 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.
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
int ff_sws_ops_compile_backend(SwsContext *ctx, const SwsOpBackend *backend, const SwsOpList *ops, SwsCompiledOp *out)
Attempt to compile a list of operations using a specific backend.
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)
Helper struct for representing a list of operations.
Main external API structure.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
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 ff_sws_graph_rollback(SwsGraph *graph, int since_idx)
Remove all passes added since the given index.