smpte: Add property for inverting the transition mask
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 15 Apr 2010 20:28:58 +0000 (22:28 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 29 Apr 2010 17:28:17 +0000 (19:28 +0200)
This converts a left-to-right transition to right-to-left or
clock-wise to counter-clock-wise.

gst/smpte/gstmask.c
gst/smpte/gstmask.h
gst/smpte/gstsmpte.c
gst/smpte/gstsmpte.h
gst/smpte/gstsmptealpha.c
gst/smpte/gstsmptealpha.h

index 9c0ba92..940bf82 100644 (file)
@@ -69,7 +69,8 @@ gst_mask_find_definition (gint type)
 }
 
 GstMask *
-gst_mask_factory_new (gint type, gint bpp, gint width, gint height)
+gst_mask_factory_new (gint type, gboolean invert, gint bpp, gint width,
+    gint height)
 {
   GstMaskDefinition *definition;
   GstMask *mask = NULL;
@@ -86,8 +87,20 @@ gst_mask_factory_new (gint type, gint bpp, gint width, gint height)
     mask->user_data = definition->user_data;
     mask->data = g_malloc (width * height * sizeof (guint32));
 
-    if (definition->draw_func)
-      definition->draw_func (mask);
+    definition->draw_func (mask);
+
+    if (invert) {
+      gint i, j;
+      guint32 *datap = mask->data;
+      guint32 max = (1 << bpp);
+
+      for (i = 0; i < height; i++) {
+        for (j = 0; j < width; j++) {
+          *datap = max - *datap;
+          datap++;
+        }
+      }
+    }
   }
 
   return mask;
index 7e29246..576475c 100644 (file)
@@ -56,7 +56,7 @@ void                    _gst_mask_register              (const GstMaskDefinition
 void                    _gst_mask_default_destroy       (GstMask *mask);
 
 const GList*            gst_mask_get_definitions        (void);
-GstMask*                gst_mask_factory_new            (gint type, gint bpp, gint width, gint height);
+GstMask*                gst_mask_factory_new            (gint type, gboolean invert, gint bpp, gint width, gint height);
 void                    gst_mask_destroy                (GstMask *mask);
 
 void _gst_barboxwipes_register (void);
index 8f1fcc5..0ef60e2 100644 (file)
@@ -87,6 +87,7 @@ enum
 #define DEFAULT_PROP_DEPTH     16
 #define DEFAULT_PROP_FPS       0.
 #define DEFAULT_PROP_DURATION  GST_SECOND
+#define DEFAULT_PROP_INVERT   FALSE
 
 enum
 {
@@ -96,6 +97,7 @@ enum
   PROP_DEPTH,
   PROP_FPS,
   PROP_DURATION,
+  PROP_INVERT,
   PROP_LAST,
 };
 
@@ -242,6 +244,9 @@ gst_smpte_class_init (GstSMPTEClass * klass)
       g_param_spec_uint64 ("duration", "Duration",
           "Duration of the transition effect in nanoseconds", 0, G_MAXUINT64,
           DEFAULT_PROP_DURATION, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
+      g_param_spec_boolean ("invert", "Invert",
+          "Invert transition mask", DEFAULT_PROP_INVERT, G_PARAM_READWRITE));
 
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_smpte_change_state);
 }
@@ -266,25 +271,27 @@ fill_i420 (guint8 * data, gint width, gint height, gint color)
 }
 
 static gboolean
-gst_smpte_update_mask (GstSMPTE * smpte, gint type, gint depth, gint width,
-    gint height)
+gst_smpte_update_mask (GstSMPTE * smpte, gint type, gboolean invert,
+    gint depth, gint width, gint height)
 {
   GstMask *newmask;
 
   if (smpte->mask) {
     if (smpte->type == type &&
+        smpte->invert == invert &&
         smpte->depth == depth &&
         smpte->width == width && smpte->height == height)
       return TRUE;
   }
 
-  newmask = gst_mask_factory_new (type, depth, width, height);
+  newmask = gst_mask_factory_new (type, invert, depth, width, height);
   if (newmask) {
     if (smpte->mask) {
       gst_mask_destroy (smpte->mask);
     }
     smpte->mask = newmask;
     smpte->type = type;
+    smpte->invert = invert;
     smpte->depth = depth;
     smpte->width = width;
     smpte->height = height;
@@ -321,8 +328,9 @@ gst_smpte_setcaps (GstPad * pad, GstCaps * caps)
 
   GST_DEBUG_OBJECT (smpte, "duration: %d frames", smpte->end_position);
 
-  ret = gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width,
-      smpte->height);
+  ret =
+      gst_smpte_update_mask (smpte, smpte->type, smpte->invert, smpte->depth,
+      smpte->width, smpte->height);
 
   return ret;
 }
@@ -365,6 +373,7 @@ gst_smpte_init (GstSMPTE * smpte)
   smpte->border = DEFAULT_PROP_BORDER;
   smpte->depth = DEFAULT_PROP_DEPTH;
   smpte->duration = DEFAULT_PROP_DURATION;
+  smpte->invert = DEFAULT_PROP_INVERT;
   smpte->fps_num = 0;
   smpte->fps_denom = 1;
 }
