videomixer: Add support for YUY2, YVYU, UYVY
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 22 Apr 2010 11:56:58 +0000 (13:56 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 29 Apr 2010 17:28:22 +0000 (19:28 +0200)
gst/videomixer/blend.c
gst/videomixer/blend.h
gst/videomixer/videomixer.c

index ac70a2c..a5c95af 100644 (file)
@@ -595,6 +595,121 @@ RGB_FILL_COLOR (rgbx_c, 4, _memset_rgbx_c);
 MEMSET_RGB_C (bgrx, 4, 2, 1, 0);
 RGB_FILL_COLOR (bgrx_c, 4, _memset_bgrx_c);
 
+/* YUY2, YVYU, UYVY */
+
+#define PACKED_422_BLEND(name, MEMCPY, BLENDLOOP) \
+static void \
+blend_##name (const guint8 * src, gint xpos, gint ypos, \
+    gint src_width, gint src_height, gdouble src_alpha, \
+    guint8 * dest, gint dest_width, gint dest_height) \
+{ \
+  gint b_alpha; \
+  gint i; \
+  gint src_stride, dest_stride; \
+  \
+  src_stride = GST_ROUND_UP_4 (src_width * 2); \
+  dest_stride = GST_ROUND_UP_4 (dest_width * 2); \
+  \
+  b_alpha = CLAMP ((gint) (src_alpha * 256), 0, 256); \
+  \
+  xpos = GST_ROUND_UP_2 (xpos); \
+  \
+  /* adjust src pointers for negative sizes */ \
+  if (xpos < 0) { \
+    src += -xpos * 2; \
+    src_width -= -xpos; \
+    xpos = 0; \
+  } \
+  if (ypos < 0) { \
+    src += -ypos * src_stride; \
+    src_height -= -ypos; \
+    ypos = 0; \
+  } \
+  \
+  /* adjust width/height if the src is bigger than dest */ \
+  if (xpos + src_width > dest_width) { \
+    src_width = dest_width - xpos; \
+  } \
+  if (ypos + src_height > dest_height) { \
+    src_height = dest_height - ypos; \
+  } \
+  \
+  dest = dest + 2 * xpos + (ypos * dest_stride); \
+  /* If it's completely transparent... we just return */ \
+  if (G_UNLIKELY (src_alpha == 0.0)) { \
+    GST_INFO ("Fast copy (alpha == 0.0)"); \
+    return; \
+  } \
+  \
+  /* If it's completely opaque, we do a fast copy */ \
+  if (G_UNLIKELY (src_alpha == 1.0)) { \
+    GST_INFO ("Fast copy (alpha == 1.0)"); \
+    for (i = 0; i < src_height; i++) { \
+      MEMCPY (dest, src, 2 * src_width); \
+      src += src_stride; \
+      dest += dest_stride; \
+    } \
+    return; \
+  } \
+  \
+  BLENDLOOP(dest, src, src_stride, dest_stride, 2 * src_width, src_height, 2 * dest_width, b_alpha); \
+}
+
+#define PACKED_422_FILL_CHECKER_C(name, Y1, U, Y2, V) \
+static void \
+fill_checker_##name##_c (guint8 * dest, gint width, gint height) \
+{ \
+  gint i, j; \
+  static const int tab[] = { 80, 160, 80, 160 }; \
+  gint dest_add; \
+  \
+  width = GST_ROUND_UP_2 (width); \
+  dest_add = GST_ROUND_UP_4 (width * 2) - width * 2; \
+  width /= 2; \
+  \
+  for (i = 0; i < height; i++) { \
+    for (j = 0; j < width; j++) { \
+      dest[Y1] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+      dest[Y2] = tab[((i & 0x8) >> 3) + ((j & 0x8) >> 3)]; \
+      dest[U] = 128; \
+      dest[V] = 128; \
+      dest += 4; \
+    } \
+    dest += dest_add; \
+  } \
+}
+
+#define PACKED_422_FILL_COLOR(name, Y1, U, Y2, V) \
+static void \
+fill_color_##name (guint8 * dest, gint width, gint height, \
+    gint colY, gint colU, gint colV) \
+{ \
+  gint i, j; \
+  gint dest_add; \
+  \
+  width = GST_ROUND_UP_2 (width); \
+  dest_add = GST_ROUND_UP_4 (width * 2) - width * 2; \
+  width /= 2; \
+  \
+  for (i = 0; i < height; i++) { \
+    for (j = 0; j < width; j++) { \
+      dest[Y1] = colY; \
+      dest[Y2] = colY; \
+      dest[U] = colU; \
+      dest[V] = colV; \
+      dest += 4; \
+    } \
+    dest += dest_add; \
+  } \
+}
+
+PACKED_422_BLEND (yuy2_c, memcpy, _blend_u8_c);
+PACKED_422_FILL_CHECKER_C (yuy2, 0, 1, 2, 3);
+PACKED_422_FILL_CHECKER_C (uyvy, 1, 0, 3, 2);
+PACKED_422_FILL_COLOR (yuy2_c, 0, 1, 2, 3);
+PACKED_422_FILL_COLOR (yvyu_c, 0, 3, 2, 1);
+PACKED_422_FILL_COLOR (uyvy_c, 1, 0, 3, 2);
+
 /* MMX Implementations */
 #ifdef BUILD_X86_ASM
 
