diff --git a/doc/filters.texi b/doc/filters.texi index ce6ba4decc..ce7417a00c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -4169,12 +4169,18 @@ Apply video transform using libopencv. To enable this filter install libopencv library and headers and configure FFmpeg with @code{--enable-libopencv}. -The filter takes the parameters: @var{filter_name}@{:=@}@var{filter_params}. +This filter accepts the following parameters: -@var{filter_name} is the name of the libopencv filter to apply. +@table @option -@var{filter_params} specifies the parameters to pass to the libopencv -filter. If not specified the default values are assumed. +@item filter_name +The name of the libopencv filter to apply. + +@item filter_params +The parameters to pass to the libopencv filter. If not specified the default +values are assumed. + +@end table Refer to the official libopencv documentation for more precise information: @@ -4188,7 +4194,7 @@ Follows the list of supported libopencv filters. Dilate an image by using a specific structuring element. This filter corresponds to the libopencv function @code{cvDilate}. -It accepts the parameters: @var{struct_el}:@var{nb_iterations}. +It accepts the parameters: @var{struct_el}|@var{nb_iterations}. @var{struct_el} represents a structuring element, and has the syntax: @var{cols}x@var{rows}+@var{anchor_x}x@var{anchor_y}/@var{shape} @@ -4216,7 +4222,7 @@ Follow some example: ocv=dilate # dilate using a structuring element with a 5x5 cross, iterate two times -ocv=dilate=5x5+2x2/cross:2 +ocv=filter_name=dilate:filter_params=5x5+2x2/cross|2 # read the shape from the file diamond.shape, iterate two times # the file diamond.shape may contain a pattern of characters like this: @@ -4226,7 +4232,7 @@ ocv=dilate=5x5+2x2/cross:2 # *** # * # the specified cols and rows are ignored (but not the anchor point coordinates) -ocv=0x0+2x2/custom=diamond.shape:2 +ocv=dilate:0x0+2x2/custom=diamond.shape|2 @end example @subsection erode @@ -4242,7 +4248,7 @@ with the same syntax and semantics as the @ref{dilate} filter. Smooth the input video. The filter takes the following parameters: -@var{type}:@var{param1}:@var{param2}:@var{param3}:@var{param4}. +@var{type}|@var{param1}|@var{param2}|@var{param3}|@var{param4}. @var{type} is the type of smooth filter to apply, and can be one of the following values: "blur", "blur_no_scale", "median", "gaussian", diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 4f0afd5ca5..d17f9bf3ae 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -671,6 +671,7 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque !strcmp(filter->filter->name, "frei0r_src") || !strcmp(filter->filter->name, "gradfun" ) || !strcmp(filter->filter->name, "hqdn3d" ) || + !strcmp(filter->filter->name, "ocv" ) || !strcmp(filter->filter->name, "format") || !strcmp(filter->filter->name, "noformat") || !strcmp(filter->filter->name, "resample") || @@ -730,7 +731,8 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque } else if (!strcmp(filter->filter->name, "format") || !strcmp(filter->filter->name, "noformat") || !strcmp(filter->filter->name, "frei0r") || - !strcmp(filter->filter->name, "frei0r_src")) { + !strcmp(filter->filter->name, "frei0r_src") || + !strcmp(filter->filter->name, "ocv")) { /* a hack for compatibility with the old syntax * replace colons with |s */ char *copy = av_strdup(args); @@ -742,7 +744,8 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque goto fail; } - if (!strcmp(filter->filter->name, "frei0r")) + if (!strcmp(filter->filter->name, "frei0r") || + !strcmp(filter->filter->name, "ocv")) nb_leading = 1; else if (!strcmp(filter->filter->name, "frei0r_src")) nb_leading = 3; diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index 7174ccc34a..aa5d0258a6 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -30,6 +30,7 @@ #include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/file.h" +#include "libavutil/opt.h" #include "avfilter.h" #include "formats.h" #include "internal.h" @@ -70,7 +71,9 @@ static int query_formats(AVFilterContext *ctx) } typedef struct { - const char *name; + const AVClass *class; + char *name; + char *params; int (*init)(AVFilterContext *ctx, const char *args); void (*uninit)(AVFilterContext *ctx); void (*end_frame_filter)(AVFilterContext *ctx, IplImage *inimg, IplImage *outimg); @@ -95,7 +98,7 @@ static av_cold int smooth_init(AVFilterContext *ctx, const char *args) smooth->param4 = 0.0; if (args) - sscanf(args, "%127[^:]:%d:%d:%lf:%lf", type_str, &smooth->param1, &smooth->param2, &smooth->param3, &smooth->param4); + sscanf(args, "%127[^|]|%d|%d|%lf|%lf", type_str, &smooth->param1, &smooth->param2, &smooth->param3, &smooth->param4); if (!strcmp(type_str, "blur" )) smooth->type = CV_BLUR; else if (!strcmp(type_str, "blur_no_scale")) smooth->type = CV_BLUR_NO_SCALE; @@ -261,14 +264,14 @@ static av_cold int dilate_init(AVFilterContext *ctx, const char *args) dilate->nb_iterations = 1; if (args) - kernel_str = av_get_token(&buf, ":"); + kernel_str = av_get_token(&buf, "|"); if ((ret = parse_iplconvkernel(&dilate->kernel, *kernel_str ? kernel_str : default_kernel_str, ctx)) < 0) return ret; av_free(kernel_str); - sscanf(buf, ":%d", &dilate->nb_iterations); + sscanf(buf, "|%d", &dilate->nb_iterations); av_log(ctx, AV_LOG_VERBOSE, "iterations_nb:%d\n", dilate->nb_iterations); if (dilate->nb_iterations <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid non-positive value '%d' for nb_iterations\n", @@ -317,27 +320,22 @@ static OCVFilterEntry ocv_filter_entries[] = { static av_cold int init(AVFilterContext *ctx, const char *args) { OCVContext *ocv = ctx->priv; - char name[128], priv_args[1024]; int i; - char c; - - sscanf(args, "%127[^=:]%c%1023s", name, &c, priv_args); for (i = 0; i < FF_ARRAY_ELEMS(ocv_filter_entries); i++) { OCVFilterEntry *entry = &ocv_filter_entries[i]; - if (!strcmp(name, entry->name)) { - ocv->name = entry->name; + if (!strcmp(ocv->name, entry->name)) { ocv->init = entry->init; ocv->uninit = entry->uninit; ocv->end_frame_filter = entry->end_frame_filter; if (!(ocv->priv = av_mallocz(entry->priv_size))) return AVERROR(ENOMEM); - return ocv->init(ctx, priv_args); + return ocv->init(ctx, ocv->params); } } - av_log(ctx, AV_LOG_ERROR, "No libopencv filter named '%s'\n", name); + av_log(ctx, AV_LOG_ERROR, "No libopencv filter named '%s'\n", ocv->name); return AVERROR(EINVAL); } @@ -348,7 +346,6 @@ static av_cold void uninit(AVFilterContext *ctx) if (ocv->uninit) ocv->uninit(ctx); av_free(ocv->priv); - memset(ocv, 0, sizeof(*ocv)); } static int filter_frame(AVFilterLink *inlink, AVFrame *in) @@ -376,6 +373,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } +#define OFFSET(x) offsetof(OCVContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { "filter_name", NULL, OFFSET(name), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { NULL }, +}; + +static const AVClass ocv_class = { + .class_name = "ocv", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + static const AVFilterPad avfilter_vf_ocv_inputs[] = { { .name = "default", @@ -398,6 +410,7 @@ AVFilter avfilter_vf_ocv = { .description = NULL_IF_CONFIG_SMALL("Apply transform using libopencv."), .priv_size = sizeof(OCVContext), + .priv_class = &ocv_class, .query_formats = query_formats, .init = init,