depth==8 routes to threshold8_neon (16 bytes/chunk); depth > 8 to
threshold16_neon (8 shorts/chunk, covering 9/10/12/14/16). C is not
auto-vectorized: four independent input streams defeat clang's
vectorizer. Per chunk the NEON kernel is cmhs+bsl.
checkasm --bench, Apple M1 (clang), speedup vs C:
threshold8 15.0x
threshold10 8.1x
threshold12 8.2x
threshold16 8.2x
Signed-off-by: DROOdotFOO <drew@axol.io>
ff_threshold{8,16}_{sse4,avx2} iterate in fixed 16-/32-byte chunks
and over-read/-write past w when w is not a multiple of mmsize.
Split the row at the largest mmsize multiple and run a C tail for
the remainder. Strengthen the checkasm test: sweep widths 1..w-1,
0xAA-sentinel output buffers, multi-row, distinct per-pointer
linesizes, and add depth 10/12 coverage.
Signed-off-by: DROOdotFOO <drew@axol.io>
Without engine_type, frc_amf uses the runtime's default DX12 engine even
on a DX11 AMF context. The interpolated frames then come back as DX12
surfaces, and the filter runs about three times slower. Select
FRC_ENGINE_DX11 on a DX11 context whose device has feature level 11_1 or
higher, and keep an explicit engine_type. The DX11 engine fails Init()
on 11_0, which is what hwcontext_d3d11va creates, so those devices keep
the default.
Assisted-by: Claude Opus 5.5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
fill_model_input_tf() pops a LastLevelTaskItem from lltask_queue and
stores it in request->lltask, but nothing frees it once the inference
has completed. The next fill_model_input_tf() on the same request just
overwrites the pointer, so only the last lltask of each request is
released, by destroy_request_item() when the model is freed. Every
inference therefore leaks one lltask, apart from the last one of each
of the nireq requests, with both async=0 and async=1.
Free it in infer_completion_callback() before the request is pushed
back to request_queue, as the OpenVINO backend does in its completion
callback. Also free it on the failure paths of execute_model_tf() and
dnn_flush_tf(), where the popped lltask is dropped in the same way. No
inference thread is running on any of these paths. av_freep() resets
the pointer, so the av_freep() in destroy_request_item() is still safe.
Signed-off-by: Jake Fineman <jake@wave.online>
Extend scale_d3d12 from NV12/P010 resizing to full pixel format and
color space conversion, matching what the D3D12 video processor is
actually capable of.
- Support converting to/from the semi-planar YUV formats (nv12, p010,
p012) and the packed RGB formats (bgra, rgba, x2bgr10, rgbaf16),
when the hardware supports it.
- Add out_color_matrix, out_range, out_color_primaries and
out_color_transfer options.
- Recalculate sample_aspect_ratio and drop size-dependent side data
on resize.
- Harden GPU teardown/reconfiguration.
Example usage:
Convert a d3d12 NV12 surface to BGRA:
scale_d3d12=format=bgra
Convert an HDR10 (P010) surface to 10-bit RGB, without altering
its HDR color properties:
scale_d3d12=format=x2bgr10
Scale and convert to full-range BGRA:
scale_d3d12=format=bgra:out_range=full
Signed-off-by: younengxiao <steven.xiao@amd.com>
The filter allocates two int64_t arrays with one entry per output
pixel, plane_f and plane_g, but nothing reads or writes them. Remove
them. The output is unchanged.
Noticed during a review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
Replace the deprecated pl_tone_map_params.param field with
pl_color_map_params.tone_constants
This allows configuring each tonemapping algorithm independently, rather
than relying on a single algorithm-specific parameter.
Update the documentation to describe the new options and their defaults.
Also deprecate the vf_libplacebo tonemapping_param option as well.
The output buffer only needs one line now, and the input buffer half a
frame plus five lines. Both were as big as a whole frame.
For 1080p yuv420p this saves about 115 MB with 10 filter threads and
about 4 MB with one. The output is unchanged.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
Compute and write one line at a time instead of filling a float buffer
for the whole slice first. The read and write helpers now work on one
line, so they no longer need strides and a height.
The output is unchanged.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
filter_slice() read the input lines with seven separate calls: three
above the slice, one for the slice and three below. Use one loop that
clamps the line number to the kept field.
The output is unchanged.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
filter_slice() split each plane into height / 2 pairs of lines, so the
last line of a plane with an odd height was never written. For 720x486
yuv420p that is the last line of both chroma planes. For very small
frames (gray with a height of 1, 4:2:0 with a height of 2 or less) no
job ran and nothing was written at all.
With odd heights the bottom edge was also clamped to a line of the
wrong field, and the output changed with the number of threads.
Use (height + 1) / 2 pairs, clamp to the first and last line of the
kept field, and always run at least one job. The output for even
heights is unchanged, except in frames where no job ran.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
The prescreener flags are only written when a prescreener is used. If
pscrn is changed to none at runtime, the flags of the previous frames
stayed in the buffer, so the predictor skipped those pixels and the
output was wrong. Clear the flags when pscrn is none.
Checked by switching pscrn with sendcmd: the frames after the switch
now match a run that started with pscrn=none.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
read_bytes() and read_words() pad each line with 32 mirrored samples
on both sides. For a plane narrower than 32 samples they read before
the start and past the end of the line. Clamp the indices. The output
for wider planes is unchanged.
Found with ASan on gray 16x16 and on the chroma of yuv420p 48x32.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
process_new() writes the prescreener flags four at a time, but the
buffer was only as wide as the plane. If the width is not a multiple
of four, up to three flags were written past the end of it.
Found with ASan using the default settings, for example on gray
321x120.
Found during a code review sweep of ffmpeg using an LLM.
Signed-off-by: romainhedouin <romain.hedouin@epitech.eu>
This filter takes a scene graph in the libplacebo scene JSON format and
exposes it as a filter. The number of inputs and their properties are
determined by the scene graph.
I decided to make this a separate filter because it invalidates most of
the existing options, including e.g. the existing scaling and fitting logic.
For simplicity, scene graphs are always assumed to have a fixed canvas size,
which the user continues specifying at init time.
Requires libplacebo API version 386 or newer, which we probe the existence
for as a separate capability so we can selectively expose the filter.
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Forces the output sample aspect ratio, instead of deriving it from the
input.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
So they can be shared with other filters in this file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Without a reference frame, only the properties derived from the output link
and the filter options are set.
Note that the conditional stripping flags (including `progressive`) are
only needed if we are copying from the ref frame; as a plain allocated
AVFrame would never have this side data / flags otherwise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Handle Dolby Vision right after copying the frame properties, before the
output link properties. No functional change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Move the output frame property setup out of output_frame(), unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
So config_input() can simply set up the GPU for every input, rather than
tracking whether the device still needs to be inherited.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
inherit_device() sets the filter's own device to the one of the input, so
choose_default_device() picks it up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Separates creating the Vulkan device from the filter-specific setup that
depends on it, so the former can be shared with other filters in this file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Move the log, shader cache and output format setup out of
libplacebo_init(), so it can be shared with other filters in this file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
The per-frame SAR disagreed with the output link: reset_sar (and thus also
normalize_sar and multiple inputs) forwarded the input SAR instead of 1:1,
and fit modes other than fill always stretched it. The frames are rendered
according to the link SAR, so use that.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
These options default to -1 (auto), but were only applied when positive,
so e.g. colorspace=gbr or range=unspecified were silently ignored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Only the status of the input ending last was forwarded, so an error on a
shorter input was reported as an ordinary EOF if a longer input ended
normally. Keep forwarding the most recent status, but prefer errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Uses ff_scale_eval_dimensions() and ff_scale_adjust_dimensions(), so linking
fails with the scale filters disabled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sponsored-by: nxtedition AB
Signed-off-by: Niklas Haas <git@haasn.dev>
Fixes: signed integer overflow
Fixes: out of array write
Fixes: 4T4QtWPFfCiD
Fixes: Depthfirst issue 019f3b84-908c-7752-be91-62fb35f8911e
Out of array write Replicated through UnModified FFmpeg with ASAN and UBSAN
The out of array write is a regression since 4e0a8b745a, the overflow
of the sum is older.
Found-by: Michael Niedermayer <michael@niedermayer.cc> using Depthfirst
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This is a new API that offers two improvements over the existing field:
1. It allows setting a different limit per media type
2. It allows updating the limit after the graph has been configured, as
long as this would not cause already existing frames to exceed the limit
I'm not sure if the second point is ever useful, but it's easy to implement
regardless.
Because the old field will be deprecated, the new API just overrides the old
value wholesale. The alternative was to respect both (i.e. use the smaller
of the two limits); but this way, callers can use the new API to e.g.
selectively uncap the limit on audio frames while remaining backwards
compatible with older libavfilter.
Explicitly set limits are tracked separately, so that avfilter_graph_config()
re-derives all other limits from the old field on every call.
Signed-off-by: Niklas Haas <git@haasn.dev>
Minor semantic change to prepare for the upcoming commits.
This shouldn't regress anything because the new behavior is strictly more
permissive than the old behavior, and the distinction is only relevant
for the uncommon case of combined audio-video filters.
Signed-off-by: Niklas Haas <git@haasn.dev>
Fixes: signed integer overflow
Found during triage/review of the security report fH770hlenwcI
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN
Fixes: signed integer overflow
Found during triage/review of the security report fH770hlenwcI
Signed integer overflow Replicated through UnModified FFmpeg with UBSAN
Fixes: heap buffer overflow (write)
Fixes: fH770hlenwcI/testcase/repro.sh
Fixes: fH770hlenwcI
Found-by: Michael Niedermayer <michael@niedermayer.cc> using Depthfirst
Out of array write Replicated through UnModified FFmpeg with ASAN
The linear RGB to RGB matrix is stored as int16 with 14 fractional
bits, so a coefficient of 2 or more wraps around. The conversion from
the XYZ basis of SMPTE ST 428-1 to BT.709 has one of 3.15, and a
neutral (126, 128, 128) came out as (99, 143, 64). Check the
coefficients before narrowing them and refuse the conversion. Fast mode
does not use the matrix and is not checked, and a refused conversion
forgets the primaries, so that the next frame is refused too instead of
using the matrix left behind.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
The matrix columns were the primaries scaled to Y = 1, x/y and
(1 - x - y)/y, and were then rescaled to fit the white point, so the
division by y cancels out. 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>
With input_resizable enabled, get_output_ov() created partial_shape with
ov_partial_shape_create() and then passed the same variable to
ov_shape_to_partial_shape(), which allocates a new dims array and
overwrites the struct. The first allocation was never freed, so every
call leaked it, on the success path and on the two error returns in
between. The dims it was built from were never used.
Drop the ov_partial_shape_create() call and the dims array; the partial
shape is built from the model's input shape by ov_shape_to_partial_shape()
and freed after ov_model_reshape_single_input() as before.
The leak was introduced with the OpenVINO API 2.0 support in e79bd1f1b1.
Signed-off-by: Jake Fineman <jake@wave.online>
In backward mode the gain is 1 / factor, but the factor is 0 for pixels
farther than dmax from the center (possible with x0/y0 or aspect), so
the gain is inf. inf * sample, or inf * 0 = NaN, is then converted to
int, which is undefined behaviour; on x86 these pixels come out black
instead of saturated.
For angles close to PI/2, the factor can also become small enough that
a finite backward gain produces sample values outside the range of int
before av_clip_uint8() is called. Bound the gain at 256 to keep these
conversions in range while preserving the saturated 8-bit output.
Signed-off-by: Martin Mirchev <mmirchev@comp.nus.edu.sg>
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: 6c89a30ecdFixes: #25419
Assisted-by: Fairy