fix up more enums
[platform/upstream/gst-plugins-good.git] / gst / videobox / gstvideobox.c
index f1ebe4d..87a72e8 100644 (file)
 #include <gst/base/gstbasetransform.h>
 #include <gst/video/video.h>
 
+#include <liboil/liboil.h>
 #include <string.h>
 
+GST_DEBUG_CATEGORY (videobox_debug);
+#define GST_CAT_DEFAULT videobox_debug
+
 #define GST_TYPE_VIDEO_BOX \
   (gst_video_box_get_type())
 #define GST_VIDEO_BOX(obj) \
@@ -141,9 +145,9 @@ gst_video_box_fill_get_type (void)
 {
   static GType video_box_fill_type = 0;
   static GEnumValue video_box_fill[] = {
-    {VIDEO_BOX_FILL_BLACK, "0", "Black"},
-    {VIDEO_BOX_FILL_GREEN, "1", "Colorkey green"},
-    {VIDEO_BOX_FILL_BLUE, "2", "Colorkey blue"},
+    {VIDEO_BOX_FILL_BLACK, "Black", "black"},
+    {VIDEO_BOX_FILL_GREEN, "Colorkey green", "green"},
+    {VIDEO_BOX_FILL_BLUE, "Colorkey blue", "blue"},
     {0, NULL, NULL},
   };
 
@@ -212,10 +216,13 @@ gst_video_box_class_init (GstVideoBoxClass * klass)
   trans_class->set_caps = gst_video_box_set_caps;
   trans_class->get_unit_size = gst_video_box_get_unit_size;
   trans_class->transform = gst_video_box_transform;
+
+  GST_DEBUG_CATEGORY_INIT (videobox_debug, "videobox", 0,
+      "Resizes a video by adding borders or cropping");
 }
 
 static void
-gst_video_box_init (GstVideoBox * video_box)
+gst_video_box_init (GstVideoBox * video_box, GstVideoBoxClass * g_class)
 {
   video_box->box_right = DEFAULT_RIGHT;
   video_box->box_left = DEFAULT_LEFT;
@@ -291,6 +298,7 @@ gst_video_box_set_property (GObject * object, guint prop_id,
       break;
   }
 }
+
 static void
 gst_video_box_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
@@ -332,23 +340,45 @@ gst_video_box_transform_caps (GstBaseTransform * trans,
   GstVideoBox *video_box;
   GstCaps *to;
   GstStructure *structure;
+  GValue list_value = { 0 }, value = {
+  0};
   gint dir, i, tmp;
 
   video_box = GST_VIDEO_BOX (trans);
+
+  g_value_init (&list_value, GST_TYPE_LIST);
+  g_value_init (&value, GST_TYPE_FOURCC);
+  gst_value_set_fourcc (&value, GST_MAKE_FOURCC ('I', '4', '2', '0'));
+  gst_value_list_append_value (&list_value, &value);
+  g_value_unset (&value);
+
   to = gst_caps_copy (from);
   dir = (direction == GST_PAD_SINK) ? -1 : 1;
 
-  /* FIXME, include AYUV */
   for (i = 0; i < gst_caps_get_size (to); i++) {
     structure = gst_caps_get_structure (to, i);
+    if (direction == GST_PAD_SINK) {    /* I420 to { I420, AYUV } */
+      g_value_init (&value, GST_TYPE_FOURCC);
+      gst_value_set_fourcc (&value, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'));
+      gst_value_list_append_value (&list_value, &value);
+      g_value_unset (&value);
+      gst_structure_set_value (structure, "format", &list_value);
+    } else if (direction == GST_PAD_SRC) {
+      gst_structure_set_value (structure, "format", &list_value);
+    }
     if (gst_structure_get_int (structure, "width", &tmp))
       gst_structure_set (structure, "width", G_TYPE_INT,
-          tmp + direction * (video_box->box_left + video_box->box_right), NULL);
+          tmp + dir * (video_box->box_left + video_box->box_right), NULL);
     if (gst_structure_get_int (structure, "height", &tmp))
       gst_structure_set (structure, "height", G_TYPE_INT,
-          tmp + direction * (video_box->box_top + video_box->box_bottom), NULL);
+          tmp + dir * (video_box->box_top + video_box->box_bottom), NULL);
   }
 
+  g_value_unset (&list_value);
+
+  GST_DEBUG_OBJECT (video_box, "direction %d, transformed %" GST_PTR_FORMAT
+      " to %" GST_PTR_FORMAT, direction, from, to);
+
   return to;
 }
 
@@ -371,43 +401,61 @@ gst_video_box_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
   ret &= gst_structure_get_int (structure, "height", &video_box->out_height);
   ret &= gst_structure_get_fourcc (structure, "format", &fourcc);
 
-  video_box->use_alpha = fourcc == GST_STR_FOURCC ("AYUV");
+  if (fourcc == GST_STR_FOURCC ("AYUV")) {
+    video_box->use_alpha = TRUE;
+  } else {
+    if (video_box->box_left == 0 && video_box->box_right == 0 &&
+        video_box->box_top == 0 && video_box->box_bottom == 0) {
+      gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box), TRUE);
+      GST_LOG ("we are using passthrough");
+    } else {
+      gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (video_box),
+          FALSE);
+      GST_LOG ("we are not using passthrough");
+    }
+  }
 
   return ret;
 }
 
-#define ROUND_UP_2(x)  (((x)+1)&~1)
-#define ROUND_UP_4(x)  (((x)+3)&~3)
-#define ROUND_UP_8(x)  (((x)+7)&~7)
-
 /* see gst-plugins/gst/games/gstvideoimage.c, paint_setup_I420() */
-#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (ROUND_UP_4(width))
-#define GST_VIDEO_I420_U_ROWSTRIDE(width) (ROUND_UP_8(width)/2)
-#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2)
+#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
+#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
+#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2)
 
 #define GST_VIDEO_I420_Y_OFFSET(w,h) (0)
-#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*ROUND_UP_2(h)))
-#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
+#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
+#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
 
