[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