Commit f8608dca authored by Stefano Sabatini's avatar Stefano Sabatini

Implement frei0r source.

Originally committed as revision 25855 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 60445a09
...@@ -60,6 +60,7 @@ version <next>: ...@@ -60,6 +60,7 @@ version <next>:
- rename aspect filter to setdar, and pixelaspect to setsar - rename aspect filter to setdar, and pixelaspect to setsar
- IEC 61937 demuxer - IEC 61937 demuxer
- Mobotix .mxg demuxer - Mobotix .mxg demuxer
- frei0r source added
version 0.6: version 0.6:
......
...@@ -283,6 +283,7 @@ The following command: ...@@ -283,6 +283,7 @@ The following command:
will convert the input video to the format "yuv420p". will convert the input video to the format "yuv420p".
@anchor{frei0r}
@section frei0r @section frei0r
Apply a frei0r effect to the input video. Apply a frei0r effect to the input video.
...@@ -869,6 +870,34 @@ respectively 352 and 288 (corresponding to the CIF size format). ...@@ -869,6 +870,34 @@ respectively 352 and 288 (corresponding to the CIF size format).
timebase. The expression can contain the constants "PI", "E", "PHI", timebase. The expression can contain the constants "PI", "E", "PHI",
"AVTB" (the default timebase), and defaults to the value "AVTB". "AVTB" (the default timebase), and defaults to the value "AVTB".
@section frei0r_src
Provide a frei0r source.
To enable compilation of this filter you need to install the frei0r
header and configure FFmpeg with --enable-frei0r.
The source supports the syntax:
@example
@var{size}:@var{rate}:@var{src_name}[@{=|:@}@var{param1}:@var{param2}:...:@var{paramN}]
@end example
@var{size} is the size of the video to generate, may be a string of the
form @var{width}x@var{height} or a frame size abbreviation.
@var{rate} is the rate of the video to generate, may be a string of
the form @var{num}/@var{den} or a frame rate abbreviation.
@var{src_name} is the name to the frei0r source to load. For more
information regarding frei0r and how to set the parameters read the
section "frei0r" (@pxref{frei0r}) in the description of the video
filters.
Some examples follow:
@example
# generate a frei0r partik0l source with size 200x200 and framerate 10
# which is overlayed on the overlay filter main input
frei0r_src=200x200:10:partik0l=1234 [overlay]; [in][overlay] overlay
@end example
@c man end VIDEO SOURCES @c man end VIDEO SOURCES
@chapter Video Sinks @chapter Video Sinks
......
...@@ -46,6 +46,7 @@ OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o ...@@ -46,6 +46,7 @@ OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o
OBJS-$(CONFIG_BUFFER_FILTER) += vsrc_buffer.o OBJS-$(CONFIG_BUFFER_FILTER) += vsrc_buffer.o
OBJS-$(CONFIG_COLOR_FILTER) += vf_pad.o OBJS-$(CONFIG_COLOR_FILTER) += vf_pad.o
OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o
OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_nullsrc.o
OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o
......
...@@ -67,6 +67,7 @@ void avfilter_register_all(void) ...@@ -67,6 +67,7 @@ void avfilter_register_all(void)
REGISTER_FILTER (BUFFER, buffer, vsrc); REGISTER_FILTER (BUFFER, buffer, vsrc);
REGISTER_FILTER (COLOR, color, vsrc); REGISTER_FILTER (COLOR, color, vsrc);
REGISTER_FILTER (FREI0R, frei0r_src, vsrc);
REGISTER_FILTER (NULLSRC, nullsrc, vsrc); REGISTER_FILTER (NULLSRC, nullsrc, vsrc);
REGISTER_FILTER (NULLSINK, nullsink, vsink); REGISTER_FILTER (NULLSINK, nullsink, vsink);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 1 #define LIBAVFILTER_VERSION_MAJOR 1
#define LIBAVFILTER_VERSION_MINOR 65 #define LIBAVFILTER_VERSION_MINOR 66
#define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_MICRO 0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <frei0r.h> #include <frei0r.h>
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavcore/imgutils.h"
#include "libavcore/parseutils.h" #include "libavcore/parseutils.h"
#include "avfilter.h" #include "avfilter.h"
...@@ -54,6 +55,11 @@ typedef struct Frei0rContext { ...@@ -54,6 +55,11 @@ typedef struct Frei0rContext {
f0r_destruct_f destruct; f0r_destruct_f destruct;
f0r_deinit_f deinit; f0r_deinit_f deinit;
char params[256]; char params[256];
/* only used by the source */
int w, h;
AVRational time_base;
uint64_t pts;
} Frei0rContext; } Frei0rContext;
static void *load_sym(AVFilterContext *ctx, const char *sym_name) 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,18 +203,14 @@ static void *load_path(AVFilterContext *ctx, const char *prefix, const char *nam
return dlopen(path, RTLD_NOW|RTLD_LOCAL); return dlopen(path, RTLD_NOW|RTLD_LOCAL);
} }
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) static av_cold int frei0r_init(AVFilterContext *ctx,
const char *dl_name, int type)
{ {
Frei0rContext *frei0r = ctx->priv; Frei0rContext *frei0r = ctx->priv;
f0r_init_f f0r_init; f0r_init_f f0r_init;
f0r_get_plugin_info_f f0r_get_plugin_info; f0r_get_plugin_info_f f0r_get_plugin_info;
f0r_plugin_info_t *pi; f0r_plugin_info_t *pi;
char dl_name[1024], *path; char *path;
*frei0r->params = 0;
if (args)
sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params);
/* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */ /* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */
if ((path = av_strdup(getenv("FREI0R_PATH")))) { if ((path = av_strdup(getenv("FREI0R_PATH")))) {
...@@ -250,9 +252,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) ...@@ -250,9 +252,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
f0r_get_plugin_info(&frei0r->plugin_info); f0r_get_plugin_info(&frei0r->plugin_info);
pi = &frei0r->plugin_info; pi = &frei0r->plugin_info;
if (pi->plugin_type != F0R_PLUGIN_TYPE_FILTER) { if (pi->plugin_type != type) {
av_log(ctx, AV_LOG_ERROR, av_log(ctx, AV_LOG_ERROR,
"Invalid type '%s' for the plugin, a filter plugin was expected\n", "Invalid type '%s' for the plugin\n",
pi->plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" :
pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" : pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" :
pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" : pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" :
pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown"); 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,6 +274,18 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return 0; return 0;
} }
static av_cold int filter_init(AVFilterContext *ctx, const char *args, void *opaque)
{
Frei0rContext *frei0r = ctx->priv;
char dl_name[1024];
*frei0r->params = 0;
if (args)
sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params);
return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_FILTER);
}
static av_cold void uninit(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx)
{ {
Frei0rContext *frei0r = ctx->priv; Frei0rContext *frei0r = ctx->priv;
...@@ -344,7 +359,7 @@ AVFilter avfilter_vf_frei0r = { ...@@ -344,7 +359,7 @@ AVFilter avfilter_vf_frei0r = {
.description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."), .description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."),
.query_formats = query_formats, .query_formats = query_formats,
.init = init, .init = filter_init,
.uninit = uninit, .uninit = uninit,
.priv_size = sizeof(Frei0rContext), .priv_size = sizeof(Frei0rContext),
...@@ -361,3 +376,89 @@ AVFilter avfilter_vf_frei0r = { ...@@ -361,3 +376,89 @@ AVFilter avfilter_vf_frei0r = {
.type = AVMEDIA_TYPE_VIDEO, }, .type = AVMEDIA_TYPE_VIDEO, },
{ .name = NULL}}, { .name = NULL}},
}; };
static av_cold int source_init(AVFilterContext *ctx, const char *args, void *opaque)
{
Frei0rContext *frei0r = ctx->priv;
char dl_name[1024], c;
char frame_size[128] = "";
char frame_rate[128] = "";
AVRational frame_rate_q;
memset(frei0r->params, 0, sizeof(frei0r->params));
if (args)
sscanf(args, "%127[^:]:%127[^:]:%1023[^:=]%c%255c",
frame_size, frame_rate, dl_name, &c, frei0r->params);
if (av_parse_video_size(&frei0r->w, &frei0r->h, frame_size) < 0) {
av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frame_size);
return AVERROR(EINVAL);
}
if (av_parse_video_rate(&frame_rate_q, frame_rate) < 0 ||
frame_rate_q.den <= 0 || frame_rate_q.num <= 0) {
av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frame_rate);
return AVERROR(EINVAL);
}
frei0r->time_base.num = frame_rate_q.den;
frei0r->time_base.den = frame_rate_q.num;
return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_SOURCE);
}
static int source_config_props(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
Frei0rContext *frei0r = ctx->priv;
if (av_image_check_size(frei0r->w, frei0r->h, 0, ctx) < 0)
return AVERROR(EINVAL);
outlink->w = frei0r->w;
outlink->h = frei0r->h;
outlink->time_base = frei0r->time_base;
if (!(frei0r->instance = frei0r->construct(outlink->w, outlink->h))) {
av_log(ctx, AV_LOG_ERROR, "Impossible to load frei0r instance");
return AVERROR(EINVAL);
}
return set_params(ctx, frei0r->params);
}
static int source_request_frame(AVFilterLink *outlink)
{
Frei0rContext *frei0r = outlink->src->priv;
AVFilterBufferRef *picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
picref->video->pixel_aspect = (AVRational) {1, 1};
picref->pts = frei0r->pts++;
picref->pos = -1;
avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}),
NULL, (uint32_t *)picref->data[0]);
avfilter_draw_slice(outlink, 0, outlink->h, 1);
avfilter_end_frame(outlink);
avfilter_unref_buffer(picref);
return 0;
}
AVFilter avfilter_vsrc_frei0r_src = {
.name = "frei0r_src",
.description = NULL_IF_CONFIG_SMALL("Generate a frei0r source."),
.priv_size = sizeof(Frei0rContext),
.init = source_init,
.uninit = uninit,
.query_formats = query_formats,
.inputs = (AVFilterPad[]) {{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.request_frame = source_request_frame,
.config_props = source_config_props },
{ .name = NULL}},
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment