44 Commits

Author SHA1 Message Date
Niklas Haas
1c2a300f66 swscale/graph: remove pointless helper
Basically identical to ff_sws_graph_add_pass() after the previous commit.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-05 23:34:56 +00:00
Niklas Haas
d9e594ca96 swscale/graph: have ff_sws_graph_add_pass() return an error code
This allows distinguishing between different types of failure, e.g.
AVERROR(EINVAL) on invalid pass dimensions.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-05 23:34:56 +00:00
Niklas Haas
0540b42657 swscale/graph: correctly handle single threaded mode
The code was evidently designed at one point in time to support "direct"
execution (not via a thread pool) for num_threads == 1, but this was never
implemented.

As a side benefit, reduces context creation overhead in single threaded
mode (relevant e.g. inside the libswscale self test), due to not needing to
spawn and destroy several thousand worker threads.

Co-authored-by: Ramiro Polla <ramiro.polla@gmail.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-03 23:13:41 +00:00
Niklas Haas
b2266d6656 swscale/graph: correctly adjust field height for interlaced frames
This is a pre-existing bug from 67f3627267.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-01 21:57:53 +00:00
Niklas Haas
02e4b45f7f swscale/graph: reintroduce SwsFrame
AVFrame just really doesn't have the semantics we want. However, there a
tangible benefit to having SwsFrame act as a carbon copy of a (subset of)
AVFrame.

This partially reverts commit 67f3627267.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-03-01 21:57:53 +00:00
Niklas Haas
67f3627267 swscale/graph: nuke SwsImg
This has now become fully redundant with AVFrame, especially since the
existence of SwsPassBuffer. Delete it, simplifying a lot of things and
avoiding reinventing the wheel everywhere.

Also generally reduces overhead, since there is less redundant copying
going on.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
4d7b1c3685 swscale/graph: move frame->field init logic to SwsGraph
And have ff_sws_graph_run() just take a bare AVFrame. This will help with
an upcoming change, aside from being a bit friendlier towards API users
in general.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
846823b174 swscale/graph: don't pointlessly align data buffers
Since d67d81a374, enabling asm explicitly requires aligned malloc,
so this FFALIGN accomplishes nothing.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
5121665463 swscale/graph: use AVFrame to track internal allocation
This commit replaces the AVBufferRef inside SwsPassBuffer by an AVFrame, in
anticipation of the SwsImg removal.

Incidentally, we could also now just use av_frame_get_buffer() here, but
at the cost of breaking the 1:1 relationship between planes and buffers,
which is required for per-plane refcopies.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
e9d1ed3fdc swscale/graph: avoid stack copies of SwsImg
In the process of nuking this abstraction in favor of AVFrame.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
d89765eb28 swscale/graph: simplify output buffer management
This function was originally written to support the use case of e.g.
partially allocated planes that implicitly reference the original input
image, but I've decided that this is stupid and doesn't currently work
anyways.

Plus, I have plans to kill SwsImg, so we need to simplify this mess.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-27 16:18:34 +00:00
Niklas Haas
841ca7a2cb swscale/format: pass SwsFormat by ref instead of by value where possible
The one exception is in adapt_colors(), which mutates these structs on
its own stack anyways.
2026-02-26 18:08:49 +00:00
Lynne
362414afba swscale: add support for processing hardware frames
Sponsored-by: Sovereign Tech Fund
2026-02-26 14:10:22 +01:00
Lynne
ad452205b6 swscale/ops: add SwsOpBackend.hw_format
Allows to filter hardware formats.

Sponsored-by: Sovereign Tech Fund
2026-02-26 14:10:22 +01:00
Lynne
c911295f09 swscale: forward original frame pointers to ops.c backend
Sponsored-by: Sovereign Tech Fund
2026-02-26 14:10:21 +01:00
Ramiro Polla
c7c8c31302 swscale/tests/sws_ops: print range values in the output
This gives more information about each operation and helps catch issues
earlier on.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Ramiro Polla <ramiro.polla@gmail.com>
2026-02-24 19:27:51 +01:00
Niklas Haas
d918551650 swscale/graph: switch SwsPass.output to refstruct
Allows multiple passes to share a single output buffer reference. We always
allocate an output buffer so that subpasses can share the same output buffer
reference while still allowing that reference to implicitly point to the
final output image.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
cc346b232d swscale/graph: store current pass input instead of global args
The global args to ff_sws_graph_run() really shouldn't matter inside thread
workers. If they ever do, it indicates a leaky abstraction. The only reason
it was needed in the first place was because of the way the input/output
buffers implicitly defaulted to the global args.

