From 6118e52ea6e072d1fa126328fc227f290cc8b06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 16 Feb 2005 23:47:00 +0000 Subject: [PATCH] Improved NV12/NV21 support. - Fixed PlanarToNV12Wrapper() and made it handle NV21. - Added yuv2nv12XinC() to handle software scaling. - Added NV12/NV21 handling to various places. - Removed NV12 from vf_hue and vf_spp as they don't look like they can actually handle it. Originally committed as revision 14716 to svn://svn.mplayerhq.hu/mplayer/trunk/postproc --- postproc/swscale.c | 74 +++++++++++++++++++++++++++++++++++-- postproc/swscale_template.c | 29 ++++++++++++++- 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/postproc/swscale.c b/postproc/swscale.c index 05f07d0444..89fcc0a55d 100644 --- a/postproc/swscale.c +++ b/postproc/swscale.c @@ -101,6 +101,7 @@ untested special converters //FIXME replace this with something faster #define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_YVU9 \ + || (x)==IMGFMT_NV12 || (x)==IMGFMT_NV21 \ || (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P) #define isYUV(x) ((x)==IMGFMT_UYVY || (x)==IMGFMT_YUY2 || isPlanarYUV(x)) #define isGray(x) ((x)==IMGFMT_Y800) @@ -114,6 +115,7 @@ untested special converters #define isSupportedOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_YUY2 || (x)==IMGFMT_UYVY\ || (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P\ || isRGB(x) || isBGR(x)\ + || (x)==IMGFMT_NV12 || (x)==IMGFMT_NV21\ || (x)==IMGFMT_Y800 || (x)==IMGFMT_YVU9) #define isPacked(x) ((x)==IMGFMT_YUY2 || (x)==IMGFMT_UYVY ||isRGB(x) || isBGR(x)) @@ -251,6 +253,56 @@ static inline void yuv2yuvXinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilt } } +static inline void yuv2nv12XinC(int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, + int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, + uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat) +{ + //FIXME Optimize (just quickly writen not opti..) + int i; + for(i=0; i>19, 0), 255); + } + + if(uDest == NULL) + return; + + if(dstFormat == IMGFMT_NV12) + for(i=0; i>19, 0), 255); + uDest[2*i+1]= MIN(MAX(v>>19, 0), 255); + } + else + for(i=0; i>19, 0), 255); + uDest[2*i+1]= MIN(MAX(u>>19, 0), 255); + } +} #define YSCALE_YUV_2_PACKEDX_C(type) \ for(i=0; i<(dstW>>1); i++){\ @@ -1379,13 +1431,16 @@ static int PlanarToNV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], i uint8_t *dstPtr= dst; for(i=0; isrcW); srcPtr+= srcStride[0]; dstPtr+= dstStride[0]; } } - dst = dstParam[1] + dstStride[1]*srcSliceY; - interleaveBytes( src[1],src[2],dst,c->srcW,srcSliceH,srcStride[1],srcStride[2],dstStride[0] ); + dst = dstParam[1] + dstStride[1]*srcSliceY/2; + if (c->dstFormat == IMGFMT_NV12) + interleaveBytes( src[1],src[2],dst,c->srcW/2,srcSliceH/2,srcStride[1],srcStride[2],dstStride[0] ); + else + interleaveBytes( src[2],src[1],dst,c->srcW/2,srcSliceH/2,srcStride[2],srcStride[1],dstStride[0] ); return srcSliceH; } @@ -1555,6 +1610,15 @@ static inline void sws_orderYUV(int format, uint8_t * sortedP[], int sortedStrid sortedStride[0]= stride[0]; sortedStride[1]= stride[1]; sortedStride[2]= stride[2]; + } + else if(format == IMGFMT_NV12 || format == IMGFMT_NV21) + { + sortedP[0]= p[0]; + sortedP[1]= p[1]; + sortedP[2]= NULL; + sortedStride[0]= stride[0]; + sortedStride[1]= stride[1]; + sortedStride[2]= 0; }else{ MSG_ERR("internal error in orderYUV\n"); } @@ -1645,6 +1709,8 @@ static void getSubSampleFactors(int *h, int *v, int format){ break; case IMGFMT_YV12: case IMGFMT_Y800: //FIXME remove after different subsamplings are fully implemented + case IMGFMT_NV12: + case IMGFMT_NV21: *h=1; *v=1; break; @@ -1873,7 +1939,7 @@ SwsContext *sws_getContext(int srcW, int srcH, int origSrcFormat, int dstW, int if(unscaled && !usesHFilter && !usesVFilter) { /* yv12_to_nv12 */ - if(srcFormat == IMGFMT_YV12 && dstFormat == IMGFMT_NV12) + if(srcFormat == IMGFMT_YV12 && (dstFormat == IMGFMT_NV12 || dstFormat == IMGFMT_NV21)) { c->swScale= PlanarToNV12Wrapper; } diff --git a/postproc/swscale_template.c b/postproc/swscale_template.c index 692a279a62..e7814f72aa 100644 --- a/postproc/swscale_template.c +++ b/postproc/swscale_template.c @@ -796,6 +796,15 @@ yuv2yuvXinC(lumFilter, lumSrc, lumFilterSize, #endif } +static inline void RENAME(yuv2nv12X)(SwsContext *c, int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, + int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, + uint8_t *dest, uint8_t *uDest, int dstW, int chrDstW, int dstFormat) +{ +yuv2nv12XinC(lumFilter, lumSrc, lumFilterSize, + chrFilter, chrSrc, chrFilterSize, + dest, uDest, dstW, chrDstW, dstFormat); +} + static inline void RENAME(yuv2yuv1)(int16_t *lumSrc, int16_t *chrSrc, uint8_t *dest, uint8_t *uDest, uint8_t *vDest, int dstW, int chrDstW) { @@ -2792,7 +2801,15 @@ i--; ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001; } #endif - if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 like + if(dstFormat == IMGFMT_NV12 || dstFormat == IMGFMT_NV21){ + const int chrSkipMask= (1<chrDstVSubSample)-1; + if(dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi + RENAME(yuv2nv12X)(c, + vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize, + vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize, + dest, uDest, dstW, chrDstW, dstFormat); + } + else if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 like { const int chrSkipMask= (1<chrDstVSubSample)-1; if((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi @@ -2840,7 +2857,15 @@ i--; { int16_t **lumSrcPtr= lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize; int16_t **chrSrcPtr= chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; - if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 + if(dstFormat == IMGFMT_NV12 || dstFormat == IMGFMT_NV21){ + const int chrSkipMask= (1<chrDstVSubSample)-1; + if(dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi + yuv2nv12XinC( + vLumFilter+dstY*vLumFilterSize , lumSrcPtr, vLumFilterSize, + vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize, + dest, uDest, dstW, chrDstW, dstFormat); + } + else if(isPlanarYUV(dstFormat) || isGray(dstFormat)) //YV12 { const int chrSkipMask= (1<chrDstVSubSample)-1; if((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi