diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2006-07-24 10:36:06 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2006-07-24 10:36:06 +0000 |
commit | bca11e75fbc6b922438670733c6cb418c70433b4 (patch) | |
tree | 16e66dc954b1c00e609786c928333c978b5a2fd4 /libswscale | |
parent | fc8833a1ad8b22c34918125fb880aa6071aea860 (diff) | |
download | ffmpeg-bca11e75fbc6b922438670733c6cb418c70433b4.tar.gz |
vertical scaler with accurate rounding, some people on doom9 can see +-1 errors
the +-1 issue is limited to >2tap vertical filters, so bilinear upscale was unaffected
the new code is sometime faster sometimes slower but the difference is significant (~20%) so its optional and enabled with arnd=1
Originally committed as revision 19177 to svn://svn.mplayerhq.hu/mplayer/trunk/libswscale
Diffstat (limited to 'libswscale')
-rw-r--r-- | libswscale/swscale.c | 12 | ||||
-rw-r--r-- | libswscale/swscale.h | 1 | ||||
-rw-r--r-- | libswscale/swscale_internal.h | 6 | ||||
-rw-r--r-- | libswscale/swscale_template.c | 332 |
4 files changed, 309 insertions, 42 deletions
diff --git a/libswscale/swscale.c b/libswscale/swscale.c index f45a4dfa46..9fcb44ca0f 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -848,7 +848,7 @@ static double getSplineCoeff(double a, double b, double c, double d, double dist dist-1.0); } -static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc, +static inline int initFilter(int16_t **outFilter, int16_t **filterPos, int *outFilterSize, int xInc, int srcW, int dstW, int filterAlign, int one, int flags, SwsVector *srcFilter, SwsVector *dstFilter, double param[2]) { @@ -1127,10 +1127,18 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out filterAlign = 1; } + if (flags & SWS_CPU_CAPS_MMX) { + // special case for unscaled vertical filtering + if(minFilterSize == 1 && filterAlign == 2) + filterAlign= 1; + } + ASSERT(minFilterSize > 0) filterSize= (minFilterSize +(filterAlign-1)) & (~(filterAlign-1)); ASSERT(filterSize > 0) filter= av_malloc(filterSize*dstW*sizeof(double)); + if(filterSize >= MAX_FILTER_SIZE) + return -1; *outFilterSize= filterSize; if(flags&SWS_PRINT_INFO) @@ -1216,6 +1224,7 @@ static inline void initFilter(int16_t **outFilter, int16_t **filterPos, int *out } av_free(filter); + return 0; } #if defined(ARCH_X86) || defined(ARCH_X86_64) @@ -2115,6 +2124,7 @@ SwsContext *sws_getContext(int srcW, int srcH, int origSrcFormat, int dstW, int /* precalculate vertical scaler filter coefficients */ { const int filterAlign= + (flags & SWS_CPU_CAPS_MMX) && (flags & SWS_ACCURATE_RND) ? 2 : (flags & SWS_CPU_CAPS_ALTIVEC) ? 8 : 1; diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 37c5ec7490..0b350234ea 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -64,6 +64,7 @@ extern "C" { //input subsampling info #define SWS_FULL_CHR_H_INP 0x4000 #define SWS_DIRECT_BGR 0x8000 +#define SWS_ACCURATE_RND 0x40000 #define SWS_CPU_CAPS_MMX 0x80000000 #define SWS_CPU_CAPS_MMX2 0x20000000 diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index bc8f08d1db..177074d6a5 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -126,7 +126,9 @@ typedef struct SwsContext{ #define DSTW_OFFSET "11*8+4*4*256*2" //do not change, its hardcoded in the asm #define ESP_OFFSET "11*8+4*4*256*2+8" #define VROUNDER_OFFSET "11*8+4*4*256*2+16" - +#define U_TEMP "11*8+4*4*256*2+24" +#define V_TEMP "11*8+4*4*256*2+32" + uint64_t redDither __attribute__((aligned(8))); uint64_t greenDither __attribute__((aligned(8))); uint64_t blueDither __attribute__((aligned(8))); @@ -144,6 +146,8 @@ typedef struct SwsContext{ int dstW; uint64_t esp __attribute__((aligned(8))); uint64_t vRounder __attribute__((aligned(8))); + uint64_t u_temp __attribute__((aligned(8))); + uint64_t v_temp __attribute__((aligned(8))); #ifdef HAVE_ALTIVEC diff --git a/libswscale/swscale_template.c b/libswscale/swscale_template.c index 9830e3d39f..4d3e5ead68 100644 --- a/libswscale/swscale_template.c +++ b/libswscale/swscale_template.c @@ -67,7 +67,8 @@ #include "swscale_altivec_template.c" #endif -#define YSCALEYUV2YV12X(x, offset) \ +#define YSCALEYUV2YV12X(x, offset, dest, width) \ + asm volatile(\ "xor %%"REG_a", %%"REG_a" \n\t"\ "movq "VROUNDER_OFFSET"(%0), %%mm3\n\t"\ "movq %%mm3, %%mm4 \n\t"\ @@ -96,7 +97,73 @@ "movq %%mm3, %%mm4 \n\t"\ "lea " offset "(%0), %%"REG_d" \n\t"\ "mov (%%"REG_d"), %%"REG_S" \n\t"\ - "jb 1b \n\t" + "jb 1b \n\t"\ + :: "r" (&c->redDither),\ + "r" (dest), "p" (width)\ + : "%"REG_a, "%"REG_d, "%"REG_S\ + ); + +#define YSCALEYUV2YV12X_ACCURATE(x, offset, dest, width) \ + asm volatile(\ + "lea " offset "(%0), %%"REG_d" \n\t"\ + "xor %%"REG_a", %%"REG_a" \n\t"\ + "pxor %%mm4, %%mm4 \n\t"\ + "pxor %%mm5, %%mm5 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + "mov (%%"REG_d"), %%"REG_S" \n\t"\ + ASMALIGN16 \ + "1: \n\t"\ + "movq " #x "(%%"REG_S", %%"REG_a", 2), %%mm0\n\t" /* srcData */\ + "movq 8+" #x "(%%"REG_S", %%"REG_a", 2), %%mm2\n\t" /* srcData */\ + "mov 4(%%"REG_d"), %%"REG_S" \n\t"\ + "movq " #x "(%%"REG_S", %%"REG_a", 2), %%mm1\n\t" /* srcData */\ + "movq %%mm0, %%mm3 \n\t"\ + "punpcklwd %%mm1, %%mm0 \n\t"\ + "punpckhwd %%mm1, %%mm3 \n\t"\ + "movq 8(%%"REG_d"), %%mm1 \n\t" /* filterCoeff */\ + "pmaddwd %%mm1, %%mm0 \n\t"\ + "pmaddwd %%mm1, %%mm3 \n\t"\ + "paddd %%mm0, %%mm4 \n\t"\ + "paddd %%mm3, %%mm5 \n\t"\ + "movq 8+" #x "(%%"REG_S", %%"REG_a", 2), %%mm3\n\t" /* srcData */\ + "mov 16(%%"REG_d"), %%"REG_S" \n\t"\ + "add $16, %%"REG_d" \n\t"\ + "test %%"REG_S", %%"REG_S" \n\t"\ + "movq %%mm2, %%mm0 \n\t"\ + "punpcklwd %%mm3, %%mm2 \n\t"\ + "punpckhwd %%mm3, %%mm0 \n\t"\ + "pmaddwd %%mm1, %%mm2 \n\t"\ + "pmaddwd %%mm1, %%mm0 \n\t"\ + "paddd %%mm2, %%mm6 \n\t"\ + "paddd %%mm0, %%mm7 \n\t"\ + " jnz 1b \n\t"\ + "psrad $16, %%mm4 \n\t"\ + "psrad $16, %%mm5 \n\t"\ + "psrad $16, %%mm6 \n\t"\ + "psrad $16, %%mm7 \n\t"\ + "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\ + "packssdw %%mm5, %%mm4 \n\t"\ + "packssdw %%mm7, %%mm6 \n\t"\ + "paddw %%mm0, %%mm4 \n\t"\ + "paddw %%mm0, %%mm6 \n\t"\ + "psraw $3, %%mm4 \n\t"\ + "psraw $3, %%mm6 \n\t"\ + "packuswb %%mm6, %%mm4 \n\t"\ + MOVNTQ(%%mm4, (%1, %%REGa))\ + "add $8, %%"REG_a" \n\t"\ + "cmp %2, %%"REG_a" \n\t"\ + "lea " offset "(%0), %%"REG_d" \n\t"\ + "pxor %%mm4, %%mm4 \n\t"\ + "pxor %%mm5, %%mm5 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + "mov (%%"REG_d"), %%"REG_S" \n\t"\ + "jb 1b \n\t"\ + :: "r" (&c->redDither),\ + "r" (dest), "p" (width)\ + : "%"REG_a, "%"REG_d, "%"REG_S\ + ); #define YSCALEYUV2YV121 \ "mov %2, %%"REG_a" \n\t"\ @@ -159,8 +226,100 @@ "test %%"REG_S", %%"REG_S" \n\t"\ " jnz 2b \n\t"\ - -#define YSCALEYUV2RGBX \ +#define YSCALEYUV2PACKEDX_ACCURATE \ + "xor %%"REG_a", %%"REG_a" \n\t"\ + ASMALIGN16\ + "nop \n\t"\ + "1: \n\t"\ + "lea "CHR_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\ + "mov (%%"REG_d"), %%"REG_S" \n\t"\ + "pxor %%mm4, %%mm4 \n\t"\ + "pxor %%mm5, %%mm5 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + ASMALIGN16\ + "2: \n\t"\ + "movq (%%"REG_S", %%"REG_a"), %%mm0 \n\t" /* UsrcData */\ + "movq 4096(%%"REG_S", %%"REG_a"), %%mm2 \n\t" /* VsrcData */\ + "mov 4(%%"REG_d"), %%"REG_S" \n\t"\ + "movq (%%"REG_S", %%"REG_a"), %%mm1 \n\t" /* UsrcData */\ + "movq %%mm0, %%mm3 \n\t"\ + "punpcklwd %%mm1, %%mm0 \n\t"\ + "punpckhwd %%mm1, %%mm3 \n\t"\ + "movq 8(%%"REG_d"), %%mm1 \n\t" /* filterCoeff */\ + "pmaddwd %%mm1, %%mm0 \n\t"\ + "pmaddwd %%mm1, %%mm3 \n\t"\ + "paddd %%mm0, %%mm4 \n\t"\ + "paddd %%mm3, %%mm5 \n\t"\ + "movq 4096(%%"REG_S", %%"REG_a"), %%mm3 \n\t" /* VsrcData */\ + "mov 16(%%"REG_d"), %%"REG_S" \n\t"\ + "add $16, %%"REG_d" \n\t"\ + "test %%"REG_S", %%"REG_S" \n\t"\ + "movq %%mm2, %%mm0 \n\t"\ + "punpcklwd %%mm3, %%mm2 \n\t"\ + "punpckhwd %%mm3, %%mm0 \n\t"\ + "pmaddwd %%mm1, %%mm2 \n\t"\ + "pmaddwd %%mm1, %%mm0 \n\t"\ + "paddd %%mm2, %%mm6 \n\t"\ + "paddd %%mm0, %%mm7 \n\t"\ + " jnz 2b \n\t"\ + "psrad $16, %%mm4 \n\t"\ + "psrad $16, %%mm5 \n\t"\ + "psrad $16, %%mm6 \n\t"\ + "psrad $16, %%mm7 \n\t"\ + "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\ + "packssdw %%mm5, %%mm4 \n\t"\ + "packssdw %%mm7, %%mm6 \n\t"\ + "paddw %%mm0, %%mm4 \n\t"\ + "paddw %%mm0, %%mm6 \n\t"\ + "movq %%mm4, "U_TEMP"(%0) \n\t"\ + "movq %%mm6, "V_TEMP"(%0) \n\t"\ +\ + "lea "LUM_MMX_FILTER_OFFSET"(%0), %%"REG_d"\n\t"\ + "mov (%%"REG_d"), %%"REG_S" \n\t"\ + "pxor %%mm1, %%mm1 \n\t"\ + "pxor %%mm5, %%mm5 \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + ASMALIGN16\ + "2: \n\t"\ + "movq (%%"REG_S", %%"REG_a", 2), %%mm0 \n\t" /* Y1srcData */\ + "movq 8(%%"REG_S", %%"REG_a", 2), %%mm2 \n\t" /* Y2srcData */\ + "mov 4(%%"REG_d"), %%"REG_S" \n\t"\ + "movq (%%"REG_S", %%"REG_a", 2), %%mm4 \n\t" /* Y1srcData */\ + "movq %%mm0, %%mm3 \n\t"\ + "punpcklwd %%mm4, %%mm0 \n\t"\ + "punpckhwd %%mm4, %%mm3 \n\t"\ + "movq 8(%%"REG_d"), %%mm4 \n\t" /* filterCoeff */\ + "pmaddwd %%mm4, %%mm0 \n\t"\ + "pmaddwd %%mm4, %%mm3 \n\t"\ + "paddd %%mm0, %%mm1 \n\t"\ + "paddd %%mm3, %%mm5 \n\t"\ + "movq 8(%%"REG_S", %%"REG_a", 2), %%mm3 \n\t" /* Y2srcData */\ + "mov 16(%%"REG_d"), %%"REG_S" \n\t"\ + "add $16, %%"REG_d" \n\t"\ + "test %%"REG_S", %%"REG_S" \n\t"\ + "movq %%mm2, %%mm0 \n\t"\ + "punpcklwd %%mm3, %%mm2 \n\t"\ + "punpckhwd %%mm3, %%mm0 \n\t"\ + "pmaddwd %%mm4, %%mm2 \n\t"\ + "pmaddwd %%mm4, %%mm0 \n\t"\ + "paddd %%mm2, %%mm7 \n\t"\ + "paddd %%mm0, %%mm6 \n\t"\ + " jnz 2b \n\t"\ + "psrad $16, %%mm1 \n\t"\ + "psrad $16, %%mm5 \n\t"\ + "psrad $16, %%mm7 \n\t"\ + "psrad $16, %%mm6 \n\t"\ + "movq "VROUNDER_OFFSET"(%0), %%mm0\n\t"\ + "packssdw %%mm5, %%mm1 \n\t"\ + "packssdw %%mm6, %%mm7 \n\t"\ + "paddw %%mm0, %%mm1 \n\t"\ + "paddw %%mm0, %%mm7 \n\t"\ + "movq "U_TEMP"(%0), %%mm3 \n\t"\ + "movq "V_TEMP"(%0), %%mm4 \n\t"\ + +#define YSCALEYUV2RGBX(YSCALEYUV2PACKEDX) \ YSCALEYUV2PACKEDX\ "psubw "U_OFFSET"(%0), %%mm3 \n\t" /* (U-128)8*/\ "psubw "V_OFFSET"(%0), %%mm4 \n\t" /* (V-128)8*/\ @@ -762,29 +921,21 @@ static inline void RENAME(yuv2yuvX)(SwsContext *c, int16_t *lumFilter, int16_t * uint8_t *dest, uint8_t *uDest, uint8_t *vDest, long dstW, long chrDstW) { #ifdef HAVE_MMX - if(uDest != NULL) - { - asm volatile( - YSCALEYUV2YV12X(0, CHR_MMX_FILTER_OFFSET) - :: "r" (&c->redDither), - "r" (uDest), "p" (chrDstW) - : "%"REG_a, "%"REG_d, "%"REG_S - ); - - asm volatile( - YSCALEYUV2YV12X(4096, CHR_MMX_FILTER_OFFSET) - :: "r" (&c->redDither), - "r" (vDest), "p" (chrDstW) - : "%"REG_a, "%"REG_d, "%"REG_S - ); - } - - asm volatile( - YSCALEYUV2YV12X(0, LUM_MMX_FILTER_OFFSET) - :: "r" (&c->redDither), - "r" (dest), "p" (dstW) - : "%"REG_a, "%"REG_d, "%"REG_S - ); + if(c->flags & SWS_ACCURATE_RND){ + if(uDest){ + YSCALEYUV2YV12X_ACCURATE( 0, CHR_MMX_FILTER_OFFSET, uDest, chrDstW) + YSCALEYUV2YV12X_ACCURATE(4096, CHR_MMX_FILTER_OFFSET, vDest, chrDstW) + } + + YSCALEYUV2YV12X_ACCURATE(0, LUM_MMX_FILTER_OFFSET, dest, dstW) + }else{ + if(uDest){ + YSCALEYUV2YV12X( 0, CHR_MMX_FILTER_OFFSET, uDest, chrDstW) + YSCALEYUV2YV12X(4096, CHR_MMX_FILTER_OFFSET, vDest, chrDstW) + } + + YSCALEYUV2YV12X(0, LUM_MMX_FILTER_OFFSET, dest, dstW) + } #else #ifdef HAVE_ALTIVEC yuv2yuvX_altivec_real(lumFilter, lumSrc, lumFilterSize, @@ -876,13 +1027,94 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ uint8_t *dest, long dstW, long dstY) { long dummy=0; +#ifdef HAVE_MMX + if(c->flags & SWS_ACCURATE_RND){ + switch(c->dstFormat){ + case IMGFMT_BGR32: + asm volatile( + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX_ACCURATE) + WRITEBGR32(%4, %5, %%REGa) + + :: "r" (&c->redDither), + "m" (dummy), "m" (dummy), "m" (dummy), + "r" (dest), "m" (dstW) + : "%"REG_a, "%"REG_d, "%"REG_S + ); + return; + case IMGFMT_BGR24: + asm volatile( + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX_ACCURATE) + "lea (%%"REG_a", %%"REG_a", 2), %%"REG_b"\n\t" //FIXME optimize + "add %4, %%"REG_b" \n\t" + WRITEBGR24(%%REGb, %5, %%REGa) + + :: "r" (&c->redDither), + "m" (dummy), "m" (dummy), "m" (dummy), + "r" (dest), "m" (dstW) + : "%"REG_a, "%"REG_b, "%"REG_d, "%"REG_S //FIXME ebx + ); + return; + case IMGFMT_BGR15: + asm volatile( + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX_ACCURATE) + /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ +#ifdef DITHER1XBPP + "paddusb "MANGLE(b5Dither)", %%mm2\n\t" + "paddusb "MANGLE(g5Dither)", %%mm4\n\t" + "paddusb "MANGLE(r5Dither)", %%mm5\n\t" +#endif + + WRITEBGR15(%4, %5, %%REGa) + + :: "r" (&c->redDither), + "m" (dummy), "m" (dummy), "m" (dummy), + "r" (dest), "m" (dstW) + : "%"REG_a, "%"REG_d, "%"REG_S + ); + return; + case IMGFMT_BGR16: + asm volatile( + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX_ACCURATE) + /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ +#ifdef DITHER1XBPP + "paddusb "MANGLE(b5Dither)", %%mm2\n\t" + "paddusb "MANGLE(g6Dither)", %%mm4\n\t" + "paddusb "MANGLE(r5Dither)", %%mm5\n\t" +#endif + + WRITEBGR16(%4, %5, %%REGa) + + :: "r" (&c->redDither), + "m" (dummy), "m" (dummy), "m" (dummy), + "r" (dest), "m" (dstW) + : "%"REG_a, "%"REG_d, "%"REG_S + ); + return; + case IMGFMT_YUY2: + asm volatile( + YSCALEYUV2PACKEDX_ACCURATE + /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ + + "psraw $3, %%mm3 \n\t" + "psraw $3, %%mm4 \n\t" + "psraw $3, %%mm1 \n\t" + "psraw $3, %%mm7 \n\t" + WRITEYUY2(%4, %5, %%REGa) + + :: "r" (&c->redDither), + "m" (dummy), "m" (dummy), "m" (dummy), + "r" (dest), "m" (dstW) + : "%"REG_a, "%"REG_d, "%"REG_S + ); + return; + } + }else{ switch(c->dstFormat) { -#ifdef HAVE_MMX case IMGFMT_BGR32: { asm volatile( - YSCALEYUV2RGBX + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX) WRITEBGR32(%4, %5, %%REGa) :: "r" (&c->redDither), @@ -891,11 +1123,11 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ : "%"REG_a, "%"REG_d, "%"REG_S ); } - break; + return; case IMGFMT_BGR24: { asm volatile( - YSCALEYUV2RGBX + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX) "lea (%%"REG_a", %%"REG_a", 2), %%"REG_b"\n\t" //FIXME optimize "add %4, %%"REG_b" \n\t" WRITEBGR24(%%REGb, %5, %%REGa) @@ -906,11 +1138,11 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ : "%"REG_a, "%"REG_b, "%"REG_d, "%"REG_S //FIXME ebx ); } - break; + return; case IMGFMT_BGR15: { asm volatile( - YSCALEYUV2RGBX + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX) /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP "paddusb "MANGLE(b5Dither)", %%mm2\n\t" @@ -926,11 +1158,11 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ : "%"REG_a, "%"REG_d, "%"REG_S ); } - break; + return; case IMGFMT_BGR16: { asm volatile( - YSCALEYUV2RGBX + YSCALEYUV2RGBX(YSCALEYUV2PACKEDX) /* mm2=B, %%mm4=G, %%mm5=R, %%mm7=0 */ #ifdef DITHER1XBPP "paddusb "MANGLE(b5Dither)", %%mm2\n\t" @@ -946,7 +1178,7 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ : "%"REG_a, "%"REG_d, "%"REG_S ); } - break; + return; case IMGFMT_YUY2: { asm volatile( @@ -965,9 +1197,10 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ : "%"REG_a, "%"REG_d, "%"REG_S ); } - break; + return; + } + } #endif - default: #ifdef HAVE_ALTIVEC /* The following list of supported dstFormat values should match what's found in the body of altivec_yuv2packedX() */ @@ -982,8 +1215,6 @@ static inline void RENAME(yuv2packedX)(SwsContext *c, int16_t *lumFilter, int16_ yuv2packedXinC(c, lumFilter, lumSrc, lumFilterSize, chrFilter, chrSrc, chrFilterSize, dest, dstW, dstY); - break; - } } /** @@ -2813,6 +3044,22 @@ i--; int16_t **chrSrcPtr= chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; #ifdef HAVE_MMX int i; + if(flags & SWS_ACCURATE_RND){ + for(i=0; i<vLumFilterSize; i+=2){ + lumMmxFilter[2*i+0]= lumSrcPtr[i ]; + lumMmxFilter[2*i+1]= lumSrcPtr[i+(vLumFilterSize>1)]; + lumMmxFilter[2*i+2]= + lumMmxFilter[2*i+3]= vLumFilter[dstY*vLumFilterSize + i ] + + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0); + } + for(i=0; i<vChrFilterSize; i+=2){ + chrMmxFilter[2*i+0]= chrSrcPtr[i ]; + chrMmxFilter[2*i+1]= chrSrcPtr[i+(vChrFilterSize>1)]; + chrMmxFilter[2*i+2]= + chrMmxFilter[2*i+3]= vChrFilter[chrDstY*vChrFilterSize + i ] + + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0); + } + }else{ for(i=0; i<vLumFilterSize; i++) { lumMmxFilter[4*i+0]= (int32_t)lumSrcPtr[i]; @@ -2827,6 +3074,7 @@ i--; chrMmxFilter[4*i+3]= ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001; } + } #endif if(dstFormat == IMGFMT_NV12 || dstFormat == IMGFMT_NV21){ const int chrSkipMask= (1<<c->chrDstVSubSample)-1; @@ -2868,6 +3116,10 @@ i--; { int lumAlpha= vLumFilter[2*dstY+1]; int chrAlpha= vChrFilter[2*dstY+1]; + lumMmxFilter[2]= + lumMmxFilter[3]= vLumFilter[2*dstY ]*0x10001; + chrMmxFilter[2]= + chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001; RENAME(yuv2packed2)(c, *lumSrcPtr, *(lumSrcPtr+1), *chrSrcPtr, *(chrSrcPtr+1), dest, dstW, lumAlpha, chrAlpha, dstY); } |