diff options
author | Paul B Mahol <onemda@gmail.com> | 2020-11-05 13:33:32 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2020-11-10 15:25:18 +0100 |
commit | ee4a04654014e24f47f5a31265fb3bde6fad8ce6 (patch) | |
tree | 231f1ea2a94cf6370cf307a6b2e00ed0e82787b6 | |
parent | 7e8306dd2da54fa499ea79a74f0ba81507e6c9d4 (diff) | |
download | ffmpeg-ee4a04654014e24f47f5a31265fb3bde6fad8ce6.tar.gz |
avfilter/af_asoftclip: add oversampling support
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | doc/filters.texi | 3 | ||||
-rw-r--r-- | libavfilter/af_asoftclip.c | 106 |
3 files changed, 103 insertions, 7 deletions
@@ -3501,6 +3501,7 @@ afir_filter_deps="avcodec" afir_filter_select="rdft" amovie_filter_deps="avcodec avformat" aresample_filter_deps="swresample" +asoftclip_filter_deps="swresample" asr_filter_deps="pocketsphinx" ass_filter_deps="libass" atempo_filter_deps="avcodec" diff --git a/doc/filters.texi b/doc/filters.texi index 40f8f614fe..8380f6cac2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2356,6 +2356,9 @@ It accepts the following values: @item param Set additional parameter which controls sigmoid function. + +@item oversample +Set oversampling factor. @end table @subsection Commands diff --git a/libavfilter/af_asoftclip.c b/libavfilter/af_asoftclip.c index ce1f7ea96a..aaae3c6d4b 100644 --- a/libavfilter/af_asoftclip.c +++ b/libavfilter/af_asoftclip.c @@ -21,6 +21,7 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" +#include "libswresample/swresample.h" #include "avfilter.h" #include "audio.h" #include "formats.h" @@ -42,14 +43,22 @@ typedef struct ASoftClipContext { const AVClass *class; int type; + int oversample; + int64_t delay; double param; + SwrContext *up_ctx; + SwrContext *down_ctx; + + AVFrame *frame; + void (*filter)(struct ASoftClipContext *s, void **dst, const void **src, int nb_samples, int channels, int start, int end); } ASoftClipContext; #define OFFSET(x) offsetof(ASoftClipContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define F AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption asoftclip_options[] = { { "type", "set softclip type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, -1, NB_TYPES-1, A, "types" }, @@ -63,6 +72,7 @@ static const AVOption asoftclip_options[] = { { "sin", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_SIN}, 0, 0, A, "types" }, { "erf", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_ERF}, 0, 0, A, "types" }, { "param", "set softclip parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 3, A }, + { "oversample", "set oversample factor", OFFSET(oversample), AV_OPT_TYPE_INT, {.i64=1}, 1, 32, F }, { NULL } }; @@ -242,6 +252,7 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ASoftClipContext *s = ctx->priv; + int ret; switch (inlink->format) { case AV_SAMPLE_FMT_FLT: @@ -251,6 +262,38 @@ static int config_input(AVFilterLink *inlink) default: av_assert0(0); } + if (s->oversample <= 1) + return 0; + + s->up_ctx = swr_alloc(); + s->down_ctx = swr_alloc(); + if (!s->up_ctx || !s->down_ctx) + return AVERROR(ENOMEM); + + av_opt_set_int(s->up_ctx, "in_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->up_ctx, "in_sample_rate", inlink->sample_rate, 0); + av_opt_set_sample_fmt(s->up_ctx, "in_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->up_ctx, "out_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->up_ctx, "out_sample_rate", inlink->sample_rate * s->oversample, 0); + av_opt_set_sample_fmt(s->up_ctx, "out_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->down_ctx, "in_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->down_ctx, "in_sample_rate", inlink->sample_rate * s->oversample, 0); + av_opt_set_sample_fmt(s->down_ctx, "in_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->down_ctx, "out_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->down_ctx, "out_sample_rate", inlink->sample_rate, 0); + av_opt_set_sample_fmt(s->down_ctx, "out_sample_fmt", inlink->format, 0); + + ret = swr_init(s->up_ctx); + if (ret < 0) + return ret; + + ret = swr_init(s->down_ctx); + if (ret < 0) + return ret; + return 0; } @@ -280,8 +323,9 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; + ASoftClipContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - int nb_samples, channels; + int ret, nb_samples, channels; ThreadData td; AVFrame *out; @@ -304,17 +348,64 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) channels = 1; } - td.in = in; - td.out = out; - td.nb_samples = nb_samples; - td.channels = channels; - ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(channels, - ff_filter_get_nb_threads(ctx))); + if (s->oversample > 1) { + s->frame = ff_get_audio_buffer(outlink, in->nb_samples * s->oversample); + if (!s->frame) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = swr_convert(s->up_ctx, (uint8_t**)s->frame->extended_data, in->nb_samples * s->oversample, + (const uint8_t **)in->extended_data, in->nb_samples); + if (ret < 0) + goto fail; + + td.in = s->frame; + td.out = s->frame; + td.nb_samples = av_sample_fmt_is_planar(in->format) ? ret : ret * in->channels; + td.channels = channels; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(channels, + ff_filter_get_nb_threads(ctx))); + + ret = swr_convert(s->down_ctx, (uint8_t**)out->extended_data, out->nb_samples, + (const uint8_t **)s->frame->extended_data, ret); + if (ret < 0) + goto fail; + + if (out->pts) + out->pts -= s->delay; + s->delay += in->nb_samples - ret; + out->nb_samples = ret; + + av_frame_free(&s->frame); + } else { + td.in = in; + td.out = out; + td.nb_samples = nb_samples; + td.channels = channels; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(channels, + ff_filter_get_nb_threads(ctx))); + } if (out != in) av_frame_free(&in); return ff_filter_frame(outlink, out); +fail: + if (out != in) + av_frame_free(&out); + av_frame_free(&in); + av_frame_free(&s->frame); + + return ret; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ASoftClipContext *s = ctx->priv; + + swr_free(&s->up_ctx); + swr_free(&s->down_ctx); } static const AVFilterPad inputs[] = { @@ -343,6 +434,7 @@ AVFilter ff_af_asoftclip = { .priv_class = &asoftclip_class, .inputs = inputs, .outputs = outputs, + .uninit = uninit, .process_command = ff_filter_process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, |