From patchwork Mon Dec 30 22:25:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 17077 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 34464449CDA for ; Tue, 31 Dec 2019 00:25:27 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1288968ACF6; Tue, 31 Dec 2019 00:25:27 +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 88FBA68ABD8 for ; Tue, 31 Dec 2019 00:25:20 +0200 (EET) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id 73F5FE397E; Mon, 30 Dec 2019 23:25:20 +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 0HzXz2I8eGE4; Mon, 30 Dec 2019 23:25:18 +0100 (CET) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id B71DAE3699; Mon, 30 Dec 2019 23:25:18 +0100 (CET) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Mon, 30 Dec 2019 23:25:04 +0100 Message-Id: <20191230222504.5942-1-cus@passwd.hu> X-Mailer: git-send-email 2.16.4 In-Reply-To: References: Subject: [FFmpeg-devel] [PATCHv2 2/3] avfilter/vf_geq: use per-thread state 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" Fixes ticket #7528. Signed-off-by: Marton Balint --- doc/filters.texi | 5 +++++ libavfilter/vf_geq.c | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index ba00989987..9572fa36fc 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -11386,6 +11386,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 2905efae24..ae5724b69e 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 { @@ -57,6 +58,7 @@ typedef struct GEQContext { int interpolation; int is_rgb; int bps; + AVExprState *states[MAX_NB_THREADS]; ///< expression states per thread (job) double *pixel_sums[NB_PLANES]; int needs_sum[NB_PLANES]; @@ -297,6 +299,14 @@ static av_cold int geq_init(AVFilterContext *ctx) geq->needs_sum[plane] = counter[5] + counter[6] + counter[7] + counter[8] + counter[9]; } + for (int i = 0; i < MAX_NB_THREADS; i++) { + geq->states[i] = av_expr_state_alloc(); + if (!geq->states[i]) { + ret = AVERROR(ENOMEM); + break; + } + } + end: return ret; } @@ -377,6 +387,7 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j int x, y; uint8_t *ptr; uint16_t *ptr16; + AVExprState *state = geq->states[jobnr]; double values[VAR_VARS_NB]; values[VAR_W] = geq->values[VAR_W]; @@ -393,7 +404,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_eval2(geq->e[plane], state, values, geq); } ptr += linesize; } @@ -404,7 +415,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_eval2(geq->e[plane], state, values, geq); } } } @@ -416,7 +427,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; @@ -470,6 +481,8 @@ static av_cold void geq_uninit(AVFilterContext *ctx) av_expr_free(geq->e[i]); for (i = 0; i < NB_PLANES; i++) av_freep(&geq->pixel_sums); + for (i = 0; i < MAX_NB_THREADS; i++) + av_expr_state_free(&geq->states[i]); } static const AVFilterPad geq_inputs[] = {