docs/design/part-TODO.txt: Update TODO.
authorWim Taymans <wim.taymans@gmail.com>
Tue, 25 Oct 2005 15:39:36 +0000 (15:39 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 25 Oct 2005 15:39:36 +0000 (15:39 +0000)
Original commit message from CVS:
* docs/design/part-TODO.txt:
Update TODO.

* gst/gstbin.c: (message_check), (bin_replace_message),
(bin_remove_messages), (is_eos), (gst_bin_add_func),
(update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler),
(bin_query_duration_init), (bin_query_duration_fold),
(bin_query_duration_done), (bin_query_generic_fold),
(gst_bin_query):
Handle SEGMENT_START/DONE messages correctly.
More evolved query algorithm that handles duration queries
correctly.

* gst/gstelement.c: (gst_element_send_event), (gst_element_query),
(gst_element_get_state_func), (gst_element_abort_state),
(gst_element_commit_state), (gst_element_lost_state):
Some more debugging.

* gst/gstmessage.h:
Added doc.

ChangeLog
docs/design/part-TODO.txt
gst/gstbin.c
gst/gstelement.c
gst/gstmessage.h

index 832d7b4..7091fee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2005-10-25  Wim Taymans  <wim@fluendo.com>
 
+       * docs/design/part-TODO.txt:
+       Update TODO.
+
+       * gst/gstbin.c: (message_check), (bin_replace_message),
+       (bin_remove_messages), (is_eos), (gst_bin_add_func),
+       (update_degree), (gst_bin_sort_iterator_next), (bin_bus_handler),
+       (bin_query_duration_init), (bin_query_duration_fold),
+       (bin_query_duration_done), (bin_query_generic_fold),
+       (gst_bin_query):
+       Handle SEGMENT_START/DONE messages correctly.
+       More evolved query algorithm that handles duration queries
+       correctly.
+
+       * gst/gstelement.c: (gst_element_send_event), (gst_element_query),
+       (gst_element_get_state_func), (gst_element_abort_state),
+       (gst_element_commit_state), (gst_element_lost_state):
+       Some more debugging.
+
+       * gst/gstmessage.h:
+       Added doc.
+
+2005-10-25  Wim Taymans  <wim@fluendo.com>
+
        * gst/base/gstbasesink.c: (gst_base_sink_get_position):
        Don't use invalid stream_time.
 
index 720eb74..599bb08 100644 (file)
@@ -31,3 +31,4 @@
 - make bin_bus_handler a vmethod so subclasses can use their own implementation
   or chain to the parent.
 
+- make it possible to seek on other formats than bytes in basesrc.
index f83cd4e..5b10c1c 100644 (file)
@@ -442,13 +442,20 @@ message_check (GstMessage * message, MessageFind * target)
 }
 
 /* with LOCK, returns TRUE if message had a valid SRC, takes ref on
- * the message. */
+ * the message. 
+ *
+ * A message that is cached and has the same SRC and type is replaced
+ * by the given message.
+ */
 static gboolean
 bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
 {
   GList *previous;
   GstObject *src;
   gboolean res = TRUE;
+  const gchar *name;
+
+  name = gst_message_type_get_name (GST_MESSAGE_TYPE (message));
 
   if ((src = GST_MESSAGE_SRC (message))) {
     MessageFind find;
@@ -465,19 +472,16 @@ bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
       previous->data = message;
 
       GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
-          gst_message_type_get_name (GST_MESSAGE_TYPE (message)),
-          GST_ELEMENT_NAME (src));
+          name, GST_ELEMENT_NAME (src));
     } else {
       /* keep new message */
       bin->messages = g_list_prepend (bin->messages, message);
 
       GST_DEBUG_OBJECT (bin, "got new message %s from %s",
-          gst_message_type_get_name (GST_MESSAGE_TYPE (message)),
-          GST_ELEMENT_NAME (src));
+          name, GST_ELEMENT_NAME (src));
     }
   } else {
-    GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing",
-        gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
+    GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing", name);
     res = FALSE;
     gst_message_unref (message);
   }
@@ -1756,6 +1760,8 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
       GST_UNLOCK (bin);
       break;
 
+      /* non toplevel bins just forward the message and don't start
+       * a recalc themselves */
     not_toplevel:
       {
         GST_UNLOCK (bin);
@@ -1769,15 +1775,54 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
     }
     case GST_MESSAGE_SEGMENT_START:
       GST_LOCK (bin);
+      /* replace any previous segment_start message from this source 
+       * with the new segment start message */
       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
       GST_UNLOCK (bin);
       break;
     case GST_MESSAGE_SEGMENT_DONE:
+    {
+      MessageFind find;
+      gboolean post = FALSE;
+      GstFormat format;
+      gint64 position;
+
+      gst_message_parse_segment_done (message, &format, &position);
+
       GST_LOCK (bin);
       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
+      /* if there are no more segment_start messages, everybody posted
+       * a segment_done and we can post one on the bus. */
+
+      /* we don't care who still has a pending segment start */
+      find.src = NULL;
+      find.types = GST_MESSAGE_SEGMENT_START;
+
+      if (!g_list_find_custom (bin->messages, &find,
+              (GCompareFunc) message_check)) {
+        /* nothing found */
+        post = TRUE;
+        /* remove all old segment_done messages */
+        bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
+      }
       GST_UNLOCK (bin);
+      if (post) {
+        /* post segment done with latest format and position. */
+        gst_element_post_message (GST_ELEMENT_CAST (bin),
+            gst_message_new_segment_done (GST_OBJECT_CAST (bin),
+                format, position));
+      }
       break;
+    }
     case GST_MESSAGE_DURATION:
