[FFmpeg-devel] [PATCH] avfilter: add ladspa wrapper filter
Paul B Mahol
onemda at gmail.com
Sun Sep 22 17:07:31 CEST 2013
On 9/22/13, Stefano Sabatini <stefasab at gmail.com> wrote:
> On date Saturday 2013-09-21 22:53:06 +0000, Paul B Mahol encoded:
>> Signed-off-by: Paul B Mahol <onemda at gmail.com>
>> ---
>> configure | 4 +
>> doc/filters.texi | 92 +++++++
>> libavfilter/Makefile | 1 +
>> libavfilter/af_ladspa.c | 666
>> +++++++++++++++++++++++++++++++++++++++++++++++
>> libavfilter/allfilters.c | 1 +
>> 5 files changed, 764 insertions(+)
>> create mode 100644 libavfilter/af_ladspa.c
>>
[...]
> 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.
>
> or something like that.
done.
>
>> +
>> + at item sample_rate, s
>> +Specify the sample rate, default to 44100. Only used if plugin have
>> +zero inputs.
>> +
>> + at 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.
>> +
>> + at item duration, d
>> +Set the minimum duration of the sourced audio. See the function
>> + at 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.
>
> nit: weird formatting
fixed
>
>> +If not specified, or the expressed duration is negative, the audio is
>> +supposed to be generated forever.
>> +Only used if plugin have zero inputs.
>> +
>> + at end table
>> +
>> + at subsection Examples
>> +
>> + at itemize
>> + at item
>> +List all available plugins within amp (LADSPA example plugin) library:
>> + at example
>> +ladspa=file=amp
>> + at end example
[...]
>> + unsigned long nb_ports;
>> +
>> + unsigned long nb_inputs;
>
>> + unsigned long *ipmap; /* map of input ports */
>
> map port number to input number?
other way around, improved description
>
>> +
>> + unsigned long nb_inputcontrols;
>> + unsigned long *icmap; /* map of input controls */
>
>> + LADSPA_Data *ictlv; /* input cotrols values */
>
> typo
fixed
>
>> +
>> + unsigned long nb_outputs;
>> + unsigned long *opmap; /* map of output ports */
>> +
>> + unsigned long nb_outputcontrols;
>> + unsigned long *ocmap; /* map of output controls */
>> + LADSPA_Data *octlv; /* output controls values */
>> +
>> + const LADSPA_Descriptor *desc;
>> + int *ctl_needs_value;
>
>> + int nb_handles;
>> + LADSPA_Handle *handles;
>
> Can you explain the relation between handles, ports, and channels?
Here or in code?
>
>> +
>> + int sample_rate;
>> + int nb_samples;
>> + int64_t pts;
>> + int64_t duration;
>> +} LADSPAContext;
>> +
[...]
>> +{
>> + char *path = av_asprintf("%s/%s.so", dir, soname);
>> + if (!path)
>> + return NULL;
>> + return dlopen(path, RTLD_NOW);
>
> leak on path
Thanks. Fixed.
>
>> +}
>> +
>> +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;
>> + 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_NOW|RTLD_LOCAL);
>
> Any reason to use RTLD_LOCAL here (and not in try_load)?
fixed
>
> You could refactor and use try_load here as well.
>
>> + } else {
>> + // argument is a shared object name
>> + char *paths = av_strdup(getenv("LADSPA_PATH"));
>> + const char *separator = ":";
>> +
[...]
>> + }
>> +
>
>> + if (s->nb_inputs == 1 && s->nb_outputs == 1) {
>
>> + // We will instantiate multiple instances, one over each channel
>
> confusing: instances of what?
LADSPA_Handle
>
>> + 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);
>> + }
>
> So you have N inputs, you create N inputs, each one with N channels?
each input/output port in ladspa maps to single input/output channel.
input controls ports are our AVOptions.
output controls ports are something like our metadata/logs.
>
>> +
>> + 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;
>> +}
>> +
> [...]
I'm very happy with quality this patch reached so I will push it.
More information about the ffmpeg-devel
mailing list