-#define GST_VIDEO_I420_SIZE(w,h)     (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
+#define GST_VIDEO_I420_SIZE(w,h)     (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
 
 static gboolean
 gst_video_box_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
     guint * size)
 {
   GstVideoBox *video_box;
+  GstStructure *structure = NULL;
+  guint32 fourcc;
+  gint width, height;
 
   g_return_val_if_fail (size, FALSE);
   video_box = GST_VIDEO_BOX (trans);
 
-  if (gst_caps_is_equal (caps, GST_PAD_CAPS (trans->sinkpad))) {
-    *size = GST_VIDEO_I420_SIZE (video_box->in_width, video_box->in_height);
-  } else if (gst_caps_is_equal (caps, GST_PAD_CAPS (trans->srcpad))) {
-    if (video_box->use_alpha) {
-      *size = video_box->out_height * video_box->out_height * 4;
-    } else {
-      *size = GST_VIDEO_I420_SIZE (video_box->out_width, video_box->out_height);
-    }
+  structure = gst_caps_get_structure (caps, 0);
+  gst_structure_get_fourcc (structure, "format", &fourcc);
+  gst_structure_get_int (structure, "width", &width);
+  gst_structure_get_int (structure, "height", &height);
+
+  switch (fourcc) {
+    case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
+      *size = width * height * 4;
+      break;
+    case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+      *size = GST_VIDEO_I420_SIZE (width, height);
+      break;
+    default:
+      return FALSE;
+      break;
   }
 
   return TRUE;
@@ -427,22 +475,22 @@ gst_video_box_copy_plane_i420 (GstVideoBox * video_box, guint8 * src,
 
   /* top border */
   for (j = 0; j < bt; j++) {
-    memset (dest, fill_color, dest_width);
+    oil_splat_u8_ns (dest, &fill_color, dest_width);
     dest += dest_stride;
   }
 
   /* copy and add left and right border */
   for (j = 0; j < src_crop_height; j++) {
-    memset (dest, fill_color, bl);
-    memcpy (dest + bl, src, src_crop_width);
-    memset (dest + bl + src_crop_width, fill_color, br);
+    oil_splat_u8_ns (dest, &fill_color, bl);
+    oil_memcpy (dest + bl, src, src_crop_width);
+    oil_splat_u8_ns (dest + bl + src_crop_width, &fill_color, br);
     dest += dest_stride;
     src += src_stride;
   }
 
   /* bottom border */
   for (j = 0; j < bb; j++) {
-    memset (dest, fill_color, dest_width);
+    oil_splat_u8_ns (dest, &fill_color, dest_width);
     dest += dest_stride;
   }
 }
@@ -514,14 +562,13 @@ gst_video_box_i420 (GstVideoBox * video_box, guint8 * src, guint8 * dest)
 
 /* Note the source image is always I420, we
  * are converting to AYUV on the fly here */
-
 static void
 gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
 {
   guint8 *srcY, *srcU, *srcV;
   gint crop_width, crop_width2, crop_height;
   gint out_width, out_height;
-  gint src_stride, src_stride2;
+  gint src_stridey, src_strideu, src_stridev;
   gint br, bl, bt, bb;
   gint colorY, colorU, colorV;
   gint i, j;
@@ -538,8 +585,9 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
   out_width = video_box->out_width;
   out_height = video_box->out_height;
 
-  src_stride = GST_VIDEO_I420_Y_ROWSTRIDE (video_box->in_width);
-  src_stride2 = src_stride / 2;
+  src_stridey = GST_VIDEO_I420_Y_ROWSTRIDE (video_box->in_width);
+  src_strideu = GST_VIDEO_I420_U_ROWSTRIDE (video_box->in_width);
+  src_stridev = GST_VIDEO_I420_V_ROWSTRIDE (video_box->in_width);
 
   crop_width =
       video_box->in_width - (video_box->crop_left + video_box->crop_right);
@@ -549,13 +597,13 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
 
   srcY =
       src + GST_VIDEO_I420_Y_OFFSET (video_box->in_width, video_box->in_height);
-  srcY += src_stride * video_box->crop_top + video_box->crop_left;
+  srcY += src_stridey * video_box->crop_top + video_box->crop_left;
   srcU =
       src + GST_VIDEO_I420_U_OFFSET (video_box->in_width, video_box->in_height);
-  srcU += src_stride2 * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+  srcU += src_strideu * (video_box->crop_top / 2) + (video_box->crop_left / 2);
   srcV =
       src + GST_VIDEO_I420_V_OFFSET (video_box->in_width, video_box->in_height);
-  srcV += src_stride2 * (video_box->crop_top / 2) + (video_box->crop_left / 2);
+  srcV += src_stridev * (video_box->crop_top / 2) + (video_box->crop_left / 2);
 
   colorY = yuv_colors_Y[video_box->fill_type];
   colorU = yuv_colors_U[video_box->fill_type];
@@ -566,24 +614,28 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
       colorV);
 
   /* top border */
-  for (i = 0; i < bt; i++) {
-    for (j = 0; j < out_width; j++) {
-      *destp++ = ayuv;
-    }
+  if (bt) {
+    size_t nb_pixels = bt * out_width;
+
+    oil_splat_u32_ns (destp, &ayuv, nb_pixels);
+    destp += nb_pixels;
   }
   for (i = 0; i < crop_height; i++) {
     /* left border */
-    for (j = 0; j < bl; j++) {
-      *destp++ = ayuv;
+    if (bl) {
+      oil_splat_u32_ns (destp, &ayuv, bl);
+      destp += bl;
     }
     dest = (guint8 *) destp;
     /* center */
+    /* We can splat the alpha channel for the whole line */
+    oil_splat_u8 (dest, 4, &i_alpha, crop_width);
     for (j = 0; j < crop_width2; j++) {
-      *dest++ = i_alpha;
+      dest++;
       *dest++ = *srcY++;
       *dest++ = *srcU;
       *dest++ = *srcV;
-      *dest++ = i_alpha;
+      dest++;
       *dest++ = *srcY++;
       *dest++ = *srcU++;
       *dest++ = *srcV++;
@@ -592,22 +644,24 @@ gst_video_box_ayuv (GstVideoBox * video_box, guint8 * src, guint8 * dest)
       srcU -= crop_width2;
       srcV -= crop_width2;
     } else {
-      srcU += src_stride2 - crop_width2;
-      srcV += src_stride2 - crop_width2;
+      srcU += src_strideu - crop_width2;
+      srcV += src_stridev - crop_width2;
     }
-    srcY += src_stride - crop_width;
+    srcY += src_stridey - crop_width;
 
     destp = (guint32 *) dest;
     /* right border */
-    for (j = 0; j < br; j++) {
-      *destp++ = ayuv;
+    if (br) {
+      oil_splat_u32_ns (destp, &ayuv, br);
+      destp += br;
     }
   }
   /* bottom border */
-  for (i = 0; i < bb; i++) {
-    for (j = 0; j < out_width; j++) {
-      *destp++ = ayuv;
-    }
+  if (bb) {
+    size_t nb_pixels = bb * out_width;
+
+    oil_splat_u32_ns (destp, &ayuv, nb_pixels);
+    destp += nb_pixels;
   }
 }
 
@@ -639,4 +693,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "videobox",
     "resizes a video by adding borders or cropping",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)