Commit Graph
3852 Commits
Author SHA1 Message Date
Greg Falcon dace243da8 swscale/aarch64: fix signed load in yuv2planeX_10
The horizontal scaler intermediate buffer holds signed 16-bit samples
that can be negative when scaling with filters that have negative lobes
(such as bicubic). The 16-pixel and 8-pixel NEON vector loops in
ff_yuv2planeX_10_neon treat src as signed int16_t via smlal, but the
scalar tail loop for remaining (dstW % 8) pixels used unsigned ldrh
before sxtw, interpreting negative intermediate values as large positive
values around 65536 and saturating output pixels.

Use ldrsh instead of ldrh so negative intermediate samples are properly
sign-extended in the scalar tail loop.

Signed-off-by: Marvin Scholz <epirat07@gmail.com>
2026-11-03 21:19:50 +00:00
Kacper Michajłow b8f362cea4 swscale/uops: check every product of an input before fusing it
exact_prod() only checked the products with the two ends of the input
range, so a coefficient times inputs in [0, 1] or [0, 2] passed as
exact although the values in between are not, and with SWS_BITEXACT the
x86 backend fused those products with FMA where the C backend rounds
them. A product is exact for every input when the coefficient is a power
of two, or when the inputs are integers whose bits fit in the
significand next to those of the coefficient.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-11-02 18:19:15 +00:00
Kacper Michajłow 7626d21bf9 swscale/uops: round every float operation of the reference backend
With x87 math the compiler keeps the intermediate results of an
expression with excess precision. Round them, so that they produce the
same results.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-11-02 18:19:15 +00:00
Kacper Michajłow 29c5dba781 swscale/ppc: build the AltiVec and VSX files only when enabled
Without AltiVec and VSX the *_altivec.c and swscale_vsx.c files only
build init functions with empty bodies that are never called. Build
them as ALTIVEC-OBJS and VSX-OBJS and drop their HAVE_ALTIVEC and
HAVE_VSX checks.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-11-02 07:24:04 +00:00
Kacper Michajłow 9ff448c18a swscale/ppc: check the CPU flags outside the AltiVec files
The PPC init functions run on every CPU to check whether AltiVec and VSX
are available, so they must not be built with the AltiVec and VSX flags
that the code next to them needs. Move the checks to swscale.c,
yuv2rgb.c and yuv2yuv.c, which hold no AltiVec code and call init
functions in the AltiVec and VSX files after them.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-11-02 07:24:04 +00:00
Kacper Michajłow 1cfb18f66f swscale/ppc: set up the coefficient banks outside the AltiVec code
ff_sws_init_altivec_bufs() and ff_sws_free_altivec_bufs() run for every
context on every CPU and fill the banks with plain C. Keep the bank
pointers in SwsInternal as pointers to arrays of 8 int16_t, which need
no AltiVec header, and move the two functions to a file without AltiVec
code.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-11-02 07:24:04 +00:00
Niklas HaasandClaude Opus 5.5 17a4a474f4 swscale: build and run ops tests unconditionally
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-30 10:55:13 +00:00
Niklas HaasandClaude Opus 5.5 47ff145f60 swscale: compile ops code unconditionally
The ops backends remain disabled by default at runtime, and are only
auto-selected with SWS_UNSTABLE (or explicitly via the backends option).

The SPIR-V backend still depends on CONFIG_UNSTABLE.

The main motivating reason here is the fact that the test framework itself
wants to depend on formats only properly introduced by the new unstable
ops code. It also means we can start preferring the ops path for format
conversions that are wholly unsupported otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-30 10:55:13 +00:00
Niklas HaasandClaude Opus 5.5 9bbaa0cdd8 configure: make swscale_vulkan depend on unstable
The SPIR-V backend is built on top of the ops code, which is only compiled
with CONFIG_UNSTABLE. Express this dependency in configure instead of
guarding the vulkan Makefile include and ff_sws_vk_init() call separately.

This also fixes linking with --disable-unstable when vulkan is enabled, as
graph.c referenced ff_sws_vk_device_ref() from the excluded vulkan objects.