@@ -674,6 +789,8 @@ RGB_FILL_COLOR (rgbx_mmx, 4, _memset_rgbx_mmx);
 
 MEMSET_xRGB_MMX (bgrx, 8, 16, 24);
 RGB_FILL_COLOR (bgrx_mmx, 4, _memset_bgrx_mmx);
+
+PACKED_422_BLEND (yuy2_mmx, _memcpy_u8_mmx, _blend_u8_mmx);
 #endif
 
 /* Init function */
@@ -689,6 +806,8 @@ BlendFunction gst_video_mixer_blend_rgb;
 /* BGR is equal to RGB */
 BlendFunction gst_video_mixer_blend_rgbx;
 /* BGRx, xRGB, xBGR are equal to RGBx */
+BlendFunction gst_video_mixer_blend_yuy2;
+/* YVYU and UYVY are equal to YUY2 */
 
 FillCheckerFunction gst_video_mixer_fill_checker_argb;
 FillCheckerFunction gst_video_mixer_fill_checker_bgra;
@@ -703,6 +822,9 @@ FillCheckerFunction gst_video_mixer_fill_checker_rgb;
 /* BGR is equal to RGB */
 FillCheckerFunction gst_video_mixer_fill_checker_xrgb;
 /* BGRx, xRGB, xBGR are equal to RGBx */
+FillCheckerFunction gst_video_mixer_fill_checker_yuy2;
+/* YVYU is equal to YUY2 */
+FillCheckerFunction gst_video_mixer_fill_checker_uyvy;
 
 FillColorFunction gst_video_mixer_fill_color_argb;
 FillColorFunction gst_video_mixer_fill_color_bgra;
@@ -720,6 +842,9 @@ FillColorFunction gst_video_mixer_fill_color_xrgb;
 FillColorFunction gst_video_mixer_fill_color_xbgr;
 FillColorFunction gst_video_mixer_fill_color_rgbx;
 FillColorFunction gst_video_mixer_fill_color_bgrx;
+FillColorFunction gst_video_mixer_fill_color_yuy2;
+FillColorFunction gst_video_mixer_fill_color_yvyu;
+FillColorFunction gst_video_mixer_fill_color_uyvy;
 
 void
 gst_video_mixer_init_blend (void)
@@ -737,6 +862,7 @@ gst_video_mixer_init_blend (void)
   gst_video_mixer_blend_y41b = blend_y41b_c;
   gst_video_mixer_blend_rgb = blend_rgb_c;
   gst_video_mixer_blend_xrgb = blend_xrgb_c;
+  gst_video_mixer_blend_yuy2 = blend_yuy2_c;
 
   gst_video_mixer_fill_checker_argb = fill_checker_argb_c;
   gst_video_mixer_fill_checker_bgra = fill_checker_bgra_c;
@@ -747,6 +873,8 @@ gst_video_mixer_init_blend (void)
   gst_video_mixer_fill_checker_y41b = fill_checker_y41b_c;
   gst_video_mixer_fill_checker_rgb = fill_checker_rgb_c;
   gst_video_mixer_fill_checker_xrgb = fill_checker_xrgb_c;
+  gst_video_mixer_fill_checker_yuy2 = fill_checker_yuy2_c;
+  gst_video_mixer_fill_checker_uyvy = fill_checker_uyvy_c;
 
   gst_video_mixer_fill_color_argb = fill_color_argb_c;
   gst_video_mixer_fill_color_bgra = fill_color_bgra_c;
@@ -764,6 +892,9 @@ gst_video_mixer_init_blend (void)
   gst_video_mixer_fill_color_xbgr = fill_color_xbgr_c;
   gst_video_mixer_fill_color_rgbx = fill_color_rgbx_c;
   gst_video_mixer_fill_color_bgrx = fill_color_bgrx_c;
