summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorGuo, Yejun <yejun.guo@intel.com>2020-12-16 14:07:00 +0800
committerGuo, Yejun <yejun.guo@intel.com>2020-12-29 09:31:06 +0800
commitc720286ee3bf59420e6f6ddd1f999f2f327c8967 (patch)
tree542b4188213d36b0ce6598fb23955e43f1aa0d89 /libavfilter
parent5024286465acc35ae005715e0152a135df30ad0a (diff)
vf_dnn_processing.c: add async support
Signed-off-by: Xie, Lin <lin.xie@intel.com> Signed-off-by: Wu Zhiwen <zhiwen.wu@intel.com> Signed-off-by: Guo, Yejun <yejun.guo@intel.com>
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/vf_dnn_processing.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c
index 342b06e6ae..da4508b50e 100644
--- a/libavfilter/vf_dnn_processing.c
+++ b/libavfilter/vf_dnn_processing.c
@@ -42,6 +42,7 @@ typedef struct DnnProcessingContext {
char *model_inputname;
char *model_outputname;
char *backend_options;
+ int async;
DNNModule *dnn_module;
DNNModel *model;
@@ -65,6 +66,7 @@ static const AVOption dnn_processing_options[] = {
{ "input", "input name of the model", OFFSET(model_inputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
{ "output", "output name of the model", OFFSET(model_outputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
{ "options", "backend options", OFFSET(backend_options), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
+ { "async", "use DNN async inference", OFFSET(async), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, FLAGS},
{ NULL }
};
@@ -103,6 +105,11 @@ static av_cold int init(AVFilterContext *context)
return AVERROR(EINVAL);
}
+ if (!ctx->dnn_module->execute_model_async && ctx->async) {
+ ctx->async = 0;
+ av_log(ctx, AV_LOG_WARNING, "this backend does not support async execution, roll back to sync.\n");
+ }
+
return 0;
}
@@ -355,9 +362,78 @@ static int activate_sync(AVFilterContext *filter_ctx)
return FFERROR_NOT_READY;
}
+static int activate_async(AVFilterContext *filter_ctx)
+{
+ AVFilterLink *inlink = filter_ctx->inputs[0];
+ AVFilterLink *outlink = filter_ctx->outputs[0];
+ DnnProcessingContext *ctx = (DnnProcessingContext *)filter_ctx->priv;
+ AVFrame *in = NULL, *out = NULL;
+ int64_t pts;
+ int ret, status;
+ int got_frame = 0;
+ int async_state;
+
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+ do {
+ // drain all input frames
+ ret = ff_inlink_consume_frame(inlink, &in);
+ if (ret < 0)
+ return ret;
+ if (ret > 0) {
+ out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+ if (!out) {
+ av_frame_free(&in);
+ return AVERROR(ENOMEM);
+ }
+ av_frame_copy_props(out, in);
+ if ((ctx->dnn_module->execute_model_async)(ctx->model, ctx->model_inputname, in,
+ (const char **)&ctx->model_outputname, 1, out) != DNN_SUCCESS) {
+ return FFERROR_NOT_READY;
+ }
+ }
+ } while (ret > 0);
+
+ // drain all processed frames
+ do {
+ AVFrame *in_frame = NULL;
+ AVFrame *out_frame = NULL;
+ async_state = (ctx->dnn_module->get_async_result)(ctx->model, &in_frame, &out_frame);
+ if (out_frame) {
+ if (isPlanarYUV(in_frame->format))
+ copy_uv_planes(ctx, out_frame, in_frame);
+ av_frame_free(&in_frame);
+ ret = ff_filter_frame(outlink, out_frame);
+ if (ret < 0)
+ return ret;
+ got_frame = 1;
+ }
+ } while (async_state == DAST_SUCCESS);
+
+ // if frame got, schedule to next filter
+ if (got_frame)
+ return 0;
+
+ if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
+ if (status == AVERROR_EOF) {
+ ff_outlink_set_status(outlink, status, pts);
+ return ret;
+ }
+ }
+
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+ return FFERROR_NOT_READY;
+}
+
static int activate(AVFilterContext *filter_ctx)
{
- return activate_sync(filter_ctx);
+ DnnProcessingContext *ctx = filter_ctx->priv;
+
+ if (ctx->async)
+ return activate_async(filter_ctx);
+ else
+ return activate_sync(filter_ctx);
}
static av_cold void uninit(AVFilterContext *ctx)