Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
601eab2b
Commit
601eab2b
authored
Sep 20, 2013
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter: add ladspa wrapper filter
Signed-off-by:
Paul B Mahol
<
onemda@gmail.com
>
parent
547c2f00
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
780 additions
and
2 deletions
+780
-2
Changelog
Changelog
+1
-0
configure
configure
+4
-0
filters.texi
doc/filters.texi
+98
-0
Makefile
libavfilter/Makefile
+1
-0
af_ladspa.c
libavfilter/af_ladspa.c
+673
-0
allfilters.c
libavfilter/allfilters.c
+1
-0
version.h
libavfilter/version.h
+2
-2
No files found.
Changelog
View file @
601eab2b
...
...
@@ -35,6 +35,7 @@ version <next>
- Fraps: use BT.709 colorspace by default for yuv, as reference fraps decoder does
- make decoding alpha optional for prores, ffv1 and vp6 by setting
the skip_alpha flag.
- ladspa wrapper filter
version 2.0:
...
...
configure
View file @
601eab2b
...
...
@@ -193,6 +193,7 @@ External library support:
--enable-frei0r enable frei0r video filtering
--enable-gnutls enable gnutls [no]
--disable-iconv disable iconv [autodetect]
--enable-ladspa enable LADSPA audio filtering
--enable-libaacplus enable AAC+ encoding via libaacplus [no]
--enable-libass enable libass subtitles rendering [no]
--enable-libbluray enable BluRay reading using libbluray [no]
...
...
@@ -1162,6 +1163,7 @@ EXTERNAL_LIBRARY_LIST="
frei0r
gnutls
iconv
ladspa
libaacplus
libass
libbluray
...
...
@@ -2210,6 +2212,7 @@ histeq_filter_deps="gpl"
hqdn3d_filter_deps
=
"gpl"
interlace_filter_deps
=
"gpl"
kerndeint_filter_deps
=
"gpl"
ladspa_filter_deps
=
"ladspa dlopen"
mcdeint_filter_deps
=
"avcodec gpl"
movie_filter_deps
=
"avcodec avformat"
mp_filter_deps
=
"gpl avcodec swscale inline_asm"
...
...
@@ -4210,6 +4213,7 @@ enabled avisynth && { { check_lib2 "windows.h" LoadLibrary; } ||
enabled fontconfig
&&
require_pkg_config fontconfig
"fontconfig/fontconfig.h"
FcInit
enabled frei0r
&&
{
check_header frei0r.h
||
die
"ERROR: frei0r.h header not found"
;
}
enabled gnutls
&&
require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
enabled ladspa
&&
{
check_header ladspa.h
||
die
"ERROR: ladspa.h header not found"
;
}
enabled libiec61883
&&
require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect
-lraw1394
-lavc1394
-lrom1394
-liec61883
enabled libaacplus
&&
require
"libaacplus >= 2.0.0"
aacplus.h aacplusEncOpen
-laacplus
enabled libass
&&
require_pkg_config libass ass/ass.h ass_library_init
...
...
doc/filters.texi
View file @
601eab2b
...
...
@@ -1400,6 +1400,104 @@ ffmpeg -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex
out
@end example
@section ladspa
Load a LADSPA (Linux Audio Developer's Simple Plugin API) plugin.
@table @option
@item file, f
Specifies the name of LADSPA plugin library to load. If the environment
variable @env{LADSPA_PATH} is defined, the LADSPA plugin is searched in
each one of the directories specified by the colon separated list in
@env{LADSPA_PATH}, otherwise in the standard LADSPA paths, which are in
this order: @file{HOME/.ladspa/lib/}, @file{/usr/local/lib/ladspa/},
@file{/usr/lib/ladspa/}.
@item plugin, p
Specifies the plugin within the library. Some libraries contain only
one plugin, but others contain many of them. If this is not set filter
will list all available plugins within the specified library.
@item controls, c
Set the '|' separated list of controls which are zero or more floating point
values that determine the behavior of the loaded plugin (for example delay,
threshold or gain).
Controls need to be defined using the following syntax:
c0=@var{value0}|c1=@var{value1}|c2=@var{value2}|..., where
@var{valuei} is the value set on the @var{i}-th control.
If @option{controls} is set to @code{help}, all available controls and
their valid ranges are printed.
@item sample_rate, s
Specify the sample rate, default to 44100. Only used if plugin have
zero inputs.
@item nb_samples, n
Set the number of samples per channel per each output frame, default
is 1024. Only used if plugin have zero inputs.
@item duration, d
Set the minimum duration of the sourced audio. See the function
@code{av_parse_time()} for the accepted format, also check the "Time duration"
section in the ffmpeg-utils manual.
Note that the resulting duration may be greater than the specified duration,
as the generated audio is always cut at the end of a complete frame.
If not specified, or the expressed duration is negative, the audio is
supposed to be generated forever.
Only used if plugin have zero inputs.
@end table
@subsection Examples
@itemize
@item
List all available plugins within amp (LADSPA example plugin) library:
@example
ladspa=file=amp
@end example
@item
List all available controls and their valid ranges for @code{vcf_notch}
plugin from @code{VCF} library:
@example
ladspa=f=vcf:p=vcf_notch:c=help
@end example
@item
Simulate low quality audio equipment using @code{Computer Music Toolkit} (CMT)
plugin library:
@example
ladspa=file=cmt:plugin=lofi:controls=c0=22|c1=12|c2=12
@end example
@item
Add reverberation to the audio using TAP-plugins
(Tom's Audio Processing plugins):
@example
ladspa=file=tap_reverb:tap_reverb
@end example
@item
Generate white noise, with 0.2 amplitude:
@example
ladspa=file=cmt:noise_source_white:c=c0=.2
@end example
@item
Generate 20 bpm clicks using plugin @code{C* Click - Metronome} from the
@code{C* Audio Plugin Suite} (CAPS) library:
@example
ladspa=file=caps:Click:c=c1=20'
@end example
@item
Apply @code{C* Eq10X2 - Stereo 10-band equaliser} effect:
@example
ladspa=caps:Eq10X2:c=c0=-48|c9=-24|c3=12|c4=2
@end example
@end itemize
@section lowpass
Apply a low-pass filter with 3dB point frequency.
...
...
libavfilter/Makefile
View file @
601eab2b
...
...
@@ -91,6 +91,7 @@ OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o
OBJS-$(CONFIG_EQUALIZER_FILTER)
+=
af_biquads.o
OBJS-$(CONFIG_HIGHPASS_FILTER)
+=
af_biquads.o
OBJS-$(CONFIG_JOIN_FILTER)
+=
af_join.o
OBJS-$(CONFIG_LADSPA_FILTER)
+=
af_ladspa.o
OBJS-$(CONFIG_LOWPASS_FILTER)
+=
af_biquads.o
OBJS-$(CONFIG_PAN_FILTER)
+=
af_pan.o
OBJS-$(CONFIG_RESAMPLE_FILTER)
+=
af_resample.o
...
...
libavfilter/af_ladspa.c
0 → 100644
View file @
601eab2b
/*
* Copyright (c) 2013 Paul B Mahol
* Copyright (c) 2011 Mina Nagy Zaki
*
* This file is part of FFmpeg.
*
* FFmpeg 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,
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* LADSPA wrapper
*/
#include <dlfcn.h>
#include <ladspa.h>
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
#include "internal.h"
typedef
struct
LADSPAContext
{
const
AVClass
*
class
;
char
*
dl_name
;
char
*
plugin
;
char
*
options
;
void
*
dl_handle
;
unsigned
long
nb_inputs
;
unsigned
long
*
ipmap
;
/* map input number to port number */
unsigned
long
nb_inputcontrols
;
unsigned
long
*
icmap
;
/* map input control number to port number */
LADSPA_Data
*
ictlv
;
/* input controls values */
unsigned
long
nb_outputs
;
unsigned
long
*
opmap
;
/* map output number to port number */
unsigned
long
nb_outputcontrols
;
unsigned
long
*
ocmap
;
/* map output control number to port number */
LADSPA_Data
*
octlv
;
/* output controls values */
const
LADSPA_Descriptor
*
desc
;
int
*
ctl_needs_value
;
int
nb_handles
;
LADSPA_Handle
*
handles
;
int
sample_rate
;
int
nb_samples
;
int64_t
pts
;
int64_t
duration
;
}
LADSPAContext
;
#define OFFSET(x) offsetof(LADSPAContext, x)
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
static
const
AVOption
ladspa_options
[]
=
{
{
"file"
,
"set library name or full path"
,
OFFSET
(
dl_name
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"f"
,
"set library name or full path"
,
OFFSET
(
dl_name
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"plugin"
,
"set plugin name"
,
OFFSET
(
plugin
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"p"
,
"set plugin name"
,
OFFSET
(
plugin
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"controls"
,
"set plugin options"
,
OFFSET
(
options
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"c"
,
"set plugin options"
,
OFFSET
(
options
),
AV_OPT_TYPE_STRING
,
.
flags
=
FLAGS
},
{
"sample_rate"
,
"set sample rate"
,
OFFSET
(
sample_rate
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"s"
,
"set sample rate"
,
OFFSET
(
sample_rate
),
AV_OPT_TYPE_INT
,
{.
i64
=
44100
},
1
,
INT32_MAX
,
FLAGS
},
{
"nb_samples"
,
"set the number of samples per requested frame"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
1024
},
1
,
INT_MAX
,
FLAGS
},
{
"n"
,
"set the number of samples per requested frame"
,
OFFSET
(
nb_samples
),
AV_OPT_TYPE_INT
,
{.
i64
=
1024
},
1
,
INT_MAX
,
FLAGS
},
{
"duration"
,
"set audio duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=-
1
},
-
1
,
INT64_MAX
,
FLAGS
},
{
"d"
,
"set audio duration"
,
OFFSET
(
duration
),
AV_OPT_TYPE_DURATION
,
{.
i64
=-
1
},
-
1
,
INT64_MAX
,
FLAGS
},
{
NULL
}
};
AVFILTER_DEFINE_CLASS
(
ladspa
);
static
void
print_ctl_info
(
AVFilterContext
*
ctx
,
int
level
,
LADSPAContext
*
s
,
int
ctl
,
unsigned
long
*
map
,
LADSPA_Data
*
values
,
int
print
)
{
const
LADSPA_PortRangeHint
*
h
=
s
->
desc
->
PortRangeHints
+
map
[
ctl
];
av_log
(
ctx
,
level
,
"c%i: %s ["
,
ctl
,
s
->
desc
->
PortNames
[
map
[
ctl
]]);
if
(
LADSPA_IS_HINT_TOGGLED
(
h
->
HintDescriptor
))
{
av_log
(
ctx
,
level
,
"toggled (1 or 0)"
);
if
(
LADSPA_IS_HINT_HAS_DEFAULT
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
" (default %i)"
,
(
int
)
values
[
ctl
]);
}
else
{
if
(
LADSPA_IS_HINT_INTEGER
(
h
->
HintDescriptor
))
{
av_log
(
ctx
,
level
,
"<int>"
);
if
(
LADSPA_IS_HINT_BOUNDED_BELOW
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", min: %i"
,
(
int
)
h
->
LowerBound
);
if
(
LADSPA_IS_HINT_BOUNDED_ABOVE
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", max: %i"
,
(
int
)
h
->
UpperBound
);
if
(
print
)
av_log
(
ctx
,
level
,
" (value %d)"
,
(
int
)
values
[
ctl
]);
else
if
(
LADSPA_IS_HINT_HAS_DEFAULT
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
" (default %d)"
,
(
int
)
values
[
ctl
]);
}
else
{
av_log
(
ctx
,
level
,
"<float>"
);
if
(
LADSPA_IS_HINT_BOUNDED_BELOW
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", min: %f"
,
h
->
LowerBound
);
if
(
LADSPA_IS_HINT_BOUNDED_ABOVE
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", max: %f"
,
h
->
UpperBound
);
if
(
print
)
av_log
(
ctx
,
level
,
" (value %f)"
,
values
[
ctl
]);
else
if
(
LADSPA_IS_HINT_HAS_DEFAULT
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
" (default %f)"
,
values
[
ctl
]);
}
if
(
LADSPA_IS_HINT_SAMPLE_RATE
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", multiple of sample rate"
);
if
(
LADSPA_IS_HINT_LOGARITHMIC
(
h
->
HintDescriptor
))
av_log
(
ctx
,
level
,
", logarithmic scale"
);
}
av_log
(
ctx
,
level
,
"]
\n
"
);
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
LADSPAContext
*
s
=
ctx
->
priv
;
AVFrame
*
out
;
int
i
,
h
;
if
(
!
s
->
nb_outputs
||
(
av_frame_is_writable
(
in
)
&&
s
->
nb_inputs
==
s
->
nb_outputs
&&
!
(
s
->
desc
->
Properties
&
LADSPA_PROPERTY_INPLACE_BROKEN
)))
{
out
=
in
;
}
else
{
out
=
ff_get_audio_buffer
(
ctx
->
outputs
[
0
],
in
->
nb_samples
);
if
(
!
out
)
{
av_frame_free
(
&
in
);
return
AVERROR
(
ENOMEM
);
}
av_frame_copy_props
(
out
,
in
);
}
for
(
h
=
0
;
h
<
s
->
nb_handles
;
h
++
)
{
for
(
i
=
0
;
i
<
s
->
nb_inputs
;
i
++
)
{
s
->
desc
->
connect_port
(
s
->
handles
[
h
],
s
->
ipmap
[
i
],
(
LADSPA_Data
*
)
in
->
extended_data
[
i
]);
}
for
(
i
=
0
;
i
<
s
->
nb_outputs
;
i
++
)
{
s
->
desc
->
connect_port
(
s
->
handles
[
h
],
s
->
opmap
[
i
],
(
LADSPA_Data
*
)
out
->
extended_data
[
i
]);
}
s
->
desc
->
run
(
s
->
handles
[
h
],
in
->
nb_samples
);
}
for
(
i
=
0
;
i
<
s
->
nb_outputcontrols
;
i
++
)
print_ctl_info
(
ctx
,
AV_LOG_VERBOSE
,
s
,
i
,
s
->
ocmap
,
s
->
octlv
,
1
);
if
(
out
!=
in
)
av_frame_free
(
&
in
);
return
ff_filter_frame
(
ctx
->
outputs
[
0
],
out
);
}
static
int
request_frame
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
LADSPAContext
*
s
=
ctx
->
priv
;
AVFrame
*
out
;
int64_t
t
;
int
i
;
if
(
ctx
->
nb_inputs
)
return
ff_request_frame
(
ctx
->
inputs
[
0
]);
t
=
av_rescale
(
s
->
pts
,
AV_TIME_BASE
,
s
->
sample_rate
);
if
(
s
->
duration
>=
0
&&
t
>=
s
->
duration
)
return
AVERROR_EOF
;
out
=
ff_get_audio_buffer
(
outlink
,
s
->
nb_samples
);
if
(
!
out
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
s
->
nb_outputs
;
i
++
)
s
->
desc
->
connect_port
(
s
->
handles
[
0
],
s
->
opmap
[
i
],
(
LADSPA_Data
*
)
out
->
extended_data
[
i
]);
s
->
desc
->
run
(
s
->
handles
[
0
],
s
->
nb_samples
);
for
(
i
=
0
;
i
<
s
->
nb_outputcontrols
;
i
++
)
print_ctl_info
(
ctx
,
AV_LOG_INFO
,
s
,
i
,
s
->
ocmap
,
s
->
octlv
,
1
);
out
->
sample_rate
=
s
->
sample_rate
;
out
->
pts
=
s
->
pts
;
s
->
pts
+=
s
->
nb_samples
;
return
ff_filter_frame
(
outlink
,
out
);
}
static
void
set_default_ctl_value
(
LADSPAContext
*
s
,
int
ctl
,
unsigned
long
*
map
,
LADSPA_Data
*
values
)
{
const
LADSPA_PortRangeHint
*
h
=
s
->
desc
->
PortRangeHints
+
map
[
ctl
];
const
LADSPA_Data
lower
=
h
->
LowerBound
;
const
LADSPA_Data
upper
=
h
->
UpperBound
;
if
(
LADSPA_IS_HINT_DEFAULT_MINIMUM
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
lower
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_MAXIMUM
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
upper
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_0
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
0
.
0
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_1
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
1
.
0
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_100
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
100
.
0
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_440
(
h
->
HintDescriptor
))
{
values
[
ctl
]
=
440
.
0
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_LOW
(
h
->
HintDescriptor
))
{
if
(
LADSPA_IS_HINT_LOGARITHMIC
(
h
->
HintDescriptor
))
values
[
ctl
]
=
exp
(
log
(
lower
)
*
0
.
75
+
log
(
upper
)
*
0
.
25
);
else
values
[
ctl
]
=
lower
*
0
.
75
+
upper
*
0
.
25
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_MIDDLE
(
h
->
HintDescriptor
))
{
if
(
LADSPA_IS_HINT_LOGARITHMIC
(
h
->
HintDescriptor
))
values
[
ctl
]
=
exp
(
log
(
lower
)
*
0
.
5
+
log
(
upper
)
*
0
.
5
);
else
values
[
ctl
]
=
lower
*
0
.
5
+
upper
*
0
.
5
;
}
else
if
(
LADSPA_IS_HINT_DEFAULT_HIGH
(
h
->
HintDescriptor
))
{
if
(
LADSPA_IS_HINT_LOGARITHMIC
(
h
->
HintDescriptor
))
values
[
ctl
]
=
exp
(
log
(
lower
)
*
0
.
25
+
log
(
upper
)
*
0
.
75
);
else
values
[
ctl
]
=
lower
*
0
.
25
+
upper
*
0
.
75
;
}
}
static
int
connect_ports
(
AVFilterContext
*
ctx
,
AVFilterLink
*
link
)
{
LADSPAContext
*
s
=
ctx
->
priv
;
int
i
,
j
;
s
->
nb_handles
=
s
->
nb_inputs
==
1
&&
s
->
nb_outputs
==
1
?
link
->
channels
:
1
;
s
->
handles
=
av_calloc
(
s
->
nb_handles
,
sizeof
(
*
s
->
handles
));
if
(
!
s
->
handles
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
s
->
nb_handles
;
i
++
)
{
s
->
handles
[
i
]
=
s
->
desc
->
instantiate
(
s
->
desc
,
link
->
sample_rate
);
if
(
!
s
->
handles
[
i
])
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not instantiate plugin.
\n
"
);
return
AVERROR_EXTERNAL
;
}
// Connect the input control ports
for
(
j
=
0
;
j
<
s
->
nb_inputcontrols
;
j
++
)
s
->
desc
->
connect_port
(
s
->
handles
[
i
],
s
->
icmap
[
j
],
s
->
ictlv
+
j
);
// Connect the output control ports
for
(
j
=
0
;
j
<
s
->
nb_outputcontrols
;
j
++
)
s
->
desc
->
connect_port
(
s
->
handles
[
i
],
s
->
ocmap
[
j
],
&
s
->
octlv
[
j
]);
if
(
s
->
desc
->
activate
)
s
->
desc
->
activate
(
s
->
handles
[
i
]);
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"handles: %d
\n
"
,
s
->
nb_handles
);
return
0
;
}
static
int
config_input
(
AVFilterLink
*
inlink
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
return
connect_ports
(
ctx
,
inlink
);
}
static
int
config_output
(
AVFilterLink
*
outlink
)
{
AVFilterContext
*
ctx
=
outlink
->
src
;
int
ret
;
if
(
ctx
->
nb_inputs
)
{
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
outlink
->
format
=
inlink
->
format
;
outlink
->
sample_rate
=
inlink
->
sample_rate
;
ret
=
0
;
}
else
{
LADSPAContext
*
s
=
ctx
->
priv
;
outlink
->
sample_rate
=
s
->
sample_rate
;
outlink
->
time_base
=
(
AVRational
){
1
,
s
->
sample_rate
};
ret
=
connect_ports
(
ctx
,
outlink
);
}
return
ret
;
}
static
void
count_ports
(
const
LADSPA_Descriptor
*
desc
,
unsigned
long
*
nb_inputs
,
unsigned
long
*
nb_outputs
)
{
LADSPA_PortDescriptor
pd
;
int
i
;
for
(
i
=
0
;
i
<
desc
->
PortCount
;
i
++
)
{
pd
=
desc
->
PortDescriptors
[
i
];
if
(
LADSPA_IS_PORT_AUDIO
(
pd
))
{
if
(
LADSPA_IS_PORT_INPUT
(
pd
))
{
(
*
nb_inputs
)
++
;
}
else
if
(
LADSPA_IS_PORT_OUTPUT
(
pd
))
{
(
*
nb_outputs
)
++
;
}
}
}
}
static
void
*
try_load
(
const
char
*
dir
,
const
char
*
soname
)
{
char
*
path
=
av_asprintf
(
"%s/%s.so"
,
dir
,
soname
);
void
*
ret
=
NULL
;
if
(
path
)
{
ret
=
dlopen
(
path
,
RTLD_LOCAL
|
RTLD_NOW
);
av_free
(
path
);
}
return
ret
;
}
static
av_cold
int
init
(
AVFilterContext
*
ctx
)
{
LADSPAContext
*
s
=
ctx
->
priv
;
LADSPA_Descriptor_Function
descriptor_fn
;
const
LADSPA_Descriptor
*
desc
;
LADSPA_PortDescriptor
pd
;
AVFilterPad
pad
=
{
NULL
};
char
*
p
,
*
arg
,
*
saveptr
=
NULL
;
unsigned
long
nb_ports
;
int
i
;
if
(
!
s
->
dl_name
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"No plugin name provided
\n
"
);
return
AVERROR
(
EINVAL
);
}
if
(
s
->
dl_name
[
0
]
==
'/'
||
s
->
dl_name
[
0
]
==
'.'
)
{
// argument is a path
s
->
dl_handle
=
dlopen
(
s
->
dl_name
,
RTLD_LOCAL
|
RTLD_NOW
);
}
else
{
// argument is a shared object name
char
*
paths
=
av_strdup
(
getenv
(
"LADSPA_PATH"
));
const
char
*
separator
=
":"
;
if
(
paths
)
{
p
=
paths
;
while
((
arg
=
av_strtok
(
p
,
separator
,
&
saveptr
))
&&
!
s
->
dl_handle
)
{
s
->
dl_handle
=
try_load
(
arg
,
s
->
dl_name
);
p
=
NULL
;
}
}
av_free
(
paths
);
if
(
!
s
->
dl_handle
&&
(
paths
=
av_asprintf
(
"%s/.ladspa/lib"
,
getenv
(
"HOME"
))))
{
s
->
dl_handle
=
try_load
(
paths
,
s
->
dl_name
);
av_free
(
paths
);
}
if
(
!
s
->
dl_handle
)
s
->
dl_handle
=
try_load
(
"/usr/local/lib/ladspa"
,
s
->
dl_name
);
if
(
!
s
->
dl_handle
)
s
->
dl_handle
=
try_load
(
"/usr/lib/ladspa"
,
s
->
dl_name
);
}
if
(
!
s
->
dl_handle
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Failed to load '%s'
\n
"
,
s
->
dl_name
);
return
AVERROR
(
EINVAL
);
}
descriptor_fn
=
dlsym
(
s
->
dl_handle
,
"ladspa_descriptor"
);
if
(
!
descriptor_fn
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not find ladspa_descriptor: %s
\n
"
,
dlerror
());
return
AVERROR
(
EINVAL
);
}
// Find the requested plugin, or list plugins
if
(
!
s
->
plugin
)
{
av_log
(
ctx
,
AV_LOG_INFO
,
"The '%s' library contains the following plugins:
\n
"
,
s
->
dl_name
);
av_log
(
ctx
,
AV_LOG_INFO
,
"I = Input Channels
\n
"
);
av_log
(
ctx
,
AV_LOG_INFO
,
"O = Output Channels
\n
"
);
av_log
(
ctx
,
AV_LOG_INFO
,
"I:O %-25s %s
\n
"
,
"Plugin"
,
"Description"
);
av_log
(
ctx
,
AV_LOG_INFO
,
"
\n
"
);
for
(
i
=
0
;
desc
=
descriptor_fn
(
i
);
i
++
)
{
unsigned
long
inputs
=
0
,
outputs
=
0
;
count_ports
(
desc
,
&
inputs
,
&
outputs
);
av_log
(
ctx
,
AV_LOG_INFO
,
"%lu:%lu %-25s %s
\n
"
,
inputs
,
outputs
,
desc
->
Label
,
av_x_if_null
(
desc
->
Name
,
"?"
));
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Maker: %s
\n
"
,
av_x_if_null
(
desc
->
Maker
,
"?"
));
av_log
(
ctx
,
AV_LOG_VERBOSE
,
"Copyright: %s
\n
"
,
av_x_if_null
(
desc
->
Copyright
,
"?"
));
}
return
AVERROR_EXIT
;
}
else
{
for
(
i
=
0
;;
i
++
)
{
desc
=
descriptor_fn
(
i
);
if
(
!
desc
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Could not find plugin: %s
\n
"
,
s
->
plugin
);
return
AVERROR
(
EINVAL
);
}
if
(
desc
->
Label
&&
!
strcmp
(
desc
->
Label
,
s
->
plugin
))
break
;
}
}
s
->
desc
=
desc
;
nb_ports
=
desc
->
PortCount
;
s
->
ipmap
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
ipmap
));
s
->
opmap
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
opmap
));
s
->
icmap
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
icmap
));
s
->
ocmap
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
ocmap
));
s
->
ictlv
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
ictlv
));
s
->
octlv
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
octlv
));
s
->
ctl_needs_value
=
av_calloc
(
nb_ports
,
sizeof
(
*
s
->
ctl_needs_value
));
if
(
!
s
->
ipmap
||
!
s
->
opmap
||
!
s
->
icmap
||
!
s
->
ocmap
||
!
s
->
ictlv
||
!
s
->
octlv
||
!
s
->
ctl_needs_value
)
return
AVERROR
(
ENOMEM
);
for
(
i
=
0
;
i
<
nb_ports
;
i
++
)
{
pd
=
desc
->
PortDescriptors
[
i
];
if
(
LADSPA_IS_PORT_AUDIO
(
pd
))
{
if
(
LADSPA_IS_PORT_INPUT
(
pd
))
{
s
->
ipmap
[
s
->
nb_inputs
]
=
i
;
s
->
nb_inputs
++
;
}
else
if
(
LADSPA_IS_PORT_OUTPUT
(
pd
))
{
s
->
opmap
[
s
->
nb_outputs
]
=
i
;
s
->
nb_outputs
++
;
}
}
else
if
(
LADSPA_IS_PORT_CONTROL
(
pd
))
{
if
(
LADSPA_IS_PORT_INPUT
(
pd
))
{
s
->
icmap
[
s
->
nb_inputcontrols
]
=
i
;
if
(
LADSPA_IS_HINT_HAS_DEFAULT
(
desc
->
PortRangeHints
[
i
].
HintDescriptor
))
set_default_ctl_value
(
s
,
s
->
nb_inputcontrols
,
s
->
icmap
,
s
->
ictlv
);
else
s
->
ctl_needs_value
[
s
->
nb_inputcontrols
]
=
1
;
s
->
nb_inputcontrols
++
;
}
else
if
(
LADSPA_IS_PORT_OUTPUT
(
pd
))
{
s
->
ocmap
[
s
->
nb_outputcontrols
]
=
i
;
s
->
nb_outputcontrols
++
;
}
}
}
// List Control Ports if "help" is specified
if
(
s
->
options
&&
!
strcmp
(
s
->
options
,
"help"
))
{
if
(
!
s
->
nb_inputcontrols
)
{
av_log
(
ctx
,
AV_LOG_INFO
,
"The '%s' plugin does not have any input controls.
\n
"
,
desc
->
Label
);
}
else
{
av_log
(
ctx
,
AV_LOG_INFO
,
"The '%s' plugin has the following input controls:
\n
"
,
desc
->
Label
);
for
(
i
=
0
;
i
<
s
->
nb_inputcontrols
;
i
++
)
print_ctl_info
(
ctx
,
AV_LOG_INFO
,
s
,
i
,
s
->
icmap
,
s
->
ictlv
,
0
);
}
return
AVERROR_EXIT
;
}
// Parse control parameters
p
=
s
->
options
;
while
(
s
->
options
)
{
LADSPA_PortRangeHint
*
h
;
LADSPA_Data
val
;
if
(
!
(
arg
=
av_strtok
(
p
,
"|"
,
&
saveptr
)))
break
;
p
=
NULL
;
if
(
sscanf
(
arg
,
"c%d=%f"
,
&
i
,
&
val
)
!=
2
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid syntax.
\n
"
);
return
AVERROR
(
EINVAL
);
}
if
(
i
<
0
||
i
>=
s
->
nb_inputcontrols
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Control c%d is out of range [0 - %lu].
\n
"
,
i
,
s
->
nb_inputcontrols
);
return
AVERROR
(
EINVAL
);
}
h
=
(
LADSPA_PortRangeHint
*
)
s
->
desc
->
PortRangeHints
+
s
->
icmap
[
i
];
s
->
ictlv
[
i
]
=
val
;
s
->
ctl_needs_value
[
i
]
=
0
;
if
(
LADSPA_IS_HINT_BOUNDED_BELOW
(
h
->
HintDescriptor
)
&&
val
<
h
->
LowerBound
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"%s: input control c%d is below lower boundary of %0.4f.
\n
"
,
s
->
desc
->
Label
,
i
,
h
->
LowerBound
);
return
AVERROR
(
EINVAL
);
}
if
(
LADSPA_IS_HINT_BOUNDED_ABOVE
(
h
->
HintDescriptor
)
&&
val
>
h
->
UpperBound
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"%s: input control c%d is above upper boundary of %0.4f.
\n
"
,
s
->
desc
->
Label
,
i
,
h
->
UpperBound
);
return
AVERROR
(
EINVAL
);
}
}
// Check if any controls are not set
for
(
i
=
0
;
i
<
s
->
nb_inputcontrols
;
i
++
)
{
if
(
s
->
ctl_needs_value
[
i
])
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Control c%d must be set.
\n
"
,
i
);
print_ctl_info
(
ctx
,
AV_LOG_ERROR
,
s
,
i
,
s
->
icmap
,
s
->
ictlv
,
0
);
return
AVERROR
(
EINVAL
);
}
}
pad
.
type
=
AVMEDIA_TYPE_AUDIO
;
if
(
s
->
nb_inputs
)
{
pad
.
name
=
av_asprintf
(
"in0:%s%lu"
,
desc
->
Label
,
s
->
nb_inputs
);
if
(
!
pad
.
name
)
return
AVERROR
(
ENOMEM
);
pad
.
filter_frame
=
filter_frame
;
pad
.
config_props
=
config_input
;
if
(
ff_insert_inpad
(
ctx
,
ctx
->
nb_inputs
,
&
pad
)
<
0
)
{
av_freep
(
&
pad
.
name
);
return
AVERROR
(
ENOMEM
);
}
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"ports: %lu
\n
"
,
nb_ports
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
"inputs: %lu outputs: %lu
\n
"
,
s
->
nb_inputs
,
s
->
nb_outputs
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
"input controls: %lu output controls: %lu
\n
"
,
s
->
nb_inputcontrols
,
s
->
nb_outputcontrols
);
return
0
;
}
static
int
query_formats
(
AVFilterContext
*
ctx
)
{
LADSPAContext
*
s
=
ctx
->
priv
;
AVFilterFormats
*
formats
;
AVFilterChannelLayouts
*
layouts
;
static
const
enum
AVSampleFormat
sample_fmts
[]
=
{
AV_SAMPLE_FMT_FLTP
,
AV_SAMPLE_FMT_NONE
};
formats
=
ff_make_format_list
(
sample_fmts
);
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ff_set_common_formats
(
ctx
,
formats
);
if
(
s
->
nb_inputs
)
{
formats
=
ff_all_samplerates
();
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
ff_set_common_samplerates
(
ctx
,
formats
);
}
else
{
int
sample_rates
[]
=
{
s
->
sample_rate
,
-
1
};
ff_set_common_samplerates
(
ctx
,
ff_make_format_list
(
sample_rates
));
}
if
(
s
->
nb_inputs
==
1
&&
s
->
nb_outputs
==
1
)
{
// We will instantiate multiple LADSPA_Handle, one over each channel
layouts
=
ff_all_channel_layouts
();
if
(
!
layouts
)
return
AVERROR
(
ENOMEM
);
ff_set_common_channel_layouts
(
ctx
,
layouts
);
}
else
{
if
(
s
->
nb_inputs
>=
1
)
{
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
int64_t
inlayout
=
FF_COUNT2LAYOUT
(
s
->
nb_inputs
);
layouts
=
NULL
;
ff_add_channel_layout
(
&
layouts
,
inlayout
);
ff_channel_layouts_ref
(
layouts
,
&
inlink
->
out_channel_layouts
);
}
if
(
s
->
nb_outputs
>=
1
)
{
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
int64_t
outlayout
=
FF_COUNT2LAYOUT
(
s
->
nb_outputs
);
layouts
=
NULL
;
ff_add_channel_layout
(
&
layouts
,
outlayout
);
ff_channel_layouts_ref
(
layouts
,
&
outlink
->
in_channel_layouts
);
}
}
return
0
;
}
static
av_cold
void
uninit
(
AVFilterContext
*
ctx
)
{
LADSPAContext
*
s
=
ctx
->
priv
;
int
i
;
for
(
i
=
0
;
i
<
s
->
nb_handles
;
i
++
)
{
if
(
s
->
desc
->
deactivate
)
s
->
desc
->
deactivate
(
s
->
handles
[
i
]);
if
(
s
->
desc
->
cleanup
)
s
->
desc
->
cleanup
(
s
->
handles
[
i
]);
}
if
(
s
->
dl_handle
)
dlclose
(
s
->
dl_handle
);
av_freep
(
&
s
->
ipmap
);
av_freep
(
&
s
->
opmap
);
av_freep
(
&
s
->
icmap
);
av_freep
(
&
s
->
ocmap
);
av_freep
(
&
s
->
ictlv
);
av_freep
(
&
s
->
octlv
);
av_freep
(
&
s
->
handles
);
av_freep
(
&
s
->
ctl_needs_value
);
if
(
ctx
->
nb_inputs
)
av_freep
(
&
ctx
->
input_pads
[
0
].
name
);
}
static
const
AVFilterPad
ladspa_outputs
[]
=
{
{
.
name
=
"default"
,
.
type
=
AVMEDIA_TYPE_AUDIO
,
.
config_props
=
config_output
,
.
request_frame
=
request_frame
,
},
{
NULL
}
};
AVFilter
avfilter_af_ladspa
=
{
.
name
=
"ladspa"
,
.
description
=
NULL_IF_CONFIG_SMALL
(
"Apply LADSPA effect."
),
.
priv_size
=
sizeof
(
LADSPAContext
),
.
priv_class
=
&
ladspa_class
,
.
init
=
init
,
.
uninit
=
uninit
,
.
query_formats
=
query_formats
,
.
inputs
=
0
,
.
outputs
=
ladspa_outputs
,
.
flags
=
AVFILTER_FLAG_DYNAMIC_INPUTS
,
};
libavfilter/allfilters.c
View file @
601eab2b
...
...
@@ -87,6 +87,7 @@ void avfilter_register_all(void)
REGISTER_FILTER
(
EQUALIZER
,
equalizer
,
af
);
REGISTER_FILTER
(
HIGHPASS
,
highpass
,
af
);
REGISTER_FILTER
(
JOIN
,
join
,
af
);
REGISTER_FILTER
(
LADSPA
,
ladspa
,
af
);
REGISTER_FILTER
(
LOWPASS
,
lowpass
,
af
);
REGISTER_FILTER
(
PAN
,
pan
,
af
);
REGISTER_FILTER
(
RESAMPLE
,
resample
,
af
);
...
...
libavfilter/version.h
View file @
601eab2b
...
...
@@ -30,8 +30,8 @@
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 8
6
#define LIBAVFILTER_VERSION_MICRO 10
2
#define LIBAVFILTER_VERSION_MINOR 8
7
#define LIBAVFILTER_VERSION_MICRO 10
0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment