From patchwork Wed Jan 29 19:25:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 17613 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 9A3F144BC18 for ; Wed, 29 Jan 2020 21:25:28 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 71CB5687FEC; Wed, 29 Jan 2020 21:25:28 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D351368B0B1 for ; Wed, 29 Jan 2020 21:25:21 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id AD931E3C19; Wed, 29 Jan 2020 20:25:21 +0100 (CET) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id MEwUqQ4prRii; Wed, 29 Jan 2020 20:25:20 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 46DF6E3A48; Wed, 29 Jan 2020 20:25:20 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Wed, 29 Jan 2020 20:25:17 +0100 Message-Id: <20200129192517.27740-1-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 Subject: [FFmpeg-devel] [PATCH] avfilter/vf_geq: use per-thread AVExpr for expression evaluation 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: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" There was no consensus about separating AVExprState from AVExpr so here is a minimal patch using the existing AVExpr to fix ticket #7528. Signed-off-by: Marton Balint --- doc/filters.texi | 5 +++++ libavfilter/vf_geq.c | 26 +++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 3f40af8439..8a59de27ee 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11464,6 +11464,11 @@ Default is bilinear. For functions, if @var{x} and @var{y} are outside the area, the value will be automatically clipped to the closer edge. +Please note that this filter can use multiple threads in which case each slice +will have its own expression state. If you want to use only a single expression +state because your expressions depend on previous state then you should limit +the number of filter threads to 1. + @subsection Examples @itemize diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c index 23c989b248..c6f76a6963 100644 --- a/libavfilter/vf_geq.c +++ b/libavfilter/vf_geq.c @@ -33,6 +33,7 @@ #include "libavutil/pixdesc.h" #include "internal.h" +#define MAX_NB_THREADS 32 #define NB_PLANES 4 enum InterpolationMethods { @@ -46,7 +47,7 @@ enum { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_ typedef struct GEQContext { const AVClass *class; - AVExpr *e[NB_PLANES]; ///< expressions for each plane + AVExpr *e[NB_PLANES][MAX_NB_THREADS]; ///< expressions for each plane and thread char *expr_str[4+3]; ///< expression strings for each plane AVFrame *picref; ///< current input buffer uint8_t *dst; ///< reference pointer to the 8bits output @@ -288,12 +289,14 @@ static av_cold int geq_init(AVFilterContext *ctx) NULL }; int counter[10] = {0}; - ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names, - NULL, NULL, func2_names, func2, 0, ctx); - if (ret < 0) - break; + for (int i = 0; i < MAX_NB_THREADS; i++) { + ret = av_expr_parse(&geq->e[plane][i], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names, + NULL, NULL, func2_names, func2, 0, ctx); + if (ret < 0) + goto end; + } - av_expr_count_func(geq->e[plane], counter, FF_ARRAY_ELEMS(counter), 2); + av_expr_count_func(geq->e[plane][0], counter, FF_ARRAY_ELEMS(counter), 2); geq->needs_sum[plane] = counter[5] + counter[6] + counter[7] + counter[8] + counter[9]; } @@ -391,7 +394,7 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j for (x = 0; x < width; x++) { values[VAR_X] = x; - ptr[x] = av_expr_eval(geq->e[plane], values, geq); + ptr[x] = av_expr_eval(geq->e[plane][jobnr], values, geq); } ptr += linesize; } @@ -401,7 +404,7 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j values[VAR_Y] = y; for (x = 0; x < width; x++) { values[VAR_X] = x; - ptr16[x] = av_expr_eval(geq->e[plane], values, geq); + ptr16[x] = av_expr_eval(geq->e[plane][jobnr], values, geq); } ptr16 += linesize/2; } @@ -414,7 +417,7 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in) { int plane; AVFilterContext *ctx = inlink->dst; - const int nb_threads = ff_filter_get_nb_threads(ctx); + const int nb_threads = FFMIN(MAX_NB_THREADS, ff_filter_get_nb_threads(ctx)); GEQContext *geq = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; @@ -464,8 +467,9 @@ static av_cold void geq_uninit(AVFilterContext *ctx) int i; GEQContext *geq = ctx->priv; - for (i = 0; i < FF_ARRAY_ELEMS(geq->e); i++) - av_expr_free(geq->e[i]); + for (i = 0; i < NB_PLANES; i++) + for (int j = 0; j < MAX_NB_THREADS; j++) + av_expr_free(geq->e[i][j]); for (i = 0; i < NB_PLANES; i++) av_freep(&geq->pixel_sums); }