[MPlayer-dev-eng] Re: [PATCH] some support for NV12 and NV21 image format

Angelo Cano angelo_cano at fastmail.fm
Tue Apr 29 08:09:29 CEST 2003


On Fri, Apr 18, 2003 at 11:36:46AM -0500, acano wrote:
> I have a tv card that outputs yuv420p using NV12 format, this patch
> enables NV12/NV21 -> YV12 conversion.
> 

Previous patch has mistakes in it, sorry.  Here's a new one.

-------------- next part --------------
diff -Nur main/DOCS/de/mplayer.1 test/DOCS/de/mplayer.1
--- main/DOCS/de/mplayer.1	Sat Mar 22 07:01:47 2003
+++ test/DOCS/de/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -756,7 +756,7 @@
 Gibt die Frequenz an, auf die der Tuner gesetzt wird (z.B.\& 511.250).
 Kann nicht zusammen mit 'channels' benutzt werden.
 .IPs outfmt=<Wert>
-Ausgabeformat des Tuners (yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2, i420)
+Ausgabeformat des Tuners (yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2, i420, nv12, nv21)
 .IPs width=<Wert>
 Breite des Ausgabefensters
 .IPs height=<Wert>
diff -Nur main/DOCS/en/mplayer.1 test/DOCS/en/mplayer.1
--- main/DOCS/en/mplayer.1	Sun Apr 27 12:19:58 2003
+++ test/DOCS/en/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -781,7 +781,7 @@
 Not compatible with channels parameter.
 .IPs outfmt=<value>
 output format of the tuner (yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2,
-i420)
+i420, nv12, nv21)
 .IPs width=<value>
 width of the output window
 .IPs height=<value>
diff -Nur main/DOCS/fr/mplayer.1 test/DOCS/fr/mplayer.1
--- main/DOCS/fr/mplayer.1	Sun Apr 27 12:19:58 2003
+++ test/DOCS/fr/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -804,7 +804,7 @@
 Non compatible avec le param?tre channels.
 .IPs outfmt=<valeur>
 format de sortie du tuner (yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2,
-i420)
+i420, nv12, nv21)
 .IPs width=<valeur>
 largeur de la fen?tre
 .IPs height=<valeur>
diff -Nur main/DOCS/hu/mplayer.1 test/DOCS/hu/mplayer.1
--- main/DOCS/hu/mplayer.1	Mon Apr 21 12:11:26 2003
+++ test/DOCS/hu/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -717,7 +717,7 @@
 Nem haszn?lhat? a channels opci?val.
 .IPs outfmt=<?rt?k>
 A tuner kimeneti form?tum?nak megv?ltoztat?sa
-(yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2, i420)
+(yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2, i420, nv12, nv21)
 .IPs width=<?rt?k>
 a kimeneti ablak sz?less?ge
 .IPs height=<?rt?k>
diff -Nur main/DOCS/pl/mplayer.1 test/DOCS/pl/mplayer.1
--- main/DOCS/pl/mplayer.1	Sun Mar 30 11:09:25 2003
+++ test/DOCS/pl/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -726,7 +726,7 @@
 Not compatible with channels parameter.
 .IPs outfmt=<value>
 output format of the tuner (yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2,
-i420)
+i420, nv12, nv21)
 .IPs width=<value>
 width of the output window
 .IPs height=<value>
diff -Nur main/DOCS/zh/mplayer.1 test/DOCS/zh/mplayer.1
--- main/DOCS/zh/mplayer.1	Sun Apr  6 08:27:10 2003
+++ test/DOCS/zh/mplayer.1	Mon Apr 28 15:49:29 2003
@@ -638,7 +638,7 @@
 ????????????????.
 .IPs outfmt=<????>
 ????????????????????(yv12, rgb32, rgb24, rgb16, rgb15, uyvy, yuy2,
-i420)
+i420, nv12, nv21)
 .IPs width=<????>
 ??????????????
 .IPs height=<????>
diff -Nur main/codec-cfg.c test/codec-cfg.c
--- main/codec-cfg.c	Sun Dec 15 21:22:37 2002
+++ test/codec-cfg.c	Mon Apr 28 15:49:29 2003
@@ -132,6 +132,8 @@
 		{"YV12",  IMGFMT_YV12},
 		{"I420",  IMGFMT_I420},
 		{"IYUV",  IMGFMT_IYUV},
+		{"NV12",  IMGFMT_NV12},
+		{"NV21",  IMGFMT_NV21},
 		{"YVU9",  IMGFMT_YVU9},
 		{"IF09",  IMGFMT_IF09},
 		{"444P",  IMGFMT_444P},
