]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_geq.c
avcodec/mjpegdec: fix SOF check in EOI
[ffmpeg] / libavfilter / vf_geq.c
index 2905efae249b56ea2913b161b48dce14bd0d6a49..d9bb6ac256f816e354272bec21d414ea6c41e9b2 100644 (file)
@@ -33,6 +33,7 @@
 #include "libavutil/pixdesc.h"
 #include "internal.h"
 
+#define MAX_NB_THREADS 32
 #define NB_PLANES 4
 
 enum InterpolationMethods {
@@ -46,7 +47,7 @@ enum                                   { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_
 
 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
@@ -68,20 +69,20 @@ enum { Y = 0, U, V, A, G, B, R };
 #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" },
@@ -269,7 +270,7 @@ static av_cold int geq_init(AVFilterContext *ctx)
     }
 
     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,
         };
@@ -282,18 +283,20 @@ static av_cold int geq_init(AVFilterContext *ctx)
             "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];
     }
 
@@ -375,8 +378,6 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
     const int slice_start = (height *  jobnr) / nb_jobs;
     const int slice_end = (height * (jobnr+1)) / nb_jobs;
     int x, y;
-    uint8_t *ptr;
-    uint16_t *ptr16;
 
     double values[VAR_VARS_NB];
     values[VAR_W] = geq->values[VAR_W];
@@ -387,25 +388,25 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
     values[VAR_T] = geq->values[VAR_T];
 
     if (geq->bps == 8) {
+        uint8_t *ptr = geq->dst + linesize * slice_start;
         for (y = slice_start; y < slice_end; y++) {
-            ptr = geq->dst + linesize * y;
             values[VAR_Y] = y;
 
             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;
         }
-    }
-    else {
+    } else {
+        uint16_t *ptr16 = geq->dst16 + (linesize/2) * slice_start;
         for (y = slice_start; y < slice_end; y++) {
-            ptr16 = geq->dst16 + (linesize/2) * y;
             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;
         }
     }
 
@@ -416,7 +417,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;
@@ -466,8 +467,9 @@ static av_cold void geq_uninit(AVFilterContext *ctx)
     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);
 }
@@ -490,7 +492,7 @@ static const AVFilterPad geq_outputs[] = {
     { NULL }
 };
 
-AVFilter ff_vf_geq = {
+const AVFilter ff_vf_geq = {
     .name          = "geq",
     .description   = NULL_IF_CONFIG_SMALL("Apply generic equation to each pixel."),
     .priv_size     = sizeof(GEQContext),