1 /*
2 * Copyright (c) 2013 Paul B Mahol
3 * Copyright (c) 2011 Mina Nagy Zaki
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 /**
23 * @file
24 * LADSPA wrapper
25 */
26
27 #include <dlfcn.h>
28 #include <ladspa.h>
39
44
51
53 unsigned long *
ipmap;
/* map input number to port number */
54
56 unsigned long *
icmap;
/* map input control number to port number */
57 LADSPA_Data *
ictlv;
/* input controls values */
58
60 unsigned long *
opmap;
/* map output number to port number */
61
63 unsigned long *
ocmap;
/* map output control number to port number */
64 LADSPA_Data *
octlv;
/* output controls values */
65
66 const LADSPA_Descriptor *
desc;
70
80
83
84 #define OFFSET(x) offsetof(LADSPAContext, x)
85 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
95 {
"nb_samples",
"set the number of samples per requested frame",
OFFSET(nb_samples),
AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX,
FLAGS },
102 };
103
105
107 {
108 int latency = 0;
109
110 for (
int ctl = 0; ctl <
s->nb_outputcontrols; ctl++) {
112 continue;
113
114 latency =
lrintf(
s->octlv[ctl]);
115 break;
116 }
117
118 return latency;
119 }
120
124 {
125 const LADSPA_PortRangeHint *
h =
s->desc->PortRangeHints +
map[ctl];
126
128
129 if (LADSPA_IS_HINT_TOGGLED(
h->HintDescriptor)) {
131
132 if (LADSPA_IS_HINT_HAS_DEFAULT(
h->HintDescriptor))
134 } else {
135 if (LADSPA_IS_HINT_INTEGER(
h->HintDescriptor)) {
137
138 if (LADSPA_IS_HINT_BOUNDED_BELOW(
h->HintDescriptor))
140
141 if (LADSPA_IS_HINT_BOUNDED_ABOVE(
h->HintDescriptor))
143
146 else if (LADSPA_IS_HINT_HAS_DEFAULT(
h->HintDescriptor))
148 } else {
150
151 if (LADSPA_IS_HINT_BOUNDED_BELOW(
h->HintDescriptor))
153
154 if (LADSPA_IS_HINT_BOUNDED_ABOVE(
h->HintDescriptor))
156
159 else if (LADSPA_IS_HINT_HAS_DEFAULT(
h->HintDescriptor))
161 }
162
163 if (LADSPA_IS_HINT_SAMPLE_RATE(
h->HintDescriptor))
165
166 if (LADSPA_IS_HINT_LOGARITHMIC(
h->HintDescriptor))
168 }
169
171 }
172
174 {
178 int i,
h,
p, new_out_samples;
183
185
186 if (!
s->nb_outputs ||
188 s->in_trim == 0 &&
s->out_pad == 0 &&
189 !(
s->desc->Properties & LADSPA_PROPERTY_INPLACE_BROKEN))) {
191 } else {
196 }
198 }
199
200 av_assert0(!
s->nb_outputs ||
out->ch_layout.nb_channels == (
s->nb_outputs *
s->nb_handles));
201
202 for (
h = 0;
h <
s->nb_handles;
h++) {
203 for (
i = 0;
i <
s->nb_inputs;
i++) {
204 p =
s->nb_handles > 1 ?
h :
i;
205 s->desc->connect_port(
s->handles[
h],
s->ipmap[
i],
207 }
208
209 for (
i = 0;
i <
s->nb_outputs;
i++) {
210 p =
s->nb_handles > 1 ?
h :
i;
211 s->desc->connect_port(
s->handles[
h],
s->opmap[
i],
212 (LADSPA_Data*)
out->extended_data[
p]);
213 }
214
219 }
220
221 for (
i = 0;
i <
s->nb_outputcontrols;
i++)
223
226
229
230 new_out_samples =
out->nb_samples;
231 if (
s->in_trim > 0) {
232 int trim =
FFMIN(new_out_samples,
s->in_trim);
233
234 new_out_samples -= trim;
236 }
237
238 if (new_out_samples <= 0) {
240 return 0;
241 } else if (new_out_samples < out->nb_samples) {
242 int offset =
out->nb_samples - new_out_samples;
243 for (
int ch = 0; ch <
out->ch_layout.nb_channels; ch++)
244 memmove(
out->extended_data[ch],
out->extended_data[ch] +
sizeof(
float) *
offset,
245 sizeof(float) * new_out_samples);
246 out->nb_samples = new_out_samples;
247 }
248
250
254
257 out->pts =
s->next_out_pts;
258 } else {
260 }
261 s->next_in_pts = in_pts + in_duration;
262 s->next_out_pts =
out->pts + out_duration;
263
265 }
266
268 {
274
275 if (
ctx->nb_inputs) {
277
282
283 s->out_pad -=
frame->nb_samples;
284 frame->pts =
s->next_in_pts;
286 }
288 }
289
291 if (
s->duration >= 0 && t >=
s->duration)
293
297
298 for (
i = 0;
i <
s->nb_outputs;
i++)
299 s->desc->connect_port(
s->handles[0],
s->opmap[
i],
300 (LADSPA_Data*)
out->extended_data[
i]);
301
302 s->desc->run(
s->handles[0],
s->nb_samples);
303
304 for (
i = 0;
i <
s->nb_outputcontrols;
i++)
306
307 out->sample_rate =
s->sample_rate;
309 s->pts +=
s->nb_samples;
310
312 }
313
316 {
317 const LADSPA_PortRangeHint *
h =
s->desc->PortRangeHints +
map[ctl];
318 const LADSPA_Data lower =
h->LowerBound;
319 const LADSPA_Data upper =
h->UpperBound;
320
321 if (LADSPA_IS_HINT_DEFAULT_MINIMUM(
h->HintDescriptor)) {
323 }
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(
h->HintDescriptor)) {
325 }
else if (LADSPA_IS_HINT_DEFAULT_0(
h->HintDescriptor)) {
327 }
else if (LADSPA_IS_HINT_DEFAULT_1(
h->HintDescriptor)) {
329 }
else if (LADSPA_IS_HINT_DEFAULT_100(
h->HintDescriptor)) {
331 }
else if (LADSPA_IS_HINT_DEFAULT_440(
h->HintDescriptor)) {
333 }
else if (LADSPA_IS_HINT_DEFAULT_LOW(
h->HintDescriptor)) {
334 if (LADSPA_IS_HINT_LOGARITHMIC(
h->HintDescriptor))
336 else
337 values[ctl] = lower * 0.75 + upper * 0.25;
338 }
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(
h->HintDescriptor)) {
339 if (LADSPA_IS_HINT_LOGARITHMIC(
h->HintDescriptor))
341 else
342 values[ctl] = lower * 0.5 + upper * 0.5;
343 }
else if (LADSPA_IS_HINT_DEFAULT_HIGH(
h->HintDescriptor)) {
344 if (LADSPA_IS_HINT_LOGARITHMIC(
h->HintDescriptor))
346 else
347 values[ctl] = lower * 0.25 + upper * 0.75;
348 }
349 }
350
352 {
355
357 s->handles =
av_calloc(
s->nb_handles,
sizeof(*
s->handles));
360
361 for (
i = 0;
i <
s->nb_handles;
i++) {
363 if (!
s->handles[
i]) {
366 }
367
368 // Connect the input control ports
369 for (j = 0; j <
s->nb_inputcontrols; j++)
370 s->desc->connect_port(
s->handles[
i],
s->icmap[j],
s->ictlv + j);
371
372 // Connect the output control ports
373 for (j = 0; j <
s->nb_outputcontrols; j++)
374 s->desc->connect_port(
s->handles[
i],
s->ocmap[j], &
s->octlv[j]);
375
376 if (
s->desc->activate)
377 s->desc->activate(
s->handles[
i]);
378 }
379
381
382 return 0;
383 }
384
386 {
388
390 }
391
393 {
397
398 if (
ctx->nb_inputs) {
400
403 if (
s->nb_inputs ==
s->nb_outputs) {
406 }
407
409 } else {
412
414 }
415
417 }
418
420 unsigned long *nb_inputs, unsigned long *nb_outputs)
421 {
422 LADSPA_PortDescriptor pd;
424
425 for (
i = 0;
i <
desc->PortCount;
i++) {
426 pd =
desc->PortDescriptors[
i];
427
428 if (LADSPA_IS_PORT_AUDIO(pd)) {
429 if (LADSPA_IS_PORT_INPUT(pd)) {
430 (*nb_inputs)++;
431 } else if (LADSPA_IS_PORT_OUTPUT(pd)) {
432 (*nb_outputs)++;
433 }
434 }
435 }
436 }
437
438 static void *
try_load(
const char *dir,
const char *soname)
439 {
442
443 if (path) {
444 ret = dlopen(path, RTLD_LOCAL|RTLD_NOW);
446 }
447
449 }
450
452 {
454 const char *label =
s->desc->Label;
455 LADSPA_PortRangeHint *
h = (LADSPA_PortRangeHint *)
s->desc->PortRangeHints +
457
458 if (port >=
s->nb_inputcontrols) {
460 port,
s->nb_inputcontrols);
462 }
463
464 if (LADSPA_IS_HINT_BOUNDED_BELOW(
h->HintDescriptor) &&
465 value < h->LowerBound) {
467 "%s: input control c%ld is below lower boundary of %0.4f.\n",
468 label, port,
h->LowerBound);
470 }
471
472 if (LADSPA_IS_HINT_BOUNDED_ABOVE(
h->HintDescriptor) &&
475 "%s: input control c%ld is above upper boundary of %0.4f.\n",
476 label, port,
h->UpperBound);
478 }
479
481
482 return 0;
483 }
484
486 {
488 LADSPA_Descriptor_Function descriptor_fn;
489 const LADSPA_Descriptor *
desc;
490 LADSPA_PortDescriptor pd;
493 unsigned long nb_ports;
495
499 }
500
501 if (
s->dl_name[0] ==
'/' ||
s->dl_name[0] ==
'.') {
502 // argument is a path
503 s->dl_handle = dlopen(
s->dl_name, RTLD_LOCAL|RTLD_NOW);
504 } else {
505 // argument is a shared object name
506 char *paths =
av_strdup(getenv(
"LADSPA_PATH"));
507 const char *home_path = getenv("HOME");
508 const char *separator = ":";
509
510 if (paths) {
512 while ((
arg =
av_strtok(
p, separator, &saveptr)) && !
s->dl_handle) {
515 }
516 }
517
519 if (!
s->dl_handle && home_path && (paths =
av_asprintf(
"%s/.ladspa", home_path))) {
522 }
523
524 if (!
s->dl_handle && home_path && (paths =
av_asprintf(
"%s/.ladspa/lib", home_path))) {
527 }
528
530 s->dl_handle =
try_load(
"/usr/local/lib/ladspa",
s->dl_name);
531
533 s->dl_handle =
try_load(
"/usr/lib/ladspa",
s->dl_name);
534 }
538 }
539
540 descriptor_fn = dlsym(
s->dl_handle,
"ladspa_descriptor");
541 if (!descriptor_fn) {
544 }
545
546 // Find the requested plugin, or list plugins
553 for (
i = 0;
desc = descriptor_fn(
i);
i++) {
555
563 }
565 } else {
567 desc = descriptor_fn(
i);
571 }
572
573 if (
desc->Label && !strcmp(
desc->Label,
s->plugin))
574 break;
575 }
576 }
577
579 nb_ports =
desc->PortCount;
580
587 s->ctl_needs_value =
av_calloc(nb_ports,
sizeof(*
s->ctl_needs_value));
588 if (!
s->ipmap || !
s->opmap || !
s->icmap ||
589 !
s->ocmap || !
s->ictlv || !
s->octlv || !
s->ctl_needs_value)
591
592 for (
i = 0;
i < nb_ports;
i++) {
593 pd =
desc->PortDescriptors[
i];
594
595 if (LADSPA_IS_PORT_AUDIO(pd)) {
596 if (LADSPA_IS_PORT_INPUT(pd)) {
597 s->ipmap[
s->nb_inputs] =
i;
599 } else if (LADSPA_IS_PORT_OUTPUT(pd)) {
600 s->opmap[
s->nb_outputs] =
i;
602 }
603 } else if (LADSPA_IS_PORT_CONTROL(pd)) {
604 if (LADSPA_IS_PORT_INPUT(pd)) {
605 s->icmap[
s->nb_inputcontrols] =
i;
606
607 if (LADSPA_IS_HINT_HAS_DEFAULT(
desc->PortRangeHints[
i].HintDescriptor))
609 else
610 s->ctl_needs_value[
s->nb_inputcontrols] = 1;
611
612 s->nb_inputcontrols++;
613 } else if (LADSPA_IS_PORT_OUTPUT(pd)) {
614 s->ocmap[
s->nb_outputcontrols] =
i;
615 s->nb_outputcontrols++;
616 }
617 }
618 }
619
620 // List Control Ports if "help" is specified
621 if (
s->options && !strcmp(
s->options,
"help")) {
622 if (!
s->nb_inputcontrols) {
624 "The '%s' plugin does not have any input controls.\n",
626 } else {
628 "The '%s' plugin has the following input controls:\n",
630 for (
i = 0;
i <
s->nb_inputcontrols;
i++)
632 }
634 }
635
636 // Parse control parameters
641
643 break;
645
650 }
652 }
653
656 s->ctl_needs_value[
i] = 0;
657 }
658
659 // Check if any controls are not set
660 for (
i = 0;
i <
s->nb_inputcontrols;
i++) {
661 if (
s->ctl_needs_value[
i]) {
665 }
666 }
667
669
674
679 }
680
683 s->nb_inputs,
s->nb_outputs);
685 s->nb_inputcontrols,
s->nb_outputcontrols);
686
689
693
694 return 0;
695 }
696
700 {
708
711
715 }
716
717 if (
s->nb_inputs == 1 &&
s->nb_outputs == 1) {
718 // We will instantiate multiple LADSPA_Handle, one over each channel
722 }
else if (
s->nb_inputs == 2 &&
s->nb_outputs == 2) {
730 } else {
731 if (
s->nb_inputs >= 1) {
733
741
742 if (!
s->nb_outputs) {
746 }
747 }
748
749 if (
s->nb_outputs >= 1) {
751
759 }
760 }
761
762 return 0;
763 }
764
766 {
769
770 for (
i = 0;
i <
s->nb_handles;
i++) {
771 if (
s->desc->deactivate)
772 s->desc->deactivate(
s->handles[
i]);
773 if (
s->desc->cleanup)
774 s->desc->cleanup(
s->handles[
i]);
775 }
776
778 dlclose(
s->dl_handle);
779
788
790 }
791
793 char *res,
int res_len,
int flags)
794 {
796 unsigned long port;
797
800
802 }
803
805 {
810 },
811 };
812
816 .p.priv_class = &ladspa_class,
824 };