However, we can solve this much more elegantly by just calculating it in
ff_sws_graph_run() directly and storing the computed SwsImg inside the
execution state.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
1e071c8585 swscale/graph: omit memcpy() if src and dst are identical
This allows already referenced planes to be skipped, in the case of e.g.
only some of the output planes being sucessfully referenced. Also avoids
what is technically UB, if the user happens to call ff_sws_graph_run() after
already having ref'd an image.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
b98751b13c swscale/graph: set up palette using current input image
Using the original input image here is completely wrong - the format/palette
could have been set to anything else in the meantime. At best, we would want to
use the original input to add_legacy_sws_pass(), but it's impossible for this
to differ from the per-pass input. The only time legacy subpasses are added
is when using cascaded contexts, but in this case, the only context actually
reading from the palette format would be the first one.

I'm not entirely sure why this code was originally written this way, but
I'm reasonably confident that it's not at all necessary. Tested extensively
on both FATE, the self-test, and real-world files.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
0b446cdccd swscale/graph: switch to an AVBufferRef per plane
This annoyingly requires recreating some of the logic inside av_img_alloc(),
because there's no good existing current helper accessible from libswscale
that gives per-plane allocations like this.

The new code is based off the calculations inside libavframe/bufferpool.c.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
afa08f4971 swscale/graph: duplicate buffer dimensions in SwsPassBuffer
When multiple passes share a buffer reference, the true buffer dimensions
may be different for each pass, depending on slice alignment. So we can't
rely on the pass dimensions being representative.

Instead, store this information in the SwsPassBuffer itself.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
fe25e54d0f swscale/graph: move output image into separate struct
I want to add more metadata to this and also turn it into a refstruct,
but get the cosmetic diff out of the way first.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
18060a8820 swscale/graph: simplify ff_sws_graph_run() API
There's little reason not to directly take an SwsImg here; it's already an
internally visible struct.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
e1fd274706 swscale/graph: check output plane pointer instead of pixel format
To see if the output buffers are allocated or not.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-23 19:39:17 +00:00
Niklas Haas
e96332cb65 swscale/ops: add ff_sws_op_list_is_noop()
And use it in ff_sws_compile_pass() instead of hard-coding the check there.
This check will become more sophisticated in the following commits.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-02-19 19:44:46 +00:00
Niklas Haas
d5174f9e5b swscale/format: add source format info to ff_sws_encode_colors()
Specifically, I need access to this for generating a better dither matrix.
2025-12-15 14:31:58 +00:00
Arpad Panyik
ef651b84ce swscale: Refactor XYZ+RGB state and add function hooks
Prepare for xyz12Torgb48 architecture-specific optimizations in
subsequent patches by:
 - Grouping XYZ+RGB gamma LUTs and 3x3 matrices into SwsColorXform
   (ctx->xyz2rgb and ctx->rgb2xyz), replacing scattered fields.
 - Dropping the unused last matrix column giving the same or smaller
   SwsInternal size.
 - Renaming ff_xyz12Torgb48 and ff_rgb48Toxyz12 and routing calls via
   the new per-context function pointer (ctx->xyz12Torgb48 and
   ctx->rgb48Toxyz12) in graph.c and swscale.c.
 - Adding ff_sws_init_xyzdsp and invoking it in swscale init paths
   (normal and unscaled).
 - Making fill_xyztables public to ease its setup later in checkasm.

These modifications do not introduce any functional changes.

Signed-off-by: Arpad Panyik <Arpad.Panyik@arm.com>
2025-12-05 10:28:18 +00:00
Niklas Haas
4ec2bffe62 configure: allow disabling experimental swscale code
In theory we can also expand this to disable e.g. experimental codecs.
2025-09-01 19:28:36 +02:00
Niklas Haas
cc42bc1f4b swscale/graph: allow experimental use of new format handler
The humor originally contained in this commit message has been
redacted to comply with the strict FFmpeg code quality standards.
2025-09-01 19:28:36 +02:00
Niklas Haas
c18676aae4 swscale/graph: pass per-pass image pointers to setup()
This behavior had no real justification and was just incredibly confusing,
since the in/out pointers passet to setup() did not match those passed to
run(), all for what is arguably an exception anyways (the palette setup).
2025-09-01 19:27:53 +02:00
Niklas Haas
4ede75b5f4 swscale/graph: fix double-free when legacy pass fails initializing
If this function returns an error after ff_sws_graph_add_pass() has been
called, and the pass->free callback is therefore already set up to free the
context, the graph will end up freed twice: once by the pass->free callback
(during ff_sws_graph_free()), and once before that by failure path of the
caller (e.g. add_legacy_sws_pass(), or init_legacy_subpass() itself for
cascaded contexts.)

