mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-10-24 02:09:03 +03:00
avcodec/x86/me_cmp: Replace MMXEXT size 16 funcs by unaligned SSE2 funcs
Snow calls some of the me_cmp_funcs with insufficient alignment
for the first pointer (see get_block_rd() in snowenc.c);
therefore SSE2 functions which really need this alignment
don't get set for Snow and 542765ce3e
consequently didn't remove MMXEXT functions which are overridden
by these SSE2 functions for normal codecs.
For reference, here is a command line which would segfault
if one simply used the ordinary SSE2 functions for Snow:
./ffmpeg -i mm-short.mpg -an -vcodec snow -t 0.2 -pix_fmt yuv444p \
-vstrict -2 -qscale 2 -flags +qpel -motion_est iter 444iter.avi
This commit adds unaligned SSE2 versions of these functions
and removes the MMXEXT ones. This in particular implies that
sad 16x16 now never uses MMX which allows to remove an emms_c
from ac3enc.c.
Benchmarks (u means unaligned version):
sad_0_c: 8.2 ( 1.00x)
sad_0_mmxext: 10.8 ( 0.76x)
sad_0_sse2: 6.2 ( 1.33x)
sad_0_sse2u: 6.7 ( 1.23x)
vsad_0_c: 44.7 ( 1.00x)
vsad_0_mmxext (approx): 12.2 ( 3.68x)
vsad_0_sse2 (approx): 7.8 ( 5.75x)
vsad_4_c: 88.4 ( 1.00x)
vsad_4_mmxext: 7.1 (12.46x)
vsad_4_sse2: 4.2 (21.15x)
vsad_4_sse2u: 5.5 (15.96x)
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@@ -32,7 +32,6 @@
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/crc.h"
|
||||
#include "libavutil/emms.h"
|
||||
#include "libavutil/internal.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/mem_internal.h"
|
||||
@@ -945,8 +944,6 @@ static void ac3_process_exponents(AC3EncodeContext *s)
|
||||
compute_exp_strategy(s);
|
||||
|
||||
encode_exponents(s);
|
||||
|
||||
emms_c();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -467,22 +467,25 @@ HF_NOISE 16
|
||||
;---------------------------------------------------------------------------------------
|
||||
;int ff_sad_<opt>(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h);
|
||||
;---------------------------------------------------------------------------------------
|
||||
;%1 = 8/16
|
||||
%macro SAD 1
|
||||
cglobal sad%1, 5, 5, 3, v, pix1, pix2, stride, h
|
||||
;%1 = 8/16, %2 = a/u (whether pix1 is aligned or not)
|
||||
%macro SAD 1-2
|
||||
%ifidn %2, u
|
||||
cglobal sad%1u, 5, 5, 5, v, pix1, pix2, stride, h
|
||||
%else
|
||||
cglobal sad%1, 5, 5, 3, v, pix1, pix2, stride, h
|
||||
%endif
|
||||
movu m2, [pix2q]
|
||||
movu m1, [pix2q+strideq]
|
||||
%ifidn %2, u
|
||||
movu m0, [pix1q]
|
||||
movu m3, [pix1q+strideq]
|
||||
psadbw m2, m0
|
||||
psadbw m1, m3
|
||||
%else
|
||||
psadbw m2, [pix1q]
|
||||
psadbw m1, [pix1q+strideq]
|
||||
paddw m2, m1
|
||||
%if %1 != mmsize
|
||||
movu m0, [pix2q+8]
|
||||
movu m1, [pix2q+strideq+8]
|
||||
psadbw m0, [pix1q+8]
|
||||
psadbw m1, [pix1q+strideq+8]
|
||||
paddw m2, m0
|
||||
paddw m2, m1
|
||||
%endif
|
||||
paddw m2, m1
|
||||
sub hd, 2
|
||||
|
||||
align 16
|
||||
@@ -491,18 +494,17 @@ align 16
|
||||
lea pix2q, [pix2q+strideq*2]
|
||||
movu m0, [pix2q]
|
||||
movu m1, [pix2q+strideq]
|
||||
%ifidn %2, u
|
||||
movu m3, [pix1q]
|
||||
movu m4, [pix1q+strideq]
|
||||
psadbw m0, m3
|
||||
psadbw m1, m4
|
||||
%else
|
||||
psadbw m0, [pix1q]
|
||||
psadbw m1, [pix1q+strideq]
|
||||
paddw m2, m0
|
||||
paddw m2, m1
|
||||
%if %1 != mmsize
|
||||
movu m0, [pix2q+8]
|
||||
movu m1, [pix2q+strideq+8]
|
||||
psadbw m0, [pix1q+8]
|
||||
psadbw m1, [pix1q+strideq+8]
|
||||
paddw m2, m0
|
||||
paddw m2, m1
|
||||
%endif
|
||||
paddw m2, m0
|
||||
paddw m2, m1
|
||||
sub hd, 2
|
||||
jg .loop
|
||||
%if mmsize == 16
|
||||
@@ -515,9 +517,9 @@ align 16
|
||||
|
||||
INIT_MMX mmxext
|
||||
SAD 8
|
||||
SAD 16
|
||||
INIT_XMM sse2
|
||||
SAD 16
|
||||
SAD 16, u
|
||||
|
||||
;------------------------------------------------------------------------------------------
|
||||
;int ff_sad_x2_<opt>(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t stride, int h);
|
||||
@@ -791,46 +793,26 @@ SAD_APPROX_XY2 16
|
||||
;int ff_vsad_intra(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
; ptrdiff_t line_size, int h);
|
||||
;--------------------------------------------------------------------
|
||||
; %1 = 8/16
|
||||
%macro VSAD_INTRA 1
|
||||
cglobal vsad_intra%1, 5, 5, 3, v, pix1, pix2, lsize, h
|
||||
mova m0, [pix1q]
|
||||
%if %1 == mmsize
|
||||
mova m2, [pix1q+lsizeq]
|
||||
psadbw m0, m2
|
||||
; %1 = 8/16, %2 = a/u (whether pix1 is aligned or not)
|
||||
%macro VSAD_INTRA 2
|
||||
%ifidn %2, u
|
||||
cglobal vsad_intra%1u, 5, 5, 3, v, pix1, pix2, lsize, h
|
||||
%else
|
||||
mova m2, [pix1q+lsizeq]
|
||||
mova m3, [pix1q+8]
|
||||
mova m4, [pix1q+lsizeq+8]
|
||||
psadbw m0, m2
|
||||
psadbw m3, m4
|
||||
paddw m0, m3
|
||||
cglobal vsad_intra%1, 5, 5, 3, v, pix1, pix2, lsize, h
|
||||
%endif
|
||||
mov%2 m0, [pix1q]
|
||||
mov%2 m2, [pix1q+lsizeq]
|
||||
psadbw m0, m2
|
||||
sub hd, 2
|
||||
|
||||
.loop:
|
||||
lea pix1q, [pix1q + 2*lsizeq]
|
||||
%if %1 == mmsize
|
||||
mova m1, [pix1q]
|
||||
mov%2 m1, [pix1q]
|
||||
psadbw m2, m1
|
||||
paddw m0, m2
|
||||
mova m2, [pix1q+lsizeq]
|
||||
mov%2 m2, [pix1q+lsizeq]
|
||||
psadbw m1, m2
|
||||
paddw m0, m1
|
||||
%else
|
||||
mova m1, [pix1q]
|
||||
mova m3, [pix1q+8]
|
||||
psadbw m2, m1
|
||||
psadbw m4, m3
|
||||
paddw m0, m2
|
||||
paddw m0, m4
|
||||
mova m2, [pix1q+lsizeq]
|
||||
mova m4, [pix1q+lsizeq+8]
|
||||
psadbw m1, m2
|
||||
psadbw m3, m4
|
||||
paddw m0, m1
|
||||
paddw m0, m3
|
||||
%endif
|
||||
sub hd, 2
|
||||
jg .loop
|
||||
|
||||
@@ -843,22 +825,25 @@ cglobal vsad_intra%1, 5, 5, 3, v, pix1, pix2, lsize, h
|
||||
%endmacro
|
||||
|
||||
INIT_MMX mmxext
|
||||
VSAD_INTRA 8
|
||||
VSAD_INTRA 16
|
||||
VSAD_INTRA 8, a
|
||||
INIT_XMM sse2
|
||||
VSAD_INTRA 16
|
||||
VSAD_INTRA 16, a
|
||||
VSAD_INTRA 16, u
|
||||
|
||||
;---------------------------------------------------------------------
|
||||
;int ff_vsad_approx(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
; ptrdiff_t line_size, int h);
|
||||
;---------------------------------------------------------------------
|
||||
; %1 = 8/16
|
||||
%macro VSAD_APPROX 1
|
||||
cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
; %1 = 8/16, %2 = a/u (whether pix1 is aligned or not)
|
||||
%macro VSAD_APPROX 2
|
||||
%ifidn %2, u
|
||||
cglobal vsad%1u_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
%else
|
||||
cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
%endif
|
||||
mova m1, [pb_80]
|
||||
mova m0, [pix1q]
|
||||
%if %1 == mmsize ; vsad8_mmxext, vsad16_sse2
|
||||
mova m4, [pix1q+lsizeq]
|
||||
mov%2 m0, [pix1q]
|
||||
mov%2 m4, [pix1q+lsizeq]
|
||||
%if mmsize == 16
|
||||
movu m3, [pix2q]
|
||||
movu m2, [pix2q+lsizeq]
|
||||
@@ -871,29 +856,12 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
pxor m0, m1
|
||||
pxor m4, m1
|
||||
psadbw m0, m4
|
||||
%else ; vsad16_mmxext
|
||||
mova m3, [pix1q+8]
|
||||
psubb m0, [pix2q]
|
||||
psubb m3, [pix2q+8]
|
||||
pxor m0, m1
|
||||
pxor m3, m1
|
||||
mova m4, [pix1q+lsizeq]
|
||||
mova m5, [pix1q+lsizeq+8]
|
||||
psubb m4, [pix2q+lsizeq]
|
||||
psubb m5, [pix2q+lsizeq+8]
|
||||
pxor m4, m1
|
||||
pxor m5, m1
|
||||
psadbw m0, m4
|
||||
psadbw m3, m5
|
||||
paddw m0, m3
|
||||
%endif
|
||||
sub hd, 2
|
||||
|
||||
.loop:
|
||||
lea pix1q, [pix1q + 2*lsizeq]
|
||||
lea pix2q, [pix2q + 2*lsizeq]
|
||||
mova m2, [pix1q]
|
||||
%if %1 == mmsize ; vsad8_mmxext, vsad16_sse2
|
||||
mov%2 m2, [pix1q]
|
||||
%if mmsize == 16
|
||||
movu m3, [pix2q]
|
||||
psubb m2, m3
|
||||
@@ -903,33 +871,12 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
pxor m2, m1
|
||||
psadbw m4, m2
|
||||
paddw m0, m4
|
||||
mova m4, [pix1q+lsizeq]
|
||||
mov%2 m4, [pix1q+lsizeq]
|
||||
movu m3, [pix2q+lsizeq]
|
||||
psubb m4, m3
|
||||
pxor m4, m1
|
||||
psadbw m2, m4
|
||||
paddw m0, m2
|
||||
%else ; vsad16_mmxext
|
||||
mova m3, [pix1q+8]
|
||||
psubb m2, [pix2q]
|
||||
psubb m3, [pix2q+8]
|
||||
pxor m2, m1
|
||||
pxor m3, m1
|
||||
psadbw m4, m2
|
||||
psadbw m5, m3
|
||||
paddw m0, m4
|
||||
paddw m0, m5
|
||||
mova m4, [pix1q+lsizeq]
|
||||
mova m5, [pix1q+lsizeq+8]
|
||||
psubb m4, [pix2q+lsizeq]
|
||||
psubb m5, [pix2q+lsizeq+8]
|
||||
pxor m4, m1
|
||||
pxor m5, m1
|
||||
psadbw m2, m4
|
||||
psadbw m3, m5
|
||||
paddw m0, m2
|
||||
paddw m0, m3
|
||||
%endif
|
||||
sub hd, 2
|
||||
jg .loop
|
||||
|
||||
@@ -942,7 +889,7 @@ cglobal vsad%1_approx, 5, 5, 5, v, pix1, pix2, lsize, h
|
||||
%endmacro
|
||||
|
||||
INIT_MMX mmxext
|
||||
VSAD_APPROX 8
|
||||
VSAD_APPROX 16
|
||||
VSAD_APPROX 8, a
|
||||
INIT_XMM sse2
|
||||
VSAD_APPROX 16
|
||||
VSAD_APPROX 16, a
|
||||
VSAD_APPROX 16, u
|
||||
|
||||
@@ -40,10 +40,10 @@ int ff_hf_noise8_mmx(const uint8_t *pix1, ptrdiff_t stride, int h);
|
||||
int ff_hf_noise16_mmx(const uint8_t *pix1, ptrdiff_t stride, int h);
|
||||
int ff_sad8_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_sad16_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_sad16_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_sad16u_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_sad8_x2_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_sad16_x2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
@@ -62,16 +62,16 @@ int ff_sad16_xy2_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad_intra8_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad_intra16_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad_intra16_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad_intra16u_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad8_approx_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad16_approx_mmxext(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad16_approx_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
int ff_vsad16u_approx_sse2(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2,
|
||||
ptrdiff_t stride, int h);
|
||||
|
||||
#define hadamard_func(cpu) \
|
||||
int ff_hadamard8_diff_ ## cpu(MPVEncContext *s, const uint8_t *src1, \
|
||||
@@ -135,20 +135,17 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx)
|
||||
c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext;
|
||||
#endif
|
||||
|
||||
c->sad[0] = ff_sad16_mmxext;
|
||||
c->sad[1] = ff_sad8_mmxext;
|
||||
|
||||
c->pix_abs[1][0] = ff_sad8_mmxext;
|
||||
c->pix_abs[1][1] = ff_sad8_x2_mmxext;
|
||||
c->pix_abs[1][2] = ff_sad8_y2_mmxext;
|
||||
|
||||
c->vsad[4] = ff_vsad_intra16_mmxext;
|
||||
c->vsad[5] = ff_vsad_intra8_mmxext;
|
||||
|
||||
if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) {
|
||||
c->pix_abs[1][3] = ff_sad8_approx_xy2_mmxext;
|
||||
|
||||
c->vsad[0] = ff_vsad16_approx_mmxext;
|
||||
c->vsad[1] = ff_vsad8_approx_mmxext;
|
||||
}
|
||||
}
|
||||
@@ -166,13 +163,22 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx)
|
||||
c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2;
|
||||
c->hadamard8_diff[1] = ff_hadamard8_diff_sse2;
|
||||
#endif
|
||||
if (!(cpu_flags & AV_CPU_FLAG_SSE2SLOW) && avctx->codec_id != AV_CODEC_ID_SNOW) {
|
||||
if (avctx->codec_id != AV_CODEC_ID_SNOW) {
|
||||
c->sad[0] = ff_sad16_sse2;
|
||||
|
||||
c->vsad[4] = ff_vsad_intra16_sse2;
|
||||
if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) {
|
||||
c->vsad[0] = ff_vsad16_approx_sse2;
|
||||
}
|
||||
} else {
|
||||
// Snow does not abide by the alignment requirements
|
||||
// of blk1, so we use special versions without them for it.
|
||||
c->sad[0] = ff_sad16u_sse2;
|
||||
|
||||
c->vsad[4] = ff_vsad_intra16u_sse2;
|
||||
if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) {
|
||||
c->vsad[0] = ff_vsad16u_approx_sse2;
|
||||
}
|
||||
}
|
||||
if (avctx->flags & AV_CODEC_FLAG_BITEXACT) {
|
||||
c->pix_abs[1][3] = ff_sad8_xy2_sse2;
|
||||
|
||||
Reference in New Issue
Block a user