changeset 27548:78da4c8b2293

Implement full horizontal chroma for rgb/bgr24/32 output.
author michael
date Thu, 11 Sep 2008 14:39:12 +0000
parents a917f63f61d3
children 60d6783b2157
files libswscale/swscale.c libswscale/swscale_template.c
diffstat 2 files changed, 115 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libswscale/swscale.c	Thu Sep 11 03:22:39 2008 +0000
+++ b/libswscale/swscale.c	Thu Sep 11 14:39:12 2008 +0000
@@ -473,6 +473,43 @@
             else if (V<0) V=0;    \
         }
 
+#define YSCALE_YUV_2_PACKEDX_FULL_C \
+    for (i=0; i<dstW; i++){\
+        int j;\
+        int Y = 0;\
+        int U = -128<<19;\
+        int V = -128<<19;\
+        int R,G,B;\
+        \
+        for (j=0; j<lumFilterSize; j++){\
+            Y += lumSrc[j][i     ] * lumFilter[j];\
+        }\
+        for (j=0; j<chrFilterSize; j++){\
+            U += chrSrc[j][i     ] * chrFilter[j];\
+            V += chrSrc[j][i+VOFW] * chrFilter[j];\
+        }\
+        Y >>=10;\
+        U >>=10;\
+        V >>=10;\
+
+#define YSCALE_YUV_2_RGBX_FULL_C(rnd) \
+    YSCALE_YUV_2_PACKEDX_FULL_C\
+        Y-= c->oy;\
+        Y*= c->cy;\
+        Y+= rnd;\
+        R= Y + V*c->cvr;\
+        G= Y + V*c->cvg + U*c->cug;\
+        B= Y +            U*c->cub;\
+        if ((R|G|B)&(0xC0000000)){\
+            if (R>=(256<<22))   R=(256<<22)-1; \
+            else if (R<0)R=0;   \
+            if (G>=(256<<22))   G=(256<<22)-1; \
+            else if (G<0)G=0;   \
+            if (B>=(256<<22))   B=(256<<22)-1; \
+            else if (B<0)B=0;   \
+        }\
+
+
 #define YSCALE_YUV_2_GRAY16_C \
     for (i=0; i<(dstW>>1); i++){\
         int j;\
@@ -756,6 +793,42 @@
     YSCALE_YUV_2_ANYRGB_C(YSCALE_YUV_2_RGBX_C, YSCALE_YUV_2_PACKEDX_C(void), YSCALE_YUV_2_GRAY16_C, YSCALE_YUV_2_MONOBLACKX_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)
+{
+    int i;
+    int step= fmt_depth(c->dstFormat)/8;
+
+    switch(c->dstFormat){
+    case PIX_FMT_ARGB:
+        dest++;
+    case PIX_FMT_RGB24:
+    case PIX_FMT_RGBA:
+        YSCALE_YUV_2_RGBX_FULL_C(1<<21)
+            dest[0]= R>>22;
+            dest[1]= G>>22;
+            dest[2]= B>>22;
+            dest[3]= 0;
+            dest+= step;
+        }
+        break;
+    case PIX_FMT_ABGR:
+        dest++;
+    case PIX_FMT_BGR24:
+    case PIX_FMT_BGRA:
+        YSCALE_YUV_2_RGBX_FULL_C(1<<21)
+            dest[0]= B>>22;
+            dest[1]= G>>22;
+            dest[2]= R>>22;
+            dest[3]= 0;
+            dest+= step;
+        }
+        break;
+    default:
+        assert(0);
+    }
+}
 
 //Note: we have C, X86, MMX, MMX2, 3DNOW version therse no 3DNOW+MMX2 one
 //Plain C versions
@@ -1880,6 +1953,13 @@
     c->ugCoeff=   roundToInt16(cgu*8192) * 0x0001000100010001ULL;
     c->yOffset=   roundToInt16(oy *   8) * 0x0001000100010001ULL;
 
+    c->cy = (int16_t)roundToInt16(cy <<13);
+    c->oy = (int16_t)roundToInt16(oy <<9);
+    c->cvr= (int16_t)roundToInt16(crv<<13);
+    c->cvg= (int16_t)roundToInt16(cgv<<13);
+    c->cug= (int16_t)roundToInt16(cgu<<13);
+    c->cub= (int16_t)roundToInt16(cbu<<13);
+
     yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation);
     //FIXME factorize
 
@@ -1993,7 +2073,13 @@
         av_log(NULL, AV_LOG_ERROR, "swScaler: Exactly one scaler algorithm must be choosen\n");
         return NULL;
     }
-
+if(   dstFormat != PIX_FMT_RGB32 //HACK
+   && dstFormat != PIX_FMT_RGB32_1
+   && dstFormat != PIX_FMT_RGB24
+   && dstFormat != PIX_FMT_BGR24
+   && dstFormat != PIX_FMT_BGR32
+   && dstFormat != PIX_FMT_BGR32_1)
+    flags &= ~SWS_FULL_CHR_H_INT;
 
     /* 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
--- a/libswscale/swscale_template.c	Thu Sep 11 03:22:39 2008 +0000
+++ b/libswscale/swscale_template.c	Thu Sep 11 14:39:12 2008 +0000
@@ -3132,8 +3132,15 @@
                 if (vLumFilterSize == 1 && vChrFilterSize == 2) //unscaled RGB
                 {
                     int chrAlpha= vChrFilter[2*dstY+1];
+                    if(flags & SWS_FULL_CHR_H_INT){
+                        yuv2rgbXinC_full(c, //FIXME write a packed1_full function
+                            vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                            vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+                            dest, dstW, dstY);
+                    }else{
                     RENAME(yuv2packed1)(c, *lumSrcPtr, *chrSrcPtr, *(chrSrcPtr+1),
                         dest, dstW, chrAlpha, dstFormat, flags, dstY);
+                    }
                 }
                 else if (vLumFilterSize == 2 && vChrFilterSize == 2) //bilinear upscale RGB
                 {
@@ -3143,15 +3150,29 @@
                     lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;
                     chrMmxFilter[2]=
                     chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;
+                    if(flags & SWS_FULL_CHR_H_INT){
+                        yuv2rgbXinC_full(c, //FIXME write a packed2_full function
+                            vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                            vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+                            dest, dstW, dstY);
+                    }else{
                     RENAME(yuv2packed2)(c, *lumSrcPtr, *(lumSrcPtr+1), *chrSrcPtr, *(chrSrcPtr+1),
                         dest, dstW, lumAlpha, chrAlpha, dstY);
+                    }
                 }
                 else //general RGB
                 {
+                    if(flags & SWS_FULL_CHR_H_INT){
+                        yuv2rgbXinC_full(c,
+                            vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                            vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+                            dest, dstW, dstY);
+                    }else{
                     RENAME(yuv2packedX)(c,
                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
                         dest, dstW, dstY);
+                    }
                 }
             }
         }
@@ -3180,10 +3201,17 @@
             {
                 assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);
                 assert(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);
+                if(flags & SWS_FULL_CHR_H_INT){
+                    yuv2rgbXinC_full(c,
+                        vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
+                        vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
+                        dest, dstW, dstY);
+                }else{
                 yuv2packedXinC(c,
                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,
                     vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,
                     dest, dstW, dstY);
+                }
             }
         }
     }