From 6f9570a63314051b3b333918eb13caae7498d6a4 Mon Sep 17 00:00:00 2001 From: Shubhanshu Saxena Date: Mon, 5 Jul 2021 16:00:58 +0530 Subject: [PATCH] lavfi/dnn_backend_tf: Error Handling This commit adds handling for cases where an error may occur, clearing the allocated memory resources. Signed-off-by: Shubhanshu Saxena --- libavfilter/dnn/dnn_backend_tf.c | 80 ++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 6664d7194b..1d4ca516c1 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -127,14 +127,18 @@ static TFInferRequest *tf_create_inference_request(void) static DNNReturnType extract_inference_from_task(TaskItem *task, Queue *inference_queue) { + TFModel *tf_model = task->model; + TFContext *ctx = &tf_model->ctx; InferenceItem *inference = av_malloc(sizeof(*inference)); if (!inference) { + av_log(ctx, AV_LOG_ERROR, "Unable to allocate space for InferenceItem\n"); return DNN_ERROR; } task->inference_todo = 1; task->inference_done = 0; inference->task = task; if (ff_queue_push_back(inference_queue, inference) < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to push back inference_queue.\n"); av_freep(&inference); return DNN_ERROR; } @@ -245,14 +249,15 @@ static DNNReturnType get_output_tf(void *model, const char *input_name, int inpu if (!in_frame) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input frame\n"); - return DNN_ERROR; + ret = DNN_ERROR; + goto err; } out_frame = av_frame_alloc(); if (!out_frame) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output frame\n"); - av_frame_free(&in_frame); - return DNN_ERROR; + ret = DNN_ERROR; + goto err; } in_frame->width = input_width; @@ -269,19 +274,22 @@ static DNNReturnType get_output_tf(void *model, const char *input_name, int inpu if (extract_inference_from_task(&task, tf_model->inference_queue) != DNN_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "unable to extract inference from task.\n"); - return DNN_ERROR; + ret = DNN_ERROR; + goto err; } request = ff_safe_queue_pop_front(tf_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + ret = DNN_ERROR; + goto err; } ret = execute_model_tf(request, tf_model->inference_queue); *output_width = out_frame->width; *output_height = out_frame->height; +err: av_frame_free(&out_frame); av_frame_free(&in_frame); return ret; @@ -802,17 +810,12 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ av_opt_set_defaults(ctx); if (av_opt_set_from_string(ctx, options, NULL, "=", "&") < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to parse options \"%s\"\n", options); - av_freep(&tf_model); - av_freep(&model); - return NULL; + goto err; } if (load_tf_model(tf_model, model_filename) != DNN_SUCCESS){ if (load_native_model(tf_model, model_filename) != DNN_SUCCESS){ - av_freep(&tf_model); - av_freep(&model); - - return NULL; + goto err; } } @@ -821,14 +824,34 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ } tf_model->request_queue = ff_safe_queue_create(); + if (!tf_model->request_queue) { + goto err; + } for (int i = 0; i < ctx->options.nireq; i++) { TFRequestItem *item = av_mallocz(sizeof(*item)); + if (!item) { + goto err; + } item->infer_request = tf_create_inference_request(); - ff_safe_queue_push_back(tf_model->request_queue, item); + if (!item->infer_request) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for TensorFlow inference request\n"); + av_freep(&item); + goto err; + } + + if (ff_safe_queue_push_back(tf_model->request_queue, item) < 0) { + av_freep(&item->infer_request); + av_freep(&item); + goto err; + } } tf_model->inference_queue = ff_queue_create(); + if (!tf_model->inference_queue) { + goto err; + } + model->model = tf_model; model->get_input = &get_input_tf; model->get_output = &get_output_tf; @@ -837,6 +860,9 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ model->func_type = func_type; return model; +err: + ff_dnn_free_model_tf(&model); + return NULL; } static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *request) { @@ -851,24 +877,31 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque task = inference->task; request->inference = inference; - if (get_input_tf(tf_model, &input, task->input_name) != DNN_SUCCESS) - return DNN_ERROR; + if (get_input_tf(tf_model, &input, task->input_name) != DNN_SUCCESS) { + goto err; + } infer_request = request->infer_request; input.height = task->in_frame->height; input.width = task->in_frame->width; infer_request->tf_input = av_malloc(sizeof(TF_Output)); + if (!infer_request->tf_input) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input tensor\n"); + goto err; + } + infer_request->tf_input->oper = TF_GraphOperationByName(tf_model->graph, task->input_name); if (!infer_request->tf_input->oper){ av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", task->input_name); - return DNN_ERROR; + goto err; } infer_request->tf_input->index = 0; + infer_request->input_tensor = allocate_input_tensor(&input); if (!infer_request->input_tensor){ av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input tensor\n"); - return DNN_ERROR; + goto err; } input.data = (float *)TF_TensorData(infer_request->input_tensor); @@ -893,13 +926,13 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->tf_outputs = av_malloc_array(task->nb_output, sizeof(TF_Output)); if (infer_request->tf_outputs == NULL) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for *tf_outputs\n"); - return DNN_ERROR; + goto err; } infer_request->output_tensors = av_mallocz_array(task->nb_output, sizeof(*infer_request->output_tensors)); if (!infer_request->output_tensors) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output tensor\n"); - return DNN_ERROR; + goto err; } for (int i = 0; i < task->nb_output; ++i) { @@ -907,12 +940,15 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->tf_outputs[i].oper = TF_GraphOperationByName(tf_model->graph, task->output_names[i]); if (!infer_request->tf_outputs[i].oper) { av_log(ctx, AV_LOG_ERROR, "Could not find output \"%s\" in model\n", task->output_names[i]); - return DNN_ERROR; + goto err; } infer_request->tf_outputs[i].index = 0; } return DNN_SUCCESS; +err: + tf_free_request(infer_request); + return DNN_ERROR; } static void infer_completion_callback(void *args) { @@ -983,6 +1019,10 @@ static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *inference_q TaskItem *task; inference = ff_queue_peek_front(inference_queue); + if (!inference) { + av_log(NULL, AV_LOG_ERROR, "Failed to get inference item\n"); + return DNN_ERROR; + } task = inference->task; tf_model = task->model; ctx = &tf_model->ctx;