Fixes: 51d4406e07 ("swscale/graph: support allocating hardware intermediate frames")
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-30 10:55:13 +00:00
Niklas HaasandClaude Opus 5.5 914e454559 swscale/uops: skip printing uop lists below the log level
As for op lists, avoid formatting the names of all uops when av_log()
discards them anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-29 15:47:35 +00:00
Niklas HaasandClaude Opus 5.5 bcf6712d01 swscale/uops: factor out ff_sws_uop_list_print()
The same loop was duplicated in three backends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-29 15:47:35 +00:00
Niklas Haas a16257e454 swscale/ops: clamp lev_extra >= lev
This doesn't make sense to pass otherwise, but the clamp is cheap.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-29 15:47:35 +00:00
Niklas Haas 484ccc1066 swscale/ops: skip printing op lists below the log level
ff_sws_op_list_print() formatted every op even when av_log() then
discarded the result. Op lists are printed during every graph setup, so
at the default log level this took about a quarter of the swscale
self-test runtime.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-29 15:47:35 +00:00
Jun Zhao 31ba826726 swscale/tests: cover chroma range conversion with FATE references
Print intermediate chroma results for both range directions at
8/9/10/12/14/16 bits, including neutral and nearby values. Test both
planes with the C and available native implementations, and keep
expected values in tests/ref/fate/sws-range-convert.

Based on the test implementation from Forgejo_Fairy in PR #25549.

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-10-29 03:10:43 +00:00
Jun Zhao eb59f938ae swscale/range_convert: preserve chroma center in range conversion
solve_range_convert() anchored the range conversion offset at the upper
endpoint (src_max -> dst_max). For chroma, mapping the limited-range
interval [16, 240] to the full-range interval [0, 255] via the upper
endpoint shifts the neutral chroma center (128 << (bit_depth - 8)) to
127.5 in 8-bit units.

After 4bee010844 added the fixed-point rounding bias, that -0.5 LSB
shift canceled out the final output rounding bias for colored chroma,
leaving a systematic -0.5 LSB truncation bias in full-range chroma and
causing neutral gray to still round down to 127 on the x86 4:2:0 vertical
filter path.

Per ITU-T H.273 Section 8.3, the achromatic chroma center is
128 << (bit_depth - 8) in both limited and full range. Anchor the chroma
range conversion offset at the neutral chroma center while keeping the
luma offset anchored at the upper endpoint.

Based on the root-cause analysis and patch from Forgejo_Fairy and alec
in issues #24005 and #25521.

Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24005
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/25521
Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-10-29 03:10:43 +00:00
Kacper Michajłow 8e362b7b51 swscale: scale X'Y'Z' to X'Y'Z' on the codes
A scaled conversion between two XYZ formats decoded the codes into
gamma 2.2 RGB, scaled that and encoded it back, which quantizes twice
and clips every color outside the BT.709 gamut. Scale the codes like
those of an RGB format instead, as the unscaled conversion already did,
and round the result to 12 bits, which keeps the 4 padding bits zero.
The slice contexts of the graph take the XYZ flags of their parent for
that.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Kacper Michajłow b1d7f78211 swscale: build the X'Y'Z' tables from the transfer functions of lavu
The tables were computed from the exponents 2.6 and 2.2 written into
the code. Build them from the lavu functions of SMPTE ST 428-1 and
gamma 2.2 instead, normalized to the top code of each curve with the
peaks in the matrix as before, so that the conversion can be set up for
any tagged transfer. The values are unchanged.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Kacper Michajłow 61ae1901c7 swscale: scale the X'Y'Z' conversion as SMPTE ST 428-1 defines it
The gamma tables put the top code of X'Y'Z' at linear 1.0, so the
48 cd/m2 reference white of a DCDM, code 3960, came out at 0.918, about
8 percent dark. ST 428-1 (H.273 transfer 17) puts 52.37 cd/m2 at the top
code, L = 52.37/48 * V^2.6, so that the white lands on 1.0 and the codes
above it are headroom. Fold the factor into the matrices, since the X and
Z of a white exceed 1.0 and a 16-bit table cannot hold them: the headroom
clips in RGB after the matrix, and RGB white encodes to code 3960.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Kacper Michajłow af885b9b2f swscale: compute the X'Y'Z' matrices from the BT.709 primaries
The matrices were rounded by hand from constants that do not quite
match the BT.709 chromaticities, the largest coefficient is off by 5
in Q12.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Kacper Michajłow df0f1ca84e swscale: name the XYZ12 table setup after SMPTE ST 428-1
The XYZ12 formats are converted with the 2.6 power of ST 428-1 (DCDM)
whatever a frame is tagged with, the path is chosen by the pixel format
alone and there is no other XYZ in swscale. Say so in the name of the
table setup, to make clear that it's ST 428.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Kacper Michajłow c206b1fdd7 swscale/csputils: derive the RGB to XYZ matrix without dividing by y
ff_sws_rgb2xyz built its columns from X/Y and Z/Y of each primary and
then solved for the scale that fits the white point, so the division by
y cancels out, while av_div_q by y = 0 turned the matrix into infinities
and NaNs. Use the xyz chromaticity vectors directly, which gives the
same matrix and also works for a primary with y = 0, such as the Z axis
of the CIE 1931 XYZ.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-10-28 19:22:28 +00:00
Niklas Haas 28fda48e0b Revert "swscale/tests/swscale: don't bail on ENOTSUP in auxiliary conversions"
This reverts commit 60c8273b35.

