[Ffmpeg-devel] [PATCH, RFC] 16-bit grayscale depth support suite

Kostya kostya.shishkov
Mon Oct 23 09:10:17 CEST 2006


On Sun, Oct 22, 2006 at 11:17:51PM +0200, Michael Niedermayer wrote:
> Hi
> 
> On Sun, Oct 22, 2006 at 08:06:34PM +0300, Kostya wrote:
> [...]
> > Here is corrected patch for imgconvert and SWS implementation. While conversion
> > is working fine when specified (gray16 -> gray, gray16 -> yuv),
> > gray16 -> rgb24 works strange. Can somebody give any hints on this?
> 
> hmm, look at hyscale() did you implement gray16* -> gray8 there?

Thanks, now it is done.

> also optional/alternative if you write a gray16 hScale() (only the small
> c loop at the end matters) then the swscaler should with some luck (maybe
> some if(mmx) will need to be changed to if(mmx && !gray16)) be able to
> actually use 15 of the 16 bits of gray16* in the horizontal scaling
> and the vertical too if SWS_ACCURATE_RND is set or the c scaler is
> used
 
Maybe in future when other >8bit depths will be supported. I understand
that if both source and destination are 16-bit then any processing will
drop precision to 8-bit but it's too much work (and I'm lazy too).
 
> [...]
> > +static void gray16be_to_gray(AVPicture *dst, const AVPicture *src,
> > +                              int width, int height)
> > +{
> > +    int x, y, src_wrap, dst_wrap;
> > +    uint8_t *s, *d;
> > +    s = src->data[0];
> > +    src_wrap = src->linesize[0] - width * 2;
> > +    d = dst->data[0];
> > +    dst_wrap = dst->linesize[0] - width;
> > +    for(y=0; y<height; y++){
> > +        for(x=0; x<width; x++){
> > +            *d++ = *s++;
> > +            s++;
> > +        }
> > +        s += src_wrap;
> > +        d += dst_wrap;
> > +    }
> > +}
> > +
> > +static void gray16le_to_gray(AVPicture *dst, const AVPicture *src,
> > +                              int width, int height)
> > +{
> > +    int x, y, src_wrap, dst_wrap;
> > +    uint8_t *s, *d;
> > +    s = src->data[0];
> > +    src_wrap = src->linesize[0] - width * 2;
> > +    d = dst->data[0];
> > +    dst_wrap = dst->linesize[0] - width;
> > +    for(y=0; y<height; y++){
> > +        for(x=0; x<width; x++){
> > +            s++;
> > +            *d++ = *s++;
> > +        }
> > +        s += src_wrap;
> > +        d += dst_wrap;
> > +    }
> > +}
> 
> isnt that the same as gray16be_to_gray except a s++ before both loops?

Right, reduced to one func in both patches.

[...]
> 
> same simplification possible as in imgconvert (check be/le and srcPtr++)
> and maybe yuy2ToY()/uyvyToY() could be used, they are mmx optimized ...
 
I used them in hyscale()

> 
> [...]
> 
> -- 
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> 
> In the past you could go to a library and read, borrow or copy any book
> Today you'd get arrested for mere telling someone where the library is
> 
-------------- next part --------------
Index: libavutil/avutil.h
===================================================================
--- libavutil/avutil.h	(revision 6734)
+++ libavutil/avutil.h	(working copy)
@@ -105,6 +105,8 @@
     PIX_FMT_RGB32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
     PIX_FMT_BGR32_1,   ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
 
+    PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
+    PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
     PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
 };
 
@@ -113,11 +115,13 @@
 #define PIX_FMT_BGRA PIX_FMT_BGR32_1
 #define PIX_FMT_ARGB PIX_FMT_RGB32
 #define PIX_FMT_ABGR PIX_FMT_BGR32
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16BE
 #else
 #define PIX_FMT_RGBA PIX_FMT_BGR32
 #define PIX_FMT_BGRA PIX_FMT_RGB32
 #define PIX_FMT_ARGB PIX_FMT_BGR32_1
 #define PIX_FMT_ABGR PIX_FMT_RGB32_1
