gst/: Identify sinks by their flag to avoid overly complicated checks (fow now).
authorWim Taymans <wim.taymans@gmail.com>
Thu, 12 May 2005 19:45:44 +0000 (19:45 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 12 May 2005 19:45:44 +0000 (19:45 +0000)
Original commit message from CVS:
* gst/base/gstbasesink.c: (gst_basesink_init),
(gst_basesink_activate):
* gst/base/gstbasesrc.c: (gst_basesrc_unlock),
(gst_basesrc_is_seekable):
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func),
(bin_element_is_sink), (gst_bin_change_state):
* gst/gstelement.c: (gst_element_add_pad), (gst_element_query):
* gst/gstelement.h:
Identify sinks by their flag to avoid overly complicated
checks (fow now).
Do state changes even for elements not reachable from the
sinks.
BaseSink is a sink now :)
Some more debugging info in the basesrc.

ChangeLog
gst/base/gstbasesink.c
gst/base/gstbasesrc.c
gst/gstbin.c
gst/gstelement.c
gst/gstelement.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesrc.c

index 0c6313e..620bede 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2005-05-12  Wim Taymans  <wim@fluendo.com>
+
+       * gst/base/gstbasesink.c: (gst_basesink_init),
+       (gst_basesink_activate):
+       * gst/base/gstbasesrc.c: (gst_basesrc_unlock),
+       (gst_basesrc_is_seekable):
+       * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func),
+       (bin_element_is_sink), (gst_bin_change_state):
+       * gst/gstelement.c: (gst_element_add_pad), (gst_element_query):
+       * gst/gstelement.h:
+       Identify sinks by their flag to avoid overly complicated
+       checks (fow now).
+       Do state changes even for elements not reachable from the
+       sinks.
+       BaseSink is a sink now :)
+       Some more debugging info in the basesrc.
+
+
 2005-05-12  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
        * gst/gstbin.c: (gst_bin_class_init), (gst_bin_query):
index 8ae3d83..4382590 100644 (file)
@@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class)
 
   basesink->pad_mode = GST_ACTIVATE_NONE;
   GST_RPAD_TASK (basesink->sinkpad) = NULL;
+
+  GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
 }
 
 static void
index 803cc96..80354fd 100644 (file)
@@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
   GstBaseSrcClass *bclass;
   gboolean result = FALSE;
 
+  GST_DEBUG ("unlock");
   /* unblock whatever the subclass is doing */
   bclass = GST_BASESRC_GET_CLASS (basesrc);
   if (bclass->unlock)
     result = bclass->unlock (basesrc);
 
+  GST_DEBUG ("unschedule clock");
   /* and unblock the clock as well, if any */
   GST_LOCK (basesrc);
   if (basesrc->clock_id) {
@@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
   }
   GST_UNLOCK (basesrc);
 
+  GST_DEBUG ("unlock done");
+
   return result;
 }
 
index 4eccfc8..090b994 100644 (file)
@@ -79,6 +79,8 @@ static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
 #endif
 
+static gint bin_element_is_sink (GstElement * child, GstBin * bin);
+
 /* Bin signals and args */
 enum
 {
@@ -379,6 +381,9 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
               GST_OBJECT_CAST (bin))))
     goto had_parent;
 
+  if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
+    GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
+
   bin->children = g_list_prepend (bin->children, element);
   bin->numchildren++;
   bin->children_cookie++;
@@ -488,6 +493,20 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
   bin->children = g_list_remove (bin->children, element);
   bin->numchildren--;
   bin->children_cookie++;
+
+  /* check if we a sink */
+  if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
+    GList *other_sink;
+
+    /* check if we removed the last sink */
+    other_sink = g_list_find_custom (bin->children,
+        bin, (GCompareFunc) bin_element_is_sink);
+    if (!other_sink) {
+      /* yups, we're not a sink anymore */
+      GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
+    }
+  }
+
   GST_UNLOCK (bin);
 
   GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
@@ -674,70 +693,22 @@ gst_bin_iterate_recurse (GstBin * bin)
 static gint
 bin_element_is_sink (GstElement * child, GstBin * bin)
 {
-  gint ret = 1;
+  gint ret;
 
   /* we lock the child here for the remainder of the function to
-   * get its pads and name safely. */
+   * get its name safely. */
   GST_LOCK (child);
-
-  /* check if this is a sink element, these are the elements
-   * without (linked) source pads. */
-  if (child->numsrcpads == 0) {
-    /* shortcut */
+  if (GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK)) {
     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
-        "adding child %s as sink", GST_OBJECT_NAME (child));
+        "finding child %s as sink", GST_OBJECT_NAME (child));
+    GST_UNLOCK (child);
     ret = 0;
   } else {
-    /* loop over all pads, try to figure out if this element
-     * is a sink because it has no linked source pads */
-    GList *pads;
-    gboolean connected_src = FALSE;
-
-    for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
-      GstPad *peer;
-
-      peer = gst_pad_get_peer (GST_PAD_CAST (pads->data));
-      if (peer) {
-        GstElement *parent;
-
-        parent = gst_pad_get_parent (peer);
-        if (parent) {
-          GstObject *grandparent;
-
-          grandparent = gst_object_get_parent (GST_OBJECT_CAST (parent));
-          if (grandparent == GST_OBJECT_CAST (bin)) {
-            connected_src = TRUE;
-          }
-          if (grandparent) {
-            gst_object_unref (GST_OBJECT_CAST (grandparent));
-          }
-          gst_object_unref (GST_OBJECT_CAST (parent));
-        }
-        gst_object_unref (GST_OBJECT_CAST (peer));
-        if (connected_src) {
-          break;
-        }
-      }
-    }
-
-    if (connected_src) {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
-          "not adding child %s as sink: linked source pads",
-          GST_OBJECT_NAME (child));
-    } else {
-      GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
-          "adding child %s as sink since it has unlinked source pads in this bin",
-          GST_OBJECT_NAME (child));
-      ret = 0;
-    }
+    GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
+        "child %s is not a sink", GST_OBJECT_NAME (child));
+    GST_UNLOCK (child);
+    ret = 1;
   }
