[FFmpeg-devel] [PATCH] frei0r wrapper

Måns Rullgård mans
Wed Sep 8 17:16:59 CEST 2010


Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:

>  configure                |    8 +
>  doc/filters.texi         |   46 ++++++
>  libavfilter/Makefile     |    1 +
>  libavfilter/allfilters.c |    1 +
>  libavfilter/vf_frei0r.c  |  353 ++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 409 insertions(+), 0 deletions(-)
>  create mode 100644 libavfilter/vf_frei0r.c
>
> diff --git a/configure b/configure
> index ae3d738..7a2117d 100755
> --- a/configure
> +++ b/configure
> @@ -162,6 +162,7 @@ Configuration options:
>  External library support:
>    --enable-avisynth        enable reading of AVISynth script files [no]
>    --enable-bzlib           enable bzlib [autodetect]
> +  --enable-frei0r          enable frei0r video filtering
>    --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]
>    --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]
>    --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
> @@ -872,6 +873,7 @@ CONFIG_LIST="
>      ffprobe
>      ffserver
>      fft
> +    frei0r
>      golomb
>      gpl
>      gray
> @@ -1006,6 +1008,7 @@ HAVE_LIST="
>      fast_cmov
>      fcntl
>      fork
> +    frei0r
>      getaddrinfo
>      gethrtime
>      GetProcessMemoryInfo

You can't have something in both of those lists.  This one should be
in CONFIG_LIST only.

> @@ -1379,6 +1382,9 @@ vfwcap_indev_extralibs="-lavicap32"
>  x11_grab_device_indev_deps="x11grab XShmCreateImage"
>  x11_grab_device_indev_extralibs="-lX11 -lXext -lXfixes"
>  
> +# filters
> +frei0r_filter_deps="frei0r dlopen"
> +
>  # protocols
>  gopher_protocol_deps="network"
>  http_protocol_deps="network"
> @@ -2704,6 +2710,7 @@ check_mathfunc truncf
>  
>  # these are off by default, so fail if requested and not available
>  enabled avisynth   && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32
> +enabled frei0r     && check_header frei0r.h

|| die "suitable message"

> diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c
> new file mode 100644
> index 0000000..4cb1cd5
> --- /dev/null
> +++ b/libavfilter/vf_frei0r.c
> @@ -0,0 +1,353 @@
> +/*
> + * Stefano Sabatini 2010
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file
> + * frei0r wrapper
> + */
> +
> +/* #define DEBUG */
> +
> +#include <dlfcn.h>
> +#include <frei0r.h>
> +#include <float.h>
> +#include "avfilter.h"
> +#include "parseutils.h"
> +
> +typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height);
> +typedef void (*f0r_destruct_f)(f0r_instance_t instance);
> +typedef void (*f0r_deinit_f)(void);
> +typedef int (*f0r_init_f)(void);
> +typedef void (*f0r_get_plugin_info_f)(f0r_plugin_info_t *info);
> +typedef void (*f0r_get_param_info_f)(f0r_param_info_t *info, int param_index);
> +typedef void (*f0r_update_f)(f0r_instance_t instance, double time, const uint32_t *inframe, uint32_t *outframe);
> +typedef void (*f0r_update2_f)(f0r_instance_t instance, double time, const uint32_t *inframe1, const uint32_t *inframe2, const uint32_t *inframe3, uint32_t *outframe);
> +typedef void (*f0r_set_param_value_f)(f0r_instance_t instance, f0r_param_t param, int param_index);
> +typedef void (*f0r_get_param_value_f)(f0r_instance_t instance, f0r_param_t param, int param_index);
> +
> +typedef struct Frei0rContext {
> +    f0r_update_f update;
> +    void *dll;
> +    char dll_filename[128];

128 is a bit short for a filename.  Also, does it really need to be
stored here?  Also "dll" has an unpleasant Windows ring to it.

> +    f0r_instance_t instance;
> +    f0r_plugin_info_t plugin_info;
> +
> +    f0r_get_param_info_f  get_param_info;
> +    f0r_get_param_value_f get_param_value;
> +    f0r_set_param_value_f set_param_value;
> +    f0r_construct_f       construct;
> +    f0r_destruct_f        destruct;
> +    f0r_deinit_f          deinit;
> +    char params[256];
> +} Frei0rContext;
> +
> +static void *load_sym(AVFilterContext *ctx, const char *sym_name)
> +{
> +    Frei0rContext *frei0r = ctx->priv;
> +    void *sym = dlsym(frei0r->dll, sym_name);
> +    if (!sym)
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Could not find symbol '%s' in module '%s'\n", sym_name, frei0r->dll_filename);
> +    return sym;
> +}
> +
> +static int set_param(AVFilterContext *ctx, f0r_param_info_t info, int index, char *param)
> +{
> +    Frei0rContext *frei0r = ctx->priv;
> +    union {
> +        double d;
> +        f0r_param_color_t col;
> +        f0r_param_position_t pos;
> +    } val;
> +
> +    switch (info.type) {
> +    case F0R_PARAM_BOOL:
> +        if      (!strcmp(param, "y")) val.d = 1.0;
> +        else if (!strcmp(param, "n")) val.d = 0.0;
> +        else goto fail;
> +    break;

Strange indentation.

> +    case F0R_PARAM_DOUBLE:
> +    {
> +        char *tail;
> +        val.d = strtod(param, &tail);
> +        if (*tail || val.d == HUGE_VAL)
> +            goto fail;
> +    }
> +    break;

Ditto.

> +    case F0R_PARAM_COLOR:
> +        if (sscanf(param, "%f/%f/%f", &val.col.r, &val.col.g, &val.col.b) != 3) {
> +            uint8_t rgba[4];
> +            if (av_parse_color(rgba, param, ctx) < 0)
> +                goto fail;
> +            val.col.r = rgba[0] / 255.0;
> +            val.col.g = rgba[1] / 255.0;
> +            val.col.b = rgba[2] / 255.0;
> +        }
> +    break;

And here.

> +    case F0R_PARAM_POSITION:
> +        if (sscanf(param, "%lf/%lf", &val.pos.x, &val.pos.y) != 2)
> +            goto fail;
> +    break;

Here too.

> +    default: /* F0R_PARAM_STRING */
> +        break;

But not here.  However, the default label is rather pointless since it
contains no code.

> +    }
> +
> +    frei0r->set_param_value(frei0r->instance, &val, index);
> +    return 0;
> +
> +fail:
> +    av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for parameter '%s'",
> +           param, info.name);
> +    return AVERROR(EINVAL);
> +}
> +

