summaryrefslogtreecommitdiff
path: root/libavfilter/dnn/dnn_backend_native.c
diff options
context:
space:
mode:
authorGuo, Yejun <yejun.guo@intel.com>2020-08-28 12:51:44 +0800
committerGuo, Yejun <yejun.guo@intel.com>2020-09-21 21:26:56 +0800
commit2003e32f62d94ba75b59d70632c9f2862b383591 (patch)
tree55ec60788bc740eb45dbafd613bd8cf50a10417a /libavfilter/dnn/dnn_backend_native.c
parent6918e240d706f7390272976d8b8d502afe426a18 (diff)
dnn: change dnn interface to replace DNNData* with AVFrame*
Currently, every filter needs to provide code to transfer data from AVFrame* to model input (DNNData*), and also from model output (DNNData*) to AVFrame*. Actually, such transfer can be implemented within DNN module, and so filter can focus on its own business logic. DNN module also exports the function pointer pre_proc and post_proc in struct DNNModel, just in case that a filter has its special logic to transfer data between AVFrame* and DNNData*. The default implementation within DNN module is used if the filter does not set pre/post_proc.
Diffstat (limited to 'libavfilter/dnn/dnn_backend_native.c')
-rw-r--r--libavfilter/dnn/dnn_backend_native.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/libavfilter/dnn/dnn_backend_native.c b/libavfilter/dnn/dnn_backend_native.c
index 830ec19c80..14e878b6b8 100644
--- a/libavfilter/dnn/dnn_backend_native.c
+++ b/libavfilter/dnn/dnn_backend_native.c
@@ -27,6 +27,7 @@
#include "libavutil/avassert.h"
#include "dnn_backend_native_layer_conv2d.h"
#include "dnn_backend_native_layers.h"
+#include "dnn_io_proc.h"
#define OFFSET(x) offsetof(NativeContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM
@@ -69,11 +70,12 @@ static DNNReturnType get_input_native(void *model, DNNData *input, const char *i
return DNN_ERROR;
}
-static DNNReturnType set_input_native(void *model, DNNData *input, const char *input_name)
+static DNNReturnType set_input_native(void *model, AVFrame *frame, const char *input_name)
{
NativeModel *native_model = (NativeModel *)model;
NativeContext *ctx = &native_model->ctx;
DnnOperand *oprd = NULL;
+ DNNData input;
if (native_model->layers_num <= 0 || native_model->operands_num <= 0) {
av_log(ctx, AV_LOG_ERROR, "No operands or layers in model\n");
@@ -97,10 +99,8 @@ static DNNReturnType set_input_native(void *model, DNNData *input, const char *i
return DNN_ERROR;
}
- oprd->dims[0] = 1;
- oprd->dims[1] = input->height;
- oprd->dims[2] = input->width;
- oprd->dims[3] = input->channels;
+ oprd->dims[1] = frame->height;
+ oprd->dims[2] = frame->width;
av_freep(&oprd->data);
oprd->length = calculate_operand_data_length(oprd);
@@ -114,7 +114,16 @@ static DNNReturnType set_input_native(void *model, DNNData *input, const char *i
return DNN_ERROR;
}
- input->data = oprd->data;
+ input.height = oprd->dims[1];
+ input.width = oprd->dims[2];
+ input.channels = oprd->dims[3];
+ input.data = oprd->data;
+ input.dt = oprd->data_type;
+ if (native_model->model->pre_proc != NULL) {
+ native_model->model->pre_proc(frame, &input, native_model->model->userdata);
+ } else {
+ proc_from_frame_to_dnn(frame, &input, ctx);
+ }
return DNN_SUCCESS;
}
@@ -185,6 +194,7 @@ DNNModel *ff_dnn_load_model_native(const char *model_filename, const char *optio
if (av_opt_set_from_string(&native_model->ctx, model->options, NULL, "=", "&") < 0)
goto fail;
model->model = (void *)native_model;
+ native_model->model = model;
#if !HAVE_PTHREAD_CANCEL
if (native_model->ctx.options.conv2d_threads > 1){
@@ -275,11 +285,19 @@ fail:
return NULL;
}
-DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNData *outputs, const char **output_names, uint32_t nb_output)
+DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, const char **output_names, uint32_t nb_output, AVFrame *out_frame)
{
NativeModel *native_model = (NativeModel *)model->model;
NativeContext *ctx = &native_model->ctx;
int32_t layer;
+ DNNData output;
+
+ if (nb_output != 1) {
+ // currently, the filter does not need multiple outputs,
+ // so we just pending the support until we really need it.
+ av_log(ctx, AV_LOG_ERROR, "do not support multiple outputs\n");
+ return DNN_ERROR;
+ }
if (native_model->layers_num <= 0 || native_model->operands_num <= 0) {
av_log(ctx, AV_LOG_ERROR, "No operands or layers in model\n");
@@ -317,11 +335,22 @@ DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNData *output
return DNN_ERROR;
}
- outputs[i].data = oprd->data;
- outputs[i].height = oprd->dims[1];
- outputs[i].width = oprd->dims[2];
- outputs[i].channels = oprd->dims[3];
- outputs[i].dt = oprd->data_type;
+ output.data = oprd->data;
+ output.height = oprd->dims[1];
+ output.width = oprd->dims[2];
+ output.channels = oprd->dims[3];
+ output.dt = oprd->data_type;
+
+ if (out_frame->width != output.width || out_frame->height != output.height) {
+ out_frame->width = output.width;
+ out_frame->height = output.height;
+ } else {
+ if (native_model->model->post_proc != NULL) {
+ native_model->model->post_proc(out_frame, &output, native_model->model->userdata);
+ } else {
+ proc_from_dnn_to_frame(out_frame, &output, ctx);
+ }
+ }
}
return DNN_SUCCESS;