+#define PIX_FMT_GRAY16 PIX_FMT_GRAY16LE
 #endif
 
 #if LIBAVUTIL_VERSION_INT < (50<<16)
Index: libavcodec/utils.c
===================================================================
--- libavcodec/utils.c	(revision 6734)
+++ libavcodec/utils.c	(working copy)
@@ -177,6 +177,8 @@
     case PIX_FMT_YUV422P:
     case PIX_FMT_YUV444P:
     case PIX_FMT_GRAY8:
+    case PIX_FMT_GRAY16BE:
+    case PIX_FMT_GRAY16LE:
     case PIX_FMT_YUVJ420P:
     case PIX_FMT_YUVJ422P:
     case PIX_FMT_YUVJ444P:
Index: libavcodec/imgconvert.c
===================================================================
--- libavcodec/imgconvert.c	(revision 6734)
+++ libavcodec/imgconvert.c	(working copy)
@@ -193,6 +193,20 @@
     },
 
     /* gray / mono formats */
+    [PIX_FMT_GRAY16BE] = {
+        .name = "gray16be",
+        .nb_channels = 1,
+        .color_type = FF_COLOR_GRAY,
+        .pixel_type = FF_PIXEL_PLANAR,
+        .depth = 16,
+    },
+    [PIX_FMT_GRAY16LE] = {
+        .name = "gray16le",
+        .nb_channels = 1,
+        .color_type = FF_COLOR_GRAY,
+        .pixel_type = FF_PIXEL_PLANAR,
+        .depth = 16,
+    },
     [PIX_FMT_GRAY8] = {
         .name = "gray",
         .nb_channels = 1,
@@ -427,6 +441,8 @@
         picture->data[2] = NULL;
         picture->linesize[0] = width * 4;
         return size * 4;
+    case PIX_FMT_GRAY16BE:
+    case PIX_FMT_GRAY16LE:
     case PIX_FMT_BGR555:
     case PIX_FMT_BGR565:
     case PIX_FMT_RGB555:
@@ -1842,6 +1858,75 @@
     gray_to_mono(dst, src, width, height, 0x00);
 }
 
+static void gray_to_gray16(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    int x, y, src_wrap, dst_wrap;
+    uint8_t *s, *d;
+    s = src->data[0];
+    src_wrap = src->linesize[0] - width;
+    d = dst->data[0];
+    dst_wrap = dst->linesize[0] - width * 2;
+    for(y=0; y<height; y++){
+        for(x=0; x<width; x++){
+            *d++ = *s;
+            *d++ = *s++;
+        }
+        s += src_wrap;
+        d += dst_wrap;
+    }
+}
+
+static void gray16_to_gray(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    int x, y, src_wrap, dst_wrap;
+    uint8_t *s, *d;
+    s = src->data[0];
+    src_wrap = src->linesize[0] - width * 2;
+    d = dst->data[0];
+    dst_wrap = dst->linesize[0] - width;
+    for(y=0; y<height; y++){
+        for(x=0; x<width; x++){
+            *d++ = *s;
+            s += 2;
+        }
+        s += src_wrap;
+        d += dst_wrap;
+    }
+}
+
+static void gray16be_to_gray(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    gray16_to_gray(dst, src, width, height);
+}
+
+static void gray16le_to_gray(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    gray16_to_gray(dst, src + 1, width, height);
+}
+
+static void gray16_to_gray16(AVPicture *dst, const AVPicture *src,
+                              int width, int height)
+{
+    int x, y, src_wrap, dst_wrap;
+    uint16_t *s, *d;
+    s = src->data[0];
+    src_wrap = (src->linesize[0] - width * 2)/2;
+    d = dst->data[0];
+    dst_wrap = (dst->linesize[0] - width * 2)/2;
+    for(y=0; y<height; y++){
+        for(x=0; x<width; x++){
+            *d++ = bswap_16(*s++);
+        }
+        s += src_wrap;
+        d += dst_wrap;
+    }
+}
+
+
 typedef struct ConvertEntry {
     void (*convert)(AVPicture *dst,
                     const AVPicture *src, int width, int height);
@@ -2024,6 +2109,22 @@
             .convert = rgb565_to_gray
         },
     },
