X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_frei0r.c;h=4dd6fbef090bc1be806b323a8d2d0dd2f991fc41;hb=b74a1da49db5ebed51aceae6cacc2329288a92c1;hp=226f656bcdc8bedadcdb02d4c4cc90d535fdcd1b;hpb=f6c182a0c3de71059e73dd5013c8b4dae0d83a5e;p=ffmpeg diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c index 226f656bcdc..4dd6fbef090 100644 --- a/libavfilter/vf_frei0r.c +++ b/libavfilter/vf_frei0r.c @@ -1,19 +1,19 @@ /* - * copyright (c) 2010 Stefano Sabatini - * This file is part of FFmpeg. + * Copyright (c) 2010 Stefano Sabatini + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,8 +27,11 @@ #include #include #include "libavutil/avstring.h" +#include "libavutil/imgutils.h" +#include "libavutil/mathematics.h" +#include "libavutil/parseutils.h" #include "avfilter.h" -#include "parseutils.h" +#include "formats.h" typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height); typedef void (*f0r_destruct_f)(f0r_instance_t instance); @@ -54,6 +57,11 @@ typedef struct Frei0rContext { f0r_destruct_f destruct; f0r_deinit_f deinit; char params[256]; + + /* only used by the source */ + int w, h; + AVRational time_base; + uint64_t pts; } Frei0rContext; static void *load_sym(AVFilterContext *ctx, const char *sym_name) @@ -197,18 +205,14 @@ static void *load_path(AVFilterContext *ctx, const char *prefix, const char *nam 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; f0r_init_f f0r_init; f0r_get_plugin_info_f f0r_get_plugin_info; f0r_plugin_info_t *pi; - char dl_name[1024], *path; - - *frei0r->params = 0; - - if (args) - sscanf(args, "%1023[^:]:%255c", dl_name, frei0r->params); + char *path; /* see: http://piksel.org/frei0r/1.2/spec/1.2/spec/group__pluglocations.html */ if ((path = av_strdup(getenv("FREI0R_PATH")))) { @@ -250,9 +254,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) f0r_get_plugin_info(&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, - "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_MIXER2 ? "mixer2" : pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown"); @@ -271,11 +276,23 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) return 0; } +static av_cold int filter_init(AVFilterContext *ctx, const char *args, void *opaque) +{ + Frei0rContext *frei0r = ctx->priv; + char dl_name[1024], c; + *frei0r->params = 0; + + if (args) + sscanf(args, "%1023[^:=]%c%255c", dl_name, &c, frei0r->params); + + return frei0r_init(ctx, dl_name, F0R_PLUGIN_TYPE_FILTER); +} + static av_cold void uninit(AVFilterContext *ctx) { Frei0rContext *frei0r = ctx->priv; - if (frei0r->destruct) + if (frei0r->destruct && frei0r->instance) frei0r->destruct(frei0r->instance); if (frei0r->deinit) frei0r->deinit(); @@ -304,20 +321,20 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *formats = NULL; if (frei0r->plugin_info.color_model == F0R_COLOR_MODEL_BGRA8888) { - avfilter_add_format(&formats, PIX_FMT_BGRA); + ff_add_format(&formats, PIX_FMT_BGRA); } else if (frei0r->plugin_info.color_model == F0R_COLOR_MODEL_RGBA8888) { - avfilter_add_format(&formats, PIX_FMT_RGBA); + ff_add_format(&formats, PIX_FMT_RGBA); } else { /* F0R_COLOR_MODEL_PACKED32 */ static const enum PixelFormat pix_fmts[] = { PIX_FMT_BGRA, PIX_FMT_ARGB, PIX_FMT_ABGR, PIX_FMT_ARGB, PIX_FMT_NONE }; - formats = avfilter_make_format_list(pix_fmts); + formats = ff_make_format_list(pix_fmts); } if (!formats) return AVERROR(ENOMEM); - avfilter_set_common_formats(ctx, formats); + ff_set_common_formats(ctx, formats); return 0; } @@ -344,7 +361,7 @@ AVFilter avfilter_vf_frei0r = { .description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."), .query_formats = query_formats, - .init = init, + .init = filter_init, .uninit = uninit, .priv_size = sizeof(Frei0rContext), @@ -361,3 +378,89 @@ AVFilter avfilter_vf_frei0r = { .type = AVMEDIA_TYPE_VIDEO, }, { .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}}, +};