call_kernel() obtains the command buffer and compute encoder from
property getters (mtlQueue.commandBuffer, buffer.computeCommandEncoder),
which return autoreleased references under the non-ARC build, and then
releases them via ff_objc_release(). That is an over-release: when the
enclosing autorelease pool is drained, the objects are released a second
time and the process crashes with EXC_BAD_ACCESS in objc_release.
On current macOS this is reproducible with the ffmpeg CLI itself. The
filter thread's thread-local autorelease pool is popped during pthread
TSD cleanup at thread exit, so any run that used yadif_videotoolbox
crashes when the filter thread terminates:
ffmpeg -init_hw_device videotoolbox=vt -filter_hw_device vt \
-f lavfi -i testsrc2=size=640x480:rate=30 \
-vf setfield=tff,format=nv12,hwupload,yadif_videotoolbox,\
hwdownload,format=nv12 -frames:v 20 -f null -
Thread 11 Crashed:: vf#0:0
0 libobjc.A.dylib objc_release + 16
1 libobjc.A.dylib AutoreleasePoolPage::releaseUntil(objc_object**) + 204
2 libobjc.A.dylib objc_autoreleasePoolPop + 244
3 libobjc.A.dylib objc_tls_direct_base<...>::dtor_(void*) + 156
4 libsystem_pthread.dylib _pthread_tsd_cleanup + 620
5 libsystem_pthread.dylib _pthread_exit + 84
Host applications hit the same crash earlier, for example when a
dispatch queue drains its last-resort pool after a work item that ran
the filter.
Wrap the kernel invocation in @autoreleasepool and drop the manual
releases, making the pool pop the single balanced release and draining
the Metal transients once per frame. The ff_objc_release() calls on the
s->mtl* members in do_uninit() stay: those hold owned references
obtained from new* methods.
(cherry picked from commit 7f2e5cdd7c)
When the filter graph is torn down early (e.g. at EOF with -frames:v),
the main thread calls dnn_free_model and destroys the request queue
while async inference threads may still be running. When a detached
thread finishes and tries to push its result back to the destroyed
queue, it triggers a segmentation fault.
Add ff_dnn_wait_requests() to dnn_backend_common which blocks
until all allocated request items (ctx->nireq) have been safely
returned to the request_queue. Call it from dnn_free_model in the
torch, tensorflow, openvino, and onnx backends before destroying the queue.
(cherry picked from commit b52c71e438)
Co-Authored-by: Fable 5
This fixes#20995. The reference is taken twice and assigned to the same pointer (see above in the same function). Only the latter is needed.
(cherry picked from commit 66a8c37582)
Limit the 8-bit column filter to the pixels remaining in the current slice. Pass slice_end - y at all three call sites so both the 8-bit and high-bit-depth column filters receive the correct remaining width. This handles partial 16-pixel blocks at frame and thread-slice boundaries. The non-column callbacks do not use this argument.
Fixes: #YWH-PGM40646-36
(cherry picked from commit 8b9e02cc17)
A format-only conversion leaves the auto use_filters value unresolved.
Regression since 5d0748243f.
Fix issue #23737
Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
(cherry picked from commit c57660fb18)
Assisted-by: Fairy
Since the input and output format can differ (e.g. 444 -> 420), we need to
reference the correct subsampling for the partially applied filter.
Keep track of this in the CUDATex itself.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 01972b4f85)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Instead of going via an AVFrame at all. This will allow us to fix the
intermediate chroma plane size for split downscaling.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 420a9e90b8)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Instead of re-creating this object every frame.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit e79e9f06ba)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
At this point, s->hwctx and CudaFunctions * are available.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 4289a29bb0)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
I want to disentangle the internal logic from AVFrame, because some
intermediate states (e.g. for partially subsampled chroma with simultaneous
scaling) may not directly map to a valid AVPixelFormat.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit fef976b197)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Make the next commit a bit easier to review.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 61750318db)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
This is already done by cudascale_filter_frame().
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 0c3f04a97c)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
NVDEC and CUVID now output AV_PIX_FMT_P012 (12-bit 4:2:0), AV_PIX_FMT_P212
(12-bit 4:2:2) and AV_PIX_FMT_YUV444P10MSB / AV_PIX_FMT_YUV444P12MSB
(10/12-bit 4:4:4) for high-bit-depth content, but these CUDA filters
rejected the formats in their supported-format lists, breaking pipelines
such as "-hwaccel cuda ... -vf scale_cuda" on 12-bit input.
These formats use 16-bit sample storage, and the filters select their CUDA
kernel by byte-storage size and plane layout, not by the number of valid
bits, so they can reuse the existing 16-bit kernels:
- scale_cuda: P012/P212 -> "semiplanar16", YUV444P10MSB/YUV444P12MSB ->
"planar16".
- transpose_cuda: the ushort/ushort2 kernels are chosen from the pixel
descriptor (byte size + channel count); just allow the new formats.
- thumbnail_cuda: P012 reuses the P010/P016 path and the MSB 4:4:4 formats
reuse the YUV444P16 path; P012 is added to the 4:2:0 chroma-histogram
scaling as well. (thumbnail has no 4:2:2 path, so P212 is not added.)
The CUDA deinterlacers (bwdif_cuda, yadif_cuda) already accept any format
with <= 2 bytes per sample and <= 2 channels, so they need no change. The
8-bit-only filters (overlay_cuda, pad_cuda, bilateral_cuda, chromakey_cuda,
colorspace_cuda) do not support high bit depths and are left untouched.
Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
(cherry-picked from commit df94900c98)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
This may be faster or slower than the existing specialized kernels,
so I opted not to prefer it by default. I also deliberately didn't expose
additional filter function capabilites yet.
The main motivating reason here is to get correct anti-aliasing behavior
when downscaling, which is currently completely broken.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 5d0748243f)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
This can be useful for any sort of separable filtering with arbitrary
weights.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit 469281fa50)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Ignored for now by the existing fixed function kernels.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit d98cc462f6)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
Useful for GPU-based filters, which may also need to compute filter weights.
Since we cannot cross-link to internal functions, we need to recompile this
helper inside libavfilter.c.
Signed-off-by: Niklas Haas <git@haasn.dev>
(cherry-picked from commit b400791442)
Signed-off-by: Marvin Scholz <epirat07@gmail.com>
The supported YUV pixel formats were separated between planar
and semiplanar. This approach reduces the number of CUDA kernels
for all pixel formats.
This patch:
1. Adds support for YUV 4:2:2 planar and semi-planar formats:
yuv422p, yuv422p10, nv16, p210, p216
2. Implements new conversion structures and kernel definitions
for planar and semi-planar formats
Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
Backported-from: 75b8567591
Backporting notes: This patch is basically just re-organizing the internal
code; since I opted not to expand the actual format support list in the
hwcontext itself. This is just to prevent merge conflicts with later
backported commits.
Signed-off-by: Niklas Haas <git@haasn.dev>
If s->stop is set, the return value would be overwritten
before being checked. This bug was introduced in the switch
to AV_TX in 014ace8f98.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
(cherry picked from commit 0992c19c30)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Reproduced with a small output (e.g. size=2x2) under ASan.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit d133b4a231)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This is a behavior preserving change for all non-overflowing cases.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit f7368f97b9)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Slice based filter workers compute their per-thread row/sample/channel
boundaries as total * jobnr / nb_jobs. The total * jobnr product is
evaluated in int and overflows signed int for large dimensions and many
slice threads, before the division by nb_jobs brings it back in range.
(cherry picked from commit 218b4771a3)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
deinterlace_slice() computed per-thread row boundaries with int
multiplication height * (jobnr + 1). With a tall frame and many filter
threads the product overflows signed int before the division by nb_jobs.
Use int64_t for the intermediate product before converting back to int
row indices.
Found-by: Kery (Qi Kery <qikeyu2001@outlook.com>)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 200e0cba67)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Fixes: integer overflow
Fixes: out of array access
Found-by: Claude (Anthropic), reported by Omkhar Arasaratnam <omkhar@linkedin.com>.
(cherry picked from commit 537e87e3c2)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
For glyphs whose source is already in bitmap form (color emoji fonts such
as NotoColorEmoji.ttf), FT_Glyph_To_Bitmap(..., destroy=0) returns the
input pointer unchanged. The result is that glyph->bglyph[idx] aliases
glyph->glyph (and analogously border_bglyph[t] may alias border_glyph).
glyph_enu_free then called FT_Done_Glyph on both, double-freeing the
underlying object.
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit 9efca1d946)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The code as written can add such glyphs in the cache so we need to check
glyphs from the cache too.
This should be the most robust and simple solution
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
(cherry picked from commit c8c4e2d2a5)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
try_push_frame() decides whether an input buffer is already tracked by testing
`j == i` (the channel index) instead of `j == nb_buffers`. Once an earlier
channel shared a buffer, nb_buffers falls behind i and a genuinely new buffer is
never referenced, so it is freed while the output frame still points at it.
Reported by Franciszek Kalinowski (isec.pl / striga.ai) and Bartosz Smigielski.
(cherry picked from commit 461fb22053)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>