+static int activate_sync(AVFilterContext *filter_ctx)
+{
+ AVFilterLink *inlink = filter_ctx->inputs[0];
+ AVFilterLink *outlink = filter_ctx->outputs[0];
+ AVFrame *in = NULL;
+ int64_t pts;
+ int ret, status;
+ int got_frame = 0;
+
+ 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) {
+ ret = filter_frame(inlink, in);
+ if (ret < 0)
+ return ret;
+ got_frame = 1;
+ }
+ } while (ret > 0);
+
+ // 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 flush_frame(AVFilterLink *outlink, int64_t pts, int64_t *out_pts)
+{
+ DnnProcessingContext *ctx = outlink->src->priv;
+ int ret;
+ DNNAsyncStatusType async_state;
+
+ ret = ff_dnn_flush(&ctx->dnnctx);
+ if (ret != DNN_SUCCESS) {
+ return -1;
+ }
+
+ do {
+ AVFrame *in_frame = NULL;
+ AVFrame *out_frame = NULL;
+ async_state = ff_dnn_get_async_result(&ctx->dnnctx, &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;
+ if (out_pts)
+ *out_pts = out_frame->pts + pts;
+ }
+ av_usleep(5000);
+ } while (async_state >= DAST_NOT_READY);
+
+ return 0;
+}
+
+static int activate_async(AVFilterContext *filter_ctx)
+{
+ AVFilterLink *inlink = filter_ctx->inputs[0];
+ AVFilterLink *outlink = filter_ctx->outputs[0];
+ DnnProcessingContext *ctx = 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 (ff_dnn_execute_model_async(&ctx->dnnctx, in, out) != DNN_SUCCESS) {
+ return AVERROR(EIO);
+ }
+ }
+ } while (ret > 0);
+
+ // drain all processed frames
+ do {
+ AVFrame *in_frame = NULL;
+ AVFrame *out_frame = NULL;
+ async_state = ff_dnn_get_async_result(&ctx->dnnctx, &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) {
+ int64_t out_pts = pts;
+ ret = flush_frame(outlink, pts, &out_pts);
+ ff_outlink_set_status(outlink, status, out_pts);
+ return ret;
+ }
+ }
+
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+ return 0;
+}
+
+static int activate(AVFilterContext *filter_ctx)
+{
+ DnnProcessingContext *ctx = filter_ctx->priv;
+
+ if (ctx->dnnctx.async)
+ return activate_async(filter_ctx);
+ else
+ return activate_sync(filter_ctx);
+}
+