From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 1AC254079B for ; Thu, 31 Mar 2022 20:54:55 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BA50168B221; Thu, 31 Mar 2022 23:54:52 +0300 (EEST) Received: from mail-4323.proton.ch (mail-4323.proton.ch [185.70.43.23]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id ADB3568B159 for ; Thu, 31 Mar 2022 23:54:45 +0300 (EEST) Date: Thu, 31 Mar 2022 20:54:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=simonbinder.eu; s=protonmail2; t=1648760084; bh=B3GYvg+o2tlpXyqzLj6/C+g4io2AIWEoxrOkOnCXnDQ=; h=Date:To:From:Reply-To:Subject:Message-ID:From:To:Cc:Date:Subject: Reply-To:Feedback-ID:Message-ID; b=T+lKom3nFnI5iZlMzuJFhk/PW7Xr/eAaUFdT8yJeYdhbE/DQcpHSDSfCa0LAiY+TH 63VpgU2foqFdMBNS/x7rohke5YQ3/zDBh3h/6hLlYiR1VNccOJolsN/GZLwvdGm/5K KxxLQ8/Luhvn5xTF3Ho5xyOkCqP9gCfzVCh6rnVOap7jKxLuWh0ls12q7rsaErg/IS a7ABMbcwXlptlL7moJyKE7zAOx4tJqOXeuR/iamH3pptP2PtZVVd0B5sTLU4zhO0bM jxZIb1oeqsXqmNgKM4seu1pEp71n0i2w9wIh1mRktBeQ1NSwGuyiUJ3qBj2gkP6CcV 3MhZp7jvtVTeg== To: ffmpeg-devel@ffmpeg.org From: Simon Binder Message-ID: <11d5064c-86b4-ff71-d8fd-b7f984005d86@simonbinder.eu> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avfilter/vf_perspective: Add support for commands X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Store expressions to avoid parsing them for each change. Support a command re-assigning all corners for the perspective. Signed-off-by: Simon Binder --- doc/filters.texi | 13 ++++ libavfilter/vf_perspective.c | 114 ++++++++++++++++++++++++++++------- 2 files changed, 106 insertions(+), 21 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 1d56d24819..4fe4dc04d9 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17201,6 +17201,19 @@ evaluate expressions for each incoming frame Default value is @samp{init}. @end table +@subsection Commands + +This filter supports the following command: + +@table @option +@item dims +Updates all eight coordinate values from one colon-separated parameter. +@example +0.0 [enter] perspective dims 0:0:300:0:0:300:300:300; +5.0 [enter] perspective dims 0:0:300:50:0:300:300:350; +@end example +@end table + @section phase Delay interlaced video by one field time so that the field order changes. diff --git a/libavfilter/vf_perspective.c b/libavfilter/vf_perspective.c index da720dcb54..e81234c7d6 100644 --- a/libavfilter/vf_perspective.c +++ b/libavfilter/vf_perspective.c @@ -19,13 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "libavutil/avassert.h" #include "libavutil/eval.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "avfilter.h" -#include "formats.h" #include "internal.h" #include "video.h" @@ -36,9 +36,13 @@ #define LINEAR 0 #define CUBIC 1 +static const char *const var_names[] = { "W", "H", "in", "on", NULL }; +enum { VAR_W, VAR_H, VAR_IN, VAR_ON, VAR_VARS_NB }; + typedef struct PerspectiveContext { const AVClass *class; char *expr_str[4][2]; + AVExpr* expr[4][2]; double ref[4][2]; int32_t (*pv)[2]; int32_t coeff[SUB_PIXELS][4]; @@ -49,6 +53,7 @@ typedef struct PerspectiveContext { int nb_planes; int sense; int eval_mode; + double var_values[VAR_VARS_NB]; int (*perspective)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); @@ -117,34 +122,31 @@ static inline double get_coeff(double d) return coeff; } -static const char *const var_names[] = { "W", "H", "in", "on", NULL }; -enum { VAR_W, VAR_H, VAR_IN, VAR_ON, VAR_VARS_NB }; - -static int calc_persp_luts(AVFilterContext *ctx, AVFilterLink *inlink) +static void set_variables_for_link(AVFilterContext *ctx, AVFilterLink *inlink) { PerspectiveContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + + s->var_values[VAR_W] = inlink->w; + s->var_values[VAR_H] = inlink->h; + s->var_values[VAR_IN] = inlink->frame_count_out + 1; + s->var_values[VAR_ON] = outlink->frame_count_in + 1; +} + +static int calc_persp_luts(AVFilterContext *ctx) +{ + PerspectiveContext *s = ctx->priv; double (*ref)[2] = s->ref; - double values[VAR_VARS_NB] = { [VAR_W] = inlink->w, [VAR_H] = inlink->h, - [VAR_IN] = inlink->frame_count_out + 1, - [VAR_ON] = outlink->frame_count_in + 1 }; - const int h = values[VAR_H]; - const int w = values[VAR_W]; + const int h = s->var_values[VAR_H]; + const int w = s->var_values[VAR_W]; double x0, x1, x2, x3, x4, x5, x6, x7, x8, q; double t0, t1, t2, t3; - int x, y, i, j, ret; + int x, y, i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 2; j++) { - if (!s->expr_str[i][j]) - return AVERROR(EINVAL); - ret = av_expr_parse_and_eval(&s->ref[i][j], s->expr_str[i][j], - var_names, &values[0], - NULL, NULL, NULL, NULL, - 0, 0, ctx); - if (ret < 0) - return ret; + s->ref[i][j] = av_expr_eval(s->expr[i][j], s->var_values, s); } } @@ -238,8 +240,27 @@ static int config_input(AVFilterLink *inlink) if (!s->pv) return AVERROR(ENOMEM); + // Parse coordinate expressions + for (i = 0; i < 4; i++) { + for (j = 0; j < 2; j++) { + av_expr_free(s->expr[i][j]); + s->expr[i][j] = NULL; + + if (!s->expr_str[i][j]) + return AVERROR(EINVAL); + + if ((ret = av_expr_parse(&s->expr[i][j], s->expr_str[i][j], var_names, + NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error occurred parsing coordinate '%s'\n", s->expr_str[i][j]); + return ret; + } + } + } + if (s->eval_mode == EVAL_MODE_INIT) { - if ((ret = calc_persp_luts(ctx, inlink)) < 0) { + set_variables_for_link(ctx, inlink); + if ((ret = calc_persp_luts(ctx)) < 0) { return ret; } } @@ -437,6 +458,49 @@ static av_cold int init(AVFilterContext *ctx) return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg, + char *res, int res_len, int flags) +{ + PerspectiveContext *s = ctx->priv; + int ret; + char *token; + AVExpr *old; + + if (!strcmp(cmd, "dims")) { + // Expect arg to be an 8-token argument containing the new coordinates + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 2; j++) { + if (!*arg) { + av_log(ctx, AV_LOG_ERROR,"Expected 8 expressions for the new coordinates\n"); + return AVERROR(EINVAL); + } + + token = av_get_token(&arg, ":"); + if (!token) + return AVERROR(ENOMEM); + arg++; + + old = s->expr[i][j]; + + if ((ret = av_expr_parse(&s->expr[i][j], token, var_names, + NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error occurred parsing coordinate '%s'\n", token); + av_free(token); + return ret; + } + av_free(token); + av_expr_free(old); + } + } + + ret = calc_persp_luts(ctx); + } else + ret = AVERROR(ENOSYS); + + return ret; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -454,7 +518,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_frame_copy_props(out, frame); if (s->eval_mode == EVAL_MODE_FRAME) { - if ((ret = calc_persp_luts(ctx, inlink)) < 0) { + set_variables_for_link(ctx, inlink); + if ((ret = calc_persp_luts(ctx)) < 0) { av_frame_free(&out); return ret; } @@ -484,6 +549,12 @@ static av_cold void uninit(AVFilterContext *ctx) PerspectiveContext *s = ctx->priv; av_freep(&s->pv); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 2; j++) { + av_expr_free(s->expr[i][j]); + s->expr[i][j] = NULL; + } + } } static const AVFilterPad perspective_inputs[] = { @@ -508,6 +579,7 @@ const AVFilter ff_vf_perspective = { .priv_size = sizeof(PerspectiveContext), .init = init, .uninit = uninit, + .process_command = &process_command, FILTER_INPUTS(perspective_inputs), FILTER_OUTPUTS(perspective_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), -- 2.35.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".