[FFmpeg-devel] [PATCH] swscale: Support setting filters through AVOptions

Michael Niedermayer michaelni at gmx.at
Sat Oct 5 22:49:55 CEST 2013


anything else could be used or the routine even be made to accept
any character as separator.

Docs are omitted as i expect long bikesheds on the syntax and which
separator char to use

Examples:
-vf scale=640:480:src_filter=1#h-0.5#0#0#0#1
-vf scale=640:480:src_filter=1#c1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1
-vf scale=640:480:src_filter=1#lh-0.2#1#-0.2#lv1#0#0#0#0#0#0#0#0#0#0#0#0#1

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
---
 libswscale/options.c          |    3 ++
 libswscale/swscale_internal.h |    4 +++
 libswscale/utils.c            |   79 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/libswscale/options.c b/libswscale/options.c
index 2b3147b..0ebb2b6 100644
--- a/libswscale/options.c
+++ b/libswscale/options.c
@@ -74,6 +74,9 @@ static const AVOption swscale_options[] = {
     { "bayer",           "bayer dither",                  0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_BAYER  }, INT_MIN, INT_MAX,        VE, "sws_dither" },
     { "ed",              "error diffusion",               0,                 AV_OPT_TYPE_CONST,  { .i64  = SWS_DITHER_ED     }, INT_MIN, INT_MAX,        VE, "sws_dither" },
 
+    { "src_filter",      "source filter",                 OFFSET(src_filter_string), AV_OPT_TYPE_STRING,  { .str = NULL      }, INT_MIN, INT_MAX,        VE },
+    { "dst_filter",      "destination filter",            OFFSET(dst_filter_string), AV_OPT_TYPE_STRING,  { .str = NULL      }, INT_MIN, INT_MAX,        VE },
+
     { NULL }
 };
 
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 33fdfc2..4b6fff6 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -296,6 +296,10 @@ typedef struct SwsContext {
     int vChrDrop;                 ///< Binary logarithm of extra vertical subsampling factor in source image chroma planes specified by user.
     int sliceDir;                 ///< Direction that slices are fed to the scaler (1 = top-to-bottom, -1 = bottom-to-top).
     double param[2];              ///< Input parameters for scaling algorithms that need them.
+    char *src_filter_string;
+    char *dst_filter_string;
+    SwsFilter *src_filter;
+    SwsFilter *dst_filter;
 
     uint32_t pal_yuv[256];
     uint32_t pal_rgb[256];
diff --git a/libswscale/utils.c b/libswscale/utils.c
index a2e3ce1..29faabb 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -42,6 +42,7 @@
 #include "libavutil/avutil.h"
 #include "libavutil/bswap.h"
 #include "libavutil/cpu.h"
+#include "libavutil/eval.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
@@ -238,6 +239,68 @@ const char *sws_format_name(enum AVPixelFormat format)
 }
 #endif
 
+static SwsVector *parse_subfilter(const SwsContext *c, const char *str, const char *id)
+{
+    const char *p;
+    int i;
+    SwsVector *v = av_mallocz(sizeof(SwsVector));
+
+    p = strstr(str, id);
+    if (p) {
+        p++;
+    } else
+        p = strchr(str, id[0]);
+    if (!p)
+        p = strchr(str, id[1]);
+    if (p)
+        p++;
+    else
+        p = str;
+    for (i=0; ; i++) {
+        char *end;
+        if (av_reallocp(&v->coeff, (i+1) * sizeof(*v->coeff)) < 0)
+            goto fail;
+        v->coeff[i] = av_strtod(p, &end);
+        if (end == p)
+            goto fail;
+        p = (const char *)end;
+        if(*p == '#' && p[1]) {
+            p++;
+            if (*p == 'l' || *p == 'c' || *p == 'h' || *p == 'v')
+                break;
+        } else if(!*p)
+            break;
+        else
+            goto fail;
+    }
+    v->length = i + 1;
+    return v;
+fail:
+    av_log(c, AV_LOG_ERROR, "parse_subfilter failed at %s\n", p);
+    sws_freeVec(v);
+    return NULL;
+}
+
+static SwsFilter *parse_filter(const SwsContext *c, const char *str)
+{
+    SwsFilter *f;
+    if (!str)
+        return NULL;
+    f = av_mallocz(sizeof(SwsFilter));
+    if (!f)
+        return NULL;
+    f->lumH = parse_subfilter(c, str, "lh");
+    f->lumV = parse_subfilter(c, str, "lv");
+    f->chrH = parse_subfilter(c, str, "ch");
+    f->chrV = parse_subfilter(c, str, "cv");
+    if (!f->lumH || !f->lumV || !f->chrH || !f->chrV) {
+        sws_freeFilter(f);
+        return NULL;
+    }
+
+    return f;
+}
+
 static double getSplineCoeff(double a, double b, double c, double d,
                              double dist)
 {
@@ -1168,6 +1231,17 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
         return AVERROR(EINVAL);
     }
 
+    sws_freeFilter(c->src_filter);
+    c->src_filter = NULL;
+    sws_freeFilter(c->dst_filter);
+    c->dst_filter = NULL;
+
+
+    if (!dstFilter)
+        c->dst_filter = dstFilter = parse_filter(c, c->dst_filter_string);
+    if (!srcFilter)
+        c->src_filter = srcFilter = parse_filter(c, c->src_filter_string);
+
     if (!dstFilter)
         dstFilter = &dummyFilter;
     if (!srcFilter)
@@ -2028,6 +2102,11 @@ void sws_freeContext(SwsContext *c)
     av_freep(&c->yuvTable);
     av_freep(&c->formatConvBuffer);
 
+    sws_freeFilter(c->src_filter);
+    c->src_filter = NULL;
+    sws_freeFilter(c->dst_filter);
+    c->dst_filter = NULL;
+
     av_free(c);
 }
 
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list