---
Made changes suggested by Diego and Loren.
libavfilter/af_volume.c | 35 ++++++-----------------
libavfilter/af_volume.h | 57 ++++++++++++++++++++++++++++++++++++++
libavfilter/x86/Makefile | 2 +
libavfilter/x86/af_volume.asm | 56 +++++++++++++++++++++++++++++++++++++
libavfilter/x86/af_volume_init.c | 38 +++++++++++++++++++++++++
5 files changed, 162 insertions(+), 26 deletions(-)
create mode 100644 libavfilter/af_volume.h
create mode 100644 libavfilter/x86/af_volume.asm
create mode 100644 libavfilter/x86/af_volume_init.c
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 7a6cefb..21f4b99 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -31,34 +31,12 @@
#include "audio.h"
#include "avfilter.h"
#include "formats.h"
-
-enum PrecisionType {
- PRECISION_FIXED = 0,
- PRECISION_FLOAT,
- PRECISION_DOUBLE,
-};
+#include "af_volume.h"
static const char *precision_str[] = {
"fixed", "float", "double"
};
-typedef struct VolumeContext {
- const AVClass *class;
- AVFloatDSPContext fdsp;
- char *volume_str;
- enum PrecisionType precision;
- double volume;
- int volume_i;
- int channels;
- int planes;
-
- void (*scale_samples_int)(struct VolumeContext *vol, uint8_t *data,
- int nb_samples, int volume);
- void (*scale_samples_dbl)(struct VolumeContext *vol, uint8_t *data,
- int nb_samples, double volume);
- int samples_align;
-} VolumeContext;
-
#define OFFSET(x) offsetof(VolumeContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
@@ -254,9 +232,9 @@ static inline void scale_samples_dbl(VolumeContext *vol,
uint8_t *data,
smp[i] *= volume;
}
-static void volume_init(VolumeContext *vol, enum AVSampleFormat sample_fmt)
+static void volume_init(VolumeContext *vol)
{
- switch (av_get_packed_sample_fmt(sample_fmt)) {
+ switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
case AV_SAMPLE_FMT_U8:
if (vol->volume_i < 16777216)
vol->scale_samples_int = scale_samples_u8_small;
@@ -281,6 +259,10 @@ static void volume_init(VolumeContext *vol, enum
AVSampleFormat sample_fmt)
vol->scale_samples_dbl = scale_samples_dbl;
break;
}
+
+#if ARCH_X86
+ ff_volume_init_x86(vol);
+#endif
}
static int config_output(AVFilterLink *outlink)
@@ -289,12 +271,13 @@ static int config_output(AVFilterLink *outlink)
VolumeContext *vol = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
+ vol->sample_fmt = inlink->format;
vol->channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels :
1;
vol->samples_align = 1;
if (vol->precision != PRECISION_FIXED || vol->volume_i != 256)
- volume_init(vol, av_get_packed_sample_fmt(inlink->format));
+ volume_init(vol);
return 0;
}
diff --git a/libavfilter/af_volume.h b/libavfilter/af_volume.h
new file mode 100644
index 0000000..2325029
--- /dev/null
+++ b/libavfilter/af_volume.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * audio volume filter
+ */
+
+#ifndef AVFILTER_AF_VOLUME_H
+#define AVFILTER_AF_VOLUME_H
+
+#include "libavutil/common.h"
+#include "libavutil/float_dsp.h"
+#include "libavutil/opt.h"
+
+enum PrecisionType {
+ PRECISION_FIXED = 0,
+ PRECISION_FLOAT,
+ PRECISION_DOUBLE,
+};
+
+typedef struct VolumeContext {
+ const AVClass *class;
+ AVFloatDSPContext fdsp;
+ char *volume_str;
+ enum PrecisionType precision;
+ double volume;
+ int volume_i;
+ int channels;
+ int planes;
+ enum AVSampleFormat sample_fmt;
+
+ void (*scale_samples_int)(struct VolumeContext *vol, uint8_t *data,
+ int nb_samples, int volume);
+ void (*scale_samples_dbl)(struct VolumeContext *vol, uint8_t *data,
+ int nb_samples, double volume);
+ int samples_align;
+} VolumeContext;
+
+void ff_volume_init_x86(VolumeContext *vol);
+
+#endif /* AVFILTER_AF_VOLUME_H */
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
index 46fc84f..e604244 100644
--- a/libavfilter/x86/Makefile
+++ b/libavfilter/x86/Makefile
@@ -1,3 +1,5 @@
+OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o
MMX-OBJS-$(CONFIG_YADIF_FILTER) += x86/yadif.o
MMX-OBJS-$(CONFIG_GRADFUN_FILTER) += x86/gradfun.o
YASM-OBJS-$(CONFIG_HQDN3D_FILTER) += x86/hqdn3d.o
+YASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o
diff --git a/libavfilter/x86/af_volume.asm b/libavfilter/x86/af_volume.asm
new file mode 100644
index 0000000..3b5f434
--- /dev/null
+++ b/libavfilter/x86/af_volume.asm
@@ -0,0 +1,56 @@
+;*****************************************************************************
+;* x86-optimized functions for volume filter
+;* Copyright (c) 2012 Justin Ruggles <[email protected]>
+;*
+;* This file is part of Libav.
+;*
+;* Libav 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.
+;*
+;* Libav 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 Libav; if not, write to the Free Software
+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;******************************************************************************
+
+%include "x86inc.asm"
+
+SECTION_RODATA 32
+
+pw_1: times 8 dw 1
+pw_128: times 8 dw 128
+
+SECTION_TEXT
+
+;------------------------------------------------------------------------------
+; void ff_scale_samples_s16(VolumeContext *ctx, uint8_t *src, int len,
+; int volume)
+;------------------------------------------------------------------------------
+
+INIT_XMM sse2
+cglobal scale_samples_s16, 4,4,4, ctx, src, len, volume
+ movd m0, volumem
+ pshuflw m0, m0, 0
+ punpcklwd m0, [pw_1]
+ mova m1, [pw_128]
+ lea lenq, [lend*2-mmsize]
+.loop:
+ ; src[i] = av_clip_int16((src[i] * volume + 128) >> 8);
+ mova m2, [srcq+lenq]
+ punpcklwd m3, m2, m1
+ punpckhwd m2, m1
+ pmaddwd m3, m0
+ pmaddwd m2, m0
+ psrad m3, 8
+ psrad m2, 8
+ packssdw m3, m2
+ mova [srcq+lenq], m3
+ sub lenq, mmsize
+ jge .loop
+ REP_RET
diff --git a/libavfilter/x86/af_volume_init.c b/libavfilter/x86/af_volume_init.c
new file mode 100644
index 0000000..511cd8e
--- /dev/null
+++ b/libavfilter/x86/af_volume_init.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libavutil/samplefmt.h"
+#include "libavutil/x86/cpu.h"
+#include "libavfilter/af_volume.h"
+
+void ff_scale_samples_s16_sse2(VolumeContext *ctx, uint8_t *src, int len,
+ int volume);
+
+void ff_volume_init_x86(VolumeContext *vol)
+{
+ int mm_flags = av_get_cpu_flags();
+ enum AVSampleFormat sample_fmt = av_get_packed_sample_fmt(vol->sample_fmt);
+
+ if (sample_fmt == AV_SAMPLE_FMT_S16) {
+ if (EXTERNAL_SSE2(mm_flags) && vol->volume_i < 65536) {
+ vol->scale_samples_int = ff_scale_samples_s16_sse2;
+ vol->samples_align = 8;
+ }
+ }
+}
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel