---
libavcodec/ac3enc.c | 22 ++------
libavcodec/dsputil.c | 17 ++++++
libavcodec/dsputil.h | 14 +++++
libavcodec/x86/dsputil_mmx.c | 24 ++++++++
libavcodec/x86/dsputil_yasm.asm | 118 +++++++++++++++++++++++++++++++++++++++
5 files changed, 178 insertions(+), 17 deletions(-)
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index bcdc183..17a2b16 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -525,19 +525,6 @@ static void compute_coupling_strategy(AC3EncodeContext *s)
/**
- * Clip an array of integers to a specified range.
- * TODO: move to dsputil
- */
-static void vector_clip_int32(int32_t *dst, int32_t *src, int32_t min,
- int32_t max, unsigned int len)
-{
- int i;
- for (i = 0; i < len; i++)
- dst[i] = av_clip(src[i], min, max);
-}
-
-
-/**
* Calculate a single coupling coordinate.
*/
static inline float calc_cpl_coord(float energy_ch, float energy_cpl)
@@ -720,8 +707,8 @@ static void apply_channel_coupling(AC3EncodeContext *s)
s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1],
cpl_coords[blk][1],
s->fbw_channels * 16);
- vector_clip_int32(fixed_cpl_coords[blk][1], fixed_cpl_coords[blk][1],
- -16777215, 16777215, s->fbw_channels * 16);
+ s->dsp.vector_clip_int32(fixed_cpl_coords[blk][1], fixed_cpl_coords[blk][1],
+ -16777215, 16777215, s->fbw_channels * 16);
s->ac3dsp.extract_exponents(block->cpl_coord_exp[1],
fixed_cpl_coords[blk][1],
s->fbw_channels * 16);
@@ -919,8 +906,9 @@ static void extract_exponents(AC3EncodeContext *s)
int chan_size = AC3_MAX_COEFS * AC3_MAX_BLOCKS * (s->channels - ch + 1);
AC3Block *block = &s->blocks[0];
- vector_clip_int32(block->fixed_coef[ch], block->fixed_coef[ch],
- -16777215, 16777215, chan_size);
+ s->dsp.vector_clip_int32(block->fixed_coef[ch], block->fixed_coef[ch],
+ -16777215, 16777215, chan_size);
+
s->ac3dsp.extract_exponents(block->exp[ch], block->fixed_coef[ch], chan_size);
}
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
index 4389289..4f17b43 100644
--- a/libavcodec/dsputil.c
+++ b/libavcodec/dsputil.c
@@ -2676,6 +2676,22 @@ static void apply_window_int16_c(int16_t *output, const int16_t *input,
}
}
+static void vector_clip_int32_c(int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len)
+{
+ do {
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ *dst++ = av_clip(*src++, min, max);
+ len -= 8;
+ } while (len > 0);
+}
+
#define W0 2048
#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */
#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */
@@ -3122,6 +3138,7 @@ av_cold void dsputil_init(DSPContext* c, AVCodecContext *avctx)
c->scalarproduct_int16 = scalarproduct_int16_c;
c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c;
c->apply_window_int16 = apply_window_int16_c;
+ c->vector_clip_int32 = vector_clip_int32_c;
c->scalarproduct_float = scalarproduct_float_c;
c->butterflies_float = butterflies_float_c;
c->vector_fmul_scalar = vector_fmul_scalar_c;
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index cfc574a..cff8406 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -555,6 +555,20 @@ typedef struct DSPContext {
void (*apply_window_int16)(int16_t *output, const int16_t *input,
const int16_t *window, unsigned int len);
+ /**
+ * Clip each element in an array of int32_t to a given minimum and maximum value.
+ * @param dst destination array
+ * constraints: 16-byte aligned
+ * @param src source array
+ * constraints: 16-byte aligned
+ * @param min minimum value
+ * @param max maximum value
+ * @param len number of elements in the array
+ * constraints: multiple of 16 greater than zero
+ */
+ void (*vector_clip_int32)(int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len);
+
/* rv30 functions */
qpel_mc_func put_rv30_tpel_pixels_tab[4][16];
qpel_mc_func avg_rv30_tpel_pixels_tab[4][16];
diff --git a/libavcodec/x86/dsputil_mmx.c b/libavcodec/x86/dsputil_mmx.c
index 1cc6991..83671c0 100644
--- a/libavcodec/x86/dsputil_mmx.c
+++ b/libavcodec/x86/dsputil_mmx.c
@@ -2416,6 +2416,15 @@ int ff_add_hfyu_left_prediction_sse4(uint8_t *dst, const uint8_t *src, int w, i
float ff_scalarproduct_float_sse(const float *v1, const float *v2, int order);
+void ff_vector_clip_int32_cmov (int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len);
+void ff_vector_clip_int32_mmx (int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len);
+void ff_vector_clip_int32_sse2 (int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len);
+void ff_vector_clip_int32_sse41 (int32_t *dst, const int32_t *src, int32_t min,
+ int32_t max, unsigned int len);
+
void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
{
int mm_flags = av_get_cpu_flags();
@@ -2556,6 +2565,8 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
c->put_rv40_chroma_pixels_tab[0]= ff_put_rv40_chroma_mc8_mmx;
c->put_rv40_chroma_pixels_tab[1]= ff_put_rv40_chroma_mc4_mmx;
+
+ c->vector_clip_int32 = ff_vector_clip_int32_mmx;
#endif
if (mm_flags & AV_CPU_FLAG_MMX2) {
@@ -2809,6 +2820,11 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
}
#endif
}
+ if (mm_flags & AV_CPU_FLAG_SSE2SLOW && HAVE_FAST_CMOV) {
+#if HAVE_YASM
+ c->vector_clip_int32 = ff_vector_clip_int32_cmov;
+#endif
+ }
if(mm_flags & AV_CPU_FLAG_SSE){
c->vorbis_inverse_coupling = vorbis_inverse_coupling_sse;
c->ac3_downmix = ac3_downmix_sse;
@@ -2829,6 +2845,9 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
#if HAVE_YASM
c->scalarproduct_int16 = ff_scalarproduct_int16_sse2;
c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_sse2;
+ if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) {
+ c->vector_clip_int32 = ff_vector_clip_int32_sse2;
+ }
if (avctx->flags & CODEC_FLAG_BITEXACT) {
c->apply_window_int16 = ff_apply_window_int16_sse2_ba;
} else {
@@ -2854,6 +2873,11 @@ void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
}
#endif
}
+ if (mm_flags & AV_CPU_FLAG_SSE4 && HAVE_SSE) {
+#if HAVE_YASM
+ c->vector_clip_int32 = ff_vector_clip_int32_sse41;
+#endif
+ }
}
if (CONFIG_ENCODERS)
diff --git a/libavcodec/x86/dsputil_yasm.asm b/libavcodec/x86/dsputil_yasm.asm
index 8b19cc1..44b5717 100644
--- a/libavcodec/x86/dsputil_yasm.asm
+++ b/libavcodec/x86/dsputil_yasm.asm
@@ -1048,3 +1048,121 @@ emu_edge sse
%ifdef ARCH_X86_32
emu_edge mmx
%endif
+
+;-----------------------------------------------------------------------------
+; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min,
+; int32_t max, unsigned int len)
+;-----------------------------------------------------------------------------
+
+%macro PMINSD_MMX 3 ; dst, src, tmp
+ mova %3, %2
+ pcmpgtd %3, %1
+ pxor %1, %2
+ pand %1, %3
+ pxor %1, %2
+%endmacro
+
+%macro PMAXSD_MMX 3 ; dst, src, tmp
+ mova %3, %1
+ pcmpgtd %3, %2
+ pand %1, %3
+ pandn %3, %2
+ por %1, %3
+%endmacro
+
+%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp
+ PMINSD_MMX %1, %3, %4
+ PMAXSD_MMX %1, %2, %4
+%endmacro
+
+%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused
+ pminsd %1, %3
+ pmaxsd %1, %2
+%endmacro
+
+%macro SPLATD_MMX 1
+ punpckldq %1, %1
+%endmacro
+
+%macro SPLATD_SSE2 1
+ pshufd %1, %1, 0
+%endmacro
+
+%macro VECTOR_CLIP_INT32 1
+cglobal vector_clip_int32_%1, 5,5,7, dst, src, min, max, len
+ movd m4, mind
+ movd m5, maxd
+ SPLATD m4
+ SPLATD m5
+.loop:
+ mova m0, [srcq ]
+ mova m1, [srcq+mmsize ]
+ mova m2, [srcq+mmsize*2]
+ mova m3, [srcq+mmsize*3]
+ CLIPD m0, m4, m5, m6
+ CLIPD m1, m4, m5, m6
+ CLIPD m2, m4, m5, m6
+ CLIPD m3, m4, m5, m6
+ mova [dstq ], m0
+ mova [dstq+mmsize ], m1
+ mova [dstq+mmsize*2], m2
+ mova [dstq+mmsize*3], m3
+ add srcq, mmsize*4
+ add dstq, mmsize*4
+ sub lend, mmsize
+ ja .loop
+ REP_RET
+%endmacro
+
+INIT_MMX
+%define SPLATD SPLATD_MMX
+%define CLIPD CLIPD_MMX
+VECTOR_CLIP_INT32 mmx
+INIT_XMM
+%define SPLATD SPLATD_SSE2
+VECTOR_CLIP_INT32 sse2
+%define CLIPD CLIPD_SSE41
+VECTOR_CLIP_INT32 sse41
+
+; This is faster on Athlon64 where cmov is fast and SSE2 is slow.
+; GCC generates similar but slower code. For some reason it wants to use
+; branching for the max value clipping instead of cmovg.
+
+%macro CLIPD_CMOV 3 ; src/dst, min, max
+ cmp %1, %3
+ cmovg %1, %3
+ cmp %1, %2
+ cmovl %1, %2
+%endmacro
+
+cglobal vector_clip_int32_cmov, 5,6,0, dst, src, min, max, len, tmp
+.loop:
+ mov tmpd, [srcq]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq], tmpd
+ mov tmpd, [srcq+4]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+4], tmpd
+ mov tmpd, [srcq+8]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+8], tmpd
+ mov tmpd, [srcq+12]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+12], tmpd
+ mov tmpd, [srcq+16]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+16], tmpd
+ mov tmpd, [srcq+20]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+20], tmpd
+ mov tmpd, [srcq+24]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+24], tmpd
+ mov tmpd, [srcq+28]
+ CLIPD_CMOV tmpd, mind, maxd
+ mov [dstq+28], tmpd
+ add srcq, 32
+ add dstq, 32
+ sub lenq, 8
+ ja .loop
+ REP_RET
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel