[MOVED FROM BAD 03/29] shapewipe: Add border property to allow smooth borders
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 29 May 2009 14:51:50 +0000 (16:51 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 12 Feb 2010 10:12:32 +0000 (11:12 +0100)
...and use a border of 0.01 in the example application.

gst/shapewipe/gstshapewipe.c
gst/shapewipe/gstshapewipe.h
tests/examples/shapewipe/shapewipe-example.c

index 4c30d89..3efe7cc 100644 (file)
@@ -57,7 +57,8 @@ static GstCaps *gst_shape_wipe_src_getcaps (GstPad * pad);
 enum
 {
   PROP_0,
-  PROP_POSITION
+  PROP_POSITION,
+  PROP_BORDER
 };
 
 static GstStaticPadTemplate video_sink_pad_template =
@@ -121,6 +122,10 @@ gst_shape_wipe_class_init (GstShapeWipeClass * klass)
       g_param_spec_float ("position", "Position", "Position of the mask",
           0.0, 1.0, 0.0,
           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
+  g_object_class_install_property (gobject_class, PROP_BORDER,
+      g_param_spec_float ("border", "Border", "Border of the mask",
+          0.0, 1.0, 0.0,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_shape_wipe_change_state);
@@ -176,6 +181,9 @@ gst_shape_wipe_get_property (GObject * object, guint prop_id,
     case PROP_POSITION:
       g_value_set_float (value, self->mask_position);
       break;
+    case PROP_BORDER:
+      g_value_set_float (value, self->mask_border);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -192,6 +200,9 @@ gst_shape_wipe_set_property (GObject * object, guint prop_id,
     case PROP_POSITION:
       self->mask_position = g_value_get_float (value);
       break;
+    case PROP_BORDER:
+      self->mask_border = g_value_get_float (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -227,6 +238,7 @@ gst_shape_wipe_reset (GstShapeWipe * self)
 
   self->width = self->height = 0;
   self->mask_position = 0.0;
+  self->mask_border = 0.0;
   self->mask_bpp = 0;
 
   gst_segment_init (&self->segment, GST_FORMAT_TIME);
@@ -544,19 +556,30 @@ gst_shape_wipe_blend_16 (GstShapeWipe * self, GstBuffer * inbuf,
   guint i, j;
   guint mask_increment = GST_ROUND_UP_2 (self->width) - self->width;
   gfloat position = self->mask_position;
+  gfloat low = MAX (0.0, position - self->mask_border);
+  gfloat high = MIN (1.0, position + self->mask_border);
 
   for (i = 0; i < self->height; i++) {
     for (j = 0; j < self->width; j++) {
-      if (*mask / 65535.0 < position) {
+      gfloat in = *mask / 65535.0;
+
+      if (in <= low) {
         output[0] = 0x00;       /* A */
         output[1] = 0x00;       /* Y */
         output[2] = 0x80;       /* U */
         output[3] = 0x80;       /* V */
-      } else {
+      } else if (in >= high) {
         output[0] = 0xff;       /* A */
         output[1] = input[1];   /* Y */
         output[2] = input[2];   /* U */
         output[3] = input[3];   /* V */
+      } else {
+        gfloat val = 255 * ((in - low) / (high - low));
+
+        output[0] = CLAMP (val, 0, 255);        /* A */
+        output[1] = input[1];   /* Y */
+        output[2] = input[2];   /* U */
+        output[3] = input[3];   /* V */
       }
 
       mask++;
@@ -579,19 +602,30 @@ gst_shape_wipe_blend_8 (GstShapeWipe * self, GstBuffer * inbuf,
   guint i, j;
   guint mask_increment = GST_ROUND_UP_4 (self->width) - self->width;
   gfloat position = self->mask_position;
+  gfloat low = MAX (0.0, position - self->mask_border);
+  gfloat high = MIN (1.0, position + self->mask_border);
 
   for (i = 0; i < self->height; i++) {
     for (j = 0; j < self->width; j++) {
-      if (*mask / 255.0 < position) {
+      gfloat in = *mask / 255.0;
+
+      if (in <= low) {
         output[0] = 0x00;       /* A */
         output[1] = 0x00;       /* Y */
         output[2] = 0x80;       /* U */
         output[3] = 0x80;       /* V */
-      } else {
+      } else if (in >= high) {
         output[0] = 0xff;       /* A */
         output[1] = input[1];   /* Y */
         output[2] = input[2];   /* U */
         output[3] = input[3];   /* V */
+      } else {
+        gfloat val = 255 * ((in - low) / (high - low));
+
+        output[0] = CLAMP (val, 0, 255);        /* A */
+        output[1] = input[1];   /* Y */
+        output[2] = input[2];   /* U */
+        output[3] = input[3];   /* V */
       }
 
       mask++;
index 6ce57c3..00ed776 100644 (file)
@@ -54,6 +54,7 @@ struct _GstShapeWipe
 
   GstBuffer *mask;
   gfloat mask_position;
+  gfloat mask_border;
   GMutex *mask_mutex;
   GCond *mask_cond;
   gint mask_bpp;
index 3b57bcc..a3aed08 100644 (file)
@@ -67,7 +67,7 @@ main (gint argc, gchar ** argv)
 
   pipeline_string =
       g_strdup_printf
-      ("videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe name=shape ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink     filesrc location=%s ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink    videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.",
+      ("videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe name=shape border=0.01 ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink     filesrc location=%s ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink    videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.",
       argv[1]);
 
   pipeline = gst_parse_launch (pipeline_string, NULL);