annotate ffmpeg/libavfilter/vf_frei0r.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2010 Stefano Sabatini
yading@10 3 * This file is part of FFmpeg.
yading@10 4 *
yading@10 5 * FFmpeg is free software; you can redistribute it and/or
yading@10 6 * modify it under the terms of the GNU Lesser General Public
yading@10 7 * License as published by the Free Software Foundation; either
yading@10 8 * version 2.1 of the License, or (at your option) any later version.
yading@10 9 *
yading@10 10 * FFmpeg is distributed in the hope that it will be useful,
yading@10 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 13 * Lesser General Public License for more details.
yading@10 14 *
yading@10 15 * You should have received a copy of the GNU Lesser General Public
yading@10 16 * License along with FFmpeg; if not, write to the Free Software
yading@10 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 18 */
yading@10 19
yading@10 20 /**
yading@10 21 * @file
yading@10 22 * frei0r wrapper
yading@10 23 */
yading@10 24
yading@10 25 /* #define DEBUG */
yading@10 26
yading@10 27 #include <dlfcn.h>
yading@10 28 #include <frei0r.h>
yading@10 29 #include <stdio.h>
yading@10 30 #include <string.h>
yading@10 31 #include <stdlib.h>
yading@10 32 #include "config.h"
yading@10 33 #include "libavutil/avstring.h"
yading@10 34 #include "libavutil/imgutils.h"
yading@10 35 #include "libavutil/internal.h"
yading@10 36 #include "libavutil/mathematics.h"
yading@10 37 #include "libavutil/mem.h"
yading@10 38 #include "libavutil/opt.h"
yading@10 39 #include "libavutil/parseutils.h"
yading@10 40 #include "avfilter.h"
yading@10 41 #include "formats.h"
yading@10 42 #include "internal.h"
yading@10 43 #include "video.h"
yading@10 44
yading@10 45 typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height);
yading@10 46 typedef void (*f0r_destruct_f)(f0r_instance_t instance);
yading@10 47 typedef void (*f0r_deinit_f)(void);
yading@10 48 typedef int (*f0r_init_f)(void);
yading@10 49 typedef void (*f0r_get_plugin_info_f)(f0r_plugin_info_t *info);
yading@10 50 typedef void (*f0r_get_param_info_f)(f0r_param_info_t *info, int param_index);
yading@10 51 typedef void (*f0r_update_f)(f0r_instance_t instance, double time, const uint32_t *inframe, uint32_t *outframe);
yading@10 52 typedef void (*f0r_update2_f)(f0r_instance_t instance, double time, const uint32_t *inframe1, const uint32_t *inframe2, const uint32_t *inframe3, uint32_t *outframe);
yading@10 53 typedef void (*f0r_set_param_value_f)(f0r_instance_t instance, f0r_param_t param, int param_index);
yading@10 54 typedef void (*f0r_get_param_value_f)(f0r_instance_t instance, f0r_param_t param, int param_index);
yading@10 55
yading@10 56 typedef struct Frei0rContext {
yading@10 57 const AVClass *class;
yading@10 58 f0r_update_f update;
yading@10 59 void *dl_handle; /* dynamic library handle */
yading@10 60 f0r_instance_t instance;
yading@10 61 f0r_plugin_info_t plugin_info;
yading@10 62
yading@10 63 f0r_get_param_info_f get_param_info;
yading@10 64 f0r_get_param_value_f get_param_value;
yading@10 65 f0r_set_param_value_f set_param_value;
yading@10 66 f0r_construct_f construct;
yading@10 67 f0r_destruct_f destruct;
yading@10 68 f0r_deinit_f deinit;
yading@10 69
yading@10 70 char *dl_name;
yading@10 71 char *params;
yading@10 72 char *size;
yading@10 73 char *framerate;
yading@10 74
yading@10 75 /* only used by the source */
yading@10 76 int w, h;
yading@10 77 AVRational time_base;
yading@10 78 uint64_t pts;
yading@10 79 } Frei0rContext;
yading@10 80
yading@10 81 static void *load_sym(AVFilterContext *ctx, const char *sym_name)
yading@10 82 {
yading@10 83 Frei0rContext *frei0r = ctx->priv;
yading@10 84 void *sym = dlsym(frei0r->dl_handle, sym_name);
yading@10 85 if (!sym)
yading@10 86 av_log(ctx, AV_LOG_ERROR, "Could not find symbol '%s' in loaded module\n", sym_name);
yading@10 87 return sym;
yading@10 88 }
yading@10 89
yading@10 90 static int set_param(AVFilterContext *ctx, f0r_param_info_t info, int index, char *param)
yading@10 91 {
yading@10 92 Frei0rContext *frei0r = ctx->priv;
yading@10 93 union {
yading@10 94 double d;
yading@10 95 f0r_param_color_t col;
yading@10 96 f0r_param_position_t pos;
yading@10 97 } val;
yading@10 98 char *tail;
yading@10 99 uint8_t rgba[4];
yading@10 100
yading@10 101 switch (info.type) {
yading@10 102 case F0R_PARAM_BOOL:
yading@10 103 if (!strcmp(param, "y")) val.d = 1.0;
yading@10 104 else if (!strcmp(param, "n")) val.d = 0.0;
yading@10 105 else goto fail;
yading@10 106 break;
yading@10 107
yading@10 108 case F0R_PARAM_DOUBLE:
yading@10 109 val.d = strtod(param, &tail);
yading@10 110 if (*tail || val.d == HUGE_VAL)
yading@10 111 goto fail;
yading@10 112 break;
yading@10 113
yading@10 114 case F0R_PARAM_COLOR:
yading@10 115 if (sscanf(param, "%f/%f/%f", &val.col.r, &val.col.g, &val.col.b) != 3) {
yading@10 116 if (av_parse_color(rgba, param, -1, ctx) < 0)
yading@10 117 goto fail;
yading@10 118 val.col.r = rgba[0] / 255.0;
yading@10 119 val.col.g = rgba[1] / 255.0;
yading@10 120 val.col.b = rgba[2] / 255.0;
yading@10 121 }
yading@10 122 break;
yading@10 123
yading@10 124 case F0R_PARAM_POSITION:
yading@10 125 if (sscanf(param, "%lf/%lf", &val.pos.x, &val.pos.y) != 2)
yading@10 126 goto fail;
yading@10 127 break;
yading@10 128 }
yading@10 129
yading@10 130 frei0r->set_param_value(frei0r->instance, &val, index);
yading@10 131 return 0;
yading@10 132
yading@10 133 fail:
yading@10 134 av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for parameter '%s'\n",
yading@10 135 param, info.name);
yading@10 136 return AVERROR(EINVAL);
yading@10 137 }
yading@10 138
yading@10 139 static int set_params(AVFilterContext *ctx, const char *params)
yading@10 140 {
yading@10 141 Frei0rContext *frei0r = ctx->priv;
yading@10 142 int i;
yading@10 143
yading@10 144 for (i = 0; i < frei0r->plugin_info.num_params; i++) {
yading@10 145 f0r_param_info_t info;
yading@10 146 char *param;
yading@10 147 int ret;
yading@10 148
yading@10 149 frei0r->get_param_info(&info, i);
yading@10 150
yading@10 151 if (*params) {
yading@10 152 if (!(param = av_get_token(&params, "|")))
yading@10 153 return AVERROR(ENOMEM);
yading@10 154 params++; /* skip ':' */
yading@10 155 ret = set_param(ctx, info, i, param);
yading@10 156 av_free(param);
yading@10 157 if (ret < 0)
yading@10 158 return ret;
yading@10 159 }
yading@10 160
yading@10 161 av_log(ctx, AV_LOG_VERBOSE,
yading@10 162 "idx:%d name:'%s' type:%s explanation:'%s' ",
yading@10 163 i, info.name,
yading@10 164 info.type == F0R_PARAM_BOOL ? "bool" :
yading@10 165 info.type == F0R_PARAM_DOUBLE ? "double" :
yading@10 166 info.type == F0R_PARAM_COLOR ? "color" :
yading@10 167 info.type == F0R_PARAM_POSITION ? "position" :
yading@10 168 info.type == F0R_PARAM_STRING ? "string" : "unknown",
yading@10 169 info.explanation);
yading@10 170
yading@10 171 #ifdef DEBUG
yading@10 172 av_log(ctx, AV_LOG_DEBUG, "value:");
yading@10 173 switch (info.type) {
yading@10 174 void *v;
yading@10 175 double d;
yading@10 176 char s[128];
yading@10 177 f0r_param_color_t col;
yading@10 178 f0r_param_position_t pos;
yading@10 179
yading@10 180 case F0R_PARAM_BOOL:
yading@10 181 v = &d;
yading@10 182 frei0r->get_param_value(frei0r->instance, v, i);
yading@10 183 av_log(ctx, AV_LOG_DEBUG, "%s", d >= 0.5 && d <= 1.0 ? "y" : "n");
yading@10 184 break;
yading@10 185 case F0R_PARAM_DOUBLE:
yading@10 186 v = &d;
yading@10 187 frei0r->get_param_value(frei0r->instance, v, i);
yading@10 188 av_log(ctx, AV_LOG_DEBUG, "%f", d);
yading@10 189 break;
yading@10 190 case F0R_PARAM_COLOR:
yading@10 191 v = &col;
yading@10 192 frei0r->get_param_value(frei0r->instance, v, i);
yading@10 193 av_log(ctx, AV_LOG_DEBUG, "%f/%f/%f", col.r, col.g, col.b);
yading@10 194 break;
yading@10 195 case F0R_PARAM_POSITION:
yading@10 196 v = &pos;
yading@10 197 frei0r->get_param_value(frei0r->instance, v, i);
yading@10 198 av_log(ctx, AV_LOG_DEBUG, "%f/%f", pos.x, pos.y);
yading@10 199 break;
yading@10 200 default: /* F0R_PARAM_STRING */
yading@10 201 v = s;
yading@10 202 frei0r->get_param_value(frei0r->instance, v, i);
yading@10 203 av_log(ctx, AV_LOG_DEBUG, "'%s'\n", s);
yading@10 204 break;
yading@10 205 }
yading@10 206 #endif
yading@10 207 av_log(ctx, AV_LOG_VERBOSE, "\n");
yading@10 208 }
yading@10 209
yading@10 210 return 0;
yading@10 211 }
yading@10 212
yading@10 213 static int load_path(AVFilterContext *ctx, void **handle_ptr, const char *prefix, const char *name)
yading@10 214 {
yading@10 215 char *path = av_asprintf("%s%s%s", prefix, name, SLIBSUF);
yading@10 216 if (!path)
yading@10 217 return AVERROR(ENOMEM);
yading@10 218 av_log(ctx, AV_LOG_DEBUG, "Looking for frei0r effect in '%s'\n", path);
yading@10 219 *handle_ptr = dlopen(path, RTLD_NOW|RTLD_LOCAL);
yading@10 220 av_free(path);
yading@10 221 return 0;
yading@10 222 }
yading@10 223
yading@10 224 static av_cold int frei0r_init(AVFilterContext *ctx,
yading@10 225 const char *dl_name, int type)
yading@10 226 {
yading@10 227 Frei0rContext *frei0r = ctx->priv;
yading@10 228 f0r_init_f f0r_init;
yading@10 229 f0r_get_plugin_info_f f0r_get_plugin_info;
yading@10 230 f0r_plugin_info_t *pi;
yading@10 231 char *path;
yading@10 232 int ret = 0;
yading@10 233
yading@10 234 if (!dl_name) {
yading@10 235 av_log(ctx, AV_LOG_ERROR, "No filter name provided.\n");
yading@10 236 return AVERROR(EINVAL);
yading@10 237 }
yading@10 238
yading@10 239 /* see: http://frei0r.dyne.org/codedoc/html/group__pluglocations.html */
yading@10 240 if ((path = av_strdup(getenv("FREI0R_PATH")))) {
yading@10 241 #ifdef _WIN32
yading@10 242 const char *separator = ";";
yading@10 243 #else
yading@10 244 const char *separator = ":";
yading@10 245 #endif
yading@10 246 char *p, *ptr = NULL;
yading@10 247 for (p = path; p = av_strtok(p, separator, &ptr); p = NULL) {
yading@10 248 /* add additional trailing slash in case it is missing */
yading@10 249 char *p1 = av_asprintf("%s/", p);
yading@10 250 if (!p1) {
yading@10 251 ret = AVERROR(ENOMEM);
yading@10 252 goto check_path_end;
yading@10 253 }
yading@10 254 ret = load_path(ctx, &frei0r->dl_handle, p1, dl_name);
yading@10 255 av_free(p1);
yading@10 256 if (ret < 0)
yading@10 257 goto check_path_end;
yading@10 258 if (frei0r->dl_handle)
yading@10 259 break;
yading@10 260 }
yading@10 261
yading@10 262 check_path_end:
yading@10 263 av_free(path);
yading@10 264 if (ret < 0)
yading@10 265 return ret;
yading@10 266 }
yading@10 267 if (!frei0r->dl_handle && (path = getenv("HOME"))) {
yading@10 268 char *prefix = av_asprintf("%s/.frei0r-1/lib/", path);
yading@10 269 if (!prefix)
yading@10 270 return AVERROR(ENOMEM);
yading@10 271 ret = load_path(ctx, &frei0r->dl_handle, prefix, dl_name);
yading@10 272 av_free(prefix);
yading@10 273 if (ret < 0)
yading@10 274 return ret;
yading@10 275 }
yading@10 276 if (!frei0r->dl_handle) {
yading@10 277 ret = load_path(ctx, &frei0r->dl_handle, "/usr/local/lib/frei0r-1/", dl_name);
yading@10 278 if (ret < 0)
yading@10 279 return ret;
yading@10 280 }
yading@10 281 if (!frei0r->dl_handle) {
yading@10 282 ret = load_path(ctx, &frei0r->dl_handle, "/usr/lib/frei0r-1/", dl_name);
yading@10 283 if (ret < 0)
yading@10 284 return ret;
yading@10 285 }
yading@10 286 if (!frei0r->dl_handle) {
yading@10 287 av_log(ctx, AV_LOG_ERROR, "Could not find module '%s'\n", dl_name);
yading@10 288 return AVERROR(EINVAL);
yading@10 289 }
yading@10 290
yading@10 291 if (!(f0r_init = load_sym(ctx, "f0r_init" )) ||
yading@10 292 !(f0r_get_plugin_info = load_sym(ctx, "f0r_get_plugin_info")) ||
yading@10 293 !(frei0r->get_param_info = load_sym(ctx, "f0r_get_param_info" )) ||
yading@10 294 !(frei0r->get_param_value = load_sym(ctx, "f0r_get_param_value")) ||
yading@10 295 !(frei0r->set_param_value = load_sym(ctx, "f0r_set_param_value")) ||
yading@10 296 !(frei0r->update = load_sym(ctx, "f0r_update" )) ||
yading@10 297 !(frei0r->construct = load_sym(ctx, "f0r_construct" )) ||
yading@10 298 !(frei0r->destruct = load_sym(ctx, "f0r_destruct" )) ||
yading@10 299 !(frei0r->deinit = load_sym(ctx, "f0r_deinit" )))
yading@10 300 return AVERROR(EINVAL);
yading@10 301
yading@10 302 if (f0r_init() < 0) {
yading@10 303 av_log(ctx, AV_LOG_ERROR, "Could not init the frei0r module\n");
yading@10 304 return AVERROR(EINVAL);
yading@10 305 }
yading@10 306
yading@10 307 f0r_get_plugin_info(&frei0r->plugin_info);
yading@10 308 pi = &frei0r->plugin_info;
yading@10 309 if (pi->plugin_type != type) {
yading@10 310 av_log(ctx, AV_LOG_ERROR,
yading@10 311 "Invalid type '%s' for the plugin\n",
yading@10 312 pi->plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" :
yading@10 313 pi->plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" :
yading@10 314 pi->plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" :
yading@10 315 pi->plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown");
yading@10 316 return AVERROR(EINVAL);
yading@10 317 }
yading@10 318
yading@10 319 av_log(ctx, AV_LOG_VERBOSE,
yading@10 320 "name:%s author:'%s' explanation:'%s' color_model:%s "
yading@10 321 "frei0r_version:%d version:%d.%d num_params:%d\n",
yading@10 322 pi->name, pi->author, pi->explanation,
yading@10 323 pi->color_model == F0R_COLOR_MODEL_BGRA8888 ? "bgra8888" :
yading@10 324 pi->color_model == F0R_COLOR_MODEL_RGBA8888 ? "rgba8888" :
yading@10 325 pi->color_model == F0R_COLOR_MODEL_PACKED32 ? "packed32" : "unknown",
yading@10 326 pi->frei0r_version, pi->major_version, pi->minor_version, pi->num_params);
yading@10 327
yading@10 328 return 0;
yading@10 329 }
yading@10 330
yading@10 331 static av_cold int filter_init(AVFilterContext *ctx)
yading@10 332 {
yading@10 333 Frei0rContext *frei0r = ctx->priv;
yading@10 334
yading@10 335 return frei0r_init(ctx, frei0r->dl_name, F0R_PLUGIN_TYPE_FILTER);
yading@10 336 }
yading@10 337
yading@10 338 static av_cold void uninit(AVFilterContext *ctx)
yading@10 339 {
yading@10 340 Frei0rContext *frei0r = ctx->priv;
yading@10 341
yading@10 342 if (frei0r->destruct && frei0r->instance)
yading@10 343 frei0r->destruct(frei0r->instance);
yading@10 344 if (frei0r->deinit)
yading@10 345 frei0r->deinit();
yading@10 346 if (frei0r->dl_handle)
yading@10 347 dlclose(frei0r->dl_handle);
yading@10 348 }
yading@10 349
yading@10 350 static int config_input_props(AVFilterLink *inlink)
yading@10 351 {
yading@10 352 AVFilterContext *ctx = inlink->dst;
yading@10 353 Frei0rContext *frei0r = ctx->priv;
yading@10 354
yading@10 355 if (!(frei0r->instance = frei0r->construct(inlink->w, inlink->h))) {
yading@10 356 av_log(ctx, AV_LOG_ERROR, "Impossible to load frei0r instance\n");
yading@10 357 return AVERROR(EINVAL);
yading@10 358 }
yading@10 359
yading@10 360 return set_params(ctx, frei0r->params);
yading@10 361 }
yading@10 362
yading@10 363 static int query_formats(AVFilterContext *ctx)
yading@10 364 {
yading@10 365 Frei0rContext *frei0r = ctx->priv;
yading@10 366 AVFilterFormats *formats = NULL;
yading@10 367
yading@10 368 if (frei0r->plugin_info.color_model == F0R_COLOR_MODEL_BGRA8888) {
yading@10 369 ff_add_format(&formats, AV_PIX_FMT_BGRA);
yading@10 370 } else if (frei0r->plugin_info.color_model == F0R_COLOR_MODEL_RGBA8888) {
yading@10 371 ff_add_format(&formats, AV_PIX_FMT_RGBA);
yading@10 372 } else { /* F0R_COLOR_MODEL_PACKED32 */
yading@10 373 static const enum AVPixelFormat pix_fmts[] = {
yading@10 374 AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, AV_PIX_FMT_NONE
yading@10 375 };
yading@10 376 formats = ff_make_format_list(pix_fmts);
yading@10 377 }
yading@10 378
yading@10 379 if (!formats)
yading@10 380 return AVERROR(ENOMEM);
yading@10 381
yading@10 382 ff_set_common_formats(ctx, formats);
yading@10 383 return 0;
yading@10 384 }
yading@10 385
yading@10 386 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
yading@10 387 {
yading@10 388 Frei0rContext *frei0r = inlink->dst->priv;
yading@10 389 AVFilterLink *outlink = inlink->dst->outputs[0];
yading@10 390 AVFrame *out;
yading@10 391
yading@10 392 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
yading@10 393 if (!out) {
yading@10 394 av_frame_free(&in);
yading@10 395 return AVERROR(ENOMEM);
yading@10 396 }
yading@10 397 av_frame_copy_props(out, in);
yading@10 398
yading@10 399 frei0r->update(frei0r->instance, in->pts * av_q2d(inlink->time_base) * 1000,
yading@10 400 (const uint32_t *)in->data[0],
yading@10 401 (uint32_t *)out->data[0]);
yading@10 402
yading@10 403 av_frame_free(&in);
yading@10 404
yading@10 405 return ff_filter_frame(outlink, out);
yading@10 406 }
yading@10 407
yading@10 408 #define OFFSET(x) offsetof(Frei0rContext, x)
yading@10 409 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
yading@10 410 static const AVOption filter_options[] = {
yading@10 411 { "filter_name", NULL, OFFSET(dl_name), AV_OPT_TYPE_STRING, .flags = FLAGS },
yading@10 412 { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = FLAGS },
yading@10 413 { NULL },
yading@10 414 };
yading@10 415
yading@10 416 static const AVClass filter_class = {
yading@10 417 .class_name = "frei0r",
yading@10 418 .item_name = av_default_item_name,
yading@10 419 .option = filter_options,
yading@10 420 .version = LIBAVUTIL_VERSION_INT,
yading@10 421 };
yading@10 422
yading@10 423 static const AVFilterPad avfilter_vf_frei0r_inputs[] = {
yading@10 424 {
yading@10 425 .name = "default",
yading@10 426 .type = AVMEDIA_TYPE_VIDEO,
yading@10 427 .config_props = config_input_props,
yading@10 428 .filter_frame = filter_frame,
yading@10 429 },
yading@10 430 { NULL }
yading@10 431 };
yading@10 432
yading@10 433 static const AVFilterPad avfilter_vf_frei0r_outputs[] = {
yading@10 434 {
yading@10 435 .name = "default",
yading@10 436 .type = AVMEDIA_TYPE_VIDEO,
yading@10 437 },
yading@10 438 { NULL }
yading@10 439 };
yading@10 440
yading@10 441 AVFilter avfilter_vf_frei0r = {
yading@10 442 .name = "frei0r",
yading@10 443 .description = NULL_IF_CONFIG_SMALL("Apply a frei0r effect."),
yading@10 444
yading@10 445 .query_formats = query_formats,
yading@10 446 .init = filter_init,
yading@10 447 .uninit = uninit,
yading@10 448
yading@10 449 .priv_size = sizeof(Frei0rContext),
yading@10 450 .priv_class = &filter_class,
yading@10 451
yading@10 452 .inputs = avfilter_vf_frei0r_inputs,
yading@10 453
yading@10 454 .outputs = avfilter_vf_frei0r_outputs,
yading@10 455 };
yading@10 456
yading@10 457 static av_cold int source_init(AVFilterContext *ctx)
yading@10 458 {
yading@10 459 Frei0rContext *frei0r = ctx->priv;
yading@10 460 AVRational frame_rate_q;
yading@10 461
yading@10 462 if (av_parse_video_size(&frei0r->w, &frei0r->h, frei0r->size) < 0) {
yading@10 463 av_log(ctx, AV_LOG_ERROR, "Invalid frame size: '%s'\n", frei0r->size);
yading@10 464 return AVERROR(EINVAL);
yading@10 465 }
yading@10 466
yading@10 467 if (av_parse_video_rate(&frame_rate_q, frei0r->framerate) < 0) {
yading@10 468 av_log(ctx, AV_LOG_ERROR, "Invalid frame rate: '%s'\n", frei0r->framerate);
yading@10 469 return AVERROR(EINVAL);
yading@10 470 }
yading@10 471 frei0r->time_base.num = frame_rate_q.den;
yading@10 472 frei0r->time_base.den = frame_rate_q.num;
yading@10 473
yading@10 474 return frei0r_init(ctx, frei0r->dl_name, F0R_PLUGIN_TYPE_SOURCE);
yading@10 475 }
yading@10 476
yading@10 477 static int source_config_props(AVFilterLink *outlink)
yading@10 478 {
yading@10 479 AVFilterContext *ctx = outlink->src;
yading@10 480 Frei0rContext *frei0r = ctx->priv;
yading@10 481
yading@10 482 if (av_image_check_size(frei0r->w, frei0r->h, 0, ctx) < 0)
yading@10 483 return AVERROR(EINVAL);
yading@10 484 outlink->w = frei0r->w;
yading@10 485 outlink->h = frei0r->h;
yading@10 486 outlink->time_base = frei0r->time_base;
yading@10 487 outlink->sample_aspect_ratio = (AVRational){1,1};
yading@10 488
yading@10 489 if (!(frei0r->instance = frei0r->construct(outlink->w, outlink->h))) {
yading@10 490 av_log(ctx, AV_LOG_ERROR, "Impossible to load frei0r instance\n");
yading@10 491 return AVERROR(EINVAL);
yading@10 492 }
yading@10 493
yading@10 494 return set_params(ctx, frei0r->params);
yading@10 495 }
yading@10 496
yading@10 497 static int source_request_frame(AVFilterLink *outlink)
yading@10 498 {
yading@10 499 Frei0rContext *frei0r = outlink->src->priv;
yading@10 500 AVFrame *frame = ff_get_video_buffer(outlink, outlink->w, outlink->h);
yading@10 501
yading@10 502 if (!frame)
yading@10 503 return AVERROR(ENOMEM);
yading@10 504
yading@10 505 frame->sample_aspect_ratio = (AVRational) {1, 1};
yading@10 506 frame->pts = frei0r->pts++;
yading@10 507
yading@10 508 frei0r->update(frei0r->instance, av_rescale_q(frame->pts, frei0r->time_base, (AVRational){1,1000}),
yading@10 509 NULL, (uint32_t *)frame->data[0]);
yading@10 510
yading@10 511 return ff_filter_frame(outlink, frame);
yading@10 512 }
yading@10 513
yading@10 514 static const AVOption src_options[] = {
yading@10 515 { "size", "Dimensions of the generated video.", OFFSET(size), AV_OPT_TYPE_STRING, { .str = "" }, .flags = FLAGS },
yading@10 516 { "framerate", NULL, OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = "25" }, .flags = FLAGS },
yading@10 517 { "filter_name", NULL, OFFSET(dl_name), AV_OPT_TYPE_STRING, .flags = FLAGS },
yading@10 518 { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = FLAGS },
yading@10 519 { NULL },
yading@10 520 };
yading@10 521
yading@10 522 static const AVClass src_class = {
yading@10 523 .class_name = "frei0r_src",
yading@10 524 .item_name = av_default_item_name,
yading@10 525 .option = src_options,
yading@10 526 .version = LIBAVUTIL_VERSION_INT,
yading@10 527 };
yading@10 528
yading@10 529 static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = {
yading@10 530 {
yading@10 531 .name = "default",
yading@10 532 .type = AVMEDIA_TYPE_VIDEO,
yading@10 533 .request_frame = source_request_frame,
yading@10 534 .config_props = source_config_props
yading@10 535 },
yading@10 536 { NULL }
yading@10 537 };
yading@10 538
yading@10 539 AVFilter avfilter_vsrc_frei0r_src = {
yading@10 540 .name = "frei0r_src",
yading@10 541 .description = NULL_IF_CONFIG_SMALL("Generate a frei0r source."),
yading@10 542
yading@10 543 .priv_size = sizeof(Frei0rContext),
yading@10 544 .priv_class = &src_class,
yading@10 545 .init = source_init,
yading@10 546 .uninit = uninit,
yading@10 547
yading@10 548 .query_formats = query_formats,
yading@10 549
yading@10 550 .inputs = NULL,
yading@10 551
yading@10 552 .outputs = avfilter_vsrc_frei0r_src_outputs,
yading@10 553 };