---
The previous patch was doing some unnecessary things in the SSSE3
version. Once I removed those, it was faster than the SSE4 version.

    C: 30735
SSSE3:  6158
  AVX:  5656

 libavfilter/x86/af_volume.asm    |   58 ++++++++++++++++++++++++++++++++++++++
 libavfilter/x86/af_volume_init.c |   14 +++++++++
 2 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/libavfilter/x86/af_volume.asm b/libavfilter/x86/af_volume.asm
index 602bab7..4094676 100644
--- a/libavfilter/x86/af_volume.asm
+++ b/libavfilter/x86/af_volume.asm
@@ -24,6 +24,9 @@
 SECTION_RODATA 32
 
 pd_128: times 4 dd 128
+pq_128: times 2 dq 128
+pq_maxsq: times 2 dq  549755813632 ; INT_MAX << 8
+pb_packqd_rsh8: db 1, 2, 3, 4, 9, 10, 11, 12, -1, -1, -1, -1, -1, -1, -1, -1
 
 SECTION_TEXT
 
@@ -55,3 +58,58 @@ cglobal scale_samples_s16, 4,4,4, ctx, src, len, volume
     sub    lenq, mmsize
     jge .loop
     REP_RET
+
+;------------------------------------------------------------------------------
+; void ff_scale_samples_s32(VolumeContext *ctx, uint8_t *src, int len,
+;                           int volume)
+;------------------------------------------------------------------------------
+
+; NOTE: This is not bit-identical with the C version because it clips to
+;       [-INT_MAX, INT_MAX] instead of [INT_MIN, INT_MAX]
+
+%macro PMINSQ 3 ; dst, src, tmp
+    pcmpgtq   %3, %2, %1
+    pxor      %1, %2
+    pand      %1, %3
+    pxor      %1, %2
+%endmacro
+
+%macro SCALE_SAMPLES_S32 0
+cglobal scale_samples_s32, 4,4,8, ctx, src, len, volume
+    movd        m0, volumed
+    pshufd      m0, m0, 0
+    mova        m3, [pq_128]
+    mova        m4, [pq_maxsq]
+    mova        m5, [pb_packqd_rsh8]
+    lea       lenq, [lend*4-mmsize]
+.loop:
+    ; src[i] = av_clipl_int32((src[i] * volume + 128) >> 8);
+    mova        m1, [srcq+lenq]
+    mova        m6, m1
+    mova        m2, m1
+    punpckhdq   m2, m1, m1
+    punpckldq   m1, m1, m1
+    pabsd       m1, m1
+    pabsd       m2, m2
+    pmuludq     m1, m0
+    pmuludq     m2, m0
+    paddq       m1, m3
+    paddq       m2, m3
+    PMINSQ      m1, m4, m7
+    PMINSQ      m2, m4, m7
+    pshufb      m1, m5
+    pshufb      m2, m5
+    punpcklqdq  m1, m2
+    psignd      m1, m6
+    mova  [srcq+lenq], m1
+    sub       lenq, mmsize
+    jge .loop
+    REP_RET
+%endmacro
+
+INIT_XMM ssse3
+SCALE_SAMPLES_S32
+%if HAVE_AVX_EXTERNAL
+INIT_XMM avx
+SCALE_SAMPLES_S32
+%endif
diff --git a/libavfilter/x86/af_volume_init.c b/libavfilter/x86/af_volume_init.c
index 4a6782b..992b752 100644
--- a/libavfilter/x86/af_volume_init.c
+++ b/libavfilter/x86/af_volume_init.c
@@ -24,6 +24,11 @@
 void ff_scale_samples_s16_sse4(VolumeContext *ctx, uint8_t *src, int len,
                                int volume);
 
+void ff_scale_samples_s32_ssse3(VolumeContext *ctx, uint8_t *src, int len,
+                                int volume);
+void ff_scale_samples_s32_avx(VolumeContext *ctx, uint8_t *src, int len,
+                              int volume);
+
 void ff_volume_init_x86(VolumeContext *vol)
 {
     int mm_flags = av_get_cpu_flags();
@@ -34,5 +39,14 @@ void ff_volume_init_x86(VolumeContext *vol)
             vol->scale_samples_int = ff_scale_samples_s16_sse4;
             vol->samples_align = 8;
         }
+    } else if (sample_fmt == AV_SAMPLE_FMT_S32) {
+        if (EXTERNAL_SSSE3(mm_flags)) {
+            vol->scale_samples_int = ff_scale_samples_s32_ssse3;
+            vol->samples_align = 4;
+        }
+        if (EXTERNAL_AVX(mm_flags)) {
+            vol->scale_samples_int = ff_scale_samples_s32_avx;
+            vol->samples_align = 4;
+        }
     }
 }
-- 
1.7.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to