cleanup & grayscale support
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 22 Jun 2002 20:37:30 +0000 (20:37 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 22 Jun 2002 20:37:30 +0000 (20:37 +0000)
Originally committed as revision 6504 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc

postproc/swscale.c
postproc/swscale_template.c

index cef9cd96644aa3bd358a07a88b0558de931f9851..96ea6ea7f677e7860f7e3491310f7ee5cb62d7ba 100644 (file)
@@ -18,7 +18,7 @@
 
 /*
   supported Input formats: YV12, I420, IYUV, YUY2, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8, Y800
-  supported output formats: YV12, I420, IYUV, BGR15, BGR16, BGR24, BGR32 (grayscale soon too)
+  supported output formats: YV12, I420, IYUV, BGR15, BGR16, BGR24, BGR32, Y8, Y800
   BGR15/16 support dithering
   
   unscaled special converters
@@ -100,26 +100,21 @@ untested special converters
 #endif
 
 //FIXME replace this with something faster
-#define isBGR(x)       ((x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15)
-#define isRGB(x)       ((x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24|| (x)==IMGFMT_RGB16|| (x)==IMGFMT_RGB15)
-#define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_IYUV|| (x)==IMGFMT_YVU9 || (x)==IMGFMT_IF09)
-#define isYUV(x)       (!(isBGR(x) || isRGB(x)))
-#define isHalfChrV(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_IYUV)
+#define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YVU9)
+#define isYUV(x)       ((x)==IMGFMT_YUY2 || isPlanarYUV(x))
+#define isHalfChrV(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420)
 #define isHalfChrH(x)  ((x)==IMGFMT_YUY2 || (x)==IMGFMT_YV12 || (x)==IMGFMT_I420)
-#define isPacked(x)    (isYUV(x) && !isPlanarYUV(x))
-#define isGray(x)      ((x)==IMGFMT_Y800) /* Behaviour the same as PACKED but it's PLANAR */
+#define isGray(x)      ((x)==IMGFMT_Y800)
 #define isSupportedIn(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YUY2 \
                        || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15\
                        || (x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24\
                        || (x)==IMGFMT_Y800)
 #define isSupportedOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 \
-                       || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15)
-#define isSupportedUnscaledIn(x)  ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x)==IMGFMT_YUY2 || (x)==IMGFMT_NV12 \
                        || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15\
-                       || (x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24\
                        || (x)==IMGFMT_Y800)
-#define isSupportedUnscaledOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_I420 || (x) == IMGFMT_YUY2 \
-                       || (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15)
+#define isRGB(x)       (((x)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
+#define isBGR(x)       (((x)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
+#define isPacked(x)    ((x)==IMGFMT_YUY2 || isRGB(x) || isBGR(x))
 
 #define RGB2YUV_SHIFT 16
 #define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
@@ -1300,7 +1295,7 @@ static void planarYuvToBgr(SwsContext *c, uint8_t* src[], int srcStride[], int s
                yuv2rgb( dst,src[0],src[2],src[1],c->srcW,srcSliceH,dstStride[0],srcStride[0],srcStride[1] );
 }
 
-static void Planar2PackedWrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+static void PlanarToYuy2Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
              int srcSliceH, uint8_t* dstParam[], int dstStride[]){
        uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
 
@@ -1542,54 +1537,49 @@ static void bgr24toyv12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], i
                dstStride[0], dstStride[1], srcStride[0]);
 }
 