+    [PIX_FMT_GRAY16BE] = {
+        [PIX_FMT_GRAY8] = {
+            .convert = gray16be_to_gray
+        },
+        [PIX_FMT_GRAY16LE] = {
+            .convert = gray16_to_gray16
+        },
+    },
+    [PIX_FMT_GRAY16LE] = {
+        [PIX_FMT_GRAY8] = {
+            .convert = gray16le_to_gray
+        },
+        [PIX_FMT_GRAY16BE] = {
+            .convert = gray16_to_gray16
+        },
+    },
     [PIX_FMT_GRAY8] = {
         [PIX_FMT_RGB555] = {
             .convert = gray_to_rgb555
@@ -2046,6 +2147,12 @@
         [PIX_FMT_MONOBLACK] = {
             .convert = gray_to_monoblack
         },
+        [PIX_FMT_GRAY16LE] = {
+            .convert = gray_to_gray16
+        },
+        [PIX_FMT_GRAY16BE] = {
+            .convert = gray_to_gray16
+        },
     },
     [PIX_FMT_MONOWHITE] = {
         [PIX_FMT_GRAY8] = {
-------------- next part --------------
Index: swscale.c
===================================================================
--- swscale.c	(revision 20305)
+++ swscale.c	(working copy)
@@ -111,11 +111,13 @@
 			|| (x)==PIX_FMT_RGB32|| (x)==PIX_FMT_BGR24|| (x)==PIX_FMT_BGR565|| (x)==PIX_FMT_BGR555\
 			|| (x)==PIX_FMT_BGR32|| (x)==PIX_FMT_RGB24\
 			|| (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P\
+			|| (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\
 			|| (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P)
 #define isSupportedOut(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422\
 			|| (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P\
 			|| isRGB(x) || isBGR(x)\
 			|| (x)==PIX_FMT_NV12 || (x)==PIX_FMT_NV21\
+			|| (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE\
 			|| (x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_YUV410P)
 #define isPacked(x)    ((x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422 ||isRGB(x) || isBGR(x))
 
@@ -231,6 +233,10 @@
             return "rgb565";
         case PIX_FMT_RGB555:
             return "rgb555";
+        case PIX_FMT_GRAY16BE:
+            return "gray16be";
+        case PIX_FMT_GRAY16LE:
+            return "gray16le";
         case PIX_FMT_GRAY8:
             return "gray8";
         case PIX_FMT_MONOWHITE:
@@ -1726,6 +1732,72 @@
 	return srcSliceH;
 }
 
+static int gray16togray(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+             int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+	int length= c->srcW;
+	int y=      srcSliceY;
+	int height= srcSliceH;
+	int i, j;
+	uint8_t *srcPtr= src[0];
+	uint8_t *dstPtr= dst[0] + dstStride[0]*y;
+
+	if(!isGray(c->dstFormat)){
+		int height= -((-srcSliceH)>>c->chrDstVSubSample);
+		memset(dst[1], 128, dstStride[1]*height);
+		memset(dst[2], 128, dstStride[2]*height);
+	}
+	if(c->srcFormat == PIX_FMT_GRAY16LE) srcPtr++;
+	for(i=0; i<height; i++)
+	{
+		for(j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
+		srcPtr+= srcStride[0];
+		dstPtr+= dstStride[0];
+	}
+	return srcSliceH;
+}
+
+static int graytogray16(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+             int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+	int length= c->srcW;
+	int y=      srcSliceY;
+	int height= srcSliceH;
+	int i, j;
+	uint8_t *srcPtr= src[0];
+	uint8_t *dstPtr= dst[0] + dstStride[0]*y;
+	for(i=0; i<height; i++)
+	{
+		for(j=0; j<length; j++)
+		{
+			dstPtr[j<<1] = srcPtr[j];
+			dstPtr[(j<<1)+1] = srcPtr[j];
+		}
+		srcPtr+= srcStride[0];
+		dstPtr+= dstStride[0];
+	}
+	return srcSliceH;
+}
+
+static int gray16swap(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,
+             int srcSliceH, uint8_t* dst[], int dstStride[]){
+
+	int length= c->srcW;
+	int y=      srcSliceY;
+	int height= srcSliceH;
+	int i, j;
+	uint16_t *srcPtr= src[0];
+	uint16_t *dstPtr= dst[0] + dstStride[0]*y/2;
+	for(i=0; i<height; i++)
+	{
+		for(j=0; j<length; j++) dstPtr[j] = bswap_16(srcPtr[j]);
+		srcPtr+= srcStride[0]/2;
+		dstPtr+= dstStride[0]/2;
+	}
+	return srcSliceH;
+}
+
+
 static void getSubSampleFactors(int *h, int *v, int format){
 	switch(format){
 	case PIX_FMT_UYVY422:
@@ -1734,6 +1806,8 @@
 		*v=0;
 		break;
 	case PIX_FMT_YUV420P:
+	case PIX_FMT_GRAY16BE:
+	case PIX_FMT_GRAY16LE:
 	case PIX_FMT_GRAY8: //FIXME remove after different subsamplings are fully implemented
 	case PIX_FMT_NV12:
 	case PIX_FMT_NV21:
@@ -2045,6 +2119,20 @@
 			c->swScale= simpleCopy;
 		}
 
+		/* gray16{le,be} conversions */
+		if(isGray16(srcFormat) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8)))
+		{
+			c->swScale= gray16togray;
+		}
+		if((isPlanarYUV(srcFormat) || (srcFormat == PIX_FMT_GRAY8)) && isGray16(dstFormat))
+		{
+			c->swScale= graytogray16;
+		}
+		if(srcFormat != dstFormat && isGray16(srcFormat) && isGray16(dstFormat))
+		{
+			c->swScale= gray16swap;
+		}		
+
 		if(c->swScale){
 			if(flags&SWS_PRINT_INFO)
 				MSG_INFO("SwScaler: using unscaled %s -> %s special converter\n", 
Index: swscale_internal.h
===================================================================
--- swscale_internal.h	(revision 20305)
+++ swscale_internal.h	(working copy)
@@ -181,7 +181,8 @@
 			|| (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_NV12	\
 			|| (x)==PIX_FMT_NV21)
 #define isYUV(x)       ((x)==PIX_FMT_UYVY422 || (x)==PIX_FMT_YUYV422 || isPlanarYUV(x))
-#define isGray(x)      ((x)==PIX_FMT_GRAY8)
+#define isGray(x)      ((x)==PIX_FMT_GRAY8 || (x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE)
+#define isGray16(x)    ((x)==PIX_FMT_GRAY16BE || (x)==PIX_FMT_GRAY16LE)
 #define isRGB(x)       ((x)==PIX_FMT_BGR32 || (x)==PIX_FMT_RGB24	\
 			|| (x)==PIX_FMT_RGB565 || (x)==PIX_FMT_RGB555	\
 			|| (x)==PIX_FMT_RGB8 || (x)==PIX_FMT_RGB4	\
@@ -204,6 +205,8 @@
             return 24;
         case PIX_FMT_BGR565:
         case PIX_FMT_RGB565:
+        case PIX_FMT_GRAY16BE:
+        case PIX_FMT_GRAY16LE:
             return 16;
         case PIX_FMT_BGR555:
         case PIX_FMT_RGB555:
Index: swscale_template.c
===================================================================
--- swscale_template.c	(revision 20305)
+++ swscale_template.c	(working copy)
@@ -2437,12 +2437,12 @@
 				   int srcFormat, uint8_t *formatConvBuffer, int16_t *mmx2Filter,
 				   int32_t *mmx2FilterPos)
 {
-    if(srcFormat==PIX_FMT_YUYV422)
+    if(srcFormat==PIX_FMT_YUYV422 || srcFormat==PIX_FMT_GRAY16BE)
     {
 	RENAME(yuy2ToY)(formatConvBuffer, src, srcW);
 	src= formatConvBuffer;
     }
-    else if(srcFormat==PIX_FMT_UYVY422)
+    else if(srcFormat==PIX_FMT_UYVY422 || srcFormat==PIX_FMT_GRAY16LE)
     {
 	RENAME(uyvyToY)(formatConvBuffer, src, srcW);
 	src= formatConvBuffer;



More information about the ffmpeg-devel mailing list