Merge remote-tracking branch 'origin/0.10'
[platform/upstream/gstreamer.git] / gst / gstelement.c
index 885d56b..da8e9f6 100644 (file)
@@ -34,7 +34,7 @@
  * core when using the appropriate locking. Do not use this in plug-ins or
  * applications in order to retain ABI compatibility.
  *
- * All elements have pads (of the type #GstPad).  These pads link to pads on
+ * Elements can have pads (of the type #GstPad).  These pads link to pads on
  * other elements.  #GstBuffer flow between these linked pads.
  * A #GstElement has a #GList of #GstPad structures for all their input (or sink)
  * and output (or source) pads.
@@ -44,7 +44,7 @@
  * An existing pad of an element can be retrieved by name with
  * gst_element_get_static_pad(). A new dynamic pad can be created using
  * gst_element_request_pad() with a #GstPadTemplate or 
- * gst_element_get_request_pad() with the template name such as "src_\%d".
+ * gst_element_get_request_pad() with the template name such as "src_\%u".
  * An iterator of all pads can be retrieved with gst_element_iterate_pads().
  *
  * Elements can be linked through their pads.
  * You can get and set a #GstClock on an element using gst_element_get_clock()
  * and gst_element_set_clock().
  * Some elements can provide a clock for the pipeline if
- * gst_element_provides_clock() returns %TRUE. With the
+ * the #GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the
  * gst_element_provide_clock() method one can retrieve the clock provided by
  * such an element.
- * Not all elements require a clock to operate correctly. If
- * gst_element_requires_clock() returns %TRUE, a clock should be set on the
+ * Not all elements require a clock to operate correctly. If the
+ * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the
  * element with gst_element_set_clock().
  *
  * Note that clock slection and distribution is normally handled by the
  * toplevel #GstPipeline so the clock functions are only to be used in very
  * specific situations.
  *
- * Last reviewed on 2009-05-29 (0.10.24)
+ * Last reviewed on 2012-03-28 (0.11.3)
  */
 
 #include "gst_private.h"
 #include "gstelementmetadata.h"
 #include "gstenumtypes.h"
 #include "gstbus.h"
-#include "gstmarshal.h"
 #include "gsterror.h"
 #include "gstevent.h"
 #include "gstutils.h"
 #include "gstinfo.h"
 #include "gstvalue.h"
 #include "gst-i18n-lib.h"
+#include "glib-compat-private.h"
 
 /* Element signals and args */
 enum
@@ -198,7 +198,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[PAD_ADDED] =
       g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
-      gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
   /**
    * GstElement::pad-removed:
    * @gstelement: the object which received the signal
@@ -209,7 +209,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[PAD_REMOVED] =
       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
-      gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+      g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
   /**
    * GstElement::no-more-pads:
    * @gstelement: the object which received the signal
@@ -221,7 +221,7 @@ gst_element_class_init (GstElementClass * klass)
   gst_element_signals[NO_MORE_PADS] =
       g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
-      NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
+      NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
 
   gobject_class->dispose = gst_element_dispose;
   gobject_class->finalize = gst_element_finalize;
@@ -290,8 +290,8 @@ gst_element_init (GstElement * element)
   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
   GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
 
-  g_static_rec_mutex_init (&element->state_lock);
-  element->state_cond = g_cond_new ();
+  g_rec_mutex_init (&element->state_lock);
+  g_cond_init (&element->state_cond);
 }
 
 /**
@@ -315,6 +315,9 @@ gst_element_release_request_pad (GstElement * element, GstPad * pad)
 
   g_return_if_fail (GST_IS_ELEMENT (element));
   g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (GST_PAD_PAD_TEMPLATE (pad) == NULL ||
+      GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
+      GST_PAD_REQUEST);
 
   oclass = GST_ELEMENT_GET_CLASS (element);
 
@@ -327,54 +330,6 @@ gst_element_release_request_pad (GstElement * element, GstPad * pad)
 }
 
 /**
- * gst_element_requires_clock:
- * @element: a #GstElement to query
- *
- * Query if the element requires a clock.
- *
- * Returns: %TRUE if the element requires a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_requires_clock (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
-
-  return result;
-}
-
-/**
- * gst_element_provides_clock:
- * @element: a #GstElement to query
- *
- * Query if the element provides a clock. A #GstClock provided by an
- * element can be used as the global #GstClock for the pipeline.
- * An element that can provide a clock is only required to do so in the PAUSED
- * state, this means when it is fully negotiated and has allocated the resources
- * to operate the clock.
- *
- * Returns: %TRUE if the element provides a clock
- *
- * MT safe.
- */
-gboolean
-gst_element_provides_clock (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
-
-  return result;
-}
-
-/**
  * gst_element_provide_clock:
  * @element: a #GstElement to query
  *
@@ -596,28 +551,7 @@ gst_element_get_start_time (GstElement * element)
   return result;
 }
 
-/**
- * gst_element_is_indexable:
- * @element: a #GstElement.
- *
- * Queries if the element can be indexed.
- *
- * Returns: TRUE if the element can be indexed.
- *
- * MT safe.
- */
-gboolean
-gst_element_is_indexable (GstElement * element)
-{
-  gboolean result;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
-  result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
-
-  return result;
-}
-
+#if 0
 /**
  * gst_element_set_index:
  * @element: a #GstElement.
@@ -668,6 +602,7 @@ gst_element_get_index (GstElement * element)
 
   return result;
 }
+#endif
 
 /**
  * gst_element_add_pad:
@@ -1835,7 +1770,7 @@ gst_element_is_locked_state (GstElement * element)
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
 
   GST_OBJECT_LOCK (element);
-  result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+  result = GST_ELEMENT_IS_LOCKED_STATE (element);
   GST_OBJECT_UNLOCK (element);
 
   return result;
@@ -1862,7 +1797,7 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state)
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
 
   GST_OBJECT_LOCK (element);
-  old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+  old = GST_ELEMENT_IS_LOCKED_STATE (element);
 
   if (G_UNLIKELY (old == locked_state))
     goto was_ok;
@@ -1870,11 +1805,11 @@ gst_element_set_locked_state (GstElement * element, gboolean locked_state)
   if (locked_state) {
     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
         GST_ELEMENT_NAME (element));
-    GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
+    GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
   } else {
     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
         GST_ELEMENT_NAME (element));
-    GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
+    GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
   }
   GST_OBJECT_UNLOCK (element);
 
@@ -1986,22 +1921,9 @@ gst_element_get_state_func (GstElement * element,
 
   old_pending = GST_STATE_PENDING (element);
   if (old_pending != GST_STATE_VOID_PENDING) {
-    GTimeVal *timeval, abstimeout;
+    gboolean signaled;
     guint32 cookie;
 
-    if (timeout != GST_CLOCK_TIME_NONE) {
-      glong add = timeout / 1000;
-
-      if (add == 0)
-        goto done;
-
-      /* make timeout absolute */
-      g_get_current_time (&abstimeout);
-      g_time_val_add (&abstimeout, add);
-      timeval = &abstimeout;
-    } else {
-      timeval = NULL;
-    }
     /* get cookie to detect state changes during waiting */
     cookie = element->state_cookie;
 
@@ -2009,7 +1931,17 @@ gst_element_get_state_func (GstElement * element,
         "waiting for element to commit state");
 
     /* we have a pending state change, wait for it to complete */
-    if (!GST_STATE_TIMED_WAIT (element, timeval)) {
+    if (timeout != GST_CLOCK_TIME_NONE) {
+      gint64 end_time;
+      /* make timeout absolute */
+      end_time = g_get_monotonic_time () + (timeout / 1000);
+      signaled = GST_STATE_WAIT_UNTIL (element, end_time);
+    } else {
+      GST_STATE_WAIT (element);
+      signaled = TRUE;
+    }
+
+    if (!signaled) {
       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
       /* timeout triggered */
       ret = GST_STATE_CHANGE_ASYNC;
@@ -2817,6 +2749,9 @@ gst_element_dispose (GObject * object)
   GstElement *element = GST_ELEMENT_CAST (object);
   GstClock **clock_p;
   GstBus **bus_p;
+  GstElementClass *oclass;
+
+  oclass = GST_ELEMENT_GET_CLASS (element);
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
 
@@ -2827,8 +2762,15 @@ gst_element_dispose (GObject * object)
       "removing %d pads", g_list_length (element->pads));
   /* first we break all our links with the outside */
   while (element->pads && element->pads->data) {
+    GstPad *pad = GST_PAD_CAST (element->pads->data);
+
     /* don't call _remove_pad with NULL */
-    gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
+    if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) &&
+        GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad))
+        == GST_PAD_REQUEST)
+      (oclass->release_pad) (element, GST_PAD_CAST (element->pads->data));
+    else
+      gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
   }
   if (G_UNLIKELY (element->pads != NULL)) {
     g_critical ("could not remove pads from element %s",
@@ -2853,7 +2795,7 @@ not_null:
   {
     gboolean is_locked;
 
-    is_locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
+    is_locked = GST_ELEMENT_IS_LOCKED_STATE (element);
     g_critical
         ("\nTrying to dispose element %s, but it is in %s%s instead of the NULL"
         " state.\n"
@@ -2875,8 +2817,8 @@ gst_element_finalize (GObject * object)
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
 
-  g_cond_free (element->state_cond);
-  g_static_rec_mutex_free (&element->state_lock);
+  g_cond_clear (&element->state_cond);
+  g_rec_mutex_clear (&element->state_lock);
 
   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");