]> git.sesse.net Git - ffmpeg/blobdiff - libswscale/swscale.c
Enable unscaled packed422 -> planar 420 converters by default as the
[ffmpeg] / libswscale / swscale.c
index 7c335f1680e8d640dd78d17696e2e2b6610b3fca..d9c1c5936962ca420e14ac595000ad0cde802ebd 100644 (file)
@@ -68,6 +68,10 @@ untested special converters
 #define MAP_ANONYMOUS MAP_ANON
 #endif
 #endif
+#if HAVE_VIRTUALALLOC
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
 #include "swscale.h"
 #include "swscale_internal.h"
 #include "rgb2rgb.h"
@@ -133,6 +137,7 @@ unsigned swscale_version(void)
     )
 #define isSupportedOut(x)   (       \
            (x)==PIX_FMT_YUV420P     \
+        || (x)==PIX_FMT_YUVA420P    \
         || (x)==PIX_FMT_YUYV422     \
         || (x)==PIX_FMT_UYVY422     \
         || (x)==PIX_FMT_YUV444P     \
@@ -469,7 +474,7 @@ const char *sws_format_name(enum PixelFormat format)
 
 static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
                                int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
-                               uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW)
+                               int16_t **alpSrc, uint8_t *dest, uint8_t *uDest, uint8_t *vDest, uint8_t *aDest, int dstW, int chrDstW)
 {
     //FIXME Optimize (just quickly written not optimized..)
     int i;
@@ -498,6 +503,17 @@ static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilt
             uDest[i]= av_clip_uint8(u>>19);
             vDest[i]= av_clip_uint8(v>>19);
         }
+
+    if (CONFIG_SWSCALE_ALPHA && aDest)
+        for (i=0; i<dstW; i++){
+            int val=1<<18;
+            int j;
+            for (j=0; j<lumFilterSize; j++)
+                val += alpSrc[j][i] * lumFilter[j];
+
+            aDest[i]= av_clip_uint8(val>>19);
+        }
+
 }
 
 static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
@@ -551,13 +567,14 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         }
 }
 
