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

Kostya kostya.shishkov
Sun Oct 22 19:06:34 CEST 2006


On Sun, Oct 22, 2006 at 04:06:22PM +0200, Michael Niedermayer wrote:
> Hi
> 
> now the actual review of the change 
> 
> On Sat, Oct 21, 2006 at 03:39:47PM +0300, Kostya wrote:
> > Here is support for grayscale 16-bit and some trivial patches
> > for 16-bit support in some formats. Comments, suggestions and
> > SWScale support is welcomed ;)
> 
> > 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
> 
> the ',' isnt aligned

Corrected
> 
> [...]
> > +static void gray_to_gray16le(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++ = 0;
> > +            *d++ = *s++;
> 
> this can be wrong depending on how the digital value -> brightness is defined
> if 0,0 = black; 255,65535=white then
>     int t= *s++;
>     *d++= t;
>     *d++= t;
> is correcter
> 
> the difference is that white (255 = 100%) becomes (65280 =99.6%) in your
> version, this is also more noticeable with fewer bits 
> (240 vs. 255 with 4->8bit and 128 vs 255 for 1->8bit)
> 
> as a sideeffect the output endianness wouldnt matter anymore

Quite right, and I forgot I saw this at aggregate.org :(. Fixed.
 
[some theoretical cases skipped]

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?
 
> 
> -- 
> 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,82 @@
     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 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;
+    }
+}
+
+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 +2116,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 +2154,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,94 @@
 	return srcSliceH;
 }
 
+static int gray16betogray(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);
+	}
+	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 gray16letogray(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);
+	}
+	for(i=0; i<height; i++)
+	{
+		for(j=0; j<length; j++) dstPtr[j] = srcPtr[(j<<1) + 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 +1828,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 +2141,24 @@
 			c->swScale= simpleCopy;
 		}
 
+		/* gray16{le,be} conversions */
+		if((srcFormat == PIX_FMT_GRAY16BE) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8)))
+		{
+			c->swScale= gray16betogray;
+		}
+		if((srcFormat == PIX_FMT_GRAY16LE) && (isPlanarYUV(dstFormat) || (dstFormat == PIX_FMT_GRAY8)))
+		{
+			c->swScale= gray16letogray;
+		}
+		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:



More information about the ffmpeg-devel mailing list