From a8b4e3681c37ed62590a32e9fd1fcb5c3321ffbc Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 19 Sep 2024 18:53:07 +0200 Subject: [PATCH] remove obsolete opencv filter wrapper --- Changelog | 1 + configure | 8 - doc/filters.texi | 104 --------- libavfilter/Makefile | 1 - libavfilter/allfilters.c | 1 - libavfilter/vf_libopencv.c | 428 ------------------------------------- 6 files changed, 1 insertion(+), 542 deletions(-) delete mode 100644 libavfilter/vf_libopencv.c diff --git a/Changelog b/Changelog index 62e79d3050..db21f54514 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,7 @@ version : - removed DEC Alpha DSP and support code - perlin video source filter - YUV colorspace negotiation for codecs and filters, obsoleting YUVJ +- removed ocv filter wrapper version 7.0: - DXV DXT1 encoder diff --git a/configure b/configure index 376dabed23..ca98954175 100755 --- a/configure +++ b/configure @@ -251,7 +251,6 @@ External library support: --enable-libmp3lame enable MP3 encoding via libmp3lame [no] --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] - --enable-libopencv enable video filtering via libopencv [no] --enable-libopenh264 enable H.264 encoding via OpenH264 [no] --enable-libopenjpeg enable JPEG 2000 encoding via OpenJPEG [no] --enable-libopenmpt enable decoding tracked files via libopenmpt [no] @@ -1931,7 +1930,6 @@ EXTERNAL_LIBRARY_LIST=" libmodplug libmp3lame libmysofa - libopencv libopenh264 libopenjpeg libopenmpt @@ -2287,7 +2285,6 @@ HEADERS_LIST=" machine_ioctl_bt848_h machine_ioctl_meteor_h malloc_h - opencv2_core_core_c_h OpenGL_gl3_h poll_h pthread_np_h @@ -3893,7 +3890,6 @@ nlmeans_opencl_filter_deps="opencl" nlmeans_vulkan_filter_deps="vulkan spirv_compiler" nnedi_filter_deps="gpl" ocr_filter_deps="libtesseract" -ocv_filter_deps="libopencv" openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" @@ -6944,10 +6940,6 @@ enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig - die "ERROR: libnpp not found"; } enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -enabled libopencv && { check_headers opencv2/core/core_c.h && - { check_pkg_config libopencv opencv opencv2/core/core_c.h cvCreateImageHeader || - require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } || - require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; } enabled libopenh264 && require_pkg_config libopenh264 "openh264 >= 1.3.0" wels/codec_api.h WelsGetCodecVersion enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } diff --git a/doc/filters.texi b/doc/filters.texi index 6a6d7c6c6c..7dc6508ea5 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18641,110 +18641,6 @@ Set character blacklist. The filter exports recognized text as the frame metadata @code{lavfi.ocr.text}. The filter exports confidence of recognized words as the frame metadata @code{lavfi.ocr.confidence}. -@section ocv - -Apply a video transform using libopencv. - -To enable this filter, install the libopencv library and headers and -configure FFmpeg with @code{--enable-libopencv}. - -It accepts the following parameters: - -@table @option - -@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: -@url{http://docs.opencv.org/master/modules/imgproc/doc/filtering.html} - -Several libopencv filters are supported; see the following subsections. - -@anchor{dilate} -@subsection dilate - -Dilate an image by using a specific structuring element. -It corresponds to the libopencv function @code{cvDilate}. - -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} - -@var{cols} and @var{rows} represent the number of columns and rows of -the structuring element, @var{anchor_x} and @var{anchor_y} the anchor -point, and @var{shape} the shape for the structuring element. @var{shape} -must be "rect", "cross", "ellipse", or "custom". - -If the value for @var{shape} is "custom", it must be followed by a -string of the form "=@var{filename}". The file with name -@var{filename} is assumed to represent a binary image, with each -printable character corresponding to a bright pixel. When a custom -@var{shape} is used, @var{cols} and @var{rows} are ignored, the number -or columns and rows of the read file are assumed instead. - -The default value for @var{struct_el} is "3x3+0x0/rect". - -@var{nb_iterations} specifies the number of times the transform is -applied to the image, and defaults to 1. - -Some examples: -@example -# Use the default values -ocv=dilate - -# Dilate using a structuring element with a 5x5 cross, iterating two times -ocv=filter_name=dilate:filter_params=5x5+2x2/cross|2 - -# Read the shape from the file diamond.shape, iterating two times. -# The file diamond.shape may contain a pattern of characters like this -# * -# *** -# ***** -# *** -# * -# The specified columns and rows are ignored -# but the anchor point coordinates are not -ocv=dilate:0x0+2x2/custom=diamond.shape|2 -@end example - -@subsection erode - -Erode an image by using a specific structuring element. -It corresponds to the libopencv function @code{cvErode}. - -It accepts the parameters: @var{struct_el}:@var{nb_iterations}, -with the same syntax and semantics as the @ref{dilate} filter. - -@subsection smooth - -Smooth the input video. - -The filter takes the following parameters: -@var{type}|@var{param1}|@var{param2}|@var{param3}|@var{param4}. - -@var{type} is the type of smooth filter to apply, and must be one of -the following values: "blur", "blur_no_scale", "median", "gaussian", -or "bilateral". The default value is "gaussian". - -The meaning of @var{param1}, @var{param2}, @var{param3}, and @var{param4} -depends on the smooth type. @var{param1} and -@var{param2} accept integer positive values or 0. @var{param3} and -@var{param4} accept floating point values. - -The default value for @var{param1} is 3. The default value for the -other parameters is 0. - -These parameters correspond to the parameters assigned to the -libopencv function @code{cvSmooth}. - @section oscilloscope 2D Video Oscilloscope. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 83ca41bb11..2dfb5890f4 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -427,7 +427,6 @@ OBJS-$(CONFIG_NOISE_FILTER) += vf_noise.o OBJS-$(CONFIG_NORMALIZE_FILTER) += vf_normalize.o OBJS-$(CONFIG_NULL_FILTER) += vf_null.o OBJS-$(CONFIG_OCR_FILTER) += vf_ocr.o -OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_CUDA_FILTER) += vf_overlay_cuda.o framesync.o vf_overlay_cuda.ptx.o \ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index e59788dbd8..098189afa4 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -404,7 +404,6 @@ extern const AVFilter ff_vf_noise; extern const AVFilter ff_vf_normalize; extern const AVFilter ff_vf_null; extern const AVFilter ff_vf_ocr; -extern const AVFilter ff_vf_ocv; extern const AVFilter ff_vf_oscilloscope; extern const AVFilter ff_vf_overlay; extern const AVFilter ff_vf_overlay_opencl; diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c deleted file mode 100644 index b8cb88e63b..0000000000 --- a/libavfilter/vf_libopencv.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright (c) 2010 Stefano Sabatini - * - * 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 - * libopencv wrapper functions - */ - -#include "config.h" -#if HAVE_OPENCV2_CORE_CORE_C_H -#include -#include -#else -#include -#include -#endif -#include "libavutil/avstring.h" -#include "libavutil/common.h" -#include "libavutil/file.h" -#include "libavutil/mem.h" -#include "libavutil/opt.h" -#include "avfilter.h" -#include "filters.h" -#include "formats.h" -#include "video.h" - -static void fill_iplimage_from_frame(IplImage *img, const AVFrame *frame, enum AVPixelFormat pixfmt) -{ - IplImage *tmpimg; - int depth, channels_nb; - - if (pixfmt == AV_PIX_FMT_GRAY8) { depth = IPL_DEPTH_8U; channels_nb = 1; } - else if (pixfmt == AV_PIX_FMT_BGRA) { depth = IPL_DEPTH_8U; channels_nb = 4; } - else if (pixfmt == AV_PIX_FMT_BGR24) { depth = IPL_DEPTH_8U; channels_nb = 3; } - else return; - - tmpimg = cvCreateImageHeader((CvSize){frame->width, frame->height}, depth, channels_nb); - *img = *tmpimg; - img->imageData = img->imageDataOrigin = frame->data[0]; - img->dataOrder = IPL_DATA_ORDER_PIXEL; - img->origin = IPL_ORIGIN_TL; - img->widthStep = frame->linesize[0]; -} - -static void fill_frame_from_iplimage(AVFrame *frame, const IplImage *img, enum AVPixelFormat pixfmt) -{ - frame->linesize[0] = img->widthStep; - frame->data[0] = img->imageData; -} - -typedef struct OCVContext { - 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); - void *priv; -} OCVContext; - -typedef struct SmoothContext { - int type; - int param1, param2; - double param3, param4; -} SmoothContext; - -static av_cold int smooth_init(AVFilterContext *ctx, const char *args) -{ - OCVContext *s = ctx->priv; - SmoothContext *smooth = s->priv; - char type_str[128] = "gaussian"; - - smooth->param1 = 3; - smooth->param2 = 0; - smooth->param3 = 0.0; - smooth->param4 = 0.0; - - if (args) - 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; - else if (!strcmp(type_str, "median" )) smooth->type = CV_MEDIAN; - else if (!strcmp(type_str, "gaussian" )) smooth->type = CV_GAUSSIAN; - else if (!strcmp(type_str, "bilateral" )) smooth->type = CV_BILATERAL; - else { - av_log(ctx, AV_LOG_ERROR, "Smoothing type '%s' unknown.\n", type_str); - return AVERROR(EINVAL); - } - - if (smooth->param1 < 0 || !(smooth->param1%2)) { - av_log(ctx, AV_LOG_ERROR, - "Invalid value '%d' for param1, it has to be a positive odd number\n", - smooth->param1); - return AVERROR(EINVAL); - } - if ((smooth->type == CV_BLUR || smooth->type == CV_BLUR_NO_SCALE || smooth->type == CV_GAUSSIAN) && - (smooth->param2 < 0 || (smooth->param2 && !(smooth->param2%2)))) { - av_log(ctx, AV_LOG_ERROR, - "Invalid value '%d' for param2, it has to be zero or a positive odd number\n", - smooth->param2); - return AVERROR(EINVAL); - } - - av_log(ctx, AV_LOG_VERBOSE, "type:%s param1:%d param2:%d param3:%f param4:%f\n", - type_str, smooth->param1, smooth->param2, smooth->param3, smooth->param4); - return 0; -} - -static void smooth_end_frame_filter(AVFilterContext *ctx, IplImage *inimg, IplImage *outimg) -{ - OCVContext *s = ctx->priv; - SmoothContext *smooth = s->priv; - cvSmooth(inimg, outimg, smooth->type, smooth->param1, smooth->param2, smooth->param3, smooth->param4); -} - -static int read_shape_from_file(int *cols, int *rows, int **values, const char *filename, - void *log_ctx) -{ - uint8_t *buf, *p, *pend; - size_t size; - int ret, i, j, w; - - if ((ret = av_file_map(filename, &buf, &size, 0, log_ctx)) < 0) - return ret; - - /* prescan file to get the number of lines and the maximum width */ - w = 0; - for (i = 0; i < size; i++) { - if (buf[i] == '\n') { - if (*rows == INT_MAX) { - av_log(log_ctx, AV_LOG_ERROR, "Overflow on the number of rows in the file\n"); - ret = AVERROR_INVALIDDATA; - goto end; - } - ++(*rows); - *cols = FFMAX(*cols, w); - w = 0; - } else if (w == INT_MAX) { - av_log(log_ctx, AV_LOG_ERROR, "Overflow on the number of columns in the file\n"); - return AVERROR_INVALIDDATA; - } - w++; - } - if (*rows > (SIZE_MAX / sizeof(int) / *cols)) { - av_log(log_ctx, AV_LOG_ERROR, "File with size %dx%d is too big\n", - *rows, *cols); - ret = AVERROR_INVALIDDATA; - goto end; - } - if (!(*values = av_calloc(sizeof(int) * *rows, *cols))) { - ret = AVERROR(ENOMEM); - goto end; - } - - /* fill *values */ - p = buf; - pend = buf + size-1; - for (i = 0; i < *rows; i++) { - for (j = 0;; j++) { - if (p > pend || *p == '\n') { - p++; - break; - } else - (*values)[*cols*i + j] = !!av_isgraph(*(p++)); - } - } - -end: - av_file_unmap(buf, size); - -#ifdef DEBUG - { - char *line; - if (!(line = av_malloc(*cols + 1))) - return AVERROR(ENOMEM); - for (i = 0; i < *rows; i++) { - for (j = 0; j < *cols; j++) - line[j] = (*values)[i * *cols + j] ? '@' : ' '; - line[j] = 0; - av_log(log_ctx, AV_LOG_DEBUG, "%3d: %s\n", i, line); - } - av_free(line); - } -#endif - - return 0; -} - -static int parse_iplconvkernel(IplConvKernel **kernel, char *buf, void *log_ctx) -{ - char shape_filename[128] = "", shape_str[32] = "rect"; - int cols = 0, rows = 0, anchor_x = 0, anchor_y = 0, shape = CV_SHAPE_RECT; - int *values = NULL, ret = 0; - - sscanf(buf, "%dx%d+%dx%d/%32[^=]=%127s", &cols, &rows, &anchor_x, &anchor_y, shape_str, shape_filename); - - if (!strcmp(shape_str, "rect" )) shape = CV_SHAPE_RECT; - else if (!strcmp(shape_str, "cross" )) shape = CV_SHAPE_CROSS; - else if (!strcmp(shape_str, "ellipse")) shape = CV_SHAPE_ELLIPSE; - else if (!strcmp(shape_str, "custom" )) { - shape = CV_SHAPE_CUSTOM; - if ((ret = read_shape_from_file(&cols, &rows, &values, shape_filename, log_ctx)) < 0) - return ret; - } else { - av_log(log_ctx, AV_LOG_ERROR, - "Shape unspecified or type '%s' unknown.\n", shape_str); - ret = AVERROR(EINVAL); - goto out; - } - - if (rows <= 0 || cols <= 0) { - av_log(log_ctx, AV_LOG_ERROR, - "Invalid non-positive values for shape size %dx%d\n", cols, rows); - ret = AVERROR(EINVAL); - goto out; - } - - if (anchor_x < 0 || anchor_y < 0 || anchor_x >= cols || anchor_y >= rows) { - av_log(log_ctx, AV_LOG_ERROR, - "Shape anchor %dx%d is not inside the rectangle with size %dx%d.\n", - anchor_x, anchor_y, cols, rows); - ret = AVERROR(EINVAL); - goto out; - } - - *kernel = cvCreateStructuringElementEx(cols, rows, anchor_x, anchor_y, shape, values); - if (!*kernel) { - ret = AVERROR(ENOMEM); - goto out; - } - - av_log(log_ctx, AV_LOG_VERBOSE, "Structuring element: w:%d h:%d x:%d y:%d shape:%s\n", - rows, cols, anchor_x, anchor_y, shape_str); -out: - av_freep(&values); - return ret; -} - -typedef struct DilateContext { - int nb_iterations; - IplConvKernel *kernel; -} DilateContext; - -static av_cold int dilate_init(AVFilterContext *ctx, const char *args) -{ - OCVContext *s = ctx->priv; - DilateContext *dilate = s->priv; - char default_kernel_str[] = "3x3+0x0/rect"; - char *kernel_str = NULL; - const char *buf = args; - int ret; - - if (args) { - kernel_str = av_get_token(&buf, "|"); - - if (!kernel_str) - return AVERROR(ENOMEM); - } - - ret = parse_iplconvkernel(&dilate->kernel, - (!kernel_str || !*kernel_str) ? default_kernel_str - : kernel_str, - ctx); - av_free(kernel_str); - if (ret < 0) - return ret; - - if (!buf || sscanf(buf, "|%d", &dilate->nb_iterations) != 1) - dilate->nb_iterations = 1; - 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", - dilate->nb_iterations); - return AVERROR(EINVAL); - } - return 0; -} - -static av_cold void dilate_uninit(AVFilterContext *ctx) -{ - OCVContext *s = ctx->priv; - DilateContext *dilate = s->priv; - - cvReleaseStructuringElement(&dilate->kernel); -} - -static void dilate_end_frame_filter(AVFilterContext *ctx, IplImage *inimg, IplImage *outimg) -{ - OCVContext *s = ctx->priv; - DilateContext *dilate = s->priv; - cvDilate(inimg, outimg, dilate->kernel, dilate->nb_iterations); -} - -static void erode_end_frame_filter(AVFilterContext *ctx, IplImage *inimg, IplImage *outimg) -{ - OCVContext *s = ctx->priv; - DilateContext *dilate = s->priv; - cvErode(inimg, outimg, dilate->kernel, dilate->nb_iterations); -} - -typedef struct OCVFilterEntry { - const char *name; - size_t priv_size; - int (*init)(AVFilterContext *ctx, const char *args); - void (*uninit)(AVFilterContext *ctx); - void (*end_frame_filter)(AVFilterContext *ctx, IplImage *inimg, IplImage *outimg); -} OCVFilterEntry; - -static const OCVFilterEntry ocv_filter_entries[] = { - { "dilate", sizeof(DilateContext), dilate_init, dilate_uninit, dilate_end_frame_filter }, - { "erode", sizeof(DilateContext), dilate_init, dilate_uninit, erode_end_frame_filter }, - { "smooth", sizeof(SmoothContext), smooth_init, NULL, smooth_end_frame_filter }, -}; - -static av_cold int init(AVFilterContext *ctx) -{ - OCVContext *s = ctx->priv; - int i; - - if (!s->name) { - av_log(ctx, AV_LOG_ERROR, "No libopencv filter name specified\n"); - return AVERROR(EINVAL); - } - for (i = 0; i < FF_ARRAY_ELEMS(ocv_filter_entries); i++) { - const OCVFilterEntry *entry = &ocv_filter_entries[i]; - if (!strcmp(s->name, entry->name)) { - s->init = entry->init; - s->uninit = entry->uninit; - s->end_frame_filter = entry->end_frame_filter; - - if (!(s->priv = av_mallocz(entry->priv_size))) - return AVERROR(ENOMEM); - return s->init(ctx, s->params); - } - } - - av_log(ctx, AV_LOG_ERROR, "No libopencv filter named '%s'\n", s->name); - return AVERROR(EINVAL); -} - -static av_cold void uninit(AVFilterContext *ctx) -{ - OCVContext *s = ctx->priv; - - if (s->uninit) - s->uninit(ctx); - av_freep(&s->priv); -} - -static int filter_frame(AVFilterLink *inlink, AVFrame *in) -{ - AVFilterContext *ctx = inlink->dst; - OCVContext *s = ctx->priv; - AVFilterLink *outlink= inlink->dst->outputs[0]; - AVFrame *out; - IplImage inimg, outimg; - - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - av_frame_copy_props(out, in); - - fill_iplimage_from_frame(&inimg , in , inlink->format); - fill_iplimage_from_frame(&outimg, out, inlink->format); - s->end_frame_filter(ctx, &inimg, &outimg); - fill_frame_from_iplimage(out, &outimg, inlink->format); - - av_frame_free(&in); - - return ff_filter_frame(outlink, out); -} - -#define OFFSET(x) offsetof(OCVContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM -static const AVOption ocv_options[] = { - { "filter_name", NULL, OFFSET(name), AV_OPT_TYPE_STRING, .flags = FLAGS }, - { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(ocv); - -static const AVFilterPad ocv_inputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, - }, -}; - -static const AVFilterPad ocv_outputs[] = { - { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - }, -}; - -const AVFilter ff_vf_ocv = { - .name = "ocv", - .description = NULL_IF_CONFIG_SMALL("Apply transform using libopencv."), - .priv_size = sizeof(OCVContext), - .priv_class = &ocv_class, - .init = init, - .uninit = uninit, - FILTER_INPUTS(ocv_inputs), - FILTER_OUTPUTS(ocv_outputs), - FILTER_PIXFMTS(AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_GRAY8), -};