-#define YSCALE_YUV_2_PACKEDX_NOCLIP_C(type) \
+#define YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha) \
     for (i=0; i<(dstW>>1); i++){\
         int j;\
         int Y1 = 1<<18;\
         int Y2 = 1<<18;\
         int U  = 1<<18;\
         int V  = 1<<18;\
+        int av_unused A1, A2;\
         type av_unused *r, *b, *g;\
         const int i2= 2*i;\
         \
@@ -575,9 +592,19 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         Y2>>=19;\
         U >>=19;\
         V >>=19;\
+        if (alpha){\
+            A1 = 1<<18;\
+            A2 = 1<<18;\
+            for (j=0; j<lumFilterSize; j++){\
+                A1 += alpSrc[j][i2  ] * lumFilter[j];\
+                A2 += alpSrc[j][i2+1] * lumFilter[j];\
+            }\
+            A1>>=19;\
+            A2>>=19;\
+        }\
 
-#define YSCALE_YUV_2_PACKEDX_C(type) \
-        YSCALE_YUV_2_PACKEDX_NOCLIP_C(type)\
+#define YSCALE_YUV_2_PACKEDX_C(type,alpha) \
+        YSCALE_YUV_2_PACKEDX_NOCLIP_C(type,alpha)\
         if ((Y1|Y2|U|V)&256)\
         {\
             if (Y1>255)   Y1=255; \
@@ -588,14 +615,19 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
             else if (U<0) U=0;    \
             if (V>255)    V=255;  \
             else if (V<0) V=0;    \
+        }\
+        if (alpha && ((A1|A2)&256)){\
+            A1=av_clip_uint8(A1);\
+            A2=av_clip_uint8(A2);\
         }
 
-#define YSCALE_YUV_2_PACKEDX_FULL_C \
+#define YSCALE_YUV_2_PACKEDX_FULL_C(rnd,alpha) \
     for (i=0; i<dstW; i++){\
         int j;\
         int Y = 0;\
         int U = -128<<19;\
         int V = -128<<19;\
+        int av_unused A;\
         int R,G,B;\
         \
         for (j=0; j<lumFilterSize; j++){\
@@ -608,9 +640,17 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         Y >>=10;\
         U >>=10;\
         V >>=10;\
+        if (alpha){\
+            A = rnd;\
+            for (j=0; j<lumFilterSize; j++)\
+                A += alpSrc[j][i     ] * lumFilter[j];\
+            A >>=19;\
+            if (A&256)\
+                A = av_clip_uint8(A);\
+        }\
 
-#define YSCALE_YUV_2_RGBX_FULL_C(rnd) \
-    YSCALE_YUV_2_PACKEDX_FULL_C\
+#define YSCALE_YUV_2_RGBX_FULL_C(rnd,alpha) \
+    YSCALE_YUV_2_PACKEDX_FULL_C(rnd>>3,alpha)\
         Y-= c->yuv2rgb_y_offset;\
         Y*= c->yuv2rgb_y_coeff;\
         Y+= rnd;\
@@ -652,19 +692,25 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
             else if (Y2<0)Y2=0;   \
         }
 
-#define YSCALE_YUV_2_RGBX_C(type) \
-    YSCALE_YUV_2_PACKEDX_C(type)  /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/\
+#define YSCALE_YUV_2_RGBX_C(type,alpha) \
+    YSCALE_YUV_2_PACKEDX_C(type,alpha)  /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/\
     r = (type *)c->table_rV[V];   \
     g = (type *)(c->table_gU[U] + c->table_gV[V]); \
     b = (type *)c->table_bU[U];   \
 
-#define YSCALE_YUV_2_PACKED2_C   \
+#define YSCALE_YUV_2_PACKED2_C(type,alpha)   \
     for (i=0; i<(dstW>>1); i++){ \
         const int i2= 2*i;       \
         int Y1= (buf0[i2  ]*yalpha1+buf1[i2  ]*yalpha)>>19;           \
         int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>19;           \
         int U= (uvbuf0[i     ]*uvalpha1+uvbuf1[i     ]*uvalpha)>>19;  \
         int V= (uvbuf0[i+VOFW]*uvalpha1+uvbuf1[i+VOFW]*uvalpha)>>19;  \
+        type av_unused *r, *b, *g;                                    \
+        int av_unused A1, A2;                                         \
+        if (alpha){\
+            A1= (abuf0[i2  ]*yalpha1+abuf1[i2  ]*yalpha)>>19;         \
+            A2= (abuf0[i2+1]*yalpha1+abuf1[i2+1]*yalpha)>>19;         \
+        }\
 
 #define YSCALE_YUV_2_GRAY16_2_C   \
     for (i=0; i<(dstW>>1); i++){ \
@@ -672,20 +718,25 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         int Y1= (buf0[i2  ]*yalpha1+buf1[i2  ]*yalpha)>>11;           \
         int Y2= (buf0[i2+1]*yalpha1+buf1[i2+1]*yalpha)>>11;           \
 
-#define YSCALE_YUV_2_RGB2_C(type) \
-    YSCALE_YUV_2_PACKED2_C\
-    type *r, *b, *g;\
+#define YSCALE_YUV_2_RGB2_C(type,alpha) \
+    YSCALE_YUV_2_PACKED2_C(type,alpha)\
     r = (type *)c->table_rV[V];\
     g = (type *)(c->table_gU[U] + c->table_gV[V]);\
     b = (type *)c->table_bU[U];\
 
-#define YSCALE_YUV_2_PACKED1_C \
+#define YSCALE_YUV_2_PACKED1_C(type,alpha) \
     for (i=0; i<(dstW>>1); i++){\
         const int i2= 2*i;\
         int Y1= buf0[i2  ]>>7;\
         int Y2= buf0[i2+1]>>7;\
         int U= (uvbuf1[i     ])>>7;\
         int V= (uvbuf1[i+VOFW])>>7;\
+        type av_unused *r, *b, *g;\
+        int av_unused A1, A2;\
+        if (alpha){\
+            A1= abuf0[i2  ]>>7;\
+            A2= abuf0[i2+1]>>7;\
+        }\
 
 #define YSCALE_YUV_2_GRAY16_1_C \
     for (i=0; i<(dstW>>1); i++){\
@@ -693,24 +744,28 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         int Y1= buf0[i2  ]<<1;\
         int Y2= buf0[i2+1]<<1;\
 
-#define YSCALE_YUV_2_RGB1_C(type) \
-    YSCALE_YUV_2_PACKED1_C\
-    type *r, *b, *g;\
+#define YSCALE_YUV_2_RGB1_C(type,alpha) \
+    YSCALE_YUV_2_PACKED1_C(type,alpha)\
     r = (type *)c->table_rV[V];\
     g = (type *)(c->table_gU[U] + c->table_gV[V]);\
     b = (type *)c->table_bU[U];\
 
-#define YSCALE_YUV_2_PACKED1B_C \
+#define YSCALE_YUV_2_PACKED1B_C(type,alpha) \
     for (i=0; i<(dstW>>1); i++){\
         const int i2= 2*i;\
         int Y1= buf0[i2  ]>>7;\
         int Y2= buf0[i2+1]>>7;\
         int U= (uvbuf0[i     ] + uvbuf1[i     ])>>8;\
         int V= (uvbuf0[i+VOFW] + uvbuf1[i+VOFW])>>8;\
+        type av_unused *r, *b, *g;\
+        int av_unused A1, A2;\
+        if (alpha){\
+            A1= abuf0[i2  ]>>7;\
+            A2= abuf0[i2+1]>>7;\
+        }\
 
-#define YSCALE_YUV_2_RGB1B_C(type) \
-    YSCALE_YUV_2_PACKED1B_C\
-    type *r, *b, *g;\
+#define YSCALE_YUV_2_RGB1B_C(type,alpha) \
+    YSCALE_YUV_2_PACKED1B_C(type,alpha)\
     r = (type *)c->table_rV[V];\
     g = (type *)(c->table_gU[U] + c->table_gV[V]);\
     b = (type *)c->table_bU[U];\
@@ -768,17 +823,52 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
 #define YSCALE_YUV_2_ANYRGB_C(func, func2, func_g16, func_monoblack)\
     switch(c->dstFormat)\
     {\
-    case PIX_FMT_RGB32:\
-    case PIX_FMT_BGR32:\
-    case PIX_FMT_RGB32_1:\
-    case PIX_FMT_BGR32_1:\
-        func(uint32_t)\
-            ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
-            ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
+    case PIX_FMT_RGBA:\
+    case PIX_FMT_BGRA:\
+        if (CONFIG_SMALL){\
+            int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;\
+            func(uint32_t,needAlpha)\
+                ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (needAlpha ? (A1<<24) : 0);\
+                ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (needAlpha ? (A2<<24) : 0);\
+            }\
+        }else{\
+            if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf){\
+                func(uint32_t,1)\
+                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (A1<<24);\
+                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (A2<<24);\
+                }\
+            }else{\
+                func(uint32_t,0)\
+                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
+                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
+                }\
+            }\
+        }\
+        break;\
+    case PIX_FMT_ARGB:\
+    case PIX_FMT_ABGR:\
+        if (CONFIG_SMALL){\
+            int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;\
+            func(uint32_t,needAlpha)\
+                ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + (needAlpha ? A1 : 0);\
+                ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + (needAlpha ? A2 : 0);\
+            }\
+        }else{\
+            if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf){\
+                func(uint32_t,1)\
+                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1] + A1;\
+                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2] + A2;\
+                }\
+            }else{\
+                func(uint32_t,0)\
+                    ((uint32_t*)dest)[i2+0]= r[Y1] + g[Y1] + b[Y1];\
+                    ((uint32_t*)dest)[i2+1]= r[Y2] + g[Y2] + b[Y2];\
+                }\
+            }\
         }                \
         break;\
     case PIX_FMT_RGB24:\
-        func(uint8_t)\
+        func(uint8_t,0)\
             ((uint8_t*)dest)[0]= r[Y1];\
             ((uint8_t*)dest)[1]= g[Y1];\
             ((uint8_t*)dest)[2]= b[Y1];\
@@ -789,7 +879,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         }\
         break;\
     case PIX_FMT_BGR24:\
-        func(uint8_t)\
+        func(uint8_t,0)\
             ((uint8_t*)dest)[0]= b[Y1];\
             ((uint8_t*)dest)[1]= g[Y1];\
             ((uint8_t*)dest)[2]= r[Y1];\
@@ -808,7 +898,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
             const int dr2= dither_2x2_8[y&1    ][1];\
             const int dg2= dither_2x2_4[y&1    ][1];\
             const int db2= dither_2x2_8[(y&1)^1][1];\
-            func(uint16_t)\
+            func(uint16_t,0)\
                 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
                 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
             }\
@@ -823,7 +913,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
             const int dr2= dither_2x2_8[y&1    ][1];\
             const int dg2= dither_2x2_8[y&1    ][0];\
             const int db2= dither_2x2_8[(y&1)^1][1];\
-            func(uint16_t)\
+            func(uint16_t,0)\
                 ((uint16_t*)dest)[i2+0]= r[Y1+dr1] + g[Y1+dg1] + b[Y1+db1];\
                 ((uint16_t*)dest)[i2+1]= r[Y2+dr2] + g[Y2+dg2] + b[Y2+db2];\
             }\