+/**
+ * bring pointers in YUV order instead of YVU
+ */
+static inline void orderYUV(SwsContext *c, uint8_t * sortedP[], int sortedStride[], uint8_t * p[], int stride[]){
+       if(c->srcFormat == IMGFMT_YV12){
+               sortedP[0]= p[0];
+               sortedP[1]= p[1];
+               sortedP[2]= p[2];
+               sortedStride[0]= sortedStride[0];
+               sortedStride[1]= sortedStride[1];
+               sortedStride[2]= sortedStride[2];
+       }
+       else if(isPacked(c->srcFormat) || isGray(c->srcFormat))
+       {
+               sortedP[0]= p[0];
+               sortedP[1]= 
+               sortedP[2]= NULL;
+               sortedStride[0]= sortedStride[0];
+               sortedStride[1]= 
+               sortedStride[2]= 0;
+       }
+       else /* I420 */
+       {
+               sortedP[0]= p[0];
+               sortedP[1]= p[2];
+               sortedP[2]= p[1];
+               sortedStride[0]= sortedStride[0];
+               sortedStride[1]= sortedStride[2];
+               sortedStride[2]= sortedStride[1];
+       }
+}
 
 /* unscaled copy like stuff (assumes nearly identical formats) */
 static void simpleCopy(SwsContext *c, uint8_t* srcParam[], int srcStrideParam[], int srcSliceY,
-             int srcSliceH, uint8_t* dstParam[], int dstStride[]){
+             int srcSliceH, uint8_t* dstParam[], int dstStrideParam[]){
 
        int srcStride[3];
+       int dstStride[3];
        uint8_t *src[3];
        uint8_t *dst[3];
 
-       if(isPlanarYUV(c->srcFormat))
-       {
-           if(c->srcFormat == IMGFMT_I420 || c->srcFormat == IMGFMT_IYUV){
-               src[0]= srcParam[0];
-               src[1]= srcParam[2];
-               src[2]= srcParam[1];
-               srcStride[0]= srcStrideParam[0];
-               srcStride[1]= srcStrideParam[2];
-               srcStride[2]= srcStrideParam[1];
-           }
-           else
-           {
-               src[0]= srcParam[0];
-               src[1]= srcParam[1];
-               src[2]= srcParam[2];
-               srcStride[0]= srcStrideParam[0];
-               srcStride[1]= srcStrideParam[1];
-               srcStride[2]= srcStrideParam[2];
-           }
-       }
-       else if(isPacked(c->srcFormat) || isGray(c->srcFormat)){
-               src[0]= srcParam[0];
-               src[1]=
-               src[2]= NULL;
-               srcStride[0]= srcStrideParam[0];
-               srcStride[1]=
-               srcStride[2]= 0;
-       }
-
-       if(c->dstFormat == IMGFMT_I420 || c->dstFormat == IMGFMT_IYUV){
-               dst[0]= dstParam[0];
-               dst[1]= dstParam[2];
-               dst[2]= dstParam[1];
-               
-       }else{
-               dst[0]= dstParam[0];
-               dst[1]= dstParam[1];
-               dst[2]= dstParam[2];
-       }
+       orderYUV(c, src, srcStride, srcParam, srcStrideParam);
+       orderYUV(c, dst, dstStride, dstParam, dstStrideParam);
 
        if(isPacked(c->srcFormat))
        {
@@ -1616,45 +1606,41 @@ static void simpleCopy(SwsContext *c, uint8_t* srcParam[], int srcStrideParam[],
                }
        }
        else 
-       { /* Planar YUV */
+       { /* Planar YUV or gray */
                int plane;
                for(plane=0; plane<3; plane++)
                {
-                       int length;
-                       int y;
-                       int height;
-                       if(c->srcFormat == IMGFMT_YVU9 || c->srcFormat == IMGFMT_IF09)
-                       {
-                           length= plane==0 ? c->srcW  : ((c->srcW+1)>>2);
-                           y=      plane==0 ? srcSliceY: ((srcSliceY+1)>>2);
-                           height= plane==0 ? srcSliceH: ((srcSliceH+1)>>2);
-                       }
-                       else
+                       int length= plane==0 ? c->srcW  : ((c->srcW+1)>>1);
+                       int y=      plane==0 ? srcSliceY: ((srcSliceY+1)>>1);
+                       int height= plane==0 ? srcSliceH: ((srcSliceH+1)>>1);
+
+                       if((isGray(c->srcFormat) || isGray(c->dstFormat)) && plane>0)
                        {
-                           length= plane==0 ? c->srcW  : ((c->srcW+1)>>1);
-                           y=      plane==0 ? srcSliceY: ((srcSliceY+1)>>1);
-                           height= plane==0 ? srcSliceH: ((srcSliceH+1)>>1);
+                               if(!isGray(c->dstFormat))
+                                       memset(dst[plane], 0, dstStride[plane]*height);
                        }
-
-                       if(dstStride[plane]==srcStride[plane])
-                               memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
                        else
                        {
-                               int i;
-                               uint8_t *srcPtr= src[plane];
-                               uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
-                               for(i=0; i<height; i++)
+                               if(dstStride[plane]==srcStride[plane])
+                                       memcpy(dst[plane] + dstStride[plane]*y, src[plane], height*dstStride[plane]);
+                               else
                                {
-                                       memcpy(dstPtr, srcPtr, length);
-                                       srcPtr+= srcStride[plane];
-                                       dstPtr+= dstStride[plane];
+                                       int i;
+                                       uint8_t *srcPtr= src[plane];
+                                       uint8_t *dstPtr= dst[plane] + dstStride[plane]*y;
+                                       for(i=0; i<height; i++)
+                                       {
+                                               memcpy(dstPtr, srcPtr, length);
+                                               srcPtr+= srcStride[plane];
+                                               dstPtr+= dstStride[plane];
+                                       }
                                }
                        }
                }
        }
 }
 
-static uint32_t remove_dup_fourcc(uint32_t fourcc)
+static int remove_dup_fourcc(int fourcc)
 {
        switch(fourcc)
        {
@@ -1670,51 +1656,31 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
        SwsContext *c;
        int i;
        int usesFilter;
-       int simple_copy, unscaled_copy;
+       int unscaled;
        SwsFilter dummyFilter= {NULL, NULL, NULL, NULL};
-
 #ifdef ARCH_X86
        if(gCpuCaps.hasMMX)
                asm volatile("emms\n\t"::: "memory");
 #endif
-
        if(swScale==NULL) globalInit();
 
        /* avoid dupplicate Formats, so we dont need to check to much */
        srcFormat = remove_dup_fourcc(srcFormat);
        dstFormat = remove_dup_fourcc(dstFormat);
-       /* don't refuse this beauty */
-       unscaled_copy = (srcW == dstW && srcH == dstH);
-       simple_copy = (srcW == dstW && srcH == dstH && srcFormat == dstFormat);
-       if(!simple_copy)
+
+       unscaled = (srcW == dstW && srcH == dstH);
+
+       if(!isSupportedIn(srcFormat)) 
        {
-           if(unscaled_copy)
-           {
-               if(!isSupportedUnscaledIn(srcFormat)) 
-               {
-                   MSG_ERR("swScaler: %s is not supported as input format\n", vo_format_name(srcFormat));
-                   return NULL;
-               }
-               if(!isSupportedUnscaledOut(dstFormat))
-               {
-                   MSG_ERR("swScaler: %s is not supported as output format\n", vo_format_name(dstFormat));
-                   return NULL;
-               }
-           }
-           else
-           {
-               if(!isSupportedIn(srcFormat)) 
-               {
-                   MSG_ERR("swScaler: %s is not supported as input format\n", vo_format_name(srcFormat));
-                   return NULL;
-               }
-               if(!isSupportedOut(dstFormat))
-               {
-                   MSG_ERR("swScaler: %s is not supported as output format\n", vo_format_name(dstFormat));
-                   return NULL;
-               }
-           }
+               MSG_ERR("swScaler: %s is not supported as input format\n", vo_format_name(srcFormat));
+               return NULL;
+       }
+       if(!isSupportedOut(dstFormat))
+       {
+               MSG_ERR("swScaler: %s is not supported as output format\n", vo_format_name(dstFormat));
+               return NULL;
        }
+
        /* sanity check */
        if(srcW<4 || srcH<1 || dstW<8 || dstH<1) //FIXME check if these are enough and try to lowwer them after fixing the relevant parts of the code
        {
@@ -1750,7 +1716,7 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
        if(srcFilter->chrH!=NULL && srcFilter->chrH->length>1) usesFilter=1;
        
        /* unscaled special Cases */
-       if(srcW==dstW && srcH==dstH && !usesFilter)
+       if(unscaled && !usesFilter)
        {
                /* yv12_to_nv12 */
                if((srcFormat == IMGFMT_YV12||srcFormat==IMGFMT_I420)&&dstFormat == IMGFMT_NV12)
@@ -1765,7 +1731,7 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
                /* yv12_to_yuy2 */
                if((srcFormat == IMGFMT_YV12||srcFormat==IMGFMT_I420)&&dstFormat == IMGFMT_YUY2)
                {
-                       c->swScale= Planar2PackedWrapper;
+                       c->swScale= PlanarToYuy2Wrapper;
 
                        if(flags&SWS_PRINT_INFO)
                                MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n", 
@@ -1793,7 +1759,8 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
                }
 
                /* simple copy */
-               if(srcFormat == dstFormat || (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat)))
+               if(srcFormat == dstFormat 
+                  || ((isPlanarYUV(srcFormat)||isGray(srcFormat)) && (isPlanarYUV(dstFormat)||isGray(dstFormat))))
                {
                        c->swScale= simpleCopy;
 
@@ -1802,7 +1769,7 @@ SwsContext *getSwsContext(int srcW, int srcH, int srcFormat, int dstW, int dstH,
                                        vo_format_name(srcFormat), vo_format_name(dstFormat));
                        return c;
                }
-               
+
                /* bgr32to24 & rgb32to24*/
                if((srcFormat==IMGFMT_BGR32 && dstFormat==IMGFMT_BGR24)
                 ||(srcFormat==IMGFMT_RGB32 && dstFormat==IMGFMT_RGB24))
@@ -2424,7 +2391,6 @@ void freeVec(SwsVector *a){
 
 void freeSwsContext(SwsContext *c){
        int i;
-
        if(!c) return;
 
        if(c->lumPixBuf)
index 41d3f9065091f5ce73a83e2ea0d9e21e611d5f42..38a94fe63d6a2d1e867c1a646afbf39577f9684f 100644 (file)
@@ -717,14 +717,17 @@ static inline void RENAME(yuv2yuv1)(int16_t *lumSrc, int16_t *chrSrc,
                : "%eax"
        );
 #else
-       //FIXME Optimize (just quickly writen not opti..)
-       //FIXME replace MINMAX with LUTs
        int i;
        for(i=0; i<dstW; i++)
        {
                int val= lumSrc[i]>>7;
+               
+               if(val&256){
+                       if(val<0) val=0;
+                       else      val=255;
+               }
 
-               dest[i]= MIN(MAX(val>>19, 0), 255);
+               dest[i]= val;
        }
 
        if(uDest != NULL)
@@ -733,8 +736,15 @@ static inline void RENAME(yuv2yuv1)(int16_t *lumSrc, int16_t *chrSrc,
                        int u=chrSrc[i]>>7;
                        int v=chrSrc[i + 2048]>>7;
 
-                       uDest[i]= MIN(MAX(u>>19, 0), 255);
-                       vDest[i]= MIN(MAX(v>>19, 0), 255);
+                       if((u|v)&256){
+                               if(u<0)         u=0;
+                               else if (u>255) u=255;
+                               if(v<0)         v=0;
+                               else if (v>255) v=255;
+                       }
+
+                       uDest[i]= u;
+                       vDest[i]= v;
                }
 #endif
 }
@@ -2575,6 +2585,7 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
        const int lumXInc= c->lumXInc;
        const int chrXInc= c->chrXInc;
        const int dstFormat= c->dstFormat;
+       const int srcFormat= c->srcFormat;
        const int flags= c->flags;
        const int canMMX2BeUsed= c->canMMX2BeUsed;
        int16_t *vLumFilterPos= c->vLumFilterPos;
@@ -2609,7 +2620,7 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
        int dstStride[3];
        uint8_t *src[3];
        uint8_t *dst[3];
-       
+
        if(c->srcFormat == IMGFMT_I420){
                src[0]= srcParam[0];
                src[1]= srcParam[2];
@@ -2626,7 +2637,7 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
                srcStride[1]= srcStrideParam[1];
                srcStride[2]= srcStrideParam[2];
        }
-       else if(isPacked(c->srcFormat) || isBGR(c->srcFormat) || isRGB(c->srcFormat)){
+       else if(isPacked(c->srcFormat)){
                src[0]=
                src[1]=
                src[2]= srcParam[0];
@@ -2729,7 +2740,9 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
                                ASSERT(lastInChrBuf + 1 - (srcSliceY>>1) < ((srcSliceH+1)>>1))
                                ASSERT(lastInChrBuf + 1 - (srcSliceY>>1) >= 0)
                                //FIXME replace parameters through context struct (some at least)
-                               RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, (srcW+1)>>1, chrXInc,
+
+                               if(!(isGray(srcFormat) || isGray(dstFormat)))
+                                       RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, (srcW+1)>>1, chrXInc,
                                                flags, canMMX2BeUsed, hChrFilter, hChrFilterPos, hChrFilterSize,
                                                funnyUVCode, c->srcFormat, formatConvBuffer, 
                                                c->chrMmx2Filter, c->chrMmx2FilterPos);
@@ -2768,7 +2781,9 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
                                ASSERT(chrBufIndex < 2*vChrBufSize)
                                ASSERT(lastInChrBuf + 1 - (srcSliceY>>1) < ((srcSliceH+1)>>1))
                                ASSERT(lastInChrBuf + 1 - (srcSliceY>>1) >= 0)
-                               RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, (srcW+1)>>1, chrXInc,
+
+                               if(!(isGray(srcFormat) || isGray(dstFormat)))
+                                       RENAME(hcscale)(chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, (srcW+1)>>1, chrXInc,
                                                flags, canMMX2BeUsed, hChrFilter, hChrFilterPos, hChrFilterSize,
                                                funnyUVCode, c->srcFormat, formatConvBuffer, 
                                                c->chrMmx2Filter, c->chrMmx2FilterPos);
@@ -2788,9 +2803,9 @@ static void RENAME(swScale)(SwsContext *c, uint8_t* srcParam[], int srcStridePar
 #endif
            if(dstY < dstH-2)
            {
-               if(isPlanarYUV(dstFormat)) //YV12 like
+               if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 like
                {
-                       if(dstY&1) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
+                       if((dstY&1) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi
                        if(vLumFilterSize == 1 && vChrFilterSize == 1) // Unscaled YV12
                        {
                                int16_t *lumBuf = lumPixBuf[0];