Fixes ticket #7528. Signed-off-by: Marton Balint <c...@passwd.hu> --- 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[] = { -- 2.16.4 _______________________________________________ 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".