No longer needed work-around (see previous commit).

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-28 15:32:15 +00:00
Niklas Haas 80a94eb669 Revert "swscale: treat XYZ formats as colorspace-less in color (de|en)coding"
This reverts commit 2ed5830108.
This was wrong from the beginning, leading to the mess we're in.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-28 15:32:15 +00:00
Niklas Haas 2c5f0d5f89 swscale/format: mark XYZ formats as unsupported
Regressed by the introduction of planar XYZ formats, which unintentionally
exposed XYZ formats as "supported" in libswscale's unstable path, despite XYZ
formats not yet being supported by the new ops code.

This incomplete partial support was then poorly and incorrectly worked
around by 2ed5830108, a20ae16999 and 60c8273b35. The test framework still
spams errors as a result of these three incomplete work-arounds.

Rather than pile on a third work-around (e.g. skipping XYZ in the test
framework), just do the sensible thing and properly disable support for
formats that are not yet handled correctly by the ops path.

Correct handling will require the introduction of 1D LUTs / TRCs, which
is a larger change on the roadmap.

Fixes: 2983c23762
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-28 15:32:15 +00:00
Ramiro Polla 16efe6927d swscale/vulkan/ops: factor plane count out of loop conditions 2026-10-28 13:05:17 +00:00
Ramiro Polla 345ce5a763 swscale/tests/swscale: factor plane count out of loop condition 2026-10-28 13:05:17 +00:00
Ramiro Polla a9212c2862 swscale: name backend compile callbacks consistently
Name the SwsOpBackend.compile callbacks compile_ops_<backend> and the
SwsOpBackend.compile_uops callbacks compile_uops_<backend>.
2026-10-28 12:32:01 +01:00
Ramiro Polla 8b06553983 swscale: name backend process functions consistently
Name the SwsCompiledOp.func c callbacks process_<backend>.
2026-10-28 12:32:01 +01:00
Ramiro Polla 46248a1400 swscale/vulkan/ops: rename free_fn to spirv_free
Make it consistent with spirv_process.
2026-10-28 12:32:01 +01:00
Niklas Haas a23e094488 swscale/vulkan/ops: implement SWS_UOP_ADD
This replaces 1x1 dither matrices by a constant addition.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Niklas Haas afc7a10081 swscale/vulkan/ops: log compiled micro-ops
Same as the other backends.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Niklas HaasandClaude Opus 5.5 11fec985c3 swscale/vulkan/ops: generate code via SwsUOps
This is still slightly abstraction-violating in that it needs the op list
to set up the plane mapping, image view formats and to know if the source
is interlaced or not. I don't have a good solution to these issues at
the moment, but at the very least, this decouples the actual codegen
from changes to the SwsOp layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Niklas Haas 3a37eb68f4 swscale/uops: correctly mark masked linear rows as identity rows
They are currently emitted identically to an explicit zero row, which is
wrong - a zero row would not be masked as it contains an operation (setting
the component to zero *is* an explicit operation; only leaving it untouched
is an implicit noop).

And also emit a 1 coefficient in the expected location in the data matrix.

I have verified that the resulting x86 and NEON kernels are bit-identical.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Niklas Haas 4f9a85d44c swscale/aarch64/ops: skip over masked SWS_UOP_LINEAR rows
These are entirely unneeded; prerequisite to the following fix, which fixes
the wrong `zero` mask for the masked identity rows.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Niklas Haas 1c03b758a3 swscale/uops: add SWS_UOP_FLAG_PUNNING
The current CPU-based backends don't suffer any penalty or consequence
of intermixing integers and float operations on the same registers. However,
this is not a universal assumption - in particular, SPIR-V expects fully
typed operations.

