From patchwork Sat Nov 18 10:44:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 6163 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.94 with SMTP id m30csp1684485jah; Sat, 18 Nov 2017 02:45:03 -0800 (PST) X-Google-Smtp-Source: AGs4zMbvn3aLSZoCqgArk3jIHFdykE1L6OkQhw06fvzutNCuxFwagQUsw+XnPjyGUB5HKZDNbdV+ X-Received: by 10.223.195.103 with SMTP id e36mr6887767wrg.10.1511001903503; Sat, 18 Nov 2017 02:45:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511001903; cv=none; d=google.com; s=arc-20160816; b=TIOQH7oWUQkFLGpv7kz/ZhNfJ2R9EwSVUMKyTIbBuw5WjRo97EFHw/Mf3VNzmYLONm A/5GkTbZUFFl/WmUinGJDIWj358TW+w5FcHw+siuv2YotxqVFBaZeQkTBkpeQf/khMCh 8ypDhrg1Ztoo3Gdd/MS33ml74YFkrhizeKuexjxVbLw6cpi1M9y8qih0SB6WhijjVXwh uVCS8vF5R1gKDRoi66gYQnVgfEyS56Vheb1QQ/ce1inL2WiOv8ZfrXslJr0XS6cPMHvp ZCFrSlPq+D47hNPCTSGTI4U3pAWOOv/+PUxMUVxO9+u7S+cHLvIlT8GohYuqbXPYpSv1 mubg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=95VJF8CJO68upvzXvT0alyPJybXXShAXoaPQexlZ0T4=; b=C9Std7aFRLG+ju5WTD0ewCr/5MOH3wBo8eyTDzTXzQ7CdibLtJ3/lHTIeUSshjwhkT 0frhBaLIBnHLW7ZRO4aY3aM0IhViJJSyvQUHWO+wD5eMDeU1N24Bs5Z/rMI+C9ECHMwr xmHEB+6FljdWTFRsNFSJhsLAK2eSh/Ej/8R+exifmcTVyGfrT+2O8qfWyzxrrpmbQICj Iqq7iBm3CWQGlzDdyia7sMm4H5jsLxci+HsajlgKc+sbr2Ozm0QqsxK/gq840MVXRssU 6r2y5pg+OHk5QqwKPX/WQ06yIg6+u96EmjLrXeIAsCUlMt5aOp+9rPWT9vlohEkHFtj5 eASA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=nWY02nzE; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id k140si4124646wmd.38.2017.11.18.02.45.02; Sat, 18 Nov 2017 02:45:03 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=nWY02nzE; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 77719689E70; Sat, 18 Nov 2017 12:44:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f54.google.com (mail-wm0-f54.google.com [74.125.82.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 64B06689A47 for ; Sat, 18 Nov 2017 12:44:39 +0200 (EET) Received: by mail-wm0-f54.google.com with SMTP id 128so2143842wmo.3 for ; Sat, 18 Nov 2017 02:44:56 -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=qe6sAnn4Nsug9RHfYuw0aip8csyvYJwTcODmX/DsYcI=; b=nWY02nzEOcbElUlcmSzMMU8V8tPSdN+p0cM7Y1VeUNAvXwnNDfaXOdUeeMRgk5Qt8v w7yb/SavQbsAsLWw5MegpV77qbYbXj9fm5k8IgPVE3vWklm5TySxmA3AdU5ANGv5d05I CYFeDXxL2Wac59xgSQLYNdt3amE9lWLeycRFARXuCIldpZ5zJitW6r9eMgxC4NcqWOV8 6vBL8kr4fBfFrM4tJGF15MpmI5spS97cU3UqE+obOtkKyCAHhCCmCKu7mk03/9nzoWCW WBVjrIdrRd4dAe/1jqSwiIZz/hrxHR04IcTXwHSsmkN1RYpq/45mdwbFX9jGdKeUCWzy zv3w== 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=qe6sAnn4Nsug9RHfYuw0aip8csyvYJwTcODmX/DsYcI=; b=HT4ZpGVYJccTIXi64cpo57ZdkGSL8qgH87c64dU2AqPCY8kYG61KMdy3w8a0K71Hwn +eS7cvZQyphqf95EuJeVLCx+xYL2vLVrxSpwvcBw5YyMjgHgIgGaaji2gFP4rJBljRz2 c4dU9bBz/Gt3yy+Km/nAmPLNsyWXUUGWrhtdyhkexF60TEdv9YrGr+tVRhCkWzCn30FR GLIYgKam2iPwQRpDA7/dmWuY0gayX3gjD6JkqBEIHon+ifZMOZ+4j2RkgWuzBhRmrqLW 5k9c4C6WJA/lRO8XSillWeUfsOda4czq+kG9ey1SY/20gN4F6BNRgAlKNi/5qs3b41vi lqCA== X-Gm-Message-State: AJaThX44E4ienffCU3/8tJTHp1O7bj8TF59gUKis/Zu5+tINECiU9BUS E7IyB6UXOUEzgqZli2tHLBRVJQ== X-Received: by 10.80.245.181 with SMTP id u50mr11191798edm.171.1511001895216; Sat, 18 Nov 2017 02:44:55 -0800 (PST) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id z23sm4366305edm.62.2017.11.18.02.44.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 18 Nov 2017 02:44:54 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sat, 18 Nov 2017 11:44:10 +0100 Message-Id: <20171118104410.1508-1-onemda@gmail.com> X-Mailer: git-send-email 2.11.0 Subject: [FFmpeg-devel] [PATCH] avfilter: add acontrast filter 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 --- doc/filters.texi | 10 +++ libavfilter/Makefile | 1 + libavfilter/af_acontrast.c | 219 +++++++++++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + 4 files changed, 231 insertions(+) create mode 100644 libavfilter/af_acontrast.c diff --git a/doc/filters.texi b/doc/filters.texi index 5d99437871..e35952510b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -429,6 +429,16 @@ How much to use compressed signal in output. Default is 1. Range is between 0 and 1. @end table +@section acontrast +Simple audio dynamic range commpression/expansion filter. + +The filter accepts the following options: + +@table @option +@item c +Set contrast. Default is 33. Allowed range is between 0 and 100. +@end table + @section acopy Copy the input audio source unchanged to the output. This is mainly useful for diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 9acae3ff5b..71c6333a52 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -31,6 +31,7 @@ OBJS-$(CONFIG_QSVVPP) += qsvvpp.o # audio filters OBJS-$(CONFIG_ABENCH_FILTER) += f_bench.o OBJS-$(CONFIG_ACOMPRESSOR_FILTER) += af_sidechaincompress.o +OBJS-$(CONFIG_ACONTRAST_FILTER) += af_acontrast.o OBJS-$(CONFIG_ACOPY_FILTER) += af_acopy.o OBJS-$(CONFIG_ACROSSFADE_FILTER) += af_afade.o OBJS-$(CONFIG_ACRUSHER_FILTER) += af_acrusher.o diff --git a/libavfilter/af_acontrast.c b/libavfilter/af_acontrast.c new file mode 100644 index 0000000000..38de08ffe5 --- /dev/null +++ b/libavfilter/af_acontrast.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2008 Rob Sykes + * Copyright (c) 2017 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/channel_layout.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct AudioContrastContext { + const AVClass *class; + float contrast; + void (*filter)(void **dst, const void **src, + int nb_samples, int channels, float contrast); +} AudioContrastContext; + +#define OFFSET(x) offsetof(AudioContrastContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption acontrast_options[] = { + { "c", "set contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl=33}, 0, 100, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(acontrast); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int 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; + + 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_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static void filter_flt(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + const float *src = s[0]; + float *dst = d[0]; + int n, c; + + for (n = 0; n < nb_samples; n++) { + for (c = 0; c < channels; c++) { + double d = src[c] * M_PI_2; + + dst[c] = sin(d + contrast * sin(d * 4)); + } + + dst += c; + src += c; + } +} + +static void filter_dbl(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + const double *src = s[0]; + double *dst = d[0]; + int n, c; + + for (n = 0; n < nb_samples; n++) { + for (c = 0; c < channels; c++) { + double d = src[c] * M_PI_2; + + dst[c] = sin(d + contrast * sin(d * 4)); + } + + dst += c; + src += c; + } +} + +static void filter_fltp(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + int n, c; + + for (c = 0; c < channels; c++) { + const float *src = s[c]; + float *dst = d[c]; + + for (n = 0; n < nb_samples; n++) { + double d = src[n] * M_PI_2; + + dst[n] = sin(d + contrast * sin(d * 4)); + } + } +} + +static void filter_dblp(void **d, const void **s, + int nb_samples, int channels, + float contrast) +{ + int n, c; + + for (c = 0; c < channels; c++) { + const double *src = s[c]; + double *dst = d[c]; + + for (n = 0; n < nb_samples; n++) { + double d = src[n] * M_PI_2; + + dst[n] = sin(d + contrast * sin(d * 4)); + } + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioContrastContext *s = ctx->priv; + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLT: s->filter = filter_flt; break; + case AV_SAMPLE_FMT_DBL: s->filter = filter_dbl; break; + case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioContrastContext *s = ctx->priv; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(inlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + s->filter((void **)out->extended_data, (const void **)in->extended_data, + in->nb_samples, in->channels, s->contrast / 750); + + if (out != in) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_acontrast = { + .name = "acontrast", + .description = NULL_IF_CONFIG_SMALL("Simple audio dynamic range compression/expansion filter."), + .query_formats = query_formats, + .priv_size = sizeof(AudioContrastContext), + .priv_class = &acontrast_class, + .inputs = inputs, + .outputs = outputs, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index a838309569..6d92b3ab5a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -42,6 +42,7 @@ static void register_all(void) { REGISTER_FILTER(ABENCH, abench, af); REGISTER_FILTER(ACOMPRESSOR, acompressor, af); + REGISTER_FILTER(ACONTRAST, acontrast, af); REGISTER_FILTER(ACOPY, acopy, af); REGISTER_FILTER(ACROSSFADE, acrossfade, af); REGISTER_FILTER(ACRUSHER, acrusher, af);