[FFmpeg-devel] [PATCH] frei0r wrapper
Måns Rullgård
mans
Mon Sep 13 11:31:52 CEST 2010
Stefano Sabatini <stefano.sabatini-lala at poste.it> writes:
>> > +typedef struct Frei0rContext {
>> > + f0r_update_f update;
>> > + void *dll;
>> > + char dll_filename[128];
>>
>> 128 is a bit short for a filename.
>
> Increased to 256.
Still easily exceeded. 1024 is the bare minimum I'd use. The system
limit is often 4096.
>> Also, does it really need to be stored here?
>
> It was to help error feedback, but I found an alternative way which
> doesn't require that.
>
>> Also "dll" has an unpleasant Windows ring to it.
>
> Stands for Dynamic Linking Loader so no Windows specific,
Have you ever seen another system use the DLL acronym?
> anyway changed to dl_handle.
>
>> > +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.
>
> Checked the specs, now I'm using FREI0R_PATH.
Where is this information? Just curious.
>> > + 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.
>
> Used RTLD_LAZY|RTLD_LOCAL, note that I'm not such an expert and I
> didn't noticed any difference so I'm simply trusting your word.
RTLD_LOCAL is a good choice for loading self-contained plugins. As
for LAZY vs NOW, LAZY loads faster, but if an undefined symbol can't
be resolved when it is first referenced, the entire application will
die. With RTLD_NOW, dlopen() reports an error if any symbol fails to
be resolved, and the caller has a chance to handle it. The choice
depends on how much you trust the loaded modules to be correct and
on the impact of aborting later.
For on-demand loading of third-party plugins into a larger
application, e.g. a web browser, RTLD_NOW would be preferred to avoid
having the entire browser die from attempting to use a bad plugin.
In our case, little is lost even if it dies during filtering. OTOH,
the plugins probably have few external dependencies and thus should
load quickly even with RTLD_NOW. Chose whichever you want.
> Updated patch in attachment.
> --
> FFmpeg = Fascinating & Funny Mastering Pacific Elastic Guru
>
> From 4cf8bce742c580dae100ffd2f523ccf1769afe7d Mon Sep 17 00:00:00 2001
> From: Stefano Sabatini <stefano.sabatini-lala at poste.it>
> Date: Tue, 24 Aug 2010 19:48:57 +0200
> Subject: [PATCH] Add frei0r filter.
>
> ---
> configure | 9 ++
> doc/filters.texi | 47 ++++++
> libavfilter/Makefile | 1 +
> libavfilter/allfilters.c | 1 +
> libavfilter/vf_frei0r.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 416 insertions(+), 0 deletions(-)
> create mode 100644 libavfilter/vf_frei0r.c
>
> diff --git a/configure b/configure
> index ae3d738..9bb8b51 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
> @@ -1047,6 +1049,7 @@ HAVE_LIST="
> poll_h
> setrlimit
> strerror_r
> + strtok_r
> struct_addrinfo
> struct_ipv6_mreq
> struct_sockaddr_in6
> @@ -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 strtok_r"
> +
> # protocols
> gopher_protocol_deps="network"
> http_protocol_deps="network"
> @@ -2631,6 +2637,7 @@ check_func mkstemp
> check_func ${malloc_prefix}posix_memalign && enable posix_memalign
> check_func setrlimit
> check_func strerror_r
> +check_func strtok_r
> check_func_headers io.h setmode
> check_func_headers lzo/lzo1x.h lzo1x_999_compress
> check_lib2 "windows.h psapi.h" GetProcessMemoryInfo -lpsapi
strtok_r is a standard POSIX function. There is no need to check for it.
> +#include <dlfcn.h>
> +#include <frei0r.h>
> +#include <float.h>
What do you need float.h for? I don't see anything from it being used.
> +static void *load_path(AVFilterContext *ctx, const char *prefix, const char *name)
> +{
> + char path[256];
> +
> + snprintf(path, sizeof(path), "%s%s", prefix, name);
> + av_log(ctx, AV_LOG_DEBUG, "Looking for frei0r effect in '%s'\n", path);
> + return dlopen(path, RTLD_LAZY|RTLD_LOCAL);
> +}
> +
> +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;
> + char dl_name[256], *frei0r_path;
> +
> + *(frei0r->params) = 0;
Useless ()
> + if (args)
> + sscanf(args, "%255[^:]:%255c", dl_name, frei0r->params);
> +
> + if (frei0r_path = av_strdup(getenv("FREI0R_PATH"))) {
GCC warns about assignment in conditional here. Please add some
parens to shut it up.
> + char *p, *ptr = NULL;
> + for (p = frei0r_path; p = strtok_r(p, ":", &ptr); p = NULL)
> + if (frei0r->dl_handle = load_path(ctx, p, dl_name))
> + break;
> + av_free(frei0r_path);
> + }
> +
> + if (!frei0r->dl_handle)
> + frei0r->dl_handle = load_path(ctx, "", dl_name);
Do not search FREI0R_PATH for absolute pathname arguments.
> + if (!frei0r->dl_handle) {
> + av_log(ctx, AV_LOG_ERROR, "Could not find module '%s'\n", dl_name);
> + 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;
> + 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" :
The type will never be filter here.
> + 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;
> +}
> +
> +static av_cold void uninit(AVFilterContext *ctx)
> +{
> + Frei0rContext *frei0r = ctx->priv;
> +
> + if (frei0r->destruct)
> + frei0r->destruct(frei0r->instance);
> + if (frei0r->deinit)
> + frei0r->deinit();
> + if (frei0r->dl_handle)
> + dlclose(frei0r->dl_handle);
Is uninit() called even if init() fails? If not, the ifs above are
unnecessary.
> + memset(&frei0r, 0, sizeof(frei0r));
> +}
> +
--
M?ns Rullg?rd
mans at mansr.com
More information about the ffmpeg-devel
mailing list