-  GST_UNLOCK (child);
-
-  /* we did not find the element, need to release the ref
-   * added by the iterator */
-  if (ret == 1)
-    gst_object_unref (GST_OBJECT (child));
-
   return ret;
 }
 
@@ -872,6 +843,7 @@ gst_bin_change_state (GstElement * element)
   GList *children;
   guint32 children_cookie;
   GQueue *elem_queue;           /* list of elements waiting for a state change */
+  GQueue *temp;                 /* temp queue of non sinks */
 
   bin = GST_BIN (element);
 
@@ -890,6 +862,7 @@ gst_bin_change_state (GstElement * element)
   /* all elements added to this queue should have their refcount
    * incremented */
   elem_queue = g_queue_new ();
+  temp = g_queue_new ();
 
   /* first step, find all sink elements, these are the elements
    * without (linked) source pads. */
@@ -908,13 +881,17 @@ restart:
        * the _is_sink function unrefs the element when it is not
        * a sink. */
       g_queue_push_tail (elem_queue, child);
+    } else {
+      g_queue_push_tail (temp, child);
     }
 
     GST_LOCK (bin);
     if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
       /* undo what we had */
       g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
+      g_queue_foreach (temp, (GFunc) gst_object_unref, NULL);
       while (g_queue_pop_head (elem_queue));
+      while (g_queue_pop_head (temp));
       goto restart;
     }
 
@@ -924,10 +901,27 @@ restart:
 
   /* second step, change state of elements in the queue */
   while (!g_queue_is_empty (elem_queue)) {
-    GstElement *qelement = g_queue_pop_head (elem_queue);
+    GstElement *qelement;
     GList *pads;
     gboolean locked;
 
+    /* take element */
+    qelement = g_queue_pop_head (elem_queue);
+    /* we don't need it in the temp anymore */
+    g_queue_remove_all (temp, qelement);
+
+    /* if queue is empty now, continue with a non-sink */
+    if (g_queue_is_empty (elem_queue)) {
+      GstElement *non_sink;
+
+      GST_DEBUG ("sinks and upstream elements exhausted");
+      non_sink = g_queue_pop_head (temp);
+      if (non_sink) {
+        GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
+        g_queue_push_tail (elem_queue, non_sink);
+      }
+    }
+
     /* queue all elements connected to the sinkpads of this element */
     GST_LOCK (qelement);
     pads = qelement->sinkpads;
@@ -1036,6 +1030,8 @@ exit:
   /* release refcounts in queue, should normally be empty */
   g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
   g_queue_free (elem_queue);
+  g_queue_foreach (temp, (GFunc) gst_object_unref, NULL);
+  g_queue_free (temp);
 
   return ret;
 }
index 9dec706..326c1ce 100644 (file)
@@ -502,6 +502,8 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
       break;
     default:
       /* can happen for ghost pads */
+      g_warning ("adding pad %s:%s wothout direction",
+          GST_DEBUG_PAD_NAME (pad));
       break;
   }
   element->pads = g_list_prepend (element->pads, pad);
index be4e9f0..5b56ed0 100644 (file)
@@ -113,6 +113,9 @@ typedef enum
   /* ignore state changes from parent */
   GST_ELEMENT_LOCKED_STATE,
 
+  /* the element is a sink */
+  GST_ELEMENT_IS_SINK,
+
   /* use some padding for future expansion */
   GST_ELEMENT_FLAG_LAST                = GST_OBJECT_FLAG_LAST + 16
 } GstElementFlags;
index 8ae3d83..4382590 100644 (file)
@@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class)
 
   basesink->pad_mode = GST_ACTIVATE_NONE;
   GST_RPAD_TASK (basesink->sinkpad) = NULL;
+
+  GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
 }
 
 static void
index 803cc96..80354fd 100644 (file)
@@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
   GstBaseSrcClass *bclass;
   gboolean result = FALSE;
 
+  GST_DEBUG ("unlock");
   /* unblock whatever the subclass is doing */
   bclass = GST_BASESRC_GET_CLASS (basesrc);
   if (bclass->unlock)
     result = bclass->unlock (basesrc);
 
+  GST_DEBUG ("unschedule clock");
   /* and unblock the clock as well, if any */
   GST_LOCK (basesrc);
   if (basesrc->clock_id) {
@@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
   }
   GST_UNLOCK (basesrc);
 
+  GST_DEBUG ("unlock done");
+
   return result;
 }