diff -Nur main/etc/codecs.conf test/etc/codecs.conf
--- main/etc/codecs.conf	Tue Apr 15 15:40:11 2003
+++ test/etc/codecs.conf	Mon Apr 28 15:49:29 2003
@@ -1429,6 +1429,24 @@
   fourcc yvu9,YVU9
   out YVU9
 
+videocodec rawnv12
+  info "RAW NV12" 
+  status working
+  driver raw    
+  format 0x0 0x3231564E
+  format 0x20776172
+  fourcc nv12,NV12
+  out NV12
+
+videocodec rawnv21
+  info "RAW NV21"
+  status working
+  driver raw    
+  format 0x0 0x3132564E
+  format 0x20776172
+  fourcc nv21,NV21
+  out NV21
+
 ; NULL codec - for testing.
 
 videocodec null
diff -Nur main/libmpcodecs/img_format.c test/libmpcodecs/img_format.c
--- main/libmpcodecs/img_format.c	Thu Jan 30 04:14:58 2003
+++ test/libmpcodecs/img_format.c	Mon Apr 28 15:49:29 2003
@@ -32,6 +32,7 @@
 	case IMGFMT_422P: return("Planar 422P");
 	case IMGFMT_411P: return("Planar 411P");
 	case IMGFMT_NV12: return("Planar NV12");
+	case IMGFMT_NV21: return("Planar NV21");
 	case IMGFMT_IUYV: return("Packed IUYV");
 	case IMGFMT_IY41: return("Packed IY41");
 	case IMGFMT_IYU1: return("Packed IYU1");
diff -Nur main/libmpcodecs/img_format.h test/libmpcodecs/img_format.h
--- main/libmpcodecs/img_format.h	Thu Jan 30 04:14:58 2003
+++ test/libmpcodecs/img_format.h	Mon Apr 28 15:49:29 2003
@@ -44,6 +44,7 @@
 #define IMGFMT_Y800 0x30303859
 #define IMGFMT_Y8   0x20203859
 #define IMGFMT_NV12 0x3231564E
+#define IMGFMT_NV21 0x3132564E
 
 /* unofficial Planar Formats, FIXME if official 4CC exists */
 #define IMGFMT_444P 0x50343434
