Skip to content

Commit 64330e3

Browse files
committed
avfilter/blend: use a per-thread AVExpr
Otherwise expression state is accessed and changed from multiple threads. Fixes ticket #10987. Signed-off-by: Marton Balint <[email protected]>
1 parent a69a0b6 commit 64330e3

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

libavfilter/blend.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ enum BlendMode {
7272
typedef struct SliceParams {
7373
double *values;
7474
int starty;
75+
AVExpr *e;
7576
} SliceParams;
7677

7778
typedef struct FilterParams {
7879
enum BlendMode mode;
7980
double opacity;
80-
AVExpr *e;
81+
AVExpr **e;
8182
char *expr_str;
8283
void (*blend)(const uint8_t *top, ptrdiff_t top_linesize,
8384
const uint8_t *bottom, ptrdiff_t bottom_linesize,

libavfilter/vf_blend.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef struct BlendContext {
4747
FilterParams params[4];
4848
int tblend;
4949
AVFrame *prev_frame; /* only used with tblend */
50+
int nb_threads;
5051
} BlendContext;
5152

5253
static const char *const var_names[] = { "X", "Y", "W", "H", "SW", "SH", "T", "N", "A", "B", "TOP", "BOTTOM", NULL };
@@ -139,7 +140,7 @@ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize,
139140
double *values = sliceparam->values; \
140141
int starty = sliceparam->starty; \
141142
type *dst = (type*)_dst; \
142-
AVExpr *e = param->e; \
143+
AVExpr *e = sliceparam->e; \
143144
int y, x; \
144145
dst_linesize /= div; \
145146
top_linesize /= div; \
@@ -173,7 +174,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
173174
const uint8_t *bottom = td->bottom->data[td->plane];
174175
uint8_t *dst = td->dst->data[td->plane];
175176
double values[VAR_VARS_NB];
176-
SliceParams sliceparam = {.values = &values[0], .starty = slice_start};
177+
SliceParams sliceparam = {.values = &values[0], .starty = slice_start, .e = td->param->e ? td->param->e[jobnr] : NULL};
177178

178179
values[VAR_N] = td->inlink->frame_count_out;
179180
values[VAR_T] = td->dst->pts == AV_NOPTS_VALUE ? NAN : td->dst->pts * av_q2d(td->inlink->time_base);
@@ -221,7 +222,7 @@ static AVFrame *blend_frame(AVFilterContext *ctx, AVFrame *top_buf,
221222
.inlink = inlink };
222223

223224
ff_filter_execute(ctx, filter_slice, &td, NULL,
224-
FFMIN(outh, ff_filter_get_nb_threads(ctx)));
225+
FFMIN(outh, s->nb_threads));
225226
}
226227

227228
if (!s->tblend)
@@ -250,6 +251,7 @@ static av_cold int init(AVFilterContext *ctx)
250251
BlendContext *s = ctx->priv;
251252

252253
s->tblend = !strcmp(ctx->filter->name, "tblend");
254+
s->nb_threads = ff_filter_get_nb_threads(ctx);
253255

254256
s->fs.on_event = blend_frame_for_dualinput;
255257
return 0;
@@ -284,8 +286,14 @@ static av_cold void uninit(AVFilterContext *ctx)
284286
ff_framesync_uninit(&s->fs);
285287
av_frame_free(&s->prev_frame);
286288

287-
for (i = 0; i < FF_ARRAY_ELEMS(s->params); i++)
288-
av_expr_free(s->params[i].e);
289+
for (i = 0; i < FF_ARRAY_ELEMS(s->params); i++) {
290+
if (s->params[i].e) {
291+
for (int j = 0; j < s->nb_threads; j++)
292+
av_expr_free(s->params[i].e[j]);
293+
av_freep(&s->params[i].e);
294+
}
295+
}
296+
289297
}
290298

291299
static int config_params(AVFilterContext *ctx)
@@ -309,10 +317,19 @@ static int config_params(AVFilterContext *ctx)
309317
return AVERROR(ENOMEM);
310318
}
311319
if (param->expr_str) {
312-
ret = av_expr_parse(&param->e, param->expr_str, var_names,
313-
NULL, NULL, NULL, NULL, 0, ctx);
314-
if (ret < 0)
315-
return ret;
320+
if (!param->e) {
321+
param->e = av_calloc(s->nb_threads, sizeof(*param->e));
322+
if (!param->e)
323+
return AVERROR(ENOMEM);
324+
}
325+
for (int i = 0; i < s->nb_threads; i++) {
326+
av_expr_free(param->e[i]);
327+
param->e[i] = NULL;
328+
ret = av_expr_parse(&param->e[i], param->expr_str, var_names,
329+
NULL, NULL, NULL, NULL, 0, ctx);
330+
if (ret < 0)
331+
return ret;
332+
}
316333
param->blend = s->depth > 8 ? s->depth > 16 ? blend_expr_32bit : blend_expr_16bit : blend_expr_8bit;
317334
}
318335
}

0 commit comments

Comments
 (0)