Browse code

Implement frei0r source.

Originally committed as revision 25855 to svn://svn.ffmpeg.org/ffmpeg/trunk

Stefano Sabatini authored on 2010/12/01 05:14:36
Showing 6 changed files
... ...
@@ -60,6 +60,7 @@ version <next>:
60 60
 - rename aspect filter to setdar, and pixelaspect to setsar
61 61
 - IEC 61937 demuxer
62 62
 - Mobotix .mxg demuxer
63
+- frei0r source added
63 64
 
64 65
 
65 66
 version 0.6:
... ...
@@ -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
+};