[FFmpeg-devel] [PATCH v3] libswscale: Extend the unaccelerated path of the unscaled yuv2rgb special converter with support for rgb444 output format

Janusz Krzysztofik jkrzyszt
Thu Mar 4 12:46:03 CET 2010


In order to play video on a 12-bit display, like OMAP1 frambuffer with 12-bit 
LCD controller that my Amstrad Delta videophone is equipped with, one or more 
libswscale converters with rgb444 output pixel format support are required. 
This patch adds such support to the unaccelerated path of the unscaled yuv2rgb 
special converter.

Created and tested against ffmpeg svn revision 22185, on top of
	[PATCH v2] Add initial support for 12-bit color mode.

Tested on Amstrad Delta with 24bpp IJPG and MP43 sourcers using patched 
mplayer video output drivers.

Signed-off-by: Janusz Krzysztofik <jkrzyszt at tis.icnet.pl>

---
Changes since v2:
- drop redundant lines from dither table, rename it.
Changes since v1:
- do not add info on global rgb12 output format support yet,
- add support for dithering.

Michael,
Thanks again for your support.

Thanks,
Janusz


diff -upr trunk/doc/swscale.txt trunk.rgb12/doc/swscale.txt
--- trunk/doc/swscale.txt	2010-02-24 15:55:28.000000000 +0100
+++ trunk.rgb12/doc/swscale.txt	2010-02-25 04:31:55.000000000 +0100
@@ -30,7 +30,7 @@ slices, that is, consecutive non-overlap
 
 special converter
     These generally are unscaled converters of common
-    formats, like YUV 4:2:0/4:2:2 -> RGB15/16/24/32. Though it could also
+    formats, like YUV 4:2:0/4:2:2 -> RGB12/15/16/24/32. Though it could also
     in principle contain scalers optimized for specific common cases.
 
 Main path
diff -upr trunk.orig/libswscale/swscale.c trunk/libswscale/swscale.c
--- trunk.orig/libswscale/swscale.c	2010-02-26 02:40:46.000000000 +0100
+++ trunk/libswscale/swscale.c	2010-03-03 01:45:00.000000000 +0100
@@ -27,7 +27,7 @@
   {BGR,RGB}{1,4,8,15,16} support dithering
 
   unscaled special converters (YV12=I420=IYUV, Y800=Y8)
-  YV12 -> {BGR,RGB}{1,4,8,15,16,24,32}
+  YV12 -> {BGR,RGB}{1,4,8,12,15,16,24,32}
   x -> x
   YUV9 -> YV12
   YUV9/YV12 -> Y800
@@ -198,6 +198,13 @@ DECLARE_ALIGNED(8, static const uint8_t,
 {  0,   4,   0,   4,   0,   4,   0,   4, },
 };
 
+DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[4][8]={
+{  8,   4,  11,   7,   8,   4,  11,   7, },
+{  2,  14,   1,  13,   2,  14,   1,  13, },
+{ 10,   6,   9,   5,  10,   6,   9,   5, },
+{  0,  12,   3,  15,   0,  12,   3,  15, },
+};
+
 DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={
 { 17,   9,  23,  15,  16,   8,  22,  14, },
 {  5,  29,   3,  27,   4,  28,   2,  26, },
diff -upr trunk.orig/libswscale/swscale_internal.h trunk/libswscale/swscale_internal.h
--- trunk.orig/libswscale/swscale_internal.h	2010-02-26 02:40:46.000000000 +0100
+++ trunk/libswscale/swscale_internal.h	2010-03-03 01:45:54.000000000 +0100
@@ -393,6 +393,7 @@ const char *sws_format_name(enum PixelFo
         || (x)==PIX_FMT_RGB24       \
         || (x)==PIX_FMT_RGB565      \
         || (x)==PIX_FMT_RGB555      \
+        || (x)==PIX_FMT_RGB444      \
         || (x)==PIX_FMT_RGB8        \
         || (x)==PIX_FMT_RGB4        \
         || (x)==PIX_FMT_RGB4_BYTE   \
@@ -405,6 +406,7 @@ const char *sws_format_name(enum PixelFo
         || (x)==PIX_FMT_BGR24       \
         || (x)==PIX_FMT_BGR565      \
         || (x)==PIX_FMT_BGR555      \
+        || (x)==PIX_FMT_BGR444      \
         || (x)==PIX_FMT_BGR8        \
         || (x)==PIX_FMT_BGR4        \
         || (x)==PIX_FMT_BGR4_BYTE   \
diff -upr trunk.orig/libswscale/yuv2rgb.c trunk/libswscale/yuv2rgb.c
--- trunk.orig/libswscale/yuv2rgb.c	2010-02-26 02:40:46.000000000 +0100
+++ trunk/libswscale/yuv2rgb.c	2010-03-03 02:29:10.000000000 +0100
@@ -34,6 +34,7 @@
 #include "swscale_internal.h"
 #include "libavutil/x86_cpu.h"
 
+extern const uint8_t dither_4x4_16[4][8];
 extern const uint8_t dither_8x8_32[8][8];
 extern const uint8_t dither_8x8_73[8][8];
 extern const uint8_t dither_8x8_220[8][8];
@@ -351,6 +352,32 @@ CLOSEYUV2RGBFUNC(8)
 #endif
 
 // r, g, b, dst_1, dst_2
+YUV2RGBFUNC(yuv2rgb_c_12_ordered_dither, uint16_t, 0)
+    const uint8_t *d16 = dither_4x4_16[y&3];
+#define PUTRGB12(dst,src,i,o)                                   \
+    Y = src[2*i];                                               \
+    dst[2*i]   = r[Y+d16[0+o]] + g[Y+d16[0+o]] + b[Y+d16[0+o]]; \
+    Y = src[2*i+1];                                             \
+    dst[2*i+1] = r[Y+d16[1+o]] + g[Y+d16[1+o]] + b[Y+d16[1+o]];
+
+    LOADCHROMA(0);
+    PUTRGB12(dst_1,py_1,0,0);
+    PUTRGB12(dst_2,py_2,0,0+8);
+
+    LOADCHROMA(1);
+    PUTRGB12(dst_2,py_2,1,2+8);
+    PUTRGB12(dst_1,py_1,1,2);
+
+    LOADCHROMA(2);
+    PUTRGB12(dst_1,py_1,2,4);
+    PUTRGB12(dst_2,py_2,2,4+8);
+
+    LOADCHROMA(3);
+    PUTRGB12(dst_2,py_2,3,6+8);
+    PUTRGB12(dst_1,py_1,3,6);
+CLOSEYUV2RGBFUNC(8)
+
+// r, g, b, dst_1, dst_2
 YUV2RGBFUNC(yuv2rgb_c_8_ordered_dither, uint8_t, 0)
     const uint8_t *d32 = dither_8x8_32[y&7];
     const uint8_t *d64 = dither_8x8_73[y&7];
@@ -552,6 +579,8 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsConte
     case PIX_FMT_BGR565:
     case PIX_FMT_RGB555:
     case PIX_FMT_BGR555:     return yuv2rgb_c_16;
+    case PIX_FMT_RGB444:
+    case PIX_FMT_BGR444:     return yuv2rgb_c_12_ordered_dither;
     case PIX_FMT_RGB8:
     case PIX_FMT_BGR8:       return yuv2rgb_c_8_ordered_dither;
     case PIX_FMT_RGB4:
@@ -598,6 +627,7 @@ av_cold int ff_yuv2rgb_c_init_tables(Sws
                         || c->dstFormat==PIX_FMT_BGR24
                         || c->dstFormat==PIX_FMT_RGB565
                         || c->dstFormat==PIX_FMT_RGB555
+                        || c->dstFormat==PIX_FMT_RGB444
                         || c->dstFormat==PIX_FMT_RGB8
                         || c->dstFormat==PIX_FMT_RGB4
                         || c->dstFormat==PIX_FMT_RGB4_BYTE
@@ -694,6 +724,25 @@ av_cold int ff_yuv2rgb_c_init_tables(Sws
         fill_table(c->table_bU, 1, cbu, y_table + yoffs + 2048);
         fill_gv_table(c->table_gV, 1, cgv);
         break;
+    case 12:
+        rbase = isRgb ? 8 : 0;
+        gbase = 4;
+        bbase = isRgb ? 0 : 8;
+        c->yuvTable = av_malloc(1024*3*2);
+        y_table16 = c->yuvTable;
+        yb = -(384<<16) - oy;
+        for (i = 0; i < 1024; i++) {
+            uint8_t yval = av_clip_uint8((yb + 0x8000) >> 16);
+            y_table16[i     ] = (yval >> 4)          << rbase;
+            y_table16[i+1024] = (yval >> 4) << gbase;
+            y_table16[i+2048] = (yval >> 4)          << bbase;
+            yb += cy;
+        }
+        fill_table(c->table_rV, 2, crv, y_table16 + yoffs);
+        fill_table(c->table_gU, 2, cgu, y_table16 + yoffs + 1024);
+        fill_table(c->table_bU, 2, cbu, y_table16 + yoffs + 2048);
+        fill_gv_table(c->table_gV, 2, cgv);
+        break;
     case 15:
     case 16:
         rbase = isRgb ? bpp - 5 : 0;



More information about the ffmpeg-devel mailing list