This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit cb032dc37b394dc21f31f03942604cbdc40ecf81
Author:     lusoris <[email protected]>
AuthorDate: Fri Oct 30 14:38:31 2026 +0100
Commit:     Lynne <[email protected]>
CommitDate: Sat Nov 7 17:01:26 2026 +0000

    avutil/hwcontext_vulkan: keep frame internals after failed CUDA imports
    
    A failure while importing a frame's memory or semaphores into CUDA freed
    all of its internal state. The frame stays in its pool, so the next
    transfer on it crashed locking the freed update_mutex, and every other
    use of the frame would have done the same.
    
    Release only the partial CUDA import, clear the handles so the next
    transfer imports again, and take the image back from the external queue.
    
    Signed-off-by: lusoris <[email protected]>
---
 libavutil/hwcontext_vulkan.c | 87 +++++++++++++++++++++++++++-----------------
 1 file changed, 53 insertions(+), 34 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 43baef0cef..023b11224e 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -2403,6 +2403,51 @@ static int alloc_mem(AVHWDeviceContext *ctx, 
VkMemoryRequirements *req,
     return 0;
 }
 
+#if CONFIG_CUDA
+static void vulkan_free_internal_cuda(AVVkFrameInternal *internal)
+{
+    AVHWFramesContext *cuda_fc;
+    AVHWDeviceContext *cuda_cu;
+    AVCUDADeviceContext *cuda_dev;
+    AVCUDADeviceContextInternal *cu_internal;
+    CudaFunctions *cu;
+    int planes;
+
+    if (!internal->cuda_fc_ref)
+        return;
+
+    cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data;
+    planes = av_pix_fmt_count_planes(cuda_fc->sw_format);
+    cuda_cu = cuda_fc->device_ctx;
+    cuda_dev = cuda_cu->hwctx;
+    cu_internal = cuda_dev->internal;
+    cu = cu_internal->cuda_dl;
+
+    for (int i = 0; i < planes; i++) {
+        if (internal->cu_sem[i])
+            CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i]));
+        if (internal->cu_mma[i])
+            CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i]));
+        if (internal->ext_mem[i])
+            CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i]));
+        internal->cu_sem[i]   = NULL;
+        internal->cu_mma[i]   = NULL;
+        internal->cu_array[i] = NULL;
+        internal->ext_mem[i]  = NULL;
+#ifdef _WIN32
+        if (internal->ext_sem_handle[i])
+            CloseHandle(internal->ext_sem_handle[i]);
+        if (internal->ext_mem_handle[i])
+            CloseHandle(internal->ext_mem_handle[i]);
+        internal->ext_sem_handle[i] = NULL;
+        internal->ext_mem_handle[i] = NULL;
+#endif
+    }
+
+    av_buffer_unref(&internal->cuda_fc_ref);
+}
+#endif
+
 static void vulkan_free_internal(VulkanDevicePriv *p, AVVkFrame *f)
 {
     av_unused AVVkFrameInternal *internal = f->internal;
@@ -2412,31 +2457,7 @@ static void vulkan_free_internal(VulkanDevicePriv *p, 
AVVkFrame *f)
         return;
 
 #if CONFIG_CUDA
-    if (internal->cuda_fc_ref) {
-        AVHWFramesContext *cuda_fc = (AVHWFramesContext 
*)internal->cuda_fc_ref->data;
-        int planes = av_pix_fmt_count_planes(cuda_fc->sw_format);
-        AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
-        AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
-        AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
-        CudaFunctions *cu = cu_internal->cuda_dl;
-
-        for (int i = 0; i < planes; i++) {
-            if (internal->cu_sem[i])
-                CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i]));
-            if (internal->cu_mma[i])
-                CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i]));
-            if (internal->ext_mem[i])
-                CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i]));
-#ifdef _WIN32
-            if (internal->ext_sem_handle[i])
-                CloseHandle(internal->ext_sem_handle[i]);
-            if (internal->ext_mem_handle[i])
-                CloseHandle(internal->ext_mem_handle[i]);
-#endif
-        }
-
-        av_buffer_unref(&internal->cuda_fc_ref);
-    }
+    vulkan_free_internal_cuda(internal);
 #endif
 
     if (internal->drm_sync_sem != VK_NULL_HANDLE)
@@ -4275,7 +4296,9 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
     return 0;
 
 fail:
-    vulkan_free_internal(p, dst_f);
+    /* Only the import failed: the frame is still valid and stays in its pool,
+     * and the next transfer starts the import over. */
+    vulkan_free_internal_cuda(dst_int);
     return err;
 }
 
@@ -4311,10 +4334,8 @@ static int 
vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc,
         return err;
 
     err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst);
-    if (err < 0) {
-        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-        return err;
-    }
+    if (err < 0)
+        goto fail;
 
     dst_int = dst_f->internal;
 
@@ -5240,10 +5261,8 @@ static int 
vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
         return err;
 
     err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src);
-    if (err < 0) {
-        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
-        return err;
-    }
+    if (err < 0)
+        goto fail;
 
     dst_int = dst_f->internal;
 

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to