From patchwork Tue Dec 22 07:47:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Guo, Yejun" X-Patchwork-Id: 24620 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 401CE4483BF for ; Tue, 22 Dec 2020 09:48:52 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2762A68A882; Tue, 22 Dec 2020 09:48:52 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7B690689D8E for ; Tue, 22 Dec 2020 09:48:44 +0200 (EET) IronPort-SDR: 9lobPDVbl/wkk56imeLJxRkK5farJ02q7oLFxb/7y52PvHQm5CFfP+w/r4BSjrcCtTC7FJG0zk q/phC/0UR+Hg== X-IronPort-AV: E=McAfee;i="6000,8403,9842"; a="175932364" X-IronPort-AV: E=Sophos;i="5.78,438,1599548400"; d="scan'208";a="175932364" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Dec 2020 23:48:42 -0800 IronPort-SDR: 9zgmB6yxeNpoGOK3ckwH1jgCh2aLwfdlg2qUmx9UW8Y9XykXK0l8aCgE562Dr3U2wVSMmiovCp Czd6sauerztA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.78,438,1599548400"; d="scan'208";a="564206065" Received: from yguo18-skl-u1604.sh.intel.com (HELO localhost.localdomain) ([10.239.159.53]) by fmsmga005.fm.intel.com with ESMTP; 21 Dec 2020 23:48:41 -0800 From: "Guo, Yejun" To: ffmpeg-devel@ffmpeg.org Date: Tue, 22 Dec 2020 15:47:41 +0800 Message-Id: <20201222074741.6511-1-yejun.guo@intel.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH 8/8] vf_dnn_processing.c: add async support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: yejun.guo@intel.com MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Xie, Lin Signed-off-by: Wu Zhiwen Signed-off-by: Guo, Yejun --- doc/filters.texi | 4 ++ libavfilter/vf_dnn_processing.c | 78 ++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index d6a53624ee..3f10a29739 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9959,6 +9959,10 @@ Set the input name of the dnn network. @item output Set the output name of the dnn network. +@item async +use DNN async execution if set (default: set), +roll back to sync execution if the backend does not support async. + @end table @subsection Examples 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)