[gst-devel] Patch for RGB/BGR 15/16 bit support

Martin Bisson martin.bisson at gmail.com
Tue Jun 1 23:28:39 CEST 2010


Hi,

Here is a small patch that adds RGB (and BGR) 15 and 16 bit video format to
GstVideoFormat and adds the necessary supporting code in
gst-plugins-base/gst-libs/gst/video/video.{c,h}.

It's the first time I "submit" a patch.  What I actually want more is
feedback on it, because aside from the little tests I did with my own little
use cases, I have a hard time evaluating the impact of this patch on the
whole project.  So I would be interested in your feedback and/or way to test
it more and/or any suggestions and/or advice on how to properly publish this
patch in gstreamer.

Thank you,

Martin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20100601/010e5d5b/attachment.htm>
-------------- next part --------------
From 699a7d33c157d49a789d1cd2bd7e6f55c142373e Mon Sep 17 00:00:00 2001
From: Martin Bisson <martin.bisson at gmail.com>
Date: Tue, 1 Jun 2010 14:42:54 +0000
Subject: [PATCH 1/2] video.{c,h}: Add support for RGB and BGR with 15 and 16 bits.

---
 gst-libs/gst/video/video.c |  137 ++++++++++++++++++++++++++++++++++++++++----
 gst-libs/gst/video/video.h |   92 ++++++++++++++++++------------
 2 files changed, 181 insertions(+), 48 deletions(-)

diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c
index e5c2c82..a456336 100644
--- a/gst-libs/gst/video/video.c
+++ b/gst-libs/gst/video/video.c
@@ -43,6 +43,8 @@ static GstVideoFormat gst_video_format_from_rgba32_masks (int red_mask,
     int green_mask, int blue_mask, int alpha_mask);
 static GstVideoFormat gst_video_format_from_rgb24_masks (int red_mask,
     int green_mask, int blue_mask);
+static GstVideoFormat gst_video_format_from_rgb16_masks (int red_mask,
+    int green_mask, int blue_mask);
 
 
 /**
@@ -381,6 +383,13 @@ gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
           ok = FALSE;
         }
+      } else if ((depth == 15 || depth == 16) && bpp == 16 &&
+          endianness == G_BIG_ENDIAN) {
+        *format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
+            blue_mask);
+        if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
+          ok = FALSE;
+        }
       } else {
         ok = FALSE;
       }
@@ -584,23 +593,65 @@ gst_video_format_new_caps (GstVideoFormat format, int width, int height,
         depth = 24;
         have_alpha = FALSE;
         break;
+      case GST_VIDEO_FORMAT_RGB16:
+      case GST_VIDEO_FORMAT_BGR16:
+        bpp = 16;
+        depth = 16;
+        have_alpha = FALSE;
+        break;
+      case GST_VIDEO_FORMAT_RGB15:
+      case GST_VIDEO_FORMAT_BGR15:
+        bpp = 16;
+        depth = 15;
+        have_alpha = FALSE;
+        break;
       default:
         return NULL;
     }
-    if (bpp == 32) {
-      mask = 0xff000000;
+    if (bpp == 32 || bpp == 24) {
+      if (bpp == 32) {
+        mask = 0xff000000;
+      } else {
+        mask = 0xff0000;
+      }
+      red_mask =
+          mask >> (8 * gst_video_format_get_component_offset (format, 0, width,
+              height));
+      green_mask =
+          mask >> (8 * gst_video_format_get_component_offset (format, 1, width,
+              height));
+      blue_mask =
+          mask >> (8 * gst_video_format_get_component_offset (format, 2, width,
+              height));
+    } else if (bpp == 16) {
+      switch (format) {
+        case GST_VIDEO_FORMAT_RGB16:
+          red_mask = GST_VIDEO_COMP1_MASK_16_INT;
+          green_mask = GST_VIDEO_COMP2_MASK_16_INT;
+          blue_mask = GST_VIDEO_COMP3_MASK_16_INT;
+          break;
+        case GST_VIDEO_FORMAT_BGR16:
+          red_mask = GST_VIDEO_COMP3_MASK_16_INT;
+          green_mask = GST_VIDEO_COMP2_MASK_16_INT;
+          blue_mask = GST_VIDEO_COMP1_MASK_16_INT;
+          break;
+          break;
+        case GST_VIDEO_FORMAT_RGB15:
+          red_mask = GST_VIDEO_COMP1_MASK_15_INT;
+          green_mask = GST_VIDEO_COMP2_MASK_15_INT;
+          blue_mask = GST_VIDEO_COMP3_MASK_15_INT;
+          break;
+        case GST_VIDEO_FORMAT_BGR15:
+          red_mask = GST_VIDEO_COMP3_MASK_15_INT;
+          green_mask = GST_VIDEO_COMP2_MASK_15_INT;
+          blue_mask = GST_VIDEO_COMP1_MASK_15_INT;
+          break;
+        default:
+          return NULL;
+      }
     } else {
-      mask = 0xff0000;
+      return NULL;
     }
-    red_mask =
-        mask >> (8 * gst_video_format_get_component_offset (format, 0, width,
-            height));
-    green_mask =
-        mask >> (8 * gst_video_format_get_component_offset (format, 1, width,
-            height));
-    blue_mask =
-        mask >> (8 * gst_video_format_get_component_offset (format, 2, width,
-            height));
 
     caps = gst_caps_new_simple ("video/x-raw-rgb",
         "bpp", G_TYPE_INT, bpp,
@@ -844,6 +895,33 @@ gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask)
   return GST_VIDEO_FORMAT_UNKNOWN;
 }
 
+static GstVideoFormat
+gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask)
+{
+  if (red_mask == GST_VIDEO_COMP1_MASK_16_INT
+      && green_mask == GST_VIDEO_COMP2_MASK_16_INT
+      && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) {
+    return GST_VIDEO_FORMAT_RGB16;
+  }
+  if (red_mask == GST_VIDEO_COMP3_MASK_16_INT
+      && green_mask == GST_VIDEO_COMP2_MASK_16_INT
+      && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) {
+    return GST_VIDEO_FORMAT_BGR16;
+  }
+  if (red_mask == GST_VIDEO_COMP1_MASK_15_INT
+      && green_mask == GST_VIDEO_COMP2_MASK_15_INT
+      && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) {
+    return GST_VIDEO_FORMAT_RGB15;
+  }
+  if (red_mask == GST_VIDEO_COMP3_MASK_15_INT
+      && green_mask == GST_VIDEO_COMP2_MASK_15_INT
+      && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) {
+    return GST_VIDEO_FORMAT_BGR15;
+  }
+
+  return GST_VIDEO_FORMAT_UNKNOWN;
+}
+
 /**
  * gst_video_format_is_rgb:
  * @format: a #GstVideoFormat
@@ -883,6 +961,10 @@ gst_video_format_is_rgb (GstVideoFormat format)
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
       return TRUE;
     default:
       return FALSE;
@@ -928,6 +1010,10 @@ gst_video_format_is_yuv (GstVideoFormat format)
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
       return FALSE;
     default:
       return FALSE;
@@ -998,6 +1084,10 @@ gst_video_format_has_alpha (GstVideoFormat format)
     case GST_VIDEO_FORMAT_xBGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
       return FALSE;
     default:
       return FALSE;
@@ -1052,6 +1142,11 @@ gst_video_format_get_row_stride (GstVideoFormat format, int component,
     case GST_VIDEO_FORMAT_ARGB:
     case GST_VIDEO_FORMAT_ABGR:
       return width * 4;
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
+      return GST_ROUND_UP_4 (width * 2);
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
     case GST_VIDEO_FORMAT_v308:
@@ -1132,6 +1227,11 @@ gst_video_format_get_pixel_stride (GstVideoFormat format, int component)
     case GST_VIDEO_FORMAT_ARGB:
     case GST_VIDEO_FORMAT_ABGR:
       return 4;
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
+      return 2;
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
     case GST_VIDEO_FORMAT_v308:
@@ -1215,6 +1315,10 @@ gst_video_format_get_component_width (GstVideoFormat format, int component,
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
     case GST_VIDEO_FORMAT_Y444:
     case GST_VIDEO_FORMAT_v308:
     case GST_VIDEO_FORMAT_NV12:
@@ -1276,6 +1380,10 @@ gst_video_format_get_component_height (GstVideoFormat format, int component,
     case GST_VIDEO_FORMAT_ABGR:
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
     case GST_VIDEO_FORMAT_Y444:
     case GST_VIDEO_FORMAT_v210:
     case GST_VIDEO_FORMAT_v216:
@@ -1528,6 +1636,11 @@ gst_video_format_get_size (GstVideoFormat format, int width, int height)
     case GST_VIDEO_FORMAT_ARGB:
     case GST_VIDEO_FORMAT_ABGR:
       return width * 4 * height;
+    case GST_VIDEO_FORMAT_RGB16:
+    case GST_VIDEO_FORMAT_BGR16:
+    case GST_VIDEO_FORMAT_RGB15:
+    case GST_VIDEO_FORMAT_BGR15:
+      return GST_ROUND_UP_4 (width * 2) * height;
     case GST_VIDEO_FORMAT_RGB:
     case GST_VIDEO_FORMAT_BGR:
     case GST_VIDEO_FORMAT_v308:
diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h
index ebf20b9..a3ec55d 100644
--- a/gst-libs/gst/video/video.h
+++ b/gst-libs/gst/video/video.h
@@ -57,6 +57,10 @@ G_BEGIN_DECLS
  * @GST_VIDEO_FORMAT_GRAY16_BE: 16-bit grayscale, most significant byte first (Since: 0.10.29)
  * @GST_VIDEO_FORMAT_GRAY16_LE: 16-bit grayscale, least significant byte first (Since: 0.10.29)
  * @GST_VIDEO_FORMAT_v308: packed 4:4:4 YUV (Since: 0.10.29)
+ * @GST_VIDEO_FORMAT_RGB16: rgb 5-6-5 bits per component (Since: 0.10.29)
+ * @GST_VIDEO_FORMAT_BGR16: reverse rgb 5-6-5 bits per component (Since: 0.10.29)
+ * @GST_VIDEO_FORMAT_RGB15: rgb 5-5-5 bits per component (Since: 0.10.29)
+ * @GST_VIDEO_FORMAT_BGR15: reverse rgb 5-5-5 bits per component (Since: 0.10.29)
  *
  * Enum value describing the most common video formats.
  */
