PR #23809 opened by KawaiiEngine URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23809 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23809.patch
`cuda_transfer_data()` can enqueue asynchronous copies for earlier planes before a later source or destination `cuArrayGetPlane()` lookup, or a later `cuMemcpy2DAsync()`, fails. The current error exits pop the CUDA context and return while that earlier work may still reference caller-owned frame buffers. Track whether at least one copy was successfully queued. On those later pre-completion errors, perform a best-effort stream synchronization before context cleanup. The primary lookup/enqueue error remains the return value; cleanup synchronization and `cuCtxPopCurrent()` errors remain log-only. Successful H2D and D2D transfers remain asynchronous. The existing host download synchronization path is unchanged. Validation: - CUDA-enabled MSVC `libavutil` rebuild passed without warnings. - Real CUDA NV12 H2D/D2H round trip passed on an NVIDIA GeForce RTX 4060 Laptop GPU (driver 610.62). - A deterministic function-table harness passed 14/14 cases, including later source/destination CUarray-plane lookup failures, later copy-enqueue failure, cleanup-sync failure, context-pop failure, successful H2D/D2D, and successful host download. - Successful H2D and D2D traces were `PCCO`, with no stream synchronization. - `git diff --check` and `tools/patcheck` passed. - The available FATE subset passed: 159 tests; `SAMPLES` was not configured. >From 9df9905a2a4ce91eb646274672f52f47cf4437a7 Mon Sep 17 00:00:00 2001 From: "KawaiiEngine (Sashimiso)" <[email protected]> Date: Wed, 15 Jul 2026 05:39:29 +0900 Subject: [PATCH] avutil/hwcontext_cuda: drain queued copies on transfer error cuda_transfer_data() can enqueue copies for earlier planes before a later cuArrayGetPlane() or cuMemcpy2DAsync() fails. Returning at that point can let queued work outlive caller-owned AVFrame buffers. Track whether a copy was successfully queued and synchronize the stream on these later failures. Synchronization is best-effort: its errors and cuCtxPopCurrent() errors stay logged without replacing the primary failure. Successful H2D and D2D transfers remain asynchronous, and the normal host-download synchronization path is unchanged. Signed-off-by: KawaiiEngine (Sashimiso) <[email protected]> --- libavutil/hwcontext_cuda.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index 61fbf52885..93c68fb051 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -520,7 +520,7 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, CudaFunctions *cu = hwctx->internal->cuda_dl; CUcontext dummy; - int i, ret; + int i, ret, copy_queued = 0; { enum AVPixelFormat src_fmt = cuda_frame_hw_format(src); @@ -578,7 +578,7 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, src_is_nonplanar_cuarray = 1; } else if (cures != CUDA_SUCCESS) { ret = CHECK_CU(cures); - goto exit; + goto fail; } cpy.srcMemoryType = CU_MEMORYTYPE_ARRAY; @@ -601,7 +601,7 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, dst_is_nonplanar_cuarray = 1; } else if (cures != CUDA_SUCCESS) { ret = CHECK_CU(cures); - goto exit; + goto fail; } cpy.dstMemoryType = CU_MEMORYTYPE_ARRAY; @@ -613,7 +613,8 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream)); if (ret < 0) - goto exit; + goto fail; + copy_queued = 1; if (src_is_nonplanar_cuarray || dst_is_nonplanar_cuarray) break; @@ -625,6 +626,9 @@ static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, goto exit; } +fail: + if (ret < 0 && copy_queued) + CHECK_CU(cu->cuStreamSynchronize(hwctx->stream)); exit: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