@@ -834,7 +924,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         {\
             const uint8_t * const d64= dither_8x8_73[y&7];\
             const uint8_t * const d32= dither_8x8_32[y&7];\
-            func(uint8_t)\
+            func(uint8_t,0)\
                 ((uint8_t*)dest)[i2+0]= r[Y1+d32[(i2+0)&7]] + g[Y1+d32[(i2+0)&7]] + b[Y1+d64[(i2+0)&7]];\
                 ((uint8_t*)dest)[i2+1]= r[Y2+d32[(i2+1)&7]] + g[Y2+d32[(i2+1)&7]] + b[Y2+d64[(i2+1)&7]];\
             }\
@@ -845,7 +935,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         {\
             const uint8_t * const d64= dither_8x8_73 [y&7];\
             const uint8_t * const d128=dither_8x8_220[y&7];\
-            func(uint8_t)\
+            func(uint8_t,0)\
                 ((uint8_t*)dest)[i]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]]\
                                  + ((r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]])<<4);\
             }\
@@ -856,7 +946,7 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
         {\
             const uint8_t * const d64= dither_8x8_73 [y&7];\
             const uint8_t * const d128=dither_8x8_220[y&7];\
-            func(uint8_t)\
+            func(uint8_t,0)\
                 ((uint8_t*)dest)[i2+0]= r[Y1+d128[(i2+0)&7]] + g[Y1+d64[(i2+0)&7]] + b[Y1+d128[(i2+0)&7]];\
                 ((uint8_t*)dest)[i2+1]= r[Y2+d128[(i2+1)&7]] + g[Y2+d64[(i2+1)&7]] + b[Y2+d128[(i2+1)&7]];\
             }\
@@ -905,15 +995,15 @@ static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFil
 
 static inline void yuv2packedXinC(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
                                   int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
-                                  uint8_t *dest, int dstW, int y)
+                                  int16_t **alpSrc, uint8_t *dest, int dstW, int y)
 {
     int i;
-    YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGBX_C, YSCALE_YUV_2_PACKEDX_C(void), YSCALE_YUV_2_GRAY16_C, YSCALE_YUV_2_MONOX_C)
+    YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGBX_C, YSCALE_YUV_2_PACKEDX_C(void,0), YSCALE_YUV_2_GRAY16_C, YSCALE_YUV_2_MONOX_C)
 }
 
 static inline void yuv2rgbXinC_full(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
                                     int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
-                                    uint8_t *dest, int dstW, int y)
+                                    int16_t **alpSrc, uint8_t *dest, int dstW, int y)
 {
     int i;
     int step= fmt_depth(c->dstFormat)/8;
@@ -922,30 +1012,72 @@ static inline void yuv2rgbXinC_full(SwsContext *c, int16_t *lumFilter, int16_t *
     switch(c->dstFormat){
     case PIX_FMT_ARGB:
         dest++;
-        aidx= -1;
+        aidx= 0;
     case PIX_FMT_RGB24:
         aidx--;
     case PIX_FMT_RGBA:
-        YSCALE_YUV_2_RGBX_FULL_C(1<<21)
-            dest[aidx]= 255;
-            dest[0]= R>>22;
-            dest[1]= G>>22;
-            dest[2]= B>>22;
-            dest+= step;
+        if (CONFIG_SMALL){
+            int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;
+            YSCALE_YUV_2_RGBX_FULL_C(1<<21, needAlpha)
+                dest[aidx]= needAlpha ? A : 255;
+                dest[0]= R>>22;
+                dest[1]= G>>22;
+                dest[2]= B>>22;
+                dest+= step;
+            }
+        }else{
+            if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf){
+                YSCALE_YUV_2_RGBX_FULL_C(1<<21, 1)
+                    dest[aidx]= A;
+                    dest[0]= R>>22;
+                    dest[1]= G>>22;
+                    dest[2]= B>>22;
+                    dest+= step;
+                }
+            }else{
+                YSCALE_YUV_2_RGBX_FULL_C(1<<21, 0)
+                    dest[aidx]= 255;
+                    dest[0]= R>>22;
+                    dest[1]= G>>22;
+                    dest[2]= B>>22;
+                    dest+= step;
+                }
+            }
         }
         break;
     case PIX_FMT_ABGR:
         dest++;
