From patchwork Thu Nov 5 12:36:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 23399 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 2FD3144BB73 for ; Thu, 5 Nov 2020 14:42:16 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0BE8468B72C; Thu, 5 Nov 2020 14:42:16 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f67.google.com (mail-ej1-f67.google.com [209.85.218.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7D6B568A8B9 for ; Thu, 5 Nov 2020 14:42:09 +0200 (EET) Received: by mail-ej1-f67.google.com with SMTP id s25so2405164ejy.6 for ; Thu, 05 Nov 2020 04:42:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=Z7gjwXO5rwrYyyLudtfCy2/FYBROGziEvaQEUmMOCJM=; b=XcKT9INIyxMRHQHYntk5RqcZqcr7TV/xkz7LKglx1GIa6cp+WVAaIVrkYZcxvsJDSq ZXCdjLsKD/LQCJDuU8zds96jSHJg4niOO6WW5DuMqDKb6NUr+UNOx8WxQqvurKzrEVNG rRXRo/FkJMTyuoClCcuJuiI3wC0bpZ0Al/JqNjJAd9bpJ/eb+xainxZau5WwX6nzv7ma JZyCYDF0BOiXbKwhUUF98SiXI7RJZWL7C6TPtmknUKP3ktXe7/2OPT880z++TKWNrLHC YpnQM+QdpuGxD40BFiRKXlpc6cfp1gmMYr7FXLm2xOEBpXJGKFlqN1tmi4FFVKiMwS1r CZZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=Z7gjwXO5rwrYyyLudtfCy2/FYBROGziEvaQEUmMOCJM=; b=SsGy7ewNhEz6hRnjsuOm9K6CkuzV+lcIXWiQPyyYSDrWacS7FbPUsHoE/RRyg+rPk5 YJvL1Q1MQlAPeVh8CZ/6XkMnt5m+Y7J3NSslZ/npb6BLvGDK20z1Z1BgVODz8MQLjwFy SXhIDFCERHeza1qlXK+Rfq4r4RgUy5vumHQvjBsjARImbeZCuRfbV65uS87c7cId79xD Xz7toHPNTUeXY2JidKx/u3SOED9rlNxop2Sc4pYHlECR2fO2JyeseWgmQtcocTmQdZQ+ ExYlVdx/nSyjBVLm4MNEnCefC9PbWRT99RdftLwoveMxYs6qAdcbem5RNwhVpv7BUhLf uKxw== X-Gm-Message-State: AOAM531+qpj1ADjavrPpIjIfcG/eOSP3Q/XtcMx5arufkzi/JVqGnYtd cKpO06Pwof1W4yJmDz218VkkHUQjLEsqpA== X-Google-Smtp-Source: ABdhPJxFhdo4/iPE/EitxhG1wd4EzOctW+mCP6kMFlEkFeKIXHwT7U9Itogc8/PSJ/tZMJcc8k7lDA== X-Received: by 2002:a17:906:d41:: with SMTP id r1mr1993853ejh.383.1604579813971; Thu, 05 Nov 2020 04:36:53 -0800 (PST) Received: from localhost.localdomain ([77.237.107.67]) by smtp.gmail.com with ESMTPSA id d10sm856834ejw.44.2020.11.05.04.36.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Nov 2020 04:36:53 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Thu, 5 Nov 2020 13:36:44 +0100 Message-Id: <20201105123644.13223-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] avfilter/af_asoftclip: add oversampling support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- configure | 1 + doc/filters.texi | 3 ++ libavfilter/af_asoftclip.c | 106 ++++++++++++++++++++++++++++++++++--- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 8a9e9b3cd7..2f02d7f5c8 100755 --- a/configure +++ b/configure @@ -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,