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

Angelo Cano angelo_cano at fastmail.fm
Fri Apr 18 18:36:46 CEST 2003


I have a tv card that outputs yuv420p using NV12 format, this patch
enables NV12/NV21 -> YV12 conversion.

-------------- next part --------------
diff -Nur main/DOCS/de/mplayer.1 work/DOCS/de/mplayer.1
--- main/DOCS/de/mplayer.1	Sat Mar 22 07:01:47 2003
+++ work/DOCS/de/mplayer.1	Fri Apr 18 11:02:10 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 work/DOCS/en/mplayer.1
--- main/DOCS/en/mplayer.1	Fri Apr 11 05:27:31 2003
+++ work/DOCS/en/mplayer.1	Fri Apr 18 11:02:10 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/fr/mplayer.1 work/DOCS/fr/mplayer.1
--- main/DOCS/fr/mplayer.1	Fri Apr 11 12:15:15 2003
+++ work/DOCS/fr/mplayer.1	Fri Apr 18 11:02:10 2003
@@ -751,7 +751,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 work/DOCS/hu/mplayer.1
--- main/DOCS/hu/mplayer.1	Mon Mar 31 11:48:54 2003
+++ work/DOCS/hu/mplayer.1	Fri Apr 18 11:02:10 2003
@@ -718,7 +718,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 work/DOCS/pl/mplayer.1
--- main/DOCS/pl/mplayer.1	Sun Mar 30 11:09:25 2003
+++ work/DOCS/pl/mplayer.1	Fri Apr 18 11:02:10 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 work/DOCS/zh/mplayer.1
--- main/DOCS/zh/mplayer.1	Sun Apr  6 08:27:10 2003
+++ work/DOCS/zh/mplayer.1	Fri Apr 18 11:02:10 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 work/codec-cfg.c
--- main/codec-cfg.c	Sun Dec 15 21:22:37 2002
+++ work/codec-cfg.c	Fri Apr 18 11:02:10 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 work/etc/codecs.conf
--- main/etc/codecs.conf	Tue Apr 15 15:40:11 2003
+++ work/etc/codecs.conf	Fri Apr 18 11:04:06 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 work/libmpcodecs/img_format.c
--- main/libmpcodecs/img_format.c	Thu Jan 30 04:14:58 2003
+++ work/libmpcodecs/img_format.c	Fri Apr 18 11:02:10 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 work/libmpcodecs/img_format.h
--- main/libmpcodecs/img_format.h	Thu Jan 30 04:14:58 2003
+++ work/libmpcodecs/img_format.h	Fri Apr 18 11:02:10 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 work/libmpcodecs/mp_image.h
--- main/libmpcodecs/mp_image.h	Fri Apr 18 08:18:59 2003
+++ work/libmpcodecs/mp_image.h	Fri Apr 18 11:06:04 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>>1);
+    mpi->chroma_height=(mpi->height>>1);
+    mpi->chroma_x_shift=1;
+    mpi->chroma_y_shift=1;
+    return;
     case IMGFMT_I420:
     case IMGFMT_IYUV:
 	mpi->flags|=MP_IMGFLAG_SWAPPED;
diff -Nur main/libmpcodecs/vf_eq.c work/libmpcodecs/vf_eq.c
--- main/libmpcodecs/vf_eq.c	Sat Mar 15 15:45:03 2003
+++ work/libmpcodecs/vf_eq.c	Fri Apr 18 11:02:10 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 work/libmpcodecs/vf_scale.c
--- main/libmpcodecs/vf_scale.c	Thu Mar 27 11:04:51 2003
+++ work/libmpcodecs/vf_scale.c	Fri Apr 18 11:02:10 2003
@@ -63,6 +63,8 @@
     IMGFMT_YV12,
     IMGFMT_I420,
     IMGFMT_IYUV,
+    IMGFMT_NV12,
+    IMGFMT_NV21,
     IMGFMT_YVU9,
     IMGFMT_IF09,
     IMGFMT_411P,
@@ -315,13 +317,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 work/libmpdemux/tv.c
--- main/libmpdemux/tv.c	Wed Apr  9 11:07:45 2003
+++ work/libmpdemux/tv.c	Fri Apr 18 11:02:10 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 work/libmpdemux/tvi_v4l.c
--- main/libmpdemux/tvi_v4l.c	Sun Mar 30 12:05:58 2003
+++ work/libmpdemux/tvi_v4l.c	Fri Apr 18 11:02:10 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/libvo/vo_x11.c work/libvo/vo_x11.c
--- main/libvo/vo_x11.c	Thu Mar 27 11:04:30 2003
+++ work/libvo/vo_x11.c	Fri Apr 18 11:02:10 2003
@@ -586,6 +586,8 @@
 //   case IMGFMT_BGR32:
 //    return 0x2;
 //   case IMGFMT_YUY2: 
+   case IMGFMT_NV12:
+   case IMGFMT_NV21:
    case IMGFMT_I420:
    case IMGFMT_IYUV:
    case IMGFMT_YV12:
diff -Nur main/postproc/swscale.c work/postproc/swscale.c
--- main/postproc/swscale.c	Thu Apr 17 14:32:46 2003
+++ work/postproc/swscale.c	Fri Apr 18 11:21:17 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)\
@@ -1474,6 +1474,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 *uPtr=dstParam[1] + dstStride[1]*srcSliceY;
+        uint8_t *vPtr=dstParam[2] + dstStride[1]*srcSliceY;
+        for(i=0; i<srcSliceH; i++)
+        {
+            for(w=0; w<c->srcW / 2; w++)
+            {
+                uPtr[w] = srcPtr[2*w+0];
+                vPtr[w] = srcPtr[2*w+1];
+            }
+            uPtr += dstStride[1] / 2;
+            vPtr += dstStride[2] / 2;
+            srcPtr += srcStride[1];
+        }
+    }
+    if (c->srcFormat==IMGFMT_NV12) {
+        uint8_t *tmpPtr=dstParam[1];
+        dstParam[1]=dstParam[2];
+        dstParam[2]=tmpPtr;
+    }
+
+    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;
@@ -1942,9 +1986,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