af_lv2.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /*
  2. * Copyright (c) 2017 Paul B Mahol
  3. * Copyright (c) 2007-2016 David Robillard <http://drobilla.net>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * LV2 wrapper
  24. */
  25. #include <lilv/lilv.h>
  26. #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
  27. #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
  28. #include "libavutil/avassert.h"
  29. #include "libavutil/avstring.h"
  30. #include "libavutil/channel_layout.h"
  31. #include "libavutil/opt.h"
  32. #include "audio.h"
  33. #include "avfilter.h"
  34. #include "internal.h"
  35. typedef struct URITable {
  36. char **uris;
  37. size_t n_uris;
  38. } URITable;
  39. typedef struct LV2Context {
  40. const AVClass *class;
  41. char *plugin_uri;
  42. char *options;
  43. unsigned nb_inputs;
  44. unsigned nb_inputcontrols;
  45. unsigned nb_outputs;
  46. int sample_rate;
  47. int nb_samples;
  48. int64_t pts;
  49. int64_t duration;
  50. LilvWorld *world;
  51. const LilvPlugin *plugin;
  52. uint32_t nb_ports;
  53. float *values;
  54. URITable uri_table;
  55. LV2_URID_Map map;
  56. LV2_Feature map_feature;
  57. LV2_URID_Unmap unmap;
  58. LV2_Feature unmap_feature;
  59. LV2_Atom_Sequence seq_in[2];
  60. LV2_Atom_Sequence *seq_out;
  61. const LV2_Feature *features[5];
  62. float *mins;
  63. float *maxes;
  64. float *controls;
  65. LilvInstance *instance;
  66. LilvNode *atom_AtomPort;
  67. LilvNode *atom_Sequence;
  68. LilvNode *lv2_AudioPort;
  69. LilvNode *lv2_CVPort;
  70. LilvNode *lv2_ControlPort;
  71. LilvNode *lv2_Optional;
  72. LilvNode *lv2_InputPort;
  73. LilvNode *lv2_OutputPort;
  74. LilvNode *urid_map;
  75. LilvNode *powerOf2BlockLength;
  76. LilvNode *fixedBlockLength;
  77. LilvNode *boundedBlockLength;
  78. } LV2Context;
  79. #define OFFSET(x) offsetof(LV2Context, x)
  80. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
  81. static const AVOption lv2_options[] = {
  82. { "plugin", "set plugin uri", OFFSET(plugin_uri), AV_OPT_TYPE_STRING, .flags = FLAGS },
  83. { "p", "set plugin uri", OFFSET(plugin_uri), AV_OPT_TYPE_STRING, .flags = FLAGS },
  84. { "controls", "set plugin options", OFFSET(options), AV_OPT_TYPE_STRING, .flags = FLAGS },
  85. { "c", "set plugin options", OFFSET(options), AV_OPT_TYPE_STRING, .flags = FLAGS },
  86. { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT32_MAX, FLAGS },
  87. { "s", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT32_MAX, FLAGS },
  88. { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS },
  89. { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS },
  90. { "duration", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },
  91. { "d", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },
  92. { NULL }
  93. };
  94. AVFILTER_DEFINE_CLASS(lv2);
  95. static void uri_table_init(URITable *table)
  96. {
  97. table->uris = NULL;
  98. table->n_uris = 0;
  99. }
  100. static void uri_table_destroy(URITable *table)
  101. {
  102. int i;
  103. for (i = 0; i < table->n_uris; i++) {
  104. av_freep(&table->uris[i]);
  105. }
  106. av_freep(&table->uris);
  107. }
  108. static LV2_URID uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
  109. {
  110. URITable *table = (URITable*)handle;
  111. const size_t len = strlen(uri);
  112. size_t i;
  113. char **tmp;
  114. for (i = 0; i < table->n_uris; i++) {
  115. if (!strcmp(table->uris[i], uri)) {
  116. return i + 1;
  117. }
  118. }
  119. tmp = av_calloc(table->n_uris + 1, sizeof(char*));
  120. if (!tmp)
  121. return table->n_uris;
  122. memcpy(tmp, table->uris, table->n_uris * sizeof(char**));
  123. av_free(table->uris);
  124. table->uris = tmp;
  125. table->uris[table->n_uris] = av_malloc(len + 1);
  126. if (!table->uris[table->n_uris])
  127. return table->n_uris;
  128. memcpy(table->uris[table->n_uris], uri, len + 1);
  129. table->n_uris++;
  130. return table->n_uris;
  131. }
  132. static const char *uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  133. {
  134. URITable *table = (URITable*)handle;
  135. if (urid > 0 && urid <= table->n_uris) {
  136. return table->uris[urid - 1];
  137. }
  138. return NULL;
  139. }
  140. static void connect_ports(LV2Context *s, AVFrame *in, AVFrame *out)
  141. {
  142. int ich = 0, och = 0, i;
  143. for (i = 0; i < s->nb_ports; i++) {
  144. const LilvPort *port = lilv_plugin_get_port_by_index(s->plugin, i);
  145. if (lilv_port_is_a(s->plugin, port, s->lv2_AudioPort) ||
  146. lilv_port_is_a(s->plugin, port, s->lv2_CVPort)) {
  147. if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort)) {
  148. lilv_instance_connect_port(s->instance, i, in->extended_data[ich++]);
  149. } else if (lilv_port_is_a(s->plugin, port, s->lv2_OutputPort)) {
  150. lilv_instance_connect_port(s->instance, i, out->extended_data[och++]);
  151. } else {
  152. av_log(s, AV_LOG_WARNING, "port %d neither input nor output, skipping\n", i);
  153. }
  154. } else if (lilv_port_is_a(s->plugin, port, s->atom_AtomPort)) {
  155. if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort)) {
  156. lilv_instance_connect_port(s->instance, i, &s->seq_in);
  157. } else {
  158. lilv_instance_connect_port(s->instance, i, s->seq_out);
  159. }
  160. } else if (lilv_port_is_a(s->plugin, port, s->lv2_ControlPort)) {
  161. lilv_instance_connect_port(s->instance, i, &s->controls[i]);
  162. }
  163. }
  164. s->seq_in[0].atom.size = sizeof(LV2_Atom_Sequence_Body);
  165. s->seq_in[0].atom.type = uri_table_map(&s->uri_table, LV2_ATOM__Sequence);
  166. s->seq_out->atom.size = 9624;
  167. s->seq_out->atom.type = uri_table_map(&s->uri_table, LV2_ATOM__Chunk);
  168. }
  169. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  170. {
  171. AVFilterContext *ctx = inlink->dst;
  172. LV2Context *s = ctx->priv;
  173. AVFrame *out;
  174. if (!s->nb_outputs ||
  175. (av_frame_is_writable(in) && s->nb_inputs == s->nb_outputs)) {
  176. out = in;
  177. } else {
  178. out = ff_get_audio_buffer(ctx->outputs[0], in->nb_samples);
  179. if (!out) {
  180. av_frame_free(&in);
  181. return AVERROR(ENOMEM);
  182. }
  183. av_frame_copy_props(out, in);
  184. }
  185. connect_ports(s, in, out);
  186. lilv_instance_run(s->instance, in->nb_samples);
  187. if (out != in)
  188. av_frame_free(&in);
  189. return ff_filter_frame(ctx->outputs[0], out);
  190. }
  191. static int request_frame(AVFilterLink *outlink)
  192. {
  193. AVFilterContext *ctx = outlink->src;
  194. LV2Context *s = ctx->priv;
  195. AVFrame *out;
  196. int64_t t;
  197. if (ctx->nb_inputs)
  198. return ff_request_frame(ctx->inputs[0]);
  199. t = av_rescale(s->pts, AV_TIME_BASE, s->sample_rate);
  200. if (s->duration >= 0 && t >= s->duration)
  201. return AVERROR_EOF;
  202. out = ff_get_audio_buffer(outlink, s->nb_samples);
  203. if (!out)
  204. return AVERROR(ENOMEM);
  205. connect_ports(s, out, out);
  206. lilv_instance_run(s->instance, out->nb_samples);
  207. out->sample_rate = s->sample_rate;
  208. out->pts = s->pts;
  209. s->pts += s->nb_samples;
  210. return ff_filter_frame(outlink, out);
  211. }
  212. static const LV2_Feature buf_size_features[3] = {
  213. { LV2_BUF_SIZE__powerOf2BlockLength, NULL },
  214. { LV2_BUF_SIZE__fixedBlockLength, NULL },
  215. { LV2_BUF_SIZE__boundedBlockLength, NULL },
  216. };
  217. static int config_output(AVFilterLink *outlink)
  218. {
  219. AVFilterContext *ctx = outlink->src;
  220. LV2Context *s = ctx->priv;
  221. char *p, *arg, *saveptr = NULL;
  222. int i, sample_rate;
  223. uri_table_init(&s->uri_table);
  224. s->map.handle = &s->uri_table;
  225. s->map.map = uri_table_map;
  226. s->map_feature.URI = LV2_URID_MAP_URI;
  227. s->map_feature.data = &s->map;
  228. s->unmap.handle = &s->uri_table;
  229. s->unmap.unmap = uri_table_unmap;
  230. s->unmap_feature.URI = LV2_URID_UNMAP_URI;
  231. s->unmap_feature.data = &s->unmap;
  232. s->features[0] = &s->map_feature;
  233. s->features[1] = &s->unmap_feature;
  234. s->features[2] = &buf_size_features[0];
  235. s->features[3] = &buf_size_features[1];
  236. s->features[4] = &buf_size_features[2];
  237. if (ctx->nb_inputs) {
  238. AVFilterLink *inlink = ctx->inputs[0];
  239. outlink->format = inlink->format;
  240. outlink->sample_rate = sample_rate = inlink->sample_rate;
  241. if (s->nb_inputs == s->nb_outputs) {
  242. outlink->channel_layout = inlink->channel_layout;
  243. outlink->channels = inlink->channels;
  244. }
  245. } else {
  246. outlink->sample_rate = sample_rate = s->sample_rate;
  247. outlink->time_base = (AVRational){1, s->sample_rate};
  248. }
  249. s->instance = lilv_plugin_instantiate(s->plugin, sample_rate, s->features);
  250. if (!s->instance) {
  251. av_log(s, AV_LOG_ERROR, "Failed to instantiate <%s>\n", lilv_node_as_uri(lilv_plugin_get_uri(s->plugin)));
  252. return AVERROR(EINVAL);
  253. }
  254. s->mins = av_calloc(s->nb_ports, sizeof(float));
  255. s->maxes = av_calloc(s->nb_ports, sizeof(float));
  256. s->controls = av_calloc(s->nb_ports, sizeof(float));
  257. if (!s->mins || !s->maxes || !s->controls)
  258. return AVERROR(ENOMEM);
  259. lilv_plugin_get_port_ranges_float(s->plugin, s->mins, s->maxes, s->controls);
  260. s->seq_out = av_malloc(sizeof(LV2_Atom_Sequence) + 9624);
  261. if (!s->seq_out)
  262. return AVERROR(ENOMEM);
  263. if (s->options && !strcmp(s->options, "help")) {
  264. if (!s->nb_inputcontrols) {
  265. av_log(ctx, AV_LOG_INFO,
  266. "The '%s' plugin does not have any input controls.\n",
  267. s->plugin_uri);
  268. } else {
  269. av_log(ctx, AV_LOG_INFO,
  270. "The '%s' plugin has the following input controls:\n",
  271. s->plugin_uri);
  272. for (i = 0; i < s->nb_ports; i++) {
  273. const LilvPort *port = lilv_plugin_get_port_by_index(s->plugin, i);
  274. const LilvNode *symbol = lilv_port_get_symbol(s->plugin, port);
  275. LilvNode *name = lilv_port_get_name(s->plugin, port);
  276. if (lilv_port_is_a(s->plugin, port, s->lv2_InputPort) &&
  277. lilv_port_is_a(s->plugin, port, s->lv2_ControlPort)) {
  278. av_log(ctx, AV_LOG_INFO, "%s\t\t<float> (from %f to %f) (default %f)\t\t%s\n",
  279. lilv_node_as_string(symbol), s->mins[i], s->maxes[i], s->controls[i],
  280. lilv_node_as_string(name));
  281. }
  282. lilv_node_free(name);
  283. }
  284. }
  285. return AVERROR_EXIT;
  286. }
  287. p = s->options;
  288. while (s->options) {
  289. const LilvPort *port;
  290. LilvNode *sym;
  291. float val;
  292. char *str, *vstr;
  293. int index;
  294. if (!(arg = av_strtok(p, " |", &saveptr)))
  295. break;
  296. p = NULL;
  297. vstr = strstr(arg, "=");
  298. if (vstr == NULL) {
  299. av_log(ctx, AV_LOG_ERROR, "Invalid syntax.\n");
  300. return AVERROR(EINVAL);
  301. }
  302. vstr[0] = 0;
  303. str = arg;
  304. val = atof(vstr+1);
  305. sym = lilv_new_string(s->world, str);
  306. port = lilv_plugin_get_port_by_symbol(s->plugin, sym);
  307. lilv_node_free(sym);
  308. if (!port) {
  309. av_log(s, AV_LOG_WARNING, "Unknown option: <%s>\n", str);
  310. } else {
  311. index = lilv_port_get_index(s->plugin, port);
  312. s->controls[index] = val;
  313. }
  314. }
  315. if (s->nb_inputs &&
  316. (lilv_plugin_has_feature(s->plugin, s->powerOf2BlockLength) ||
  317. lilv_plugin_has_feature(s->plugin, s->fixedBlockLength) ||
  318. lilv_plugin_has_feature(s->plugin, s->boundedBlockLength))) {
  319. AVFilterLink *inlink = ctx->inputs[0];
  320. inlink->partial_buf_size = inlink->min_samples = inlink->max_samples = 4096;
  321. }
  322. return 0;
  323. }
  324. static av_cold int init(AVFilterContext *ctx)
  325. {
  326. LV2Context *s = ctx->priv;
  327. const LilvPlugins *plugins;
  328. const LilvPlugin *plugin;
  329. AVFilterPad pad = { NULL };
  330. LilvNode *uri;
  331. int i;
  332. s->world = lilv_world_new();
  333. if (!s->world)
  334. return AVERROR(ENOMEM);
  335. uri = lilv_new_uri(s->world, s->plugin_uri);
  336. if (!uri) {
  337. av_log(s, AV_LOG_ERROR, "Invalid plugin URI <%s>\n", s->plugin_uri);
  338. return AVERROR(EINVAL);
  339. }
  340. lilv_world_load_all(s->world);
  341. plugins = lilv_world_get_all_plugins(s->world);
  342. plugin = lilv_plugins_get_by_uri(plugins, uri);
  343. lilv_node_free(uri);
  344. if (!plugin) {
  345. av_log(s, AV_LOG_ERROR, "Plugin <%s> not found\n", s->plugin_uri);
  346. return AVERROR(EINVAL);
  347. }
  348. s->plugin = plugin;
  349. s->nb_ports = lilv_plugin_get_num_ports(s->plugin);
  350. s->lv2_InputPort = lilv_new_uri(s->world, LV2_CORE__InputPort);
  351. s->lv2_OutputPort = lilv_new_uri(s->world, LV2_CORE__OutputPort);
  352. s->lv2_AudioPort = lilv_new_uri(s->world, LV2_CORE__AudioPort);
  353. s->lv2_ControlPort = lilv_new_uri(s->world, LV2_CORE__ControlPort);
  354. s->lv2_Optional = lilv_new_uri(s->world, LV2_CORE__connectionOptional);
  355. s->atom_AtomPort = lilv_new_uri(s->world, LV2_ATOM__AtomPort);
  356. s->atom_Sequence = lilv_new_uri(s->world, LV2_ATOM__Sequence);
  357. s->urid_map = lilv_new_uri(s->world, LV2_URID__map);
  358. s->powerOf2BlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__powerOf2BlockLength);
  359. s->fixedBlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__fixedBlockLength);
  360. s->boundedBlockLength = lilv_new_uri(s->world, LV2_BUF_SIZE__boundedBlockLength);
  361. for (i = 0; i < s->nb_ports; i++) {
  362. const LilvPort *lport = lilv_plugin_get_port_by_index(s->plugin, i);
  363. int is_input = 0;
  364. int is_optional = 0;
  365. is_optional = lilv_port_has_property(s->plugin, lport, s->lv2_Optional);
  366. if (lilv_port_is_a(s->plugin, lport, s->lv2_InputPort)) {
  367. is_input = 1;
  368. } else if (!lilv_port_is_a(s->plugin, lport, s->lv2_OutputPort) && !is_optional) {
  369. return AVERROR(EINVAL);
  370. }
  371. if (lilv_port_is_a(s->plugin, lport, s->lv2_ControlPort)) {
  372. if (is_input) {
  373. s->nb_inputcontrols++;
  374. }
  375. } else if (lilv_port_is_a(s->plugin, lport, s->lv2_AudioPort)) {
  376. if (is_input) {
  377. s->nb_inputs++;
  378. } else {
  379. s->nb_outputs++;
  380. }
  381. }
  382. }
  383. pad.type = AVMEDIA_TYPE_AUDIO;
  384. if (s->nb_inputs) {
  385. pad.name = av_asprintf("in0:%s:%u", s->plugin_uri, s->nb_inputs);
  386. if (!pad.name)
  387. return AVERROR(ENOMEM);
  388. pad.filter_frame = filter_frame;
  389. if (ff_insert_inpad(ctx, ctx->nb_inputs, &pad) < 0) {
  390. av_freep(&pad.name);
  391. return AVERROR(ENOMEM);
  392. }
  393. }
  394. return 0;
  395. }
  396. static int query_formats(AVFilterContext *ctx)
  397. {
  398. LV2Context *s = ctx->priv;
  399. AVFilterFormats *formats;
  400. AVFilterChannelLayouts *layouts;
  401. AVFilterLink *outlink = ctx->outputs[0];
  402. static const enum AVSampleFormat sample_fmts[] = {
  403. AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE };
  404. int ret;
  405. formats = ff_make_format_list(sample_fmts);
  406. if (!formats)
  407. return AVERROR(ENOMEM);
  408. ret = ff_set_common_formats(ctx, formats);
  409. if (ret < 0)
  410. return ret;
  411. if (s->nb_inputs) {
  412. formats = ff_all_samplerates();
  413. if (!formats)
  414. return AVERROR(ENOMEM);
  415. ret = ff_set_common_samplerates(ctx, formats);
  416. if (ret < 0)
  417. return ret;
  418. } else {
  419. int sample_rates[] = { s->sample_rate, -1 };
  420. ret = ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates));
  421. if (ret < 0)
  422. return ret;
  423. }
  424. if (s->nb_inputs == 2 && s->nb_outputs == 2) {
  425. layouts = NULL;
  426. ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO);
  427. if (ret < 0)
  428. return ret;
  429. ret = ff_set_common_channel_layouts(ctx, layouts);
  430. if (ret < 0)
  431. return ret;
  432. } else {
  433. if (s->nb_inputs >= 1) {
  434. AVFilterLink *inlink = ctx->inputs[0];
  435. uint64_t inlayout = FF_COUNT2LAYOUT(s->nb_inputs);
  436. layouts = NULL;
  437. ret = ff_add_channel_layout(&layouts, inlayout);
  438. if (ret < 0)
  439. return ret;
  440. ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
  441. if (ret < 0)
  442. return ret;
  443. if (!s->nb_outputs) {
  444. ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
  445. if (ret < 0)
  446. return ret;
  447. }
  448. }
  449. if (s->nb_outputs >= 1) {
  450. uint64_t outlayout = FF_COUNT2LAYOUT(s->nb_outputs);
  451. layouts = NULL;
  452. ret = ff_add_channel_layout(&layouts, outlayout);
  453. if (ret < 0)
  454. return ret;
  455. ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
  456. if (ret < 0)
  457. return ret;
  458. }
  459. }
  460. return 0;
  461. }
  462. static av_cold void uninit(AVFilterContext *ctx)
  463. {
  464. LV2Context *s = ctx->priv;
  465. lilv_node_free(s->powerOf2BlockLength);
  466. lilv_node_free(s->fixedBlockLength);
  467. lilv_node_free(s->boundedBlockLength);
  468. lilv_node_free(s->urid_map);
  469. lilv_node_free(s->atom_Sequence);
  470. lilv_node_free(s->atom_AtomPort);
  471. lilv_node_free(s->lv2_Optional);
  472. lilv_node_free(s->lv2_ControlPort);
  473. lilv_node_free(s->lv2_AudioPort);
  474. lilv_node_free(s->lv2_OutputPort);
  475. lilv_node_free(s->lv2_InputPort);
  476. uri_table_destroy(&s->uri_table);
  477. lilv_instance_free(s->instance);
  478. lilv_world_free(s->world);
  479. av_freep(&s->mins);
  480. av_freep(&s->maxes);
  481. av_freep(&s->controls);
  482. av_freep(&s->seq_out);
  483. if (ctx->nb_inputs)
  484. av_freep(&ctx->input_pads[0].name);
  485. }
  486. static const AVFilterPad lv2_outputs[] = {
  487. {
  488. .name = "default",
  489. .type = AVMEDIA_TYPE_AUDIO,
  490. .config_props = config_output,
  491. .request_frame = request_frame,
  492. },
  493. { NULL }
  494. };
  495. AVFilter ff_af_lv2 = {
  496. .name = "lv2",
  497. .description = NULL_IF_CONFIG_SMALL("Apply LV2 effect."),
  498. .priv_size = sizeof(LV2Context),
  499. .priv_class = &lv2_class,
  500. .init = init,
  501. .uninit = uninit,
  502. .query_formats = query_formats,
  503. .inputs = 0,
  504. .outputs = lv2_outputs,
  505. .flags = AVFILTER_FLAG_DYNAMIC_INPUTS,
  506. };