@@ -47,6 +47,7 @@ typedef struct BlendContext {
47
47
FilterParams params [4 ];
48
48
int tblend ;
49
49
AVFrame * prev_frame ; /* only used with tblend */
50
+ int nb_threads ;
50
51
} BlendContext ;
51
52
52
53
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,
139
140
double *values = sliceparam->values; \
140
141
int starty = sliceparam->starty; \
141
142
type *dst = (type*)_dst; \
142
- AVExpr *e = param ->e; \
143
+ AVExpr *e = sliceparam ->e; \
143
144
int y, x; \
144
145
dst_linesize /= div; \
145
146
top_linesize /= div; \
@@ -173,7 +174,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
173
174
const uint8_t * bottom = td -> bottom -> data [td -> plane ];
174
175
uint8_t * dst = td -> dst -> data [td -> plane ];
175
176
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 };
177
178
178
179
values [VAR_N ] = td -> inlink -> frame_count_out ;
179
180
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,
221
222
.inlink = inlink };
222
223
223
224
ff_filter_execute (ctx , filter_slice , & td , NULL ,
224
- FFMIN (outh , ff_filter_get_nb_threads ( ctx ) ));
225
+ FFMIN (outh , s -> nb_threads ));
225
226
}
226
227
227
228
if (!s -> tblend )
@@ -250,6 +251,7 @@ static av_cold int init(AVFilterContext *ctx)
250
251
BlendContext * s = ctx -> priv ;
251
252
252
253
s -> tblend = !strcmp (ctx -> filter -> name , "tblend" );
254
+ s -> nb_threads = ff_filter_get_nb_threads (ctx );
253
255
254
256
s -> fs .on_event = blend_frame_for_dualinput ;
255
257
return 0 ;
@@ -284,8 +286,14 @@ static av_cold void uninit(AVFilterContext *ctx)
284
286
ff_framesync_uninit (& s -> fs );
285
287
av_frame_free (& s -> prev_frame );
286
288
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
+
289
297
}
290
298
291
299
static int config_params (AVFilterContext * ctx )
@@ -309,10 +317,19 @@ static int config_params(AVFilterContext *ctx)
309
317
return AVERROR (ENOMEM );
310
318
}
311
319
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
+ }
316
333
param -> blend = s -> depth > 8 ? s -> depth > 16 ? blend_expr_32bit : blend_expr_16bit : blend_expr_8bit ;
317
334
}
318
335
}
0 commit comments