2 * Copyright (c) 2017 Paul B Mahol
3 * Copyright (c) 2007-2016 David Robillard <http://drobilla.net>
5 * This file is part of FFmpeg.
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.
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.
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
27 #include <lilv/lilv.h>
28 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
29 #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
31 #include "libavutil/avstring.h"
32 #include "libavutil/channel_layout.h"
33 #include "libavutil/mem.h"
34 #include "libavutil/opt.h"
40 typedef struct URITable
{
45 typedef struct LV2Context
{
51 unsigned nb_inputcontrols
;
60 const LilvPlugin
*plugin
;
65 LV2_Feature map_feature
;
67 LV2_Feature unmap_feature
;
68 LV2_Atom_Sequence seq_in
[2];
69 LV2_Atom_Sequence
*seq_out
;
70 const LV2_Feature
*features
[5];
76 LilvInstance
*instance
;
78 LilvNode
*atom_AtomPort
;
79 LilvNode
*atom_Sequence
;
80 LilvNode
*lv2_AudioPort
;
82 LilvNode
*lv2_ControlPort
;
83 LilvNode
*lv2_Optional
;
84 LilvNode
*lv2_InputPort
;
85 LilvNode
*lv2_OutputPort
;
87 LilvNode
*powerOf2BlockLength
;
88 LilvNode
*fixedBlockLength
;
89 LilvNode
*boundedBlockLength
;
92 #define OFFSET(x) offsetof(LV2Context, x)
93 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
95 static const AVOption lv2_options
[] = {
96 { "plugin", "set plugin uri", OFFSET(plugin_uri
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
97 { "p", "set plugin uri", OFFSET(plugin_uri
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
98 { "controls", "set plugin options", OFFSET(options
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
99 { "c", "set plugin options", OFFSET(options
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
100 { "sample_rate", "set sample rate", OFFSET(sample_rate
), AV_OPT_TYPE_INT
, {.i64
=44100}, 1, INT32_MAX
, FLAGS
},
101 { "s", "set sample rate", OFFSET(sample_rate
), AV_OPT_TYPE_INT
, {.i64
=44100}, 1, INT32_MAX
, FLAGS
},
102 { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples
), AV_OPT_TYPE_INT
, {.i64
=1024}, 1, INT_MAX
, FLAGS
},
103 { "n", "set the number of samples per requested frame", OFFSET(nb_samples
), AV_OPT_TYPE_INT
, {.i64
=1024}, 1, INT_MAX
, FLAGS
},
104 { "duration", "set audio duration", OFFSET(duration
), AV_OPT_TYPE_DURATION
, {.i64
=-1}, -1, INT64_MAX
, FLAGS
},
105 { "d", "set audio duration", OFFSET(duration
), AV_OPT_TYPE_DURATION
, {.i64
=-1}, -1, INT64_MAX
, FLAGS
},
109 AVFILTER_DEFINE_CLASS(lv2
);
111 static void uri_table_init(URITable
*table
)
117 static void uri_table_destroy(URITable
*table
)
121 for (i
= 0; i
< table
->n_uris
; i
++) {
122 av_freep(&table
->uris
[i
]);
125 av_freep(&table
->uris
);
128 static LV2_URID
uri_table_map(LV2_URID_Map_Handle handle
, const char *uri
)
130 URITable
*table
= (URITable
*)handle
;
131 const size_t len
= strlen(uri
);
135 for (i
= 0; i
< table
->n_uris
; i
++) {
136 if (!strcmp(table
->uris
[i
], uri
)) {
141 tmp
= av_calloc(table
->n_uris
+ 1, sizeof(char*));
143 return table
->n_uris
;
144 memcpy(tmp
, table
->uris
, table
->n_uris
* sizeof(char**));
146 av_free(table
->uris
);
148 table
->uris
[table
->n_uris
] = av_malloc(len
+ 1);
149 if (!table
->uris
[table
->n_uris
])
150 return table
->n_uris
;
152 memcpy(table
->uris
[table
->n_uris
], uri
, len
+ 1);
155 return table
->n_uris
;
158 static const char *uri_table_unmap(LV2_URID_Map_Handle handle
, LV2_URID urid
)
160 URITable
*table
= (URITable
*)handle
;
162 if (urid
> 0 && urid
<= table
->n_uris
) {
163 return table
->uris
[urid
- 1];
169 static void connect_ports(LV2Context
*s
, AVFrame
*in
, AVFrame
*out
)
171 int ich
= 0, och
= 0, i
;
173 for (i
= 0; i
< s
->nb_ports
; i
++) {
174 const LilvPort
*port
= lilv_plugin_get_port_by_index(s
->plugin
, i
);
176 if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_AudioPort
) ||
177 lilv_port_is_a(s
->plugin
, port
, s
->lv2_CVPort
)) {
178 if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_InputPort
)) {
179 lilv_instance_connect_port(s
->instance
, i
, in
->extended_data
[ich
++]);
180 } else if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_OutputPort
)) {
181 lilv_instance_connect_port(s
->instance
, i
, out
->extended_data
[och
++]);
183 av_log(s
, AV_LOG_WARNING
, "port %d neither input nor output, skipping\n", i
);
185 } else if (lilv_port_is_a(s
->plugin
, port
, s
->atom_AtomPort
)) {
186 if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_InputPort
)) {
187 lilv_instance_connect_port(s
->instance
, i
, &s
->seq_in
);
189 lilv_instance_connect_port(s
->instance
, i
, s
->seq_out
);
191 } else if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_ControlPort
)) {
192 lilv_instance_connect_port(s
->instance
, i
, &s
->controls
[i
]);
196 s
->seq_in
[0].atom
.size
= sizeof(LV2_Atom_Sequence_Body
);
197 s
->seq_in
[0].atom
.type
= uri_table_map(&s
->uri_table
, LV2_ATOM__Sequence
);
198 s
->seq_out
->atom
.size
= 9624;
199 s
->seq_out
->atom
.type
= uri_table_map(&s
->uri_table
, LV2_ATOM__Chunk
);
202 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*in
)
204 AVFilterContext
*ctx
= inlink
->dst
;
205 LV2Context
*s
= ctx
->priv
;
208 if (!s
->nb_outputs
||
209 (av_frame_is_writable(in
) && s
->nb_inputs
== s
->nb_outputs
)) {
212 out
= ff_get_audio_buffer(ctx
->outputs
[0], in
->nb_samples
);
215 return AVERROR(ENOMEM
);
217 av_frame_copy_props(out
, in
);
220 connect_ports(s
, in
, out
);
222 lilv_instance_run(s
->instance
, in
->nb_samples
);
227 return ff_filter_frame(ctx
->outputs
[0], out
);
230 static int request_frame(AVFilterLink
*outlink
)
232 AVFilterContext
*ctx
= outlink
->src
;
233 LV2Context
*s
= ctx
->priv
;
238 return ff_request_frame(ctx
->inputs
[0]);
240 t
= av_rescale(s
->pts
, AV_TIME_BASE
, s
->sample_rate
);
241 if (s
->duration
>= 0 && t
>= s
->duration
)
244 out
= ff_get_audio_buffer(outlink
, s
->nb_samples
);
246 return AVERROR(ENOMEM
);
248 connect_ports(s
, out
, out
);
250 lilv_instance_run(s
->instance
, out
->nb_samples
);
252 out
->sample_rate
= s
->sample_rate
;
254 s
->pts
+= s
->nb_samples
;
256 return ff_filter_frame(outlink
, out
);
259 static const LV2_Feature buf_size_features
[3] = {
260 { LV2_BUF_SIZE__powerOf2BlockLength
, NULL
},
261 { LV2_BUF_SIZE__fixedBlockLength
, NULL
},
262 { LV2_BUF_SIZE__boundedBlockLength
, NULL
},
265 static int config_output(AVFilterLink
*outlink
)
267 AVFilterContext
*ctx
= outlink
->src
;
268 LV2Context
*s
= ctx
->priv
;
269 char *p
, *arg
, *saveptr
= NULL
;
272 uri_table_init(&s
->uri_table
);
273 s
->map
.handle
= &s
->uri_table
;
274 s
->map
.map
= uri_table_map
;
275 s
->map_feature
.URI
= LV2_URID_MAP_URI
;
276 s
->map_feature
.data
= &s
->map
;
277 s
->unmap
.handle
= &s
->uri_table
;
278 s
->unmap
.unmap
= uri_table_unmap
;
279 s
->unmap_feature
.URI
= LV2_URID_UNMAP_URI
;
280 s
->unmap_feature
.data
= &s
->unmap
;
281 s
->features
[0] = &s
->map_feature
;
282 s
->features
[1] = &s
->unmap_feature
;
283 s
->features
[2] = &buf_size_features
[0];
284 s
->features
[3] = &buf_size_features
[1];
285 s
->features
[4] = &buf_size_features
[2];
287 if (ctx
->nb_inputs
) {
288 AVFilterLink
*inlink
= ctx
->inputs
[0];
290 outlink
->format
= inlink
->format
;
291 outlink
->sample_rate
= sample_rate
= inlink
->sample_rate
;
292 if (s
->nb_inputs
== s
->nb_outputs
) {
294 if ((ret
= av_channel_layout_copy(&outlink
->ch_layout
, &inlink
->ch_layout
)) < 0)
299 outlink
->sample_rate
= sample_rate
= s
->sample_rate
;
300 outlink
->time_base
= (AVRational
){1, s
->sample_rate
};
303 s
->instance
= lilv_plugin_instantiate(s
->plugin
, sample_rate
, s
->features
);
305 av_log(s
, AV_LOG_ERROR
, "Failed to instantiate <%s>\n", lilv_node_as_uri(lilv_plugin_get_uri(s
->plugin
)));
306 return AVERROR(EINVAL
);
309 s
->mins
= av_calloc(s
->nb_ports
, sizeof(float));
310 s
->maxes
= av_calloc(s
->nb_ports
, sizeof(float));
311 s
->controls
= av_calloc(s
->nb_ports
, sizeof(float));
313 if (!s
->mins
|| !s
->maxes
|| !s
->controls
)
314 return AVERROR(ENOMEM
);
316 lilv_plugin_get_port_ranges_float(s
->plugin
, s
->mins
, s
->maxes
, s
->controls
);
317 s
->seq_out
= av_malloc(sizeof(LV2_Atom_Sequence
) + 9624);
319 return AVERROR(ENOMEM
);
321 if (s
->options
&& !strcmp(s
->options
, "help")) {
322 if (!s
->nb_inputcontrols
) {
323 av_log(ctx
, AV_LOG_INFO
,
324 "The '%s' plugin does not have any input controls.\n",
327 av_log(ctx
, AV_LOG_INFO
,
328 "The '%s' plugin has the following input controls:\n",
330 for (i
= 0; i
< s
->nb_ports
; i
++) {
331 const LilvPort
*port
= lilv_plugin_get_port_by_index(s
->plugin
, i
);
332 const LilvNode
*symbol
= lilv_port_get_symbol(s
->plugin
, port
);
333 LilvNode
*name
= lilv_port_get_name(s
->plugin
, port
);
335 if (lilv_port_is_a(s
->plugin
, port
, s
->lv2_InputPort
) &&
336 lilv_port_is_a(s
->plugin
, port
, s
->lv2_ControlPort
)) {
337 av_log(ctx
, AV_LOG_INFO
, "%s\t\t<float> (from %f to %f) (default %f)\t\t%s\n",
338 lilv_node_as_string(symbol
), s
->mins
[i
], s
->maxes
[i
], s
->controls
[i
],
339 lilv_node_as_string(name
));
342 lilv_node_free(name
);
350 const LilvPort
*port
;
356 if (!(arg
= av_strtok(p
, " |", &saveptr
)))
360 vstr
= strstr(arg
, "=");
362 av_log(ctx
, AV_LOG_ERROR
, "Invalid syntax.\n");
363 return AVERROR(EINVAL
);
369 sym
= lilv_new_string(s
->world
, str
);
370 port
= lilv_plugin_get_port_by_symbol(s
->plugin
, sym
);
373 av_log(s
, AV_LOG_WARNING
, "Unknown option: <%s>\n", str
);
375 index
= lilv_port_get_index(s
->plugin
, port
);
376 s
->controls
[index
] = val
;
381 (lilv_plugin_has_feature(s
->plugin
, s
->powerOf2BlockLength
) ||
382 lilv_plugin_has_feature(s
->plugin
, s
->fixedBlockLength
) ||
383 lilv_plugin_has_feature(s
->plugin
, s
->boundedBlockLength
))) {
384 FilterLink
*inlink
= ff_filter_link(ctx
->inputs
[0]);
386 inlink
->min_samples
= inlink
->max_samples
= 4096;
392 static av_cold
int init(AVFilterContext
*ctx
)
394 LV2Context
*s
= ctx
->priv
;
395 const LilvPlugins
*plugins
;
396 const LilvPlugin
*plugin
;
397 AVFilterPad pad
= { NULL
};
401 s
->world
= lilv_world_new();
403 return AVERROR(ENOMEM
);
405 uri
= lilv_new_uri(s
->world
, s
->plugin_uri
);
407 av_log(s
, AV_LOG_ERROR
, "Invalid plugin URI <%s>\n", s
->plugin_uri
);
408 return AVERROR(EINVAL
);
411 lilv_world_load_all(s
->world
);
412 plugins
= lilv_world_get_all_plugins(s
->world
);
413 plugin
= lilv_plugins_get_by_uri(plugins
, uri
);
417 av_log(s
, AV_LOG_ERROR
, "Plugin <%s> not found\n", s
->plugin_uri
);
418 return AVERROR(EINVAL
);
422 s
->nb_ports
= lilv_plugin_get_num_ports(s
->plugin
);
424 s
->lv2_InputPort
= lilv_new_uri(s
->world
, LV2_CORE__InputPort
);
425 s
->lv2_OutputPort
= lilv_new_uri(s
->world
, LV2_CORE__OutputPort
);
426 s
->lv2_AudioPort
= lilv_new_uri(s
->world
, LV2_CORE__AudioPort
);
427 s
->lv2_ControlPort
= lilv_new_uri(s
->world
, LV2_CORE__ControlPort
);
428 s
->lv2_Optional
= lilv_new_uri(s
->world
, LV2_CORE__connectionOptional
);
429 s
->atom_AtomPort
= lilv_new_uri(s
->world
, LV2_ATOM__AtomPort
);
430 s
->atom_Sequence
= lilv_new_uri(s
->world
, LV2_ATOM__Sequence
);
431 s
->urid_map
= lilv_new_uri(s
->world
, LV2_URID__map
);
432 s
->powerOf2BlockLength
= lilv_new_uri(s
->world
, LV2_BUF_SIZE__powerOf2BlockLength
);
433 s
->fixedBlockLength
= lilv_new_uri(s
->world
, LV2_BUF_SIZE__fixedBlockLength
);
434 s
->boundedBlockLength
= lilv_new_uri(s
->world
, LV2_BUF_SIZE__boundedBlockLength
);
436 for (i
= 0; i
< s
->nb_ports
; i
++) {
437 const LilvPort
*lport
= lilv_plugin_get_port_by_index(s
->plugin
, i
);
441 is_optional
= lilv_port_has_property(s
->plugin
, lport
, s
->lv2_Optional
);
443 if (lilv_port_is_a(s
->plugin
, lport
, s
->lv2_InputPort
)) {
445 } else if (!lilv_port_is_a(s
->plugin
, lport
, s
->lv2_OutputPort
) && !is_optional
) {
446 return AVERROR(EINVAL
);
449 if (lilv_port_is_a(s
->plugin
, lport
, s
->lv2_ControlPort
)) {
451 s
->nb_inputcontrols
++;
453 } else if (lilv_port_is_a(s
->plugin
, lport
, s
->lv2_AudioPort
)) {
462 pad
.type
= AVMEDIA_TYPE_AUDIO
;
465 pad
.name
= av_asprintf("in0:%s:%u", s
->plugin_uri
, s
->nb_inputs
);
467 return AVERROR(ENOMEM
);
469 pad
.filter_frame
= filter_frame
;
470 if ((ret
= ff_append_inpad_free_name(ctx
, &pad
)) < 0)
477 static int query_formats(const AVFilterContext
*ctx
,
478 AVFilterFormatsConfig
**cfg_in
,
479 AVFilterFormatsConfig
**cfg_out
)
481 const LV2Context
*s
= ctx
->priv
;
482 AVFilterChannelLayouts
*layouts
;
483 static const enum AVSampleFormat sample_fmts
[] = {
484 AV_SAMPLE_FMT_FLTP
, AV_SAMPLE_FMT_NONE
};
485 int ret
= ff_set_common_formats_from_list2(ctx
, cfg_in
, cfg_out
, sample_fmts
);
490 int sample_rates
[] = { s
->sample_rate
, -1 };
492 ret
= ff_set_common_samplerates_from_list2(ctx
, cfg_in
, cfg_out
, sample_rates
);
497 if (s
->nb_inputs
== 2 && s
->nb_outputs
== 2) {
499 ret
= ff_add_channel_layout(&layouts
, &(AVChannelLayout
)AV_CHANNEL_LAYOUT_STEREO
);
502 ret
= ff_set_common_channel_layouts2(ctx
, cfg_in
, cfg_out
, layouts
);
506 if (s
->nb_inputs
>= 1) {
507 AVChannelLayout inlayout
= FF_COUNT2LAYOUT(s
->nb_inputs
);
510 ret
= ff_add_channel_layout(&layouts
, &inlayout
);
513 ret
= ff_channel_layouts_ref(layouts
, &cfg_in
[0]->channel_layouts
);
517 if (!s
->nb_outputs
) {
518 ret
= ff_channel_layouts_ref(layouts
, &cfg_out
[0]->channel_layouts
);
524 if (s
->nb_outputs
>= 1) {
525 AVChannelLayout outlayout
= FF_COUNT2LAYOUT(s
->nb_outputs
);
528 ret
= ff_add_channel_layout(&layouts
, &outlayout
);
531 ret
= ff_channel_layouts_ref(layouts
, &cfg_out
[0]->channel_layouts
);
540 static int process_command(AVFilterContext
*ctx
, const char *cmd
, const char *args
,
541 char *res
, int res_len
, int flags
)
543 LV2Context
*s
= ctx
->priv
;
544 const LilvPort
*port
;
548 sym
= lilv_new_string(s
->world
, cmd
);
549 port
= lilv_plugin_get_port_by_symbol(s
->plugin
, sym
);
552 av_log(s
, AV_LOG_WARNING
, "Unknown option: <%s>\n", cmd
);
554 index
= lilv_port_get_index(s
->plugin
, port
);
555 s
->controls
[index
] = atof(args
);
560 static av_cold
void uninit(AVFilterContext
*ctx
)
562 LV2Context
*s
= ctx
->priv
;
564 lilv_node_free(s
->powerOf2BlockLength
);
565 lilv_node_free(s
->fixedBlockLength
);
566 lilv_node_free(s
->boundedBlockLength
);
567 lilv_node_free(s
->urid_map
);
568 lilv_node_free(s
->atom_Sequence
);
569 lilv_node_free(s
->atom_AtomPort
);
570 lilv_node_free(s
->lv2_Optional
);
571 lilv_node_free(s
->lv2_ControlPort
);
572 lilv_node_free(s
->lv2_AudioPort
);
573 lilv_node_free(s
->lv2_OutputPort
);
574 lilv_node_free(s
->lv2_InputPort
);
575 uri_table_destroy(&s
->uri_table
);
576 lilv_instance_free(s
->instance
);
577 lilv_world_free(s
->world
);
580 av_freep(&s
->controls
);
581 av_freep(&s
->seq_out
);
584 static const AVFilterPad lv2_outputs
[] = {
587 .type
= AVMEDIA_TYPE_AUDIO
,
588 .config_props
= config_output
,
589 .request_frame
= request_frame
,
593 const FFFilter ff_af_lv2
= {
595 .p
.description
= NULL_IF_CONFIG_SMALL("Apply LV2 effect."),
596 .p
.priv_class
= &lv2_class
,
597 .p
.flags
= AVFILTER_FLAG_DYNAMIC_INPUTS
,
598 .priv_size
= sizeof(LV2Context
),
601 .process_command
= process_command
,
602 FILTER_OUTPUTS(lv2_outputs
),
603 FILTER_QUERY_FUNC2(query_formats
),