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

Stefano Sabatini stefasab at gmail.com
Fri Oct 11 14:41:50 CEST 2013


On date Saturday 2013-10-05 22:49:55 +0200, Michael Niedermayer encoded:
> 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

1. this needs sh escaping, since "#" introduces a comment
2. in case we extend lavfi graph syntac, this may need escaping inner
   escaping since are likely going to use "#" for comments (indeed I
   was surprised that we already don't)

Thus I suggest another separator character. We use "|" in such
cases. Ideally we should have a syntax to represent matrixes / vectors
(e.g. employing Matlab notation), but this would cause escaping hell
since we already use both ";" and ":" in the filtergraph.

In conclusion "|" seems at the moment preferable.

> 
> 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 },

set source filter
set destination filter

> +
>      { 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);

not very robust (this will ignore leading characters, possibly
introduced because of typos)

> +    if (p) {
> +        p++;
> +    } else
> +        p = strchr(str, id[0]);

> +    if (!p)
> +        p = strchr(str, id[1]);

this is weird

> +    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;
> +    }

I'd prefer to have something like:

int parse_vector(SwsVector **vec, enun VectorType *vec_type, char **buf, void *log_ctx) {...}

int parse_filter(SwsFilter **filt, const char *str, void *log_ctx)
{
   SwsFilter *f = alloc_filter();
   char *p = str;
   while (p && *p) {
       SwsVector *v;
       ret = parse_vector(&v, ...);
       if (ret < 0) ERROR;
       switch (vec_type) {
           LH: filt->lumH = v; break;
           LV: filt->lumV = v; break;
           ...
       }
   }
   ...
   *filt = f;
   return 0;
   ...
}

[...]

I volunteer to write the parsing code during the weekend if you don't
want to do it yourself.
-- 
FFmpeg = Fostering and Fabulous Mere Porno Evanescent Glue


More information about the ffmpeg-devel mailing list