vf_frei0r: switch to an AVOptions-based system.
authorAnton Khirnov <anton@khirnov.net>
Mon, 25 Feb 2013 20:21:29 +0000 (21:21 +0100)
committerAnton Khirnov <anton@khirnov.net>
Tue, 9 Apr 2013 17:04:28 +0000 (19:04 +0200)
doc/filters.texi
libavfilter/avfilter.c
libavfilter/vf_frei0r.c

index 6949621..8ac0f29 100644 (file)
@@ -1118,20 +1118,22 @@ Apply a frei0r effect to the input video.
 To enable compilation of this filter you need to install the frei0r
 header and configure Libav with --enable-frei0r.
 
-The filter supports the syntax:
-@example
-@var{filter_name}[@{:|=@}@var{param1}:@var{param2}:...:@var{paramN}]
-@end example
+This filter accepts the following options:
+
+@table @option
+
+@item filter_name
+The name to the frei0r effect to load. If the environment variable
+@env{FREI0R_PATH} is defined, the frei0r effect is searched in each one of the
+directories specified by the colon separated list in @env{FREIOR_PATH},
+otherwise in the standard frei0r paths, which are in this order:
+@file{HOME/.frei0r-1/lib/}, @file{/usr/local/lib/frei0r-1/},
+@file{/usr/lib/frei0r-1/}.
 
-@var{filter_name} is the name to the frei0r effect to load. If the
-environment variable @env{FREI0R_PATH} is defined, the frei0r effect
-is searched in each one of the directories specified by the colon
-separated list in @env{FREIOR_PATH}, otherwise in the standard frei0r
-paths, which are in this order: @file{HOME/.frei0r-1/lib/},
-@file{/usr/local/lib/frei0r-1/}, @file{/usr/lib/frei0r-1/}.
+@item filter_params
+A '|'-separated list of parameters to pass to the frei0r effect.
 