-        aidx= -1;
+        aidx= 0;
     case PIX_FMT_BGR24:
         aidx--;
     case PIX_FMT_BGRA:
-        YSCALE_YUV_2_RGBX_FULL_C(1<<21)
-            dest[aidx]= 255;
-            dest[0]= B>>22;
-            dest[1]= G>>22;
-            dest[2]= R>>22;
-            dest+= step;
+        if (CONFIG_SMALL){
+            int needAlpha = CONFIG_SWSCALE_ALPHA && c->alpPixBuf;
+            YSCALE_YUV_2_RGBX_FULL_C(1<<21, needAlpha)
+                dest[aidx]= needAlpha ? A : 255;
+                dest[0]= B>>22;
+                dest[1]= G>>22;
+                dest[2]= R>>22;
+                dest+= step;
+            }
+        }else{
+            if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf){
+                YSCALE_YUV_2_RGBX_FULL_C(1<<21, 1)
+                    dest[aidx]= A;
+                    dest[0]= B>>22;
+                    dest[1]= G>>22;
+                    dest[2]= R>>22;
+                    dest+= step;
+                }
+            }else{
+                YSCALE_YUV_2_RGBX_FULL_C(1<<21, 0)
+                    dest[aidx]= 255;
+                    dest[0]= B>>22;
+                    dest[1]= G>>22;
+                    dest[2]= R>>22;
+                    dest+= step;
+                }
+            }
         }
         break;
     default:
@@ -953,6 +1085,15 @@ static inline void yuv2rgbXinC_full(SwsContext *c, int16_t *lumFilter, int16_t *
     }
 }
 
+static void fillPlane(uint8_t* plane, int stride, int width, int height, int y, uint8_t val){
+    int i;
+    uint8_t *ptr = plane + stride*y;
+    for (i=0; i<height; i++){
+        memset(ptr, val, width);
+        ptr += stride;
+    }
+}
+
 //Note: we have C, X86, MMX, MMX2, 3DNOW versions, there is no 3DNOW+MMX2 one
 //Plain C versions
 #if !HAVE_MMX || defined (RUNTIME_CPUDETECT) || !CONFIG_GPL
@@ -1457,13 +1598,13 @@ error:
 static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *filter, int32_t *filterPos, int numSplits)
 {
     uint8_t *fragmentA;
-    long imm8OfPShufW1A;
-    long imm8OfPShufW2A;
-    long fragmentLengthA;
+    x86_reg imm8OfPShufW1A;
+    x86_reg imm8OfPShufW2A;
+    x86_reg fragmentLengthA;
     uint8_t *fragmentB;
-    long imm8OfPShufW1B;
-    long imm8OfPShufW2B;
-    long fragmentLengthB;
+    x86_reg imm8OfPShufW1B;
+    x86_reg imm8OfPShufW2B;
+    x86_reg fragmentLengthB;
     int fragmentPos;
 
     int xpos, i;
@@ -1622,7 +1763,7 @@ static void initMMX2HScaler(int dstW, int xInc, uint8_t *funnyCode, int16_t *fil
         }
         xpos+=xInc;
     }