+    {
+      /* remove all cached duration messages, next time somebody asks
+       * for duration, we will recalculate. */
+      GST_LOCK (bin);
+      bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION);
+      GST_UNLOCK (bin);
+      /* fallthrough */
+    }
     default:
       /* Send all other messages upward */
       GST_DEBUG_OBJECT (bin, "posting message upward");
@@ -1788,40 +1833,130 @@ bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
   return GST_BUS_DROP;
 }
 
+/* generic struct passed to all query fold methods */
+typedef struct
+{
+  GstQuery *query;
+  gint64 max;
+} QueryFold;
+
+typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold);
+typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold);
+
+/* for duration we collect all durations and take the MAX of
+ * all valid results */
+static void
+bin_query_duration_init (GstBin * bin, QueryFold * fold)
+{
+  fold->max = -1;
+}
+
+static gboolean
+bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
+{
+  if (gst_element_query (item, fold->query)) {
+    gint64 duration;
+
+    g_value_set_boolean (ret, TRUE);
+
+    gst_query_parse_duration (fold->query, NULL, &duration);
+
+    GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
+
+    if (duration > fold->max)
+      fold->max = duration;
+  }
+  return TRUE;
+}
+static void
+bin_query_duration_done (GstBin * bin, QueryFold * fold)
+{
+  GstFormat format;
+
+  gst_query_parse_duration (fold->query, &format, NULL);
+  /* store max in query result */
+  gst_query_set_duration (fold->query, format, fold->max);
+
+  GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
+}
+
+/* generic fold, return first valid result */
+static gboolean
+bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
+{
+  gboolean res;
+
+  if ((res = gst_element_query (item, fold->query))) {
+    g_value_set_boolean (ret, TRUE);
+    GST_DEBUG_OBJECT (item, "answered query");
+  }
+
+  /* and stop as soon as we have a valid result */
+  return !res;
+}
+
 static gboolean
 gst_bin_query (GstElement * element, GstQuery * query)
 {
   GstBin *bin = GST_BIN (element);
   GstIterator *iter;
-  gboolean res = FALSE, done = FALSE;
+  gboolean res = FALSE;
+  GstIteratorFoldFunction fold_func;
+  QueryInitFunction fold_init = NULL;
+  QueryDoneFunction fold_done = NULL;
+  QueryFold fold_data;
+  GValue ret = { 0 };
+
+  fold_data.query = query;
+
+  g_value_init (&ret, G_TYPE_BOOLEAN);
+  g_value_set_boolean (&ret, FALSE);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_DURATION:
+      fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
+      fold_init = bin_query_duration_init;
+      fold_done = bin_query_duration_done;
+      break;
+    default:
+      fold_func = (GstIteratorFoldFunction) bin_query_generic_fold;
+      break;
+  }
 
   iter = gst_bin_iterate_sinks (bin);
   GST_DEBUG_OBJECT (bin, "Sending query to sink children");
 
-  while (!(res || done)) {
-    gpointer data;
+  if (fold_init)
+    fold_init (bin, &fold_data);
 
-    switch (gst_iterator_next (iter, &data)) {
-      case GST_ITERATOR_OK:
-      {
-        GstElement *sink;
+  while (TRUE) {
+    GstIteratorResult ires;
 
-        sink = GST_ELEMENT_CAST (data);
-        res = gst_element_query (sink, query);
-        gst_object_unref (sink);
-        break;
-      }
+    ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
+
+    switch (ires) {
       case GST_ITERATOR_RESYNC:
         gst_iterator_resync (iter);
+        if (fold_init)
+          fold_init (bin, &fold_data);
+        g_value_set_boolean (&ret, FALSE);
         break;
-      default:
+      case GST_ITERATOR_OK:
       case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
+        if (fold_done)
+          fold_done (bin, &fold_data);
+        res = g_value_get_boolean (&ret);
+        goto done;
+      default:
+        res = FALSE;
+        goto done;
     }
   }
+done:
   gst_iterator_free (iter);
 
+  GST_DEBUG_OBJECT (bin, "query result %d", res);
+
   return res;
 }
 
index a2758c4..f8d9c36 100644 (file)
@@ -1185,6 +1185,8 @@ gst_element_send_event (GstElement * element, GstEvent * event)
   oclass = GST_ELEMENT_GET_CLASS (element);
 
   if (oclass->send_event) {
+    GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send event on element %s",
+        GST_ELEMENT_NAME (element));
     result = oclass->send_event (element, event);
   } else {
     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
@@ -1306,6 +1308,8 @@ gst_element_query (GstElement * element, GstQuery * query)
   oclass = GST_ELEMENT_GET_CLASS (element);
 
   if (oclass->query) {
+    GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
+        GST_ELEMENT_NAME (element));
     result = oclass->query (element, query);
   } else {
     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
index 15c80c7..37af75a 100644 (file)
@@ -37,6 +37,7 @@ typedef struct _GstMessageClass GstMessageClass;
  * @GST_MESSAGE_TAG: a tag was found.
  * @GST_MESSAGE_BUFFERING: the pipeline is buffering
  * @GST_MESSAGE_STATE_CHANGED: a state change happened
+ * @GST_MESSAGE_STATE_DIRTY: an element changed state in a streaming thread
  * @GST_MESSAGE_STEP_DONE: a framestep finished.
  * @GST_MESSAGE_CLOCK_PROVIDE: an element notifies its capability of providing
  *                             a clock.