| @@ -27,6 +27,7 @@ · 26 unmodified lines |
| 27 | #include <dlfcn.h> | 27 | #include <dlfcn.h> |
| 28 | #include <frei0r.h> | 28 | #include <frei0r.h> |
| 29 | #include "libavutil/avstring.h" | 29 | #include "libavutil/avstring.h" |
| | 30 | #include "libavcore/imgutils.h" |
| 30 | #include "libavcore/parseutils.h" | 31 | #include "libavcore/parseutils.h" |
| 31 | #include "avfilter.h" | 32 | #include "avfilter.h" |
| 32 | | 33 | |
| @@ -54,6 +55,11 @@ typedef struct Frei0rContext { · 21 unmodified lines |
| 54 | f0r_destruct_f destruct; | 55 | f0r_destruct_f destruct; |
| 55 | f0r_deinit_f deinit; | 56 | f0r_deinit_f deinit; |
| 56 | char params[256]; | 57 | char params[256]; |
| | 58 | |
| | 59 | /* only used by the source */ |
| | 60 | int w, h; |
| | 61 | AVRational time_base; |
| | 62 | uint64_t pts; |
| 57 | } Frei0rContext; | 63 | } Frei0rContext; |
| 58 | | 64 | |
| 59 | static void *load_sym(AVFilterContext *ctx, const char *sym_name) | 65 | 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 · 137 unmodified lines |
| 197 | return dlopen(path, RTLD_NOW|RTLD_LOCAL); | 203 | return dlopen(path, RTLD_NOW|RTLD_LOCAL); |
| 198 | } | 204 | } |
| 199 | | 205 | |
| 200 | static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | 206 | static av_cold int frei0r_init(AVFilterContext *ctx, |
| | 207 | const char *dl_name, int type) |
| 201 | { | 208 | { |
| 202 | Frei0rContext *frei0r = ctx->priv; | 209 | Frei0rContext *frei0r = ctx->priv; |
| 203 | f0r_init_f f0r_init; | 210 | f0r_init_f f0r_init; |
| 204 | f0r_get_plugin_info_f f0r_get_plugin_info; | 211 | f0r_get_plugin_info_f f0r_get_plugin_info; |
| 205 | f0r_plugin_info_t *pi; | 212 | f0r_plugin_info_t *pi; |
| 206 | char dl_name[1024], *path; | 213 | char *path; |
| 207 | | | |
| 208 | *frei0r->params = 0; | | |
| 209 | | | |
| 210 | if (args) | | |
| 211 | sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params); | | |
| 212 | | 214 | |
| 213 | /* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */ | 215 | /* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */ |
| 214 | if ((path = av_strdup(getenv("FREI0R_PATH")))) { | 216 | if ((path = av_strdup(getenv("FREI0R_PATH")))) { |
| @@ -250,9 +252,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) · 35 unmodified lines |
| 250 | | 252 | |
| 251 | f0r_get_plugin_info(&frei0r->plugin_info); | 253 | f0r_get_plugin_info(&frei0r->plugin_info); |
| 252 | pi = &frei0r->plugin_info; | 254 | pi = &frei0r->plugin_info; |
| 253 | if (pi->plugin_type != F0R_PLUGIN_TYPE_FILTER) { | 255 | if (pi->plugin_type != type) { |
| 254 | av_log(ctx, AV_LOG_ERROR, | 256 | av_log(ctx, AV_LOG_ERROR, |
| 255 | "Invalid type '%s' for the plugin, a filter plugin was expected\n", | 257 | "Invalid type '%s' for the plugin\n", |
| | 258 | pi->plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" : |
| 256 | pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" : | 259 | pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" : |
| 257 | pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" : | 260 | pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" : |
| 258 | pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown"); | 261 | 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) · 12 unmodified lines |
| 271 | return 0; | 274 | return 0; |
| 272 | } | 275 | } |
| 273 | | 276 | |
| | 277 | static av_cold int filter_init(AVFilterContext *ctx, const char *args, void *opaque) |
| | 278 | { |
| | 279 | Frei0rContext *frei0r = ctx->priv; |
| | 280 | char dl_name[1024]; |
| | 281 | *frei0r->params = 0; |
| | 282 | |
| | 283 | if (args) |
| | 284 | sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params); |
| | 285 | |
| | 286 | return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_FILTER); |
| | 287 | } |
| | 288 | |
| 274 | static av_cold void uninit(AVFilterContext *ctx) | 289 | static av_cold void uninit(AVFilterContext *ctx) |
| 275 | { | 290 | { |
| 276 | Frei0rContext *frei0r = ctx->priv; | 291 | Frei0rContext *frei0r = ctx->priv; |
| @@ -344,7 +359,7 @@ AVFilter avfilter_vf_frei0r = { · 67 unmodified lines |
| 344 | .description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."), | 359 | .description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."), |
| 345 | | 360 | |
| 346 | .query_formats = query_formats, | 361 | .query_formats = query_formats, |
| 347 | .init = init, | 362 | .init = filter_init, |
| 348 | .uninit = uninit, | 363 | .uninit = uninit, |
| 349 | | 364 | |
| 350 | .priv_size = sizeof(Frei0rContext), | 365 | .priv_size = sizeof(Frei0rContext), |
| @@ -361,3 +376,89 @@ AVFilter avfilter_vf_frei0r = { · 10 unmodified lines |
| 361 | .type = AVMEDIA_TYPE_VIDEO, }, | 376 | .type = AVMEDIA_TYPE_VIDEO, }, |
| 362 | { .name = NULL}}, | 377 | { .name = NULL}}, |
| 363 | }; | 378 | }; |
| | 379 | |
| | 380 | static av_cold int source_init(AVFilterContext *ctx, const char *args, void *opaque) |
| | 381 | { |
| | 382 | Frei0rContext *frei0r = ctx->priv; |
| | 383 | char dl_name[1024], c; |
| | 384 | char frame_size[128] = ""; |
| | 385 | char frame_rate[128] = ""; |
| | 386 | AVRational frame_rate_q; |
| | 387 | |
| | 388 | memset(frei0r->params, 0, sizeof(frei0r->params)); |
| | 389 | |
| | 390 | if (args) |
| | 391 | sscanf(args, "%127[^:]:%127[^:]:%1023[^:=]%c%255c", |
| | 392 | frame_size, frame_rate, dl_name, &c, frei0r->params); |
| | 393 | |
| | 394 | if (av_parse_video_size(&frei0r->w, &frei0r->h, frame_size) < 0) { |
| | 395 | av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frame_size); |
| | 396 | return AVERROR(EINVAL); |
| | 397 | } |
| | 398 | |
| | 399 | if (av_parse_video_rate(&frame_rate_q, frame_rate) < 0 || |
| | 400 | frame_rate_q.den <= 0 || frame_rate_q.num <= 0) { |
| | 401 | av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frame_rate); |
| | 402 | return AVERROR(EINVAL); |
| | 403 | } |
| | 404 | frei0r->time_base.num = frame_rate_q.den; |
| | 405 | frei0r->time_base.den = frame_rate_q.num; |
| | 406 | |
| | 407 | return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_SOURCE); |
| | 408 | } |
| | 409 | |
| | 410 | static int source_config_props(AVFilterLink *outlink) |
| | 411 | { |
| | 412 | AVFilterContext *ctx = outlink->src; |
| | 413 | Frei0rContext *frei0r = ctx->priv; |
| | 414 | |
| | 415 | if (av_image_check_size(frei0r->w, frei0r->h, 0, ctx) < 0) |
| | 416 | return AVERROR(EINVAL); |
| | 417 | outlink->w = frei0r->w; |
| | 418 | outlink->h = frei0r->h; |
| | 419 | outlink->time_base = frei0r->time_base; |
| | 420 | |
| | 421 | if (!(frei0r->instance = frei0r->construct(outlink->w, outlink->h))) { |
| | 422 | av_log(ctx, AV_LOG_ERROR, "Impossible to load frei0r instance"); |
| | 423 | return AVERROR(EINVAL); |
| | 424 | } |
| | 425 | |
| | 426 | return set_params(ctx, frei0r->params); |
| | 427 | } |
| | 428 | |
| | 429 | static int source_request_frame(AVFilterLink *outlink) |
| | 430 | { |
| | 431 | Frei0rContext *frei0r = outlink->src->priv; |
| | 432 | AVFilterBufferRef *picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| | 433 | picref->video->pixel_aspect = (AVRational) {1, 1}; |
| | 434 | picref->pts = frei0r->pts++; |
| | 435 | picref->pos = -1; |
| | 436 | |
| | 437 | avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); |
| | 438 | frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}), |
| | 439 | NULL, (uint32_t *)picref->data[0]); |
| | 440 | avfilter_draw_slice(outlink, 0, outlink->h, 1); |
| | 441 | avfilter_end_frame(outlink); |
| | 442 | avfilter_unref_buffer(picref); |
| | 443 | |
| | 444 | return 0; |
| | 445 | } |
| | 446 | |
| | 447 | AVFilter avfilter_vsrc_frei0r_src = { |
| | 448 | .name = "frei0r_src", |
| | 449 | .description = NULL_IF_CONFIG_SMALL("Generate a frei0r source."), |
| | 450 | |
| | 451 | .priv_size = sizeof(Frei0rContext), |
| | 452 | .init = source_init, |
| | 453 | .uninit = uninit, |
| | 454 | |
| | 455 | .query_formats = query_formats, |
| | 456 | |
| | 457 | .inputs = (AVFilterPad[]) {{ .name = NULL}}, |
| | 458 | |
| | 459 | .outputs = (AVFilterPad[]) {{ .name = "default", |
| | 460 | .type = AVMEDIA_TYPE_VIDEO, |
| | 461 | .request_frame = source_request_frame, |
| | 462 | .config_props = source_config_props }, |
| | 463 | { .name = NULL}}, |
| | 464 | }; |