-@var{param1}, @var{param2}, ... , @var{paramN} specify the parameters
-for the frei0r effect.
+@end table
 
 A frei0r effect parameter can be a boolean (whose values are specified
 with "y" and "n"), a double, a color (specified by the syntax
@@ -1146,7 +1148,7 @@ effect parameter is not specified the default value is set.
 Some examples follow:
 @example
 # apply the distort0r effect, set the first two double parameters
-frei0r=distort0r:0.5:0.01
+frei0r=filter_name=distort0r:filter_params=0.5|0.01
 
 # apply the colordistance effect, takes a color as first parameter
 frei0r=colordistance:0.2/0.3/0.4
@@ -1155,7 +1157,7 @@ frei0r=colordistance:0x112233
 
 # apply the perspective effect, specify the top left and top right
 # image positions
-frei0r=perspective:0.2/0.2:0.8/0.2
+frei0r=perspective:0.2/0.2|0.8/0.2
 @end example
 
 For more information see:
@@ -2375,24 +2377,33 @@ Provide a frei0r source.
 To enable compilation of this filter you need to install the frei0r
 header and configure Libav with --enable-frei0r.
 
-The source supports the syntax:
-@example
-@var{size}:@var{rate}:@var{src_name}[@{=|:@}@var{param1}:@var{param2}:...:@var{paramN}]
-@end example
+This source accepts the following options:
+
+@table @option
+
+@item size
+The size of the video to generate, may be a string of the form
+@var{width}x@var{height} or a frame size abbreviation.
 
-@var{size} is the size of the video to generate, may be a string of the
-form @var{width}x@var{height} or a frame size abbreviation.
-@var{rate} is the rate of the video to generate, may be a string of
-the form @var{num}/@var{den} or a frame rate abbreviation.
-@var{src_name} is the name to the frei0r source to load. For more
-information regarding frei0r and how to set the parameters read the
-section @ref{frei0r} in the description of the video filters.
+@item framerate
+Framerate of the generated video, may be a string of the form
+@var{num}/@var{den} or a frame rate abbreviation.
+
+@item filter_name
+The name to the frei0r source to load. For more information regarding frei0r and
+how to set the parameters read the section @ref{frei0r} in the description of
+the video filters.
+
+@item filter_params
+A '|'-separated list of parameters to pass to the frei0r source.
+
+@end table
 
 Some examples follow:
 @example
 # generate a frei0r partik0l source with size 200x200 and framerate 10
 # which is overlayed on the overlay filter main input
-frei0r_src=200x200:10:partik0l=1234 [overlay]; [in][overlay] overlay
+frei0r_src=size=200x200:framerate=10:filter_name=partik0l:filter_params=1234 [overlay]; [in][overlay] overlay
 @end example
 
 @section rgbtestsrc, testsrc
index e5a7f13..29b0583 100644 (file)
@@ -487,19 +487,36 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
             if (ret < 0)
                 goto fail;
 #if FF_API_OLD_FILTER_OPTS
-        } else if (!strcmp(filter->filter->name, "format") ||
-                   !strcmp(filter->filter->name, "noformat")) {
+        } else if (!strcmp(filter->filter->name, "format")     ||
+                   !strcmp(filter->filter->name, "noformat")   ||
+                   !strcmp(filter->filter->name, "frei0r")     ||
+                   !strcmp(filter->filter->name, "frei0r_src")) {
             /* a hack for compatibility with the old syntax
              * replace colons with |s */
             char *copy = av_strdup(args);
             char *p    = copy;
+            int nb_leading = 0; // number of leading colons to skip
 
             if (!copy) {
                 ret = AVERROR(ENOMEM);
                 goto fail;
             }
 
-            if (strchr(copy, ':')) {
+            if (!strcmp(filter->filter->name, "frei0r"))
+                nb_leading = 1;
+            else if (!strcmp(filter->filter->name, "frei0r_src"))
+                nb_leading = 3;
+
+            while (nb_leading--) {
+                p = strchr(p, ':');
+                if (!p) {
+                    p = copy + strlen(copy);
+                    break;
+                }
+                p++;
+            }
+
+            if (strchr(p, ':')) {
                 av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use "
                        "'|' to separate the list items.\n");
             }
index fab0d15..e749fe7 100644 (file)
@@ -35,6 +35,7 @@
 #include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "avfilter.h"
 #include "formats.h"
@@ -53,6 +54,7 @@ typedef void (*f0r_set_param_value_f)(f0r_instance_t instance, f0r_param_t param
 typedef void (*f0r_get_param_value_f)(f0r_instance_t instance, f0r_param_t param, int param_index);
 
 typedef struct Frei0rContext {
+    const AVClass *class;
     f0r_update_f update;
     void *dl_handle;            /* dynamic library handle   */
     f0r_instance_t instance;
@@ -64,7 +66,11 @@ typedef struct Frei0rContext {
     f0r_construct_f       construct;
     f0r_destruct_f        destruct;
     f0r_deinit_f          deinit;
-    char params[256];
+
+    char *dl_name;
+    char *params;
+    char *size;
+    char *framerate;
 
     /* only used by the source */
     int w, h;
@@ -143,7 +149,7 @@ static int set_params(AVFilterContext *ctx, const char *params)
         frei0r->get_param_info(&info, i);
 
         if (*params) {
-            if (!(param = av_get_token(&params, ":")))
+            if (!(param = av_get_token(&params, "|")))
                 return AVERROR(ENOMEM);
             params++;               /* skip ':' */
             ret = set_param(ctx, info, i, param);
@@ -222,6 +228,11 @@ static av_cold int frei0r_init(AVFilterContext *ctx,
     f0r_plugin_info_t *pi;
     char *path;
 
+    if (!dl_name) {
+        av_log(ctx, AV_LOG_ERROR, "No filter name provided.\n");
+        return AVERROR(EINVAL);
+    }
+
     /* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */
     if ((path = av_strdup(getenv("FREI0R_PATH")))) {
         char *p, *ptr = NULL;
@@ -287,13 +298,8 @@ static av_cold int frei0r_init(AVFilterContext *ctx,
 static av_cold int filter_init(AVFilterContext *ctx, const char *args)
 {
     Frei0rContext *frei0r = ctx->priv;
-    char dl_name[1024], c;
-    *frei0r->params = 0;
 
-    if (args)
-        sscanf(args, "%1023[^:=]%c%255c", dl_name, &c, frei0r->params);
-
-    return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_FILTER);
+    return frei0r_init(ctx, frei0r->dl_name, F0R_PLUGIN_TYPE_FILTER);
 }
 
 static av_cold void uninit(AVFilterContext *ctx)
@@ -306,8 +312,6 @@ static av_cold void uninit(AVFilterContext *ctx)
         frei0r->deinit();
     if (frei0r->dl_handle)
         dlclose(frei0r->dl_handle);
-
-    memset(frei0r, 0, sizeof(*frei0r));
 }
 
 static int config_input_props(AVFilterLink *inlink)
@@ -368,6 +372,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     return ff_filter_frame(outlink, out);
 }
 
+#define OFFSET(x) offsetof(Frei0rContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
+static const AVOption filter_options[] = {
+    { "filter_name",   NULL, OFFSET(dl_name), AV_OPT_TYPE_STRING, .flags = FLAGS },
+    { "filter_params", NULL, OFFSET(params),  AV_OPT_TYPE_STRING, .flags = FLAGS },
+    { NULL },
+};
+
+static const AVClass filter_class = {
+    .class_name = "frei0r",
+    .item_name  = av_default_item_name,
+    .option     = filter_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 static const AVFilterPad avfilter_vf_frei0r_inputs[] = {
     {
         .name         = "default",
@@ -395,6 +414,7 @@ AVFilter avfilter_vf_frei0r = {
     .uninit = uninit,
 
     .priv_size = sizeof(Frei0rContext),
+    .priv_class = &filter_class,
 
     .inputs    = avfilter_vf_frei0r_inputs,
 
@@ -404,31 +424,22 @@ AVFilter avfilter_vf_frei0r = {
 static av_cold int source_init(AVFilterContext *ctx, const char *args)
 {
     Frei0rContext *frei0r = ctx->priv;
-    char dl_name[1024], c;
-    char frame_size[128] = "";
-    char frame_rate[128] = "";
     AVRational frame_rate_q;
 
-    memset(frei0r->params, 0, sizeof(frei0r->params));
-
-    if (args)
-        sscanf(args, "%127[^:]:%127[^:]:%1023[^:=]%c%255c",
-               frame_size, frame_rate, dl_name, &c, frei0r->params);
-
-    if (av_parse_video_size(&frei0r->w, &frei0r->h, frame_size) < 0) {
-        av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frame_size);
+    if (av_parse_video_size(&frei0r->w, &frei0r->h, frei0r->size) < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frei0r->size);
         return AVERROR(EINVAL);
     }
 
-    if (av_parse_video_rate(&frame_rate_q, frame_rate) < 0 ||
+    if (av_parse_video_rate(&frame_rate_q, frei0r->framerate) < 0 ||
         frame_rate_q.den <= 0 || frame_rate_q.num <= 0) {
-        av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frame_rate);
+        av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frei0r->framerate);
         return AVERROR(EINVAL);
     }
     frei0r->time_base.num = frame_rate_q.den;
     frei0r->time_base.den = frame_rate_q.num;
 
-    return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_SOURCE);
+    return frei0r_init(ctx, frei0r->dl_name, F0R_PLUGIN_TYPE_SOURCE);
 }
 
 static int source_config_props(AVFilterLink *outlink)
@@ -467,6 +478,21 @@ static int source_request_frame(AVFilterLink *outlink)
     return ff_filter_frame(outlink, frame);
 }
 
+static const AVOption src_options[] = {
+    { "size",          "Dimensions of the generated video.", OFFSET(size),      AV_OPT_TYPE_STRING, { .str = "" },   .flags = FLAGS },
+    { "framerate",     NULL,                                 OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = "25" }, .flags = FLAGS },
+    { "filter_name",   NULL,                                 OFFSET(dl_name),   AV_OPT_TYPE_STRING,                  .flags = FLAGS },
+    { "filter_params", NULL,                                 OFFSET(params),    AV_OPT_TYPE_STRING,                  .flags = FLAGS },
+    { NULL },
+};
+
+static const AVClass src_class = {
+    .class_name = "frei0r_src",
+    .item_name  = av_default_item_name,
+    .option     = src_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = {
     {
         .name          = "default",
@@ -482,6 +508,7 @@ AVFilter avfilter_vsrc_frei0r_src = {
     .description = NULL_IF_CONFIG_SMALL("Generate a frei0r source."),
 
     .priv_size = sizeof(Frei0rContext),
+    .priv_class = &src_class,
     .init      = source_init,
     .uninit    = uninit,