From c260a1139d5990a9cdcf0d678a7e6c99978b98c1 Mon Sep 17 00:00:00 2001 From: syrjala 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. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@14716 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libmpcodecs/vf.c | 6 +++ libmpcodecs/vf_eq.c | 1 + libmpcodecs/vf_hue.c | 1 - libmpcodecs/vf_scale.c | 4 ++ libmpcodecs/vf_spp.c | 2 - postproc/swscale.c | 74 +++++++++++++++++++++++++++++++++++-- postproc/swscale_template.c | 29 ++++++++++++++- 7 files changed, 108 insertions(+), 9 deletions(-) diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index bd591163d6..0bebfcc49e 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -356,6 +356,7 @@ mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, //if(!mpi->stride[0]) mpi->stride[0]=mpi->width; //if(!mpi->stride[1]) + if(mpi->num_planes > 2){ mpi->stride[1]=mpi->stride[2]=mpi->chroma_width; if(mpi->flags&MP_IMGFLAG_SWAPPED){ // I420/IYUV (Y,U,V) @@ -366,6 +367,11 @@ mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, mpi->planes[2]=mpi->planes[0]+mpi->width*mpi->height; mpi->planes[1]=mpi->planes[2]+mpi->chroma_width*mpi->chroma_height; } + } else { + // NV12/NV21 + mpi->stride[1]=mpi->chroma_width; + mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height; + } } else { //if(!mpi->stride[0]) mpi->stride[0]=mpi->width*mpi->bpp/8; diff --git a/libmpcodecs/vf_eq.c b/libmpcodecs/vf_eq.c index d7adeea1ff..5b27e5250c 100644 --- a/libmpcodecs/vf_eq.c +++ b/libmpcodecs/vf_eq.c @@ -188,6 +188,7 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt) case IMGFMT_Y800: case IMGFMT_Y8: case IMGFMT_NV12: + case IMGFMT_NV21: case IMGFMT_444P: case IMGFMT_422P: case IMGFMT_411P: diff --git a/libmpcodecs/vf_hue.c b/libmpcodecs/vf_hue.c index b7952d9536..f1e8b4d642 100644 --- a/libmpcodecs/vf_hue.c +++ b/libmpcodecs/vf_hue.c @@ -130,7 +130,6 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt) case IMGFMT_I420: case IMGFMT_IYUV: case IMGFMT_CLPL: - case IMGFMT_NV12: case IMGFMT_444P: case IMGFMT_422P: case IMGFMT_411P: diff --git a/libmpcodecs/vf_scale.c b/libmpcodecs/vf_scale.c index 17416bb14b..98d1ba89f7 100644 --- a/libmpcodecs/vf_scale.c +++ b/libmpcodecs/vf_scale.c @@ -56,6 +56,8 @@ static unsigned int outfmt_list[]={ IMGFMT_YVU9, IMGFMT_IF09, IMGFMT_411P, + IMGFMT_NV12, + IMGFMT_NV21, IMGFMT_YUY2, IMGFMT_UYVY, // RGB and grayscale (Y8 and Y800): @@ -175,6 +177,8 @@ static int config(struct vf_instance_s* vf, case IMGFMT_YV12: /* YV12 needs w & h rounded to 2 */ case IMGFMT_I420: case IMGFMT_IYUV: + case IMGFMT_NV12: + case IMGFMT_NV21: vf->priv->h = (vf->priv->h + 1) & ~1; case IMGFMT_YUY2: /* YUY2 needs w rounded to 2 */ case IMGFMT_UYVY: diff --git a/libmpcodecs/vf_spp.c b/libmpcodecs/vf_spp.c index 4a19153479..dce9e4f649 100644 --- a/libmpcodecs/vf_spp.c +++ b/libmpcodecs/vf_spp.c @@ -528,7 +528,6 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){ case IMGFMT_CLPL: case IMGFMT_Y800: case IMGFMT_Y8: - case IMGFMT_NV12: case IMGFMT_444P: case IMGFMT_422P: case IMGFMT_411P: @@ -546,7 +545,6 @@ static unsigned int fmt_list[]={ IMGFMT_CLPL, IMGFMT_Y800, IMGFMT_Y8, - IMGFMT_NV12, IMGFMT_444P, IMGFMT_422P, IMGFMT_411P, 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