Signed-off-by: alex_qt <3.1...@ukr.net>
---
 libavfilter/vf_overlay_cuda.c | 146 ++++++++++++++++++++++++++++------
 1 file changed, 120 insertions(+), 26 deletions(-)


diff --git a/libavfilter/vf_overlay_cuda.c b/libavfilter/vf_overlay_cuda.c
index 2f0f860e50..636ddbedb0 100644
--- a/libavfilter/vf_overlay_cuda.c
+++ b/libavfilter/vf_overlay_cuda.c
@@ -30,11 +30,15 @@
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_cuda_internal.h"
 #include "libavutil/cuda_check.h"
+#include "libavutil/eval.h"
 
 #include "avfilter.h"
 #include "framesync.h"
 #include "internal.h"
 
+#define OFFSET(x) offsetof(OverlayCUDAContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+
 #define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, ctx->hwctx->internal->cuda_dl, x)
 #define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) )
 
@@ -54,6 +58,16 @@ static const enum AVPixelFormat supported_overlay_formats[] = {
     AV_PIX_FMT_NONE,
 };
 
+enum var_name {
+    VAR_MAIN_W,     VAR_MW,
+    VAR_MAIN_H,     VAR_MH,
+    VAR_OVERLAY_W,  VAR_OW,
+    VAR_OVERLAY_H,  VAR_OH,
+    VAR_OVERLAY_X,  VAR_OX,
+    VAR_OVERLAY_Y,  VAR_OY,
+    VAR_VARS_NB
+};
+
 /**
  * OverlayCUDAContext
  */
@@ -69,14 +83,77 @@ typedef struct OverlayCUDAContext {
     CUmodule cu_module;
     CUfunction cu_func;
     CUstream cu_stream;
+    CUfunction  cu_func_uchar;
 
     FFFrameSync fs;
 
     int x_position;
     int y_position;
+    double var_values[VAR_VARS_NB];
+    char *x_expr,*y_expr;
 
 } OverlayCUDAContext;
 
+static const char *const var_names[] = {
+    "main_w",    "W", ///< width  of the main    video
+    "main_h",    "H", ///< height of the main    video
+    "overlay_w", "w", ///< width  of the overlay video
+    "overlay_h", "h", ///< height of the overlay video
+    NULL
+};
+
+static const AVOption overlay_cuda_options[] = {
+    { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS },
+    { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS },
+    { "eof_action", "Action to take when encountering EOF from secondary input ",
+        OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
+        EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
+        { "repeat", "Repeat the previous frame.",   0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
+        { "endall", "End both streams.",            0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
+        { "pass",   "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS },   .flags = FLAGS, "eof_action" },
+    { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+    { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
+    { NULL },
+};
+
+FRAMESYNC_DEFINE_CLASS(overlay_cuda, OverlayCUDAContext, fs);
+
+static int eval_expr(AVFilterContext *ctx)
+{
+    OverlayCUDAContext *c = ctx->priv;
+    double     *var_values = c->var_values;
+    int                ret = 0;
+    AVExpr *x_expr = NULL, *y_expr = NULL;
+
+#define PASS_EXPR(e, s) {\
+    ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \
+    if (ret < 0) {\
+        av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s);\
+        goto release;\
+    }\
+}
+    PASS_EXPR(x_expr, c->x_expr);
+    PASS_EXPR(y_expr, c->y_expr);
+#undef PASS_EXPR
+
+    var_values[VAR_OVERLAY_X] =
+    var_values[VAR_OX]        = av_expr_eval(x_expr, var_values, NULL);
+    var_values[VAR_OVERLAY_Y] =
+    var_values[VAR_OY]        = av_expr_eval(y_expr, var_values, NULL);
+
+    /* calc again in case ox is relative to oy */
+    var_values[VAR_OVERLAY_X] =
+    var_values[VAR_OX]        = av_expr_eval(x_expr, var_values, NULL);
+
+        c->x_position=(int)var_values[VAR_OVERLAY_X];
+        c->y_position=(int)var_values[VAR_OVERLAY_Y];
+release:
+    av_expr_free(x_expr);
+    av_expr_free(y_expr);
+
+    return ret;
+}
+
 /**
  * Helper to find out if provided format is supported by filter
  */
@@ -174,8 +251,6 @@ static int overlay_cuda_blend(FFFrameSync *fs)
         return ret;
     }
 
-    // overlay first plane
-
     overlay_cuda_call_kernel(ctx,
         ctx->x_position, ctx->y_position,
         input_main->data[0], input_main->linesize[0],
@@ -280,11 +355,49 @@ static int overlay_cuda_query_formats(AVFilterContext *avctx)
 }
 
 /**
- * Configure output
+ * Configure inputs
  */
-static int overlay_cuda_config_output(AVFilterLink *outlink)
+ static int config_main_input(AVFilterLink *inlink)
+{
+    AVFilterContext      *ctx = inlink->dst;
+    OverlayCUDAContext    *o = ctx->priv;
+
+    av_log(ctx, AV_LOG_DEBUG, "Input[%d] is of %s.\n", FF_INLINK_IDX(inlink),
+           av_get_pix_fmt_name(inlink->format));
+
+    o->var_values[VAR_MAIN_W] =
+    o->var_values[VAR_MW]      = inlink->w;
+    o->var_values[VAR_MAIN_H] =
+    o->var_values[VAR_MH]      = inlink->h;
+
+    return 0;
+}
+static int config_overlay_input(AVFilterLink *inlink)
 {
+    AVFilterContext       *ctx = inlink->dst;
+    OverlayCUDAContext     *o = ctx->priv;
+    int                    ret = 0;
+
+    av_log(ctx, AV_LOG_DEBUG, "Input[%d] is of %s.\n", FF_INLINK_IDX(inlink),
+           av_get_pix_fmt_name(inlink->format));
+
+    o->var_values[VAR_OVERLAY_W] =
+    o->var_values[VAR_OW] = inlink->w;
+    o->var_values[VAR_OVERLAY_H] =
+    o->var_values[VAR_OH] = inlink->h;
+
+    ret = eval_expr(ctx);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
 
+/**
+ * Configure output
+ */
+static av_cold int overlay_cuda_config_output(AVFilterLink *outlink)
+{
     extern char vf_overlay_cuda_ptx[];
 
     int err;
@@ -379,36 +492,17 @@ static int overlay_cuda_config_output(AVFilterLink *outlink)
     return ff_framesync_configure(&ctx->fs);
 }
 
-
-#define OFFSET(x) offsetof(OverlayCUDAContext, x)
-#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
-
-static const AVOption overlay_cuda_options[] = {
-    { "x", "Overlay x position",
-      OFFSET(x_position), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = FLAGS },
-    { "y", "Overlay y position",
-      OFFSET(y_position), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = FLAGS },
-    { "eof_action", "Action to take when encountering EOF from secondary input ",
-        OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
-        EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
-        { "repeat", "Repeat the previous frame.",   0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
-        { "endall", "End both streams.",            0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
-        { "pass",   "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS },   .flags = FLAGS, "eof_action" },
-    { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
-    { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
-    { NULL },
-};
-
-FRAMESYNC_DEFINE_CLASS(overlay_cuda, OverlayCUDAContext, fs);
-
 static const AVFilterPad overlay_cuda_inputs[] = {
     {
         .name         = "main",
         .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props  = config_main_input,
     },
     {
         .name         = "overlay",
         .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props  = config_overlay_input,
+
     },
     { NULL }
 };

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to