PR #22780 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22780 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22780.patch
>From f3f1945eb6dae7cfb8f62081eb68e996f395122b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Tue, 7 Apr 2026 23:50:43 +0200 Subject: [PATCH 01/13] avcodec/snowdata: Don't use 8 bits for six bits data This has been done in 561a18d3ba07382dffdf583dda13f6954109b116 in order to avoid shifts, yet this rationale no longer applies since d593e329832a432777218eb92469bad10594a3c5. So shift them back; this is in preparation for using these coefficients together with pmaddubsw. Hint: 561a18d3ba07382dffdf583dda13f6954109b116 also added a block guarded by "if(LOG2_OBMC_MAX == 8". I changed the condition to remove this check (i.e. kept the block) which should not change the output at all. Yet all FATE tests pass if the block is completely removed. I don't know if this block is necessary at all. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow.c | 9 +-- libavcodec/snow.h | 2 +- libavcodec/snowdata.h | 120 +++++++++++++++++++-------------------- libavcodec/snowenc.c | 7 +-- libavcodec/x86/snowdsp.c | 8 +-- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/libavcodec/snow.c b/libavcodec/snow.c index b2850356ef..fa191c08c0 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -131,10 +131,11 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_ +obmc3[x] * block[1][x + y*src_stride] +obmc4[x] * block[0][x + y*src_stride]; - v <<= 8 - LOG2_OBMC_MAX; - if(FRAC_BITS != 8){ - v >>= 8 - FRAC_BITS; - } +#if FRAC_BITS > LOG2_OBMC_MAX + v <<= FRAC_BITS - LOG2_OBMC_MAX; +#elif FRAC_BITS < LOG2_OBMC_MAX + v >>= LOG2_OBMC_MAX - FRAC_BITS; +#endif if(add){ v += dst[x + src_x]; v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS; diff --git a/libavcodec/snow.h b/libavcodec/snow.h index f8f45b8763..fa351bd53c 100644 --- a/libavcodec/snow.h +++ b/libavcodec/snow.h @@ -45,7 +45,7 @@ #define FRAC_BITS 4 #define MAX_REF_FRAMES 8 -#define LOG2_OBMC_MAX 8 +#define LOG2_OBMC_MAX 6 #define OBMC_MAX (1<<(LOG2_OBMC_MAX)) typedef struct BlockNode{ int16_t mx; ///< Motion vector component X, see mv_scale diff --git a/libavcodec/snowdata.h b/libavcodec/snowdata.h index ca0c1e3f7a..87ab354385 100644 --- a/libavcodec/snowdata.h +++ b/libavcodec/snowdata.h @@ -25,79 +25,79 @@ #include "snow.h" static const uint8_t obmc32[1024]={ - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, - 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, - 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, - 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, - 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, - 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, - 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, - 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, - 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, - 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, - 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, - 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, - 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, - 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, - 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, - 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, - 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, - 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, - 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, - 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, - 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, - 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, - 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, - 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, - 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, - 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, - 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, - 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, - 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, - 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, - 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 0, + 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 8, 8, 7, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 4, 3, 2, 1, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, + 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 19, 20, 21, 21, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 6, 5, 3, 2, 1, + 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 17, 19, 20, 22, 24, 25, 25, 24, 22, 20, 19, 17, 15, 14, 12, 11, 9, 7, 6, 4, 2, 1, + 1, 3, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 23, 25, 27, 29, 29, 27, 25, 23, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 3, 1, + 1, 3, 5, 7, 10, 12, 14, 16, 18, 20, 22, 24, 27, 29, 31, 33, 33, 31, 29, 27, 24, 22, 20, 18, 16, 14, 12, 10, 7, 5, 3, 1, + 1, 4, 6, 8, 11, 13, 15, 18, 20, 23, 25, 27, 30, 32, 34, 37, 37, 34, 32, 30, 27, 25, 23, 20, 18, 15, 13, 11, 8, 6, 4, 1, + 1, 4, 7, 9, 12, 14, 17, 20, 22, 25, 28, 30, 33, 35, 38, 41, 41, 38, 35, 33, 30, 28, 25, 22, 20, 17, 14, 12, 9, 7, 4, 1, + 1, 4, 7, 10, 13, 16, 19, 22, 24, 27, 30, 33, 36, 39, 42, 45, 45, 42, 39, 36, 33, 30, 27, 24, 22, 19, 16, 13, 10, 7, 4, 1, + 2, 5, 8, 11, 14, 17, 20, 23, 27, 30, 33, 36, 39, 42, 45, 48, 48, 45, 42, 39, 36, 33, 30, 27, 23, 20, 17, 14, 11, 8, 5, 2, + 2, 5, 8, 12, 15, 19, 22, 25, 29, 32, 35, 39, 42, 46, 49, 52, 52, 49, 46, 42, 39, 35, 32, 29, 25, 22, 19, 15, 12, 8, 5, 2, + 2, 5, 9, 13, 16, 20, 24, 27, 31, 34, 38, 42, 45, 49, 53, 56, 56, 53, 49, 45, 42, 38, 34, 31, 27, 24, 20, 16, 13, 9, 5, 2, + 2, 6, 10, 14, 17, 21, 25, 29, 33, 37, 41, 45, 48, 52, 56, 60, 60, 56, 52, 48, 45, 41, 37, 33, 29, 25, 21, 17, 14, 10, 6, 2, + 2, 6, 10, 14, 17, 21, 25, 29, 33, 37, 41, 45, 48, 52, 56, 60, 60, 56, 52, 48, 45, 41, 37, 33, 29, 25, 21, 17, 14, 10, 6, 2, + 2, 5, 9, 13, 16, 20, 24, 27, 31, 34, 38, 42, 45, 49, 53, 56, 56, 53, 49, 45, 42, 38, 34, 31, 27, 24, 20, 16, 13, 9, 5, 2, + 2, 5, 8, 12, 15, 19, 22, 25, 29, 32, 35, 39, 42, 46, 49, 52, 52, 49, 46, 42, 39, 35, 32, 29, 25, 22, 19, 15, 12, 8, 5, 2, + 2, 5, 8, 11, 14, 17, 20, 23, 27, 30, 33, 36, 39, 42, 45, 48, 48, 45, 42, 39, 36, 33, 30, 27, 23, 20, 17, 14, 11, 8, 5, 2, + 1, 4, 7, 10, 13, 16, 19, 22, 24, 27, 30, 33, 36, 39, 42, 45, 45, 42, 39, 36, 33, 30, 27, 24, 22, 19, 16, 13, 10, 7, 4, 1, + 1, 4, 7, 9, 12, 14, 17, 20, 22, 25, 28, 30, 33, 35, 38, 41, 41, 38, 35, 33, 30, 28, 25, 22, 20, 17, 14, 12, 9, 7, 4, 1, + 1, 4, 6, 8, 11, 13, 15, 18, 20, 23, 25, 27, 30, 32, 34, 37, 37, 34, 32, 30, 27, 25, 23, 20, 18, 15, 13, 11, 8, 6, 4, 1, + 1, 3, 5, 7, 10, 12, 14, 16, 18, 20, 22, 24, 27, 29, 31, 33, 33, 31, 29, 27, 24, 22, 20, 18, 16, 14, 12, 10, 7, 5, 3, 1, + 1, 3, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 23, 25, 27, 29, 29, 27, 25, 23, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 3, 1, + 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 17, 19, 20, 22, 24, 25, 25, 24, 22, 20, 19, 17, 15, 14, 12, 11, 9, 7, 6, 4, 2, 1, + 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 19, 20, 21, 21, 20, 19, 17, 16, 14, 13, 12, 10, 9, 8, 6, 5, 3, 2, 1, + 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 17, 16, 15, 14, 13, 12, 11, 10, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 8, 8, 7, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 0, + 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, //error:0.000020 }; static const uint8_t obmc16[256]={ - 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, - 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, - 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, - 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, - 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, - 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, - 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, - 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, - 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, - 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, - 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, - 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, - 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, - 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, - 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, - 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, + 0, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 2, 1, 1, 0, + 1, 2, 4, 5, 7, 8, 10, 11, 11, 10, 8, 7, 5, 4, 2, 1, + 1, 4, 6, 9, 11, 14, 16, 19, 19, 16, 14, 11, 9, 6, 4, 1, + 2, 5, 9, 12, 16, 19, 23, 26, 26, 23, 19, 16, 12, 9, 5, 2, + 2, 7, 11, 16, 20, 25, 29, 34, 34, 29, 25, 20, 16, 11, 7, 2, + 3, 8, 14, 19, 25, 30, 36, 41, 41, 36, 30, 25, 19, 14, 8, 3, + 3, 10, 16, 23, 29, 36, 42, 49, 49, 42, 36, 29, 23, 16, 10, 3, + 4, 11, 19, 26, 34, 41, 49, 56, 56, 49, 41, 34, 26, 19, 11, 4, + 4, 11, 19, 26, 34, 41, 49, 56, 56, 49, 41, 34, 26, 19, 11, 4, + 3, 10, 16, 23, 29, 36, 42, 49, 49, 42, 36, 29, 23, 16, 10, 3, + 3, 8, 14, 19, 25, 30, 36, 41, 41, 36, 30, 25, 19, 14, 8, 3, + 2, 7, 11, 16, 20, 25, 29, 34, 34, 29, 25, 20, 16, 11, 7, 2, + 2, 5, 9, 12, 16, 19, 23, 26, 26, 23, 19, 16, 12, 9, 5, 2, + 1, 4, 6, 9, 11, 14, 16, 19, 19, 16, 14, 11, 9, 6, 4, 1, + 1, 2, 4, 5, 7, 8, 10, 11, 11, 10, 8, 7, 5, 4, 2, 1, + 0, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 2, 1, 1, 0, //error:0.000015 }; //linear *64 static const uint8_t obmc8[64]={ - 4, 12, 20, 28, 28, 20, 12, 4, - 12, 36, 60, 84, 84, 60, 36, 12, - 20, 60,100,140,140,100, 60, 20, - 28, 84,140,196,196,140, 84, 28, - 28, 84,140,196,196,140, 84, 28, - 20, 60,100,140,140,100, 60, 20, - 12, 36, 60, 84, 84, 60, 36, 12, - 4, 12, 20, 28, 28, 20, 12, 4, + 1, 3, 5, 7, 7, 5, 3, 1, + 3, 9, 15, 21, 21, 15, 9, 3, + 5, 15, 25, 35, 35, 25, 15, 5, + 7, 21, 35, 49, 49, 35, 21, 7, + 7, 21, 35, 49, 49, 35, 21, 7, + 5, 15, 25, 35, 35, 25, 15, 5, + 3, 9, 15, 21, 21, 15, 9, 3, + 1, 3, 5, 7, 7, 5, 3, 1, //error:0.000000 }; //linear *64 static const uint8_t obmc4[16]={ - 16, 48, 48, 16, - 48,144,144, 48, - 48,144,144, 48, - 16, 48, 48, 16, + 4, 12, 12, 4, + 12, 36, 36, 12, + 12, 36, 36, 12, + 4, 12, 12, 4, //error:0.000000 }; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 5312d48e99..29a1f114c3 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -815,10 +815,9 @@ static int get_block_rd(SnowEncContext *enc, int mb_x, int mb_y, } } - /* copy the regions where obmc[] = (uint8_t)256 */ - if(LOG2_OBMC_MAX == 8 - && (mb_x == 0 || mb_x == b_stride-1) - && (mb_y == 0 || mb_y == b_height-1)){ + /* copy the regions where obmc[] = (uint8_t)(1<<LOG2_OBMC_MAX) */ + if ((mb_x == 0 || mb_x == b_stride-1) && + (mb_y == 0 || mb_y == b_height-1)){ if(mb_x == 0) x1 = block_w; else diff --git a/libavcodec/x86/snowdsp.c b/libavcodec/x86/snowdsp.c index bd0aa766e5..78a71f4aa5 100644 --- a/libavcodec/x86/snowdsp.c +++ b/libavcodec/x86/snowdsp.c @@ -746,8 +746,8 @@ snow_inner_add_yblock_sse2_accum_16("1", "512") snow_inner_add_yblock_sse2_accum_16("0", "528") "mov %0, %%"FF_REG_d" \n\t" - "psrlw $4, %%xmm1 \n\t" - "psrlw $4, %%xmm5 \n\t" + "psrlw $2, %%xmm1 \n\t" + "psrlw $2, %%xmm5 \n\t" "paddw (%%"FF_REG_D"), %%xmm1 \n\t" "paddw 16(%%"FF_REG_D"), %%xmm5 \n\t" "paddw %%xmm3, %%xmm1 \n\t" @@ -797,8 +797,8 @@ snow_inner_add_yblock_sse2_end_16 #define snow_inner_add_yblock_mmx_mix(read_offset, write_offset)\ "mov %0, %%"FF_REG_d" \n\t"\ - "psrlw $4, %%mm1 \n\t"\ - "psrlw $4, %%mm5 \n\t"\ + "psrlw $2, %%mm1 \n\t"\ + "psrlw $2, %%mm5 \n\t"\ "paddw "read_offset"(%%"FF_REG_D"), %%mm1 \n\t"\ "paddw "read_offset"+8(%%"FF_REG_D"), %%mm5 \n\t"\ "paddw %%mm3, %%mm1 \n\t"\ -- 2.52.0 >From 5a9bb23452fbbc8f81d74239be4761fa2eccc23b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 09:20:25 +0200 Subject: [PATCH 02/13] avcodec/snow: Disable dead code in ff_snow_inner_add_yblock() It is only used with add != 0 (and the assembly functions only support this case). Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/snow.c b/libavcodec/snow.c index fa191c08c0..b6aa94e1ce 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -20,6 +20,7 @@ #include <assert.h> +#include "libavutil/avassert.h" #include "libavutil/log.h" #include "libavutil/mem.h" #include "libavutil/thread.h" @@ -118,6 +119,9 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_ int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ int y, x; IDWTELEM * dst; + + av_assume(add); // add == 0 is currently unused + for(y=0; y<b_h; y++){ //FIXME ugly misuse of obmc_stride const uint8_t *obmc1= obmc + y*obmc_stride; -- 2.52.0 >From 42f80b10f4b1b7fe1332c664fc6787228cd3b56a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 09:29:33 +0200 Subject: [PATCH 03/13] avcodec/snow: Avoid always-true branch The input lines used in ff_snow_inner_add_yblock() must always be set (because their values are used). The MMX assembly always relied on this. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/snow.c b/libavcodec/snow.c index b6aa94e1ce..76dcdd5488 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -118,7 +118,6 @@ static av_cold void init_qpel(SnowContext *const s) void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ int y, x; - IDWTELEM * dst; av_assume(add); // add == 0 is currently unused @@ -128,7 +127,9 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_ const uint8_t *obmc2= obmc1+ (obmc_stride>>1); const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1); const uint8_t *obmc4= obmc3+ (obmc_stride>>1); - dst = slice_buffer_get_line(sb, src_y + y); + IDWTELEM *dst = sb->line[src_y+y]; + av_assert2(dst); + for(x=0; x<b_w; x++){ int v= obmc1[x] * block[3][x + y*src_stride] +obmc2[x] * block[2][x + y*src_stride] -- 2.52.0 >From a028877e45ef561cbe9a7cfc9bc74029941e9f97 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 10:39:04 +0200 Subject: [PATCH 04/13] avcodec/x86/snow_dwt: Avoid slice_buffer in inner_add_yblock It is unnecessary and avoids the src_y parameter; it also makes this function more ASM-friendly. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow.c | 5 +++-- libavcodec/snow.h | 2 +- libavcodec/snow_dwt.h | 4 ++-- libavcodec/x86/snowdsp.c | 39 +++++++++++++++++++++------------------ 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/libavcodec/snow.c b/libavcodec/snow.c index 76dcdd5488..e61f4f726a 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -116,7 +116,8 @@ static av_cold void init_qpel(SnowContext *const s) } void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t *dst8) +{ int y, x; av_assume(add); // add == 0 is currently unused @@ -127,7 +128,7 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_ const uint8_t *obmc2= obmc1+ (obmc_stride>>1); const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1); const uint8_t *obmc4= obmc3+ (obmc_stride>>1); - IDWTELEM *dst = sb->line[src_y+y]; + IDWTELEM *dst = lines[y]; av_assert2(dst); for(x=0; x<b_w; x++){ diff --git a/libavcodec/snow.h b/libavcodec/snow.h index fa351bd53c..7a38fa057f 100644 --- a/libavcodec/snow.h +++ b/libavcodec/snow.h @@ -313,7 +313,7 @@ static av_always_inline void add_yblock(SnowContext *s, int sliced, slice_buffer ff_snow_pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h); } if(sliced){ - s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, sb->line + src_y, add, dst8); }else{ for(y=0; y<b_h; y++){ //FIXME ugly misuse of obmc_stride diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h index b5803bc99a..d2ebb79328 100644 --- a/libavcodec/snow_dwt.h +++ b/libavcodec/snow_dwt.h @@ -62,7 +62,7 @@ typedef struct SnowDWTContext { void (*horizontal_compose97i)(IDWTELEM *b, IDWTELEM *temp, int width); void (*inner_add_yblock)(const uint8_t *obmc, const int obmc_stride, uint8_t **block, int b_w, int b_h, int src_x, - int src_y, int src_stride, slice_buffer *sb, + int src_stride, IDWTELEM * const *lines, int add, uint8_t *dst8); } SnowDWTContext; @@ -141,7 +141,7 @@ IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line); void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t **block, int b_w, int b_h, int src_x, - int src_y, int src_stride, slice_buffer *sb, + int src_stride, IDWTELEM *const *lines, int add, uint8_t *dst8); int ff_w53_32_c(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t line_size, int h); diff --git a/libavcodec/x86/snowdsp.c b/libavcodec/x86/snowdsp.c index 78a71f4aa5..7cd3fd5415 100644 --- a/libavcodec/x86/snowdsp.c +++ b/libavcodec/x86/snowdsp.c @@ -608,7 +608,6 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM #if HAVE_6REGS #define snow_inner_add_yblock_sse2_header \ - IDWTELEM * * dst_array = sb->line + src_y;\ x86_reg tmp;\ __asm__ volatile(\ "mov %7, %%"FF_REG_c" \n\t"\ @@ -669,7 +668,7 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM #define snow_inner_add_yblock_sse2_end_common2\ "jnz 1b \n\t"\ - :"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\ + :"+m"(dst8),"+m"(lines),"=&r"(tmp)\ :\ "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", )\ @@ -690,7 +689,8 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM snow_inner_add_yblock_sse2_end_common2 static void inner_add_yblock_bw_8_obmc_16_bh_even_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ snow_inner_add_yblock_sse2_header snow_inner_add_yblock_sse2_start_8("xmm1", "xmm5", "3", "0") snow_inner_add_yblock_sse2_accum_8("2", "8") @@ -738,7 +738,8 @@ snow_inner_add_yblock_sse2_end_8 } static void inner_add_yblock_bw_16_obmc_32_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ snow_inner_add_yblock_sse2_header snow_inner_add_yblock_sse2_start_16("xmm1", "xmm5", "3", "0") snow_inner_add_yblock_sse2_accum_16("2", "16") @@ -762,7 +763,6 @@ snow_inner_add_yblock_sse2_end_16 } #define snow_inner_add_yblock_mmx_header \ - IDWTELEM * * dst_array = sb->line + src_y;\ x86_reg tmp;\ __asm__ volatile(\ "mov %7, %%"FF_REG_c" \n\t"\ @@ -818,13 +818,14 @@ snow_inner_add_yblock_sse2_end_16 "add %%"FF_REG_c", %0 \n\t"\ "dec %2 \n\t"\ "jnz 1b \n\t"\ - :"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\ + :"+m"(dst8),"+m"(lines),"=&r"(tmp)\ :\ "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ "%"FF_REG_c"","%"FF_REG_S"","%"FF_REG_D"","%"FF_REG_d""); static void inner_add_yblock_bw_8_obmc_16_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ snow_inner_add_yblock_mmx_header snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") snow_inner_add_yblock_mmx_accum("2", "8", "0") @@ -835,7 +836,8 @@ snow_inner_add_yblock_mmx_end("16") } static void inner_add_yblock_bw_16_obmc_32_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ snow_inner_add_yblock_mmx_header snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") snow_inner_add_yblock_mmx_accum("2", "16", "0") @@ -852,27 +854,28 @@ snow_inner_add_yblock_mmx_end("32") } static void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ - + int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ if (b_w == 16) - inner_add_yblock_bw_16_obmc_32_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + inner_add_yblock_bw_16_obmc_32_sse2(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); else if (b_w == 8 && obmc_stride == 16) { if (!(b_h & 1)) - inner_add_yblock_bw_8_obmc_16_bh_even_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + inner_add_yblock_bw_8_obmc_16_bh_even_sse2(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); else - inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } else - ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) +{ if (b_w == 16) - inner_add_yblock_bw_16_obmc_32_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + inner_add_yblock_bw_16_obmc_32_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); else if (b_w == 8 && obmc_stride == 16) - inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); else - ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } #endif /* HAVE_6REGS */ -- 2.52.0 >From 8a55e7690be335285d20d5901e1062d673b85719 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 10:41:28 +0200 Subject: [PATCH 05/13] avcodec/snow_dwt: Remove pointless forward declaration Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow_dwt.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h index d2ebb79328..a26db62d6d 100644 --- a/libavcodec/snow_dwt.h +++ b/libavcodec/snow_dwt.h @@ -53,8 +53,6 @@ typedef struct slice_buffer_s { IDWTELEM *base_buffer; ///< Buffer that this structure is caching. } slice_buffer; -struct SnowDWTContext; - typedef struct SnowDWTContext { void (*vertical_compose97i)(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, -- 2.52.0 >From 1cf18360c74d7c58218ab78cf7b5ce0ffad1a45a Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 18:20:33 +0200 Subject: [PATCH 06/13] avcodec/snowdata: Add explicit alignment for obmc tables This is in preparation for adding SSSE3 assembly. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snowdata.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/snowdata.h b/libavcodec/snowdata.h index 87ab354385..fa31ae72c2 100644 --- a/libavcodec/snowdata.h +++ b/libavcodec/snowdata.h @@ -23,8 +23,9 @@ #define AVCODEC_SNOWDATA_H #include "snow.h" +#include "libavutil/mem_internal.h" -static const uint8_t obmc32[1024]={ +DECLARE_ALIGNED(16, static const uint8_t, obmc32)[1024]={ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 8, 8, 7, 7, 6, 5, 5, 4, 3, 3, 2, 2, 1, 0, @@ -59,7 +60,7 @@ static const uint8_t obmc32[1024]={ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, //error:0.000020 }; -static const uint8_t obmc16[256]={ +DECLARE_ALIGNED(16, static const uint8_t, obmc16)[256]={ 0, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 2, 2, 1, 1, 0, 1, 2, 4, 5, 7, 8, 10, 11, 11, 10, 8, 7, 5, 4, 2, 1, 1, 4, 6, 9, 11, 14, 16, 19, 19, 16, 14, 11, 9, 6, 4, 1, -- 2.52.0 >From c289e3547e4ff8b1be23ab4a3044b8d7ae622961 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Fri, 10 Apr 2026 10:25:22 +0200 Subject: [PATCH 07/13] tests/checkasm: Add snowdsp test Only inner_add_yblock for now. Hint: Said function uses a pointer to an array of pointers as parameter. The MMX version clobbers the array in such a way that calling the function repeatedly with the same arguments (as happens inside bench_new()) leads to buffer overflows and segfaults. Therefore CALL4 had to be overridden to restore the original pointers. This workaround will be removed soon when the MMX version is removed. Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/Makefile | 1 + tests/checkasm/checkasm.c | 3 + tests/checkasm/checkasm.h | 1 + tests/checkasm/snowdsp.c | 159 ++++++++++++++++++++++++++++++++++++++ tests/fate/checkasm.mak | 1 + 5 files changed, 165 insertions(+) create mode 100644 tests/checkasm/snowdsp.c diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index bf2d6b7ec2..55d2527047 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -50,6 +50,7 @@ AVCODECOBJS-$(CONFIG_PNG_DECODER) += png.o AVCODECOBJS-$(CONFIG_RV34DSP) += rv34dsp.o AVCODECOBJS-$(CONFIG_RV40_DECODER) += rv40dsp.o AVCODECOBJS-$(CONFIG_SBC_ENCODER) += sbcdsp.o +AVCODECOBJS-$(CONFIG_SNOW_DECODER) += snowdsp.o AVCODECOBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o AVCODECOBJS-$(CONFIG_TAK_DECODER) += takdsp.o AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 8629f26788..e863ff6eed 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -253,6 +253,9 @@ static const struct { #if CONFIG_SBC_ENCODER { "sbcdsp", checkasm_check_sbcdsp }, #endif + #if CONFIG_SNOW_DECODER + { "snowdsp", checkasm_check_snowdsp }, + #endif #if CONFIG_SVQ1_ENCODER { "svq1enc", checkasm_check_svq1enc }, #endif diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 43c158e97b..72a1404163 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -141,6 +141,7 @@ void checkasm_check_sbrdsp(void); void checkasm_check_rv34dsp(void); void checkasm_check_rv40dsp(void); void checkasm_check_scene_sad(void); +void checkasm_check_snowdsp(void); void checkasm_check_svq1enc(void); void checkasm_check_synth_filter(void); void checkasm_check_sw_gbrp(void); diff --git a/tests/checkasm/snowdsp.c b/tests/checkasm/snowdsp.c new file mode 100644 index 0000000000..2edad643ad --- /dev/null +++ b/tests/checkasm/snowdsp.c @@ -0,0 +1,159 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include "libavutil/intreadwrite.h" +#include "libavutil/macros.h" +#include "libavutil/mem_internal.h" + +#include "libavcodec/snow.h" +#include "libavcodec/snow_dwt.h" + +#include "checkasm.h" + +#define randomize_buffer(buf) \ +do { \ + for (size_t k = 0; k < (sizeof(buf) & ~3); k += 4) \ + AV_WN32A((char*)buf + k, rnd()); \ + for (size_t k = sizeof(buf) & ~3; k < sizeof(buf); ++k) \ + ((char*)buf)[k] = rnd(); \ +} while (0) + +static void checkasm_check_inner_add_yblock(const SnowDWTContext *const snowdsp) +{ + enum { + LOG2_MAX_BLOCKSIZE = 4, + MAX_BLOCKSIZE = 1 << LOG2_MAX_BLOCKSIZE, + LOG2_MIN_BLOCKSIZE = 1, + MAX_STRIDE = 256, + }; + declare_func_emms(AV_CPU_FLAG_MMX, void, const uint8_t *obmc, const int obmc_stride, + uint8_t **block, int b_w, int b_h, int src_x, + int src_stride, IDWTELEM * const *lines, + int add, uint8_t *dst8); + DECLARE_ALIGNED(16, uint8_t, dst8_ref)[MAX_STRIDE * MAX_BLOCKSIZE]; + DECLARE_ALIGNED(16, uint8_t, dst8_new)[MAX_STRIDE * MAX_BLOCKSIZE]; + DECLARE_ALIGNED(16, uint8_t, block)[4][MAX_STRIDE * (MAX_BLOCKSIZE - 1) + MAX_BLOCKSIZE]; + DECLARE_ALIGNED(16, IDWTELEM, linebuf)[MAX_BLOCKSIZE][MAX_STRIDE]; + int inited = 0; + + for (int i = 0; i < 2; ++i) { + for (int j = LOG2_MIN_BLOCKSIZE; j <= LOG2_MAX_BLOCKSIZE; ++j) { + int b_w = 1 << j; + + if (!check_func(snowdsp->inner_add_yblock, "inner_add_yblock_%d%s", b_w, i ? "_border" : "")) + continue; + + const uint8_t *obmc = ff_obmc_tab[LOG2_MAX_BLOCKSIZE - j]; + int obmc_stride = 2 << j; + int b_h = b_w, mb_x; + int width = 1 + rnd() % MAX_STRIDE; + + if (!i) { + // Test the ordinary case of a complete block. + width = FFMAX(width, 2 * b_w); + int nb_complete_blocks = (width - b_w / 2) / b_w; + mb_x = 1 + rnd() % nb_complete_blocks; + } else { + // Test a boundary block. If width == b_w/2 mod b_w, + // there is no right boundary block, so use the left one. + mb_x = (width + b_w/2) % b_w && rnd() & 1 ? (width + b_w/2) / b_w : 0; + } + ptrdiff_t src_stride = FFALIGN(width + rnd() % (MAX_STRIDE - width + 1), 16); + int src_x = b_w*mb_x - b_w/2; + + if (src_x < 0) { + obmc -= src_x; + b_w += src_x; + src_x = 0; + } + if (src_x + b_w > width) { + b_w = width - src_x; + } + + uint8_t *dst8p_ref = dst8_ref + src_x; + uint8_t *dst8p_new = dst8_new + src_x; + unsigned rand = rnd(); + uint8_t *blocks[4] = { block[rand % 4], block[rand / 4 % 4], + block[rand / 16 % 4], block[rand / 64 % 4] }; + if (rnd() & 1) { // negate stride + dst8p_ref += (b_h - 1) * src_stride; + dst8p_new += (b_h - 1) * src_stride; + blocks[0] += (b_h - 1) * src_stride; + blocks[1] += (b_h - 1) * src_stride; + blocks[2] += (b_h - 1) * src_stride; + blocks[3] += (b_h - 1) * src_stride; + src_stride = -src_stride; + } + uint8_t *blocks_backup[4] = { blocks[0], blocks[1], + blocks[2], blocks[3] }; + IDWTELEM *lines[MAX_BLOCKSIZE]; + + for (int k = 0; k < b_h; ++k) + lines[k] = linebuf[rnd() % MAX_BLOCKSIZE]; + + if (!inited) { + inited = 1; + randomize_buffer(block); + randomize_buffer(dst8_ref); + for (size_t k = 0; k < FF_ARRAY_ELEMS(linebuf); ++k) { + for (size_t l = 0; l < FF_ARRAY_ELEMS(linebuf[0]); ++l) + linebuf[k][l] = sign_extend(rnd(), 15); + } + } + + memcpy(dst8_new, dst8_ref, sizeof(dst8_new)); + + call_ref(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_ref); + memcpy(blocks, blocks_backup, sizeof(blocks));\ + call_new(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_new); + + if (memcmp(dst8_ref, dst8_new, sizeof(dst8_new))) + fail(); + +#undef CALL4 +#define CALL4(...)\ + do {\ + memcpy(blocks, blocks_backup, sizeof(blocks));\ + tfunc(__VA_ARGS__); \ + memcpy(blocks, blocks_backup, sizeof(blocks));\ + tfunc(__VA_ARGS__); \ + memcpy(blocks, blocks_backup, sizeof(blocks));\ + tfunc(__VA_ARGS__); \ + memcpy(blocks, blocks_backup, sizeof(blocks));\ + tfunc(__VA_ARGS__); \ + } while (0) + + bench_new(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_new); + } + } + report("inner_add_yblock"); +} + +void checkasm_check_snowdsp(void) +{ + SnowDWTContext snowdsp; + + ff_dwt_init(&snowdsp); + + checkasm_check_inner_add_yblock(&snowdsp); +} diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 2fb1f693b8..b7392fa745 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -56,6 +56,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp \ fate-checkasm-rv40dsp \ fate-checkasm-sbcdsp \ fate-checkasm-scene_sad \ + fate-checkasm-snowdsp \ fate-checkasm-svq1enc \ fate-checkasm-synth_filter \ fate-checkasm-sw_gbrp \ -- 2.52.0 >From 7aee8017b6f366fde85844beb1378847dfee06d5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Fri, 10 Apr 2026 10:57:45 +0200 Subject: [PATCH 08/13] tests/checkasm/llvidencdsp: Fix nonsense randomization The first loop was never entered due to a precedence problem; the second loop initialized everything, although it was not intended that way. This has been added in 56b8769a1c26dac8fe51319f0c2b94de67a64217. Sorry for this. Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/llvidencdsp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/checkasm/llvidencdsp.c b/tests/checkasm/llvidencdsp.c index 785553f70a..d8ee673e0f 100644 --- a/tests/checkasm/llvidencdsp.c +++ b/tests/checkasm/llvidencdsp.c @@ -28,12 +28,12 @@ #include "checkasm.h" -#define randomize_buffers(buf, size) \ - do { \ - for (size_t j = 0; j < size & ~3; j += 4) \ - AV_WN32(buf + j, rnd()); \ - for (size_t j = 0; j < size; ++j) \ - buf[j] = rnd(); \ +#define randomize_buffers(buf, size) \ + do { \ + for (size_t j = 0; j < (size & ~3); j += 4) \ + AV_WN32(buf + j, rnd()); \ + for (size_t j = size & ~3; j < size; ++j) \ + buf[j] = rnd(); \ } while (0) static const struct {uint8_t w, h, s;} planes[] = { -- 2.52.0 >From 855e6c3976f03370a5df4dcea9637f4eb7bdc7f8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Fri, 10 Apr 2026 11:08:48 +0200 Subject: [PATCH 09/13] tests/checkasm/mpegvideo_unquantize: Fix precedence problem Signed-off-by: Andreas Rheinhardt <[email protected]> --- tests/checkasm/mpegvideo_unquantize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/checkasm/mpegvideo_unquantize.c b/tests/checkasm/mpegvideo_unquantize.c index 0430e20354..9de0bb4284 100644 --- a/tests/checkasm/mpegvideo_unquantize.c +++ b/tests/checkasm/mpegvideo_unquantize.c @@ -36,7 +36,7 @@ static_assert(!(_Alignof(TYPE) % 4), \ "can't use aligned stores"); \ unsigned char *ptr = (unsigned char*)s; \ - for (size_t i = 0; i < sizeof(*s) & ~3; i += 4) \ + for (size_t i = 0; i < (sizeof(*s) & ~3); i += 4) \ AV_WN32A(ptr + i, rnd()); \ for (size_t i = sizeof(*s) & ~3; i < sizeof(*s); ++i) \ ptr[i] = rnd(); \ -- 2.52.0 >From d7869eb9c531c88ed7f4139efeaca54d0b08f7c7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 18:43:54 +0200 Subject: [PATCH 10/13] avcodec/x86/snowdsp: Add SSSE3 inner_add_yblock Compared to the MMX version, this version benefits from wider registers and pmaddubsw. It also has fewer unnecessary loads and stores: On x64, the MMX version has 12 unnecessary GPR loads and 6 stores in each line when width is eight; for width 16, there are 17 unnecessary GPR loads and six stores per line. Even the 32bit SSSE3 version only has six loads and zero stores per line more than the x64 version. Furthermore, in contrast to the MMX version, the SSSE3 version also does not clobber the array of block pointers given to it. Benchmarks: inner_add_yblock_2_c: 29.2 ( 1.00x) inner_add_yblock_2_mmx: 32.5 ( 0.90x) inner_add_yblock_2_ssse3: 28.6 ( 1.02x) inner_add_yblock_4_c: 85.2 ( 1.00x) inner_add_yblock_4_mmx: 89.2 ( 0.96x) inner_add_yblock_4_ssse3: 84.5 ( 1.01x) inner_add_yblock_8_c: 302.0 ( 1.00x) inner_add_yblock_8_mmx: 77.0 ( 3.92x) inner_add_yblock_8_ssse3: 30.6 ( 9.85x) inner_add_yblock_16_c: 1164.7 ( 1.00x) inner_add_yblock_16_mmx: 260.4 ( 4.47x) inner_add_yblock_16_ssse3: 82.3 (14.15x) Both the MMX and SSSE3 versions leave the size 2 and 4 cases to ff_snow_inner_add_yblock_c() (but the MMX version has a prologue at the beginning that it needs to undo before the call, leading to the higher overhead for these sizes). I don't know why the SSSE3 version is marginally faster than the C version in these cases. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/snow.c | 4 +- libavcodec/snow_dwt.c | 2 +- libavcodec/snow_dwt.h | 8 +- libavcodec/x86/Makefile | 6 +- libavcodec/x86/snowdsp.asm | 191 +++++++++++++++++++ libavcodec/x86/{snowdsp.c => snowdsp_init.c} | 17 +- 6 files changed, 216 insertions(+), 12 deletions(-) create mode 100644 libavcodec/x86/snowdsp.asm rename libavcodec/x86/{snowdsp.c => snowdsp_init.c} (98%) diff --git a/libavcodec/snow.c b/libavcodec/snow.c index e61f4f726a..5c13709b5c 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -115,8 +115,8 @@ static av_cold void init_qpel(SnowContext *const s) s->put_snow_qpel_pixels_tab[3][15] = put_snow_qpel2_mc33_8_c; } -void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t *dst8) +void ff_snow_inner_add_yblock_c(const uint8_t *obmc, const int obmc_stride, uint8_t **block, int b_w, int b_h, + int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t *dst8) { int y, x; diff --git a/libavcodec/snow_dwt.c b/libavcodec/snow_dwt.c index eb4d1e4d36..28fbebbe4d 100644 --- a/libavcodec/snow_dwt.c +++ b/libavcodec/snow_dwt.c @@ -852,7 +852,7 @@ av_cold void ff_dwt_init(SnowDWTContext *c) { c->vertical_compose97i = snow_vertical_compose97i; c->horizontal_compose97i = snow_horizontal_compose97i; - c->inner_add_yblock = ff_snow_inner_add_yblock; + c->inner_add_yblock = ff_snow_inner_add_yblock_c; #if ARCH_X86 && HAVE_MMX ff_dwt_init_x86(c); diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h index a26db62d6d..d4a384b267 100644 --- a/libavcodec/snow_dwt.h +++ b/libavcodec/snow_dwt.h @@ -137,10 +137,10 @@ void ff_slice_buffer_flush(slice_buffer *buf); void ff_slice_buffer_destroy(slice_buffer *buf); IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line); -void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, - uint8_t **block, int b_w, int b_h, int src_x, - int src_stride, IDWTELEM *const *lines, - int add, uint8_t *dst8); +void ff_snow_inner_add_yblock_c(const uint8_t *obmc, const int obmc_stride, + uint8_t **block, int b_w, int b_h, int src_x, + int src_stride, IDWTELEM *const *lines, + int add, uint8_t *dst8); int ff_w53_32_c(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t line_size, int h); int ff_w97_32_c(MPVEncContext *v, const uint8_t *pix1, const uint8_t *pix2, ptrdiff_t line_size, int h); diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index bf723ed1a6..e87cb750f4 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -65,8 +65,10 @@ X86ASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o X86ASM-OBJS-$(CONFIG_PRORES_RAW_DECODER) += x86/proresdsp_init.o X86ASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv40dsp_init.o X86ASM-OBJS-$(CONFIG_SBC_ENCODER) += x86/sbcdsp_init.o -OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp.o -OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp.o +OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp_init.o +X86ASM-OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp.o +OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp_init.o +X86ASM-OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp.o X86ASM-OBJS-$(CONFIG_SVQ1_ENCODER) += x86/svq1enc_init.o X86ASM-OBJS-$(CONFIG_TAK_DECODER) += x86/takdsp_init.o OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp_init.o diff --git a/libavcodec/x86/snowdsp.asm b/libavcodec/x86/snowdsp.asm new file mode 100644 index 0000000000..bde9054731 --- /dev/null +++ b/libavcodec/x86/snowdsp.asm @@ -0,0 +1,191 @@ +;* +;* ASM optimized Snow DSP functions +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg 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. +;* +;* FFmpeg 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 FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +cextern snow_inner_add_yblock_c + +SECTION .text + +%assign FRAC_BITS 4 +%assign LOG2_OBMC_MAX 6 + +%macro ADD_YBLOCK_PROLOGUE 1 +%assign stack_offset 0 +%if ARCH_X86_32 + PROLOGUE 1, 7, 7+(%1>>4), obmc, offset, dst8, lines, b_h, src_x, dst + ; copy all four block pointers to the stack to be able to load + ; them via esp + mov r2, r2m + mov b_hd, b_hm + mov src_xd, src_xm + movups m1, [r2] + mov linesq, r7m + shl src_xd, 1 ; convert src_x from IDWTELEM to bytes + mov dst8q, r9m + mov src_xm, src_xd + ; Just reuse the space for the arguments to store the block pointers. +%if HAVE_ALIGNED_STACK + movaps r0m, m1 +%else + movups r0m, m1 +%endif + %define src_strideq r6m +%else ; X64 + PROLOGUE 1, 12, 7+(%1>>4), obmc, offset, dst8, lines, b_h, src_x, src_stride, dst, block0, block1, block2, block3 + mov block0q, [r2q] + mov block1q, [r2q + gprsize] + mov block2q, [r2q + 2*gprsize] + mov block3q, [r2q + 3*gprsize] + movifnidn b_hd, b_hm + movifnidn src_xd, src_xm + shl src_xd, 1 ; convert src_x from IDWTELEM to bytes and zero-extend it + movsxd src_strideq, src_stridem + mov linesq, r7mp + mov dst8q, r9mp +%endif + xor offsetd, offsetd + psllw m0, FRAC_BITS - 1 ; pw_m8 +%endmacro + +%macro LOAD_BLOCKPOINTER_FOR_X86_32 2 +%if ARCH_X86_32 + ; we put block #i into the spot of register r#i + mov r5, r %+ %1 %+ m + mov r6, r %+ %2 %+ m + %xdefine block%1q r5 + %xdefine block%2q r6 +%endif +%endmacro + +INIT_XMM ssse3 +; void ff_snow_inner_add_yblock_ssse3(const uint8_t *obmc, const int obmc_stride, +; uint8_t **block, int b_w, int b_h, int src_x, +; int src_stride, IDWTELEM *const *lines, +; int add, uint8_t *dst8); +; Don't use cglobal to load args, as we may want to perform +; a tail call to ff_snow_inner_add_yblock. +cglobal snow_inner_add_yblock + pcmpeqw m0, m0 +%if ARCH_X86_32 + mov r0d, r3m ; block width + cmp r0d, 16 + je .w16 + cmp r0d, 8 + jne snow_inner_add_yblock_c + cmp r1mp, 16 + jne snow_inner_add_yblock_c +%else + ; all arguments used to check for support are already in registers + cmp r3d, 16 + je .w16 + cmp r3d, 8 + jne snow_inner_add_yblock_c + cmp r1d, 16 + jne snow_inner_add_yblock_c +%endif + ADD_YBLOCK_PROLOGUE 8 + .loop8: + LOAD_BLOCKPOINTER_FOR_X86_32 1, 3 + movq m3, [block3q+offsetq] + movq m4, [block1q+offsetq] + mova m1, [obmcq] + mova m2, [obmcq+16*8] +%if ARCH_X86_64 + mov dstq, [linesq] +%endif + LOAD_BLOCKPOINTER_FOR_X86_32 0, 2 + movq m5, [block2q+offsetq] + movq m6, [block0q+offsetq] + punpcklbw m3, m4 +%if ARCH_X86_32 + mov dstq, [linesq] + add dstq, src_xm +%endif + SBUTTERFLY bw, 1, 2, 4 +%if ARCH_X86_64 + movu m4, [dstq+src_xq] +%else + movu m4, [dstq] +%endif + pmaddubsw m3, m1 + add obmcq, 16 + punpcklbw m5, m6 + pmaddubsw m5, m2 + add linesq, gprsize + paddw m3, m5 + psubw m4, m0 ; + 1<<(FRAC_BITS-1) + psrlw m3, LOG2_OBMC_MAX - FRAC_BITS + paddw m3, m4 + psraw m3, FRAC_BITS + packuswb m3, m3 + movq [dst8q+offsetq], m3 + add offsetq, src_strideq + dec b_hd + jnz .loop8 + RET + .w16: + ADD_YBLOCK_PROLOGUE 16 + .loop16: + LOAD_BLOCKPOINTER_FOR_X86_32 2, 3 + mova m3, [block3q+offsetq] + mova m4, [block2q+offsetq] + mova m1, [obmcq] + mova m2, [obmcq+16] + LOAD_BLOCKPOINTER_FOR_X86_32 0, 1 + SBUTTERFLY bw, 3, 4, 7 + mova m5, [block1q+offsetq] + mova m6, [block0q+offsetq] + SBUTTERFLY bw, 1, 2, 7 + mov dstq, [linesq] + pmaddubsw m3, m1 + mova m1, [obmcq+32*16] + pmaddubsw m4, m2 + mova m2, [obmcq+32*16+16] +%if ARCH_X86_32 + add dstq, src_xm +%endif + SBUTTERFLY bw, 5, 6, 7 + SBUTTERFLY bw, 1, 2, 7 + pmaddubsw m5, m1 + add linesq, gprsize + pmaddubsw m6, m2 + paddw m3, m5 + paddw m4, m6 + psrlw m3, LOG2_OBMC_MAX - FRAC_BITS + psrlw m4, LOG2_OBMC_MAX - FRAC_BITS + add obmcq, 32 +%if ARCH_X86_32 + paddw m3, [dstq] + paddw m4, [dstq+16] +%else + paddw m3, [dstq+src_xq] + paddw m4, [dstq+src_xq+16] +%endif + psubw m3, m0 ; + 1<<(FRAC_BITS-1) + psubw m4, m0 ; + 1<<(FRAC_BITS-1) + psraw m3, FRAC_BITS + psraw m4, FRAC_BITS + packuswb m3, m4 + movu [dst8q+offsetq], m3 + add offsetq, src_strideq + dec b_hd + jnz .loop16 + RET diff --git a/libavcodec/x86/snowdsp.c b/libavcodec/x86/snowdsp_init.c similarity index 98% rename from libavcodec/x86/snowdsp.c rename to libavcodec/x86/snowdsp_init.c index 7cd3fd5415..2a120cd0e0 100644 --- a/libavcodec/x86/snowdsp.c +++ b/libavcodec/x86/snowdsp_init.c @@ -24,8 +24,14 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" #include "libavcodec/snow_dwt.h" +void ff_snow_inner_add_yblock_ssse3(const uint8_t *obmc, const int obmc_stride, + uint8_t **block, int b_w, int b_h, int src_x, + int src_stride, IDWTELEM *const *lines, + int add, uint8_t *dst8); + #if HAVE_INLINE_ASM static void ff_snow_horizontal_compose97i_sse2(IDWTELEM *b, IDWTELEM *temp, int width){ @@ -864,7 +870,7 @@ static void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_st else inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } else - ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); + ff_snow_inner_add_yblock_c(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, @@ -875,7 +881,7 @@ static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_str else if (b_w == 8 && obmc_stride == 16) inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); else - ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); + ff_snow_inner_add_yblock_c(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); } #endif /* HAVE_6REGS */ @@ -883,9 +889,9 @@ static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_str av_cold void ff_dwt_init_x86(SnowDWTContext *c) { -#if HAVE_INLINE_ASM int mm_flags = av_get_cpu_flags(); +#if HAVE_INLINE_ASM if (mm_flags & AV_CPU_FLAG_MMX) { if(mm_flags & AV_CPU_FLAG_SSE2 & 0){ c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; @@ -909,4 +915,9 @@ av_cold void ff_dwt_init_x86(SnowDWTContext *c) } } #endif /* HAVE_INLINE_ASM */ +#if HAVE_SSSE3_EXTERNAL + if (EXTERNAL_SSSE3(mm_flags)) { + c->inner_add_yblock = ff_snow_inner_add_yblock_ssse3; + } +#endif } -- 2.52.0 >From 9303de3d4681250333a702c84c3cce4b860c4e6e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 20:35:06 +0200 Subject: [PATCH 11/13] avcodec/x86/snowdsp_init: Remove MMXEXT, SSE2 inner_add_yblock versions They have been superseded by SSSE3; the SSE2 version was even disabled (and segfaults if enabled). Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/snowdsp_init.c | 281 ---------------------------------- tests/checkasm/snowdsp.c | 18 +-- 2 files changed, 1 insertion(+), 298 deletions(-) diff --git a/libavcodec/x86/snowdsp_init.c b/libavcodec/x86/snowdsp_init.c index 2a120cd0e0..18c7cfd364 100644 --- a/libavcodec/x86/snowdsp_init.c +++ b/libavcodec/x86/snowdsp_init.c @@ -612,279 +612,6 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM } #endif //HAVE_7REGS -#if HAVE_6REGS -#define snow_inner_add_yblock_sse2_header \ - x86_reg tmp;\ - __asm__ volatile(\ - "mov %7, %%"FF_REG_c" \n\t"\ - "mov %6, %2 \n\t"\ - "mov %4, %%"FF_REG_S" \n\t"\ - "pxor %%xmm7, %%xmm7 \n\t" /* 0 */\ - "pcmpeqd %%xmm3, %%xmm3 \n\t"\ - "psllw $15, %%xmm3 \n\t"\ - "psrlw $12, %%xmm3 \n\t" /* FRAC_BITS >> 1 */\ - "1: \n\t"\ - "mov %1, %%"FF_REG_D" \n\t"\ - "mov (%%"FF_REG_D"), %%"FF_REG_D" \n\t"\ - "add %3, %%"FF_REG_D" \n\t" - -#define snow_inner_add_yblock_sse2_start_8(out_reg1, out_reg2, ptr_offset, s_offset)\ - "mov "FF_PTR_SIZE"*"ptr_offset"(%%"FF_REG_a"), %%"FF_REG_d"; \n\t"\ - "movq (%%"FF_REG_d"), %%"out_reg1" \n\t"\ - "movq (%%"FF_REG_d", %%"FF_REG_c"), %%"out_reg2" \n\t"\ - "punpcklbw %%xmm7, %%"out_reg1" \n\t"\ - "punpcklbw %%xmm7, %%"out_reg2" \n\t"\ - "movq "s_offset"(%%"FF_REG_S"), %%xmm0 \n\t"\ - "movq "s_offset"+16(%%"FF_REG_S"), %%xmm4 \n\t"\ - "punpcklbw %%xmm7, %%xmm0 \n\t"\ - "punpcklbw %%xmm7, %%xmm4 \n\t"\ - "pmullw %%xmm0, %%"out_reg1" \n\t"\ - "pmullw %%xmm4, %%"out_reg2" \n\t" - -#define snow_inner_add_yblock_sse2_start_16(out_reg1, out_reg2, ptr_offset, s_offset)\ - "mov "FF_PTR_SIZE"*"ptr_offset"(%%"FF_REG_a"), %%"FF_REG_d"; \n\t"\ - "movq (%%"FF_REG_d"), %%"out_reg1" \n\t"\ - "movq 8(%%"FF_REG_d"), %%"out_reg2" \n\t"\ - "punpcklbw %%xmm7, %%"out_reg1" \n\t"\ - "punpcklbw %%xmm7, %%"out_reg2" \n\t"\ - "movq "s_offset"(%%"FF_REG_S"), %%xmm0 \n\t"\ - "movq "s_offset"+8(%%"FF_REG_S"), %%xmm4 \n\t"\ - "punpcklbw %%xmm7, %%xmm0 \n\t"\ - "punpcklbw %%xmm7, %%xmm4 \n\t"\ - "pmullw %%xmm0, %%"out_reg1" \n\t"\ - "pmullw %%xmm4, %%"out_reg2" \n\t" - -#define snow_inner_add_yblock_sse2_accum_8(ptr_offset, s_offset) \ - snow_inner_add_yblock_sse2_start_8("xmm2", "xmm6", ptr_offset, s_offset)\ - "paddusw %%xmm2, %%xmm1 \n\t"\ - "paddusw %%xmm6, %%xmm5 \n\t" - -#define snow_inner_add_yblock_sse2_accum_16(ptr_offset, s_offset) \ - snow_inner_add_yblock_sse2_start_16("xmm2", "xmm6", ptr_offset, s_offset)\ - "paddusw %%xmm2, %%xmm1 \n\t"\ - "paddusw %%xmm6, %%xmm5 \n\t" - -#define snow_inner_add_yblock_sse2_end_common1\ - "add $32, %%"FF_REG_S" \n\t"\ - "add %%"FF_REG_c", %0 \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*3(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*2(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*1(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", (%%"FF_REG_a") \n\t" - -#define snow_inner_add_yblock_sse2_end_common2\ - "jnz 1b \n\t"\ - :"+m"(dst8),"+m"(lines),"=&r"(tmp)\ - :\ - "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ - XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", )\ - "%"FF_REG_c"","%"FF_REG_S"","%"FF_REG_D"","%"FF_REG_d""); - -#define snow_inner_add_yblock_sse2_end_8\ - "sal $1, %%"FF_REG_c" \n\t"\ - "add"FF_OPSIZE" $"FF_PTR_SIZE"*2, %1 \n\t"\ - snow_inner_add_yblock_sse2_end_common1\ - "sar $1, %%"FF_REG_c" \n\t"\ - "sub $2, %2 \n\t"\ - snow_inner_add_yblock_sse2_end_common2 - -#define snow_inner_add_yblock_sse2_end_16\ - "add"FF_OPSIZE" $"FF_PTR_SIZE"*1, %1 \n\t"\ - snow_inner_add_yblock_sse2_end_common1\ - "dec %2 \n\t"\ - snow_inner_add_yblock_sse2_end_common2 - -static void inner_add_yblock_bw_8_obmc_16_bh_even_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ -snow_inner_add_yblock_sse2_header -snow_inner_add_yblock_sse2_start_8("xmm1", "xmm5", "3", "0") -snow_inner_add_yblock_sse2_accum_8("2", "8") -snow_inner_add_yblock_sse2_accum_8("1", "128") -snow_inner_add_yblock_sse2_accum_8("0", "136") - - "mov %0, %%"FF_REG_d" \n\t" - "movdqa (%%"FF_REG_D"), %%xmm0 \n\t" - "movdqa %%xmm1, %%xmm2 \n\t" - - "punpckhwd %%xmm7, %%xmm1 \n\t" - "punpcklwd %%xmm7, %%xmm2 \n\t" - "paddd %%xmm2, %%xmm0 \n\t" - "movdqa 16(%%"FF_REG_D"), %%xmm2\n\t" - "paddd %%xmm1, %%xmm2 \n\t" - "paddd %%xmm3, %%xmm0 \n\t" - "paddd %%xmm3, %%xmm2 \n\t" - - "mov %1, %%"FF_REG_D" \n\t" - "mov "FF_PTR_SIZE"(%%"FF_REG_D"), %%"FF_REG_D"; \n\t" - "add %3, %%"FF_REG_D" \n\t" - - "movdqa (%%"FF_REG_D"), %%xmm4 \n\t" - "movdqa %%xmm5, %%xmm6 \n\t" - "punpckhwd %%xmm7, %%xmm5 \n\t" - "punpcklwd %%xmm7, %%xmm6 \n\t" - "paddd %%xmm6, %%xmm4 \n\t" - "movdqa 16(%%"FF_REG_D"), %%xmm6\n\t" - "paddd %%xmm5, %%xmm6 \n\t" - "paddd %%xmm3, %%xmm4 \n\t" - "paddd %%xmm3, %%xmm6 \n\t" - - "psrad $8, %%xmm0 \n\t" /* FRAC_BITS. */ - "psrad $8, %%xmm2 \n\t" /* FRAC_BITS. */ - "packssdw %%xmm2, %%xmm0 \n\t" - "packuswb %%xmm7, %%xmm0 \n\t" - "movq %%xmm0, (%%"FF_REG_d") \n\t" - - "psrad $8, %%xmm4 \n\t" /* FRAC_BITS. */ - "psrad $8, %%xmm6 \n\t" /* FRAC_BITS. */ - "packssdw %%xmm6, %%xmm4 \n\t" - "packuswb %%xmm7, %%xmm4 \n\t" - "movq %%xmm4, (%%"FF_REG_d",%%"FF_REG_c"); \n\t" -snow_inner_add_yblock_sse2_end_8 -} - -static void inner_add_yblock_bw_16_obmc_32_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ -snow_inner_add_yblock_sse2_header -snow_inner_add_yblock_sse2_start_16("xmm1", "xmm5", "3", "0") -snow_inner_add_yblock_sse2_accum_16("2", "16") -snow_inner_add_yblock_sse2_accum_16("1", "512") -snow_inner_add_yblock_sse2_accum_16("0", "528") - - "mov %0, %%"FF_REG_d" \n\t" - "psrlw $2, %%xmm1 \n\t" - "psrlw $2, %%xmm5 \n\t" - "paddw (%%"FF_REG_D"), %%xmm1 \n\t" - "paddw 16(%%"FF_REG_D"), %%xmm5 \n\t" - "paddw %%xmm3, %%xmm1 \n\t" - "paddw %%xmm3, %%xmm5 \n\t" - "psraw $4, %%xmm1 \n\t" /* FRAC_BITS. */ - "psraw $4, %%xmm5 \n\t" /* FRAC_BITS. */ - "packuswb %%xmm5, %%xmm1 \n\t" - - "movdqu %%xmm1, (%%"FF_REG_d") \n\t" - -snow_inner_add_yblock_sse2_end_16 -} - -#define snow_inner_add_yblock_mmx_header \ - x86_reg tmp;\ - __asm__ volatile(\ - "mov %7, %%"FF_REG_c" \n\t"\ - "mov %6, %2 \n\t"\ - "mov %4, %%"FF_REG_S" \n\t"\ - "pxor %%mm7, %%mm7 \n\t" /* 0 */\ - "pcmpeqd %%mm3, %%mm3 \n\t"\ - "psllw $15, %%mm3 \n\t"\ - "psrlw $12, %%mm3 \n\t" /* FRAC_BITS >> 1 */\ - "1: \n\t"\ - "mov %1, %%"FF_REG_D" \n\t"\ - "mov (%%"FF_REG_D"), %%"FF_REG_D" \n\t"\ - "add %3, %%"FF_REG_D" \n\t" - -#define snow_inner_add_yblock_mmx_start(out_reg1, out_reg2, ptr_offset, s_offset, d_offset)\ - "mov "FF_PTR_SIZE"*"ptr_offset"(%%"FF_REG_a"), %%"FF_REG_d"; \n\t"\ - "movd "d_offset"(%%"FF_REG_d"), %%"out_reg1" \n\t"\ - "movd "d_offset"+4(%%"FF_REG_d"), %%"out_reg2" \n\t"\ - "punpcklbw %%mm7, %%"out_reg1" \n\t"\ - "punpcklbw %%mm7, %%"out_reg2" \n\t"\ - "movd "s_offset"(%%"FF_REG_S"), %%mm0 \n\t"\ - "movd "s_offset"+4(%%"FF_REG_S"), %%mm4 \n\t"\ - "punpcklbw %%mm7, %%mm0 \n\t"\ - "punpcklbw %%mm7, %%mm4 \n\t"\ - "pmullw %%mm0, %%"out_reg1" \n\t"\ - "pmullw %%mm4, %%"out_reg2" \n\t" - -#define snow_inner_add_yblock_mmx_accum(ptr_offset, s_offset, d_offset) \ - snow_inner_add_yblock_mmx_start("mm2", "mm6", ptr_offset, s_offset, d_offset)\ - "paddusw %%mm2, %%mm1 \n\t"\ - "paddusw %%mm6, %%mm5 \n\t" - -#define snow_inner_add_yblock_mmx_mix(read_offset, write_offset)\ - "mov %0, %%"FF_REG_d" \n\t"\ - "psrlw $2, %%mm1 \n\t"\ - "psrlw $2, %%mm5 \n\t"\ - "paddw "read_offset"(%%"FF_REG_D"), %%mm1 \n\t"\ - "paddw "read_offset"+8(%%"FF_REG_D"), %%mm5 \n\t"\ - "paddw %%mm3, %%mm1 \n\t"\ - "paddw %%mm3, %%mm5 \n\t"\ - "psraw $4, %%mm1 \n\t"\ - "psraw $4, %%mm5 \n\t"\ - "packuswb %%mm5, %%mm1 \n\t"\ - "movq %%mm1, "write_offset"(%%"FF_REG_d") \n\t" - -#define snow_inner_add_yblock_mmx_end(s_step)\ - "add $"s_step", %%"FF_REG_S" \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*3(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*2(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", "FF_PTR_SIZE"*1(%%"FF_REG_a"); \n\t"\ - "add %%"FF_REG_c", (%%"FF_REG_a") \n\t"\ - "add"FF_OPSIZE " $"FF_PTR_SIZE"*1, %1 \n\t"\ - "add %%"FF_REG_c", %0 \n\t"\ - "dec %2 \n\t"\ - "jnz 1b \n\t"\ - :"+m"(dst8),"+m"(lines),"=&r"(tmp)\ - :\ - "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ - "%"FF_REG_c"","%"FF_REG_S"","%"FF_REG_D"","%"FF_REG_d""); - -static void inner_add_yblock_bw_8_obmc_16_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ -snow_inner_add_yblock_mmx_header -snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") -snow_inner_add_yblock_mmx_accum("2", "8", "0") -snow_inner_add_yblock_mmx_accum("1", "128", "0") -snow_inner_add_yblock_mmx_accum("0", "136", "0") -snow_inner_add_yblock_mmx_mix("0", "0") -snow_inner_add_yblock_mmx_end("16") -} - -static void inner_add_yblock_bw_16_obmc_32_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, - int src_x, x86_reg src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ -snow_inner_add_yblock_mmx_header -snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") -snow_inner_add_yblock_mmx_accum("2", "16", "0") -snow_inner_add_yblock_mmx_accum("1", "512", "0") -snow_inner_add_yblock_mmx_accum("0", "528", "0") -snow_inner_add_yblock_mmx_mix("0", "0") - -snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "8", "8") -snow_inner_add_yblock_mmx_accum("2", "24", "8") -snow_inner_add_yblock_mmx_accum("1", "520", "8") -snow_inner_add_yblock_mmx_accum("0", "536", "8") -snow_inner_add_yblock_mmx_mix("16", "8") -snow_inner_add_yblock_mmx_end("32") -} - -static void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ - if (b_w == 16) - inner_add_yblock_bw_16_obmc_32_sse2(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); - else if (b_w == 8 && obmc_stride == 16) { - if (!(b_h & 1)) - inner_add_yblock_bw_8_obmc_16_bh_even_sse2(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); - else - inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); - } else - ff_snow_inner_add_yblock_c(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); -} - -static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, - int src_x, int src_stride, IDWTELEM *const *lines, int add, uint8_t * dst8) -{ - if (b_w == 16) - inner_add_yblock_bw_16_obmc_32_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); - else if (b_w == 8 && obmc_stride == 16) - inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); - else - ff_snow_inner_add_yblock_c(obmc, obmc_stride, block, b_w, b_h, src_x, src_stride, lines, add, dst8); -} -#endif /* HAVE_6REGS */ - #endif /* HAVE_INLINE_ASM */ av_cold void ff_dwt_init_x86(SnowDWTContext *c) @@ -892,14 +619,10 @@ av_cold void ff_dwt_init_x86(SnowDWTContext *c) int mm_flags = av_get_cpu_flags(); #if HAVE_INLINE_ASM - if (mm_flags & AV_CPU_FLAG_MMX) { if(mm_flags & AV_CPU_FLAG_SSE2 & 0){ c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; #if HAVE_7REGS c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; -#endif -#if HAVE_6REGS - c->inner_add_yblock = ff_snow_inner_add_yblock_sse2; #endif } else{ @@ -909,11 +632,7 @@ av_cold void ff_dwt_init_x86(SnowDWTContext *c) c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; #endif } -#if HAVE_6REGS - c->inner_add_yblock = ff_snow_inner_add_yblock_mmx; -#endif } - } #endif /* HAVE_INLINE_ASM */ #if HAVE_SSSE3_EXTERNAL if (EXTERNAL_SSSE3(mm_flags)) { diff --git a/tests/checkasm/snowdsp.c b/tests/checkasm/snowdsp.c index 2edad643ad..99cfae679e 100644 --- a/tests/checkasm/snowdsp.c +++ b/tests/checkasm/snowdsp.c @@ -46,7 +46,7 @@ static void checkasm_check_inner_add_yblock(const SnowDWTContext *const snowdsp) LOG2_MIN_BLOCKSIZE = 1, MAX_STRIDE = 256, }; - declare_func_emms(AV_CPU_FLAG_MMX, void, const uint8_t *obmc, const int obmc_stride, + declare_func(void, const uint8_t *obmc, const int obmc_stride, uint8_t **block, int b_w, int b_h, int src_x, int src_stride, IDWTELEM * const *lines, int add, uint8_t *dst8); @@ -104,8 +104,6 @@ static void checkasm_check_inner_add_yblock(const SnowDWTContext *const snowdsp) blocks[3] += (b_h - 1) * src_stride; src_stride = -src_stride; } - uint8_t *blocks_backup[4] = { blocks[0], blocks[1], - blocks[2], blocks[3] }; IDWTELEM *lines[MAX_BLOCKSIZE]; for (int k = 0; k < b_h; ++k) @@ -124,25 +122,11 @@ static void checkasm_check_inner_add_yblock(const SnowDWTContext *const snowdsp) memcpy(dst8_new, dst8_ref, sizeof(dst8_new)); call_ref(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_ref); - memcpy(blocks, blocks_backup, sizeof(blocks));\ call_new(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_new); if (memcmp(dst8_ref, dst8_new, sizeof(dst8_new))) fail(); -#undef CALL4 -#define CALL4(...)\ - do {\ - memcpy(blocks, blocks_backup, sizeof(blocks));\ - tfunc(__VA_ARGS__); \ - memcpy(blocks, blocks_backup, sizeof(blocks));\ - tfunc(__VA_ARGS__); \ - memcpy(blocks, blocks_backup, sizeof(blocks));\ - tfunc(__VA_ARGS__); \ - memcpy(blocks, blocks_backup, sizeof(blocks));\ - tfunc(__VA_ARGS__); \ - } while (0) - bench_new(obmc, obmc_stride, blocks, b_w, b_h, src_x, src_stride, lines, 1, dst8p_new); } } -- 2.52.0 >From 9de8fb46d2b9e5c365f5da90ab58cec39a12689d Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 20:47:11 +0200 Subject: [PATCH 12/13] avcodec/x86/snowdsp_init: Use standard init pattern Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/snowdsp_init.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libavcodec/x86/snowdsp_init.c b/libavcodec/x86/snowdsp_init.c index 18c7cfd364..1d51901f33 100644 --- a/libavcodec/x86/snowdsp_init.c +++ b/libavcodec/x86/snowdsp_init.c @@ -616,26 +616,24 @@ static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM av_cold void ff_dwt_init_x86(SnowDWTContext *c) { - int mm_flags = av_get_cpu_flags(); + int cpuflags = av_get_cpu_flags(); #if HAVE_INLINE_ASM - if(mm_flags & AV_CPU_FLAG_SSE2 & 0){ - c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; + if (INLINE_MMXEXT(cpuflags)) { + c->horizontal_compose97i = ff_snow_horizontal_compose97i_mmx; #if HAVE_7REGS - c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; + c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; #endif - } - else{ - if (mm_flags & AV_CPU_FLAG_MMXEXT) { - c->horizontal_compose97i = ff_snow_horizontal_compose97i_mmx; + } + if (INLINE_SSE2(cpuflags) && 0) { + c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; #if HAVE_7REGS - c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; + c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; #endif - } - } + } #endif /* HAVE_INLINE_ASM */ #if HAVE_SSSE3_EXTERNAL - if (EXTERNAL_SSSE3(mm_flags)) { + if (EXTERNAL_SSSE3(cpuflags)) { c->inner_add_yblock = ff_snow_inner_add_yblock_ssse3; } #endif -- 2.52.0 >From 0b3fbdaf89a2ecb0783837a0058bfc2c6cf9bd20 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Wed, 8 Apr 2026 23:23:30 +0200 Subject: [PATCH 13/13] avcodec/x86/snowdsp_init: Remove disabled SSE2 functions Disabled in 3e0f7126b53b395d9e79df57b2e626eb99ad846b (almost 20 years ago) and no one fixed them, so remove them. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavcodec/x86/snowdsp_init.c | 293 +--------------------------------- 1 file changed, 1 insertion(+), 292 deletions(-) diff --git a/libavcodec/x86/snowdsp_init.c b/libavcodec/x86/snowdsp_init.c index 1d51901f33..34f91c1ee7 100644 --- a/libavcodec/x86/snowdsp_init.c +++ b/libavcodec/x86/snowdsp_init.c @@ -1,5 +1,5 @@ /* - * MMX and SSE2 optimized snow DSP utils + * ASM optimized Snow DSP utils * Copyright (c) 2005-2006 Robert Edele <[email protected]> * * This file is part of FFmpeg. @@ -34,194 +34,6 @@ void ff_snow_inner_add_yblock_ssse3(const uint8_t *obmc, const int obmc_stride, #if HAVE_INLINE_ASM -static void ff_snow_horizontal_compose97i_sse2(IDWTELEM *b, IDWTELEM *temp, int width){ - const int w2= (width+1)>>1; - const int w_l= (width>>1); - const int w_r= w2 - 1; - int i; - - { // Lift 0 - IDWTELEM * const ref = b + w2 - 1; - IDWTELEM b_0 = b[0]; //By allowing the first entry in b[0] to be calculated twice - // (the first time erroneously), we allow the SSE2 code to run an extra pass. - // The savings in code and time are well worth having to store this value and - // calculate b[0] correctly afterwards. - - i = 0; - __asm__ volatile( - "pcmpeqd %%xmm7, %%xmm7 \n\t" - "pcmpeqd %%xmm3, %%xmm3 \n\t" - "psllw $1, %%xmm3 \n\t" - "paddw %%xmm7, %%xmm3 \n\t" - "psllw $13, %%xmm3 \n\t" - ::); - for(; i<w_l-15; i+=16){ - __asm__ volatile( - "movdqu (%1), %%xmm1 \n\t" - "movdqu 16(%1), %%xmm5 \n\t" - "movdqu 2(%1), %%xmm2 \n\t" - "movdqu 18(%1), %%xmm6 \n\t" - "paddw %%xmm1, %%xmm2 \n\t" - "paddw %%xmm5, %%xmm6 \n\t" - "paddw %%xmm7, %%xmm2 \n\t" - "paddw %%xmm7, %%xmm6 \n\t" - "pmulhw %%xmm3, %%xmm2 \n\t" - "pmulhw %%xmm3, %%xmm6 \n\t" - "paddw (%0), %%xmm2 \n\t" - "paddw 16(%0), %%xmm6 \n\t" - "movdqa %%xmm2, (%0) \n\t" - "movdqa %%xmm6, 16(%0) \n\t" - :: "r"(&b[i]), "r"(&ref[i]) - : "memory" - ); - } - snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS); - b[0] = b_0 - ((W_DM * 2 * ref[1]+W_DO)>>W_DS); - } - - { // Lift 1 - IDWTELEM * const dst = b+w2; - - i = 0; - for(; (((x86_reg)&dst[i]) & 0x1F) && i<w_r; i++){ - dst[i] = dst[i] - (b[i] + b[i + 1]); - } - for(; i<w_r-15; i+=16){ - __asm__ volatile( - "movdqu (%1), %%xmm1 \n\t" - "movdqu 16(%1), %%xmm5 \n\t" - "movdqu 2(%1), %%xmm2 \n\t" - "movdqu 18(%1), %%xmm6 \n\t" - "paddw %%xmm1, %%xmm2 \n\t" - "paddw %%xmm5, %%xmm6 \n\t" - "movdqa (%0), %%xmm0 \n\t" - "movdqa 16(%0), %%xmm4 \n\t" - "psubw %%xmm2, %%xmm0 \n\t" - "psubw %%xmm6, %%xmm4 \n\t" - "movdqa %%xmm0, (%0) \n\t" - "movdqa %%xmm4, 16(%0) \n\t" - :: "r"(&dst[i]), "r"(&b[i]) - : "memory" - ); - } - snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS); - } - - { // Lift 2 - IDWTELEM * const ref = b+w2 - 1; - IDWTELEM b_0 = b[0]; - - i = 0; - __asm__ volatile( - "psllw $15, %%xmm7 \n\t" - "pcmpeqw %%xmm6, %%xmm6 \n\t" - "psrlw $13, %%xmm6 \n\t" - "paddw %%xmm7, %%xmm6 \n\t" - ::); - for(; i<w_l-15; i+=16){ - __asm__ volatile( - "movdqu (%1), %%xmm0 \n\t" - "movdqu 16(%1), %%xmm4 \n\t" - "movdqu 2(%1), %%xmm1 \n\t" - "movdqu 18(%1), %%xmm5 \n\t" //FIXME try aligned reads and shifts - "paddw %%xmm6, %%xmm0 \n\t" - "paddw %%xmm6, %%xmm4 \n\t" - "paddw %%xmm7, %%xmm1 \n\t" - "paddw %%xmm7, %%xmm5 \n\t" - "pavgw %%xmm1, %%xmm0 \n\t" - "pavgw %%xmm5, %%xmm4 \n\t" - "psubw %%xmm7, %%xmm0 \n\t" - "psubw %%xmm7, %%xmm4 \n\t" - "psraw $1, %%xmm0 \n\t" - "psraw $1, %%xmm4 \n\t" - "movdqa (%0), %%xmm1 \n\t" - "movdqa 16(%0), %%xmm5 \n\t" - "paddw %%xmm1, %%xmm0 \n\t" - "paddw %%xmm5, %%xmm4 \n\t" - "psraw $2, %%xmm0 \n\t" - "psraw $2, %%xmm4 \n\t" - "paddw %%xmm1, %%xmm0 \n\t" - "paddw %%xmm5, %%xmm4 \n\t" - "movdqa %%xmm0, (%0) \n\t" - "movdqa %%xmm4, 16(%0) \n\t" - :: "r"(&b[i]), "r"(&ref[i]) - : "memory" - ); - } - snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l); - b[0] = b_0 + ((2 * ref[1] + W_BO-1 + 4 * b_0) >> W_BS); - } - - { // Lift 3 - IDWTELEM * const src = b+w2; - - i = 0; - for(; (((x86_reg)&temp[i]) & 0x1F) && i<w_r; i++){ - temp[i] = src[i] - ((-W_AM*(b[i] + b[i+1]))>>W_AS); - } - for(; i<w_r-7; i+=8){ - __asm__ volatile( - "movdqu 2(%1), %%xmm2 \n\t" - "movdqu 18(%1), %%xmm6 \n\t" - "paddw (%1), %%xmm2 \n\t" - "paddw 16(%1), %%xmm6 \n\t" - "movdqu (%0), %%xmm0 \n\t" - "movdqu 16(%0), %%xmm4 \n\t" - "paddw %%xmm2, %%xmm0 \n\t" - "paddw %%xmm6, %%xmm4 \n\t" - "psraw $1, %%xmm2 \n\t" - "psraw $1, %%xmm6 \n\t" - "paddw %%xmm0, %%xmm2 \n\t" - "paddw %%xmm4, %%xmm6 \n\t" - "movdqa %%xmm2, (%2) \n\t" - "movdqa %%xmm6, 16(%2) \n\t" - :: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i]) - : "memory" - ); - } - snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO+1, W_AS); - } - - { - snow_interleave_line_header(&i, width, b, temp); - - for (; (i & 0x3E) != 0x3E; i-=2){ - b[i+1] = temp[i>>1]; - b[i] = b[i>>1]; - } - for (i-=62; i>=0; i-=64){ - __asm__ volatile( - "movdqa (%1), %%xmm0 \n\t" - "movdqa 16(%1), %%xmm2 \n\t" - "movdqa 32(%1), %%xmm4 \n\t" - "movdqa 48(%1), %%xmm6 \n\t" - "movdqa (%1), %%xmm1 \n\t" - "movdqa 16(%1), %%xmm3 \n\t" - "movdqa 32(%1), %%xmm5 \n\t" - "movdqa 48(%1), %%xmm7 \n\t" - "punpcklwd (%2), %%xmm0 \n\t" - "punpcklwd 16(%2), %%xmm2 \n\t" - "punpcklwd 32(%2), %%xmm4 \n\t" - "punpcklwd 48(%2), %%xmm6 \n\t" - "movdqa %%xmm0, (%0) \n\t" - "movdqa %%xmm2, 32(%0) \n\t" - "movdqa %%xmm4, 64(%0) \n\t" - "movdqa %%xmm6, 96(%0) \n\t" - "punpckhwd (%2), %%xmm1 \n\t" - "punpckhwd 16(%2), %%xmm3 \n\t" - "punpckhwd 32(%2), %%xmm5 \n\t" - "punpckhwd 48(%2), %%xmm7 \n\t" - "movdqa %%xmm1, 16(%0) \n\t" - "movdqa %%xmm3, 48(%0) \n\t" - "movdqa %%xmm5, 80(%0) \n\t" - "movdqa %%xmm7, 112(%0) \n\t" - :: "r"(&(b)[i]), "r"(&(b)[i>>1]), "r"(&(temp)[i>>1]) - : "memory" - ); - } - } -} - static void ff_snow_horizontal_compose97i_mmx(IDWTELEM *b, IDWTELEM *temp, int width){ const int w2= (width+1)>>1; const int w_l= (width>>1); @@ -396,30 +208,12 @@ static void ff_snow_horizontal_compose97i_mmx(IDWTELEM *b, IDWTELEM *temp, int w } #if HAVE_7REGS -#define snow_vertical_compose_sse2_load_add(op,r,t0,t1,t2,t3)\ - ""op" ("r",%%"FF_REG_d"), %%"t0" \n\t"\ - ""op" 16("r",%%"FF_REG_d"), %%"t1" \n\t"\ - ""op" 32("r",%%"FF_REG_d"), %%"t2" \n\t"\ - ""op" 48("r",%%"FF_REG_d"), %%"t3" \n\t" - -#define snow_vertical_compose_sse2_load(r,t0,t1,t2,t3)\ - snow_vertical_compose_sse2_load_add("movdqa",r,t0,t1,t2,t3) - -#define snow_vertical_compose_sse2_add(r,t0,t1,t2,t3)\ - snow_vertical_compose_sse2_load_add("paddw",r,t0,t1,t2,t3) - #define snow_vertical_compose_r2r_sub(s0,s1,s2,s3,t0,t1,t2,t3)\ "psubw %%"s0", %%"t0" \n\t"\ "psubw %%"s1", %%"t1" \n\t"\ "psubw %%"s2", %%"t2" \n\t"\ "psubw %%"s3", %%"t3" \n\t" -#define snow_vertical_compose_sse2_store(w,s0,s1,s2,s3)\ - "movdqa %%"s0", ("w",%%"FF_REG_d") \n\t"\ - "movdqa %%"s1", 16("w",%%"FF_REG_d") \n\t"\ - "movdqa %%"s2", 32("w",%%"FF_REG_d") \n\t"\ - "movdqa %%"s3", 48("w",%%"FF_REG_d") \n\t" - #define snow_vertical_compose_sra(n,t0,t1,t2,t3)\ "psraw $"n", %%"t0" \n\t"\ "psraw $"n", %%"t1" \n\t"\ @@ -438,85 +232,6 @@ static void ff_snow_horizontal_compose97i_mmx(IDWTELEM *b, IDWTELEM *temp, int w "pmulhw %%"s2", %%"t2" \n\t"\ "pmulhw %%"s3", %%"t3" \n\t" -#define snow_vertical_compose_sse2_move(s0,s1,s2,s3,t0,t1,t2,t3)\ - "movdqa %%"s0", %%"t0" \n\t"\ - "movdqa %%"s1", %%"t1" \n\t"\ - "movdqa %%"s2", %%"t2" \n\t"\ - "movdqa %%"s3", %%"t3" \n\t" - -static void ff_snow_vertical_compose97i_sse2(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){ - x86_reg i = width; - - while(i & 0x1F) - { - i--; - b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS; - b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS; - b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS; - b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; - } - i+=i; - - __asm__ volatile ( - "jmp 2f \n\t" - "1: \n\t" - snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%6","xmm0","xmm2","xmm4","xmm6") - - - "pcmpeqw %%xmm0, %%xmm0 \n\t" - "pcmpeqw %%xmm2, %%xmm2 \n\t" - "paddw %%xmm2, %%xmm2 \n\t" - "paddw %%xmm0, %%xmm2 \n\t" - "psllw $13, %%xmm2 \n\t" - snow_vertical_compose_r2r_add("xmm0","xmm0","xmm0","xmm0","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_r2r_pmulhw("xmm2","xmm2","xmm2","xmm2","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_sse2_add("%5","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_sse2_store("%5","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%3","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_r2r_sub("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_store("%4","xmm0","xmm2","xmm4","xmm6") - - "pcmpeqw %%xmm7, %%xmm7 \n\t" - "pcmpeqw %%xmm5, %%xmm5 \n\t" - "psllw $15, %%xmm7 \n\t" - "psrlw $13, %%xmm5 \n\t" - "paddw %%xmm7, %%xmm5 \n\t" - snow_vertical_compose_r2r_add("xmm5","xmm5","xmm5","xmm5","xmm0","xmm2","xmm4","xmm6") - "movq (%2,%%"FF_REG_d"), %%xmm1 \n\t" - "movq 8(%2,%%"FF_REG_d"), %%xmm3 \n\t" - "paddw %%xmm7, %%xmm1 \n\t" - "paddw %%xmm7, %%xmm3 \n\t" - "pavgw %%xmm1, %%xmm0 \n\t" - "pavgw %%xmm3, %%xmm2 \n\t" - "movq 16(%2,%%"FF_REG_d"), %%xmm1 \n\t" - "movq 24(%2,%%"FF_REG_d"), %%xmm3 \n\t" - "paddw %%xmm7, %%xmm1 \n\t" - "paddw %%xmm7, %%xmm3 \n\t" - "pavgw %%xmm1, %%xmm4 \n\t" - "pavgw %%xmm3, %%xmm6 \n\t" - snow_vertical_compose_r2r_sub("xmm7","xmm7","xmm7","xmm7","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6") - - snow_vertical_compose_sra("2","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_store("%3","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%1","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_move("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7") - snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_add("%2","xmm0","xmm2","xmm4","xmm6") - snow_vertical_compose_sse2_store("%2","xmm0","xmm2","xmm4","xmm6") - - "2: \n\t" - "sub $64, %%"FF_REG_d" \n\t" - "jge 1b \n\t" - :"+d"(i) - :"r"(b0),"r"(b1),"r"(b2),"r"(b3),"r"(b4),"r"(b5)); -} - #define snow_vertical_compose_mmx_load_add(op,r,t0,t1,t2,t3)\ ""op" ("r",%%"FF_REG_d"), %%"t0" \n\t"\ ""op" 8("r",%%"FF_REG_d"), %%"t1" \n\t"\ @@ -623,12 +338,6 @@ av_cold void ff_dwt_init_x86(SnowDWTContext *c) c->horizontal_compose97i = ff_snow_horizontal_compose97i_mmx; #if HAVE_7REGS c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; -#endif - } - if (INLINE_SSE2(cpuflags) && 0) { - c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; -#if HAVE_7REGS - c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; #endif } #endif /* HAVE_INLINE_ASM */ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
