... | ... |
@@ -6950,6 +6950,109 @@ For example, to vertically flip a video with @command{ffmpeg}: |
6950 | 6950 |
ffmpeg -i in.avi -vf "vflip" out.avi |
6951 | 6951 |
@end example |
6952 | 6952 |
|
6953 |
+@section vignette |
|
6954 |
+ |
|
6955 |
+Make or reverse a natural vignetting effect. |
|
6956 |
+ |
|
6957 |
+The filter accepts the following options: |
|
6958 |
+ |
|
6959 |
+@table @option |
|
6960 |
+@item angle, a |
|
6961 |
+Set lens angle expression as a number of radians. |
|
6962 |
+ |
|
6963 |
+The value is clipped in the @code{[0,PI/2]} range. |
|
6964 |
+ |
|
6965 |
+Default value: @code{"PI/5"} |
|
6966 |
+ |
|
6967 |
+@item x0 |
|
6968 |
+@item y0 |
|
6969 |
+Set center coordinates expressions. Respectively @code{"w/2"} and @code{"h/2"} |
|
6970 |
+by default. |
|
6971 |
+ |
|
6972 |
+@item mode |
|
6973 |
+Set forward/backward mode. |
|
6974 |
+ |
|
6975 |
+Available modes are: |
|
6976 |
+@table @samp |
|
6977 |
+@item forward |
|
6978 |
+The larger the distance from the central point, the darker the image becomes. |
|
6979 |
+ |
|
6980 |
+@item backward |
|
6981 |
+The larger the distance from the central point, the brighter the image becomes. |
|
6982 |
+This can be used to reverse a vignette effect, though there is no automatic |
|
6983 |
+detection to extract the lens @option{angle} and other settings (yet). It can |
|
6984 |
+also be used to create a burning effect. |
|
6985 |
+@end table |
|
6986 |
+ |
|
6987 |
+Default value is @samp{forward}. |
|
6988 |
+ |
|
6989 |
+@item eval |
|
6990 |
+Set evaluation mode for the expressions (@option{angle}, @option{x0}, @option{y0}). |
|
6991 |
+ |
|
6992 |
+It accepts the following values: |
|
6993 |
+@table @samp |
|
6994 |
+@item init |
|
6995 |
+Evaluate expressions only once during the filter initialization. |
|
6996 |
+ |
|
6997 |
+@item frame |
|
6998 |
+Evaluate expressions for each incoming frame. This is way slower than the |
|
6999 |
+@samp{init} mode since it requires all the scalers to be re-computed, but it |
|
7000 |
+allows advanced dynamic expressions. |
|
7001 |
+@end table |
|
7002 |
+ |
|
7003 |
+Default value is @samp{init}. |
|
7004 |
+ |
|
7005 |
+@item dither |
|
7006 |
+Set dithering to reduce the circular banding effects. Default is @code{1} |
|
7007 |
+(enabled). |
|
7008 |
+@end table |
|
7009 |
+ |
|
7010 |
+@subsection Expressions |
|
7011 |
+ |
|
7012 |
+The @option{alpha}, @option{x0} and @option{y0} expressions can contain the |
|
7013 |
+following parameters. |
|
7014 |
+ |
|
7015 |
+@table @option |
|
7016 |
+@item w |
|
7017 |
+@item h |
|
7018 |
+input width and height |
|
7019 |
+ |
|
7020 |
+@item n |
|
7021 |
+the number of input frame, starting from 0 |
|
7022 |
+ |
|
7023 |
+@item pts |
|
7024 |
+the PTS (Presentation TimeStamp) time of the filtered video frame, expressed in |
|
7025 |
+@var{TB} units, NAN if undefined |
|
7026 |
+ |
|
7027 |
+@item r |
|
7028 |
+frame rate of the input video, NAN if the input frame rate is unknown |
|
7029 |
+ |
|
7030 |
+@item t |
|
7031 |
+the PTS (Presentation TimeStamp) of the filtered video frame, |
|
7032 |
+expressed in seconds, NAN if undefined |
|
7033 |
+ |
|
7034 |
+@item tb |
|
7035 |
+time base of the input video |
|
7036 |
+@end table |
|
7037 |
+ |
|
7038 |
+ |
|
7039 |
+@subsection Examples |
|
7040 |
+ |
|
7041 |
+@itemize |
|
7042 |
+@item |
|
7043 |
+Apply simple strong vignetting effect: |
|
7044 |
+@example |
|
7045 |
+vignette=PI/4 |
|
7046 |
+@end example |
|
7047 |
+ |
|
7048 |
+@item |
|
7049 |
+Make a flickering vignetting: |
|
7050 |
+@example |
|
7051 |
+vignette='PI/4+random(1)*PI/50':eval=frame |
|
7052 |
+@end example |
|
7053 |
+ |
|
7054 |
+@end itemize |
|
7055 |
+ |
|
6953 | 7056 |
@anchor{yadif} |
6954 | 7057 |
@section yadif |
6955 | 7058 |
|
... | ... |
@@ -191,6 +191,7 @@ OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o |
191 | 191 |
OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o |
192 | 192 |
OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o |
193 | 193 |
OBJS-$(CONFIG_VIDSTABTRANSFORM_FILTER) += vidstabutils.o vf_vidstabtransform.o |
194 |
+OBJS-$(CONFIG_VIGNETTE_FILTER) += vf_vignette.o |
|
194 | 195 |
OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o |
195 | 196 |
OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o |
196 | 197 |
|
... | ... |
@@ -188,6 +188,7 @@ void avfilter_register_all(void) |
188 | 188 |
REGISTER_FILTER(VFLIP, vflip, vf); |
189 | 189 |
REGISTER_FILTER(VIDSTABDETECT, vidstabdetect, vf); |
190 | 190 |
REGISTER_FILTER(VIDSTABTRANSFORM, vidstabtransform, vf); |
191 |
+ REGISTER_FILTER(VIGNETTE, vignette, vf); |
|
191 | 192 |
REGISTER_FILTER(YADIF, yadif, vf); |
192 | 193 |
REGISTER_FILTER(ZMQ, zmq, vf); |
193 | 194 |
|
... | ... |
@@ -30,7 +30,7 @@ |
30 | 30 |
#include "libavutil/avutil.h" |
31 | 31 |
|
32 | 32 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
33 |
-#define LIBAVFILTER_VERSION_MINOR 72 |
|
33 |
+#define LIBAVFILTER_VERSION_MINOR 73 |
|
34 | 34 |
#define LIBAVFILTER_VERSION_MICRO 100 |
35 | 35 |
|
36 | 36 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
37 | 37 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,330 @@ |
0 |
+/* |
|
1 |
+ * Copyright (c) 2013 Clément Bœsch |
|
2 |
+ * |
|
3 |
+ * This file is part of FFmpeg. |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#include "libavutil/opt.h" |
|
21 |
+#include "libavutil/eval.h" |
|
22 |
+#include "libavutil/avassert.h" |
|
23 |
+#include "libavutil/pixdesc.h" |
|
24 |
+#include "avfilter.h" |
|
25 |
+#include "formats.h" |
|
26 |
+#include "internal.h" |
|
27 |
+#include "video.h" |
|
28 |
+ |
|
29 |
+static const char *const var_names[] = { |
|
30 |
+ "w", // stream width |
|
31 |
+ "h", // stream height |
|
32 |
+ "n", // frame count |
|
33 |
+ "pts", // presentation timestamp expressed in AV_TIME_BASE units |
|
34 |
+ "r", // frame rate |
|
35 |
+ "t", // timestamp expressed in seconds |
|
36 |
+ "tb", // timebase |
|
37 |
+ NULL |
|
38 |
+}; |
|
39 |
+ |
|
40 |
+enum var_name { |
|
41 |
+ VAR_W, |
|
42 |
+ VAR_H, |
|
43 |
+ VAR_N, |
|
44 |
+ VAR_PTS, |
|
45 |
+ VAR_R, |
|
46 |
+ VAR_T, |
|
47 |
+ VAR_TB, |
|
48 |
+ VAR_NB |
|
49 |
+}; |
|
50 |
+ |
|
51 |
+typedef struct { |
|
52 |
+ const AVClass *class; |
|
53 |
+ const AVPixFmtDescriptor *desc; |
|
54 |
+ int backward; |
|
55 |
+ enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, EVAL_MODE_NB } eval_mode; |
|
56 |
+#define DEF_EXPR_FIELDS(name) AVExpr *name##_pexpr; char *name##_expr; double name; |
|
57 |
+ DEF_EXPR_FIELDS(angle); |
|
58 |
+ DEF_EXPR_FIELDS(x0); |
|
59 |
+ DEF_EXPR_FIELDS(y0); |
|
60 |
+ double var_values[VAR_NB]; |
|
61 |
+ float *fmap; |
|
62 |
+ int fmap_linesize; |
|
63 |
+ double dmax; |
|
64 |
+ float xscale, yscale; |
|
65 |
+ uint32_t dither; |
|
66 |
+ int do_dither; |
|
67 |
+} VignetteContext; |
|
68 |
+ |
|
69 |
+#define OFFSET(x) offsetof(VignetteContext, x) |
|
70 |
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
71 |
+static const AVOption vignette_options[] = { |
|
72 |
+ { "angle", "set lens angle", OFFSET(angle_expr), AV_OPT_TYPE_STRING, {.str="PI/5"}, .flags = FLAGS }, |
|
73 |
+ { "a", "set lens angle", OFFSET(angle_expr), AV_OPT_TYPE_STRING, {.str="PI/5"}, .flags = FLAGS }, |
|
74 |
+ { "x0", "set circle center position on x-axis", OFFSET(x0_expr), AV_OPT_TYPE_STRING, {.str="w/2"}, .flags = FLAGS }, |
|
75 |
+ { "y0", "set circle center position on y-axis", OFFSET(y0_expr), AV_OPT_TYPE_STRING, {.str="h/2"}, .flags = FLAGS }, |
|
76 |
+ { "mode", "set forward/backward mode", OFFSET(backward), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS, "mode" }, |
|
77 |
+ { "forward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
78 |
+ { "backward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
79 |
+ { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, |
|
80 |
+ { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" }, |
|
81 |
+ { "frame", "eval expressions for each frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, |
|
82 |
+ { "dither", "set dithering", OFFSET(do_dither), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, FLAGS }, |
|
83 |
+ { NULL } |
|
84 |
+}; |
|
85 |
+ |
|
86 |
+AVFILTER_DEFINE_CLASS(vignette); |
|
87 |
+ |
|
88 |
+static av_cold int init(AVFilterContext *ctx) |
|
89 |
+{ |
|
90 |
+ VignetteContext *s = ctx->priv; |
|
91 |
+ |
|
92 |
+#define PARSE_EXPR(name) do { \ |
|
93 |
+ int ret = av_expr_parse(&s->name##_pexpr, s->name##_expr, var_names, \ |
|
94 |
+ NULL, NULL, NULL, NULL, 0, ctx); \ |
|
95 |
+ if (ret < 0) { \ |
|
96 |
+ av_log(ctx, AV_LOG_ERROR, "Unable to parse expression for '" \ |
|
97 |
+ AV_STRINGIFY(name) "'\n"); \ |
|
98 |
+ return ret; \ |
|
99 |
+ } \ |
|
100 |
+} while (0) |
|
101 |
+ |
|
102 |
+ PARSE_EXPR(angle); |
|
103 |
+ PARSE_EXPR(x0); |
|
104 |
+ PARSE_EXPR(y0); |
|
105 |
+ return 0; |
|
106 |
+} |
|
107 |
+ |
|
108 |
+static av_cold void uninit(AVFilterContext *ctx) |
|
109 |
+{ |
|
110 |
+ VignetteContext *s = ctx->priv; |
|
111 |
+ av_freep(&s->fmap); |
|
112 |
+ av_expr_free(s->angle_pexpr); |
|
113 |
+ av_expr_free(s->x0_pexpr); |
|
114 |
+ av_expr_free(s->y0_pexpr); |
|
115 |
+} |
|
116 |
+ |
|
117 |
+static int query_formats(AVFilterContext *ctx) |
|
118 |
+{ |
|
119 |
+ static const enum AVPixelFormat pix_fmts[] = { |
|
120 |
+ AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, |
|
121 |
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, |
|
122 |
+ AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, |
|
123 |
+ AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, |
|
124 |
+ AV_PIX_FMT_GRAY8, |
|
125 |
+ AV_PIX_FMT_NONE |
|
126 |
+ }; |
|
127 |
+ ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); |
|
128 |
+ return 0; |
|
129 |
+} |
|
130 |
+ |
|
131 |
+static double get_natural_factor(const VignetteContext *s, int x, int y) |
|
132 |
+{ |
|
133 |
+ const int xx = (x - s->x0) * s->xscale; |
|
134 |
+ const int yy = (y - s->y0) * s->yscale; |
|
135 |
+ const double dnorm = hypot(xx, yy) / s->dmax; |
|
136 |
+ if (dnorm > 1) { |
|
137 |
+ return 0; |
|
138 |
+ } else { |
|
139 |
+ const double c = cos(s->angle * dnorm); |
|
140 |
+ return (c*c)*(c*c); // do not remove braces, it helps compilers |
|
141 |
+ } |
|
142 |
+} |
|
143 |
+ |
|
144 |
+#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) |
|
145 |
+#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) |
|
146 |
+ |
|
147 |
+static void update_context(VignetteContext *s, AVFilterLink *inlink, AVFrame *frame) |
|
148 |
+{ |
|
149 |
+ int x, y; |
|
150 |
+ float *dst = s->fmap; |
|
151 |
+ int dst_linesize = s->fmap_linesize; |
|
152 |
+ |
|
153 |
+ if (frame) { |
|
154 |
+ s->var_values[VAR_N] = inlink->frame_count; |
|
155 |
+ s->var_values[VAR_T] = TS2T(frame->pts, inlink->time_base); |
|
156 |
+ s->var_values[VAR_PTS] = TS2D(frame->pts); |
|
157 |
+ } else { |
|
158 |
+ s->var_values[VAR_N] = 0; |
|
159 |
+ s->var_values[VAR_T] = NAN; |
|
160 |
+ s->var_values[VAR_PTS] = NAN; |
|
161 |
+ } |
|
162 |
+ |
|
163 |
+ s->angle = av_clipf(av_expr_eval(s->angle_pexpr, s->var_values, NULL), 0, M_PI_2); |
|
164 |
+ s->x0 = av_expr_eval(s->x0_pexpr, s->var_values, NULL); |
|
165 |
+ s->y0 = av_expr_eval(s->y0_pexpr, s->var_values, NULL); |
|
166 |
+ |
|
167 |
+ if (s->backward) { |
|
168 |
+ for (y = 0; y < inlink->h; y++) { |
|
169 |
+ for (x = 0; x < inlink->w; x++) |
|
170 |
+ dst[x] = 1. / get_natural_factor(s, x, y); |
|
171 |
+ dst += dst_linesize; |
|
172 |
+ } |
|
173 |
+ } else { |
|
174 |
+ for (y = 0; y < inlink->h; y++) { |
|
175 |
+ for (x = 0; x < inlink->w; x++) |
|
176 |
+ dst[x] = get_natural_factor(s, x, y); |
|
177 |
+ dst += dst_linesize; |
|
178 |
+ } |
|
179 |
+ } |
|
180 |
+} |
|
181 |
+ |
|
182 |
+static inline double get_dither_value(VignetteContext *s) |
|
183 |
+{ |
|
184 |
+ double dv = 0; |
|
185 |
+ if (s->do_dither) { |
|
186 |
+ dv = s->dither / (double)(1LL<<32); |
|
187 |
+ s->dither = s->dither * 1664525 + 1013904223; |
|
188 |
+ } |
|
189 |
+ return dv; |
|
190 |
+} |
|
191 |
+ |
|
192 |
+static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
|
193 |
+{ |
|
194 |
+ unsigned x, y; |
|
195 |
+ AVFilterContext *ctx = inlink->dst; |
|
196 |
+ VignetteContext *s = ctx->priv; |
|
197 |
+ AVFilterLink *outlink = inlink->dst->outputs[0]; |
|
198 |
+ AVFrame *out; |
|
199 |
+ |
|
200 |
+ out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
|
201 |
+ if (!out) { |
|
202 |
+ av_frame_free(&in); |
|
203 |
+ return AVERROR(ENOMEM); |
|
204 |
+ } |
|
205 |
+ av_frame_copy_props(out, in); |
|
206 |
+ |
|
207 |
+ if (s->eval_mode == EVAL_MODE_FRAME) |
|
208 |
+ update_context(s, inlink, in); |
|
209 |
+ |
|
210 |
+ if (s->desc->flags & PIX_FMT_RGB) { |
|
211 |
+ uint8_t *dst = out->data[0]; |
|
212 |
+ const uint8_t *src = in ->data[0]; |
|
213 |
+ const float *fmap = s->fmap; |
|
214 |
+ const int dst_linesize = out->linesize[0]; |
|
215 |
+ const int src_linesize = in ->linesize[0]; |
|
216 |
+ const int fmap_linesize = s->fmap_linesize; |
|
217 |
+ |
|
218 |
+ for (y = 0; y < inlink->h; y++) { |
|
219 |
+ uint8_t *dstp = dst; |
|
220 |
+ const uint8_t *srcp = src; |
|
221 |
+ |
|
222 |
+ for (x = 0; x < inlink->w; x++, dstp += 3, srcp += 3) { |
|
223 |
+ const float f = fmap[x]; |
|
224 |
+ |
|
225 |
+ dstp[0] = av_clip_uint8(srcp[0] * f + get_dither_value(s)); |
|
226 |
+ dstp[1] = av_clip_uint8(srcp[1] * f + get_dither_value(s)); |
|
227 |
+ dstp[2] = av_clip_uint8(srcp[2] * f + get_dither_value(s)); |
|
228 |
+ } |
|
229 |
+ dst += dst_linesize; |
|
230 |
+ src += src_linesize; |
|
231 |
+ fmap += fmap_linesize; |
|
232 |
+ } |
|
233 |
+ } else { |
|
234 |
+ int plane; |
|
235 |
+ |
|
236 |
+ for (plane = 0; plane < 4 && in->data[plane]; plane++) { |
|
237 |
+ uint8_t *dst = out->data[plane]; |
|
238 |
+ const uint8_t *src = in ->data[plane]; |
|
239 |
+ const float *fmap = s->fmap; |
|
240 |
+ const int dst_linesize = out->linesize[plane]; |
|
241 |
+ const int src_linesize = in ->linesize[plane]; |
|
242 |
+ const int fmap_linesize = s->fmap_linesize; |
|
243 |
+ const int chroma = plane == 1 || plane == 2; |
|
244 |
+ const int hsub = chroma ? s->desc->log2_chroma_w : 0; |
|
245 |
+ const int vsub = chroma ? s->desc->log2_chroma_h : 0; |
|
246 |
+ const int w = FF_CEIL_RSHIFT(inlink->w, hsub); |
|
247 |
+ const int h = FF_CEIL_RSHIFT(inlink->h, vsub); |
|
248 |
+ |
|
249 |
+ for (y = 0; y < h; y++) { |
|
250 |
+ uint8_t *dstp = dst; |
|
251 |
+ const uint8_t *srcp = src; |
|
252 |
+ |
|
253 |
+ for (x = 0; x < w; x++) { |
|
254 |
+ const double dv = get_dither_value(s); |
|
255 |
+ if (chroma) *dstp++ = av_clip_uint8(fmap[x << hsub] * (*srcp++ - 127) + 127 + dv); |
|
256 |
+ else *dstp++ = av_clip_uint8(fmap[x ] * *srcp++ + dv); |
|
257 |
+ } |
|
258 |
+ dst += dst_linesize; |
|
259 |
+ src += src_linesize; |
|
260 |
+ fmap += fmap_linesize << vsub; |
|
261 |
+ } |
|
262 |
+ } |
|
263 |
+ } |
|
264 |
+ |
|
265 |
+ return ff_filter_frame(outlink, out); |
|
266 |
+} |
|
267 |
+ |
|
268 |
+static int config_props(AVFilterLink *inlink) |
|
269 |
+{ |
|
270 |
+ VignetteContext *s = inlink->dst->priv; |
|
271 |
+ |
|
272 |
+ s->desc = av_pix_fmt_desc_get(inlink->format); |
|
273 |
+ s->var_values[VAR_W] = inlink->w; |
|
274 |
+ s->var_values[VAR_H] = inlink->h; |
|
275 |
+ s->var_values[VAR_TB] = av_q2d(inlink->time_base); |
|
276 |
+ s->var_values[VAR_R] = inlink->frame_rate.num == 0 || inlink->frame_rate.den == 0 ? |
|
277 |
+ NAN : av_q2d(inlink->frame_rate); |
|
278 |
+ |
|
279 |
+ if (inlink->sample_aspect_ratio.num > inlink->sample_aspect_ratio.den) { |
|
280 |
+ s->xscale = av_q2d(inlink->sample_aspect_ratio); |
|
281 |
+ s->yscale = 1; |
|
282 |
+ s->dmax = hypot(inlink->w / 2., s->yscale * inlink->h / 2.); |
|
283 |
+ } else { |
|
284 |
+ s->yscale = av_q2d(inlink->sample_aspect_ratio); |
|
285 |
+ s->xscale = 1; |
|
286 |
+ s->dmax = hypot(s->xscale * inlink->w / 2., inlink->h / 2.); |
|
287 |
+ } |
|
288 |
+ |
|
289 |
+ s->fmap_linesize = FFALIGN(inlink->w, 32); |
|
290 |
+ s->fmap = av_malloc(s->fmap_linesize * inlink->h * sizeof(*s->fmap)); |
|
291 |
+ if (!s->fmap) |
|
292 |
+ return AVERROR(ENOMEM); |
|
293 |
+ |
|
294 |
+ if (s->eval_mode == EVAL_MODE_INIT) |
|
295 |
+ update_context(s, inlink, NULL); |
|
296 |
+ |
|
297 |
+ return 0; |
|
298 |
+} |
|
299 |
+ |
|
300 |
+static const AVFilterPad vignette_inputs[] = { |
|
301 |
+ { |
|
302 |
+ .name = "default", |
|
303 |
+ .type = AVMEDIA_TYPE_VIDEO, |
|
304 |
+ .filter_frame = filter_frame, |
|
305 |
+ .config_props = config_props, |
|
306 |
+ }, |
|
307 |
+ { NULL } |
|
308 |
+}; |
|
309 |
+ |
|
310 |
+static const AVFilterPad vignette_outputs[] = { |
|
311 |
+ { |
|
312 |
+ .name = "default", |
|
313 |
+ .type = AVMEDIA_TYPE_VIDEO, |
|
314 |
+ }, |
|
315 |
+ { NULL } |
|
316 |
+}; |
|
317 |
+ |
|
318 |
+AVFilter avfilter_vf_vignette = { |
|
319 |
+ .name = "vignette", |
|
320 |
+ .description = NULL_IF_CONFIG_SMALL("Make or reverse a vignette effect."), |
|
321 |
+ .priv_size = sizeof(VignetteContext), |
|
322 |
+ .init = init, |
|
323 |
+ .uninit = uninit, |
|
324 |
+ .query_formats = query_formats, |
|
325 |
+ .inputs = vignette_inputs, |
|
326 |
+ .outputs = vignette_outputs, |
|
327 |
+ .priv_class = &vignette_class, |
|
328 |
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, |
|
329 |
+}; |