[...]

> +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
> +{
> +    Frei0rContext *frei0r = ctx->priv;
> +    f0r_init_f            f0r_init;
> +    f0r_get_plugin_info_f f0r_get_plugin_info;
> +    f0r_plugin_info_t *pi;
> +    int i;
> +    const char *dll_prefixes[]= {
> +        "", "/usr/lib/frei0r-1/", "/usr/local/lib/frei0r-1/"
> +    };

That's a rather limited set.  Is there some environment variable
customarily used to find these files?  If so, use it.  If not, pick a
suitable name and use that.

> +    char dll_filename[128];
> +
> +    *(frei0r->params) = 0;
> +
> +    if (args)
> +        sscanf(args, "%127[^:]:%255c", dll_filename, frei0r->params);
> +
> +    for (i = 0; i < FF_ARRAY_ELEMS(dll_prefixes); i++) {
> +        snprintf(frei0r->dll_filename, sizeof(frei0r->dll_filename), "%s%s", dll_prefixes[i], dll_filename);
> +        if ((frei0r->dll = dlopen(frei0r->dll_filename, RTLD_NOW)))

Why RTLD_NOW?  You also should specify one of RTLD_GLOBAL or
RTLD_LOCAL.  I suggest the latter.

> +            break;
> +    }
> +
> +    if (!frei0r->dll) {
> +        av_log(ctx, AV_LOG_ERROR, "Could not find module '%s'\n", dll_filename);
> +        return AVERROR(EINVAL);
> +    }
> +
> +    if (!(f0r_init                = load_sym(ctx, "f0r_init"           )) ||
> +        !(f0r_get_plugin_info     = load_sym(ctx, "f0r_get_plugin_info")) ||
> +        !(frei0r->get_param_info  = load_sym(ctx, "f0r_get_param_info" )) ||
> +        !(frei0r->get_param_value = load_sym(ctx, "f0r_get_param_value")) ||
> +        !(frei0r->set_param_value = load_sym(ctx, "f0r_set_param_value")) ||
> +        !(frei0r->update          = load_sym(ctx, "f0r_update"         )) ||
> +        !(frei0r->construct       = load_sym(ctx, "f0r_construct"      )) ||
> +        !(frei0r->destruct        = load_sym(ctx, "f0r_destruct"       )) ||
> +        !(frei0r->deinit          = load_sym(ctx, "f0r_deinit"         )))
> +        return AVERROR(EINVAL);
> +
> +    if (f0r_init() < 0) {
> +        av_log(ctx, AV_LOG_ERROR, "Could not init the frei0r module");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    f0r_get_plugin_info(&frei0r->plugin_info);
> +    pi = &(frei0r->plugin_info);

Useless ().

> +    if (pi->plugin_type != F0R_PLUGIN_TYPE_FILTER) {
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Invalid type '%s' for the plugin, a filter plugin was expected\n",
> +               pi->plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" :
> +               pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" :
> +               pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" :
> +               pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    av_log(ctx, AV_LOG_INFO,
> +           "name:%s author:'%s' explanation:'%s' color_model:%s "
> +           "frei0r_version:%d version:%d.%d num_params:%d\n",
> +           pi->name, pi->author, pi->explanation,
> +           pi->color_model == F0R_COLOR_MODEL_BGRA8888 ? "bgra8888" :
> +           pi->color_model == F0R_COLOR_MODEL_RGBA8888 ? "rgba8888" :
> +           pi->color_model == F0R_COLOR_MODEL_PACKED32 ? "packed32" : "unknown",
> +           pi->frei0r_version, pi->major_version, pi->minor_version, pi->num_params);
> +
> +    return 0;
> +}

-- 
M?ns Rullg?rd
mans at mansr.com



More information about the ffmpeg-devel mailing list