PR #24082 opened by Steven Xiao (younengxiao)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24082
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24082.patch

dnn_load_model_onnx() always allocated exactly one ONNXRequestItem,
but dnn_free_model_onnx() waits via ff_dnn_wait_requests() for the
queue to reach ctx->nireq items. Since a7e72069f1 made that wait
block on a condition variable instead of polling, nireq >= 2 now
hangs forever on teardown instead of exiting.

Fix by allocating ctx->nireq items in a loop, matching the
TensorFlow/OpenVINO backends, and normalizing nireq (default 0) to
av_cpu_count() / 2 + 1 beforehand so the loop isn't skipped.

Signed-off-by: younengxiao <[email protected]>



>From e9976eb5d63476d05321f6f79104d157f9ba317b Mon Sep 17 00:00:00 2001
From: younengxiao <[email protected]>
Date: Tue, 11 Aug 2026 12:45:11 -0400
Subject: [PATCH] avfilter/dnn: fix nireq deadlock in ONNX backend

dnn_load_model_onnx() always allocated exactly one ONNXRequestItem,
but dnn_free_model_onnx() waits via ff_dnn_wait_requests() for the
queue to reach ctx->nireq items. Since a7e72069f1 made that wait
block on a condition variable instead of polling, nireq >= 2 now
hangs forever on teardown instead of exiting.

Fix by allocating ctx->nireq items in a loop, matching the
TensorFlow/OpenVINO backends, and normalizing nireq (default 0) to
av_cpu_count() / 2 + 1 beforehand so the loop isn't skipped.

Signed-off-by: younengxiao <[email protected]>
---
 libavfilter/dnn/dnn_backend_onnx.c | 45 +++++++++++++++++-------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/libavfilter/dnn/dnn_backend_onnx.c 
b/libavfilter/dnn/dnn_backend_onnx.c
index 6c75d6eb24..d264a53736 100644
--- a/libavfilter/dnn/dnn_backend_onnx.c
+++ b/libavfilter/dnn/dnn_backend_onnx.c
@@ -25,6 +25,7 @@
 
 #include "libavutil/opt.h"
 #include "libavutil/avassert.h"
+#include "libavutil/cpu.h"
 #include "libavutil/mem.h"
 #include "libavutil/avstring.h"
 #include "libavutil/thread.h"
@@ -726,7 +727,6 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, 
DNNFunctionType func_type,
 {
     DNNModel       *model = NULL;
     ONNXModel *onnx_model = NULL;
-    ONNXRequestItem *item = NULL;
     ONNXOptions  *options = &ctx->onnx_option;
     OrtStatus *status;
 
@@ -973,29 +973,37 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, 
DNNFunctionType func_type,
         }
     }
 
+    if (ctx->nireq <= 0) {
+        // the default value is a rough estimation
+        ctx->nireq = av_cpu_count() / 2 + 1;
+    }
+
     onnx_model->request_queue = ff_safe_queue_create();
     if (!onnx_model->request_queue) {
         goto fail;
     }
 
-    item = av_mallocz(sizeof(ONNXRequestItem));
-    if (!item) {
-        goto fail;
-    }
-    item->lltask = NULL;
-    item->infer_request = onnx_create_inference_request();
-    if (!item->infer_request) {
-        av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for ONNX 
inference request\n");
-        goto fail;
-    }
-    item->exec_module.start_inference = &onnx_start_inference;
-    item->exec_module.callback = &infer_completion_callback;
-    item->exec_module.args = item;
+    for (int i = 0; i < ctx->nireq; i++) {
+        ONNXRequestItem *item = av_mallocz(sizeof(*item));
+        if (!item) {
+            goto fail;
+        }
+        item->lltask = NULL;
+        item->infer_request = onnx_create_inference_request();
+        if (!item->infer_request) {
+            av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for ONNX 
inference request\n");
+            av_freep(&item);
+            goto fail;
+        }
+        item->exec_module.start_inference = &onnx_start_inference;
+        item->exec_module.callback = &infer_completion_callback;
+        item->exec_module.args = item;
 
-    if (ff_safe_queue_push_back(onnx_model->request_queue, item) < 0) {
-        goto fail;
+        if (ff_safe_queue_push_back(onnx_model->request_queue, item) < 0) {
+            destroy_request_item(&item);
+            goto fail;
+        }
     }
-    item = NULL;
 
     onnx_model->task_queue = ff_queue_create();
     if (!onnx_model->task_queue) {
@@ -1015,9 +1023,6 @@ static DNNModel *dnn_load_model_onnx(DnnContext *ctx, 
DNNFunctionType func_type,
     return model;
 
 fail:
-    if (item) {
-        destroy_request_item(&item);
-    }
     dnn_free_model_onnx(&model);
     return NULL;
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to