diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2002-06-22 20:37:30 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2002-06-22 20:37:30 +0000 |
commit | 44c1035c2f41543417180daa5262494d81f3f3f3 (patch) | |
tree | 8b243f4c4829b704342a29ece5a5fffed784b46e /postproc/swscale.c | |
parent | bd5e1c72f824c0e9f8d4912359aafef48d25b179 (diff) | |
download | ffmpeg-44c1035c2f41543417180daa5262494d81f3f3f3.tar.gz |
cleanup & grayscale support
Originally committed as revision 6504 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc
Diffstat (limited to 'postproc/swscale.c')
-rw-r--r-- | postproc/swscale.c | 200 |
1 files changed, 83 insertions, 117 deletions
diff --git a/postproc/swscale.c b/postproc/swscale.c index cef9cd9664..96ea6ea7f6 100644 --- a/postproc/swscale.c +++ b/postproc/swscale.c @@ -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) |