1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-15 14:13:16 +02:00

avfilter: add acontrast filter

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol
2017-11-18 10:28:27 +01:00
parent 0ecb1c53c8
commit e679ac8d7c
6 changed files with 233 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ version <next>:
- NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-2, VC1 and VP9 hwaccel decoding - NVIDIA NVDEC-accelerated H.264, HEVC, MPEG-2, VC1 and VP9 hwaccel decoding
- Intel QSV-accelerated overlay filter - Intel QSV-accelerated overlay filter
- mcompand audio filter - mcompand audio filter
- acontrast audio filter
version 3.4: version 3.4:

View File

@@ -429,6 +429,16 @@ How much to use compressed signal in output. Default is 1.
Range is between 0 and 1. Range is between 0 and 1.
@end table @end table
@section acontrast
Simple audio dynamic range commpression/expansion filter.
The filter accepts the following options:
@table @option
@item contrast
Set contrast. Default is 33. Allowed range is between 0 and 100.
@end table
@section acopy @section acopy
Copy the input audio source unchanged to the output. This is mainly useful for Copy the input audio source unchanged to the output. This is mainly useful for

View File

@@ -31,6 +31,7 @@ OBJS-$(CONFIG_QSVVPP) += qsvvpp.o
# audio filters # audio filters
OBJS-$(CONFIG_ABENCH_FILTER) += f_bench.o OBJS-$(CONFIG_ABENCH_FILTER) += f_bench.o
OBJS-$(CONFIG_ACOMPRESSOR_FILTER) += af_sidechaincompress.o OBJS-$(CONFIG_ACOMPRESSOR_FILTER) += af_sidechaincompress.o
OBJS-$(CONFIG_ACONTRAST_FILTER) += af_acontrast.o
OBJS-$(CONFIG_ACOPY_FILTER) += af_acopy.o OBJS-$(CONFIG_ACOPY_FILTER) += af_acopy.o
OBJS-$(CONFIG_ACROSSFADE_FILTER) += af_afade.o OBJS-$(CONFIG_ACROSSFADE_FILTER) += af_afade.o
OBJS-$(CONFIG_ACRUSHER_FILTER) += af_acrusher.o OBJS-$(CONFIG_ACRUSHER_FILTER) += af_acrusher.o

219
libavfilter/af_acontrast.c Normal file
View File

@@ -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[] = {
{ "contrast", "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++) {
float d = src[c] * M_PI_2;
dst[c] = sinf(d + contrast * sinf(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++) {
float d = src[n] * M_PI_2;
dst[n] = sinf(d + contrast * sinf(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,
};

View File

@@ -42,6 +42,7 @@ static void register_all(void)
{ {
REGISTER_FILTER(ABENCH, abench, af); REGISTER_FILTER(ABENCH, abench, af);
REGISTER_FILTER(ACOMPRESSOR, acompressor, af); REGISTER_FILTER(ACOMPRESSOR, acompressor, af);
REGISTER_FILTER(ACONTRAST, acontrast, af);
REGISTER_FILTER(ACOPY, acopy, af); REGISTER_FILTER(ACOPY, acopy, af);
REGISTER_FILTER(ACROSSFADE, acrossfade, af); REGISTER_FILTER(ACROSSFADE, acrossfade, af);
REGISTER_FILTER(ACRUSHER, acrusher, af); REGISTER_FILTER(ACRUSHER, acrusher, af);

View File

@@ -30,7 +30,7 @@
#include "libavutil/version.h" #include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MAJOR 7
#define LIBAVFILTER_VERSION_MINOR 1 #define LIBAVFILTER_VERSION_MINOR 2
#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \