Message ID | 20190418211734.11300-2-onemda@gmail.com |
---|---|
State | New |
Headers | show |
2019-04-18 23:17 GMT+02:00, Paul B Mahol <onemda@gmail.com>: > Signed-off-by: Paul B Mahol <onemda@gmail.com> > --- > libavfilter/Makefile | 1 + > libavfilter/af_aupsample.c | 159 +++++++++++++++++++++++++++++++++++++ > libavfilter/allfilters.c | 1 + > 3 files changed, 161 insertions(+) > create mode 100644 libavfilter/af_aupsample.c > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 682df45ef5..a38bc35231 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -86,6 +86,7 @@ OBJS-$(CONFIG_ASTATS_FILTER) += > af_astats.o > OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o > framesync.o > OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o > OBJS-$(CONFIG_ATRIM_FILTER) += trim.o > +OBJS-$(CONFIG_AUPSAMPLE_FILTER) += af_aupsample.o > OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o > OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o > OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o > diff --git a/libavfilter/af_aupsample.c b/libavfilter/af_aupsample.c > new file mode 100644 > index 0000000000..ee35b9c0c6 > --- /dev/null > +++ b/libavfilter/af_aupsample.c > @@ -0,0 +1,159 @@ > +/* > + * Copyright (c) 2019 Paul B Mahol > + * > + * 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 > + */ > + > +#include "libavutil/opt.h" > +#include "libavutil/samplefmt.h" > +#include "avfilter.h" > +#include "audio.h" > +#include "filters.h" > +#include "internal.h" > + > +typedef struct AudioUpSampleContext { > + const AVClass *class; > + int factor; > + > + int64_t next_pts; > +} AudioUpSampleContext; > + > +#define OFFSET(x) offsetof(AudioUpSampleContext, x) > +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > + > +static const AVOption aupsample_options[] = { > + { "factor", "set upsampling factor", OFFSET(factor), AV_OPT_TYPE_INT, > {.i64=1}, 1, 64, A }, > + { NULL } > +}; > + > +AVFILTER_DEFINE_CLASS(aupsample); > + > +static int query_formats(AVFilterContext *ctx) > +{ > + AudioUpSampleContext *s = ctx->priv; > + AVFilterChannelLayouts *layouts; > + AVFilterFormats *formats; > + int sample_rates[] = { 44100, -1 }; > + static const enum AVSampleFormat sample_fmts[] = { > + AV_SAMPLE_FMT_DBLP, > + AV_SAMPLE_FMT_NONE > + }; > + AVFilterFormats *avff; > + int ret; > + > + if (!ctx->inputs[0]->in_samplerates || > + !ctx->inputs[0]->in_samplerates->nb_formats) { > + return AVERROR(EAGAIN); > + } > + > + layouts = ff_all_channel_counts(); > + if (!layouts) > + return AVERROR(ENOMEM); > + ret = ff_set_common_channel_layouts(ctx, layouts); > + if (ret < 0) > + return ret; > + > + formats = ff_make_format_list(sample_fmts); > + if (!formats) > + return AVERROR(ENOMEM); > + ret = ff_set_common_formats(ctx, formats); > + if (ret < 0) > + return ret; > + > + avff = ctx->inputs[0]->in_samplerates; > + sample_rates[0] = avff->formats[0]; > + if (!ctx->inputs[0]->out_samplerates) > + if ((ret = ff_formats_ref(ff_make_format_list(sample_rates), > + &ctx->inputs[0]->out_samplerates)) < 0) > + return ret; > + > + sample_rates[0] = avff->formats[0] * s->factor; > + return ff_formats_ref(ff_make_format_list(sample_rates), > + &ctx->outputs[0]->in_samplerates); > +} > + > +static int config_input(AVFilterLink *inlink) > +{ > + AVFilterContext *ctx = inlink->dst; > + AudioUpSampleContext *s = ctx->priv; > + > + s->next_pts = AV_NOPTS_VALUE; > + > + return 0; > +} > + > +static int filter_frame(AVFilterLink *inlink, AVFrame *in) > +{ > + AVFilterContext *ctx = inlink->dst; > + AVFilterLink *outlink = ctx->outputs[0]; > + AudioUpSampleContext *s = ctx->priv; > + const int factor = s->factor; > + AVFrame *out; > + > + if (s->factor == 1) > + return ff_filter_frame(outlink, in); > + > + out = ff_get_audio_buffer(outlink, in->nb_samples * s->factor); > + if (!out) { > + av_frame_free(&in); > + return AVERROR(ENOMEM); > + } > + > + if (s->next_pts == AV_NOPTS_VALUE) > + s->next_pts = in->pts; > + > + for (int c = 0; c < in->channels; c++) { > + const double *src = (const double *)in->extended_data[c]; > + double *dst = (double *)out->extended_data[c]; > + > + for (int n = 0; n < in->nb_samples; n++) > + dst[n*factor] = src[n]; > + } > + > + out->pts = s->next_pts; > + s->next_pts += av_rescale_q(out->nb_samples, (AVRational){1, > outlink->sample_rate}, outlink->time_base); > + av_frame_free(&in); > + return ff_filter_frame(ctx->outputs[0], out); > +} > + > +static const AVFilterPad aupsample_inputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_AUDIO, > + .filter_frame = filter_frame, > + .config_props = config_input, > + }, > + { NULL } > +}; > + > +static const AVFilterPad aupsample_outputs[] = { > + { > + .name = "default", > + .type = AVMEDIA_TYPE_AUDIO, > + }, > + { NULL } > +}; > + > +AVFilter ff_af_aupsample = { > + .name = "aupsample", > + .description = NULL_IF_CONFIG_SMALL("Upsample > audio by integer factor."), Is it faster? Better quality? Just wondering, Carl Eugen
On 4/19/19, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote: > 2019-04-18 23:17 GMT+02:00, Paul B Mahol <onemda@gmail.com>: >> Signed-off-by: Paul B Mahol <onemda@gmail.com> >> --- >> libavfilter/Makefile | 1 + >> libavfilter/af_aupsample.c | 159 +++++++++++++++++++++++++++++++++++++ >> libavfilter/allfilters.c | 1 + >> 3 files changed, 161 insertions(+) >> create mode 100644 libavfilter/af_aupsample.c >> >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile >> index 682df45ef5..a38bc35231 100644 >> --- a/libavfilter/Makefile >> +++ b/libavfilter/Makefile >> @@ -86,6 +86,7 @@ OBJS-$(CONFIG_ASTATS_FILTER) += >> af_astats.o >> OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o >> framesync.o >> OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o >> OBJS-$(CONFIG_ATRIM_FILTER) += trim.o >> +OBJS-$(CONFIG_AUPSAMPLE_FILTER) += af_aupsample.o >> OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o >> OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o >> OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o >> diff --git a/libavfilter/af_aupsample.c b/libavfilter/af_aupsample.c >> new file mode 100644 >> index 0000000000..ee35b9c0c6 >> --- /dev/null >> +++ b/libavfilter/af_aupsample.c >> @@ -0,0 +1,159 @@ >> +/* >> + * Copyright (c) 2019 Paul B Mahol >> + * >> + * 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 >> + */ >> + >> +#include "libavutil/opt.h" >> +#include "libavutil/samplefmt.h" >> +#include "avfilter.h" >> +#include "audio.h" >> +#include "filters.h" >> +#include "internal.h" >> + >> +typedef struct AudioUpSampleContext { >> + const AVClass *class; >> + int factor; >> + >> + int64_t next_pts; >> +} AudioUpSampleContext; >> + >> +#define OFFSET(x) offsetof(AudioUpSampleContext, x) >> +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM >> + >> +static const AVOption aupsample_options[] = { >> + { "factor", "set upsampling factor", OFFSET(factor), AV_OPT_TYPE_INT, >> {.i64=1}, 1, 64, A }, >> + { NULL } >> +}; >> + >> +AVFILTER_DEFINE_CLASS(aupsample); >> + >> +static int query_formats(AVFilterContext *ctx) >> +{ >> + AudioUpSampleContext *s = ctx->priv; >> + AVFilterChannelLayouts *layouts; >> + AVFilterFormats *formats; >> + int sample_rates[] = { 44100, -1 }; >> + static const enum AVSampleFormat sample_fmts[] = { >> + AV_SAMPLE_FMT_DBLP, >> + AV_SAMPLE_FMT_NONE >> + }; >> + AVFilterFormats *avff; >> + int ret; >> + >> + if (!ctx->inputs[0]->in_samplerates || >> + !ctx->inputs[0]->in_samplerates->nb_formats) { >> + return AVERROR(EAGAIN); >> + } >> + >> + layouts = ff_all_channel_counts(); >> + if (!layouts) >> + return AVERROR(ENOMEM); >> + ret = ff_set_common_channel_layouts(ctx, layouts); >> + if (ret < 0) >> + return ret; >> + >> + formats = ff_make_format_list(sample_fmts); >> + if (!formats) >> + return AVERROR(ENOMEM); >> + ret = ff_set_common_formats(ctx, formats); >> + if (ret < 0) >> + return ret; >> + >> + avff = ctx->inputs[0]->in_samplerates; >> + sample_rates[0] = avff->formats[0]; >> + if (!ctx->inputs[0]->out_samplerates) >> + if ((ret = ff_formats_ref(ff_make_format_list(sample_rates), >> + &ctx->inputs[0]->out_samplerates)) < 0) >> + return ret; >> + >> + sample_rates[0] = avff->formats[0] * s->factor; >> + return ff_formats_ref(ff_make_format_list(sample_rates), >> + &ctx->outputs[0]->in_samplerates); >> +} >> + >> +static int config_input(AVFilterLink *inlink) >> +{ >> + AVFilterContext *ctx = inlink->dst; >> + AudioUpSampleContext *s = ctx->priv; >> + >> + s->next_pts = AV_NOPTS_VALUE; >> + >> + return 0; >> +} >> + >> +static int filter_frame(AVFilterLink *inlink, AVFrame *in) >> +{ >> + AVFilterContext *ctx = inlink->dst; >> + AVFilterLink *outlink = ctx->outputs[0]; >> + AudioUpSampleContext *s = ctx->priv; >> + const int factor = s->factor; >> + AVFrame *out; >> + >> + if (s->factor == 1) >> + return ff_filter_frame(outlink, in); >> + >> + out = ff_get_audio_buffer(outlink, in->nb_samples * s->factor); >> + if (!out) { >> + av_frame_free(&in); >> + return AVERROR(ENOMEM); >> + } >> + >> + if (s->next_pts == AV_NOPTS_VALUE) >> + s->next_pts = in->pts; >> + >> + for (int c = 0; c < in->channels; c++) { >> + const double *src = (const double *)in->extended_data[c]; >> + double *dst = (double *)out->extended_data[c]; >> + >> + for (int n = 0; n < in->nb_samples; n++) >> + dst[n*factor] = src[n]; >> + } >> + >> + out->pts = s->next_pts; >> + s->next_pts += av_rescale_q(out->nb_samples, (AVRational){1, >> outlink->sample_rate}, outlink->time_base); >> + av_frame_free(&in); >> + return ff_filter_frame(ctx->outputs[0], out); >> +} >> + >> +static const AVFilterPad aupsample_inputs[] = { >> + { >> + .name = "default", >> + .type = AVMEDIA_TYPE_AUDIO, >> + .filter_frame = filter_frame, >> + .config_props = config_input, >> + }, >> + { NULL } >> +}; >> + >> +static const AVFilterPad aupsample_outputs[] = { >> + { >> + .name = "default", >> + .type = AVMEDIA_TYPE_AUDIO, >> + }, >> + { NULL } >> +}; >> + >> +AVFilter ff_af_aupsample = { >> + .name = "aupsample", >> + .description = NULL_IF_CONFIG_SMALL("Upsample >> audio by integer factor."), > > Is it faster? > Better quality? This is not same as resampling. This is used as part of other filtering. Namely when filter needs to oversample audio when processing - it then upsample audio before processing and downsample it by same factor after processing it.
Paul B Mahol (12019-04-19): > This is used as part of other filtering. Namely when filter needs to oversample > audio when processing - it then upsample audio before processing and downsample > it by same factor after processing it. How do you intend to implement that? Filters cannot call other filters.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> This is used as part of other filtering. Namely when filter needs to >> oversample >> audio when processing - it then upsample audio before processing and >> downsample >> it by same factor after processing it. > > How do you intend to implement that? Filters cannot call other filters. Users that know what they are doing will do: upsample=4,some additional filtering,alimiter=parameters,some additional filtering,downsample=4 This is already done by SoX.
Paul B Mahol (12019-04-19): > Users that know what they are doing will do: > > upsample=4,some additional filtering,alimiter=parameters,some > additional filtering,downsample=4 Bad design. We have sample rate negotiation. > This is already done by SoX. We are not SoX.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> Users that know what they are doing will do: >> >> upsample=4,some additional filtering,alimiter=parameters,some >> additional filtering,downsample=4 > > Bad design. We have sample rate negotiation. This is not about sample rate negotiation. > >> This is already done by SoX. > > We are not SoX. Bad argumentation. > > -- > Nicolas George > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Paul B Mahol (12019-04-19): > This is not about sample rate negotiation. Yes it is. > Bad argumentation. Then argue better. Patches rejected for now.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> This is not about sample rate negotiation. > > Yes it is. Give proof. No, you need to argue better your pathetic behavior. > >> Bad argumentation. > > Then argue better. > > Patches rejected for now. Look, you are full of shit. And know nothing about audio processing.
Paul B Mahol (12019-04-19):
> Look, you are full of shit.
Unacceptable. Excuses expected.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> Look, you are full of shit. > > Unacceptable. Excuses expected. I will ignore your one liners, snarky replies.
On 19-04-2019 02:43 PM, Nicolas George wrote: > Paul B Mahol (12019-04-19): >> Users that know what they are doing will do: >> >> upsample=4,some additional filtering,alimiter=parameters,some >> additional filtering,downsample=4 > Bad design. We have sample rate negotiation. How about a filter that can store link and/or frame props as metadata? This filter can be inserted before 'processing' filters. Then Paul's filters, inserted afterwards, can read those meta keys to obtain pre-process props. Gyan
On 4/19/19, Gyan <ffmpeg@gyani.pro> wrote: > > > On 19-04-2019 02:43 PM, Nicolas George wrote: >> Paul B Mahol (12019-04-19): >>> Users that know what they are doing will do: >>> >>> upsample=4,some additional filtering,alimiter=parameters,some >>> additional filtering,downsample=4 >> Bad design. We have sample rate negotiation. > > How about a filter that can store link and/or frame props as metadata? > This filter can be inserted before 'processing' filters. > > Then Paul's filters, inserted afterwards, can read those meta keys to > obtain pre-process props. There are numerous ways how oversampling/undersampling can be done. This two filters are fundamental blocks of oversampling/undersampling. The "some additional filtering" can be IIR or FIR lowpass, or FFT where anything above certain range is set to 0. All mentioned solutions have same good and bad points. Implementing this as part of existing filter is not flexible enough and will limit us to only some solutions also it needs more lines of code.
On Fri, Apr 19, 2019 at 11:34:04AM +0200, Paul B Mahol wrote: > On 4/19/19, Nicolas George <george@nsup.org> wrote: > > Paul B Mahol (12019-04-19): > >> This is not about sample rate negotiation. > > > > Yes it is. > > Give proof. > > No, you need to argue better your pathetic behavior. > > > > >> Bad argumentation. > > > > Then argue better. > > > > Patches rejected for now. > > Look, you are full of shit. And know nothing about audio processing. As i have been asked to look into this (and as we dont have many other ML admins currently) This is a technical mailing list, arguing about how much you love each other does not belong here. As a remainder Everyone, the subject of discussions should be FFmpeg and the technologies sorounding it. Insults, "Ad hominem" argumentation/attacks, and so on lead to a hostile climate that helps noone not even the one winning the argument eventually. If theres a disagreement on a patch (one wanting it in one not wanting it in and after technical discussion its not resolved), we can if everything else fails do a vote on the patch. A technical solution with technical arguments is better though than a vote. Thanks [...]
Michael Niedermayer (12019-04-19): > As i have been asked to look into this Not to look into this: to take action. > Everyone, the subject of discussions should be FFmpeg and the technologies > sorounding it. Insults, "Ad hominem" argumentation/attacks, and so on lead > to a hostile climate that helps noone not even the one winning the argument > eventually. Indeed. I will have a technical discussion about these patches, but not with somebody who insults me. Until I have reviewed and approved the patches, which cannot happen until the insults are gone for good, patches on lavfi are rejected. Regards,
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Michael Niedermayer (12019-04-19): >> As i have been asked to look into this > > Not to look into this: to take action. > >> Everyone, the subject of discussions should be FFmpeg and the >> technologies >> sorounding it. Insults, "Ad hominem" argumentation/attacks, and so on >> lead >> to a hostile climate that helps noone not even the one winning the >> argument >> eventually. > > Indeed. I will have a technical discussion about these patches, but not > with somebody who insults me. Until I have reviewed and approved the > patches, which cannot happen until the insults are gone for good, > patches on lavfi are rejected. What you actually want?
Paul B Mahol (12019-04-19):
> What you actually want?
I demand, that you behave in a civil manner.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> What you actually want? > > I demand, that you behave in a civil manner. I'm very civil here. If I'm not polite than that is because of your snarky comments. You already blocked several my patches for no apparent good reason. In the long run that hurts mostly users.
Paul B Mahol (12019-04-19):
> I'm very civil here.
https://ffmpeg.org/pipermail/ffmpeg-devel/2019-April/242839.html
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> I'm very civil here. > > https://ffmpeg.org/pipermail/ffmpeg-devel/2019-April/242839.html I'm really sorry if that hurt you.
Paul B Mahol (12019-04-19):
> I'm really sorry if that hurt you.
That's not excuses for the insult.
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> I'm really sorry if that hurt you. > > That's not excuses for the insult. I'm really sorry.
Paul B Mahol (12019-04-19):
> I'm really sorry.
For what, and what do you intend to do about it?
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> I'm really sorry. > > For what, and what do you intend to do about it? I'm really sorry for insulting you, and I will try to not repeat it.
Paul B Mahol (12019-04-19):
> I'm really sorry for insulting you, and I will try to not repeat it.
Accepted, although I have a feeling that "try" is weak.
Now, you have complained about what you call my "one liners". I do not
know if you realize, but I have adopted the policy of not wasting lines
to write to you because it is exactly the way you express yourself to me
and others most of the time. If you do not like when it comes to you, do
not send it to other people.
Now that this is clear, please explain in details why you think these
filters are necessary and not redundant with the generic resampling and
automatic format negotiation, and I will either stop my objections or
explain why I think you are mistaken.
Note that the effort you will take in making this discussion civil and
constructive will be taken as an indication on whether your excuses were
sincere or just a way of getting what you want. If in doubt, explain
more, not less.
Regards,
On 4/19/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> I'm really sorry for insulting you, and I will try to not repeat it. > > Accepted, although I have a feeling that "try" is weak. > > Now, you have complained about what you call my "one liners". I do not > know if you realize, but I have adopted the policy of not wasting lines > to write to you because it is exactly the way you express yourself to me > and others most of the time. If you do not like when it comes to you, do > not send it to other people. > > Now that this is clear, please explain in details why you think these > filters are necessary and not redundant with the generic resampling and > automatic format negotiation, and I will either stop my objections or > explain why I think you are mistaken. Generic resampling via aresample is completely another filtering that have nothing to do with this filters, for more info read: https://www.oblique-audio.com/technique/oversampling > > Note that the effort you will take in making this discussion civil and > constructive will be taken as an indication on whether your excuses were > sincere or just a way of getting what you want. If in doubt, explain > more, not less. > > Regards, > > -- > Nicolas George >
Paul B Mahol (12019-04-19): > Generic resampling via aresample is completely another filtering that have > nothing to do with this filters, for more info read: > > https://www.oblique-audio.com/technique/oversampling Quite the opposite: this page makes it rather clear that oversampling is a kind of resampling, with specific settings to ensure particular properties of the spectrum. As such, it should go into the generic resampling filter (or even library), enabled by options. That way, it is available not only explicitly from expert users but also automatically, when filters declare specific samples rates. Regards,
On 4/21/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-19): >> Generic resampling via aresample is completely another filtering that >> have >> nothing to do with this filters, for more info read: >> >> https://www.oblique-audio.com/technique/oversampling > > Quite the opposite: this page makes it rather clear that oversampling is > a kind of resampling, with specific settings to ensure particular > properties of the spectrum. It is not kind of resampling. Resampling is specific and belongs to separate library. The oversampling is another thing, and doing only upsampling/downsampling via libswresample is fragile/incomplete, as you need some kind of lowpass. (be it IIR, FIR or simple FFT) after upsample and before downsample. That is why it best fit into lavfi because it is just one block of processing with multiple solutions. And not one way do it all solution, set once and forget what it does. > > As such, it should go into the generic resampling filter (or even > library), enabled by options. That way, it is available not only > explicitly from expert users but also automatically, when filters > declare specific samples rates. Does not make sense to provide this into libswresample library. Also how that could be exported? It does not belong there. It would just confuse users, more because it supports only integer factor multiplication/divide of rates.
I apperciate the efforts to reply more than half a line. Paul B Mahol (12019-04-21): > It is not kind of resampling. Resampling is specific and belongs to > separate library. There is no doubt it IS a kind of resampling: it is in the name. The question is whether is it specific enough to warrant a separate interface. > The oversampling is another thing, and doing only upsampling/downsampling > via libswresample is fragile/incomplete, as you need some kind of lowpass. > (be it IIR, FIR or simple FFT) after upsample and before downsample. There are various way of doing a resampling with various properties. This is just another one. > That is why it best fit into lavfi because it is just one block of > processing with multiple solutions. Making it a separate filter is the easy solution, but not the good one. It is reporting all the choices to later or the end user. That makes for easy quick code now, but terrible use later. > Also how that could be exported? It does not belong there. Options. We already have them, just add a few. And in that case, it becomes accessible for all filters. Regards,
On 4/21/19, Nicolas George <george@nsup.org> wrote: > I apperciate the efforts to reply more than half a line. > > Paul B Mahol (12019-04-21): >> It is not kind of resampling. Resampling is specific and belongs to >> separate library. > > There is no doubt it IS a kind of resampling: it is in the name. The > question is whether is it specific enough to warrant a separate > interface. https://dspguru.com/dsp/faqs/multirate/resampling/ Resampling involves interpolation. If I do resampling with aresample and resampling with factor 2 from 44100 to 88200 I can see there is still some spectrum data in highest frequencies. > >> The oversampling is another thing, and doing only upsampling/downsampling >> via libswresample is fragile/incomplete, as you need some kind of >> lowpass. >> (be it IIR, FIR or simple FFT) after upsample and before downsample. > > There are various way of doing a resampling with various properties. > This is just another one. If you haven't noticed, this is just upsampling/downsampling without lowpass. And that is not resampling in any way. > >> That is why it best fit into lavfi because it is just one block of >> processing with multiple solutions. > > Making it a separate filter is the easy solution, but not the good one. > It is reporting all the choices to later or the end user. That makes for > easy quick code now, but terrible use later. That is just your opinion now, you need to provide technical terms to support your statements. > >> Also how that could be exported? It does not belong there. > > Options. We already have them, just add a few. And in that case, it > becomes accessible for all filters. Another option to aresample filter would just confuse users. Two options which would set rate with completely different outcome.
Paul B Mahol (12019-04-21): > https://dspguru.com/dsp/faqs/multirate/resampling/ > > Resampling involves interpolation. > If I do resampling with aresample and resampling with factor 2 from > 44100 to 88200 > I can see there is still some spectrum data in highest frequencies. Resampling MAY involve interpolation, to enhance the subjective quality of the output. > If you haven't noticed, this is just upsampling/downsampling without lowpass. > And that is not resampling in any way. No matter how many times you repeat it, saying that changing the sample rate is not resampling will not make it true. > That is just your opinion now, you need to provide technical terms > to support your statements. I have given technical considerations: we have automatic sample rate negotiation. These filter would not fit with it. What have you provided besides your opinion and links to generic considerations that do not substantiate your views? > Another option to aresample filter would just confuse users. Less so than yet another pair of filters that do almost exactly the same thing as others. Regards,
On 4/22/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-21): >> https://dspguru.com/dsp/faqs/multirate/resampling/ >> >> Resampling involves interpolation. >> If I do resampling with aresample and resampling with factor 2 from >> 44100 to 88200 >> I can see there is still some spectrum data in highest frequencies. > > Resampling MAY involve interpolation, to enhance the subjective quality > of the output. It is not MAY, it MUST involve interpolation in almost any scenario. > >> If you haven't noticed, this is just upsampling/downsampling without >> lowpass. >> And that is not resampling in any way. > > No matter how many times you repeat it, saying that changing the sample > rate is not resampling will not make it true. By your flawed reasoning asetrate filter is doing resamping too. > >> That is just your opinion now, you need to provide technical terms >> to support your statements. > > I have given technical considerations: we have automatic sample rate > negotiation. These filter would not fit with it. If you haven't tried them, they fit well with sample rate negotiation. Filters change sample rate metadata by integer factor up or down. > > What have you provided besides your opinion and links to generic > considerations that do not substantiate your views? I have provided actual facts, and not opinions unlike you. > >> Another option to aresample filter would just confuse users. > > Less so than yet another pair of filters that do almost exactly the same > thing as others. No filter in libavfilter does what those filters do. And there is reason why SoX have those as separate filters and not some strange combination with their generic resampling effect.
On 4/22/19, Paul B Mahol <onemda@gmail.com> wrote: > On 4/22/19, Nicolas George <george@nsup.org> wrote: >> Paul B Mahol (12019-04-21): >>> https://dspguru.com/dsp/faqs/multirate/resampling/ >>> >>> Resampling involves interpolation. >>> If I do resampling with aresample and resampling with factor 2 from >>> 44100 to 88200 >>> I can see there is still some spectrum data in highest frequencies. >> >> Resampling MAY involve interpolation, to enhance the subjective quality >> of the output. > > It is not MAY, it MUST involve interpolation in almost any scenario. > >> >>> If you haven't noticed, this is just upsampling/downsampling without >>> lowpass. >>> And that is not resampling in any way. >> >> No matter how many times you repeat it, saying that changing the sample >> rate is not resampling will not make it true. > > By your flawed reasoning asetrate filter is doing resamping too. > >> >>> That is just your opinion now, you need to provide technical terms >>> to support your statements. >> >> I have given technical considerations: we have automatic sample rate >> negotiation. These filter would not fit with it. > > If you haven't tried them, they fit well with sample rate negotiation. > Filters change sample rate metadata by integer factor up or down. > >> >> What have you provided besides your opinion and links to generic >> considerations that do not substantiate your views? > > I have provided actual facts, and not opinions unlike you. > >> >>> Another option to aresample filter would just confuse users. >> >> Less so than yet another pair of filters that do almost exactly the same >> thing as others. > > No filter in libavfilter does what those filters do. > > And there is reason why SoX have those as separate filters and not some > strange combination with their generic resampling effect. > As there appears to be no more comments or valid arguments against this set I will apply it.
Paul B Mahol (12019-04-25): > As there appears to be no more comments or valid arguments against this Saying it does not make it true. > set I will apply it. Do it and I will revert and ask that your commits rights be revoked.
On 4/25/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-25): >> As there appears to be no more comments or valid arguments against this > > Saying it does not make it true. You haven't replied any more, and nothing that you said earlier is valid. > >> set I will apply it. > > Do it and I will revert and ask that your commits rights be revoked. Michael, please remove Nicolas from committers as he want to revert my patches and do not have valid technical arguments for his actions.
Paul B Mahol (12019-04-25):
> You haven't replied any more, and nothing that you said earlier is valid.
I have stated: rejected until it plays well with sample rate
negotiation. You have not reacted to it.
On 4/25/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-25): >> You haven't replied any more, and nothing that you said earlier is valid. > > I have stated: rejected until it plays well with sample rate > negotiation. You have not reacted to it. I did reacted. It plays well with negotiation. Can you be more specific what exactly you mean by "plays well with sample rate negotiation"?
Paul B Mahol (12019-04-25): > I did reacted. It plays well with negotiation. I missed that part, sorry. But it did not address my concern. > Can you be more specific what exactly you mean by "plays well with > sample rate negotiation"? If the user judges that this is the kind of sample rate change that is necessary, then when the negotiation detects a sample rate change is necessary, these filters are used. Regards,
On Thu, Apr 25, 2019 at 7:25 PM Nicolas George <george@nsup.org> wrote: > > Paul B Mahol (12019-04-25): > > I did reacted. It plays well with negotiation. > > I missed that part, sorry. But it did not address my concern. > > > Can you be more specific what exactly you mean by "plays well with > > sample rate negotiation"? > > If the user judges that this is the kind of sample rate change that is > necessary, then when the negotiation detects a sample rate change is > necessary, these filters are used. > The point of this kind of filtering is not that they are necessary to perform filtering, because you can filter at any sample rate, but that oversampling for certain filters, and downsampling after, improves quality. As such, negotiation is not really equipped to handle it, since its designed to deal with compatibility between filters, not quality concerns, and you also wouldn't want to remove the ability to filter at ordinary sample rates either. - Hendrik
Hendrik Leppkes (12019-04-25): > The point of this kind of filtering is not that they are necessary to > perform filtering, because you can filter at any sample rate, but that > oversampling for certain filters, and downsampling after, improves > quality. As such, negotiation is not really equipped to handle it, > since its designed to deal with compatibility between filters, not > quality concerns, and you also wouldn't want to remove the ability to > filter at ordinary sample rates either. I do not want them to be available ONLY with negotiation. If people want to add them, fine. But when negotiation decides a conversion needs to happen somewhere, these treatments must be available for it, at the place where it is needed, which is often not known to the user. And the simplest way of achieving that is to make it an option of the resample filter, or even better, en option if lswr. After all, it is only the audio equivalent of sws_flags=neighbor. Regards,
On 4/25/19, Nicolas George <george@nsup.org> wrote: > Hendrik Leppkes (12019-04-25): >> The point of this kind of filtering is not that they are necessary to >> perform filtering, because you can filter at any sample rate, but that >> oversampling for certain filters, and downsampling after, improves >> quality. As such, negotiation is not really equipped to handle it, >> since its designed to deal with compatibility between filters, not >> quality concerns, and you also wouldn't want to remove the ability to >> filter at ordinary sample rates either. > > I do not want them to be available ONLY with negotiation. If people want > to add them, fine. > > But when negotiation decides a conversion needs to happen somewhere, > these treatments must be available for it, at the place where it is > needed, which is often not known to the user. > > And the simplest way of achieving that is to make it an option of the > resample filter, or even better, en option if lswr. After all, it is > only the audio equivalent of sws_flags=neighbor. The filter does not take sample rate as argument, but integer factor instead. So that make it impossible to be used with lswr.
Paul B Mahol (12019-04-25): > The filter does not take sample rate as argument, but integer factor instead. > So that make it impossible to be used with lswr. No need for an argument: the filter knows the negotiated input and output sample rate.
On 4/25/19, Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-25): >> The filter does not take sample rate as argument, but integer factor >> instead. >> So that make it impossible to be used with lswr. > > No need for an argument: the filter knows the negotiated input and > output sample rate. Not really, it works with 2x/3x/4x/5x.. sample rate or 1/2 / 1/3 / 1/4 / 1/5 o sample rate in other direction. It can not be done in aresample filter because of limitations of query_formats code in libavfilter and doing it anyway for aresample filter would cause many regressions.
Paul B Mahol (12019-04-25): > Not really, it works with 2x/3x/4x/5x.. sample rate or 1/2 / 1/3 / 1/4 / 1/5 > o sample rate in other direction. I do not think so: the algorithm can work for absolutely any ratio. The effect on the spectrum will not be as clean if the ratio is not an integer, but that is another problem. > It can not be done in aresample filter because of limitations of query_formats > code in libavfilter Please elaborate. > and doing it anyway for aresample filter would > cause many regressions. I do not think so. Please elaborate.
On Thu, Apr 25, 2019 at 9:14 PM Nicolas George <george@nsup.org> wrote: > Paul B Mahol (12019-04-25): > > Not really, it works with 2x/3x/4x/5x.. sample rate or 1/2 / 1/3 / 1/4 / > 1/5 > > o sample rate in other direction. > > I do not think so: the algorithm can work for absolutely any ratio. The > effect on the spectrum will not be as clean if the ratio is not an > integer, but that is another problem. > > > It can not be done in aresample filter because of limitations of > query_formats > > code in libavfilter > > Please elaborate. > > > and doing it anyway for aresample filter would > > cause many regressions. > > I do not think so. Please elaborate. > I really lost any motivation to deal with Nicolas George behavior. So I please ask again for TC to deal with this. There are too many great patches lost because of his behavior.
On Sun, Oct 25, 2020 at 1:41 PM Paul B Mahol <onemda@gmail.com> wrote: > > > On Thu, Apr 25, 2019 at 9:14 PM Nicolas George <george@nsup.org> wrote: > >> Paul B Mahol (12019-04-25): >> > Not really, it works with 2x/3x/4x/5x.. sample rate or 1/2 / 1/3 / 1/4 >> / 1/5 >> > o sample rate in other direction. >> >> I do not think so: the algorithm can work for absolutely any ratio. The >> effect on the spectrum will not be as clean if the ratio is not an >> integer, but that is another problem. >> >> > It can not be done in aresample filter because of limitations of >> query_formats >> > code in libavfilter >> >> Please elaborate. >> >> > and doing it anyway for aresample filter would >> > cause many regressions. >> >> I do not think so. Please elaborate. >> > > I really lost any motivation to deal with Nicolas George behavior. > So I please ask again for TC to deal with this. > There are too many great patches lost because of his behavior. > I still want that TC and CC take this into reconsidering.
diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 682df45ef5..a38bc35231 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o framesync.o OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o OBJS-$(CONFIG_ATRIM_FILTER) += trim.o +OBJS-$(CONFIG_AUPSAMPLE_FILTER) += af_aupsample.o OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o diff --git a/libavfilter/af_aupsample.c b/libavfilter/af_aupsample.c new file mode 100644 index 0000000000..ee35b9c0c6 --- /dev/null +++ b/libavfilter/af_aupsample.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * 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 + */ + +#include "libavutil/opt.h" +#include "libavutil/samplefmt.h" +#include "avfilter.h" +#include "audio.h" +#include "filters.h" +#include "internal.h" + +typedef struct AudioUpSampleContext { + const AVClass *class; + int factor; + + int64_t next_pts; +} AudioUpSampleContext; + +#define OFFSET(x) offsetof(AudioUpSampleContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption aupsample_options[] = { + { "factor", "set upsampling factor", OFFSET(factor), AV_OPT_TYPE_INT, {.i64=1}, 1, 64, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aupsample); + +static int query_formats(AVFilterContext *ctx) +{ + AudioUpSampleContext *s = ctx->priv; + AVFilterChannelLayouts *layouts; + AVFilterFormats *formats; + int sample_rates[] = { 44100, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + AVFilterFormats *avff; + int ret; + + if (!ctx->inputs[0]->in_samplerates || + !ctx->inputs[0]->in_samplerates->nb_formats) { + return AVERROR(EAGAIN); + } + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + avff = ctx->inputs[0]->in_samplerates; + sample_rates[0] = avff->formats[0]; + if (!ctx->inputs[0]->out_samplerates) + if ((ret = ff_formats_ref(ff_make_format_list(sample_rates), + &ctx->inputs[0]->out_samplerates)) < 0) + return ret; + + sample_rates[0] = avff->formats[0] * s->factor; + return ff_formats_ref(ff_make_format_list(sample_rates), + &ctx->outputs[0]->in_samplerates); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioUpSampleContext *s = ctx->priv; + + s->next_pts = AV_NOPTS_VALUE; + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioUpSampleContext *s = ctx->priv; + const int factor = s->factor; + AVFrame *out; + + if (s->factor == 1) + return ff_filter_frame(outlink, in); + + out = ff_get_audio_buffer(outlink, in->nb_samples * s->factor); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + + if (s->next_pts == AV_NOPTS_VALUE) + s->next_pts = in->pts; + + for (int c = 0; c < in->channels; c++) { + const double *src = (const double *)in->extended_data[c]; + double *dst = (double *)out->extended_data[c]; + + for (int n = 0; n < in->nb_samples; n++) + dst[n*factor] = src[n]; + } + + out->pts = s->next_pts; + s->next_pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + av_frame_free(&in); + return ff_filter_frame(ctx->outputs[0], out); +} + +static const AVFilterPad aupsample_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad aupsample_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_aupsample = { + .name = "aupsample", + .description = NULL_IF_CONFIG_SMALL("Upsample audio by integer factor."), + .query_formats = query_formats, + .priv_size = sizeof(AudioUpSampleContext), + .priv_class = &aupsample_class, + .inputs = aupsample_inputs, + .outputs = aupsample_outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 4d3039d6ba..29b372a1db 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -78,6 +78,7 @@ extern AVFilter ff_af_astats; extern AVFilter ff_af_astreamselect; extern AVFilter ff_af_atempo; extern AVFilter ff_af_atrim; +extern AVFilter ff_af_aupsample; extern AVFilter ff_af_azmq; extern AVFilter ff_af_bandpass; extern AVFilter ff_af_bandreject;
Signed-off-by: Paul B Mahol <onemda@gmail.com> --- libavfilter/Makefile | 1 + libavfilter/af_aupsample.c | 159 +++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + 3 files changed, 161 insertions(+) create mode 100644 libavfilter/af_aupsample.c