In theory, older x86 CPUs also have a penalty for switching from float to
int, but ENOCARE.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-27 18:53:16 +00:00
Marvin Scholz 86444dd368 gitignore: add missing entries 2026-10-27 13:37:51 +00:00
Michael Niedermayer a3f1b1e87c avutil/framepool: provide a single copy for static builds
Both libavfilter and libswscale currently put framepool.o in their regular
OBJS, defining the same four ff_frame_pool_* symbols. Loading both static
archives in full therefore fails with multiple definitions.

Move the implementation and internal header to libavutil. Include the
object in its STLIBOBJS when either consumer is enabled, and use SHLIBOBJS
for the private copies in libavfilter and libswscale. This preserves
independent builds and shared-library symbol visibility without adding
an inter-library dependency or exposing a new public API.

Verified whole-archive links with both consumers, and with each consumer
configured independently. Shared builds pass fate-filter-rgbtestsrc-gbrp12
and fate-filter-rgbtestsrc-gbrap12; static and shared video scaling and
audio volume smoke tests produce identical frame checksums. Also checked
static consumers linked against shared dependencies.

Fixes: 6c89a30ecd
Fixes: #25419
Assisted-by: Fairy
2026-10-26 16:53:24 +00:00
Niklas Haas 31855b2a70 swscale/ops_optimizer: mark split scaling intermediates progressive
Interlaced cascaded scaling otherwise skips every second line.
Technically, setting the field to FIELD_TOP here is unnecessary, but it
can't hurt to be explicit.

Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 10:11:09 +00:00
Niklas Haas 464fc8c2ed swscale/uops_macros_gen: fix argument order in the C macro documentation
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 0e49820959 swscale: generate disjoint uop macros for the C and x86 backends
Previously, the uop macros were generated from the union of uops over all
backends, so each backend would also instantiate uops that only the other
one can ever use. Split off a separate "x86" backend, and generate a separate
C header for it, together with its NASM macros in a single pass.

The x86 backend only enables SWS_UOP_FLAG_FMA on CPUs with FMA3, so generate
its uops both with and without FMA.

This does not reduce the checkasm coverage: the uops removed from
uops_macros.h are all LINEAR_FMA, READ_PLANAR_FV_FMA or RW_SHUFFLE, which
checkasm does not test, since the C reference backend cannot run them. The
only tests that disappear are the SSE4 and AVX2 variants of two U8 PERMUTE
kernels, which the x86 backend no longer builds because it never uses them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 6eb7510072 swscale/uops_macros_gen: use a per-backend header include guard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 2fab0667db swscale/uops_macros_gen: add -backend option
Allows generating the set of uops for a specific backend. For now, only a
single "c" backend is defined, which still covers the union of uops used by
all backends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 4e3adb4225 swscale/x86: use NASM uop macros generated by uops_macros_gen
Replaces the hack of running the C preprocessor over the C macros to produce
NASM syntax at build time. The generated file is now committed and checked by
FATE, as with uops_macros.h.

As a side effect, the DECL_* macros are now proper multi-line NASM macros,
so drop the parentheses around their arguments.

The FATE test is split up per generated file, with fate-sws-uops-macros
running all of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 372d0019b3 swscale/uops_macros_gen: add -nasm option
Additionally writes the uops as NASM macros to the given file, as one
DECL_<TYPE>_<UOP> macro per uop group invoking DECL_OP for each uop. This is
an alternative to running the C preprocessor over the C macros.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 5104bf0245 swscale/uops_macros_gen: split uop enumeration from macro generation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 366b9ab690 swscale/uops_macros_gen: share uop param printing between variants
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 ab19678f55 swscale/uops_macros_gen: align struct param formatting with plain variant
Print the hex masks with the same zero padding in both variants, and use
flat designators for the dither params. This prepares for sharing the
printing code between both variants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
Niklas HaasandClaude Opus 5.5 8417c28919 swscale/uops_macros_gen: factor out common uop flags
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
2026-10-25 02:23:01 +00:00
James Almer 5f0a7701c1 Bump minor after branching release/9.1
Signed-off-by: James Almer <jamrial@gmail.com>
2026-10-24 17:05:20 -03:00
James Almer aecf409c18 Bump minor version for release/9.1
Signed-off-by: James Almer <jamrial@gmail.com>
2026-10-24 17:05:20 -03:00