-    filterPos[i/2]= xpos>>16; // needed to jump to the next part
+    filterPos[((i/2)+1)&(~1)]= xpos>>16; // needed to jump to the next part
 }
 #endif /* COMPILE_MMX2 */
 
@@ -1736,6 +1877,50 @@ static int YUV422PToUyvyWrapper(SwsContext *c, uint8_t* src[], int srcStride[],
     return srcSliceH;
 }
 
+static int YUYV2YUV420Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
+
+    yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+
+    return srcSliceH;
+}
+
+static int YUYV2YUV422Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
+
+    yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+
+    return srcSliceH;
+}
+
+static int UYVY2YUV420Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY/2;
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY/2;
+
+    uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+
+    return srcSliceH;
+}
+
+static int UYVY2YUV422Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+                               int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+    uint8_t *ydst=dstParam[0] + dstStride[0]*srcSliceY;
+    uint8_t *udst=dstParam[1] + dstStride[1]*srcSliceY;
+    uint8_t *vdst=dstParam[2] + dstStride[2]*srcSliceY;
+
+    uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], dstStride[1], srcStride[0]);
+
+    return srcSliceH;
+}
+
 static int pal2rgbWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
                           int srcSliceH, uint8_t* dst[], int dstStride[]){
     const enum PixelFormat srcFormat= c->srcFormat;
@@ -1884,7 +2069,7 @@ static int yvu9toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int
         }
     }
 
-    if (c->dstFormat==PIX_FMT_YUV420P){
+    if (c->dstFormat==PIX_FMT_YUV420P || c->dstFormat==PIX_FMT_YUVA420P){
         planar2x(src[1], dst[1], c->chrSrcW, c->chrSrcH, srcStride[1], dstStride[1]);
         planar2x(src[2], dst[2], c->chrSrcW, c->chrSrcH, srcStride[2], dstStride[2]);
     }else{
@@ -1926,17 +2111,17 @@ static int planarCopy(SwsContext *c, uint8_t* src[], int srcStride[], int srcSli
                       int srcSliceH, uint8_t* dst[], int dstStride[])
 {
     int plane;
-    for (plane=0; plane<3; plane++)
+    for (plane=0; plane<4; plane++)
     {
-        int length= plane==0 ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
-        int y=      plane==0 ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
-        int height= plane==0 ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
-
-        if ((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0)
-        {
-            if (!isGray(c->dstFormat))
-                memset(dst[plane], 128, dstStride[plane]*height);
-        }
+        int length= (plane==0 || plane==3) ? c->srcW  : -((-c->srcW  )>>c->chrDstHSubSample);
+        int y=      (plane==0 || plane==3) ? srcSliceY: -((-srcSliceY)>>c->chrDstVSubSample);
+        int height= (plane==0 || plane==3) ? srcSliceH: -((-srcSliceH)>>c->chrDstVSubSample);
+
+        if (!dst[plane]) continue;
+        // ignore palette for GRAY8
+        if (plane == 1 && !dst[2]) continue;
+        if (!src[plane] || (plane == 1 && !src[2]))
+            fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
         else
         {
             if (dstStride[plane]==srcStride[plane] && srcStride[plane] > 0)
@@ -2133,12 +2318,12 @@ int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange
     c->yuv2rgb_u2g_coeff= (int16_t)roundToInt16(cgu<<13);
     c->yuv2rgb_u2b_coeff= (int16_t)roundToInt16(cbu<<13);
 
-    sws_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
+    ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
     //FIXME factorize
 
 #ifdef COMPILE_ALTIVEC
     if (c->flags & SWS_CPU_CAPS_ALTIVEC)
-        sws_yuv2rgb_altivec_init_tables (c, inv_table, brightness, contrast, saturation);
+        ff_yuv2rgb_init_tables_altivec(c, inv_table, brightness, contrast, saturation);
 #endif
     return 0;
 }
@@ -2335,16 +2520,16 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
         if ((srcFormat==PIX_FMT_YUV420P || srcFormat==PIX_FMT_YUV422P || srcFormat==PIX_FMT_YUVA420P) && (isBGR(dstFormat) || isRGB(dstFormat))
             && !(flags & SWS_ACCURATE_RND) && !(dstH&1))
         {
-            c->swScale= sws_yuv2rgb_get_func_ptr(c);
+            c->swScale= ff_yuv2rgb_get_func_ptr(c);
         }
 
-        if (srcFormat==PIX_FMT_YUV410P && dstFormat==PIX_FMT_YUV420P && !(flags & SWS_BITEXACT))
+        if (srcFormat==PIX_FMT_YUV410P && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_BITEXACT))
         {
             c->swScale= yvu9toyv12Wrapper;
         }
 
         /* bgr24toYV12 */
-        if (srcFormat==PIX_FMT_BGR24 && dstFormat==PIX_FMT_YUV420P && !(flags & SWS_ACCURATE_RND))
+        if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND))
             c->swScale= bgr24toyv12Wrapper;
 
         /* RGB/BGR -> RGB/BGR (no dither needed forms) */
@@ -2391,6 +2576,14 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
                     c->swScale= PlanarToUyvyWrapper;
             }
         }
