[FFmpeg-devel] [PATCHv2 2/3] avfilter/vf_geq: use per-thread state for expression evaluation
Marton Balint
cus at passwd.hu
Tue Dec 31 00:25:04 EET 2019
Fixes ticket #7528.
Signed-off-by: Marton Balint <cus at 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
More information about the ffmpeg-devel
mailing list