@@ -558,6 +567,9 @@ gst_smpte_set_property (GObject * object, guint prop_id,
     case PROP_DURATION:
       smpte->duration = g_value_get_uint64 (value);
       break;
+    case PROP_INVERT:
+      smpte->invert = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -588,6 +600,9 @@ gst_smpte_get_property (GObject * object, guint prop_id,
     case PROP_DURATION:
       g_value_set_uint64 (value, smpte->duration);
       break;
+    case PROP_INVERT:
+      g_value_set_boolean (value, smpte->invert);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 44a88c2..dc6bc6d 100644 (file)
@@ -56,6 +56,7 @@ struct _GstSMPTE {
   gint           border;
   gint           depth;
   guint64        duration;
+  gboolean       invert;
 
   /* negotiated format */
   gint           format;
index dbebb73..0c962cc 100644 (file)
@@ -88,6 +88,7 @@ enum
 #define DEFAULT_PROP_BORDER    0
 #define DEFAULT_PROP_DEPTH     16
 #define DEFAULT_PROP_POSITION  0.0
+#define DEFAULT_PROP_INVERT   FALSE
 
 enum
 {
@@ -96,6 +97,7 @@ enum
   PROP_BORDER,
   PROP_DEPTH,
   PROP_POSITION,
+  PROP_INVERT,
   PROP_LAST,
 };
 
@@ -231,6 +233,10 @@ gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass)
       g_param_spec_double ("position", "Position",
           "Position of the transition effect", 0.0, 1.0, DEFAULT_PROP_POSITION,
           GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
+      g_param_spec_boolean ("invert", "Invert",
+          "Invert transition mask", DEFAULT_PROP_POSITION,
+          GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_smpte_alpha_setcaps);
   trans_class->get_unit_size =
@@ -239,8 +245,8 @@ gst_smpte_alpha_class_init (GstSMPTEAlphaClass * klass)
 }
 
 static gboolean
-gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth,
-    gint width, gint height)
+gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type,
+    gboolean invert, gint depth, gint width, gint height)
 {
   GstMask *newmask;
 
@@ -248,12 +254,14 @@ gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth,
    * correct */
   if (smpte->mask) {
     if (smpte->type == type &&
+        smpte->invert == invert &&
         smpte->depth == depth &&
         smpte->width == width && smpte->height == height)
       return TRUE;
   }
 
   smpte->type = type;
+  smpte->invert = invert;
   smpte->depth = depth;
   smpte->width = width;
   smpte->height = height;
@@ -263,7 +271,7 @@ gst_smpte_alpha_update_mask (GstSMPTEAlpha * smpte, gint type, gint depth,
     return TRUE;
   }
 
-  newmask = gst_mask_factory_new (type, depth, width, height);
+  newmask = gst_mask_factory_new (type, invert, depth, width, height);
   if (!newmask)
     goto mask_failed;
 
@@ -306,8 +314,9 @@ gst_smpte_alpha_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
   /* try to update the mask now, this will also adjust the width/height on
    * success */
   GST_OBJECT_LOCK (smpte);
-  ret = gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->depth,
-      width, height);
+  ret =
+      gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert,
+      smpte->depth, width, height);
   GST_OBJECT_UNLOCK (smpte);
   if (!ret)
     goto mask_failed;
@@ -383,6 +392,7 @@ gst_smpte_alpha_init (GstSMPTEAlpha * smpte)
   smpte->border = DEFAULT_PROP_BORDER;
   smpte->depth = DEFAULT_PROP_DEPTH;
   smpte->position = DEFAULT_PROP_POSITION;
+  smpte->invert = DEFAULT_PROP_INVERT;
 }
 
 static void
@@ -574,7 +584,7 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
        * have to wait for the transform lock */
       GST_OBJECT_LOCK (smpte);
       GST_OBJECT_UNLOCK (smpte);
-      gst_smpte_alpha_update_mask (smpte, type,
+      gst_smpte_alpha_update_mask (smpte, type, smpte->invert,
           smpte->depth, smpte->width, smpte->height);
       GST_BASE_TRANSFORM_UNLOCK (smpte);
       break;
@@ -594,7 +604,7 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
        * have to wait for the transform lock */
       GST_OBJECT_LOCK (smpte);
       GST_OBJECT_UNLOCK (smpte);
-      gst_smpte_alpha_update_mask (smpte, smpte->type,
+      gst_smpte_alpha_update_mask (smpte, smpte->type, smpte->invert,
           depth, smpte->width, smpte->height);
       GST_BASE_TRANSFORM_UNLOCK (smpte);
       break;
@@ -604,6 +614,20 @@ gst_smpte_alpha_set_property (GObject * object, guint prop_id,
       smpte->position = g_value_get_double (value);
       GST_OBJECT_UNLOCK (smpte);
       break;
+    case PROP_INVERT:{
+      gboolean invert;
+
+      invert = g_value_get_boolean (value);
+      GST_BASE_TRANSFORM_LOCK (smpte);
+      /* also lock with the object lock so that reading the property doesn't
+       * have to wait for the transform lock */
+      GST_OBJECT_LOCK (smpte);
+      GST_OBJECT_UNLOCK (smpte);
+      gst_smpte_alpha_update_mask (smpte, smpte->type, invert,
+          smpte->depth, smpte->width, smpte->height);
+      GST_BASE_TRANSFORM_UNLOCK (smpte);
+      break;
+    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -639,6 +663,11 @@ gst_smpte_alpha_get_property (GObject * object, guint prop_id,
       g_value_set_double (value, smpte->position);
       GST_OBJECT_UNLOCK (smpte);
       break;
+    case PROP_INVERT:
+      GST_OBJECT_LOCK (smpte);
+      g_value_set_boolean (value, smpte->invert);
+      GST_OBJECT_UNLOCK (smpte);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 5e8f6fc..df9261e 100644 (file)
@@ -52,6 +52,7 @@ struct _GstSMPTEAlpha {
   gint           border;
   gint           depth;
   gdouble        position;
+  gboolean       invert;
 
   /* negotiated format */
   GstVideoFormat format;