+        if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV420P)
+            c->swScale= YUYV2YUV420Wrapper;
+        if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV420P)
+            c->swScale= UYVY2YUV420Wrapper;
+        if(srcFormat == PIX_FMT_YUYV422 && dstFormat == PIX_FMT_YUV422P)
+            c->swScale= YUYV2YUV422Wrapper;
+        if(srcFormat == PIX_FMT_UYVY422 && dstFormat == PIX_FMT_YUV422P)
+            c->swScale= UYVY2YUV422Wrapper;
 
 #ifdef COMPILE_ALTIVEC
         if ((c->flags & SWS_CPU_CAPS_ALTIVEC) &&
@@ -2407,6 +2600,7 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
         /* simple copy */
         if (  srcFormat == dstFormat
             || (srcFormat == PIX_FMT_YUVA420P && dstFormat == PIX_FMT_YUV420P)
+            || (srcFormat == PIX_FMT_YUV420P && dstFormat == PIX_FMT_YUVA420P)
             || (isPlanarYUV(srcFormat) && isGray(dstFormat))
             || (isPlanarYUV(dstFormat) && isGray(srcFormat)))
         {
@@ -2502,10 +2696,13 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
         if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR))
         {
 #ifdef MAP_ANONYMOUS
-            c->funnyYCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-            c->funnyUVCode = (uint8_t*)mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+            c->funnyYCode  = mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+            c->funnyUVCode = mmap(NULL, MAX_FUNNY_CODE_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+#elif HAVE_VIRTUALALLOC
+            c->funnyYCode  = VirtualAlloc(NULL, MAX_FUNNY_CODE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+            c->funnyUVCode = VirtualAlloc(NULL, MAX_FUNNY_CODE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 #else
-            c->funnyYCode = av_malloc(MAX_FUNNY_CODE_SIZE);
+            c->funnyYCode  = av_malloc(MAX_FUNNY_CODE_SIZE);
             c->funnyUVCode = av_malloc(MAX_FUNNY_CODE_SIZE);
 #endif
 
@@ -2578,12 +2775,17 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
     // allocate pixbufs (we use dynamic allocation because otherwise we would need to
     c->lumPixBuf= av_malloc(c->vLumBufSize*2*sizeof(int16_t*));
     c->chrPixBuf= av_malloc(c->vChrBufSize*2*sizeof(int16_t*));
+    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
+        c->alpPixBuf= av_malloc(c->vLumBufSize*2*sizeof(int16_t*));
     //Note we need at least one pixel more at the end because of the MMX code (just in case someone wanna replace the 4000/8000)
     /* align at 16 bytes for AltiVec */
     for (i=0; i<c->vLumBufSize; i++)
         c->lumPixBuf[i]= c->lumPixBuf[i+c->vLumBufSize]= av_mallocz(VOF+1);
     for (i=0; i<c->vChrBufSize; i++)
         c->chrPixBuf[i]= c->chrPixBuf[i+c->vChrBufSize]= av_malloc((VOF+1)*2);
+    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
+        for (i=0; i<c->vLumBufSize; i++)
+            c->alpPixBuf[i]= c->alpPixBuf[i+c->vLumBufSize]= av_mallocz(VOF+1);
 
     //try to avoid drawing green stuff between the right end and the stride end
     for (i=0; i<c->vChrBufSize; i++) memset(c->chrPixBuf[i], 64, (VOF+1)*2);
@@ -2726,7 +2928,7 @@ SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int d
 int sws_scale(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
               int srcSliceH, uint8_t* dst[], int dstStride[]){
     int i;
-    uint8_t* src2[4]= {src[0], src[1], src[2]};
+    uint8_t* src2[4]= {src[0], src[1], src[2], src[3]};
 
     if (c->sliceDir == 0 && srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
         av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
@@ -2800,21 +3002,23 @@ int sws_scale(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
     // copy strides, so they can safely be modified
     if (c->sliceDir == 1) {
         // slices go from top to bottom
-        int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2]};
-        int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2]};
+        int srcStride2[4]= {srcStride[0], srcStride[1], srcStride[2], srcStride[3]};
+        int dstStride2[4]= {dstStride[0], dstStride[1], dstStride[2], dstStride[3]};
         return c->swScale(c, src2, srcStride2, srcSliceY, srcSliceH, dst, dstStride2);
     } else {
         // slices go from bottom to top => we flip the image internally
         uint8_t* dst2[4]= {dst[0] + (c->dstH-1)*dstStride[0],
                            dst[1] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[1],
-                           dst[2] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2]};
-        int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2]};
-        int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2]};
+                           dst[2] + ((c->dstH>>c->chrDstVSubSample)-1)*dstStride[2],
+                           dst[3] + (c->dstH-1)*dstStride[3]};
+        int srcStride2[4]= {-srcStride[0], -srcStride[1], -srcStride[2], -srcStride[3]};
+        int dstStride2[4]= {-dstStride[0], -dstStride[1], -dstStride[2], -dstStride[3]};
 
         src2[0] += (srcSliceH-1)*srcStride[0];
         if (!usePal(c->srcFormat))
             src2[1] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[1];
         src2[2] += ((srcSliceH>>c->chrSrcVSubSample)-1)*srcStride[2];
