event: Hide the GstStructure
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 10 May 2011 09:50:16 +0000 (11:50 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 10 May 2011 09:50:16 +0000 (11:50 +0200)
Hide the GstStructure of the event in the implementation specific part so that
we can change it.
Add methods to check and make the event writable.
Add a new method to get a writable GstStructure of the element.
Avoid directly accising the event structure.

gst/gstevent.c
gst/gstevent.h
gst/gstinfo.c
libs/gst/check/gstconsistencychecker.c
libs/gst/dataprotocol/dataprotocol.c

index 61a22ed..e069709 100644 (file)
@@ -89,6 +89,15 @@ static GType _gst_event_type = 0;
 
 typedef struct
 {
+  GstEvent event;
+
+  GstStructure *structure;
+} GstEventImpl;
+
+#define GST_EVENT_STRUCTURE(e)  (((GstEventImpl *)(e))->structure)
+
+typedef struct
+{
   const gint type;
   const gchar *name;
   GQuark quark;
@@ -203,49 +212,55 @@ gst_event_get_type (void)
 static void
 _gst_event_free (GstEvent * event)
 {
+  GstStructure *s;
+
   g_return_if_fail (event != NULL);
   g_return_if_fail (GST_IS_EVENT (event));
 
   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
       GST_EVENT_TYPE_NAME (event));
 
-  if (event->structure) {
-    gst_structure_set_parent_refcount (event->structure, NULL);
-    gst_structure_free (event->structure);
+  s = GST_EVENT_STRUCTURE (event);
+
+  if (s) {
+    gst_structure_set_parent_refcount (s, NULL);
+    gst_structure_free (s);
   }
 
   g_slice_free1 (GST_MINI_OBJECT_SIZE (event), event);
 }
 
-static void gst_event_init (GstEvent * event, gsize size, GstEventType type);
+static void gst_event_init (GstEventImpl * event, gsize size,
+    GstEventType type);
 
 static GstEvent *
 _gst_event_copy (GstEvent * event)
 {
-  GstEvent *copy;
+  GstEventImpl *copy;
+  GstStructure *s;
 
-  copy = g_slice_new0 (GstEvent);
+  copy = g_slice_new0 (GstEventImpl);
 
-  gst_event_init (copy, sizeof (GstEvent), GST_EVENT_TYPE (event));
+  gst_event_init (copy, sizeof (GstEventImpl), GST_EVENT_TYPE (event));
 
   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
   GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event);
 
-  if (event->structure) {
-    copy->structure = gst_structure_copy (event->structure);
-    gst_structure_set_parent_refcount (copy->structure,
-        &copy->mini_object.refcount);
+  s = GST_EVENT_STRUCTURE (event);
+  if (s) {
+    GST_EVENT_STRUCTURE (copy) = gst_structure_copy (s);
+    gst_structure_set_parent_refcount (s, &copy->event.mini_object.refcount);
   }
-  return copy;
+  return GST_EVENT_CAST (copy);
 }
 
 static void
-gst_event_init (GstEvent * event, gsize size, GstEventType type)
+gst_event_init (GstEventImpl * event, gsize size, GstEventType type)
 {
   gst_mini_object_init (GST_MINI_OBJECT_CAST (event), _gst_event_type, size);
 
-  event->mini_object.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
-  event->mini_object.free = (GstMiniObjectFreeFunction) _gst_event_free;
+  event->event.mini_object.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
+  event->event.mini_object.free = (GstMiniObjectFreeFunction) _gst_event_free;
 
   GST_EVENT_TYPE (event) = type;
   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
@@ -255,16 +270,16 @@ gst_event_init (GstEvent * event, gsize size, GstEventType type)
 static GstEvent *
 gst_event_new (GstEventType type)
 {
-  GstEvent *event;
+  GstEventImpl *event;
 
-  event = g_slice_new0 (GstEvent);
+  event = g_slice_new0 (GstEventImpl);
 
   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
       gst_event_type_get_name (type), type);
 
-  gst_event_init (event, sizeof (GstEvent), type);
+  gst_event_init (event, sizeof (GstEventImpl), type);
 
-  return event;
+  return GST_EVENT_CAST (event);
 }
 
 /**
@@ -298,7 +313,7 @@ gst_event_new_custom (GstEventType type, GstStructure * structure)
   event = gst_event_new (type);
   if (structure) {
     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
-    event->structure = structure;
+    GST_EVENT_STRUCTURE (event) = structure;
   }
   return event;
 }
@@ -320,7 +335,40 @@ gst_event_get_structure (GstEvent * event)
 {
   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
 
-  return event->structure;
+  return GST_EVENT_STRUCTURE (event);
+}
+
+/**
+ * gst_event_writable_structure:
+ * @event: The #GstEvent.
+ *
+ * Get a writable version of the structure.
+ *
+ * Returns: The structure of the event. The structure is still
+ * owned by the event, which means that you should not free it and
+ * that the pointer becomes invalid when you free the event.
+ * This function checks if @event is writable and will never return NULL.
+ *
+ * MT safe.
+ */
+GstStructure *
+gst_event_writable_structure (GstEvent * event)
+{
+  GstStructure *structure;
+
+  g_return_val_if_fail (GST_IS_EVENT (event), NULL);
+  g_return_val_if_fail (gst_event_is_writable (event), NULL);
+
+  structure = GST_EVENT_STRUCTURE (event);
+
+  if (structure == NULL) {
+    structure =
+        gst_structure_id_empty_new (gst_event_type_to_quark (GST_EVENT_TYPE
+            (event)));
+    gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
+    GST_EVENT_STRUCTURE (event) = structure;
+  }
+  return structure;
 }
 
 /**
@@ -340,10 +388,10 @@ gst_event_has_name (GstEvent * event, const gchar * name)
 {
   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
 
-  if (event->structure == NULL)
+  if (GST_EVENT_STRUCTURE (event) == NULL)
     return FALSE;
 
-  return gst_structure_has_name (event->structure, name);
+  return gst_structure_has_name (GST_EVENT_STRUCTURE (event), name);
 }
 
 /**
@@ -519,7 +567,7 @@ gst_event_parse_caps (GstEvent * event, GstCaps ** caps)
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (G_LIKELY (caps))
     *caps =
         g_value_get_boxed (gst_structure_id_get_value (structure,
@@ -641,7 +689,7 @@ gst_event_parse_new_segment (GstEvent * event, gboolean * update,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (G_LIKELY (update))
     *update =
         g_value_get_boolean (gst_structure_id_get_value (structure,
@@ -706,7 +754,7 @@ gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
 
   if (taglist)
-    *taglist = (GstTagList *) event->structure;
+    *taglist = (GstTagList *) GST_EVENT_STRUCTURE (event);
 }
 
 /* buffersize event */
@@ -765,7 +813,7 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format =
         g_value_get_enum (gst_structure_id_get_value (structure,
@@ -881,7 +929,7 @@ gst_event_parse_qos (GstEvent * event, GstQOSType * type,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (type)
     *type =
         g_value_get_enum (gst_structure_id_get_value (structure,
@@ -1005,7 +1053,7 @@ gst_event_parse_seek (GstEvent * event, gdouble * rate,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (rate)
     *rate =
         g_value_get_double (gst_structure_id_get_value (structure,
@@ -1101,8 +1149,8 @@ gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
 
   if (latency)
     *latency =
-        g_value_get_uint64 (gst_structure_id_get_value (event->structure,
-            GST_QUARK (LATENCY)));
+        g_value_get_uint64 (gst_structure_id_get_value (GST_EVENT_STRUCTURE
+            (event), GST_QUARK (LATENCY)));
 }
 
 /**
@@ -1175,7 +1223,7 @@ gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format = g_value_get_enum (gst_structure_id_get_value (structure,
             GST_QUARK (FORMAT)));
@@ -1264,7 +1312,7 @@ gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE);
 
-  structure = event->structure;
+  structure = GST_EVENT_STRUCTURE (event);
   if (msg)
     *msg =
         GST_MESSAGE (g_value_dup_boxed (gst_structure_id_get_value
index 804de17..8d49477 100644 (file)
@@ -240,6 +240,26 @@ typedef struct _GstEvent GstEvent;
 #define GST_EVENT_IS_STICKY(ev)     !!(GST_EVENT_TYPE (ev) & GST_EVENT_TYPE_STICKY)
 
 /**
+ * gst_event_is_writable:
+ * @ev: a #GstEvent
+ *
+ * Tests if you can safely write data into a event's structure or validly
+ * modify the seqnum and timestamp field.
+ */
+#define         gst_event_is_writable(ev)     gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (ev))
+/**
+ * gst_event_make_writable:
+ * @ev: (transfer full): a #GstEvent
+ *
+ * Makes a writable event from the given event. If the source event is
+ * already writable, this will simply return the same event. A copy will
+ * otherwise be made using gst_event_copy().
+ *
+ * Returns: (transfer full): a writable event which may or may not be the
+ *     same as @ev
+ */
+#define         gst_event_make_writable(ev)   GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (ev)))
+/**
  * gst_event_replace:
  * @old_event: (inout) (transfer full): pointer to a pointer to a #GstEvent
  *     to be replaced.
@@ -337,12 +357,12 @@ typedef enum {
  *    type is also used when buffers arrive early or in time.
  * @GST_QOS_TYPE_UNDERFLOW: The QoS event type that is produced when downstream
  *    elements are producing data too slowly and need to speed up their processing
- *    rate. 
+ *    rate.
  * @GST_QOS_TYPE_THROTTLE: The QoS event type that is produced when the
  *    application enabled throttling to limit the datarate.
  *
- * The different types of QoS events that can be given to the 
- * gst_event_new_qos_full() method. 
+ * The different types of QoS events that can be given to the
+ * gst_event_new_qos() method.
  *
  * Since: 0.10.33
  */
@@ -368,11 +388,6 @@ struct _GstEvent {
   GstEventType  type;
   guint64       timestamp;
   guint32       seqnum;
-
-  GstStructure  *structure;
-
-  /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
 };
 
 const gchar*    gst_event_type_get_name         (GstEventType type);
@@ -443,6 +458,7 @@ GstEvent*       gst_event_new_custom            (GstEventType type, GstStructure
 
 const GstStructure *
                 gst_event_get_structure         (GstEvent *event);
+GstStructure *  gst_event_writable_structure    (GstEvent *event);
 
 gboolean        gst_event_has_name              (GstEvent *event, const gchar *name);
 
index 340e341..8681178 100644 (file)
@@ -681,9 +681,11 @@ gst_debug_print_object (gpointer ptr)
   if (GST_IS_EVENT (object)) {
     GstEvent *event = GST_EVENT_CAST (object);
     gchar *s, *ret;
+    GstStructure *structure;
 
-    if (event->structure) {
-      s = gst_info_structure_to_string (event->structure);
+    structure = (GstStructure *) gst_event_get_structure (event);
+    if (structure) {
+      s = gst_info_structure_to_string (structure);
     } else {
       s = g_strdup ("(NULL)");
     }
index ded047e..f7408dd 100644 (file)
@@ -78,7 +78,8 @@ source_pad_data_cb (GstPad * pad, GstMiniObject * data,
         consist->newsegment = FALSE;
         break;
       case GST_EVENT_TAG:
-        GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT, event->structure);
+        GST_DEBUG_OBJECT (pad, "tag %" GST_PTR_FORMAT,
+            gst_event_get_structure (event));
         /* fall through */
       default:
         if (GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_IS_DOWNSTREAM (event)) {
index 728b3f5..b1cda55 100644 (file)
@@ -394,6 +394,7 @@ gst_dp_packet_from_event_1_0 (const GstEvent * event, GstDPHeaderFlag flags,
   guint8 *h;
   guint32 pl_length;            /* length of payload */
   guchar *string = NULL;
+  const GstStructure *structure;
 
   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
   g_return_val_if_fail (length, FALSE);
@@ -403,8 +404,9 @@ gst_dp_packet_from_event_1_0 (const GstEvent * event, GstDPHeaderFlag flags,
   *length = GST_DP_HEADER_LENGTH;
   h = g_malloc0 (GST_DP_HEADER_LENGTH);
 
-  if (event->structure) {
-    string = (guchar *) gst_structure_to_string (event->structure);
+  structure = gst_event_get_structure ((GstEvent *) event);
+  if (structure) {
+    string = (guchar *) gst_structure_to_string (structure);
     GST_LOG ("event %p has structure, string %s", event, string);
     pl_length = strlen ((gchar *) string) + 1;  /* include trailing 0 */
   } else {