1
0
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:
Andreas Rheinhardt
2025-10-14 10:33:18 +02:00
parent 69a700043d
commit d91b1559e0
3 changed files with 66 additions and 116 deletions

View File

@@ -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();
}

View File

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

View File

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