+        src2[3] += (srcSliceH-1)*srcStride[3];
 
         return c->swScale(c, src2, srcStride2, c->srcH-srcSliceY-srcSliceH, srcSliceH, dst2, dstStride2);
     }
@@ -3132,6 +3336,12 @@ void sws_freeContext(SwsContext *c){
         av_freep(&c->chrPixBuf);
     }
 
+    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf){
+        for (i=0; i<c->vLumBufSize; i++)
+            av_freep(&c->alpPixBuf[i]);
+        av_freep(&c->alpPixBuf);
+    }
+
     av_freep(&c->vLumFilter);
     av_freep(&c->vChrFilter);
     av_freep(&c->hLumFilter);
@@ -3148,10 +3358,13 @@ void sws_freeContext(SwsContext *c){
 
 #if ARCH_X86 && CONFIG_GPL
 #ifdef MAP_ANONYMOUS
-    if (c->funnyYCode) munmap(c->funnyYCode, MAX_FUNNY_CODE_SIZE);
+    if (c->funnyYCode ) munmap(c->funnyYCode , MAX_FUNNY_CODE_SIZE);
     if (c->funnyUVCode) munmap(c->funnyUVCode, MAX_FUNNY_CODE_SIZE);
+#elif HAVE_VIRTUALALLOC
+    if (c->funnyYCode ) VirtualFree(c->funnyYCode , MAX_FUNNY_CODE_SIZE, MEM_RELEASE);
+    if (c->funnyUVCode) VirtualFree(c->funnyUVCode, MAX_FUNNY_CODE_SIZE, MEM_RELEASE);
 #else
-    av_free(c->funnyYCode);
+    av_free(c->funnyYCode );
     av_free(c->funnyUVCode);
 #endif
     c->funnyYCode=NULL;