@@ -88,7 +92,11 @@ typedef enum {
   GST_VIDEO_FORMAT_GRAY8,
   GST_VIDEO_FORMAT_GRAY16_BE,
   GST_VIDEO_FORMAT_GRAY16_LE,
-  GST_VIDEO_FORMAT_v308
+  GST_VIDEO_FORMAT_v308,
+  GST_VIDEO_FORMAT_RGB16,
+  GST_VIDEO_FORMAT_BGR16,
+  GST_VIDEO_FORMAT_RGB15,
+  GST_VIDEO_FORMAT_BGR15
 } GstVideoFormat;
 
 #define GST_VIDEO_BYTE1_MASK_32  "0xFF000000"
@@ -109,21 +117,21 @@ typedef enum {
 #define GST_VIDEO_BYTE2_MASK_24_INT  0x0000FF00
 #define GST_VIDEO_BYTE3_MASK_24_INT  0x000000FF
 
-#define GST_VIDEO_RED_MASK_16 "0xf800"
-#define GST_VIDEO_GREEN_MASK_16 "0x07e0"
-#define GST_VIDEO_BLUE_MASK_16 "0x001f"
+#define GST_VIDEO_COMP1_MASK_16 "0xf800"
+#define GST_VIDEO_COMP2_MASK_16 "0x07e0"
+#define GST_VIDEO_COMP3_MASK_16 "0x001f"
 
-#define GST_VIDEO_RED_MASK_15 "0x7c00"
-#define GST_VIDEO_GREEN_MASK_15 "0x03e0"
-#define GST_VIDEO_BLUE_MASK_15 "0x001f"
+#define GST_VIDEO_COMP1_MASK_15 "0x7c00"
+#define GST_VIDEO_COMP2_MASK_15 "0x03e0"
+#define GST_VIDEO_COMP3_MASK_15 "0x001f"
 
-#define GST_VIDEO_RED_MASK_16_INT 0xf800
-#define GST_VIDEO_GREEN_MASK_16_INT 0x07e0
-#define GST_VIDEO_BLUE_MASK_16_INT 0x001f
+#define GST_VIDEO_COMP1_MASK_16_INT 0xf800
+#define GST_VIDEO_COMP2_MASK_16_INT 0x07e0
+#define GST_VIDEO_COMP3_MASK_16_INT 0x001f
 
-#define GST_VIDEO_RED_MASK_15_INT 0x7c00
-#define GST_VIDEO_GREEN_MASK_15_INT 0x03e0
-#define GST_VIDEO_BLUE_MASK_15_INT 0x001f
+#define GST_VIDEO_COMP1_MASK_15_INT 0x7c00
+#define GST_VIDEO_COMP2_MASK_15_INT 0x03e0
+#define GST_VIDEO_COMP3_MASK_15_INT 0x001f
 
 #define GST_VIDEO_SIZE_RANGE "(int) [ 1, max ]"
 #define GST_VIDEO_FPS_RANGE "(fraction) [ 0, max ]"
@@ -166,6 +174,30 @@ typedef enum {
     "height = " GST_VIDEO_SIZE_RANGE ", "                               \
     "framerate = " GST_VIDEO_FPS_RANGE
 
+#define __GST_VIDEO_CAPS_MAKE_16(R, G, B)                               \
+    "video/x-raw-rgb, "                                                 \
+    "bpp = (int) 16, "                                                  \
+    "depth = (int) 16, "                                                \
+    "endianness = (int) BIG_ENDIAN, "                                   \
+    "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_16 ", "            \
+    "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_16 ", "          \
+    "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_16 ", "           \
+    "width = " GST_VIDEO_SIZE_RANGE ", "                                \
+    "height = " GST_VIDEO_SIZE_RANGE ", "                               \
+    "framerate = " GST_VIDEO_FPS_RANGE
+
+#define __GST_VIDEO_CAPS_MAKE_15(R, G, B)                               \
+    "video/x-raw-rgb, "                                                 \
+    "bpp = (int) 16, "                                                  \
+    "depth = (int) 15, "                                                \
+    "endianness = (int) BIG_ENDIAN, "                                   \
+    "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_15 ", "            \
+    "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_15 ", "          \
+    "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_15 ", "           \
+    "width = " GST_VIDEO_SIZE_RANGE ", "                                \
+    "height = " GST_VIDEO_SIZE_RANGE ", "                               \
+    "framerate = " GST_VIDEO_FPS_RANGE
+
 
 /* 24 bit */
 
@@ -218,29 +250,17 @@ typedef enum {
       
 /* 15/16 bit */
   
-#define GST_VIDEO_CAPS_RGB_16                                           \
-            "video/x-raw-rgb, "                                         \
-            "bpp = (int) 16, "                                          \
-            "depth = (int) 16, "                                        \
-            "endianness = (int) BYTE_ORDER, "                           \
-            "red_mask = (int) " GST_VIDEO_RED_MASK_16 ", "              \
-            "green_mask = (int) " GST_VIDEO_GREEN_MASK_16 ", "          \
-            "blue_mask = (int) " GST_VIDEO_BLUE_MASK_16 ", "            \
-            "width = " GST_VIDEO_SIZE_RANGE ", "                        \
-            "height = " GST_VIDEO_SIZE_RANGE ", "                       \
-            "framerate = " GST_VIDEO_FPS_RANGE
-
-#define GST_VIDEO_CAPS_RGB_15                                           \
-            "video/x-raw-rgb, "                                         \
-            "bpp = (int) 16, "                                          \
-            "depth = (int) 15, "                                        \
-            "endianness = (int) BYTE_ORDER, "                           \
-            "red_mask = (int) " GST_VIDEO_RED_MASK_15 ", "              \
-            "green_mask = (int) " GST_VIDEO_GREEN_MASK_15 ", "          \
-            "blue_mask = (int) " GST_VIDEO_BLUE_MASK_15 ", "            \
-            "width = " GST_VIDEO_SIZE_RANGE ", "                        \
-            "height = " GST_VIDEO_SIZE_RANGE ", "                       \
-            "framerate = " GST_VIDEO_FPS_RANGE
+#define GST_VIDEO_CAPS_RGB_16 \
+    __GST_VIDEO_CAPS_MAKE_16 (1, 2, 3)
+
+#define GST_VIDEO_CAPS_BGR_16 \
+    __GST_VIDEO_CAPS_MAKE_16 (3, 2, 1)
+
+#define GST_VIDEO_CAPS_RGB_15 \
+    __GST_VIDEO_CAPS_MAKE_15 (1, 2, 3)
+
+#define GST_VIDEO_CAPS_BGR_15 \
+    __GST_VIDEO_CAPS_MAKE_15 (3, 2, 1)
 
 /**
  * GST_VIDEO_CAPS_YUV:
-- 
1.6.4.4


From 9cdd2d4d9ccc984f805bcc2c8745ae2878833049 Mon Sep 17 00:00:00 2001
From: Martin Bisson <martin.bisson at gmail.com>
Date: Tue, 1 Jun 2010 16:45:34 +0000
Subject: [PATCH 2/2] video.{c,h}: Fix an endianness bug fix.

This commit makes sure the endianness is ok for RGB/BGR 15/16 formats.
---
 gst-libs/gst/video/video.c |    2 +-
 gst-libs/gst/video/video.h |    4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c
index a456336..b670f46 100644
--- a/gst-libs/gst/video/video.c
+++ b/gst-libs/gst/video/video.c
@@ -384,7 +384,7 @@ gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
           ok = FALSE;
         }
       } else if ((depth == 15 || depth == 16) && bpp == 16 &&
-          endianness == G_BIG_ENDIAN) {
+          endianness == G_BYTE_ORDER) {
         *format = gst_video_format_from_rgb16_masks (red_mask, green_mask,
             blue_mask);
         if (*format == GST_VIDEO_FORMAT_UNKNOWN) {
diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h
index a3ec55d..e145c33 100644
--- a/gst-libs/gst/video/video.h
+++ b/gst-libs/gst/video/video.h
@@ -178,7 +178,7 @@ typedef enum {
     "video/x-raw-rgb, "                                                 \
     "bpp = (int) 16, "                                                  \
     "depth = (int) 16, "                                                \
-    "endianness = (int) BIG_ENDIAN, "                                   \
+    "endianness = (int) BYTE_ORDER, "                                   \
     "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_16 ", "            \
     "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_16 ", "          \
     "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_16 ", "           \
@@ -190,7 +190,7 @@ typedef enum {
     "video/x-raw-rgb, "                                                 \
     "bpp = (int) 16, "                                                  \
     "depth = (int) 15, "                                                \
-    "endianness = (int) BIG_ENDIAN, "                                   \
+    "endianness = (int) BYTE_ORDER, "                                   \
     "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_15 ", "            \
     "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_15 ", "          \
     "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_15 ", "           \
-- 
1.6.4.4



More information about the gstreamer-devel mailing list