---
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

Reply via email to