avfilter/vf_floodfill: finish early if source and destination fill matches
authorPaul B Mahol <onemda@gmail.com>
Thu, 10 Oct 2019 19:50:03 +0000 (21:50 +0200)
committerPaul B Mahol <onemda@gmail.com>
Thu, 10 Oct 2019 19:52:51 +0000 (21:52 +0200)
Fixes #8236

libavfilter/vf_floodfill.c

index 323dd0e..cf8f689 100644 (file)
@@ -34,9 +34,10 @@ typedef struct FloodfillContext {
     const AVClass *class;
 
     int x, y;
-    int s0, s1, s2, s3;
-    int d0, d1, d2, d3;
+    int s[4];
+    int d[4];
 
+    int nb_planes;
     int back, front;
     Points *points;
 
@@ -238,12 +239,12 @@ static int config_input(AVFilterLink *inlink)
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     AVFilterContext *ctx = inlink->dst;
     FloodfillContext *s = ctx->priv;
-    int nb_planes = av_pix_fmt_count_planes(inlink->format);
     int depth;
 
+    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
     depth = desc->comp[0].depth;
     if (depth == 8) {
-        switch (nb_planes) {
+        switch (s->nb_planes) {
         case 1: s->set_pixel  = set_pixel1;
                 s->is_same    = is_same1;
                 s->pick_pixel = pick_pixel1; break;
@@ -255,7 +256,7 @@ static int config_input(AVFilterLink *inlink)
                 s->pick_pixel = pick_pixel4; break;
        }
     } else {
-        switch (nb_planes) {
+        switch (s->nb_planes) {
         case 1: s->set_pixel  = set_pixel1_16;
                 s->is_same    = is_same1_16;
                 s->pick_pixel = pick_pixel1_16; break;
@@ -280,17 +281,25 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 {
     AVFilterContext *ctx = link->dst;
     FloodfillContext *s = ctx->priv;
-    const unsigned d0 = s->d0;
-    const unsigned d1 = s->d1;
-    const unsigned d2 = s->d2;
-    const unsigned d3 = s->d3;
-    int s0 = s->s0;
-    int s1 = s->s1;
-    int s2 = s->s2;
-    int s3 = s->s3;
+    const unsigned d0 = s->d[0];
+    const unsigned d1 = s->d[1];
+    const unsigned d2 = s->d[2];
+    const unsigned d3 = s->d[3];
+    int s0 = s->s[0];
+    int s1 = s->s[1];
+    int s2 = s->s[2];
+    int s3 = s->s[3];
     const int w = frame->width;
     const int h = frame->height;
-    int ret;
+    int i, ret;
+
+    for (i = 0; i < s->nb_planes; i++) {
+        if (s->s[i] != s->d[i])
+            break;
+    }
+
+    if (i == s->nb_planes)
+        goto end;
 
     if (ret = av_frame_make_writable(frame))
         return ret;
@@ -337,6 +346,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
         }
     }
 
+end:
     return ff_filter_frame(ctx->outputs[0], frame);
 }
 
@@ -405,16 +415,16 @@ static const AVFilterPad floodfill_outputs[] = {
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
 static const AVOption floodfill_options[] = {
-    { "x",  "set pixel x coordinate",             OFFSET(x),  AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
-    { "y",  "set pixel y coordinate",             OFFSET(y),  AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
-    { "s0", "set source #0 component value",      OFFSET(s0), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
-    { "s1", "set source #1 component value",      OFFSET(s1), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
-    { "s2", "set source #2 component value",      OFFSET(s2), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
-    { "s3", "set source #3 component value",      OFFSET(s3), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
-    { "d0", "set destination #0 component value", OFFSET(d0), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
-    { "d1", "set destination #1 component value", OFFSET(d1), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
-    { "d2", "set destination #2 component value", OFFSET(d2), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
-    { "d3", "set destination #3 component value", OFFSET(d3), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "x",  "set pixel x coordinate",             OFFSET(x),    AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "y",  "set pixel y coordinate",             OFFSET(y),    AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "s0", "set source #0 component value",      OFFSET(s[0]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
+    { "s1", "set source #1 component value",      OFFSET(s[1]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
+    { "s2", "set source #2 component value",      OFFSET(s[2]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
+    { "s3", "set source #3 component value",      OFFSET(s[3]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS },
+    { "d0", "set destination #0 component value", OFFSET(d[0]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "d1", "set destination #1 component value", OFFSET(d[1]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "d2", "set destination #2 component value", OFFSET(d[2]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
+    { "d3", "set destination #3 component value", OFFSET(d[3]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS },
     { NULL }
 };