Originally committed as revision 25855 to svn://svn.ffmpeg.org/ffmpeg/trunk
Stefano Sabatini authored on 2010/12/01 05:14:36... | ... |
@@ -283,6 +283,7 @@ The following command: |
283 | 283 |
|
284 | 284 |
will convert the input video to the format "yuv420p". |
285 | 285 |
|
286 |
+@anchor{frei0r} |
|
286 | 287 |
@section frei0r |
287 | 288 |
|
288 | 289 |
Apply a frei0r effect to the input video. |
... | ... |
@@ -869,6 +870,34 @@ respectively 352 and 288 (corresponding to the CIF size format). |
869 | 869 |
timebase. The expression can contain the constants "PI", "E", "PHI", |
870 | 870 |
"AVTB" (the default timebase), and defaults to the value "AVTB". |
871 | 871 |
|
872 |
+@section frei0r_src |
|
873 |
+ |
|
874 |
+Provide a frei0r source. |
|
875 |
+ |
|
876 |
+To enable compilation of this filter you need to install the frei0r |
|
877 |
+header and configure FFmpeg with --enable-frei0r. |
|
878 |
+ |
|
879 |
+The source supports the syntax: |
|
880 |
+@example |
|
881 |
+@var{size}:@var{rate}:@var{src_name}[@{=|:@}@var{param1}:@var{param2}:...:@var{paramN}] |
|
882 |
+@end example |
|
883 |
+ |
|
884 |
+@var{size} is the size of the video to generate, may be a string of the |
|
885 |
+form @var{width}x@var{height} or a frame size abbreviation. |
|
886 |
+@var{rate} is the rate of the video to generate, may be a string of |
|
887 |
+the form @var{num}/@var{den} or a frame rate abbreviation. |
|
888 |
+@var{src_name} is the name to the frei0r source to load. For more |
|
889 |
+information regarding frei0r and how to set the parameters read the |
|
890 |
+section "frei0r" (@pxref{frei0r}) in the description of the video |
|
891 |
+filters. |
|
892 |
+ |
|
893 |
+Some examples follow: |
|
894 |
+@example |
|
895 |
+# generate a frei0r partik0l source with size 200x200 and framerate 10 |
|
896 |
+# which is overlayed on the overlay filter main input |
|
897 |
+frei0r_src=200x200:10:partik0l=1234 [overlay]; [in][overlay] overlay |
|
898 |
+@end example |
|
899 |
+ |
|
872 | 900 |
@c man end VIDEO SOURCES |
873 | 901 |
|
874 | 902 |
@chapter Video Sinks |
... | ... |
@@ -46,6 +46,7 @@ OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o |
46 | 46 |
|
47 | 47 |
OBJS-$(CONFIG_BUFFER_FILTER) += vsrc_buffer.o |
48 | 48 |
OBJS-$(CONFIG_COLOR_FILTER) += vf_pad.o |
49 |
+OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o |
|
49 | 50 |
OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o |
50 | 51 |
|
51 | 52 |
OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o |
... | ... |
@@ -67,6 +67,7 @@ void avfilter_register_all(void) |
67 | 67 |
|
68 | 68 |
REGISTER_FILTER (BUFFER, buffer, vsrc); |
69 | 69 |
REGISTER_FILTER (COLOR, color, vsrc); |
70 |
+ REGISTER_FILTER (FREI0R, frei0r_src, vsrc); |
|
70 | 71 |
REGISTER_FILTER (NULLSRC, nullsrc, vsrc); |
71 | 72 |
|
72 | 73 |
REGISTER_FILTER (NULLSINK, nullsink, vsink); |
... | ... |
@@ -25,7 +25,7 @@ |
25 | 25 |
#include "libavutil/avutil.h" |
26 | 26 |
|
27 | 27 |
#define LIBAVFILTER_VERSION_MAJOR 1 |
28 |
-#define LIBAVFILTER_VERSION_MINOR 65 |
|
28 |
+#define LIBAVFILTER_VERSION_MINOR 66 |
|
29 | 29 |
#define LIBAVFILTER_VERSION_MICRO 0 |
30 | 30 |
|
31 | 31 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
... | ... |
@@ -27,6 +27,7 @@ |
27 | 27 |
#include <dlfcn.h> |
28 | 28 |
#include <frei0r.h> |
29 | 29 |
#include "libavutil/avstring.h" |
30 |
+#include "libavcore/imgutils.h" |
|
30 | 31 |
#include "libavcore/parseutils.h" |
31 | 32 |
#include "avfilter.h" |
32 | 33 |
|
... | ... |
@@ -54,6 +55,11 @@ typedef struct Frei0rContext { |
54 | 54 |
f0r_destruct_f destruct; |
55 | 55 |
f0r_deinit_f deinit; |
56 | 56 |
char params[256]; |
57 |
+ |
|
58 |
+ /* only used by the source */ |
|
59 |
+ int w, h; |
|
60 |
+ AVRational time_base; |
|
61 |
+ uint64_t pts; |
|
57 | 62 |
} Frei0rContext; |
58 | 63 |
|
59 | 64 |
static void *load_sym(AVFilterContext *ctx, const char *sym_name) |
... | ... |
@@ -197,18 +203,14 @@ static void *load_path(AVFilterContext *ctx, const char *prefix, const char *nam |
197 | 197 |
return dlopen(path, RTLD_NOW|RTLD_LOCAL); |
198 | 198 |
} |
199 | 199 |
|
200 |
-static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
|
200 |
+static av_cold int frei0r_init(AVFilterContext *ctx, |
|
201 |
+ const char *dl_name, int type) |
|
201 | 202 |
{ |
202 | 203 |
Frei0rContext *frei0r = ctx->priv; |
203 | 204 |
f0r_init_f f0r_init; |
204 | 205 |
f0r_get_plugin_info_f f0r_get_plugin_info; |
205 | 206 |
f0r_plugin_info_t *pi; |
206 |
- char dl_name[1024], *path; |
|
207 |
- |
|
208 |
- *frei0r->params = 0; |
|
209 |
- |
|
210 |
- if (args) |
|
211 |
- sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params); |
|
207 |
+ char *path; |
|
212 | 208 |
|
213 | 209 |
/* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */ |
214 | 210 |
if ((path = av_strdup(getenv("FREI0R_PATH")))) { |
... | ... |
@@ -250,9 +252,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
250 | 250 |
|
251 | 251 |
f0r_get_plugin_info(&frei0r->plugin_info); |
252 | 252 |
pi = &frei0r->plugin_info; |
253 |
- if (pi->plugin_type != F0R_PLUGIN_TYPE_FILTER) { |
|
253 |
+ if (pi->plugin_type != type) { |
|
254 | 254 |
av_log(ctx, AV_LOG_ERROR, |
255 |
- "Invalid type '%s' for the plugin, a filter plugin was expected\n", |
|
255 |
+ "Invalid type '%s' for the plugin\n", |
|
256 |
+ pi->plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" : |
|
256 | 257 |
pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" : |
257 | 258 |
pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" : |
258 | 259 |
pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown"); |
... | ... |
@@ -271,6 +274,18 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
271 | 271 |
return 0; |
272 | 272 |
} |
273 | 273 |
|
274 |
+static av_cold int filter_init(AVFilterContext *ctx, const char *args, void *opaque) |
|
275 |
+{ |
|
276 |
+ Frei0rContext *frei0r = ctx->priv; |
|
277 |
+ char dl_name[1024]; |
|
278 |
+ *frei0r->params = 0; |
|
279 |
+ |
|
280 |
+ if (args) |
|
281 |
+ sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params); |
|
282 |
+ |
|
283 |
+ return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_FILTER); |
|
284 |
+} |
|
285 |
+ |
|
274 | 286 |
static av_cold void uninit(AVFilterContext *ctx) |
275 | 287 |
{ |
276 | 288 |
Frei0rContext *frei0r = ctx->priv; |
... | ... |
@@ -344,7 +359,7 @@ AVFilter avfilter_vf_frei0r = { |
344 | 344 |
.description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."), |
345 | 345 |
|
346 | 346 |
.query_formats = query_formats, |
347 |
- .init = init, |
|
347 |
+ .init = filter_init, |
|
348 | 348 |
.uninit = uninit, |
349 | 349 |
|
350 | 350 |
.priv_size = sizeof(Frei0rContext), |
... | ... |
@@ -361,3 +376,89 @@ AVFilter avfilter_vf_frei0r = { |
361 | 361 |
.type = AVMEDIA_TYPE_VIDEO, }, |
362 | 362 |
{ .name = NULL}}, |
363 | 363 |
}; |
364 |
+ |
|
365 |
+static av_cold int source_init(AVFilterContext *ctx, const char *args, void *opaque) |
|
366 |
+{ |
|
367 |
+ Frei0rContext *frei0r = ctx->priv; |
|
368 |
+ char dl_name[1024], c; |
|
369 |
+ char frame_size[128] = ""; |
|
370 |
+ char frame_rate[128] = ""; |
|
371 |
+ AVRational frame_rate_q; |
|
372 |
+ |
|
373 |
+ memset(frei0r->params, 0, sizeof(frei0r->params)); |
|
374 |
+ |
|
375 |
+ if (args) |
|
376 |
+ sscanf(args, "%127[^:]:%127[^:]:%1023[^:=]%c%255c", |
|
377 |
+ frame_size, frame_rate, dl_name, &c, frei0r->params); |
|
378 |
+ |
|
379 |
+ if (av_parse_video_size(&frei0r->w, &frei0r->h, frame_size) < 0) { |
|
380 |
+ av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frame_size); |
|
381 |
+ return AVERROR(EINVAL); |
|
382 |
+ } |
|
383 |
+ |
|
384 |
+ if (av_parse_video_rate(&frame_rate_q, frame_rate) < 0 || |
|
385 |
+ frame_rate_q.den <= 0 || frame_rate_q.num <= 0) { |
|
386 |
+ av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frame_rate); |
|
387 |
+ return AVERROR(EINVAL); |
|
388 |
+ } |
|
389 |
+ frei0r->time_base.num = frame_rate_q.den; |
|
390 |
+ frei0r->time_base.den = frame_rate_q.num; |
|
391 |
+ |
|
392 |
+ return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_SOURCE); |
|
393 |
+} |
|
394 |
+ |
|
395 |
+static int source_config_props(AVFilterLink *outlink) |
|
396 |
+{ |
|
397 |
+ AVFilterContext *ctx = outlink->src; |
|
398 |
+ Frei0rContext *frei0r = ctx->priv; |
|
399 |
+ |
|
400 |
+ if (av_image_check_size(frei0r->w, frei0r->h, 0, ctx) < 0) |
|
401 |
+ return AVERROR(EINVAL); |
|
402 |
+ outlink->w = frei0r->w; |
|
403 |
+ outlink->h = frei0r->h; |
|
404 |
+ outlink->time_base = frei0r->time_base; |
|
405 |
+ |
|
406 |
+ if (!(frei0r->instance = frei0r->construct(outlink->w, outlink->h))) { |
|
407 |
+ av_log(ctx, AV_LOG_ERROR, "Impossible to load frei0r instance"); |
|
408 |
+ return AVERROR(EINVAL); |
|
409 |
+ } |
|
410 |
+ |
|
411 |
+ return set_params(ctx, frei0r->params); |
|
412 |
+} |
|
413 |
+ |
|
414 |
+static int source_request_frame(AVFilterLink *outlink) |
|
415 |
+{ |
|
416 |
+ Frei0rContext *frei0r = outlink->src->priv; |
|
417 |
+ AVFilterBufferRef *picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
|
418 |
+ picref->video->pixel_aspect = (AVRational) {1, 1}; |
|
419 |
+ picref->pts = frei0r->pts++; |
|
420 |
+ picref->pos = -1; |
|
421 |
+ |
|
422 |
+ avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); |
|
423 |
+ frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}), |
|
424 |
+ NULL, (uint32_t *)picref->data[0]); |
|
425 |
+ avfilter_draw_slice(outlink, 0, outlink->h, 1); |
|
426 |
+ avfilter_end_frame(outlink); |
|
427 |
+ avfilter_unref_buffer(picref); |
|
428 |
+ |
|
429 |
+ return 0; |
|
430 |
+} |
|
431 |
+ |
|
432 |
+AVFilter avfilter_vsrc_frei0r_src = { |
|
433 |
+ .name = "frei0r_src", |
|
434 |
+ .description = NULL_IF_CONFIG_SMALL("Generate a frei0r source."), |
|
435 |
+ |
|
436 |
+ .priv_size = sizeof(Frei0rContext), |
|
437 |
+ .init = source_init, |
|
438 |
+ .uninit = uninit, |
|
439 |
+ |
|
440 |
+ .query_formats = query_formats, |
|
441 |
+ |
|
442 |
+ .inputs = (AVFilterPad[]) {{ .name = NULL}}, |
|
443 |
+ |
|
444 |
+ .outputs = (AVFilterPad[]) {{ .name = "default", |
|
445 |
+ .type = AVMEDIA_TYPE_VIDEO, |
|
446 |
+ .request_frame = source_request_frame, |
|
447 |
+ .config_props = source_config_props }, |
|
448 |
+ { .name = NULL}}, |
|
449 |
+}; |