pango: Add support for xRGB and BGRx formats
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 4 Aug 2009 10:46:57 +0000 (12:46 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 6 Aug 2009 04:43:38 +0000 (06:43 +0200)
ext/pango/gsttextoverlay.c
ext/pango/gsttextoverlay.h

index b735bf4..d05f3d4 100644 (file)
@@ -179,16 +179,18 @@ static GstStaticPadTemplate src_template_factory =
     GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";"
-        GST_VIDEO_CAPS_YUV ("UYVY"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
+        GST_VIDEO_CAPS_xRGB ";"
+        GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("UYVY"))
     );
 
 static GstStaticPadTemplate video_sink_template_factory =
     GST_STATIC_PAD_TEMPLATE ("video_sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") ";"
-        GST_VIDEO_CAPS_YUV ("UYVY"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";"
+        GST_VIDEO_CAPS_xRGB ";"
+        GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("UYVY"))
     );
 
 static GstStaticPadTemplate text_sink_template_factory =
@@ -686,10 +688,9 @@ gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
   structure = gst_caps_get_structure (caps, 0);
   fps = gst_structure_get_value (structure, "framerate");
 
-  if (gst_structure_get_int (structure, "width", &overlay->width) &&
-      gst_structure_get_int (structure, "height", &overlay->height) &&
-      gst_structure_get_fourcc (structure, "format", &overlay->format) &&
-      fps != NULL) {
+  if (fps
+      && gst_video_format_parse_caps (caps, &overlay->format, &overlay->width,
+          &overlay->height)) {
     ret = gst_pad_set_caps (overlay->srcpad, caps);
   }
 
@@ -1319,6 +1320,32 @@ gst_text_overlay_shade_UYVY_y (GstTextOverlay * overlay, guchar * dest,
   }
 }
 
+#define gst_text_overlay_shade_BGRx gst_text_overlay_shade_xRGB
+static inline void
+gst_text_overlay_shade_xRGB (GstTextOverlay * overlay, guchar * dest,
+    gint x0, gint x1, gint y0, gint y1)
+{
+  gint i, j;
+
+  x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width);
+  x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width);
+
+  y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height);
+  y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height);
+
+  for (i = y0; i < y1; i++) {
+    for (j = x0; j < x1; j++) {
+      gint y, y_pos, k;
+
+      y_pos = (i * 4 * overlay->width) + j * 4;
+      for (k = 0; k < 4; k++) {
+        y = dest[y_pos + k] + overlay->shading_value;
+        dest[y_pos + k] = CLAMP (y, 0, 255);
+      }
+    }
+  }
+}
+
 /* FIXME:
  *  - use proper strides and offset for I420
  *  - don't draw over the edge of the picture (try a longer
@@ -1426,6 +1453,51 @@ gst_text_overlay_blit_UYVY (GstTextOverlay * overlay,
   }
 }
 
+#define xRGB_BLIT_FUNCTION(name, R, G, B) \
+static inline void \
+gst_text_overlay_blit_##name (GstTextOverlay * overlay, \
+    guint8 * rgb_pixels, gint xpos, gint ypos) \
+{ \
+  int a, r, g, b; \
+  int i, j; \
+  int h, w; \
+  guchar *pimage, *dest; \
+  \
+  w = overlay->image_width; \
+  h = overlay->image_height; \
+  \
+  if (xpos < 0) { \
+    xpos = 0; \
+  } \
+  \
+  if (xpos + w > overlay->width) { \
+    w = overlay->width - xpos; \
+  } \
+  \
+  if (ypos + h > overlay->height) { \
+    h = overlay->height - ypos; \
+  } \
+  \
+  for (i = 0; i < h; i++) { \
+    pimage = overlay->text_image + i * overlay->image_width * 4; \
+    dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; \
+    for (j = 0; j < w; j++) { \
+      a = pimage[CAIRO_ARGB_A]; \
+      b = (pimage[CAIRO_ARGB_B] * a + dest[B] * (255-a)) / 255; \
+      g = (pimage[CAIRO_ARGB_G] * a + dest[G] * (255-a)) / 255; \
+      r = (pimage[CAIRO_ARGB_R] * a + dest[R] * (255-a)) / 255; \
+      \
+      dest[B] = b; \
+      dest[G] = g; \
+      dest[R] = r; \
+      pimage += 4; \
+      dest += 4; \
+    } \
+  } \
+}
+xRGB_BLIT_FUNCTION (xRGB, 1, 2, 3);
+xRGB_BLIT_FUNCTION (BGRx, 2, 1, 0);
+
 static void
 gst_text_overlay_render_text (GstTextOverlay * overlay,
     const gchar * text, gint textlen)
@@ -1515,16 +1587,26 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
   /* shaded background box */
   if (overlay->want_shading) {
     switch (overlay->format) {
-      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+      case GST_VIDEO_FORMAT_I420:
         gst_text_overlay_shade_I420_y (overlay,
             GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
             ypos, ypos + overlay->image_height);
         break;
-      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+      case GST_VIDEO_FORMAT_UYVY:
         gst_text_overlay_shade_UYVY_y (overlay,
             GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
             ypos, ypos + overlay->image_height);
         break;
+      case GST_VIDEO_FORMAT_xRGB:
+        gst_text_overlay_shade_xRGB (overlay,
+            GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+            ypos, ypos + overlay->image_height);
+        break;
+      case GST_VIDEO_FORMAT_BGRx:
+        gst_text_overlay_shade_BGRx (overlay,
+            GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+            ypos, ypos + overlay->image_height);
+        break;
       default:
         g_assert_not_reached ();
     }
@@ -1535,14 +1617,22 @@ gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
 
   if (overlay->text_image) {
     switch (overlay->format) {
-      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+      case GST_VIDEO_FORMAT_I420:
         gst_text_overlay_blit_I420 (overlay,
             GST_BUFFER_DATA (video_frame), xpos, ypos);
         break;
-      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+      case GST_VIDEO_FORMAT_UYVY:
         gst_text_overlay_blit_UYVY (overlay,
             GST_BUFFER_DATA (video_frame), xpos, ypos);
         break;
+      case GST_VIDEO_FORMAT_BGRx:
+        gst_text_overlay_blit_BGRx (overlay,
+            GST_BUFFER_DATA (video_frame), xpos, ypos);
+        break;
+      case GST_VIDEO_FORMAT_xRGB:
+        gst_text_overlay_blit_xRGB (overlay,
+            GST_BUFFER_DATA (video_frame), xpos, ypos);
+        break;
       default:
         g_assert_not_reached ();
     }
index 94ef1f8..232d97a 100644 (file)
@@ -2,6 +2,7 @@
 #define __GST_TEXT_OVERLAY_H__
 
 #include <gst/gst.h>
+#include <gst/video/video.h>
 #include <pango/pangocairo.h>
 
 G_BEGIN_DECLS
@@ -109,7 +110,7 @@ struct _GstTextOverlay {
     gint                     height;
     gint                     fps_n;
     gint                     fps_d;
-    guint32                  format;
+    GstVideoFormat           format;
 
     GstTextOverlayVAlign     valign;
     GstTextOverlayHAlign     halign;