#include "libavutil/pixdesc.h"
#include "internal.h"
+#define MAX_NB_THREADS 32
#define NB_PLANES 4
enum InterpolationMethods {
typedef struct GEQContext {
const AVClass *class;
- AVExpr *e[NB_PLANES]; ///< expressions for each plane
+ AVExpr *e[NB_PLANES][MAX_NB_THREADS]; ///< expressions for each plane and thread
char *expr_str[4+3]; ///< expression strings for each plane
AVFrame *picref; ///< current input buffer
uint8_t *dst; ///< reference pointer to the 8bits output
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static const AVOption geq_options[] = {
- { "lum_expr", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "lum", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "cb_expr", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "cb", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "cr_expr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "cr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "alpha_expr", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "a", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "red_expr", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "r", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "green_expr", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "g", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "blue_expr", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "b", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+ { "lum_expr", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "lum", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "cb_expr", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "cb", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "cr_expr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "cr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "alpha_expr", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "a", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "red_expr", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "r", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "green_expr", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "g", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "blue_expr", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "b", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
{ "interpolation","set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
{ "i", "set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
{ "nearest", "nearest interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST}, 0, 0, FLAGS, "interp" },
}
for (plane = 0; plane < NB_PLANES; plane++) {
- static double (*p[])(void *, double, double) = {
+ static double (*const p[])(void *, double, double) = {
lum , cb , cr , alpha ,
lumsum, cbsum, crsub, alphasum,
};
"gsum", "bsum", "rsum", "alphasum", "psum",
NULL };
const char *const *func2_names = geq->is_rgb ? func2_rgb_names : func2_yuv_names;
- double (*func2[])(void *, double, double) = {
+ double (*const func2[])(void *, double, double) = {
lum , cb , cr , alpha , p[plane],
lumsum, cbsum, crsub, alphasum, p[plane + 4],
NULL };
int counter[10] = {0};
- ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names,
- NULL, NULL, func2_names, func2, 0, ctx);
- if (ret < 0)
- break;
+ for (int i = 0; i < MAX_NB_THREADS; i++) {
+ ret = av_expr_parse(&geq->e[plane][i], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names,
+ NULL, NULL, func2_names, func2, 0, ctx);
+ if (ret < 0)
+ goto end;
+ }
- av_expr_count_func(geq->e[plane], counter, FF_ARRAY_ELEMS(counter), 2);
+ av_expr_count_func(geq->e[plane][0], counter, FF_ARRAY_ELEMS(counter), 2);
geq->needs_sum[plane] = counter[5] + counter[6] + counter[7] + counter[8] + counter[9];
}
for (x = 0; x < width; x++) {
values[VAR_X] = x;
- ptr[x] = av_expr_eval(geq->e[plane], values, geq);
+ ptr[x] = av_expr_eval(geq->e[plane][jobnr], values, geq);
}
ptr += linesize;
}
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_eval(geq->e[plane][jobnr], values, geq);
}
ptr16 += linesize/2;
}
{
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;
int i;
GEQContext *geq = ctx->priv;
- for (i = 0; i < FF_ARRAY_ELEMS(geq->e); i++)
- av_expr_free(geq->e[i]);
+ for (i = 0; i < NB_PLANES; i++)
+ for (int j = 0; j < MAX_NB_THREADS; j++)
+ av_expr_free(geq->e[i][j]);
for (i = 0; i < NB_PLANES; i++)
av_freep(&geq->pixel_sums);
}