On date Saturday 2015-02-28 20:22:49 +0530, Arwa Arif encoded: > Updated the patch.
> From ba761516b97b146f4c62d6c5c08dc5ea02c06af5 Mon Sep 17 00:00:00 2001 > From: Arwa Arif <[email protected]> > Date: Tue, 24 Feb 2015 12:17:30 +0530 > Subject: [PATCH] Port FFT domain filter. Subject: lavfi: add FFT domain filter > > --- > libavfilter/Makefile | 1 + > libavfilter/allfilters.c | 1 + > libavfilter/vf_fftfilt.c | 258 > ++++++++++++++++++++++++++++++++++++++++++++++ this could be renamed to fft, the "filt" part is redundant. Also missing documentation. > 3 files changed, 260 insertions(+) > create mode 100644 libavfilter/vf_fftfilt.c > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 289c63b..b184f07 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -120,6 +120,7 @@ OBJS-$(CONFIG_EDGEDETECT_FILTER) += > vf_edgedetect.o > OBJS-$(CONFIG_EQ_FILTER) += vf_eq.o > OBJS-$(CONFIG_EXTRACTPLANES_FILTER) += vf_extractplanes.o > OBJS-$(CONFIG_FADE_FILTER) += vf_fade.o > +OBJS-$(CONFIG_FFTFILT_FILTER) += vf_fftfilt.o > OBJS-$(CONFIG_FIELD_FILTER) += vf_field.o > OBJS-$(CONFIG_FIELDMATCH_FILTER) += vf_fieldmatch.o > OBJS-$(CONFIG_FIELDORDER_FILTER) += vf_fieldorder.o > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c > index 55de154..043ac56 100644 > --- a/libavfilter/allfilters.c > +++ b/libavfilter/allfilters.c > @@ -136,6 +136,7 @@ void avfilter_register_all(void) > REGISTER_FILTER(EQ, eq, vf); > REGISTER_FILTER(EXTRACTPLANES, extractplanes, vf); > REGISTER_FILTER(FADE, fade, vf); > + REGISTER_FILTER(FFTFILT, fftfilt, vf); > REGISTER_FILTER(FIELD, field, vf); > REGISTER_FILTER(FIELDMATCH, fieldmatch, vf); > REGISTER_FILTER(FIELDORDER, fieldorder, vf); > diff --git a/libavfilter/vf_fftfilt.c b/libavfilter/vf_fftfilt.c > new file mode 100644 > index 0000000..6d0a961 > --- /dev/null > +++ b/libavfilter/vf_fftfilt.c > @@ -0,0 +1,258 @@ > +/* > + * Copyright (c) 2015 Arwa Arif <[email protected]> > + * > + * 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 > + * FFT domain filtering. > + */ > + > +#include "libavfilter/internal.h" > +#include "libavutil/common.h" > +#include "libavutil/imgutils.h" > +#include "libavutil/opt.h" > +#include "libavutil/pixdesc.h" > +#include "libavcodec/avfft.h" > +#include "libavutil/eval.h" > + > +typedef struct { > + const AVClass *class; > + > + RDFTContext *rdft; > + int rdft_hbits; > + int rdft_vbits; > + size_t rdft_hlen; > + size_t rdft_vlen; > + FFTSample *rdft_hdata; > + FFTSample *rdft_vdata; > + > + int dc; > + char *lum_str; > + AVExpr *lum_expr; > + double *lum_data; > + > +} FFTFILTContext; > + > +static const char *const var_names[] = { "X", "Y", "W", "H", > NULL }; > +enum { VAR_X, VAR_Y, VAR_W, VAR_H, > VAR_VARS_NB }; > + > +#define OFFSET(x) offsetof(FFTFILTContext, x) > +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > + > +static const AVOption fftfilt_options[] = { > + { "dc", "adjust gain", OFFSET(dc), AV_OPT_TYPE_INT, > {.i64 = 0}, 0, 1000, FLAGS }, > + { "lum", "set luminance expression", OFFSET(lum_str), > AV_OPT_TYPE_STRING, {.str = "1"}, CHAR_MIN, CHAR_MAX, FLAGS }, > + {NULL}, > +}; > + > +AVFILTER_DEFINE_CLASS(fftfilt); > + > +static inline double lum(void *priv, double x, double y) > +{ > + FFTFILTContext *fftfilt = priv; > + FFTSample *rdft_data = fftfilt->rdft_vdata; > + size_t rdft_vlen = fftfilt->rdft_vlen; > + > + return rdft_data[(int)x * rdft_vlen + (int)y]; simpler return fft->rdft_data[(int)x * fft->rdft_vlen + (int)y]; > +} > + > +static av_cold int initialize(AVFilterContext *ctx) > +{ > + FFTFILTContext *fftfilt = ctx->priv; > + int ret = 0; > + > + static double (*p[])(void *, double, double) = {lum}; > + const char *const func2_names[] = {"lum", NULL }; > + double (*func2[])(void *, double, double) = {lum, p[0], NULL }; why this p thing indirection? > + ret = av_expr_parse(&fftfilt->lum_expr, fftfilt->lum_str, var_names, > NULL, NULL, func2_names, func2, 0, ctx); > + return ret; > +} > + > +static int config_props(AVFilterLink *inlink) > +{ > + FFTFILTContext *fftfilt = inlink->dst->priv; > + int w = inlink->w; > + int h = inlink->h; > + int rdft_hbits, rdft_vbits, i, j; > + double values[VAR_VARS_NB]; > + > + /* RDFT - Array initialization for Horizontal pass*/ > + for (rdft_hbits = 1; 1 << rdft_hbits < w; rdft_hbits++); > + fftfilt->rdft_hbits = rdft_hbits; > + fftfilt->rdft_hlen = 1 << rdft_hbits; > + if (!(fftfilt->rdft_hdata = av_malloc_array(h, fftfilt->rdft_hlen * > sizeof(FFTSample)))) > + return AVERROR(ENOMEM); > + > + /* RDFT - Array initialization for Vertical pass*/ > + for (rdft_vbits = 1; 1 << rdft_vbits < h; rdft_vbits++); > + fftfilt->rdft_vbits = rdft_vbits; > + fftfilt->rdft_vlen = 1 << rdft_vbits; > + if (!(fftfilt->rdft_vdata = av_malloc_array(fftfilt->rdft_hlen, > fftfilt->rdft_vlen * sizeof(FFTSample)))) > + return AVERROR(ENOMEM); > + > + /*Luminance value - Array initialization*/ > + if(!(fftfilt->lum_data = av_malloc_array(fftfilt->rdft_hlen, > fftfilt->rdft_vlen * sizeof(double)))) > + return AVERROR(ENOMEM); > + values[VAR_W] = w; > + values[VAR_H] = h; > + for (i = 0; i < fftfilt->rdft_hlen; i++) > + { > + values[VAR_X] = i; > + for (j = 0; j < fftfilt->rdft_vlen; j++) > + { > + values[VAR_Y] = j; > + fftfilt->lum_data[i * fftfilt->rdft_vlen + j] = > av_expr_eval(fftfilt->lum_expr, values, fftfilt); > + } > + } > + return 0; > +} > + > +static int filter_frame(AVFilterLink *inlink, AVFrame *in) > +{ > + AVFilterContext *ctx = inlink->dst; > + AVFilterLink *outlink = inlink->dst->outputs[0]; > + FFTFILTContext *fftfilt = ctx->priv; > + AVFrame *out; > + int w = inlink->w; > + int h = inlink->h; > + size_t rdft_hlen = fftfilt->rdft_hlen; > + size_t rdft_vlen = fftfilt->rdft_vlen; > + int i, j; > + > + out = ff_get_video_buffer(outlink, inlink->w, inlink->h); > + if (!out) > + return AVERROR(ENOMEM); > + > + av_frame_copy_props(out, in); > + > + /*Horizontal pass - RDFT*/ > + fftfilt->rdft = av_rdft_init(fftfilt->rdft_hbits, DFT_R2C); > + for (i = 0; i < h; i++) > + { > + memset(fftfilt->rdft_hdata + i * rdft_hlen, 0, rdft_hlen * > sizeof(*fftfilt->rdft_hdata)); > + for (j = 0; j < w; j++) > + fftfilt->rdft_hdata[i * rdft_hlen + j] = *(in->data[0] + > in->linesize[0] * i + j); > + } > + > + for (i = 0; i < h; i++) > + av_rdft_calc(fftfilt->rdft, fftfilt->rdft_hdata + i * rdft_hlen); > + > + av_rdft_end(fftfilt->rdft); > + > + /*Vertical pass - RDFT*/ > + fftfilt->rdft = av_rdft_init(fftfilt->rdft_vbits, DFT_R2C); > + for (i = 0; i < rdft_hlen; i++) > + { > + memset(fftfilt->rdft_vdata + i * rdft_vlen, 0, rdft_vlen * > sizeof(*fftfilt->rdft_vdata)); > + for (j = 0; j < h; j++) > + fftfilt->rdft_vdata[i * rdft_vlen + j] = fftfilt->rdft_hdata[j * > rdft_hlen + i]; > + } > + > + for (i = 0; i < rdft_hlen; i++) > + av_rdft_calc(fftfilt->rdft, fftfilt->rdft_vdata + i * rdft_vlen); > + > + av_rdft_end(fftfilt->rdft); > + > + /*Change user defined parameters*/ > + for (i = 0; i < rdft_hlen; i++) > + for (j = 0; j < rdft_vlen; j++) > + fftfilt->rdft_vdata[i * rdft_vlen + j] *= fftfilt->lum_data[i * > rdft_vlen + j]; > + fftfilt->rdft_vdata[0] += rdft_hlen * rdft_vlen * fftfilt->dc; > + > + /*Vertical pass - IRDFT*/ > + fftfilt->rdft = av_rdft_init(fftfilt->rdft_vbits, IDFT_C2R); > + > + for (i = 0; i < rdft_hlen; i++) > + av_rdft_calc(fftfilt->rdft, fftfilt->rdft_vdata + i * rdft_vlen); > + > + for (i = 0; i < rdft_hlen; i++) > + for (j = 0; j < h; j++) > + fftfilt->rdft_hdata[j * rdft_hlen + i] = fftfilt->rdft_vdata[i * > rdft_vlen + j]; > + > + av_rdft_end(fftfilt->rdft); > + > + /*Horizontal pass - IRDFT*/ > + fftfilt->rdft = av_rdft_init(fftfilt->rdft_hbits, IDFT_C2R); > + > + for (i = 0; i < h; i++) > + av_rdft_calc(fftfilt->rdft, fftfilt->rdft_hdata + i * rdft_hlen); > + > + for (i = 0; i < h; i++) > + for (j = 0; j < w; j++) > + *(out->data[0] + out->linesize[0] * i + j) = > av_clip(fftfilt->rdft_hdata[i * rdft_hlen + j] > + * 4 / > (rdft_hlen * rdft_vlen), 0, 255); > + > + av_rdft_end(fftfilt->rdft); > + > + av_free(fftfilt->rdft_hdata); > + av_free(fftfilt->rdft_vdata); does this work with multiple frames? Shuoldn't this be freed in uninit? > + > + av_frame_free(&in); > + > + return ff_filter_frame(outlink, out); > +} > + > +static av_cold void uninit(AVFilterContext *ctx) > +{ > + FFTFILTContext *fftfilt = ctx->priv; > + av_expr_free(fftfilt->lum_expr); > + av_free(fftfilt->lum_data); > +} > + > +static int query_formats(AVFilterContext *ctx) > +{ > + static const enum AVPixelFormat pixel_fmts_fftfilt[] = { > + AV_PIX_FMT_GRAY8, > + AV_PIX_FMT_NONE > + }; > + > + ff_set_common_formats(ctx, ff_make_format_list(pixel_fmts_fftfilt)); > + > + return 0; > +} > + > +static const AVFilterPad fftfilt_inputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_VIDEO, > + .config_props = config_props, > + .filter_frame = filter_frame, > + }, > + { NULL } > +}; > + > +static const AVFilterPad fftfilt_outputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_VIDEO, > + }, > + { NULL } > +}; > + > +AVFilter ff_vf_fftfilt = { > + .name = "fftfilt", fftfilt -> fft > + .description = NULL_IF_CONFIG_SMALL("Adjust gain."), poor description [...] -- FFmpeg = Formidable & Furious Mere Portentous Evil Guru _______________________________________________ ffmpeg-devel mailing list [email protected] http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
