FFmpeg
dnn_backend_common.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file
21  * DNN common functions different backends.
22  */
23 
24 #include "libavutil/mem.h"
25 #include "libavutil/time.h"
26 #include "dnn_backend_common.h"
27 
28 #define DNN_ASYNC_SUCCESS (void *)0
29 #define DNN_ASYNC_FAIL (void *)-1
30 
31 int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func_type, DNNExecBaseParams *exec_params)
32 {
33  if (!exec_params) {
34  av_log(ctx, AV_LOG_ERROR, "exec_params is null when execute model.\n");
35  return AVERROR(EINVAL);
36  }
37 
38  if (!exec_params->in_frame) {
39  av_log(ctx, AV_LOG_ERROR, "in frame is NULL when execute model.\n");
40  return AVERROR(EINVAL);
41  }
42 
43  if (!exec_params->out_frame && func_type == DFT_PROCESS_FRAME) {
44  av_log(ctx, AV_LOG_ERROR, "out frame is NULL when execute model.\n");
45  return AVERROR(EINVAL);
46  }
47 
48  return 0;
49 }
50 
51 int ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc) {
52  if (task == NULL || exec_params == NULL || backend_model == NULL)
53  return AVERROR(EINVAL);
54  if (do_ioproc != 0 && do_ioproc != 1)
55  return AVERROR(EINVAL);
56  if (async != 0 && async != 1)
57  return AVERROR(EINVAL);
58 
59  task->do_ioproc = do_ioproc;
60  task->async = async;
61  task->input_name = exec_params->input_name;
62  task->in_frame = exec_params->in_frame;
63  task->out_frame = exec_params->out_frame;
64  task->model = backend_model;
65  task->nb_output = exec_params->nb_output;
66  task->output_names = exec_params->output_names;
67 
68  return 0;
69 }
70 
71 /**
72  * Thread routine for async execution.
73  * @param args pointer to DNNAsyncExecModule module
74  */
75 static void *async_thread_routine(void *args)
76 {
77  DNNAsyncExecModule *async_module = args;
78  void *request = async_module->args;
79 
80  if (async_module->start_inference(request) != 0) {
81  return DNN_ASYNC_FAIL;
82  }
83  async_module->callback(request);
84  return DNN_ASYNC_SUCCESS;
85 }
86 
88 {
89  void *status = 0;
90  if (!async_module) {
91  return AVERROR(EINVAL);
92  }
93 #if HAVE_PTHREAD_CANCEL
94  pthread_join(async_module->thread_id, &status);
95  if (status == DNN_ASYNC_FAIL) {
96  av_log(NULL, AV_LOG_ERROR, "Last Inference Failed.\n");
97  return DNN_GENERIC_ERROR;
98  }
99 #endif
100  async_module->start_inference = NULL;
101  async_module->callback = NULL;
102  async_module->args = NULL;
103  return 0;
104 }
105 
106 void ff_dnn_wait_requests(SafeQueue *request_queue, int nireq)
107 {
108  if (!request_queue)
109  return;
110  while (ff_safe_queue_size(request_queue) < nireq)
111  av_usleep(10000);
112 }
113 
115 {
116  int ret;
117  void *status = 0;
118 
119  if (!async_module) {
120  av_log(ctx, AV_LOG_ERROR, "async_module is null when starting async inference.\n");
121  return AVERROR(EINVAL);
122  }
123 
124 #if HAVE_PTHREAD_CANCEL
125  pthread_join(async_module->thread_id, &status);
126  if (status == DNN_ASYNC_FAIL) {
127  av_log(ctx, AV_LOG_ERROR, "Unable to start inference as previous inference failed.\n");
128  return DNN_GENERIC_ERROR;
129  }
130  ret = pthread_create(&async_module->thread_id, NULL, async_thread_routine, async_module);
131  if (ret != 0) {
132  av_log(ctx, AV_LOG_ERROR, "Unable to start async inference.\n");
133  return ret;
134  }
135 #else
136  ret = async_module->start_inference(async_module->args);
137  if (ret != 0) {
138  return ret;
139  }
140  async_module->callback(async_module->args);
141 #endif
142  return 0;
143 }
144 
146 {
147  TaskItem *task = ff_queue_peek_front(task_queue);
148 
149  if (!task) {
150  return DAST_EMPTY_QUEUE;
151  }
152 
153  if (task->inference_done != task->inference_todo) {
154  return DAST_NOT_READY;
155  }
156 
157  *in = task->in_frame;
158  *out = task->out_frame;
159  ff_queue_pop_front(task_queue);
160  av_freep(&task);
161 
162  return DAST_SUCCESS;
163 }
164 
165 int ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx)
166 {
167  AVFrame *in_frame = NULL;
168  AVFrame *out_frame = NULL;
169 
170  in_frame = av_frame_alloc();
171  if (!in_frame) {
172  av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input frame\n");
173  return AVERROR(ENOMEM);
174  }
175 
176  out_frame = av_frame_alloc();
177  if (!out_frame) {
178  av_frame_free(&in_frame);
179  av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output frame\n");
180  return AVERROR(ENOMEM);
181  }
182 
183  in_frame->width = input_width;
184  in_frame->height = input_height;
185  exec_params->in_frame = in_frame;
186  exec_params->out_frame = out_frame;
187 
188  return ff_dnn_fill_task(task, exec_params, backend_model, 0, 0);
189 }
pthread_join
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:94
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
out
static FILE * out
Definition: movenc.c:55
DNNAsyncExecModule
Common Async Execution Mechanism for the DNN Backends.
Definition: dnn_backend_common.h:66
DNNFunctionType
DNNFunctionType
Definition: dnn_interface.h:57
ff_queue_pop_front
void * ff_queue_pop_front(Queue *q)
Remove and free first element from the Queue.
Definition: queue.c:151
ff_check_exec_params
int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func_type, DNNExecBaseParams *exec_params)
Definition: dnn_backend_common.c:31
DNN_GENERIC_ERROR
#define DNN_GENERIC_ERROR
Definition: dnn_interface.h:33
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
AVFrame::width
int width
Definition: frame.h:544
SafeQueue
Double-ended queue with mutex locks ensuring data consistency while multithreading.
Definition: safe_queue.c:46
DNNExecBaseParams::input_name
const char * input_name
Definition: dnn_interface.h:82
TaskItem
Definition: dnn_backend_common.h:44
DNNAsyncExecModule::callback
void(* callback)(void *args)
Completion Callback for the backend.
Definition: dnn_backend_common.h:78
DNNExecBaseParams::in_frame
AVFrame * in_frame
Definition: dnn_interface.h:85
DNN_ASYNC_SUCCESS
#define DNN_ASYNC_SUCCESS
Definition: dnn_backend_common.c:28
TaskItem::model
void * model
Definition: dnn_backend_common.h:45
ff_dnn_wait_requests
void ff_dnn_wait_requests(SafeQueue *request_queue, int nireq)
Wait for all inference requests to complete before teardown.
Definition: dnn_backend_common.c:106
Queue
Linear double-ended data structure.
Definition: executor.c:51
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
ff_dnn_fill_gettingoutput_task
int ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx)
Allocate input and output frames and fill the Task with execution parameters.
Definition: dnn_backend_common.c:165
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
TaskItem::inference_todo
uint32_t inference_todo
Definition: dnn_backend_common.h:53
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:93
pthread_create
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition: os2threads.h:80
ff_safe_queue_size
size_t ff_safe_queue_size(SafeQueue *sq)
Return the length of the SafeQueue.
Definition: safe_queue.c:80
NULL
#define NULL
Definition: coverity.c:32
ff_dnn_async_module_cleanup
int ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module)
Join the Async Execution thread and set module pointers to NULL.
Definition: dnn_backend_common.c:87
time.h
TaskItem::in_frame
AVFrame * in_frame
Definition: dnn_backend_common.h:46
TaskItem::async
uint8_t async
Definition: dnn_backend_common.h:50
DAST_SUCCESS
@ DAST_SUCCESS
Definition: dnn_interface.h:54
TaskItem::inference_done
uint32_t inference_done
Definition: dnn_backend_common.h:54
DNNBackendType
DNNBackendType
Definition: dnn_interface.h:35
DAST_EMPTY_QUEUE
@ DAST_EMPTY_QUEUE
Definition: dnn_interface.h:52
ff_dnn_fill_task
int ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc)
Fill the Task for Backend Execution.
Definition: dnn_backend_common.c:51
DNNExecBaseParams::out_frame
AVFrame * out_frame
Definition: dnn_interface.h:86
DNNAsyncExecModule::start_inference
int(* start_inference)(void *request)
Synchronous inference function for the backend with corresponding request item as the argument.
Definition: dnn_backend_common.h:71
DNNAsyncExecModule::args
void * args
Argument for the execution functions.
Definition: dnn_backend_common.h:84
TaskItem::output_names
const char ** output_names
Definition: dnn_backend_common.h:49
async_thread_routine
static void * async_thread_routine(void *args)
Thread routine for async execution.
Definition: dnn_backend_common.c:75
ret
ret
Definition: filter_design.txt:187
TaskItem::out_frame
AVFrame * out_frame
Definition: dnn_backend_common.h:47
AVFrame::height
int height
Definition: frame.h:544
status
ov_status_e status
Definition: dnn_backend_openvino.c:99
dnn_backend_common.h
DNN_ASYNC_FAIL
#define DNN_ASYNC_FAIL
Definition: dnn_backend_common.c:29
ff_dnn_get_result_common
DNNAsyncStatusType ff_dnn_get_result_common(Queue *task_queue, AVFrame **in, AVFrame **out)
Extract input and output frame from the Task Queue after asynchronous inference.
Definition: dnn_backend_common.c:145
ff_queue_peek_front
void * ff_queue_peek_front(Queue *q)
Return a pointer to the data at the head of the queue.
Definition: queue.c:93
DNNExecBaseParams::output_names
const char ** output_names
Definition: dnn_interface.h:83
ff_dnn_start_inference_async
int ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module)
Start asynchronous inference routine for the TensorFlow model on a detached thread.
Definition: dnn_backend_common.c:114
mem.h
TaskItem::input_name
const char * input_name
Definition: dnn_backend_common.h:48
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
DNNExecBaseParams
Definition: dnn_interface.h:81
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
TaskItem::do_ioproc
uint8_t do_ioproc
Definition: dnn_backend_common.h:51
DAST_NOT_READY
@ DAST_NOT_READY
Definition: dnn_interface.h:53
DNNAsyncStatusType
DNNAsyncStatusType
Definition: dnn_interface.h:50
DFT_PROCESS_FRAME
@ DFT_PROCESS_FRAME
Definition: dnn_interface.h:59
TaskItem::nb_output
uint32_t nb_output
Definition: dnn_backend_common.h:52
DNNExecBaseParams::nb_output
uint32_t nb_output
Definition: dnn_interface.h:84