The solution is to redefine the ownership of SwsGraph to pass clearly from
the caller of add_legacy_sws_pass() to init_legacy_subpass(), which can then
deal with appropriately freeing the context conditional on whether or not the
pass was already registered in the pass list.

Reported-by: 김영민 <kunshim@naver.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2025-08-29 13:22:03 +00:00
Timo Rothenpieler
262d41c804 all: fix typos found by codespell 2025-08-03 13:48:47 +02:00
Niklas Haas
d95944786e swscale/graph: move vshift() and shift_img() to shared header
I need to reuse these inside `ops.c`.
2025-05-18 14:39:57 +02:00
Niklas Haas
bc9696bff8 swscale/graph: make noop loop more robust
The current loop only works if the input and output have the same number
of planes. However, with the new scaling logic, we can also optimize into a
noop the case where the input has extra unneeded planes.

For the memcpy fallback to work in these cases we have to instead check if
the *output* pointer is set, rather than the input pointer.
2025-05-18 14:37:33 +02:00
Niklas Haas
51e912466f swscale/graph: expose ff_sws_graph_add_pass
So we can move pass-adding business logic outside of graph.c.
2025-05-18 14:37:33 +02:00
Niklas Haas
ae84aa775f swscale/utils: split off format code into new file
utils.c is getting quite crowded, and I need a new place to dump a lot of
format handling code for the ongoing rewrite. Rather than bloating this file
even more, start splitting format handling helpers off into a new file.

This also renames the existing utils.h header, which didn't really contain
anything except the SwsFormat definition anyway (the prototypes for what should
have been in utils.h are all still in the legacy swscale_internal.h).
2025-03-14 19:50:44 +01:00
James Almer
268d0b6527 swscale/graph: copy scaler_params to the legacy subpass context
Fixes ticket #11448.

Signed-off-by: James Almer <jamrial@gmail.com>
2025-02-07 13:17:37 -03:00
Andreas Rheinhardt
4973bb661e swscale/cms,graph,lut3d: Use ff_-prefix, don't export internal functions
Symbols with the sws_* prefix are exported.

Reviewed-by: Alexander Strasser <eclipse7@gmx.net>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2025-01-12 15:41:39 +01:00
Niklas Haas
6da940e118 swscale/graph: allow dynamically updating HDR metadata
Without triggering a full graph reinit.
2024-12-23 12:33:43 +01:00
Niklas Haas
efff80c8f6 swscale/graph: add color mapping pass
This leverages the previously introduced color management subsystem in order
to adapt between transfer functions and color spaces, as well as for HDR tone
mapping.

Take special care to handle grayscale formats without a colorspace
gracefully.
2024-12-23 12:33:43 +01:00
Niklas Haas
45f0a7ad33 swscale: add ICC intent enum and option
This setting can be used to infuence the type of tone and gamut mapping used
internally when color space conversions are required. As discussed at VDD'24,
the default was set to relative colorimetric clipping, which is approximately
associative, surjective and idempotent. As such, it roundtrips well, although
it is strictly speaking not associative on out-of-gamut colors.
2024-12-23 12:33:43 +01:00
Niklas Haas
79452d382f swscale/graph: fix memleak of cascaded graphs
Just free them directly and discard the parent context.

Fixes: bf738412e8
Signed-off-by: Niklas Haas <git@haasn.dev>
Sponsored-by: Sovereign Tech Fund
2024-12-04 11:38:30 +01:00
Niklas Haas
bf738412e8 swscale/graph: add new high-level scaler dispatch mechanism
This interface has been designed from the ground up to serve as a new
framework for dispatching various scaling operations at a high level. This
will eventually replace the old ad-hoc system of using cascaded contexts,
as well as allowing us to plug in more dynamic scaling passes requiring
intermediate steps, such as colorspace conversions, etc.

The starter implementation merely piggybacks off the existing sws_init() and
sws_scale(), functions, though it does bring the immediate improvement of
splitting up cascaded functions and pre/post conversion functions into
separate filter passes, which allows them to e.g. be executed in parallel
even when the main scaler is required to be single threaded. Additionally,
a dedicated (multi-threaded) noop memcpy pass substantially improves
throughput of that fast path.

Follow-up commits will eventually expand this to move all of the scaling
decision logic into the graph init function, and also eliminate some of the
current special cases.

Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
2024-11-25 11:02:16 +01:00