diff -Nur main/libmpcodecs/mp_image.h test/libmpcodecs/mp_image.h
--- main/libmpcodecs/mp_image.h	Fri Apr 18 08:18:59 2003
+++ test/libmpcodecs/mp_image.h	Tue Apr 29 00:12:48 2003
@@ -114,6 +114,17 @@
     mpi->flags|=MP_IMGFLAG_YUV;
     mpi->num_planes=3;
     switch(out_fmt){
+    case IMGFMT_NV12:
+	mpi->flags|=MP_IMGFLAG_SWAPPED;
+    case IMGFMT_NV21:
+	mpi->num_planes=2;
+	mpi->flags|=MP_IMGFLAG_PLANAR;
+	mpi->bpp=12;
+	mpi->chroma_width=(mpi->width>>0);
+	mpi->chroma_height=(mpi->height>>1);
+	mpi->chroma_x_shift=0;
+	mpi->chroma_y_shift=1;
+	return;
     case IMGFMT_I420:
     case IMGFMT_IYUV:
 	mpi->flags|=MP_IMGFLAG_SWAPPED;
diff -Nur main/libmpcodecs/vd_raw.c test/libmpcodecs/vd_raw.c
--- main/libmpcodecs/vd_raw.c	Thu Oct 17 16:32:35 2002
+++ test/libmpcodecs/vd_raw.c	Mon Apr 28 16:13:42 2003
@@ -68,7 +68,11 @@
 	mpi->planes[0]=data;
 	mpi->stride[0]=mpi->width;
 	frame_size=mpi->stride[0]*mpi->h;
-        if(mpi->flags&MP_IMGFLAG_YUV) {
+	if(mpi->imgfmt==IMGFMT_NV12 || mpi->imgfmt==IMGFMT_NV21) {
+		mpi->planes[1]=mpi->planes[0]+mpi->width*mpi->height;
+		mpi->stride[1]=mpi->chroma_width;
+		frame_size+=mpi->chroma_width*mpi->chroma_height;
+	} else if(mpi->flags&MP_IMGFLAG_YUV) {
             // Support for some common Planar YUV formats
 	    /* YV12,I420,IYUV */
             int cb=2, cr=1;
diff -Nur main/libmpcodecs/vf_eq.c test/libmpcodecs/vf_eq.c
--- main/libmpcodecs/vf_eq.c	Sat Mar 15 15:45:03 2003
+++ test/libmpcodecs/vf_eq.c	Mon Apr 28 15:49:29 2003
@@ -188,6 +188,7 @@
 	case IMGFMT_Y800:
 	case IMGFMT_Y8:
 	case IMGFMT_NV12:
+	case IMGFMT_NV21:
 	case IMGFMT_444P:
 	case IMGFMT_422P:
 	case IMGFMT_411P:
diff -Nur main/libmpcodecs/vf_scale.c test/libmpcodecs/vf_scale.c
--- main/libmpcodecs/vf_scale.c	Sun Apr 27 12:19:59 2003
+++ test/libmpcodecs/vf_scale.c	Mon Apr 28 15:49:29 2003
@@ -67,6 +67,8 @@
     IMGFMT_YV12,
     IMGFMT_I420,
     IMGFMT_IYUV,
+    IMGFMT_NV12,
+    IMGFMT_NV21,
     IMGFMT_YVU9,
     IMGFMT_IF09,
     IMGFMT_411P,
@@ -327,13 +329,15 @@
 
 //===========================================================================//
 
-//  supported Input formats: YV12, I420, IYUV, YUY2, UYVY, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8, Y800
+//  supported Input formats: YV12, I420, IYUV, NV12, NV21, YUY2, UYVY, BGR32, BGR24, BGR16, BGR15, RGB32, RGB24, Y8, Y800
 
 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
     switch(fmt){
     case IMGFMT_YV12:
     case IMGFMT_I420:
     case IMGFMT_IYUV:
+    case IMGFMT_NV12:
+    case IMGFMT_NV21:
     case IMGFMT_UYVY:
     case IMGFMT_YUY2:
     case IMGFMT_BGR32:
diff -Nur main/libmpdemux/tv.c test/libmpdemux/tv.c
--- main/libmpdemux/tv.c	Mon Apr 28 15:47:14 2003
+++ test/libmpdemux/tv.c	Mon Apr 28 15:49:29 2003
@@ -149,6 +149,10 @@
 	picture_format = IMGFMT_RGB16;
     else if (!strcasecmp(tv_param_outfmt, "rgb15"))
 	picture_format = IMGFMT_RGB15;
+    else if (!strcasecmp(tv_param_outfmt, "nv12"))
+	picture_format = IMGFMT_NV12;
+    else if (!strcasecmp(tv_param_outfmt, "nv21"))
+	picture_format = IMGFMT_NV21;
     else
     {
 	mp_msg(MSGT_TV, MSGL_ERR, "Unknown format given: %s\n", tv_param_outfmt);
diff -Nur main/libmpdemux/tvi_v4l.c test/libmpdemux/tvi_v4l.c
--- main/libmpdemux/tvi_v4l.c	Sun Mar 30 12:05:58 2003
+++ test/libmpdemux/tvi_v4l.c	Mon Apr 28 15:49:29 2003
@@ -151,7 +151,7 @@
 static const char *device_palette2name[] = {
     "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15", "yuv422",
     "yuyv", "uyvy", "yuv420", "yuv411", "raw", "yuv422p", "yuv411p",
-    "yuv420p", "yuv410p"
+    "yuv420p", "yuv410p", "nv12", "nv21"
 };
 #define PALETTE(x) ((x < sizeof(device_palette2name)/sizeof(char*)) ? device_palette2name[x] : "UNKNOWN")
 
@@ -234,6 +234,8 @@
 	    return(VIDEO_PALETTE_RGB32);
 	case IMGFMT_YV12:
 	case IMGFMT_I420:
+	case IMGFMT_NV12:
+	case IMGFMT_NV21:
 	    return(VIDEO_PALETTE_YUV420P);
 	case IMGFMT_YUY2:
 	    return(VIDEO_PALETTE_YUV422);
diff -Nur main/m_option.c test/m_option.c
--- main/m_option.c	Sat Apr 12 08:45:43 2003
+++ test/m_option.c	Mon Apr 28 17:40:22 2003
@@ -926,6 +926,8 @@
   {"yuy2", IMGFMT_YUY2},
   {"yv12", IMGFMT_YV12},
   {"i420", IMGFMT_I420},
+  {"nv12", IMGFMT_NV12},
+  {"nv21", IMGFMT_NV21},
   {"yvu9", IMGFMT_YVU9},
   {"if09", IMGFMT_IF09},
   {"iyuv", IMGFMT_IYUV},
diff -Nur main/postproc/swscale.c test/postproc/swscale.c
--- main/postproc/swscale.c	Fri Apr 25 13:32:43 2003
+++ test/postproc/swscale.c	Tue Apr 29 00:03:41 2003
@@ -105,7 +105,7 @@
 
 //FIXME replace this with something faster
 #define isPlanarYUV(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_YVU9 \
-			|| (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P)
+			|| (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P || (x)==IMGFMT_NV12 || (x)==IMGFMT_NV21)
 #define isYUV(x)       ((x)==IMGFMT_UYVY || (x)==IMGFMT_YUY2 || isPlanarYUV(x))
 #define isGray(x)      ((x)==IMGFMT_Y800)
 #define isRGB(x)       (((x)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
@@ -114,7 +114,7 @@
 			|| (x)==IMGFMT_BGR32|| (x)==IMGFMT_BGR24|| (x)==IMGFMT_BGR16|| (x)==IMGFMT_BGR15\
 			|| (x)==IMGFMT_RGB32|| (x)==IMGFMT_RGB24\
 			|| (x)==IMGFMT_Y800 || (x)==IMGFMT_YVU9\
-			|| (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P)
+			|| (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P || (x)==IMGFMT_NV12 || (x)==IMGFMT_NV21)
 #define isSupportedOut(x) ((x)==IMGFMT_YV12 || (x)==IMGFMT_YUY2\
 			|| (x)==IMGFMT_444P || (x)==IMGFMT_422P || (x)==IMGFMT_411P\
 			|| isRGB(x) || isBGR(x)\
@@ -1315,6 +1315,50 @@
 #endif //!RUNTIME_CPUDETECT
 }
 
+static int NVxxToYV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dstParam[], int dstStride[]) {
+    uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
+    /* Copy Y plane */
+	if(dstStride[0]==srcStride[0])
+		memcpy(dst, src[0], srcSliceH*dstStride[0]);
+    else
+    {
+        int i;
+        uint8_t *srcPtr= src[0];
+        uint8_t *dstPtr= dst;
+        for(i=0; i<srcSliceH; i++)
+        {
+            memcpy(dstPtr, srcPtr, srcStride[0]);
+            srcPtr+= srcStride[0];
+            dstPtr+= dstStride[0];
+        }
+    }
+    // de-interleaveBytes ()
+    {
+        int i,w;
+        uint8_t *srcPtr=src[1];
+        uint8_t *vPtr=dstParam[1] + dstStride[1]*srcSliceY;
+        uint8_t *uPtr=dstParam[2] + dstStride[2]*srcSliceY;
+        if (c->srcFormat==IMGFMT_NV21) {
+            uint8_t *tmpPtr=vPtr;
+            vPtr=uPtr;
+            uPtr=tmpPtr;
+        }
+        for(i=0; i<srcSliceH / 2; i++)
+        {
+            for(w=0; w<c->srcW / 2; w++)
+            {
+                uPtr[w] = srcPtr[2*w+0];
+                vPtr[w] = srcPtr[2*w+1];
+            }
+            vPtr += dstStride[1];
+            uPtr += dstStride[2];
+            srcPtr += srcStride[1];
+        }
+    }
+
+    return srcSliceH;
+}
+
 static int PlanarToNV12Wrapper(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
              int srcSliceH, uint8_t* dstParam[], int dstStride[]){
 	uint8_t *dst=dstParam[0] + dstStride[0]*srcSliceY;
@@ -1795,9 +1839,21 @@
 
 	sws_setColorspaceDetails(c, Inverse_Table_6_9[SWS_CS_DEFAULT], 0, Inverse_Table_6_9[SWS_CS_DEFAULT] /* FIXME*/, 0, 0, 1<<16, 1<<16); 
 
+       //FIXME maybe not the best place for this kind of check
+	if((srcFormat==IMGFMT_NV12 || srcFormat==IMGFMT_NV21) && (!unscaled || usesFilter || dstFormat!=IMGFMT_YV12))
+	{
+		MSG_ERR("swScaler: only unscaled and unfiltered NV12/NV21 -> YV12 supported, %s and %s %s -> %s isn't supported yet\n", unscaled ? "unscaled" : "scaled", usesFilter ? "filtered" : "unfiltered", vo_format_name(srcFormat), vo_format_name(dstFormat));
+		free (c);
+		return NULL;
+	}
+
 	/* unscaled special Cases */
 	if(unscaled && !usesFilter)
 	{
+		if((srcFormat==IMGFMT_NV12 || srcFormat==IMGFMT_NV21) && dstFormat==IMGFMT_YV12)
+		{
+			c->swScale= NVxxToYV12Wrapper;
+		}
 		/* yv12_to_nv12 */
 		if(srcFormat == IMGFMT_YV12 && dstFormat == IMGFMT_NV12)
 		{


More information about the MPlayer-dev-eng mailing list