+  gst_video_mixer_fill_color_yuy2 = fill_color_yuy2_c;
+  gst_video_mixer_fill_color_yvyu = fill_color_yvyu_c;
+  gst_video_mixer_fill_color_uyvy = fill_color_uyvy_c;
 
 #ifdef BUILD_X86_ASM
   if (cpu_flags & OIL_IMPL_FLAG_MMX) {
@@ -775,6 +906,7 @@ gst_video_mixer_init_blend (void)
     gst_video_mixer_blend_y41b = blend_y41b_mmx;
     gst_video_mixer_blend_rgb = blend_rgb_mmx;
     gst_video_mixer_blend_xrgb = blend_xrgb_mmx;
+    gst_video_mixer_blend_yuy2 = blend_yuy2_mmx;
 
     gst_video_mixer_fill_checker_i420 = fill_checker_i420_mmx;
     gst_video_mixer_fill_checker_y444 = fill_checker_y444_mmx;
index 3c0a2d8..4f770cb 100644 (file)
@@ -42,6 +42,9 @@ extern BlendFunction gst_video_mixer_blend_rgbx;
 #define gst_video_mixer_blend_bgrx gst_video_mixer_blend_rgbx
 #define gst_video_mixer_blend_xrgb gst_video_mixer_blend_rgbx
 #define gst_video_mixer_blend_xbgr gst_video_mixer_blend_rgbx
+extern BlendFunction gst_video_mixer_blend_yuy2;
+#define gst_video_mixer_blend_uyvy gst_video_mixer_blend_yuy2;
+#define gst_video_mixer_blend_yvyu gst_video_mixer_blend_yuy2;
 
 extern FillCheckerFunction gst_video_mixer_fill_checker_argb;
 #define gst_video_mixer_fill_checker_abgr gst_video_mixer_fill_checker_argb
@@ -59,6 +62,9 @@ extern FillCheckerFunction gst_video_mixer_fill_checker_rgbx;
 #define gst_video_mixer_fill_checker_bgrx gst_video_mixer_fill_checker_rgbx
 #define gst_video_mixer_fill_checker_xrgb gst_video_mixer_fill_checker_rgbx
 #define gst_video_mixer_fill_checker_xbgr gst_video_mixer_fill_checker_rgbx
+extern FillCheckerFunction gst_video_mixer_fill_checker_yuy2;
+#define gst_video_mixer_fill_checker_yvyu gst_video_mixer_fill_checker_yuy2;
+extern FillCheckerFunction gst_video_mixer_fill_checker_uyvy;
 
 extern FillColorFunction gst_video_mixer_fill_color_argb;
 extern FillColorFunction gst_video_mixer_fill_color_abgr;
@@ -76,6 +82,9 @@ extern FillColorFunction gst_video_mixer_fill_color_xrgb;
 extern FillColorFunction gst_video_mixer_fill_color_xbgr;
 extern FillColorFunction gst_video_mixer_fill_color_rgbx;
 extern FillColorFunction gst_video_mixer_fill_color_bgrx;
+extern FillColorFunction gst_video_mixer_fill_color_yuy2;
+extern FillColorFunction gst_video_mixer_fill_color_yvyu;
+extern FillColorFunction gst_video_mixer_fill_color_uyvy;
 
 void gst_video_mixer_init_blend (void);
 
index c4448a6..c77604e 100644 (file)
@@ -472,7 +472,9 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_BGRA ";"
         GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_ABGR ";"
         GST_VIDEO_CAPS_YUV ("Y444") ";" GST_VIDEO_CAPS_YUV ("Y42B") ";"
-        GST_VIDEO_CAPS_YUV ("{ I420, YV12 }") ";"
+        GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("UYVY") ";"
+        GST_VIDEO_CAPS_YUV ("YVYU") ";"
+        GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("YV12") ";"
         GST_VIDEO_CAPS_YUV ("Y41B") ";" GST_VIDEO_CAPS_RGB ";"
         GST_VIDEO_CAPS_BGR ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";"
         GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx)
@@ -484,7 +486,9 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d",
     GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_BGRA ";"
         GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_ABGR ";"
         GST_VIDEO_CAPS_YUV ("Y444") ";" GST_VIDEO_CAPS_YUV ("Y42B") ";"
-        GST_VIDEO_CAPS_YUV ("{ I420, YV12 }") ";"
+        GST_VIDEO_CAPS_YUV ("YUY2") ";" GST_VIDEO_CAPS_YUV ("UYVY") ";"
+        GST_VIDEO_CAPS_YUV ("YVYU") ";"
+        GST_VIDEO_CAPS_YUV ("I420") ";" GST_VIDEO_CAPS_YUV ("YV12") ";"
         GST_VIDEO_CAPS_YUV ("Y41B") ";" GST_VIDEO_CAPS_RGB ";"
         GST_VIDEO_CAPS_BGR ";" GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";"
         GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx)
@@ -991,6 +995,24 @@ gst_videomixer_setcaps (GstPad * pad, GstCaps * caps)
       mixer->fill_color = gst_video_mixer_fill_color_y42b;
       ret = TRUE;
       break;
+    case GST_VIDEO_FORMAT_YUY2:
+      mixer->blend = gst_video_mixer_blend_yuy2;
+      mixer->fill_checker = gst_video_mixer_fill_checker_yuy2;
+      mixer->fill_color = gst_video_mixer_fill_color_yuy2;
+      ret = TRUE;
+      break;
+    case GST_VIDEO_FORMAT_UYVY:
+      mixer->blend = gst_video_mixer_blend_uyvy;
+      mixer->fill_checker = gst_video_mixer_fill_checker_uyvy;
+      mixer->fill_color = gst_video_mixer_fill_color_uyvy;
+      ret = TRUE;
+      break;
+    case GST_VIDEO_FORMAT_YVYU:
+      mixer->blend = gst_video_mixer_blend_yvyu;
+      mixer->fill_checker = gst_video_mixer_fill_checker_yvyu;
+      mixer->fill_color = gst_video_mixer_fill_color_yvyu;
+      ret = TRUE;
+      break;
     case GST_VIDEO_FORMAT_I420:
       mixer->blend = gst_video_mixer_blend_i420;
       mixer->fill_checker = gst_video_mixer_fill_checker_i420;